using System.Collections.ObjectModel; using System.Globalization; using System.Security.AccessControl; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Documents; using System.Windows.Media; using System.Xml.Serialization; using Evaluation.ViewModel; using HeuristicLab.Algorithms.Bandits; using HeuristicLab.Algorithms.Bandits.BanditPolicies; using HeuristicLab.Algorithms.GeneticProgramming; using HeuristicLab.Algorithms.GrammaticalOptimization; using HeuristicLab.Algorithms.MonteCarloTreeSearch; using HeuristicLab.Algorithms.MonteCarloTreeSearch.Simulation; using HeuristicLab.Problems.GrammaticalOptimization; using Microsoft.Research.DynamicDataDisplay; using Microsoft.Research.DynamicDataDisplay.DataSources; using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.IO; using System.Windows; using System.Windows.Controls; using System.Windows.Threading; using Microsoft.Win32; using WpfTestSvgSample; namespace Evaluation { /// /// Interaction logic for MainWindow.xaml /// public partial class MainWindow : Window { private EvaluationViewModel vm; private DrawingPage treeDrawingPage; public MainWindow() { InitializeComponent(); CenterWindowOnScreen(); this.DataContext = vm = new EvaluationViewModel(); vm.MaxLen = 17; vm.MaxIterations = 300000; vm.NrRuns = 20; vm.MaxThreads = 10; } private void CenterWindowOnScreen() { double screenWidth = System.Windows.SystemParameters.PrimaryScreenWidth; double screenHeight = System.Windows.SystemParameters.PrimaryScreenHeight; double windowWidth = this.Width; double windowHeight = this.Height; this.Left = (screenWidth / 2) - (windowWidth / 2); this.Top = (screenHeight / 2) - (windowHeight / 2); } private void DrawQualityChart(Run run) { List solutions = new List(run.FoundSolutions); if (run.BestSolutionFoundAt < run.Evaluations) { solutions.Add(new FoundSolution(run.EndTime, run.Evaluations, run.BestQuality, run.BestSolution)); } // insert point between two solutions, with the result that there is no direct line from solutionpoint to solutionpoint for (int i = 1; i < solutions.Count; i++) { FoundSolution previousSolution = solutions[i - 1]; FoundSolution currentSolution = solutions[i]; // insert point solutions.Insert(i, new FoundSolution(currentSolution.Time, currentSolution.Iteration, previousSolution.Quality, "placeholder")); i++; } var ds = new EnumerableDataSource(solutions); ds.SetXMapping(x => x.Iteration); ds.SetYMapping(y => y.Quality / run.BestKnownQuality); LineGraph graph = new LineGraph(ds); graph.StrokeThickness = 2; graph.AddToPlotter(QualityChartPlotter); } private void DrawSelectionChart(Run run) { // quality line List solutions = new List(run.FoundSolutions); if (run.BestSolutionFoundAt < run.Evaluations) { solutions.Add(new FoundSolution(run.EndTime, run.Evaluations, run.BestQuality, run.BestSolution)); } // insert point between two solutions, with the result that there is no direct line from solutionpoint to solutionpoint for (int i = 1; i < solutions.Count; i++) { FoundSolution previousSolution = solutions[i - 1]; FoundSolution currentSolution = solutions[i]; // insert point solutions.Insert(i, new FoundSolution(currentSolution.Time, currentSolution.Iteration, previousSolution.Quality, "placeholder")); i++; } var ds = new EnumerableDataSource(solutions); ds.SetXMapping(x => x.Iteration); ds.SetYMapping(y => y.Quality / run.BestKnownQuality); LineGraph graph = new LineGraph(ds); graph.StrokeThickness = 2; graph.AddToPlotter(SelectionChartPlotter); // selection indicator line List selectionIndicators = new List(run.SelectionIndicators); var dssi = new EnumerableDataSource(selectionIndicators); dssi.SetXMapping(x => x.Evaluation); dssi.SetYMapping(y => y.Indicator); graph = new LineGraph(dssi); graph.StrokeThickness = 2; graph.Stroke = Brushes.Red; graph.AddToPlotter(SelectionChartPlotter); } private void DrawTreeChart(Run run) { if (!string.IsNullOrEmpty(run.SvgFile)) { treeDrawingPage.LoadDocument(run.SvgFile); } } private void DoRun(Object threadContext) { Run run = (Run)threadContext; run.RunState = RunState.Running; run.StartTime = DateTime.Now; run.Solver.Run(run.MaxIterations); run.EndTime = DateTime.Now; run.RunState = RunState.Analyzing; if (run.FoundSolutions.Count > 0) { if (run.Solver is MonteCarloTreeSearch) { MonteCarloTreeSearch mctsSolver = (MonteCarloTreeSearch)run.Solver; run.TreeInfos = mctsSolver.GetTreeInfos(); // svg-tree -> //byte[] output = mctsSolver.GenerateSvg(); //if (output != null && output.Length > 0) //{ // run.SvgFile = string.Format("MCTS_SVG_#{0}_{1}.svg", run.RunNumber, DateTime.Now.Ticks); // File.WriteAllBytes(run.SvgFile, output); //} mctsSolver.FreeAll(); } } run.RunState = RunState.Finished; lock (vm.CompletedRuns) { int completed = 0; foreach (Run r in vm.Runs) { if (r.RunState == RunState.Finished) { completed++; } } vm.CompletedRuns = string.Format("{0}/{1}", completed, vm.Runs.Count); if (completed == vm.NrRuns) { Dispatcher.Invoke(AllRunsFinished); } } } private void AllRunsFinished() { ButtonRun.IsEnabled = true; TextBoxMaxIterations.IsEnabled = true; TextBoxMaxLen.IsEnabled = true; TextBoxRuns.IsEnabled = true; TextBoxMaxThreads.IsEnabled = true; } private void StartRuns() { vm.CompletedRuns = string.Format("0/{0}", vm.NrRuns); Type algorithmType = vm.SelectedAlgorithm; ISymbolicExpressionTreeProblem problem = vm.SelectedProblem; Type policy = vm.SelectedPolicy; IBanditPolicy policyInstance = null; if (policy == typeof(UCTPolicy)) { policyInstance = new UCTPolicy(vm.PolicyParameter); } else if (policy == typeof(ThresholdAscentPolicy)) { policyInstance = new ThresholdAscentPolicy(); } else if (policy == typeof(BoltzmannExplorationPolicy)) { policyInstance = new BoltzmannExplorationPolicy(2); } else if (policy == typeof(EpsGreedyPolicy)) { policyInstance = new EpsGreedyPolicy(vm.PolicyParameter); } else { policyInstance = (IBanditPolicy)Activator.CreateInstance(policy); } for (int i = 0; i < vm.NrRuns; i++) { ISolver solver = null; Random random = new Random(Guid.NewGuid().GetHashCode()); if (algorithmType == typeof(MonteCarloTreeSearch_PruneLeaves)) { solver = new MonteCarloTreeSearch_PruneLeaves(problem, vm.MaxLen, random, policyInstance, new RandomSimulation(problem, random, vm.MaxLen)); } else if (algorithmType == typeof(MonteCarloTreeSearch)) { solver = new MonteCarloTreeSearch(problem, vm.MaxLen, random, policyInstance, new RandomSimulation(problem, random, vm.MaxLen)); } else if (algorithmType == typeof(SequentialSearch)) { solver = new SequentialSearch(problem, vm.MaxLen, random, 0, new HeuristicLab.Algorithms.Bandits.GrammarPolicies.GenericGrammarPolicy(problem, policyInstance)); } else if (algorithmType == typeof(RandomSearch)) { solver = new RandomSearch(problem, random, vm.MaxLen); } else if (algorithmType == typeof(StandardGP)) { solver = new StandardGP(problem, random); } else if (algorithmType == typeof(OffspringSelectionGP)) { solver = new OffspringSelectionGP(problem, random); } Run run = new Run(problem, policyInstance, solver, i + 1, vm.MaxIterations, vm.MaxLen); vm.Runs.Add(run); } Task.Run(() => Parallel.For(0, vm.NrRuns, new ParallelOptions { MaxDegreeOfParallelism = vm.MaxThreads }, i => DoRun(vm.Runs[i]))); } private void ClearQualityChart() { QualityChartPlotter.Children.RemoveAll(); } private void ClearComparisonChart() { ComparisonChartPlotter.Children.RemoveAll(); } private void ClearSelectionChart() { SelectionChartPlotter.Children.RemoveAll(); } private void ButtonRun_OnClick(object sender, RoutedEventArgs e) { ClearQualityChart(); ClearComparisonChart(); ClearSelectionChart(); vm.Runs.Clear(); vm.SelectedRun = null; ButtonRun.IsEnabled = false; TextBoxMaxIterations.IsEnabled = false; TextBoxMaxLen.IsEnabled = false; TextBoxRuns.IsEnabled = false; StartRuns(); } private void ButtonPause_OnClick(object sender, RoutedEventArgs e) { //if (vm.SelectedAlgorithm == typeof(MonteCarloTreeSearch)) //{ // MonteCarloTreeSearch mcts = (MonteCarloTreeSearch)solver; // mcts.PauseContinue(); // if (mcts.IsPaused) // { // ButtonPause.Content = "Continue"; // } // else // { // ButtonPause.Content = "Pause"; // } //} } private void ButtonStop_OnClick(object sender, RoutedEventArgs e) { //worker.CancelAsync(); } private void ComboBoxAlgorithms_OnSelectionChanged(object sender, SelectionChangedEventArgs e) { if (vm.SelectedAlgorithm == typeof(MonteCarloTreeSearch) || vm.SelectedAlgorithm == typeof(MonteCarloTreeSearch_PruneLeaves)) { ComboBoxPolicies.IsEnabled = true; TabItemTree.IsEnabled = true; } else if (vm.SelectedAlgorithm == typeof(SequentialSearch)) { ComboBoxPolicies.IsEnabled = true; TabItemTree.IsEnabled = false; } else { ComboBoxPolicies.IsEnabled = false; TabItemTree.IsEnabled = false; } } private void Window_Loaded(object sender, RoutedEventArgs e) { treeDrawingPage = treeDrawing.Content as DrawingPage; } private void ListBoxRuns_OnSelectionChanged(object sender, SelectionChangedEventArgs e) { if (vm.SelectedRun != null) { vm.SelectedRun.Solver.FoundNewBestSolution -= SelectedRun_FoundNewBestSolution; } if (ListBoxRuns.SelectedItem != null) { vm.SelectedRun = (Run)ListBoxRuns.SelectedItem; vm.SelectedRun.Solver.FoundNewBestSolution += SelectedRun_FoundNewBestSolution; ClearQualityChart(); DrawQualityChart(vm.SelectedRun); if (vm.SelectedRun.RunState == RunState.Finished) { ClearSelectionChart(); DrawSelectionChart(vm.SelectedRun); } //DrawTreeChart(vm.SelectedRun); } else { vm.SelectedRun = null; } } void SelectedRun_FoundNewBestSolution(string arg1, double arg2) { Dispatcher.BeginInvoke(new Action(() => { ClearQualityChart(); DrawQualityChart(vm.SelectedRun); })); } public void SaveToFile() { SaveFileDialog dlg = new SaveFileDialog(); dlg.FileName = "runs"; // Default file name dlg.DefaultExt = ".xml"; // Default file extension // Show save file dialog box Nullable result = dlg.ShowDialog(); // Process save file dialog box results if (result == true) { // Save document string filename = dlg.FileName; XmlSerializer serializer = new XmlSerializer(typeof(ObservableCollection)); using (TextWriter writer = new StreamWriter(filename)) { serializer.Serialize(writer, vm.Runs); } } } public void LoadFromFile() { OpenFileDialog dlg = new OpenFileDialog(); // Show save file dialog box Nullable result = dlg.ShowDialog(); // Process save file dialog box results if (result == true) { // Load document string filename = dlg.FileName; XmlSerializer deserializer = new XmlSerializer(typeof(ObservableCollection)); using (TextReader reader = new StreamReader(filename)) { object obj = deserializer.Deserialize(reader); vm.Runs = (ObservableCollection)obj; } } } private void LoadButton_OnClick(object sender, RoutedEventArgs e) { LoadFromFile(); } private void SaveButton_OnClick(object sender, RoutedEventArgs e) { SaveToFile(); } private void MenuItemCopyToClipboard_OnClick(object sender, RoutedEventArgs e) { StringBuilder tableExport = new StringBuilder(); tableExport.Append( "Run\tMaxIterations\tEvaluations\tBestKnownQuality\tQuality\tQuality %\tFoundAt\tTotalTime\tSolutionTime\tEvaluationsPerSecond\tSolution"); if (ListViewRuns.Items.Count > 0 && ((Run)ListViewRuns.Items[0]).TreeInfos != null) { tableExport.Append("\tTotalNodes\tUnexpandedNodes\tExpandedNodes\tLeaveNodes\tDeepestLevel"); } tableExport.AppendLine(); for (int i = 0; i < ListViewRuns.Items.Count; i++) { Run run = (Run)ListViewRuns.Items[i]; tableExport.Append(string.Format("{0}\t{1}\t{2}\t{3}\t{4}\t{5}\t{6}\t{7}\t{8}\t{9}\t{10}", run.RunNumber, run.MaxIterations, run.Evaluations, run.BestKnownQuality, run.BestQuality, run.BestQuality / run.BestKnownQuality, run.BestSolutionFoundAt, run.TotalTime, run.BestSolutionTime, run.EvaluationsPerSecond, run.BestSolution)); if (run.TreeInfos != null) { tableExport.Append(string.Format("\t{0}\t{1}\t{2}\t{3}\t{4}", run.TreeInfos.TotalNodes, run.TreeInfos.UnexpandedNodes, run.TreeInfos.ExpandedNodes, run.TreeInfos.LeaveNodes, run.TreeInfos.DeepestLevel)); } tableExport.AppendLine(); } Clipboard.SetData(DataFormats.Text, tableExport.ToString()); } private void ComboBoxPolicies_OnSelectionChanged(object sender, SelectionChangedEventArgs e) { if (vm.SelectedPolicy == typeof(EpsGreedyPolicy)) { TextBoxEpsylon.Visibility = Visibility.Visible; vm.PolicyParameter = 0.5; TextBlockEpsylon.Text = "Epsilon"; TextBlockEpsylon.Visibility = Visibility.Visible; } else if (vm.SelectedPolicy == typeof(UCTPolicy)) { TextBoxEpsylon.Visibility = Visibility.Visible; vm.PolicyParameter = Math.Sqrt(2); TextBlockEpsylon.Text = "c"; TextBlockEpsylon.Visibility = Visibility.Visible; } else { TextBoxEpsylon.Visibility = Visibility.Hidden; TextBlockEpsylon.Visibility = Visibility.Hidden; } } private void Selector_OnSelectionChanged(object sender, SelectionChangedEventArgs e) { if (vm.SelectedRun != null && vm.SelectedRun.RunState == RunState.Finished) { if (ChartSelector.SelectedItem == TabSelectionIndicator) { ClearSelectionChart(); DrawSelectionChart(vm.SelectedRun); } else if (ChartSelector.SelectedItem == TabQualityChart) { ClearQualityChart(); DrawQualityChart(vm.SelectedRun); } else if (ChartSelector.SelectedItem == TabItemTree) { DrawTreeChart(vm.SelectedRun); } } } } }