Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 13780 was 3589, checked in by gkronber, 15 years ago

Fixed persistence of number of tickets for functions. #748 (FunctionLibraryView is empty)

File size: 10.9 KB
RevLine 
[645]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;
[2210]28using HeuristicLab.GP.Interfaces;
[2675]29using System.Linq;
[645]30
31namespace HeuristicLab.GP {
[2700]32  public abstract class Function : ItemBase, IFunction {
[2202]33    private List<List<IFunction>> allowedSubFunctions = new List<List<IFunction>>();
[645]34    private int minArity = -1;
35    private int maxArity = -1;
[2202]36    private double tickets = 1.0;
37    private IOperator initializer;
38    private IOperator manipulator;
39    private int minTreeHeight = -1;
40    private int minTreeSize = -1;
[645]41
[2700]42    private string name;
[2202]43    public virtual string Name {
[2700]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      }
[645]52    }
53
[2700]54    protected Function() {
55      name = this.GetType().Name;
56    }
57
[2202]58    public virtual string Description {
59      get { return "Description for this function is missing (TODO)"; }
[645]60    }
61
[2211]62    public int MinSubTrees {
[645]63      get {
64        return minArity;
65      }
[2700]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        }
[2202]74      }
[645]75    }
76
[2211]77    public int MaxSubTrees {
[645]78      get {
79        return maxArity;
80      }
[2700]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        }
[2202]99      }
[645]100    }
101
[2202]102
103    public int MinTreeSize {
104      get {
[2700]105        if (minTreeSize <= 0) {
106          RecalculateMinimalTreeSize();
107          FireChanged();
108        }
[2675]109        Debug.Assert(minTreeSize > 0);
[2202]110        return minTreeSize;
[645]111      }
112    }
113
[2202]114    public int MinTreeHeight {
115      get {
[2700]116        if (minTreeHeight <= 0) {
117          RecalculateMinimalTreeHeight();
118          FireChanged();
119        }
[2675]120        Debug.Assert(minTreeHeight > 0);
[2202]121        return minTreeHeight;
[645]122      }
123    }
124
[2202]125    public double Tickets {
126      get { return tickets; }
127      set {
128        if (value < 0.0) throw new ArgumentException("Number of tickets must be positive");
[2700]129        if (value != tickets) {
130          tickets = value;
131          FireChanged();
132        }
[645]133      }
134    }
135
[2202]136    public IOperator Initializer {
137      get { return initializer; }
[2700]138      set {
139        if (initializer != value) {
140          initializer = value;
141          FireChanged();
142        }
143      }
[645]144    }
145
[2202]146    public IOperator Manipulator {
147      get { return manipulator; }
[2700]148      set {
149        if (manipulator != value) {
150          manipulator = value;
151          FireChanged();
152        }
153      }
[645]154    }
155
[2202]156    public virtual IFunctionTree GetTreeNode() {
[2700]157      return new FunctionTree(this);
[645]158    }
159
[2202]160    public ICollection<IFunction> GetAllowedSubFunctions(int index) {
[2211]161      if (index < 0 || index > MaxSubTrees) throw new ArgumentException("Index outside of allowed range. index = " + index);
[2202]162      return allowedSubFunctions[index];
[645]163    }
164
[2202]165    public void AddAllowedSubFunction(IFunction function, int index) {
[2211]166      if (index < 0 || index > MaxSubTrees) throw new ArgumentException("Index outside of allowed range. index = " + index);
[2202]167      if (allowedSubFunctions[index] == null) {
168        allowedSubFunctions[index] = new List<IFunction>();
169      }
170      if (!allowedSubFunctions[index].Contains(function)) {
171        allowedSubFunctions[index].Add(function);
172      }
[2700]173      ResetCachedValues();
174      FireChanged();
[645]175    }
[2202]176    public void RemoveAllowedSubFunction(IFunction function, int index) {
[2211]177      if (index < 0 || index > MaxSubTrees) throw new ArgumentException("Index outside of allowed range. index = " + index);
[2700]178      if (allowedSubFunctions[index].Contains(function)) {
179        allowedSubFunctions[index].Remove(function);
180        ResetCachedValues();
181        FireChanged();
182      }
[645]183    }
184
[2700]185    private void ResetCachedValues() {
186      minTreeHeight = -1;
187      minTreeSize = -1;
188    }
189
[2202]190    public bool IsAllowedSubFunction(IFunction function, int index) {
191      return GetAllowedSubFunctions(index).Contains(function);
[645]192    }
193
[2202]194    private void RecalculateMinimalTreeSize() {
[2675]195      if (MinSubTrees == 0) minTreeSize = 1;
196      else {
[2700]197        minTreeSize = int.MaxValue; // prevent infinite recursion       
[2675]198        minTreeSize = 1 + (from slot in Enumerable.Range(0, MinSubTrees)
199                           let minForSlot = (from function in GetAllowedSubFunctions(slot)
200                                             where function != this
[2700]201                                             select function.MinTreeSize).DefaultIfEmpty(0).Min()
[2675]202                           select minForSlot).Sum();
[2202]203      }
[645]204    }
205
[2202]206    private void RecalculateMinimalTreeHeight() {
[2675]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
[2700]213                                               select function.MinTreeHeight).DefaultIfEmpty(0).Min()
[2675]214                             select minForSlot).Max();
[2202]215      }
[645]216    }
[2216]217
[2700]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
[2216]227    public override object Clone(IDictionary<Guid, object> clonedObjects) {
[2700]228      Function clone = (Function)base.Clone(clonedObjects);
[2729]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();
[2219]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;
[2216]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);
[3589]253      XmlAttribute ticketsAttr = document.CreateAttribute("Tickets");
254      ticketsAttr.Value = XmlConvert.ToString(Tickets);
[2216]255      node.Attributes.Append(minSubTreesAttr);
256      node.Attributes.Append(maxSubTreesAttr);
[3589]257      node.Attributes.Append(ticketsAttr);
[2729]258      if (initializer != null)
259        node.AppendChild(PersistenceManager.Persist("Initializer", initializer, document, persistedObjects));
260      if (manipulator != null)
261        node.AppendChild(PersistenceManager.Persist("Manipulator", manipulator, document, persistedObjects));
[2216]262      for (int i = 0; i < MaxSubTrees; i++) {
263        XmlNode slotNode = document.CreateElement("AllowedSubFunctions");
264        XmlAttribute slotAttr = document.CreateAttribute("Slot");
265        slotAttr.Value = XmlConvert.ToString(i);
266        slotNode.Attributes.Append(slotAttr);
267        node.AppendChild(slotNode);
268        foreach (IFunction f in GetAllowedSubFunctions(i)) {
269          slotNode.AppendChild(PersistenceManager.Persist(f, document, persistedObjects));
270        }
271      }
272      return node;
273    }
274
275    public override void Populate(XmlNode node, IDictionary<Guid, IStorable> restoredObjects) {
276      base.Populate(node, restoredObjects);
277      MinSubTrees = XmlConvert.ToInt32(node.Attributes["MinSubTrees"].Value);
278      MaxSubTrees = XmlConvert.ToInt32(node.Attributes["MaxSubTrees"].Value);
[3589]279      if (node.Attributes["Tickets"] != null) {
280        tickets = XmlConvert.ToInt32(node.Attributes["Tickets"].Value);
281      } else {
282        tickets = 1;
283      }
[2729]284      if (node.SelectSingleNode("Initializer") != null) {
285        initializer = (IOperator)PersistenceManager.Restore(node.SelectSingleNode("Initializer"), restoredObjects);
286      }
287      if (node.SelectSingleNode("Manipulator") != null) {
288        manipulator = (IOperator)PersistenceManager.Restore(node.SelectSingleNode("Manipulator"), restoredObjects);
289      }
290      foreach (var subFunctionsList in allowedSubFunctions) subFunctionsList.Clear();
[2216]291      foreach (XmlNode allowedSubFunctionsNode in node.SelectNodes("AllowedSubFunctions")) {
292        int slot = XmlConvert.ToInt32(allowedSubFunctionsNode.Attributes["Slot"].Value);
293        foreach (XmlNode fNode in allowedSubFunctionsNode.ChildNodes) {
294          AddAllowedSubFunction((IFunction)PersistenceManager.Restore(fNode, restoredObjects), slot);
295        }
296      }
297    }
[2700]298    #endregion
[645]299  }
300}
Note: See TracBrowser for help on using the repository browser.