718 | | Finally, we implement the {Problem} class. |
| 718 | Finally, we implement the {{{Problem}}} class. The {{{Problem}}} holds all necessary information of a lawn mower problem instance. It has multiple parameters which are set to instances of the classes that we implemented so far. |
| 719 | |
| 720 | The parameters for the problem are: |
| 721 | * LawnWidth: Width of the lawn (integer, default value: 8) |
| 722 | * LawnHeight: Height of the lawn (integer, default value: 8) |
| 723 | * MaxProgramLength: Maximal length of the lawn mower program represented as a symbolic expression tree in number of nodes (integer, default value: 13) |
| 724 | * MaxProgramDepth: Maximal depth of the lawn mower program represented as a symbolic expression tree (integer, default value: 1000 = no limit) |
| 725 | * Grammar: The grammar for lawn mower programs that specifies syntactically correct lawn mower programs (Grammar, default value: new Grammar()) |
| 726 | |
| 727 | These parameters are created in the constructor of the {{{Problem}}} class. The integer-valued parameters are created as {{{FixedValueParameters}}} to make sure that the contained IntValue instance cannot be replaced. The {{{Problem}}} class also provides properties for the parameters for convenience. |
| 728 | |
| 729 | In the {{{Problem}}} constructor we also instantiate our {{{Evaluator}}} for the lawn mower problem and a solution creator for symbolic expression trees (in this case the {{{RampedHalfAndHalfTreeCreator}}}). The solution creator and the {{{Evaluator}}} are necessary for the constructor of the base class ({{{SingleObjectiveHeuristicOptimizationProblem<Evaluator,ISymbolicExpressionTreeCreator>}}}). |
| 730 | |
| 731 | At the end of the {{{Problem}}} constructor we set the {{{Maximization}}} property to true (we want to maximize the mowed cells). Finally, we initialize the operators list for algorithms with {{{InitializeOperators()}}}. |
| 732 | {{{ |
| 733 | #!csharp |
| 734 | // default constructor for the problem |
| 735 | // also creates the fitness evaluation operator (Evaluator), |
| 736 | // and the tree creation operator (RampedHalfAndHalfTreeCreator) |
| 737 | public Problem() |
| 738 | : base(new Evaluator(), new RampedHalfAndHalfTreeCreator()) { |
| 739 | Parameters.Add( |
| 740 | new FixedValueParameter<IntValue>( |
| 741 | LawnWidthParameterName, |
| 742 | "Width of the lawn.", |
| 743 | new IntValue(8))); |
| 744 | Parameters.Add( |
| 745 | new FixedValueParameter<IntValue>( |
| 746 | LawnLengthParameterName, |
| 747 | "Length of the lawn.", |
| 748 | new IntValue(8))); |
| 749 | Parameters.Add( |
| 750 | new FixedValueParameter<IntValue>( |
| 751 | MaxLawnMowerProgramDepthParameterName, |
| 752 | "Maximal depth of the lawn mower program.", |
| 753 | new IntValue(13))); |
| 754 | Parameters.Add( |
| 755 | new FixedValueParameter<IntValue>( |
| 756 | MaxLawnMowerProgramLengthParameterName, |
| 757 | "Maximal length of the lawn mower program.", |
| 758 | new IntValue(1000))); |
| 759 | Parameters.Add( |
| 760 | new ValueParameter<Grammar>( |
| 761 | LawnMowerGrammarParameterName, |
| 762 | "Grammar for the lawn mower program.", |
| 763 | new Grammar())); |
| 764 | Maximization.Value = true; |
| 765 | InitializeOperators(); |
| 766 | } |
| 767 | }}} |
| 768 | |
| 769 | |
| 770 | {{{InitializeOperator}}} must create the operators that algorithms can use to solve the problem and add them to the {{{Operators}}} list. Our lawn mower problem uses the symbolic expression tree encoding. Thus we can add all operators for symbolic expression trees. Usually we also want to add some analyzers to generate results but this is optional. In this case we add a tree-length analyzer, a symbol-frequency analyzer and a best solution analyzer. |
| 771 | {{{ |
| 772 | #!csharp |
| 773 | // ... |
| 774 | Operators.AddRange( |
| 775 | ApplicationManager.Manager.GetInstances<ISymbolicExpressionTreeOperator>()); |
| 776 | Operators.Add(new MinAverageMaxSymbolicExpressionTreeLengthAnalyzer()); |
| 777 | Operators.Add(new SymbolicExpressionSymbolFrequencyAnalyzer()); |
| 778 | Operators.Add(new BestSolutionAnalyzer()); |
| 779 | }}} |
| 780 | |
| 781 | Next the operators must be configured. The actual parameter names of the operators must match the parameter names of the problem to guarantee that the operator will find the necessary parameter values when executed. |
| 782 | This operator parameter matching is at the core of all remaining code. |
| 783 | |
| 784 | In {{{ParameterizeOperators()}}} we iterate over all kinds of interfaces for symbolic expression tree operators and set the actual names of parameters defined in these interfaces to the names of the parameters supplied by the lawn mower problem. |
| 785 | {{{ |
| 786 | #!csharp |
| 787 | private void ParameterizeOperators() { |
| 788 | var operators = Parameters |
| 789 | .OfType<IValueParameter>() |
| 790 | .Select(p => p.Value) |
| 791 | .OfType<IOperator>() |
| 792 | .Union(Operators); |
| 793 | foreach (var o in operators.OfType<ISymbolicExpressionTreeGrammarBasedOperator>()) { |
| 794 | o.SymbolicExpressionTreeGrammarParameter.ActualName = |
| 795 | LawnMowerGrammarParameterName; |
| 796 | } |
| 797 | foreach (var o in operators.OfType<ISymbolicExpressionTreeSizeConstraintOperator>()) { |
| 798 | o.MaximumSymbolicExpressionTreeDepthParameter.ActualName = |
| 799 | MaxLawnMowerProgramDepthParameterName; |
| 800 | o.MaximumSymbolicExpressionTreeLengthParameter.ActualName = |
| 801 | MaxLawnMowerProgramLengthParameterName; |
| 802 | } |
| 803 | foreach (var op in operators.OfType<Evaluator>()) { |
| 804 | op.LawnMowerProgramParameter.ActualName = |
| 805 | SolutionCreator.SymbolicExpressionTreeParameter.ActualName; |
| 806 | op.LawnLengthParameter.ActualName = LawnLengthParameterName; |
| 807 | op.LawnWidthParameter.ActualName = LawnWidthParameterName; |
| 808 | } |
| 809 | foreach (var op in operators.OfType<ISymbolicExpressionTreeCrossover>()) { |
| 810 | op.ParentsParameter.ActualName = |
| 811 | SolutionCreator.SymbolicExpressionTreeParameter.ActualName; |
| 812 | op.ChildParameter.ActualName = |
| 813 | SolutionCreator.SymbolicExpressionTreeParameter.ActualName; |
| 814 | } |
| 815 | foreach (var op in operators.OfType<ISymbolicExpressionTreeManipulator>()) { |
| 816 | op.SymbolicExpressionTreeParameter.ActualName = |
| 817 | SolutionCreator.SymbolicExpressionTreeParameter.ActualName; |
| 818 | } |
| 819 | foreach (var op in operators.OfType<ISymbolicExpressionTreeCreator>()) { |
| 820 | op.SymbolicExpressionTreeParameter.ActualName = |
| 821 | SolutionCreator.SymbolicExpressionTreeParameter.ActualName; |
| 822 | } |
| 823 | } |
| 824 | }}} |