Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.SGA/3.3/SGA.cs @ 2577

Last change on this file since 2577 was 2526, checked in by swagner, 15 years ago

Refactored cloning (#806)

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