Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.SA/SA.cs @ 1335

Last change on this file since 1335 was 1289, checked in by abeham, 15 years ago

Added simulated annealing (SA) user interface (#18)

File size: 22.4 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2009 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.Text;
25using System.Xml;
26using HeuristicLab.Core;
27using HeuristicLab.Data;
28using HeuristicLab.SequentialEngine;
29using HeuristicLab.Operators;
30using HeuristicLab.Random;
31using HeuristicLab.Logging;
32using HeuristicLab.Selection;
33using HeuristicLab.Selection.OffspringSelection;
34using HeuristicLab.Evolutionary;
35
36namespace HeuristicLab.SA {
37  /// <summary>
38  /// Class for the heuristic optimization technique "simulated annealing".
39  /// </summary>
40  public class SA : ItemBase, IEditable {
41    #region Create Operators
42    /// <summary>
43    /// Creates operators for the current instance.
44    /// </summary>
45    /// <param name="engine">The engine where to add the operators.</param>
46    public static void Create(IEngine engine) {
47      engine.OperatorGraph.Clear();
48
49      CombinedOperator co = CreateSA();
50      co.Name = "SA";
51      engine.OperatorGraph.AddOperator(co);
52      engine.OperatorGraph.InitialOperator = co;
53
54      engine.Reset();
55    }
56    private static CombinedOperator CreateSA() {
57      CombinedOperator op = new CombinedOperator();
58      SequentialProcessor sp = new SequentialProcessor();
59      op.OperatorGraph.AddOperator(sp);
60      op.OperatorGraph.InitialOperator = sp;
61
62      CombinedOperator co1 = CreateVariableInjection();
63      co1.Name = "Variable Injection";
64      op.OperatorGraph.AddOperator(co1);
65      sp.AddSubOperator(co1);
66
67      // place holder for ProblemInjector
68      EmptyOperator eo1 = new EmptyOperator();
69      eo1.Name = "ProblemInjector";
70      op.OperatorGraph.AddOperator(eo1);
71      co1.AddSubOperator(eo1);
72
73      CombinedOperator co2 = CreateSolutionInitialization();
74      co2.Name = "Solution Initialization";
75      op.OperatorGraph.AddOperator(co2);
76      sp.AddSubOperator(co2);
77
78      // place holder for SolutionGenerator
79      EmptyOperator eo2 = new EmptyOperator();
80      eo2.Name = "SolutionGenerator";
81      op.OperatorGraph.AddOperator(eo2);
82      co2.AddSubOperator(eo2);
83
84      // place holder for Evaluator
85      EmptyOperator eo3 = new EmptyOperator();
86      eo3.Name = "Evaluator";
87      op.OperatorGraph.AddOperator(eo3);
88      co2.AddSubOperator(eo3);
89
90      CombinedOperator co3 = CreateSAMain();
91      co3.Name = "SA Main";
92      op.OperatorGraph.AddOperator(co3);
93      sp.AddSubOperator(co3);
94
95      EmptyOperator eo4 = new EmptyOperator();
96      eo4.Name = "AnnealingScheme";
97      op.OperatorGraph.AddOperator(eo4);
98      co3.AddSubOperator(eo4);
99
100      // place holder for Mutator
101      EmptyOperator eo5 = new EmptyOperator();
102      eo5.Name = "Mutator";
103      op.OperatorGraph.AddOperator(eo5);
104      co3.AddSubOperator(eo5);
105
106      // place holder for Evaluator
107      co3.AddSubOperator(eo3);
108
109      return op;
110    }
111    private static CombinedOperator CreateVariableInjection() {
112      CombinedOperator op = new CombinedOperator();
113      SequentialProcessor sp = new SequentialProcessor();
114      op.OperatorGraph.AddOperator(sp);
115      op.OperatorGraph.InitialOperator = sp;
116
117      RandomInjector ri = new RandomInjector();
118      op.OperatorGraph.AddOperator(ri);
119      sp.AddSubOperator(ri);
120
121      OperatorExtractor oe = new OperatorExtractor();
122      oe.Name = "ProblemInjector";
123      oe.GetVariableInfo("Operator").ActualName = "ProblemInjector";
124      op.OperatorGraph.AddOperator(oe);
125      sp.AddSubOperator(oe);
126
127      VariableInjector vi = new VariableInjector();
128      vi.AddVariable(new Variable("EvaluatedSolutions", new IntData(0)));
129      vi.AddVariable(new Variable("Iteration", new IntData(0)));
130      vi.AddVariable(new Variable("MaximumIterations", new IntData(1000)));
131      vi.AddVariable(new Variable("Temperature", new DoubleData(100)));
132      vi.AddVariable(new Variable("AnnealingParameter", new DoubleData(0.95)));
133      vi.AddVariable(new Variable("SuccessRatioLimit", new DoubleData(1)));
134      vi.AddVariable(new Variable("MaximumIterationEffort", new DoubleData(1)));
135      op.OperatorGraph.AddOperator(vi);
136      sp.AddSubOperator(vi);
137
138      return op;
139    }
140    private static CombinedOperator CreateSolutionInitialization() {
141      CombinedOperator op = new CombinedOperator();
142      SequentialProcessor sp1 = new SequentialProcessor();
143      op.OperatorGraph.AddOperator(sp1);
144      op.OperatorGraph.InitialOperator = sp1;
145
146      SubScopesCreater ssc = new SubScopesCreater();
147      ssc.GetVariableInfo("SubScopes").Local = true;
148      ssc.AddVariable(new Variable("SubScopes", new IntData(1)));
149      op.OperatorGraph.AddOperator(ssc);
150      sp1.AddSubOperator(ssc);
151
152      UniformSequentialSubScopesProcessor ussp = new UniformSequentialSubScopesProcessor();
153      op.OperatorGraph.AddOperator(ussp);
154      sp1.AddSubOperator(ussp);
155
156      SequentialProcessor sp2 = new SequentialProcessor();
157      op.OperatorGraph.AddOperator(sp2);
158      ussp.AddSubOperator(sp2);
159
160      OperatorExtractor oe1 = new OperatorExtractor();
161      oe1.Name = "SolutionGenerator (Extractor)";
162      oe1.GetVariableInfo("Operator").ActualName = "SolutionGenerator";
163      op.OperatorGraph.AddOperator(oe1);
164      sp2.AddSubOperator(oe1);
165
166      OperatorExtractor oe2 = new OperatorExtractor();
167      oe2.Name = "Evaluator (Extractor)";
168      oe2.GetVariableInfo("Operator").ActualName = "Evaluator";
169      op.OperatorGraph.AddOperator(oe2);
170      sp2.AddSubOperator(oe2);
171
172      Counter c = new Counter();
173      c.GetVariableInfo("Value").ActualName = "EvaluatedSolutions";
174      op.OperatorGraph.AddOperator(c);
175      sp2.AddSubOperator(c);
176
177      return op;
178    }
179    private static CombinedOperator CreateSAMain() {
180      CombinedOperator op = new CombinedOperator();
181      SequentialProcessor sp = new SequentialProcessor();
182      op.OperatorGraph.AddOperator(sp);
183      op.OperatorGraph.InitialOperator = sp;
184
185      SequentialProcessor sp1 = new SequentialProcessor();
186      op.OperatorGraph.AddOperator(sp1);
187      sp.AddSubOperator(sp1);
188
189      LeftSelector ls = new LeftSelector();
190      ls.GetVariable("CopySelected").GetValue<BoolData>().Data = true;
191      ls.GetVariableInfo("Selected").Local = true;
192      ls.AddVariable(new Variable("Selected", new IntData(1)));
193      op.OperatorGraph.AddOperator(ls);
194      sp1.AddSubOperator(ls);
195
196      SequentialSubScopesProcessor ssp = new SequentialSubScopesProcessor();
197      op.OperatorGraph.AddOperator(ssp);
198      sp1.AddSubOperator(ssp);
199
200      EmptyOperator eo = new EmptyOperator();
201      op.OperatorGraph.AddOperator(eo);
202      ssp.AddSubOperator(eo);
203
204      CombinedOperator co1 = CreateCreateMutant();
205      co1.Name = "Create Mutant";
206      op.OperatorGraph.AddOperator(co1);
207      ssp.AddSubOperator(co1);
208
209      OffspringSelector oss = new OffspringSelector();
210      oss.GetVariableInfo("SelectionPressureLimit").ActualName = "MaximumIterationEffort";
211      op.OperatorGraph.AddOperator(oss);
212      sp1.AddSubOperator(oss);
213      oss.AddSubOperator(sp1);
214
215      LessThanComparator ltc = new LessThanComparator();
216      ltc.Name = "SuccessRatio";
217      ltc.GetVariableInfo("LeftSide").ActualName = "SuccessRatio";
218      ltc.GetVariableInfo("RightSide").ActualName = "SuccessRatioLimit";
219      ltc.GetVariableInfo("Result").ActualName = "SuccessfulOS";
220      op.OperatorGraph.AddOperator(ltc);
221      sp.AddSubOperator(ltc);
222
223      ConditionalBranch cb = new ConditionalBranch();
224      cb.GetVariableInfo("Condition").ActualName = "SuccessfulOS";
225      op.OperatorGraph.AddOperator(cb);
226      sp.AddSubOperator(cb);
227
228      LeftReducer lr = new LeftReducer();
229      lr.Name = "No Replacement";
230      op.OperatorGraph.AddOperator(lr);
231      cb.AddSubOperator(lr);
232
233      RightReducer rr = new RightReducer();
234      rr.Name = "Replacement";
235      op.OperatorGraph.AddOperator(rr);
236      cb.AddSubOperator(rr);
237
238      QualityLogger ql = new QualityLogger();
239      op.OperatorGraph.AddOperator(ql);
240      sp.AddSubOperator(ql);
241
242      BestAverageWorstQualityCalculator bawqc = new BestAverageWorstQualityCalculator();
243      bawqc.GetVariableInfo("AverageQuality").Local = true;
244      bawqc.GetVariableInfo("WorstQuality").Local = true;
245      op.OperatorGraph.AddOperator(bawqc);
246      sp.AddSubOperator(bawqc);
247
248      DataCollector dc = new DataCollector();
249      ItemList<StringData> names = dc.GetVariable("VariableNames").GetValue<ItemList<StringData>>();
250      names.Add(new StringData("BestQuality"));
251      op.OperatorGraph.AddOperator(dc);
252      sp.AddSubOperator(dc);
253
254      LinechartInjector lci = new LinechartInjector();
255      lci.GetVariableInfo("Linechart").ActualName = "Quality Linechart";
256      lci.GetVariable("NumberOfLines").GetValue<IntData>().Data = 1;
257      op.OperatorGraph.AddOperator(lci);
258      sp.AddSubOperator(lci);
259
260      Counter c = new Counter();
261      c.GetVariableInfo("Value").ActualName = "Iteration";
262      op.OperatorGraph.AddOperator(c);
263      sp.AddSubOperator(c);
264
265      VariableAssigner va = new VariableAssigner();
266      va.Name = "Reset SelectionPressure";
267      va.GetVariableInfo("Variable").ActualName = "SelectionPressure";
268      va.GetVariableInfo("Value").Local = true;
269      va.AddVariable(new Variable("Value", new DoubleData(1)));
270      op.OperatorGraph.AddOperator(va);
271      sp.AddSubOperator(va);
272
273      OperatorExtractor oe = new OperatorExtractor();
274      oe.Name = "AnnealingScheme (Extractor)";
275      oe.GetVariableInfo("Operator").ActualName = "AnnealingScheme";
276      op.OperatorGraph.AddOperator(oe);
277      sp.AddSubOperator(oe);
278
279      GreaterThanComparator gtc = new GreaterThanComparator();
280      gtc.Name = "Temperature > 0";
281      gtc.GetVariableInfo("LeftSide").ActualName = "Temperature";
282      gtc.GetVariableInfo("RightSide").Local = true;
283      gtc.AddVariable(new Variable("RightSide", new DoubleData(0)));
284      gtc.GetVariableInfo("Result").ActualName = "TemperatureCondition";
285      op.OperatorGraph.AddOperator(gtc);
286      sp.AddSubOperator(gtc);
287
288      ConditionalBranch cb1 = new ConditionalBranch();
289      cb1.GetVariableInfo("Condition").ActualName = "TemperatureCondition";
290      op.OperatorGraph.AddOperator(cb1);
291      sp.AddSubOperator(cb1);
292
293      SequentialProcessor sp2 = new SequentialProcessor();
294      op.OperatorGraph.AddOperator(sp2);
295      cb1.AddSubOperator(sp2);
296
297      LessThanComparator ltc1 = new LessThanComparator();
298      ltc1.Name = "Iteration < MaximumIterations";
299      ltc1.GetVariableInfo("LeftSide").ActualName = "Iteration";
300      ltc1.GetVariableInfo("RightSide").ActualName = "MaximumIterations";
301      ltc1.GetVariableInfo("Result").ActualName = "IterationsCondition";
302      op.OperatorGraph.AddOperator(ltc1);
303      sp2.AddSubOperator(ltc1);
304
305      ConditionalBranch cb2 = new ConditionalBranch();
306      cb2.GetVariableInfo("Condition").ActualName = "IterationsCondition";
307      op.OperatorGraph.AddOperator(cb2);
308      sp2.AddSubOperator(cb2);
309
310      cb2.AddSubOperator(sp);
311
312      return op;
313    }
314    private static CombinedOperator CreateCreateMutant() {
315      CombinedOperator op = new CombinedOperator();
316      SequentialProcessor sp1 = new SequentialProcessor();
317      op.OperatorGraph.AddOperator(sp1);
318      op.OperatorGraph.InitialOperator = sp1;
319
320      ChildrenInitializer ci = new ChildrenInitializer();
321      ci.GetVariable("ParentsPerChild").GetValue<IntData>().Data = 1;
322      op.OperatorGraph.AddOperator(ci);
323      sp1.AddSubOperator(ci);
324
325      UniformSequentialSubScopesProcessor ussp = new UniformSequentialSubScopesProcessor();
326      op.OperatorGraph.AddOperator(ussp);
327      sp1.AddSubOperator(ussp);
328
329      SequentialProcessor sp2 = new SequentialProcessor();
330      op.OperatorGraph.AddOperator(sp2);
331      ussp.AddSubOperator(sp2);
332
333      VariablesCopier vc = new VariablesCopier();
334      op.OperatorGraph.AddOperator(vc);
335      sp2.AddSubOperator(vc);
336
337      OperatorExtractor oe = new OperatorExtractor();
338      oe.Name = "Mutator (Extractor)";
339      oe.GetVariableInfo("Operator").ActualName = "Mutator";
340      op.OperatorGraph.AddOperator(oe);
341      sp2.AddSubOperator(oe);
342
343      OperatorExtractor oe1 = new OperatorExtractor();
344      oe1.Name = "Evaluator (Extractor)";
345      oe1.GetVariableInfo("Operator").ActualName = "Evaluator";
346      op.OperatorGraph.AddOperator(oe1);
347      sp2.AddSubOperator(oe1);
348
349      Counter c = new Counter();
350      c.GetVariableInfo("Value").ActualName = "EvaluatedSolutions";
351      op.OperatorGraph.AddOperator(c);
352      sp2.AddSubOperator(c);
353
354      TemperatureBasedFitnessComparer tbfc = new TemperatureBasedFitnessComparer();
355      op.OperatorGraph.AddOperator(tbfc);
356      sp2.AddSubOperator(tbfc);
357
358      SubScopesRemover sr = new SubScopesRemover();
359      sr.GetVariableInfo("SubScopeIndex").Local = true;
360      op.OperatorGraph.AddOperator(sr);
361      sp2.AddSubOperator(sr);
362
363      return op;
364    }
365    #endregion
366
367    #region Properties
368    private IEngine myEngine;
369    /// <summary>
370    /// Gets the engine of the current instance.
371    /// </summary>
372    public IEngine Engine {
373      get { return myEngine; }
374    }
375    private BoolData mySetSeedRandomly;
376    /// <summary>
377    /// Gets or sets the flag whether to set the seed randomly or not.
378    /// </summary>
379    public bool SetSeedRandomly {
380      get { return mySetSeedRandomly.Data; }
381      set { mySetSeedRandomly.Data = value; }
382    }
383    private IntData mySeed;
384    /// <summary>
385    /// Gets or sets the value of the seed of the current instance.
386    /// </summary>
387    public int Seed {
388      get { return mySeed.Data; }
389      set { mySeed.Data = value; }
390    }
391    private IntData myMaximumIterations;
392    /// <summary>
393    /// Gets or sets the number of maximum iterations.
394    /// </summary>
395    public int MaximumIterations {
396      get { return myMaximumIterations.Data; }
397      set { myMaximumIterations.Data = value; }
398    }
399    private DoubleData myTemperature;
400    /// <summary>
401    /// Gets or sets the initial temperature.
402    /// </summary>
403    public double Temperature {
404      get { return myTemperature.Data; }
405      set { myTemperature.Data = value; }
406    }
407    private DoubleData myAnnealingParameter;
408    /// <summary>
409    /// Gets or sets the annealing parameter.
410    /// </summary>
411    public double AnnealingParameter {
412      get { return myAnnealingParameter.Data; }
413      set { myAnnealingParameter.Data = value; }
414    }
415    private DoubleData myMaximumIterationEffort;
416    /// <summary>
417    /// Gets or sets how much solutions should be created in one temperature in attempt to find a better one.
418    /// </summary>
419    public double MaximumIterationEffort {
420      get { return myMaximumIterationEffort.Data; }
421      set { myMaximumIterationEffort.Data = value; }
422    }
423    private CombinedOperator mySA;
424    private IOperator myVariableInjection;
425    /// <summary>
426    /// Gets or sets the problem injector of the current instance.
427    /// </summary>
428    public IOperator ProblemInjector {
429      get { return myVariableInjection.SubOperators[0]; }
430      set {
431        value.Name = "ProblemInjector";
432        mySA.OperatorGraph.RemoveOperator(ProblemInjector.Guid);
433        mySA.OperatorGraph.AddOperator(value);
434        myVariableInjection.AddSubOperator(value, 0);
435      }
436    }
437    private IOperator myPopulationInitialization;
438    /// <summary>
439    /// Gets or sets the solution generator of the current instance.
440    /// </summary>
441    public IOperator SolutionGenerator {
442      get { return myPopulationInitialization.SubOperators[0]; }
443      set {
444        value.Name = "SolutionGenerator";
445        mySA.OperatorGraph.RemoveOperator(SolutionGenerator.Guid);
446        mySA.OperatorGraph.AddOperator(value);
447        myPopulationInitialization.AddSubOperator(value, 0);
448      }
449    }
450    /// <summary>
451    /// Gets or sets the evaluator of the current instance.
452    /// </summary>
453    public IOperator Evaluator {
454      get { return myPopulationInitialization.SubOperators[1]; }
455      set {
456        value.Name = "Evaluator";
457        mySA.OperatorGraph.RemoveOperator(Evaluator.Guid);
458        mySA.OperatorGraph.AddOperator(value);
459        myPopulationInitialization.AddSubOperator(value, 1);
460        mySAMain.AddSubOperator(value, 2);
461      }
462    }
463    private IOperator mySAMain;
464    /// <summary>
465    /// Gets or sets the mutation operator of the current instance.
466    /// </summary>
467    public IOperator Mutator {
468      get { return mySAMain.SubOperators[1]; }
469      set {
470        value.Name = "Mutator";
471        mySA.OperatorGraph.RemoveOperator(Mutator.Guid);
472        mySA.OperatorGraph.AddOperator(value);
473        mySAMain.AddSubOperator(value, 1);
474      }
475    }
476    /// <summary>
477    /// Gets or sets the annealing schema to be used
478    /// </summary>
479    public IOperator AnnealingScheme {
480      get { return mySAMain.SubOperators[0]; }
481      set {
482        value.Name = "AnnealingScheme";
483        mySA.OperatorGraph.RemoveOperator(AnnealingScheme.Guid);
484        mySA.OperatorGraph.AddOperator(value);
485        mySAMain.AddSubOperator(value, 0);
486      }
487    }
488    #endregion
489
490    /// <summary>
491    /// Initializes a new instance of <see cref="SA"/>.
492    /// </summary>
493    public SA() {
494      myEngine = new SequentialEngine.SequentialEngine();
495      Create(myEngine);
496      SetReferences();
497    }
498
499    /// <summary>
500    /// Creates a new instance of the <see cref="SAEditor"/> class.
501    /// </summary>
502    /// <returns>The created instance of the <see cref="SAEditor"/>.</returns>
503    public override IView CreateView() {
504      return new SAEditor(this);
505    }
506    /// <summary>
507    /// Creates a new instance of the <see cref="SAEditor"/> class.
508    /// </summary>
509    /// <returns>The created instance of the <see cref="SAEditor"/>.</returns>
510    public virtual IEditor CreateEditor() {
511      return new SAEditor(this);
512    }
513
514    /// <summary>
515    /// Clones the current instance (deep clone).
516    /// </summary>
517    /// <remarks>Deep clone through <see cref="Auxiliary.Clone"/> method of helper class
518    /// <see cref="Auxiliary"/>.</remarks>
519    /// <param name="clonedObjects">Dictionary of all already cloned objects. (Needed to avoid cycles.)</param>
520    /// <returns>The cloned object as <see cref="SA"/>.</returns>
521    public override object Clone(IDictionary<Guid, object> clonedObjects) {
522      SA clone = new SA();
523      clonedObjects.Add(Guid, clone);
524      clone.myEngine = (IEngine)Auxiliary.Clone(Engine, clonedObjects);
525      return clone;
526    }
527
528    #region SetReferences Method
529    private void SetReferences() {
530      // SA
531      CombinedOperator co1 = (CombinedOperator)Engine.OperatorGraph.InitialOperator;
532      mySA = co1;
533      // SequentialProcessor in SA
534      SequentialProcessor sp1 = (SequentialProcessor)co1.OperatorGraph.InitialOperator;
535      // Variable Injection
536      CombinedOperator co2 = (CombinedOperator)sp1.SubOperators[0];
537      myVariableInjection = co2;
538      // SequentialProcessor in Variable Injection
539      SequentialProcessor sp2 = (SequentialProcessor)co2.OperatorGraph.InitialOperator;
540      // RandomInjector
541      RandomInjector ri = (RandomInjector)sp2.SubOperators[0];
542      mySetSeedRandomly = ri.GetVariable("SetSeedRandomly").GetValue<BoolData>();
543      mySeed = ri.GetVariable("Seed").GetValue<IntData>();
544      // VariableInjector
545      VariableInjector vi = (VariableInjector)sp2.SubOperators[2];
546      myMaximumIterations = vi.GetVariable("MaximumIterations").GetValue<IntData>();
547      myMaximumIterationEffort = vi.GetVariable("MaximumIterationEffort").GetValue<DoubleData>();
548      myTemperature = vi.GetVariable("Temperature").GetValue<DoubleData>();
549      myAnnealingParameter = vi.GetVariable("AnnealingParameter").GetValue<DoubleData>();
550      // Population Initialization
551      CombinedOperator co3 = (CombinedOperator)sp1.SubOperators[1];
552      myPopulationInitialization = co3;
553      // SA Main
554      CombinedOperator co4 = (CombinedOperator)sp1.SubOperators[2];
555      mySAMain = co4;
556    }
557    #endregion
558
559    #region Persistence Methods
560    /// <summary>
561    /// Saves the current instance as <see cref="XmlNode"/> in the specified <paramref name="document"/>.
562    /// </summary>
563    /// <remarks>The engine of the current instance is saved as a child node with the tag name
564    /// <c>Engine</c>.</remarks>
565    /// <param name="name">The (tag)name of the <see cref="XmlNode"/>.</param>
566    /// <param name="document">The <see cref="XmlDocument"/> where the data is saved.</param>
567    /// <param name="persistedObjects">A dictionary of all already persisted objects. (Needed to avoid cycles.)</param>
568    /// <returns>The saved <see cref="XmlNode"/>.</returns>
569    public override XmlNode GetXmlNode(string name, XmlDocument document, IDictionary<Guid,IStorable> persistedObjects) {
570      XmlNode node = base.GetXmlNode(name, document, persistedObjects);
571      node.AppendChild(PersistenceManager.Persist("Engine", Engine, document, persistedObjects));
572      return node;
573    }
574    /// <summary>
575    /// Loads the persisted instance from the specified <paramref name="node"/>.
576    /// </summary>
577    /// <remarks>The elements of the current instance must be saved in a special way, see
578    /// <see cref="GetXmlNode"/>.</remarks>
579    /// <param name="node">The <see cref="XmlNode"/> where the instance is saved.</param>
580    /// <param name="restoredObjects">The dictionary of all already restored objects. (Needed to avoid cycles.)</param>
581    public override void Populate(XmlNode node, IDictionary<Guid,IStorable> restoredObjects) {
582      base.Populate(node, restoredObjects);
583      myEngine = (IEngine)PersistenceManager.Restore(node.SelectSingleNode("Engine"), restoredObjects);
584      SetReferences();
585    }
586    #endregion
587  }
588}
Note: See TracBrowser for help on using the repository browser.