Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.SGA/SGA.cs @ 1182

Last change on this file since 1182 was 1153, checked in by vdorfer, 16 years ago

Created API documentation for HeuristicLab.Random, HeuristicLab.SGA and HeuristicLab.Selection.OffspringSelection namespace (#331)

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