Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.GP.Algorithms/3.2/AlgorithmBase.cs @ 3155

Last change on this file since 3155 was 2683, checked in by gkronber, 15 years ago

Implemented operator to calculate variable impacts based on the log of variable frequencies over the whole GP run and integrated operators into default SGP and OSGP algorithms. #853 (Operator to calculate variable impacts as integral over the relative frequencies of variable references over the whole GP run and the whole population)

File size: 21.8 KB
RevLine 
[1230]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;
[2222]24using System.Xml;
[1230]25using HeuristicLab.Core;
[2222]26using HeuristicLab.Data;
27using HeuristicLab.Evolutionary;
28using HeuristicLab.Logging;
[1230]29using HeuristicLab.Operators;
30using HeuristicLab.Random;
31using HeuristicLab.Selection;
[2331]32using HeuristicLab.GP.Operators;
[2566]33using HeuristicLab.GP.Interfaces;
[1230]34
[2331]35namespace HeuristicLab.GP.Algorithms {
[2566]36  public abstract class AlgorithmBase : ItemBase, IGeneticProgrammingAlgorithm {
[1857]37    public virtual string Name { get { return "GP"; } }
38    public virtual string Description { get { return "TODO"; } }
39
[1231]40    public virtual double MutationRate {
[1287]41      get { return GetVariableInjector().GetVariable("MutationRate").GetValue<DoubleData>().Data; }
42      set { GetVariableInjector().GetVariable("MutationRate").GetValue<DoubleData>().Data = value; }
[1230]43    }
[1231]44    public virtual int PopulationSize {
[1287]45      get { return GetVariableInjector().GetVariable("PopulationSize").GetValue<IntData>().Data; }
46      set { GetVariableInjector().GetVariable("PopulationSize").GetValue<IntData>().Data = value; }
[1230]47    }
48
[2335]49    public virtual int MaxGenerations {
50      get { return GetVariableInjector().GetVariable("MaxGenerations").GetValue<IntData>().Data; }
51      set { GetVariableInjector().GetVariable("MaxGenerations").GetValue<IntData>().Data = value; }
[1230]52    }
53
[1231]54    public virtual int Elites {
[1287]55      get { return GetVariableInjector().GetVariable("Elites").GetValue<IntData>().Data; }
56      set { GetVariableInjector().GetVariable("Elites").GetValue<IntData>().Data = value; }
[1230]57    }
58
[1231]59    public virtual int MaxTreeSize {
[1287]60      get { return GetVariableInjector().GetVariable("MaxTreeSize").GetValue<IntData>().Data; }
61      set { GetVariableInjector().GetVariable("MaxTreeSize").GetValue<IntData>().Data = value; }
[1230]62    }
63
[2335]64    public virtual int MinTreeSize {
65      get { return GetVariableInjector().GetVariable("MinTreeSize").GetValue<IntData>().Data; }
66      set { GetVariableInjector().GetVariable("MinTreeSize").GetValue<IntData>().Data = value; }
67    }
68
[1231]69    public virtual int MaxTreeHeight {
[1287]70      get { return GetVariableInjector().GetVariable("MaxTreeHeight").GetValue<IntData>().Data; }
71      set { GetVariableInjector().GetVariable("MaxTreeHeight").GetValue<IntData>().Data = value; }
[1230]72    }
73
[1231]74    public virtual int Parents {
[1287]75      get { return GetVariableInjector().GetVariable("Parents").GetValue<IntData>().Data; }
76      set { GetVariableInjector().GetVariable("Parents").GetValue<IntData>().Data = value; }
[1231]77    }
78
[2335]79    public virtual bool SetSeedRandomly {
80      get { return GetRandomInjector().GetVariable("SetSeedRandomly").GetValue<BoolData>().Data; }
81      set { GetRandomInjector().GetVariable("SetSeedRandomly").GetValue<BoolData>().Data = value; }
82    }
83
84    public virtual int RandomSeed {
85      get { return GetRandomInjector().GetVariable("Seed").GetValue<IntData>().Data; }
86      set { GetRandomInjector().GetVariable("Seed").GetValue<IntData>().Data = value; }
87    }
88
89    public virtual IOperator ProblemInjector {
90      get { return GetInitializationOperator().SubOperators[0]; }
91      set {
92        value.Name = "ProblemInjector";
93        IOperator init = GetInitializationOperator();
94        init.RemoveSubOperator(0);
95        init.AddSubOperator(value, 0);
96      }
97    }
98
99    public virtual IOperator FunctionLibraryInjector {
100      get { return GetInitializationOperator().SubOperators[1]; }
101      set {
102        value.Name = "FunctionLibraryInjector";
103        IOperator init = GetInitializationOperator();
104        init.RemoveSubOperator(1);
105        init.AddSubOperator(value, 1);
106      }
107    }
108
[2377]109    private IEngine engine;
[1230]110    public IEngine Engine {
111      get { return engine; }
[2377]112      protected set { engine = value; }
[1230]113    }
114
115    public AlgorithmBase() {
116      engine = new SequentialEngine.SequentialEngine();
117      CombinedOperator algo = CreateAlgorithm();
118      engine.OperatorGraph.AddOperator(algo);
119      engine.OperatorGraph.InitialOperator = algo;
[1287]120      SetSeedRandomly = true;
121      Elites = 1;
122      MutationRate = 0.15;
123      PopulationSize = 1000;
[2335]124      MaxGenerations = 100;
[1287]125      MaxTreeSize = 100;
[2335]126      MinTreeSize = 1;
[1287]127      MaxTreeHeight = 10;
128      Parents = 2000;
[1230]129    }
130
[1287]131    protected internal virtual CombinedOperator CreateAlgorithm() {
[1230]132      CombinedOperator algo = new CombinedOperator();
[2361]133      algo.Name = Name;
[1230]134      SequentialProcessor seq = new SequentialProcessor();
[2361]135      seq.Name = Name;
[2335]136      IOperator init = CreateInitializationOperator();
137      init.AddSubOperator(CreateProblemInjector());
138      init.AddSubOperator(CreateFunctionLibraryInjector());
139      seq.AddSubOperator(init);
[1230]140
[2335]141      IOperator initPopulation = CreateInitialPopulationGenerator();
142      initPopulation.AddSubOperator(CreateRandomSolutionGenerator());
143      initPopulation.AddSubOperator(CreateInitialPopulationEvaluator());
144      seq.AddSubOperator(initPopulation);
[1230]145
146      IOperator mainLoop = CreateMainLoop();
[2335]147      mainLoop.AddSubOperator(CreateSelectionOperator());
148      mainLoop.AddSubOperator(CreateCrossoverOperator());
149      mainLoop.AddSubOperator(CreateManipulationOperator());
150      mainLoop.AddSubOperator(CreateEvaluationOperator());
151      mainLoop.AddSubOperator(CreateTerminationCondition());
[1230]152      seq.AddSubOperator(mainLoop);
153
[2335]154      IOperator postProcess = CreatePostProcessingOperator();
155      seq.AddSubOperator(postProcess);
[1230]156
157      algo.OperatorGraph.AddOperator(seq);
158      algo.OperatorGraph.InitialOperator = seq;
159      return algo;
160    }
161
[2335]162    #region global init
163    protected virtual IOperator CreateInitializationOperator() {
164      CombinedOperator init = new CombinedOperator();
165      init.Name = "Initialization";
166      SequentialProcessor seq = new SequentialProcessor();
167      seq.AddSubOperator(CreateRandomInjector());
168      seq.AddSubOperator(CreateGlobalInjector());
[2328]169
[2335]170      OperatorExtractor probInjectorExtractor = new OperatorExtractor();
171      probInjectorExtractor.Name = "ProblemInjector";
172      probInjectorExtractor.GetVariableInfo("Operator").ActualName = "ProblemInjector";
173      seq.AddSubOperator(probInjectorExtractor);
174
175      OperatorExtractor funLibInjectorExtractor = new OperatorExtractor();
176      funLibInjectorExtractor.Name = "FunctionLibraryInjector";
177      funLibInjectorExtractor.GetVariableInfo("Operator").ActualName = "FunctionLibraryInjector";
178      seq.AddSubOperator(funLibInjectorExtractor);
179
180      init.OperatorGraph.AddOperator(seq);
181      init.OperatorGraph.InitialOperator = seq;
182      return init;
[1287]183    }
[1230]184
[2335]185    protected virtual IOperator CreateRandomInjector() {
186      RandomInjector randomInjector = new RandomInjector();
187      randomInjector.Name = "Random Injector";
188      return randomInjector;
[2331]189    }
[1230]190
[2335]191    protected virtual VariableInjector CreateGlobalInjector() {
[1230]192      VariableInjector injector = new VariableInjector();
193      injector.Name = "Global Injector";
194      injector.AddVariable(new HeuristicLab.Core.Variable("Generations", new IntData(0)));
[2335]195      injector.AddVariable(new HeuristicLab.Core.Variable("MaxGenerations", new IntData()));
[1287]196      injector.AddVariable(new HeuristicLab.Core.Variable("MutationRate", new DoubleData()));
197      injector.AddVariable(new HeuristicLab.Core.Variable("PopulationSize", new IntData()));
198      injector.AddVariable(new HeuristicLab.Core.Variable("Elites", new IntData()));
[1230]199      injector.AddVariable(new HeuristicLab.Core.Variable("Maximization", new BoolData(false)));
[1287]200      injector.AddVariable(new HeuristicLab.Core.Variable("MaxTreeHeight", new IntData()));
201      injector.AddVariable(new HeuristicLab.Core.Variable("MaxTreeSize", new IntData()));
[2335]202      injector.AddVariable(new HeuristicLab.Core.Variable("MinTreeSize", new IntData()));
[1230]203      injector.AddVariable(new HeuristicLab.Core.Variable("EvaluatedSolutions", new IntData(0)));
204      injector.AddVariable(new HeuristicLab.Core.Variable("TotalEvaluatedNodes", new DoubleData(0)));
[1287]205      injector.AddVariable(new HeuristicLab.Core.Variable("Parents", new IntData()));
[1230]206      return injector;
207    }
208
209
[2335]210    protected virtual IOperator CreateProblemInjector() {
211      return new EmptyOperator();
212    }
213
214    protected virtual IOperator CreateFunctionLibraryInjector() {
215      return new EmptyOperator();
216    }
217    #endregion
218
219    #region population init
220    private IOperator CreateInitialPopulationGenerator() {
221      CombinedOperator initPopulation = new CombinedOperator();
222      initPopulation.Name = "Init population";
[1230]223      SequentialProcessor seq = new SequentialProcessor();
224      SubScopesCreater subScopesCreater = new SubScopesCreater();
225      subScopesCreater.GetVariableInfo("SubScopes").ActualName = "PopulationSize";
226      UniformSequentialSubScopesProcessor subScopesProc = new UniformSequentialSubScopesProcessor();
227      SequentialProcessor individualSeq = new SequentialProcessor();
228      OperatorExtractor treeCreater = new OperatorExtractor();
229      treeCreater.Name = "Tree generator (extr.)";
[2335]230      treeCreater.GetVariableInfo("Operator").ActualName = "Solution generator";
231
[1230]232      OperatorExtractor evaluator = new OperatorExtractor();
233      evaluator.Name = "Evaluator (extr.)";
234      evaluator.GetVariableInfo("Operator").ActualName = "Evaluator";
235      Counter evalCounter = new Counter();
236      evalCounter.GetVariableInfo("Value").ActualName = "EvaluatedSolutions";
237      Sorter sorter = new Sorter();
238      sorter.GetVariableInfo("Descending").ActualName = "Maximization";
239      sorter.GetVariableInfo("Value").ActualName = "Quality";
240
241      seq.AddSubOperator(subScopesCreater);
242      seq.AddSubOperator(subScopesProc);
243      seq.AddSubOperator(sorter);
244
245      subScopesProc.AddSubOperator(individualSeq);
246      individualSeq.AddSubOperator(treeCreater);
247      individualSeq.AddSubOperator(evaluator);
248      individualSeq.AddSubOperator(evalCounter);
249
[2335]250      initPopulation.OperatorGraph.AddOperator(seq);
251      initPopulation.OperatorGraph.InitialOperator = seq;
252      return initPopulation;
[1230]253    }
254
[2335]255    protected virtual IOperator CreateRandomSolutionGenerator() {
256      ProbabilisticTreeCreator treeCreator = new ProbabilisticTreeCreator();
257      treeCreator.Name = "Solution generator";
258      return treeCreator;
259    }
260
261    protected virtual IOperator CreateInitialPopulationEvaluator() {
262      return new EmptyOperator();
263    }
264    #endregion
265
266    #region mainloop
267    protected virtual IOperator CreateMainLoop() {
[1230]268      CombinedOperator main = new CombinedOperator();
[2335]269      main.Name = "Main";
[1230]270      SequentialProcessor seq = new SequentialProcessor();
271      IOperator childCreater = CreateChildCreater();
272      IOperator replacement = CreateReplacement();
273
274      BestAverageWorstQualityCalculator qualityCalculator = new BestAverageWorstQualityCalculator();
[1287]275      IOperator loggingOperator = CreateLoggingOperator();
[1230]276      Counter counter = new Counter();
277      counter.GetVariableInfo("Value").ActualName = "Generations";
278
[2335]279      OperatorExtractor terminationCriterionExtractor = new OperatorExtractor();
280      terminationCriterionExtractor.Name = "TerminationCondition (extr.)";
281      terminationCriterionExtractor.GetVariableInfo("Operator").ActualName = "TerminationCondition";
282
283      ConditionalBranch loop = new ConditionalBranch();
284      loop.Name = "Main loop";
285      loop.GetVariableInfo("Condition").ActualName = "TerminationCriterion";
286      loop.AddSubOperator(new EmptyOperator());
287      loop.AddSubOperator(seq);
288
[2683]289      seq.AddSubOperator(CreateGenerationStepHook());
[1230]290      seq.AddSubOperator(qualityCalculator);
[1287]291      seq.AddSubOperator(loggingOperator);
[1230]292      seq.AddSubOperator(counter);
[2683]293      seq.AddSubOperator(childCreater);
294      seq.AddSubOperator(replacement);
[2335]295      seq.AddSubOperator(terminationCriterionExtractor);
296      seq.AddSubOperator(loop);
[1230]297
298      main.OperatorGraph.AddOperator(seq);
299      main.OperatorGraph.InitialOperator = seq;
300      return main;
301    }
302
[2335]303    protected virtual IOperator CreateChildCreater() {
[1230]304      CombinedOperator childCreater = new CombinedOperator();
305      childCreater.Name = "Create children";
306      SequentialProcessor seq = new SequentialProcessor();
307      OperatorExtractor selector = new OperatorExtractor();
308      selector.Name = "Selector (extr.)";
309      selector.GetVariableInfo("Operator").ActualName = "Selector";
[1335]310
[1230]311      SequentialSubScopesProcessor seqScopesProc = new SequentialSubScopesProcessor();
312      EmptyOperator emptyOpt = new EmptyOperator();
313      SequentialProcessor selectedProc = new SequentialProcessor();
[1335]314      ChildrenInitializer childInitializer = new ChildrenInitializer();
315      ((IntData)childInitializer.GetVariable("ParentsPerChild").Value).Data = 2;
316
[1230]317      OperatorExtractor crossover = new OperatorExtractor();
318      crossover.Name = "Crossover (extr.)";
319      crossover.GetVariableInfo("Operator").ActualName = "Crossover";
320      UniformSequentialSubScopesProcessor individualProc = new UniformSequentialSubScopesProcessor();
321      SequentialProcessor individualSeqProc = new SequentialProcessor();
322      StochasticBranch cond = new StochasticBranch();
323      cond.GetVariableInfo("Probability").ActualName = "MutationRate";
324      OperatorExtractor manipulator = new OperatorExtractor();
325      manipulator.Name = "Manipulator (extr.)";
326      manipulator.GetVariableInfo("Operator").ActualName = "Manipulator";
327      OperatorExtractor evaluator = new OperatorExtractor();
328      evaluator.Name = "Evaluator (extr.)";
329      evaluator.GetVariableInfo("Operator").ActualName = "Evaluator";
330      Counter evalCounter = new Counter();
331      evalCounter.GetVariableInfo("Value").ActualName = "EvaluatedSolutions";
[1335]332      SubScopesRemover parentRefRemover = new SubScopesRemover();
[1230]333
334      Sorter sorter = new Sorter();
335      sorter.GetVariableInfo("Descending").ActualName = "Maximization";
336      sorter.GetVariableInfo("Value").ActualName = "Quality";
337
338
339      seq.AddSubOperator(selector);
340      seq.AddSubOperator(seqScopesProc);
341      seqScopesProc.AddSubOperator(emptyOpt);
342      seqScopesProc.AddSubOperator(selectedProc);
[1335]343      selectedProc.AddSubOperator(childInitializer);
[1230]344      selectedProc.AddSubOperator(individualProc);
345      individualProc.AddSubOperator(individualSeqProc);
[1335]346      individualSeqProc.AddSubOperator(crossover);
[1230]347      individualSeqProc.AddSubOperator(cond);
348      cond.AddSubOperator(manipulator);
349      individualSeqProc.AddSubOperator(evaluator);
350      individualSeqProc.AddSubOperator(evalCounter);
[1335]351      individualSeqProc.AddSubOperator(parentRefRemover);
[1230]352      selectedProc.AddSubOperator(sorter);
353
354      childCreater.OperatorGraph.AddOperator(seq);
355      childCreater.OperatorGraph.InitialOperator = seq;
356      return childCreater;
357    }
358
[2335]359    protected virtual IOperator CreateReplacement() {
360      CombinedOperator replacement = new CombinedOperator();
361      replacement.Name = "Replacement";
362      SequentialProcessor seq = new SequentialProcessor();
363      SequentialSubScopesProcessor seqScopeProc = new SequentialSubScopesProcessor();
364      SequentialProcessor selectedProc = new SequentialProcessor();
365      LeftSelector leftSelector = new LeftSelector();
366      leftSelector.GetVariableInfo("Selected").ActualName = "Elites";
367      RightReducer rightReducer = new RightReducer();
[2270]368
[2335]369      SequentialProcessor remainingProc = new SequentialProcessor();
370      RightSelector rightSelector = new RightSelector();
371      rightSelector.GetVariableInfo("Selected").ActualName = "Elites";
372      LeftReducer leftReducer = new LeftReducer();
373      MergingReducer mergingReducer = new MergingReducer();
374      Sorter sorter = new Sorter();
375      sorter.GetVariableInfo("Descending").ActualName = "Maximization";
376      sorter.GetVariableInfo("Value").ActualName = "Quality";
[2041]377
[2335]378      seq.AddSubOperator(seqScopeProc);
379      seqScopeProc.AddSubOperator(selectedProc);
380      selectedProc.AddSubOperator(leftSelector);
381      selectedProc.AddSubOperator(rightReducer);
[2328]382
[2335]383      seqScopeProc.AddSubOperator(remainingProc);
384      remainingProc.AddSubOperator(rightSelector);
385      remainingProc.AddSubOperator(leftReducer);
386      seq.AddSubOperator(mergingReducer);
387      seq.AddSubOperator(sorter);
388      replacement.OperatorGraph.AddOperator(seq);
389      replacement.OperatorGraph.InitialOperator = seq;
390      return replacement;
[1906]391    }
392
[2335]393    protected virtual IOperator CreateLoggingOperator() {
394      CombinedOperator loggingOperator = new CombinedOperator();
395      loggingOperator.Name = "Logging";
396      SequentialProcessor seq = new SequentialProcessor();
397
398      DataCollector collector = new DataCollector();
399      ItemList<StringData> names = collector.GetVariable("VariableNames").GetValue<ItemList<StringData>>();
400      names.Add(new StringData("BestQuality"));
401      names.Add(new StringData("AverageQuality"));
402      names.Add(new StringData("WorstQuality"));
403      LinechartInjector lineChartInjector = new LinechartInjector();
404      lineChartInjector.GetVariableInfo("Linechart").ActualName = "Quality Linechart";
405      lineChartInjector.GetVariable("NumberOfLines").GetValue<IntData>().Data = 3;
406      QualityLogger qualityLogger = new QualityLogger();
407
408      seq.AddSubOperator(collector);
409      seq.AddSubOperator(lineChartInjector);
410      seq.AddSubOperator(qualityLogger);
411
412      loggingOperator.OperatorGraph.AddOperator(seq);
413      loggingOperator.OperatorGraph.InitialOperator = seq;
414      return loggingOperator;
415    }
416
417    protected virtual IOperator CreateGenerationStepHook() {
418      return new EmptyOperator();
419    }
420
421    protected virtual IOperator CreateTerminationCondition() {
422      CombinedOperator terminationCriterion = new CombinedOperator();
423      terminationCriterion.Name = "TerminationCondition";
424      SequentialProcessor seq = new SequentialProcessor();
425      GreaterThanComparator comparator = new GreaterThanComparator();
426      comparator.GetVariableInfo("LeftSide").ActualName = "Generations";
427      comparator.GetVariableInfo("RightSide").ActualName = "MaxGenerations";
428      comparator.GetVariableInfo("Result").ActualName = "TerminationCriterion";
429
430      seq.AddSubOperator(comparator);
431      terminationCriterion.OperatorGraph.AddOperator(seq);
432      terminationCriterion.OperatorGraph.InitialOperator = seq;
433      return terminationCriterion;
434    }
435
436    protected virtual IOperator CreateEvaluationOperator() {
437      return new EmptyOperator();
438    }
439
440    protected virtual IOperator CreateManipulationOperator() {
441      ChangeNodeTypeManipulation manipulator = new ChangeNodeTypeManipulation();
442      manipulator.Name = "Manipulator";
443      return manipulator;
444    }
445
446    protected virtual IOperator CreateCrossoverOperator() {
447      StandardCrossOver crossover = new StandardCrossOver();
448      crossover.Name = "Crossover";
449      return crossover;
450    }
451
452    protected virtual IOperator CreateSelectionOperator() {
453      TournamentSelector selector = new TournamentSelector();
454      selector.GetVariableInfo("Selected").ActualName = "Parents";
455      selector.GetVariable("GroupSize").Value = new IntData(7);
456      selector.Name = "Selector";
457      return selector;
458    }
459
460    #endregion
461
462    protected virtual IOperator CreatePostProcessingOperator() {
463      return new EmptyOperator();
464    }
465
466    protected virtual IOperator GetVariableInjector() {
467      CombinedOperator init = (CombinedOperator)GetInitializationOperator();
468      return init.OperatorGraph.InitialOperator.SubOperators[1];
[1230]469    }
470
[2335]471    protected virtual IOperator GetRandomInjector() {
472      CombinedOperator init = (CombinedOperator)GetInitializationOperator();
473      return init.OperatorGraph.InitialOperator.SubOperators[0];
[1287]474    }
475
[2335]476    protected virtual IOperator GetInitializationOperator() {
[2377]477      CombinedOperator algo = (CombinedOperator)Engine.OperatorGraph.InitialOperator;
478      return algo.OperatorGraph.InitialOperator.SubOperators[0];
[2335]479    }
480
[1230]481    #region Persistence Methods
[2377]482    public override object Clone(IDictionary<Guid, object> clonedObjects) {
483      AlgorithmBase clone = (AlgorithmBase)base.Clone(clonedObjects);
484      clone.engine = (IEngine)Auxiliary.Clone(Engine, clonedObjects);
485      return clone;
486    }
487
[1230]488    public override XmlNode GetXmlNode(string name, XmlDocument document, IDictionary<Guid, IStorable> persistedObjects) {
489      XmlNode node = base.GetXmlNode(name, document, persistedObjects);
490      node.AppendChild(PersistenceManager.Persist("Engine", Engine, document, persistedObjects));
491      return node;
492    }
493    public override void Populate(XmlNode node, IDictionary<Guid, IStorable> restoredObjects) {
494      base.Populate(node, restoredObjects);
[2377]495      engine = (IEngine)PersistenceManager.Restore(node.SelectSingleNode("Engine"), restoredObjects);
[1230]496    }
497    #endregion
[2385]498
499
500    public static IOperator CombineTerminationCriterions(IOperator criterion1, IOperator criterion2) {
501      ConditionalBranch branch = new ConditionalBranch();
502      branch.GetVariableInfo("Condition").ActualName = "TerminationCriterion";
503      branch.AddSubOperator(new EmptyOperator());
504      branch.AddSubOperator(criterion2);
505
506      SequentialProcessor seq = new SequentialProcessor();
507      seq.AddSubOperator(criterion1);
508      seq.AddSubOperator(branch);
509
510      return seq;
511    }
[1230]512  }
513}
Note: See TracBrowser for help on using the repository browser.