VBAF.Core.Test-ValidationDashboard.ps1
|
#Requires -Version 5.1 # Dashboard 3 <# .SYNOPSIS Validation dashboard for VBAF foundation components .DESCRIPTION Visual proof that neural networks, Q-learning, and experience replay work. Three panels: NN training XOR, Q-learning grid world, Experience replay stats .EXAMPLE . C:\Users\henni\OneDrive\WindowsPowerShell\VBAF.Core.Test-ValidationDashboard.ps1 #> # Load dependencies $basePath = "C:\Users\henni\OneDrive\WindowsPowerShell" . "$basePath\VBAF.Core.AllClasses.ps1" . "$basePath\VBAF.RL.QTable.ps1" . "$basePath\VBAF.RL.ExperienceReplay.ps1" . "$basePath\VBAF.RL.QLearningAgent.ps1" Add-Type -AssemblyName System.Windows.Forms Add-Type -AssemblyName System.Drawing # ==================== VALIDATION STATE ==================== class ValidationState { # Neural Network State [object]$NeuralNetwork [System.Collections.ArrayList]$NNErrorHistory [int]$NNEpoch [double]$NNCurrentError [bool]$NNTraining # Q-Learning State [object]$QLAgent [int]$QLEpisode [double]$QLTotalReward [System.Collections.ArrayList]$QLRewardHistory [int]$GridX [int]$GridY [int]$GoalX [int]$GoalY # Experience Replay State [object]$ExperienceReplay [int]$ReplaySize [System.Collections.ArrayList]$ReplaySizeHistory ValidationState() { $this.NNErrorHistory = New-Object System.Collections.ArrayList $this.NNEpoch = 0 $this.NNCurrentError = 1.0 $this.NNTraining = $false $this.QLRewardHistory = New-Object System.Collections.ArrayList $this.QLEpisode = 0 $this.QLTotalReward = 0 $this.GridX = 0 $this.GridY = 0 $this.GoalX = 9 $this.GoalY = 9 $this.ReplaySizeHistory = New-Object System.Collections.ArrayList $this.ReplaySize = 0 } } $global:valState = New-Object ValidationState # ==================== NEURAL NETWORK SETUP ==================== function Initialize-NeuralNetwork { Write-Host "Initializing Neural Network for XOR..." -ForegroundColor Cyan # Create XOR training data $global:xorData = @( @{Input=@(0.0,0.0); Expected=@(0.0)}, @{Input=@(0.0,1.0); Expected=@(1.0)}, @{Input=@(1.0,0.0); Expected=@(1.0)}, @{Input=@(1.0,1.0); Expected=@(0.0)} ) # Create network: 2 inputs, 4 hidden, 1 output try { $global:valState.NeuralNetwork = New-Object NeuralNetwork -ArgumentList @(2, 4, 1), 0.5 Write-Host " ✓ Neural Network created (2-4-1 architecture)" -ForegroundColor Green } catch { Write-Host " ✗ Failed to create Neural Network: $_" -ForegroundColor Red } } # ==================== Q-LEARNING GRID WORLD SETUP ==================== function Initialize-QLearning { Write-Host "Initializing Q-Learning Grid World..." -ForegroundColor Cyan # Create simple grid world agent $actions = @("up", "down", "left", "right") try { # Use 3-parameter constructor: actions, learningRate, epsilon $global:valState.QLAgent = New-Object QLearningAgent -ArgumentList (,$actions), 0.1, 0.3 $global:valState.ExperienceReplay = New-Object ExperienceReplay -ArgumentList 100 Write-Host " ✓ Q-Learning agent created (10x10 grid)" -ForegroundColor Green } catch { Write-Host " ✗ Failed to create Q-Learning agent: $_" -ForegroundColor Red } } # ==================== TRAINING STEP FUNCTIONS ==================== function Step-NeuralNetwork { if (-not $global:valState.NNTraining) { return } if ($global:valState.NNEpoch -ge 1000) { $global:valState.NNTraining = $false return } # Train one epoch $totalError = 0 foreach ($sample in $global:xorData) { $output = $global:valState.NeuralNetwork.Forward($sample.Input) $error = $sample.Expected[0] - $output[0] $totalError += $error * $error $global:valState.NeuralNetwork.Backward($sample.Expected) } $global:valState.NNCurrentError = $totalError / $global:xorData.Count $global:valState.NNErrorHistory.Add($global:valState.NNCurrentError) | Out-Null $global:valState.NNEpoch++ } function Step-QLearning { # Get current state $state = "$($global:valState.GridX),$($global:valState.GridY)" # Choose action $action = $global:valState.QLAgent.ChooseAction($state) # Execute action $newX = $global:valState.GridX $newY = $global:valState.GridY if ($action -eq "up" -and $newY -gt 0) { $newY-- } if ($action -eq "down" -and $newY -lt 9) { $newY++ } if ($action -eq "left" -and $newX -gt 0) { $newX-- } if ($action -eq "right" -and $newX -lt 9) { $newX++ } # Calculate reward $reward = -0.1 # Step penalty if ($newX -eq $global:valState.GoalX -and $newY -eq $global:valState.GoalY) { $reward = 10.0 # Goal reward } $nextState = "$newX,$newY" # Learn $global:valState.QLAgent.Learn($state, $action, $reward, $nextState) # Store experience $experience = @{ State = $state Action = $action Reward = $reward NextState = $nextState } $global:valState.ExperienceReplay.Add($experience) # Update state $global:valState.GridX = $newX $global:valState.GridY = $newY $global:valState.QLTotalReward += $reward # Reset if goal reached if ($newX -eq $global:valState.GoalX -and $newY -eq $global:valState.GoalY) { $global:valState.QLRewardHistory.Add($global:valState.QLTotalReward) | Out-Null $global:valState.QLEpisode++ $global:valState.GridX = 0 $global:valState.GridY = 0 $global:valState.QLTotalReward = 0 } # Update replay stats $global:valState.ReplaySize = $global:valState.ExperienceReplay.Size() $global:valState.ReplaySizeHistory.Add($global:valState.ReplaySize) | Out-Null } # ==================== DRAWING FUNCTIONS ==================== function Draw-NeuralNetworkPanel { param($g, $width, $height) # Background $bgBrush = New-Object System.Drawing.SolidBrush([System.Drawing.Color]::FromArgb(30, 30, 30)) $g.FillRectangle($bgBrush, 0, 0, $width, $height) $bgBrush.Dispose() # Title $titleFont = New-Object System.Drawing.Font("Segoe UI", 11, [System.Drawing.FontStyle]::Bold) $titleBrush = New-Object System.Drawing.SolidBrush([System.Drawing.Color]::White) $g.DrawString("Neural Network - XOR Training", $titleFont, $titleBrush, 10, 10) $titleFont.Dispose() $titleBrush.Dispose() # Status $font = New-Object System.Drawing.Font("Consolas", 10) $brush = New-Object System.Drawing.SolidBrush([System.Drawing.Color]::Cyan) $status = "Epoch: $($global:valState.NNEpoch) | Error: $([Math]::Round($global:valState.NNCurrentError, 4))" if ($global:valState.NNTraining) { $status += " | TRAINING" } $g.DrawString($status, $font, $brush, 10, 40) # Learning curve if ($global:valState.NNErrorHistory.Count -gt 1) { $graphY = 80 $graphHeight = $height - 120 $graphWidth = $width - 40 # Grid $gridPen = New-Object System.Drawing.Pen([System.Drawing.Color]::FromArgb(50, 50, 50)) for ($i = 0; $i -le 5; $i++) { $y = $graphY + ($graphHeight * $i / 5) $g.DrawLine($gridPen, 20, $y, 20 + $graphWidth, $y) } $gridPen.Dispose() # Error line $maxError = 1.0 if ($global:valState.NNErrorHistory.Count -gt 0) { $max = ($global:valState.NNErrorHistory | Measure-Object -Maximum).Maximum if ($max -gt 0) { $maxError = $max } } $points = New-Object System.Collections.ArrayList for ($i = 0; $i -lt $global:valState.NNErrorHistory.Count; $i++) { $x = 20 + ($i / [Math]::Max(1, $global:valState.NNErrorHistory.Count - 1)) * $graphWidth $y = $graphY + $graphHeight - (($global:valState.NNErrorHistory[$i] / $maxError) * $graphHeight) $point = New-Object System.Drawing.PointF($x, $y) $points.Add($point) | Out-Null } if ($points.Count -gt 1) { $pen = New-Object System.Drawing.Pen([System.Drawing.Color]::Lime, 2) $g.DrawLines($pen, $points.ToArray([System.Drawing.PointF])) $pen.Dispose() } } $font.Dispose() $brush.Dispose() } function Draw-QLearningPanel { param($g, $width, $height) # Background $bgBrush = New-Object System.Drawing.SolidBrush([System.Drawing.Color]::FromArgb(30, 30, 30)) $g.FillRectangle($bgBrush, 0, 0, $width, $height) $bgBrush.Dispose() # Title $titleFont = New-Object System.Drawing.Font("Segoe UI", 11, [System.Drawing.FontStyle]::Bold) $titleBrush = New-Object System.Drawing.SolidBrush([System.Drawing.Color]::White) $g.DrawString("Q-Learning - Grid World (10x10)", $titleFont, $titleBrush, 10, 10) $titleFont.Dispose() $titleBrush.Dispose() # Status $font = New-Object System.Drawing.Font("Consolas", 10) $brush = New-Object System.Drawing.SolidBrush([System.Drawing.Color]::Cyan) $status = "Episode: $($global:valState.QLEpisode) | Position: ($($global:valState.GridX),$($global:valState.GridY))" $g.DrawString($status, $font, $brush, 10, 40) # Draw grid $cellSize = 25 $gridStartX = 20 $gridStartY = 80 for ($y = 0; $y -lt 10; $y++) { for ($x = 0; $x -lt 10; $x++) { $cellX = $gridStartX + ($x * $cellSize) $cellY = $gridStartY + ($y * $cellSize) # Cell color $cellBrush = New-Object System.Drawing.SolidBrush([System.Drawing.Color]::FromArgb(50, 50, 50)) # Agent position if ($x -eq $global:valState.GridX -and $y -eq $global:valState.GridY) { $cellBrush = New-Object System.Drawing.SolidBrush([System.Drawing.Color]::Yellow) } # Goal position if ($x -eq $global:valState.GoalX -and $y -eq $global:valState.GoalY) { $cellBrush = New-Object System.Drawing.SolidBrush([System.Drawing.Color]::Green) } $g.FillRectangle($cellBrush, $cellX, $cellY, $cellSize - 2, $cellSize - 2) $cellBrush.Dispose() } } # Reward history graph if ($global:valState.QLRewardHistory.Count -gt 1) { $graphY = $gridStartY + 270 $graphHeight = $height - $graphY - 20 $graphWidth = $width - 40 $points = New-Object System.Collections.ArrayList $maxReward = ($global:valState.QLRewardHistory | Measure-Object -Maximum).Maximum $minReward = ($global:valState.QLRewardHistory | Measure-Object -Minimum).Minimum $range = $maxReward - $minReward if ($range -eq 0) { $range = 1 } for ($i = 0; $i -lt $global:valState.QLRewardHistory.Count; $i++) { $x = 20 + ($i / [Math]::Max(1, $global:valState.QLRewardHistory.Count - 1)) * $graphWidth $normalized = ($global:valState.QLRewardHistory[$i] - $minReward) / $range $y = $graphY + $graphHeight - ($normalized * $graphHeight) $point = New-Object System.Drawing.PointF($x, $y) $points.Add($point) | Out-Null } if ($points.Count -gt 1) { $pen = New-Object System.Drawing.Pen([System.Drawing.Color]::Orange, 2) $g.DrawLines($pen, $points.ToArray([System.Drawing.PointF])) $pen.Dispose() } } $font.Dispose() $brush.Dispose() } function Draw-ExperienceReplayPanel { param($g, $width, $height) # Background $bgBrush = New-Object System.Drawing.SolidBrush([System.Drawing.Color]::FromArgb(30, 30, 30)) $g.FillRectangle($bgBrush, 0, 0, $width, $height) $bgBrush.Dispose() # Title $titleFont = New-Object System.Drawing.Font("Segoe UI", 11, [System.Drawing.FontStyle]::Bold) $titleBrush = New-Object System.Drawing.SolidBrush([System.Drawing.Color]::White) $g.DrawString("Experience Replay Buffer", $titleFont, $titleBrush, 10, 10) $titleFont.Dispose() $titleBrush.Dispose() # Status $font = New-Object System.Drawing.Font("Consolas", 10) $brush = New-Object System.Drawing.SolidBrush([System.Drawing.Color]::Cyan) $status = "Buffer Size: $($global:valState.ReplaySize) / 100" $g.DrawString($status, $font, $brush, 10, 40) # Buffer fill bar $barX = 20 $barY = 80 $barWidth = $width - 40 $barHeight = 30 $emptyBrush = New-Object System.Drawing.SolidBrush([System.Drawing.Color]::FromArgb(50, 50, 50)) $g.FillRectangle($emptyBrush, $barX, $barY, $barWidth, $barHeight) $emptyBrush.Dispose() $fillWidth = ($global:valState.ReplaySize / 100.0) * $barWidth $fillBrush = New-Object System.Drawing.SolidBrush([System.Drawing.Color]::Magenta) $g.FillRectangle($fillBrush, $barX, $barY, $fillWidth, $barHeight) $fillBrush.Dispose() # Buffer size history if ($global:valState.ReplaySizeHistory.Count -gt 1) { $graphY = 140 $graphHeight = $height - 160 $graphWidth = $width - 40 $points = New-Object System.Collections.ArrayList for ($i = 0; $i -lt $global:valState.ReplaySizeHistory.Count; $i++) { $x = 20 + ($i / [Math]::Max(1, $global:valState.ReplaySizeHistory.Count - 1)) * $graphWidth $y = $graphY + $graphHeight - (($global:valState.ReplaySizeHistory[$i] / 100.0) * $graphHeight) $point = New-Object System.Drawing.PointF($x, $y) $points.Add($point) | Out-Null } if ($points.Count -gt 1) { $pen = New-Object System.Drawing.Pen([System.Drawing.Color]::Magenta, 2) $g.DrawLines($pen, $points.ToArray([System.Drawing.PointF])) $pen.Dispose() } } $font.Dispose() $brush.Dispose() } # ==================== MAIN FORM ==================== Write-Host " - oo00oo - " -ForegroundColor Yellow Write-Host "VBAF Validation Dashboard" -ForegroundColor Cyan Write-Host " - oo00oo - " -ForegroundColor Yellow Initialize-NeuralNetwork Initialize-QLearning $form = New-Object System.Windows.Forms.Form $form.Text = "VBAF Validation Dashboard - Foundation Proof" $form.Width = 1400 $form.Height = 600 $form.BackColor = [System.Drawing.Color]::Black $form.FormBorderStyle = [System.Windows.Forms.FormBorderStyle]::FixedDialog $form.MaximizeBox = $false $form.StartPosition = [System.Windows.Forms.FormStartPosition]::CenterScreen $form.TopMost = $true # Bring to front when opening # Create panels $nnPanel = New-Object System.Windows.Forms.Panel $nnPanel.Left = 10 $nnPanel.Top = 50 $nnPanel.Width = 440 $nnPanel.Height = 450 $nnPanel.BackColor = [System.Drawing.Color]::FromArgb(30, 30, 30) $form.Controls.Add($nnPanel) $qlPanel = New-Object System.Windows.Forms.Panel $qlPanel.Left = 460 $qlPanel.Top = 50 $qlPanel.Width = 440 $qlPanel.Height = 450 $qlPanel.BackColor = [System.Drawing.Color]::FromArgb(30, 30, 30) $form.Controls.Add($qlPanel) $erPanel = New-Object System.Windows.Forms.Panel $erPanel.Left = 910 $erPanel.Top = 50 $erPanel.Width = 440 $erPanel.Height = 450 $erPanel.BackColor = [System.Drawing.Color]::FromArgb(30, 30, 30) $form.Controls.Add($erPanel) # Enable double buffering $prop = $nnPanel.GetType().GetProperty("DoubleBuffered", [System.Reflection.BindingFlags]"Instance,NonPublic") $prop.SetValue($nnPanel, $true, $null) $prop.SetValue($qlPanel, $true, $null) $prop.SetValue($erPanel, $true, $null) # Paint events $nnPanel.Add_Paint({ param($sender, $e) Draw-NeuralNetworkPanel $e.Graphics $sender.Width $sender.Height }) $qlPanel.Add_Paint({ param($sender, $e) Draw-QLearningPanel $e.Graphics $sender.Width $sender.Height }) $erPanel.Add_Paint({ param($sender, $e) Draw-ExperienceReplayPanel $e.Graphics $sender.Width $sender.Height }) # Control buttons $startButton = New-Object System.Windows.Forms.Button $startButton.Text = "▶ Start NN Training" $startButton.Left = 10 $startButton.Top = 10 #$startButton.Width = 150 #$startButton.Height = 30 $startButton.Width = 120 $startButton.Height = 20 $startButton.BackColor = [System.Drawing.Color]::FromArgb(0, 120, 215) # Bright blue $startButton.ForeColor = [System.Drawing.Color]::White $startButton.FlatStyle = [System.Windows.Forms.FlatStyle]::Flat $startButton.Font = New-Object System.Drawing.Font("Segoe UI", 9, [System.Drawing.FontStyle]::Bold) $startButton.Add_Click({ if (-not $global:valState.NNTraining) { # Start/Resume $global:valState.NNTraining = $true $timer.Start() $startButton.Text = "⏸ Pause NN Training" $startButton.BackColor = [System.Drawing.Color]::FromArgb(255, 140, 0) # Orange $stopButton.Enabled = $true $stopButton.Text = "⏹ Stop All" } else { # Pause $global:valState.NNTraining = $false $startButton.Text = "▶ Resume NN" $startButton.BackColor = [System.Drawing.Color]::FromArgb(0, 200, 80) # Green } }) $form.Controls.Add($startButton) $stopButton = New-Object System.Windows.Forms.Button $stopButton.Text = "⏹ Stop All" $stopButton.Left = 170 $stopButton.Top = 10 #$stopButton.Width = 120 #$stopButton.Height = 30 $stopButton.Width = 100 $stopButton.Height = 20 $stopButton.BackColor = [System.Drawing.Color]::FromArgb(220, 50, 50) # Bright red $stopButton.ForeColor = [System.Drawing.Color]::White $stopButton.FlatStyle = [System.Windows.Forms.FlatStyle]::Flat $stopButton.Font = New-Object System.Drawing.Font("Segoe UI", 9, [System.Drawing.FontStyle]::Bold) $stopButton.Add_Click({ $global:valState.NNTraining = $false $timer.Stop() $startButton.Text = "▶ Resume" $startButton.BackColor = [System.Drawing.Color]::FromArgb(0, 200, 80) # Green $startButton.Enabled = $true $stopButton.Text = "⏹ Stopped" $stopButton.Enabled = $false }) $form.Controls.Add($stopButton) $statusLabel = New-Object System.Windows.Forms.Label $statusLabel.Text = "Ready - Press Start to begin" $statusLabel.Left = 300 $statusLabel.Top = 15 $statusLabel.Width = 1000 $statusLabel.ForeColor = [System.Drawing.Color]::Lime $statusLabel.Font = New-Object System.Drawing.Font("Consolas", 10, [System.Drawing.FontStyle]::Bold) $form.Controls.Add($statusLabel) # Update timer $timer = New-Object System.Windows.Forms.Timer $timer.Interval = 50 # 20 FPS $timer.Add_Tick({ # Step NN training Step-NeuralNetwork # Step Q-Learning (every frame) Step-QLearning # Update status if ($global:valState.NNTraining) { $accuracy = (1.0 - $global:valState.NNCurrentError) * 100 $statusLabel.Text = "Training... Epoch: $($global:valState.NNEpoch) | Accuracy: $([Math]::Round($accuracy, 1))% | QL Episodes: $($global:valState.QLEpisode)" } elseif ($global:valState.NNEpoch -ge 1000) { $statusLabel.Text = "✓ Training Complete! NN converged. QL Episodes: $($global:valState.QLEpisode)" $statusLabel.ForeColor = [System.Drawing.Color]::Lime } # Redraw panels $nnPanel.Invalidate() $qlPanel.Invalidate() $erPanel.Invalidate() }) $timer.Start() Write-Host " ✓ Dashboard ready!" -ForegroundColor Green Write-Host " - oo00oo - " -ForegroundColor Yellow $form.ShowDialog() $timer.Stop() |