Free cookie consent management tool by TermsFeed Policy Generator

source: branches/3.2/sources/HeuristicLab.GP/3.3/BaseClasses/Function.cs @ 3580

Last change on this file since 3580 was 2729, checked in by gkronber, 14 years ago

Fixed problems in persistence and cloning of functions and function libraries. Added test-functionality to editor for function libraries. Fixed bugs in editor for function libraries. #748 (FunctionLibraryView is empty)

File size: 10.6 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 HeuristicLab.Core;
26using System.Xml;
27using System.Diagnostics;
28using HeuristicLab.GP.Interfaces;
29using System.Linq;
30
31namespace HeuristicLab.GP {
32  public abstract class Function : ItemBase, IFunction {
33    private List<List<IFunction>> allowedSubFunctions = new List<List<IFunction>>();
34    private int minArity = -1;
35    private int maxArity = -1;
36    private double tickets = 1.0;
37    private IOperator initializer;
38    private IOperator manipulator;
39    private int minTreeHeight = -1;
40    private int minTreeSize = -1;
41
42    private string name;
43    public virtual string Name {
44      get { return name; }
45      set {
46        if (string.IsNullOrEmpty(value)) throw new ArgumentException();
47        if (value != name) {
48          name = value;
49          FireChanged();
50        }
51      }
52    }
53
54    protected Function() {
55      name = this.GetType().Name;
56    }
57
58    public virtual string Description {
59      get { return "Description for this function is missing (TODO)"; }
60    }
61
62    public int MinSubTrees {
63      get {
64        return minArity;
65      }
66      protected internal set {
67        if (value < 0) throw new ArgumentException();
68        if (minArity != value) {
69          minArity = value;
70          while (minArity > allowedSubFunctions.Count) allowedSubFunctions.Add(new List<IFunction>());
71          ResetCachedValues();
72          FireChanged();
73        }
74      }
75    }
76
77    public int MaxSubTrees {
78      get {
79        return maxArity;
80      }
81      protected internal set {
82        if (value < 0) throw new ArgumentException();
83        if (value < minArity) throw new ArgumentException();
84        if (value != maxArity) {
85          maxArity = value;
86          while (allowedSubFunctions.Count > maxArity) allowedSubFunctions.RemoveAt(allowedSubFunctions.Count - 1);
87          while (maxArity > allowedSubFunctions.Count) {
88            if (allowedSubFunctions.Count > 0) {
89              // copy the list of allowed sub-functions from the previous slot
90              allowedSubFunctions.Add(new List<IFunction>(allowedSubFunctions[allowedSubFunctions.Count - 1]));
91            } else {
92              // add empty list
93              allowedSubFunctions.Add(new List<IFunction>());
94            }
95          }
96          ResetCachedValues();
97          FireChanged();
98        }
99      }
100    }
101
102
103    public int MinTreeSize {
104      get {
105        if (minTreeSize <= 0) {
106          RecalculateMinimalTreeSize();
107          FireChanged();
108        }
109        Debug.Assert(minTreeSize > 0);
110        return minTreeSize;
111      }
112    }
113
114    public int MinTreeHeight {
115      get {
116        if (minTreeHeight <= 0) {
117          RecalculateMinimalTreeHeight();
118          FireChanged();
119        }
120        Debug.Assert(minTreeHeight > 0);
121        return minTreeHeight;
122      }
123    }
124
125    public double Tickets {
126      get { return tickets; }
127      set {
128        if (value < 0.0) throw new ArgumentException("Number of tickets must be positive");
129        if (value != tickets) {
130          tickets = value;
131          FireChanged();
132        }
133      }
134    }
135
136    public IOperator Initializer {
137      get { return initializer; }
138      set {
139        if (initializer != value) {
140          initializer = value;
141          FireChanged();
142        }
143      }
144    }
145
146    public IOperator Manipulator {
147      get { return manipulator; }
148      set {
149        if (manipulator != value) {
150          manipulator = value;
151          FireChanged();
152        }
153      }
154    }
155
156    public virtual IFunctionTree GetTreeNode() {
157      return new FunctionTree(this);
158    }
159
160    public ICollection<IFunction> GetAllowedSubFunctions(int index) {
161      if (index < 0 || index > MaxSubTrees) throw new ArgumentException("Index outside of allowed range. index = " + index);
162      return allowedSubFunctions[index];
163    }
164
165    public void AddAllowedSubFunction(IFunction function, int index) {
166      if (index < 0 || index > MaxSubTrees) throw new ArgumentException("Index outside of allowed range. index = " + index);
167      if (allowedSubFunctions[index] == null) {
168        allowedSubFunctions[index] = new List<IFunction>();
169      }
170      if (!allowedSubFunctions[index].Contains(function)) {
171        allowedSubFunctions[index].Add(function);
172      }
173      ResetCachedValues();
174      FireChanged();
175    }
176    public void RemoveAllowedSubFunction(IFunction function, int index) {
177      if (index < 0 || index > MaxSubTrees) throw new ArgumentException("Index outside of allowed range. index = " + index);
178      if (allowedSubFunctions[index].Contains(function)) {
179        allowedSubFunctions[index].Remove(function);
180        ResetCachedValues();
181        FireChanged();
182      }
183    }
184
185    private void ResetCachedValues() {
186      minTreeHeight = -1;
187      minTreeSize = -1;
188    }
189
190    public bool IsAllowedSubFunction(IFunction function, int index) {
191      return GetAllowedSubFunctions(index).Contains(function);
192    }
193
194    private void RecalculateMinimalTreeSize() {
195      if (MinSubTrees == 0) minTreeSize = 1;
196      else {
197        minTreeSize = int.MaxValue; // prevent infinite recursion       
198        minTreeSize = 1 + (from slot in Enumerable.Range(0, MinSubTrees)
199                           let minForSlot = (from function in GetAllowedSubFunctions(slot)
200                                             where function != this
201                                             select function.MinTreeSize).DefaultIfEmpty(0).Min()
202                           select minForSlot).Sum();
203      }
204    }
205
206    private void RecalculateMinimalTreeHeight() {
207      if (MinSubTrees == 0) minTreeHeight = 1;
208      else {
209        minTreeHeight = int.MaxValue;
210        minTreeHeight = 1 + (from slot in Enumerable.Range(0, MinSubTrees)
211                             let minForSlot = (from function in GetAllowedSubFunctions(slot)
212                                               where function != this
213                                               select function.MinTreeHeight).DefaultIfEmpty(0).Min()
214                             select minForSlot).Max();
215      }
216    }
217
218    public override IView CreateView() {
219      return new FunctionView(this);
220    }
221
222    public override string ToString() {
223      return name;
224    }
225
226    #region persistence
227    public override object Clone(IDictionary<Guid, object> clonedObjects) {
228      Function clone = (Function)base.Clone(clonedObjects);
229      if (initializer != null) clone.initializer = (IOperator)Auxiliary.Clone(initializer, clonedObjects);
230      else clone.initializer = null;
231      if (manipulator != null) clone.manipulator = (IOperator)Auxiliary.Clone(manipulator, clonedObjects);
232      else clone.manipulator = null;
233      clone.MaxSubTrees = maxArity;
234      clone.MinSubTrees = minArity;
235      clone.Tickets = tickets;
236      clone.allowedSubFunctions.Clear();
237      for (int i = 0; i < MaxSubTrees; i++) {
238        var allowedSubFunctionsForSlot = new List<IFunction>();
239        foreach (IFunction f in GetAllowedSubFunctions(i)) {
240          allowedSubFunctionsForSlot.Add((IFunction)Auxiliary.Clone(f, clonedObjects));
241        }
242        clone.allowedSubFunctions.Add(allowedSubFunctionsForSlot);
243      }
244      return clone;
245    }
246
247    public override XmlNode GetXmlNode(string name, XmlDocument document, IDictionary<Guid, IStorable> persistedObjects) {
248      XmlNode node = base.GetXmlNode(name, document, persistedObjects);
249      XmlAttribute minSubTreesAttr = document.CreateAttribute("MinSubTrees");
250      minSubTreesAttr.Value = XmlConvert.ToString(MinSubTrees);
251      XmlAttribute maxSubTreesAttr = document.CreateAttribute("MaxSubTrees");
252      maxSubTreesAttr.Value = XmlConvert.ToString(MaxSubTrees);
253      node.Attributes.Append(minSubTreesAttr);
254      node.Attributes.Append(maxSubTreesAttr);
255      if (initializer != null)
256        node.AppendChild(PersistenceManager.Persist("Initializer", initializer, document, persistedObjects));
257      if (manipulator != null)
258        node.AppendChild(PersistenceManager.Persist("Manipulator", manipulator, document, persistedObjects));
259      for (int i = 0; i < MaxSubTrees; i++) {
260        XmlNode slotNode = document.CreateElement("AllowedSubFunctions");
261        XmlAttribute slotAttr = document.CreateAttribute("Slot");
262        slotAttr.Value = XmlConvert.ToString(i);
263        slotNode.Attributes.Append(slotAttr);
264        node.AppendChild(slotNode);
265        foreach (IFunction f in GetAllowedSubFunctions(i)) {
266          slotNode.AppendChild(PersistenceManager.Persist(f, document, persistedObjects));
267        }
268      }
269      return node;
270    }
271
272    public override void Populate(XmlNode node, IDictionary<Guid, IStorable> restoredObjects) {
273      base.Populate(node, restoredObjects);
274      MinSubTrees = XmlConvert.ToInt32(node.Attributes["MinSubTrees"].Value);
275      MaxSubTrees = XmlConvert.ToInt32(node.Attributes["MaxSubTrees"].Value);
276      if (node.SelectSingleNode("Initializer") != null) {
277        initializer = (IOperator)PersistenceManager.Restore(node.SelectSingleNode("Initializer"), restoredObjects);
278      }
279      if (node.SelectSingleNode("Manipulator") != null) {
280        manipulator = (IOperator)PersistenceManager.Restore(node.SelectSingleNode("Manipulator"), restoredObjects);
281      }
282      foreach (var subFunctionsList in allowedSubFunctions) subFunctionsList.Clear();
283      foreach (XmlNode allowedSubFunctionsNode in node.SelectNodes("AllowedSubFunctions")) {
284        int slot = XmlConvert.ToInt32(allowedSubFunctionsNode.Attributes["Slot"].Value);
285        foreach (XmlNode fNode in allowedSubFunctionsNode.ChildNodes) {
286          AddAllowedSubFunction((IFunction)PersistenceManager.Restore(fNode, restoredObjects), slot);
287        }
288      }
289    }
290    #endregion
291  }
292}
Note: See TracBrowser for help on using the repository browser.