Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2895_PushGP_GenealogyAnalysis/HeuristicLab.Problems.ProgramSynthesis.Views/PushDebuggerView.cs @ 16726

Last change on this file since 16726 was 15771, checked in by bburlacu, 7 years ago

#2895: Add solution skeleton for PushGP with genealogy analysis.

File size: 8.3 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.Drawing;
4using System.Linq;
5using System.Windows.Forms;
6using HeuristicLab.Core.Views;
7using HeuristicLab.MainForm;
8
9namespace HeuristicLab.Problems.ProgramSynthesis.Views {
10
11  public partial class PushDebuggerView : ItemView {
12    private readonly IDictionary<StackTypes, ListBox> debugListDict = new Dictionary<StackTypes, ListBox>();
13    private readonly IDictionary<StackTypes, PushProgramTreeView> debugPushProgramDict = new Dictionary<StackTypes, PushProgramTreeView>();
14
15    private PooledPushInterpreter interpreter;
16    private PushInterpreterPool pool;
17
18    private const string GROUP_BOX_TEXT_STRING_FORMAT = "{0}[{1}]";
19    private const string EXEC_COUNT_LABEL_FORMAT = "{0}/{1} max. expressions evaluated";
20
21    public event EventHandler<IPushInterpreter> OnReset;
22
23    public PushDebuggerView() {
24      InitializeComponent();
25      InitEvents();
26    }
27
28    ~PushDebuggerView() {
29      interpreter.Dispose();
30    }
31
32    public new PushSolution Content {
33      get { return (PushSolution)base.Content; }
34      set {
35        base.Content = value;
36      }
37    }
38
39    protected override void OnContentChanged() {
40      if (Content == null) return;
41
42      Name = "Push Debugger";
43      pool = new PushInterpreterPool(Content.Config);
44
45      if (interpreter != null) {
46        interpreter.Dispose();
47      }
48
49      var random = Content.GetRandom();
50      interpreter = pool.Create(random);
51
52      InitDebugLists(Content.Config);
53      ClearDebugLists();
54      UpdateExecList();
55      UpdateDebugLists();
56      ResetDebugging();
57    }
58
59    private void UpdateExecCountLabel() {
60      execCountLabel.Text = string.Format(
61        EXEC_COUNT_LABEL_FORMAT,
62        interpreter.ExecCounter,
63        Content.Config.EvalPushLimit);
64    }
65
66    private void InitEvents() {
67      runButton.Click += RunButtonClick;
68      resetButton.Click += ResetButtonClick;
69      stepButton.Click += StepButtonClick;
70      simplifyButton.Click += SimplifyButtonClick;
71    }
72
73    private void RunButtonClick(object sender, EventArgs e) {
74      if (interpreter == null)
75        return;
76
77      interpreter.Resume();
78      UpdateStep();
79    }
80
81    private void StepButtonClick(object sender, EventArgs e) {
82      if (interpreter == null || stepWidthBox.Value <= 0)
83        return;
84
85      var count = Math.Min(stepWidthBox.Value, interpreter.ExecStack.Count);
86
87      for (var i = 0; i < count; i++) {
88        SkipNoops();
89
90        // run next none noop expression
91        interpreter.Step();
92      }
93
94      // skip trailing noops so next expression is a none noop in debugger
95      SkipNoops();
96
97      stepWidthBox.Maximum = Math.Max(1, interpreter.ExecStack.Count);
98      UpdateStep();
99    }
100
101    private void UpdateStep() {
102      UpdateExecList();
103      UpdateDebugLists();
104      UpdateExecCountLabel();
105      CheckIfButtonsCanBeEnabled();
106    }
107
108    private void SkipNoops() {
109      // skip noops
110      if (skipNoopsCheckBox.Checked) {
111        while (interpreter.CanStep && interpreter.ExecStack.Top.IsNoop(interpreter)) {
112          interpreter.Step();
113        }
114      }
115    }
116
117    private void CheckIfButtonsCanBeEnabled() {
118      runButton.Enabled = interpreter != null && interpreter.CanStep;
119      stepButton.Enabled = interpreter != null && interpreter.CanStep;
120      stepWidthBox.Enabled = interpreter != null && interpreter.CanStep;
121    }
122
123    private void ResetButtonClick(object sender, EventArgs e) {
124      ResetDebugging();
125    }
126
127    private void SimplifyButtonClick(object sender, EventArgs e) {
128      var newContent = Content.Simplify();
129
130      MainFormManager.MainForm.ShowContent(newContent, GetType());
131    }
132
133    public void ResetDebugging() {
134      if (Content == null ||
135          pool == null ||
136          Content.Program == null)
137        return;
138
139      if (interpreter != null) {
140        interpreter.Reset();
141      }
142
143      if (OnReset != null) {
144        OnReset(this, interpreter);
145      }
146
147      interpreter.Run(Content.Program, true);
148
149      stepWidthBox.Maximum = interpreter.ExecStack.Count;
150      UpdateStep();
151    }
152
153    private void ClearDebugLists() {
154      foreach (var list in debugListDict.Values) {
155        list.Items.Clear();
156      }
157
158      foreach (var treeView in debugPushProgramDict.Values) {
159        treeView.Nodes.Clear();
160      }
161    }
162
163    private void UpdateExecList() {
164      execTreeView.LoadExpressions(interpreter.ExecStack.Reverse());
165      exec2GroupBox.Text = string.Format(GROUP_BOX_TEXT_STRING_FORMAT, Enum.GetName(typeof(StackTypes), StackTypes.Exec), interpreter.ExecStack.Count);
166    }
167
168    private void InitDebugLists(IReadOnlyPushConfiguration config) {
169      debugListDict.Clear();
170      debugPushProgramDict.Clear();
171
172      // 2 = ExecList + EmptyColumn which is required to fill empty space
173      while (debugTableLayout.ColumnCount > 2) {
174        debugTableLayout.Controls.RemoveAt(1);
175        debugTableLayout.ColumnCount--;
176      }
177
178      foreach (StackTypes stackType in Enum.GetValues(typeof(StackTypes))) {
179        if (stackType == StackTypes.Exec || !config.IsStackEnabled(stackType))
180          continue;
181
182        switch (stackType) {
183          case StackTypes.Code:
184            var treeView = CreatePushProgramTreeView(stackType);
185            debugPushProgramDict.Add(stackType, treeView);
186            break;
187          default:
188            var list = CreateDebugList(stackType);
189            debugListDict.Add(stackType, list);
190            break;
191        }
192      }
193    }
194
195    private PushProgramTreeView CreatePushProgramTreeView(StackTypes type) {
196
197      var treeView = new PushProgramTreeView {
198        Dock = DockStyle.Fill
199      };
200
201      AddStackControlToTableLayout(type, treeView, 400);
202
203      return treeView;
204    }
205
206    private void AddStackControlToTableLayout(StackTypes type, Control control, int width) {
207      var groupBox = CreateStackGroupBox(type);
208      groupBox.Controls.Add(control);
209
210      debugTableLayout.ColumnCount++;
211      debugTableLayout.ColumnStyles.Insert(1, new ColumnStyle(SizeType.Absolute, width));
212      debugTableLayout.Controls.Add(groupBox);
213      debugTableLayout.Controls.SetChildIndex(groupBox, 1);
214    }
215
216    private ListBox CreateDebugList(StackTypes type) {
217      var list = new ListBox {
218        Dock = DockStyle.Fill
219      };
220
221      // align numbers right
222      if (type == StackTypes.Integer ||
223          type == StackTypes.Float) {
224        list.DrawMode = DrawMode.OwnerDrawFixed;
225        list.DrawItem += (sender, e) => {
226          if (e.Index <= -1) return;
227          var item = list.Items[e.Index];
228
229          e.DrawBackground();
230          e.DrawFocusRectangle();
231
232          var brush = new SolidBrush(e.ForeColor);
233          var size = e.Graphics.MeasureString(item.ToString(), e.Font);
234
235          e.Graphics.DrawString(
236            item.ToString(),
237            e.Font,
238            brush,
239            e.Bounds.Right - size.Width,
240            e.Bounds.Top + (e.Bounds.Height / 2 - size.Height / 2));
241        };
242      }
243
244      AddStackControlToTableLayout(type, list, 150);
245
246      return list;
247    }
248
249    private static GroupBox CreateStackGroupBox(StackTypes type) {
250      return new GroupBox {
251        Anchor = AnchorStyles.Bottom | AnchorStyles.Right | AnchorStyles.Left | AnchorStyles.Top,
252        AutoSize = true,
253        AutoSizeMode = AutoSizeMode.GrowAndShrink,
254        Text = Enum.GetName(typeof(StackTypes), type)
255      };
256    }
257
258    private void UpdateDebugLists() {
259      ClearDebugLists();
260
261      if (Content == null || interpreter == null)
262        return;
263
264      foreach (var pair in debugPushProgramDict) {
265        var name = Enum.GetName(typeof(StackTypes), pair.Key);
266        var stack = (IPushStack<Expression>)interpreter.Stacks[pair.Key];
267
268        pair.Value.AddExpressions(stack);
269        ((GroupBox)pair.Value.Parent).Text = string.Format(GROUP_BOX_TEXT_STRING_FORMAT, name, pair.Value.Nodes.Count);
270      }
271
272      foreach (var pair in debugListDict) {
273        var name = Enum.GetName(typeof(StackTypes), pair.Key);
274        var items = interpreter.StringifyStack(pair.Key).ToArray();
275
276        pair.Value.Items.AddRange(items);
277        ((GroupBox)pair.Value.Parent).Text = string.Format(GROUP_BOX_TEXT_STRING_FORMAT, name, pair.Value.Items.Count);
278      }
279    }
280
281  }
282}
Note: See TracBrowser for help on using the repository browser.