- Timestamp:
- 05/06/10 19:06:26 (15 years ago)
- Location:
- trunk/sources/HeuristicLab.Algorithms.ParticleSwarmOptimization/3.3
- Files:
-
- 2 added
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/sources/HeuristicLab.Algorithms.ParticleSwarmOptimization/3.3/HeuristicLab.Algorithms.ParticleSwarmOptimization-3.3.csproj
r3415 r3682 81 81 <ItemGroup> 82 82 <Compile Include="HeuristicLabAlgorithmsParticleSwarmOptimizationPlugin.cs" /> 83 <Compile Include="IRealVectorEncoder.cs" />84 83 <Compile Include="ParticleSwarmOptimization.cs" /> 85 84 <Compile Include="ParticleSwarmOptimizationMainLoop.cs" /> 86 85 <Compile Include="PermutationToRealVectorEncoder.cs" /> 87 86 <Compile Include="Properties\AssemblyInfo.cs" /> 88 <Compile Include="RealVectorToRealVectorEncoder.cs" /> 87 <Compile Include="ParticleUpdater.cs" /> 88 <Compile Include="SwarmUpdater.cs" /> 89 89 </ItemGroup> 90 90 <ItemGroup> … … 94 94 </ItemGroup> 95 95 <ItemGroup> 96 <ProjectReference Include="..\..\HeuristicLab.Analysis\3.3\HeuristicLab.Analysis-3.3.csproj"> 97 <Project>{887425B4-4348-49ED-A457-B7D2C26DDBF9}</Project> 98 <Name>HeuristicLab.Analysis-3.3</Name> 99 </ProjectReference> 96 100 <ProjectReference Include="..\..\HeuristicLab.Collections\3.3\HeuristicLab.Collections-3.3.csproj"> 97 101 <Project>{958B43BC-CC5C-4FA2-8628-2B3B01D890B6}</Project> -
trunk/sources/HeuristicLab.Algorithms.ParticleSwarmOptimization/3.3/ParticleSwarmOptimization.cs
r3415 r3682 34 34 using HeuristicLab.PluginInfrastructure; 35 35 using HeuristicLab.Random; 36 using HeuristicLab.Analysis; 36 37 37 38 namespace HeuristicLab.Algorithms.ParticleSwarmOptimization { … … 52 53 set { EncoderParameter.Value = value; } 53 54 } 55 public MultiAnalyzer Analyzer { 56 get { return AnalyzerParameter.Value; } 57 set { AnalyzerParameter.Value = value; } 58 } 54 59 #endregion 55 60 … … 69 74 private OptionalConstrainedValueParameter<IRealVectorEncoder> EncoderParameter { 70 75 get { return (OptionalConstrainedValueParameter<IRealVectorEncoder>)Parameters["Encoder"]; } 76 } 77 private ValueParameter<MultiAnalyzer> AnalyzerParameter { 78 get { return (ValueParameter<MultiAnalyzer>)Parameters["Analyzer"]; } 71 79 } 72 80 #endregion … … 78 86 get { return mainLoop; } 79 87 } 88 [StorableAttribute] 89 private Assigner bestLocalQualityInitalizer; // Check this ! 90 private Assigner BestLocalQualityInitalizer { 91 get { return bestLocalQualityInitalizer; } 92 } 93 94 private BestAverageWorstQualityAnalyzer qualityAnalyzer; 80 95 #endregion 81 96 … … 86 101 Parameters.Add(new ValueParameter<IntValue>("SwarmSize", "Size of the particle swarm.", new IntValue(1))); 87 102 Parameters.Add(new ValueParameter<IntValue>("MaxIterations", "Maximal number of iterations.", new IntValue(1000))); 88 Parameters.Add(new OptionalConstrainedValueParameter<IRealVectorEncoder>("Encoder", "The operator used to encode solutions as position vector.")); 89 //Parameters.Add(new ConstrainedValueParameter<IManipulator>("Mutator", "The operator used to mutate solutions.")); 103 Parameters.Add(new ConstrainedValueParameter<IRealVectorEncoder>("Encoder", "The operator used to encode solutions as position vector.")); 104 Parameters.Add(new ValueParameter<IntValue>("PositionLength", "Length of the position encoding.", new IntValue(0))); 105 Parameters.Add(new ValueParameter<MultiAnalyzer>("Analyzer", "The operator used to analyze each generation.", new MultiAnalyzer())); 90 106 RandomCreator randomCreator = new RandomCreator(); 91 107 SolutionsCreator solutionsCreator = new SolutionsCreator(); 92 108 UniformSubScopesProcessor uniformSubScopesProcessor = new UniformSubScopesProcessor(); 109 UniformSubScopesProcessor uniformSubScopesProcessor2 = new UniformSubScopesProcessor(); 93 110 VariableCreator variableCreator = new VariableCreator(); 94 variableCreator.CollectedValues.Add(new ValueParameter<RealVector>("Velocity", new RealVector())); 95 //solutionsCreator.SolutionCreatorParameter.ActualName = Problem.SolutionCreator.Name; 96 //mainLoop = new ParticleSwarmOptimizationMainLoop(); 97 OperatorGraph.InitialOperator = randomCreator; 111 VariableCreator localVariableCreator = new VariableCreator(); 112 Placeholder encoder = new Placeholder(); 113 UniformRandomRealVectorCreator velocityVectorCreator = new UniformRandomRealVectorCreator(); 114 bestLocalQualityInitalizer = new Assigner(); 115 Assigner bestLocalPositionInitalizer = new Assigner(); 116 Assigner bestGlobalPositionInitalizer = new Assigner(); 117 mainLoop = new ParticleSwarmOptimizationMainLoop(); 118 BestAverageWorstQualityCalculator bawCalculator = new BestAverageWorstQualityCalculator(); 119 Comparator comparator = new Comparator(); 120 ConditionalBranch branch = new ConditionalBranch(); 121 122 variableCreator.CollectedValues.Add(new ValueParameter<RealVector>("CurrentBestPosition", new RealVector())); 123 variableCreator.CollectedValues.Add(new ValueParameter<DoubleMatrix>("ZeroBounds", new DoubleMatrix(new double[,] { { 0, 0 } }))); 124 variableCreator.CollectedValues.Add(new ValueParameter<IntValue>("Length", new IntValue(2))); 125 126 localVariableCreator.CollectedValues.Add(new ValueParameter<DoubleValue>("BestQuality", new DoubleValue(0))); 127 localVariableCreator.CollectedValues.Add(new ValueParameter<RealVector>("BestPosition", new RealVector())); 98 128 99 129 randomCreator.RandomParameter.ActualName = "Random"; … … 102 132 randomCreator.SetSeedRandomlyParameter.ActualName = SetSeedRandomlyParameter.Name; 103 133 randomCreator.SetSeedRandomlyParameter.Value = null; 134 135 solutionsCreator.NumberOfSolutionsParameter.ActualName = SwarmSizeParameter.Name; 136 137 encoder.OperatorParameter.ActualName = "Encoder"; 138 139 velocityVectorCreator.BoundsParameter.ActualName = "ZeroBounds"; 140 velocityVectorCreator.RealVectorParameter.ActualName = "Velocity"; 141 142 bestLocalQualityInitalizer.LeftSideParameter.ActualName = "BestQuality"; // cloned value 143 bestLocalQualityInitalizer.RightSideParameter.ActualName = "Quality"; // FIXME!!! Should be mapped 144 145 bestLocalPositionInitalizer.LeftSideParameter.ActualName = "BestPosition"; 146 bestLocalPositionInitalizer.RightSideParameter.ActualName = "Position"; // FixMe 147 148 bestGlobalPositionInitalizer.LeftSideParameter.ActualName = "CurrentBestPosition"; 149 bestGlobalPositionInitalizer.RightSideParameter.ActualName = "BestPosition"; 150 151 bawCalculator.AverageQualityParameter.ActualName = "CurrentAverageBestQuality"; 152 bawCalculator.BestQualityParameter.ActualName = "CurrentBestBestQuality"; 153 bawCalculator.MaximizationParameter.ActualName = "Maximization"; // FIXME 154 bawCalculator.QualityParameter.ActualName = "Quality"; 155 bawCalculator.WorstQualityParameter.ActualName = "CurrentWorstBestQuality"; 156 157 comparator.Comparison = new Comparison(ComparisonType.Equal); 158 comparator.LeftSideParameter.ActualName = "Quality"; 159 comparator.ResultParameter.ActualName = "NewGlobalBest"; 160 comparator.RightSideParameter.ActualName = "CurrentBestBestQuality"; 161 162 branch.ConditionParameter.ActualName = "NewGlobalBest"; 163 branch.TrueBranch = bestGlobalPositionInitalizer; // copy position vector 164 165 mainLoop.MaximumGenerationsParameter.ActualName = MaxIterationsParameter.Name; 166 mainLoop.ResultsParameter.ActualName = "Results"; 167 mainLoop.AnalyzerParameter.ActualName = AnalyzerParameter.Name; 168 169 OperatorGraph.InitialOperator = randomCreator; 104 170 randomCreator.Successor = solutionsCreator; 105 106 solutionsCreator.NumberOfSolutionsParameter.ActualName = SwarmSizeParameter.Name;107 171 solutionsCreator.Successor = variableCreator; 108 172 variableCreator.Successor = uniformSubScopesProcessor; 109 110 111 //evaluator.Successor = mainLoop; 112 //mainLoop.EncoderParameter.ActualName = EncoderParameter.Name; 113 173 uniformSubScopesProcessor.Operator = encoder; 174 encoder.Successor = velocityVectorCreator; 175 velocityVectorCreator.Successor = localVariableCreator; 176 localVariableCreator.Successor = bestLocalQualityInitalizer; 177 bestLocalQualityInitalizer.Successor = bestLocalPositionInitalizer; 178 uniformSubScopesProcessor.Successor = bawCalculator; // mainLoop; 179 bawCalculator.Successor = uniformSubScopesProcessor2; 180 uniformSubScopesProcessor2.Operator = comparator; 181 comparator.Successor = branch; 182 uniformSubScopesProcessor2.Successor = mainLoop; 114 183 Initialize(); 115 184 } … … 117 186 [StorableHook(HookType.AfterDeserialization)] 118 187 private void Initialize() { 188 InitializeAnalyzers(); 189 UpdateAnalyzers(); 119 190 EncoderParameter.ValueChanged += new EventHandler(EncoderParameter_ValueChanged); 191 if (Problem != null) { 192 bestLocalQualityInitalizer.RightSideParameter.ActualName = Problem.Evaluator.QualityParameter.ActualName; 193 } 120 194 } 121 195 … … 135 209 #region Events 136 210 protected override void OnProblemChanged() { 137 //ParameterizeStochasticOperator(Problem.SolutionCreator);138 //ParameterizeStochasticOperator(Problem.Evaluator);139 //ParameterizeStochasticOperator(Problem.Visualizer);140 //foreach (IOperator op in Problem.Operators) ParameterizeStochasticOperator(op);141 //ParameterizeSolutionsCreator();142 //ParameterizeMainLoop();143 211 UpdateEncoders(); 144 //UpdateMutators(); 145 //Problem.Evaluator.QualityParameter.ActualNameChanged += new EventHandler(Evaluator_QualityParameter_ActualNameChanged); 212 UpdateAnalyzers(); 213 bestLocalQualityInitalizer.RightSideParameter.ActualName = Problem.Evaluator.QualityParameter.ActualName; 214 Problem.Evaluator.QualityParameter.ActualNameChanged += new EventHandler(Evaluator_QualityParameter_ActualNameChanged); 215 MainLoop.EvaluatorParameter.ActualName = Problem.EvaluatorParameter.Name; 146 216 base.OnProblemChanged(); 147 217 } 148 218 149 219 private void EncoderParameter_ValueChanged(object sender, EventArgs e) { 150 ((UniformSubScopesProcessor)((SolutionsCreator)((RandomCreator)OperatorGraph.InitialOperator).Successor).Successor).Operator = EncoderParameter.Value; 220 //IRealVectorEncoder old = (IRealVectorEncoder)((UniformSubScopesProcessor)((VariableCreator)((SolutionsCreator)((RandomCreator)OperatorGraph.InitialOperator).Successor).Successor).Successor).Operator; 221 //((UniformSubScopesProcessor)((VariableCreator)((SolutionsCreator)((RandomCreator)OperatorGraph.InitialOperator).Successor).Successor).Successor).Operator = EncoderParameter.Value; 222 //((SingleSuccessorOperator)EncoderParameter.Value).Successor = ((SingleSuccessorOperator)old).Successor; 151 223 } 152 224 #endregion 153 225 154 226 #region Helpers 227 private void Evaluator_QualityParameter_ActualNameChanged(object sender, EventArgs e) { 228 // 229 // 230 } 231 232 private void ParameterizeMainLoop() { 233 //GeneticAlgorithmMainLoop.QualityParameter.ActualName = Problem.Evaluator.QualityParameter.ActualName; 234 } 155 235 156 236 private void UpdateEncoders() { 157 237 IRealVectorEncoder oldEncoder = EncoderParameter.Value; 158 238 EncoderParameter.ValidValues.Clear(); 159 foreach (IRealVectorEncoder encoder in Problem.Operators.OfType<IRealVectorEncoder>().OrderBy(x => x.Name)) { 160 EncoderParameter.ValidValues.Add(encoder); 161 encoder.RealVectorParameter.ActualName = "Position"; 162 } 163 if (oldEncoder != null) { 164 IRealVectorEncoder encoder = EncoderParameter.ValidValues.FirstOrDefault(x => x.GetType() == oldEncoder.GetType()); 165 if (encoder != null) EncoderParameter.Value = encoder; 239 List<IRealVectorEncoder> encoders = Problem.Operators.OfType<IRealVectorEncoder>().OrderBy(x => x.Name).ToList<IRealVectorEncoder>(); 240 if (encoders.Count > 0) { // ToDo: Add wiring; else: use Position Vector directly --> name matching 241 foreach (IRealVectorEncoder encoder in Problem.Operators.OfType<IRealVectorEncoder>().OrderBy(x => x.Name)) { 242 EncoderParameter.ValidValues.Add(encoder); 243 ((ILookupParameter)encoder.RealVectorParameter).ActualName = "Position"; 244 } 245 if (oldEncoder != null) { 246 IRealVectorEncoder encoder = EncoderParameter.ValidValues.FirstOrDefault(x => x.GetType() == oldEncoder.GetType()); 247 if (encoder != null) EncoderParameter.Value = encoder; 248 } 249 } 250 } 251 252 private void InitializeAnalyzers() { 253 qualityAnalyzer = new BestAverageWorstQualityAnalyzer(); 254 ParameterizeAnalyzers(); 255 } 256 257 private void ParameterizeAnalyzers() { 258 qualityAnalyzer.ResultsParameter.ActualName = "Results"; 259 if (Problem != null) { 260 qualityAnalyzer.MaximizationParameter.ActualName = Problem.MaximizationParameter.Name; 261 qualityAnalyzer.QualityParameter.ActualName = Problem.Evaluator.QualityParameter.ActualName; 262 qualityAnalyzer.BestKnownQualityParameter.ActualName = Problem.BestKnownQualityParameter.Name; 263 } 264 } 265 266 private void UpdateAnalyzers() { 267 Analyzer.Operators.Clear(); 268 Analyzer.Operators.Add(qualityAnalyzer); 269 if (Problem != null) { 270 foreach (IAnalyzer analyzer in Problem.Operators.OfType<IAnalyzer>().OrderBy(x => x.Name)) 271 Analyzer.Operators.Add(analyzer); 166 272 } 167 273 } -
trunk/sources/HeuristicLab.Algorithms.ParticleSwarmOptimization/3.3/ParticleSwarmOptimizationMainLoop.cs
r3415 r3682 9 9 using HeuristicLab.Parameters; 10 10 using HeuristicLab.Data; 11 using HeuristicLab.Analysis; 12 using HeuristicLab.Optimization.Operators; 13 using HeuristicLab.Encodings.RealVectorEncoding; 11 14 12 15 namespace HeuristicLab.Algorithms.ParticleSwarmOptimization { … … 24 27 get { return (ValueLookupParameter<IOperator>)Parameters["Encoder"]; } 25 28 } 26 //public ValueLookupParameter<IOperator> EvaluatorParameter { 27 // get { return (ValueLookupParameter<IOperator>)Parameters["Evaluator"]; } 28 //} 29 public ValueLookupParameter<IOperator> DecoderParameter { 30 get { return (ValueLookupParameter<IOperator>)Parameters["Decoder"]; } 31 } 32 public ValueLookupParameter<BoolValue> MaximizationParameter { 33 get { return (ValueLookupParameter<BoolValue>)Parameters["Maximization"]; } 34 } 35 public ScopeTreeLookupParameter<DoubleValue> QualityParameter { 36 get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["Quality"]; } 37 } 38 public ValueLookupParameter<IntValue> MaximumGenerationsParameter { 39 get { return (ValueLookupParameter<IntValue>)Parameters["MaximumGenerations"]; } 40 } 41 public ValueLookupParameter<IOperator> EvaluatorParameter { 42 get { return (ValueLookupParameter<IOperator>)Parameters["Evaluator"]; } 43 } 44 public ValueLookupParameter<IOperator> AnalyzerParameter { 45 get { return (ValueLookupParameter<IOperator>)Parameters["Analyzer"]; } 46 } 29 47 #endregion 30 48 … … 40 58 Parameters.Add(new ValueLookupParameter<VariableCollection>("Results", "The variable collection where results should be stored.")); 41 59 Parameters.Add(new ValueLookupParameter<IOperator>("Encoder", "The encoding operator that maps a solution to a position vector.")); 42 //Parameters.Add(new ValueLookupParameter<IOperator>("Evaluator", "The operator used to evaluate solutions.")); 60 Parameters.Add(new ValueLookupParameter<IOperator>("Decoder", "The decoding operator that maps a position vector to a solution.")); 61 Parameters.Add(new ValueLookupParameter<BoolValue>("Maximization", "True if the problem is a maximization problem, otherwise false.")); 62 Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("Quality", "The value which represents the quality of a solution.")); 63 Parameters.Add(new ValueLookupParameter<IntValue>("MaximumGenerations", "The maximum number of generations which should be processed.")); 64 Parameters.Add(new ValueLookupParameter<IOperator>("Evaluator", "The operator used to evaluate solutions.")); 65 Parameters.Add(new ValueLookupParameter<IOperator>("Analyzer", "The operator used to analyze each generation.")); 43 66 #endregion 44 67 45 68 #region Create operators 46 69 VariableCreator variableCreator = new VariableCreator(); 47 //variableCreator.CollectedValues.Add(new ValueParameter<IntValue>("Generations", new IntValue(0))); 70 ResultsCollector resultsCollector1 = new ResultsCollector(); 71 IntCounter intCounter = new IntCounter(); 72 ConditionalBranch conditionalBranch = new ConditionalBranch(); 73 ParticleUpdater velocityUpdater = new ParticleUpdater(); 48 74 UniformSubScopesProcessor uniformSubScopesProcessor = new UniformSubScopesProcessor(); 49 Placeholder encoder = new Placeholder(); 75 UniformSubScopesProcessor uniformSubScopesProcessor2 = new UniformSubScopesProcessor(); 76 Placeholder encPlaceholder = new Placeholder(); 77 Placeholder decPlaceholder = new Placeholder(); 50 78 Placeholder evaluator = new Placeholder(); 79 Comparator comparator = new Comparator(); 80 SwarmUpdater swarmUpdater = new SwarmUpdater(); 81 Placeholder analyzer1 = new Placeholder(); 51 82 52 encoder.Name = "Encoder (placeholder)";53 encoder.OperatorParameter.ActualName = EncoderParameter.Name;83 analyzer1.Name = "Analyzer (placeholder)"; 84 analyzer1.OperatorParameter.ActualName = AnalyzerParameter.Name; 54 85 55 //evaluator.Name = "Evaluator (placeholder)"; 56 //evaluator.OperatorParameter.ActualName = EvaluatorParameter.Name; 86 variableCreator.CollectedValues.Add(new ValueParameter<IntValue>("Generations", new IntValue(1))); // Initial generation already built 87 88 resultsCollector1.CollectedValues.Add(new LookupParameter<IntValue>("Generations")); 89 resultsCollector1.ResultsParameter.ActualName = "Results"; 90 91 intCounter.Increment = new IntValue(1); 92 intCounter.ValueParameter.ActualName = "Generations"; 93 94 comparator.Comparison = new Comparison(ComparisonType.GreaterOrEqual); 95 comparator.LeftSideParameter.ActualName = "Generations"; 96 comparator.ResultParameter.ActualName = "Terminate"; 97 comparator.RightSideParameter.ActualName = MaximumGenerationsParameter.Name; 98 99 conditionalBranch.ConditionParameter.ActualName = "Terminate"; 100 101 velocityUpdater.BestGlobalParameter.ActualName = "CurrentBestPosition"; 102 velocityUpdater.BestLocalParameter.ActualName = "BestPosition"; 103 velocityUpdater.CurrentPositionParameter.ActualName = "Position"; 104 velocityUpdater.VelocityParameter.ActualName = "Velocity"; 105 106 encPlaceholder.OperatorParameter.ActualName = EncoderParameter.ActualName; 107 decPlaceholder.OperatorParameter.ActualName = DecoderParameter.ActualName; 108 109 evaluator.Name = "Evaluator (placeholder)"; 110 evaluator.OperatorParameter.ActualName = EvaluatorParameter.Name; 111 112 swarmUpdater.CurrentPositionParameter.ActualName = "Position"; 113 swarmUpdater.CurrentQualityParameter.ActualName = "Quality"; 114 swarmUpdater.BestGlobalParameter.ActualName = "CurrentBestPosition"; 115 swarmUpdater.BestLocalParameter.ActualName = "BestPosition"; 116 swarmUpdater.LocalBestQualityParameter.ActualName = "BestQuality"; 117 swarmUpdater.GlobalBestQualityParameter.ActualName = "CurrentBestBestQuality"; 118 57 119 #endregion 58 120 59 121 #region Create operator graph 60 122 OperatorGraph.InitialOperator = variableCreator; 61 variableCreator.Successor = uniformSubScopesProcessor; 62 uniformSubScopesProcessor.Operator = encoder; 63 //uniformSubScopesProcessor.Successor = evaluator; 123 variableCreator.Successor = comparator; 124 comparator.Successor = conditionalBranch; 125 conditionalBranch.FalseBranch = uniformSubScopesProcessor; 126 uniformSubScopesProcessor.Operator = velocityUpdater; 127 velocityUpdater.Successor = decPlaceholder; 128 uniformSubScopesProcessor.Successor = uniformSubScopesProcessor2; 129 uniformSubScopesProcessor2.Operator = evaluator; 130 evaluator.Successor = swarmUpdater; 131 swarmUpdater.Successor = intCounter; 132 intCounter.Successor = resultsCollector1; 133 resultsCollector1.Successor = comparator; //analyzer1; 134 //analyzer1.Successor = comparator; 64 135 #endregion 65 136 } -
trunk/sources/HeuristicLab.Algorithms.ParticleSwarmOptimization/3.3/PermutationToRealVectorEncoder.cs
r3376 r3682 11 11 using HeuristicLab.Encodings.RealVectorEncoding; 12 12 using HeuristicLab.Collections; 13 using HeuristicLab.Optimization; 13 14 14 15 namespace HeuristicLab.Algorithms.ParticleSwarmOptimization { 15 public class PermutationToRealVectorEncoder : SingleSuccessorOperator, IRealVectorEncoder , IPermutationManipulator{16 public class PermutationToRealVectorEncoder : SingleSuccessorOperator, IRealVectorEncoder { 16 17 17 public I LookupParameter<RealVector>RealVectorParameter {18 get { return (I LookupParameter<RealVector>)Parameters["RealVector"]; }18 public IParameter RealVectorParameter { 19 get { return (IParameter)Parameters["RealVector"]; } 19 20 } 20 21 … … 23 24 } 24 25 26 public ILookupParameter<IntValue> LengthParameter { 27 get { return (ILookupParameter<IntValue>)Parameters["Length"]; } 28 } 29 25 30 public PermutationToRealVectorEncoder() : base() { 26 31 Parameters.Add(new LookupParameter<Permutation>("Permutation", "The permutation to encode.")); 27 32 Parameters.Add(new LookupParameter<RealVector>("RealVector", "The resulting real vector.")); 33 Parameters.Add(new LookupParameter<IntValue>("Length", "Vector length.")); 28 34 } 29 35 … … 37 43 max = max - 1; 38 44 } 39 RealVectorParameter.ActualValue = realVector; 45 RealVectorParameter.ActualValue = realVector; 46 LengthParameter.ActualValue = new IntValue(realVector.Length); 40 47 return base.Apply(); 41 48 }
Note: See TracChangeset
for help on using the changeset viewer.