#region License Information
/* HeuristicLab
* Copyright (C) 2002-2008 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
*
* This file is part of HeuristicLab.
*
* HeuristicLab is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* HeuristicLab is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with HeuristicLab. If not, see .
*/
#endregion
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Threading;
namespace HeuristicLab.Core {
public abstract class EngineBase : ItemBase, IEngine {
protected IOperatorGraph myOperatorGraph;
public IOperatorGraph OperatorGraph {
get { return myOperatorGraph; }
}
protected IScope myGlobalScope;
public IScope GlobalScope {
get { return myGlobalScope; }
}
private TimeSpan myExecutionTime;
public TimeSpan ExecutionTime {
get { return myExecutionTime; }
protected set {
myExecutionTime = value;
OnExecutionTimeChanged();
}
}
protected Stack myExecutionStack;
public Stack ExecutionStack {
get { return myExecutionStack; }
}
protected bool myRunning;
public bool Running {
get { return myRunning; }
}
protected bool myCanceled;
public bool Canceled {
get { return myCanceled; }
}
public virtual bool Terminated {
get { return ExecutionStack.Count == 0; }
}
protected EngineBase() {
myOperatorGraph = new OperatorGraph();
myGlobalScope = new Scope("Global");
myExecutionStack = new Stack();
Reset();
}
public override object Clone(IDictionary clonedObjects) {
EngineBase clone = (EngineBase)base.Clone(clonedObjects);
clone.myOperatorGraph = (IOperatorGraph)Auxiliary.Clone(OperatorGraph, clonedObjects);
clone.myGlobalScope = (IScope)Auxiliary.Clone(GlobalScope, clonedObjects);
clone.myExecutionTime = ExecutionTime;
IOperation[] operations = new IOperation[ExecutionStack.Count];
ExecutionStack.CopyTo(operations, 0);
for (int i = operations.Length - 1; i >= 0; i--)
clone.myExecutionStack.Push((IOperation)Auxiliary.Clone(operations[i], clonedObjects));
clone.myRunning = Running;
clone.myCanceled = Canceled;
return clone;
}
public virtual void Execute() {
myRunning = true;
myCanceled = false;
ThreadPool.QueueUserWorkItem(new WaitCallback(Run), null);
}
public virtual void ExecuteSteps(int steps) {
myRunning = true;
myCanceled = false;
ThreadPool.QueueUserWorkItem(new WaitCallback(Run), steps);
}
public void ExecuteStep() {
ExecuteSteps(1);
}
public virtual void Abort() {
myCanceled = true;
}
public virtual void Reset() {
myCanceled = false;
myRunning = false;
OperatorGraph.Reset();
GlobalScope.Clear();
ExecutionTime = new TimeSpan();
myExecutionStack.Clear();
if (OperatorGraph.InitialOperator != null)
myExecutionStack.Push(new AtomicOperation(OperatorGraph.InitialOperator, GlobalScope));
OnInitialized();
}
private void Run(object state) {
if (state == null) Run();
else RunSteps((int)state);
myRunning = false;
OnFinished();
}
private void Run() {
DateTime start = DateTime.Now;
DateTime end;
while ((!Canceled) && (!Terminated)) {
ProcessNextOperation();
end = DateTime.Now;
ExecutionTime += end - start;
start = end;
}
ExecutionTime += DateTime.Now - start;
}
private void RunSteps(int steps) {
DateTime start = DateTime.Now;
DateTime end;
int step = 0;
while ((!Canceled) && (!Terminated) && (step < steps)) {
ProcessNextOperation();
step++;
end = DateTime.Now;
ExecutionTime += end - start;
start = end;
}
ExecutionTime += DateTime.Now - start;
}
protected abstract void ProcessNextOperation();
public event EventHandler Initialized;
protected virtual void OnInitialized() {
if (Initialized != null)
Initialized(this, new EventArgs());
}
public event EventHandler OperationExecuted;
protected virtual void OnOperationExecuted(IOperation operation) {
if (OperationExecuted != null)
OperationExecuted(this, new OperationEventArgs(operation));
}
public event EventHandler ExceptionOccurred;
protected virtual void OnExceptionOccurred(Exception exception) {
Abort();
if (ExceptionOccurred != null)
ExceptionOccurred(this, new ExceptionEventArgs(exception));
}
public event EventHandler ExecutionTimeChanged;
protected virtual void OnExecutionTimeChanged() {
if (ExecutionTimeChanged != null)
ExecutionTimeChanged(this, new EventArgs());
}
public event EventHandler Finished;
protected virtual void OnFinished() {
if (Finished != null)
Finished(this, new EventArgs());
}
#region Persistence Methods
public override XmlNode GetXmlNode(string name, XmlDocument document, IDictionary persistedObjects) {
XmlNode node = base.GetXmlNode(name, document, persistedObjects);
node.AppendChild(PersistenceManager.Persist("OperatorGraph", OperatorGraph, document, persistedObjects));
node.AppendChild(PersistenceManager.Persist("GlobalScope", GlobalScope, document, persistedObjects));
XmlNode stackNode = document.CreateNode(XmlNodeType.Element, "ExecutionStack", null);
IOperation[] operations = new IOperation[ExecutionStack.Count];
ExecutionStack.CopyTo(operations, 0);
for (int i = 0; i < operations.Length; i++)
stackNode.AppendChild(PersistenceManager.Persist(operations[i], document, persistedObjects));
node.AppendChild(stackNode);
XmlNode timeNode = document.CreateNode(XmlNodeType.Element, "ExecutionTime", null);
timeNode.InnerText = ExecutionTime.ToString();
node.AppendChild(timeNode);
return node;
}
public override void Populate(XmlNode node, IDictionary restoredObjects) {
base.Populate(node, restoredObjects);
myOperatorGraph = (IOperatorGraph)PersistenceManager.Restore(node.SelectSingleNode("OperatorGraph"), restoredObjects);
myGlobalScope = (IScope)PersistenceManager.Restore(node.SelectSingleNode("GlobalScope"), restoredObjects);
XmlNode stackNode = node.SelectSingleNode("ExecutionStack");
for (int i = stackNode.ChildNodes.Count - 1; i >= 0; i--)
myExecutionStack.Push((IOperation)PersistenceManager.Restore(stackNode.ChildNodes[i], restoredObjects));
XmlNode timeNode = node.SelectSingleNode("ExecutionTime");
myExecutionTime = TimeSpan.Parse(timeNode.InnerText);
}
#endregion
}
}