Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Core/3.3/Engine.cs @ 2796

Last change on this file since 2796 was 2796, checked in by swagner, 14 years ago

Operator architecture refactoring (#95)

  • worked on operators, parameters and problems
File size: 11.0 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2010 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections.Generic;
24using System.Drawing;
25using System.Threading;
26using HeuristicLab.Common;
27using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
28
29namespace HeuristicLab.Core {
30  /// <summary>
31  /// Base class to represent an engine, which is an interpreter, holding the code, the data and
32  /// the actual state, which is the runtime stack and a pointer onto the next operation. It represents
33  /// one execution and can handle parallel executions.
34  /// </summary>
35  [Item("Engine", "A base class for engines.")]
36  public abstract class Engine : Item, IEngine {
37    public override Image ItemImage {
38      get { return HeuristicLab.Common.Resources.VS2008ImageLibrary.Event; }
39    }
40
41    private OperatorGraph operatorGraph;
42    /// <summary>
43    /// Gets or sets the current operator graph.
44    /// </summary>
45    [Storable]
46    public OperatorGraph OperatorGraph {
47      get { return operatorGraph; }
48      set {
49        if (value == null) throw new ArgumentNullException();
50        if (value != operatorGraph) {
51          if (operatorGraph != null) operatorGraph.InitialOperatorChanged -= new EventHandler(operatorGraph_InitialOperatorChanged);
52          operatorGraph = value;
53          if (operatorGraph != null) operatorGraph.InitialOperatorChanged += new EventHandler(operatorGraph_InitialOperatorChanged);
54          OnOperatorGraphChanged();
55          Prepare();
56        }
57      }
58    }
59
60    /// <summary>
61    /// Field of the current instance that represent the global scope.
62    /// </summary>
63    [Storable]
64    private IScope globalScope;
65    /// <summary>
66    /// Gets the current global scope.
67    /// </summary>
68    public IScope GlobalScope {
69      get { return globalScope; }
70    }
71
72    [Storable]
73    private IProblem problem;
74    /// <summary>
75    /// Gets or sets the current problem.
76    /// </summary>
77    public IProblem Problem {
78      get { return problem; }
79      set {
80        if (value == null) throw new ArgumentNullException();
81        if (value != problem) {
82          problem = value;
83          OnProblemChanged();
84          Prepare();
85        }
86      }
87    }
88
89    [Storable]
90    private TimeSpan executionTime;
91    /// <summary>
92    /// Gets or sets the execution time.
93    /// </summary>
94    /// <remarks>Calls <see cref="OnExecutionTimeChanged"/> in the setter.</remarks>
95    public TimeSpan ExecutionTime {
96      get { return executionTime; }
97      protected set {
98        executionTime = value;
99        OnExecutionTimeChanged();
100      }
101    }
102
103    /// <summary>
104    /// Field of the current instance that represent the execution stack.
105    /// </summary>
106    [Storable]
107    private Stack<IExecutionSequence> executionStack;
108    /// <summary>
109    /// Gets the current execution stack.
110    /// </summary>
111    protected Stack<IExecutionSequence> ExecutionStack {
112      get { return executionStack; }
113    }
114
115    /// <summary>
116    /// Flag of the current instance whether it is currently running.
117    /// </summary>
118    private bool running;
119    /// <summary>
120    /// Gets information whether the instance is currently running.
121    /// </summary>
122    public bool Running {
123      get { return running; }
124    }
125
126    /// <summary>
127    /// Flag of the current instance whether it is canceled.
128    /// </summary>
129    private bool canceled;
130    /// <summary>
131    /// Gets information whether the instance is currently canceled.
132    /// </summary>
133    protected bool Canceled {
134      get { return canceled; }
135    }
136    /// <summary>
137    /// Gets information whether the instance has already terminated.
138    /// </summary>
139    public bool Finished {
140      get { return executionStack.Count == 0; }
141    }
142
143    /// <summary>
144    /// Initializes a new instance of <see cref="EngineBase"/> with a new global scope.
145    /// </summary>
146    protected Engine() {
147      globalScope = new Scope("Global");
148      problem = null;
149      executionStack = new Stack<IExecutionSequence>();
150      OperatorGraph = new OperatorGraph();
151    }
152
153    /// <summary>
154    /// Clones the current instance (deep clone).
155    /// </summary>
156    /// <remarks>Deep clone through <see cref="cloner.Clone"/> method of helper class
157    /// <see cref="Auxiliary"/>.</remarks>
158    /// <param name="clonedObjects">Dictionary of all already clone objects. (Needed to avoid cycles.)</param>
159    /// <returns>The cloned object as <see cref="EngineBase"/>.</returns>
160    public override IDeepCloneable Clone(Cloner cloner) {
161      Engine clone = (Engine)base.Clone(cloner);
162      clone.OperatorGraph = (OperatorGraph)cloner.Clone(operatorGraph);
163      clone.globalScope = (Scope)cloner.Clone(globalScope);
164      clone.problem = (IProblem)cloner.Clone(problem);
165      clone.executionTime = executionTime;
166      IExecutionSequence[] contexts = executionStack.ToArray();
167      for (int i = contexts.Length - 1; i >= 0; i--)
168        clone.executionStack.Push((IExecutionSequence)cloner.Clone(contexts[i]));
169      clone.running = running;
170      clone.canceled = canceled;
171      return clone;
172    }
173
174    /// <inheritdoc/>
175    /// <remarks>Sets <c>myCanceled</c> and <c>myRunning</c> to <c>false</c>. The global scope is cleared,
176    /// the execution time is reset, the execution stack is cleared and a new <see cref="AtomicOperation"/>
177    /// with the initial operator is added. <br/>
178    /// Calls <see cref="OnPrepared"/>.</remarks>
179    public void Prepare() {
180      canceled = false;
181      running = false;
182      globalScope.Clear();
183      ExecutionTime = new TimeSpan();
184      executionStack.Clear();
185      if ((OperatorGraph.InitialOperator != null) && (Problem != null))
186        executionStack.Push(new ExecutionContext(null, OperatorGraph.InitialOperator, GlobalScope, Problem));
187      OnPrepared();
188    }
189    /// <inheritdoc/>
190    /// <remarks>Calls <see cref="ThreadPool.QueueUserWorkItem(System.Threading.WaitCallback, object)"/>
191    /// of class <see cref="ThreadPool"/>.</remarks>
192    public void Start() {
193      running = true;
194      canceled = false;
195      ThreadPool.QueueUserWorkItem(new WaitCallback(Run), null);
196    }
197    /// <inheritdoc/>
198    /// <remarks>Calls <see cref="ThreadPool.QueueUserWorkItem(System.Threading.WaitCallback, object)"/>
199    /// of class <see cref="ThreadPool"/>.</remarks>
200    public void Step() {
201      running = true;
202      canceled = false;
203      ThreadPool.QueueUserWorkItem(new WaitCallback(RunStep), null);
204    }
205    /// <inheritdoc/>
206    /// <remarks>Sets the protected flag <c>myCanceled</c> to <c>true</c>.</remarks>
207    public virtual void Stop() {
208      canceled = true;
209    }
210
211    private void Run(object state) {
212      OnStarted();
213      DateTime start = DateTime.Now;
214      DateTime end;
215      while ((!Canceled) && (!Finished)) {
216        ProcessNextOperator();
217        end = DateTime.Now;
218        ExecutionTime += end - start;
219        start = end;
220      }
221      ExecutionTime += DateTime.Now - start;
222      running = false;
223      OnStopped();
224    }
225    private void RunStep(object state) {
226      OnStarted();
227      DateTime start = DateTime.Now;
228      if ((!Canceled) && (!Finished))
229        ProcessNextOperator();
230      ExecutionTime += DateTime.Now - start;
231      running = false;
232      OnStopped();
233    }
234
235    /// <summary>
236    /// Performs the next operation.
237    /// </summary>
238    protected abstract void ProcessNextOperator();
239
240    private void operatorGraph_InitialOperatorChanged(object sender, EventArgs e) {
241      Prepare();
242    }
243
244    /// <summary>
245    /// Occurs when the operator graph was changed.
246    /// </summary>
247    public event EventHandler OperatorGraphChanged;
248    /// <summary>
249    /// Fires a new <c>OperatorGraphChanged</c> event.
250    /// </summary>
251    protected virtual void OnOperatorGraphChanged() {
252      if (OperatorGraphChanged != null)
253        OperatorGraphChanged(this, EventArgs.Empty);
254    }
255    /// <summary>
256    /// Occurs when the problem was changed.
257    /// </summary>
258    public event EventHandler ProblemChanged;
259    /// <summary>
260    /// Fires a new <c>ProblemChanged</c> event.
261    /// </summary>
262    protected virtual void OnProblemChanged() {
263      if (ProblemChanged != null)
264        ProblemChanged(this, EventArgs.Empty);
265    }
266    /// <summary>
267    /// Occurs when the execution time changed.
268    /// </summary>
269    public event EventHandler ExecutionTimeChanged;
270    /// <summary>
271    /// Fires a new <c>ExecutionTimeChanged</c> event.
272    /// </summary>
273    protected virtual void OnExecutionTimeChanged() {
274      if (ExecutionTimeChanged != null)
275        ExecutionTimeChanged(this, EventArgs.Empty);
276    }
277    /// <summary>
278    /// Occurs when the execution is prepared for a new run.
279    /// </summary>
280    public event EventHandler Prepared;
281    /// <summary>
282    /// Fires a new <c>Prepared</c> event.
283    /// </summary>
284    protected virtual void OnPrepared() {
285      if (Prepared != null)
286        Prepared(this, EventArgs.Empty);
287    }
288    /// <summary>
289    /// Occurs when the execution is executed.
290    /// </summary>
291    public event EventHandler Started;
292    /// <summary>
293    /// Fires a new <c>Started</c> event.
294    /// </summary>
295    protected virtual void OnStarted() {
296      if (Started != null)
297        Started(this, EventArgs.Empty);
298    }
299    /// <summary>
300    /// Occurs when the execution is finished.
301    /// </summary>
302    public event EventHandler Stopped;
303    /// <summary>
304    /// Fires a new <c>Stopped</c> event.
305    /// </summary>
306    protected virtual void OnStopped() {
307      if (Stopped != null)
308        Stopped(this, EventArgs.Empty);
309    }
310    /// <summary>
311    /// Occurs when an exception occured during the execution.
312    /// </summary>
313    public event EventHandler<EventArgs<Exception>> ExceptionOccurred;
314    /// <summary>
315    /// Aborts the execution and fires a new <c>ExceptionOccurred</c> event.
316    /// </summary>
317    /// <param name="exception">The exception that was thrown.</param>
318    protected virtual void OnExceptionOccurred(Exception exception) {
319      if (ExceptionOccurred != null)
320        ExceptionOccurred(this, new EventArgs<Exception>(exception));
321    }
322  }
323}
Note: See TracBrowser for help on using the repository browser.