Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Operators/3.3/StochasticMultiOperator.cs @ 3527

Last change on this file since 3527 was 3527, checked in by abeham, 15 years ago

Added an exception to indicate that multi crossover doesn't contain any crossovers (also for manipulators)
fixed text in StochasticMultiOperator
#893

File size: 6.1 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2010 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.Linq;
25using HeuristicLab.Collections;
26using HeuristicLab.Core;
27using HeuristicLab.Data;
28using HeuristicLab.Parameters;
29using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
30using HeuristicLab.PluginInfrastructure;
31
32namespace HeuristicLab.Operators {
33  /// <summary>
34  /// Base class for stochastic multi operators.
35  /// </summary>
36  [Item("StochasticMultiOperator<T>", "Base class for stochastic multi operators.")]
37  [StorableClass]
38  public abstract class StochasticMultiOperator<T> : MultiOperator<T> where T : class, IOperator {
39    /// <summary>
40    /// Should return true if the StochasticMultiOperator should create a new child operation with the selected successor
41    /// or if it should create a new operation. If you need to shield the parameters of the successor you should return true here.
42    /// </summary>
43    protected abstract bool CreateChildOperation { get; }
44
45    public ValueLookupParameter<DoubleArray> ProbabilitiesParameter {
46      get { return (ValueLookupParameter<DoubleArray>)Parameters["Probabilities"]; }
47    }
48    public ILookupParameter<IRandom> RandomParameter {
49      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
50    }
51
52    public DoubleArray Probabilities {
53      get { return ProbabilitiesParameter.Value; }
54      set { ProbabilitiesParameter.Value = value; }
55    }
56
57    [StorableConstructor]
58    protected StochasticMultiOperator(bool deserializing) : base(deserializing) { }
59    /// <summary>
60    /// Initializes a new instance of <see cref="StochasticMultiOperator"/> with two parameters
61    /// (<c>Probabilities</c> and <c>Random</c>).
62    /// </summary>
63    public StochasticMultiOperator()
64      : base() {
65      Parameters.Add(new ValueLookupParameter<DoubleArray>("Probabilities", "The array of relative probabilities for each operator.", new DoubleArray()));
66      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator to use."));
67    }
68
69    protected override void Operators_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IndexedItem<T>> e) {
70      base.Operators_ItemsRemoved(sender, e);
71      if (Probabilities != null && Probabilities.Length > Operators.Count) {
72        List<double> probs = new List<double>(Probabilities.Cast<double>());
73        var sorted = e.Items.OrderByDescending(x => x.Index);
74        foreach (IndexedItem<T> item in sorted)
75          if (probs.Count > item.Index) probs.RemoveAt(item.Index);
76        Probabilities = new DoubleArray(probs.ToArray());
77      }
78    }
79
80    protected override void Operators_ItemsAdded(object sender, HeuristicLab.Collections.CollectionItemsChangedEventArgs<IndexedItem<T>> e) {
81      base.Operators_ItemsAdded(sender, e);
82      if (Probabilities != null && Probabilities.Length < Operators.Count) {
83        DoubleArray probs = new DoubleArray(Operators.Count);
84        double avg = 0;
85        if (Probabilities.Length > 0) {
86          int zeros = 0;
87          for (int i = 0; i < Probabilities.Length; i++) {
88            if (Probabilities[i] == 0) zeros++;
89            else avg += Probabilities[i];
90          }
91          if (Probabilities.Length - zeros > 0)
92            avg /= (double)(Probabilities.Length - zeros);
93          else avg = 1;
94        } else avg = 1;
95
96        var added = e.Items.OrderBy(x => x.Index).ToList();
97        int insertCount = 0;
98        for (int i = 0; i < Operators.Count; i++) {
99          if (insertCount < added.Count && i == added[insertCount].Index) {
100            probs[i] = avg;
101            insertCount++;
102          } else if (i - insertCount < Probabilities.Length) {
103            probs[i] = Probabilities[i - insertCount];
104          } else probs[i] = avg;
105        }
106        Probabilities = probs;
107      }
108    }
109
110    /// <summary>
111    /// Applies an operator of the branches to the current scope with a
112    /// specific probability.
113    /// </summary>
114    /// <exception cref="InvalidOperationException">Thrown when the list of probabilites does not
115    /// match the number of operators.</exception>
116    /// <returns>A new operation with the operator that was selected followed by the current operator's successor.</returns>
117    public override IOperation Apply() {
118      IRandom random = RandomParameter.ActualValue;
119      DoubleArray probabilities = ProbabilitiesParameter.ActualValue;
120      if(probabilities.Length != Operators.Count) {
121        throw new InvalidOperationException(Name + ": The list of probabilities has to match the number of operators");
122      }
123      double sum = 0;
124      for (int i = 0; i < Operators.Count; i++) {
125        sum += probabilities[i];
126      }
127      double r = random.NextDouble() * sum;
128      sum = 0;
129      IOperator successor = null;
130      for(int i = 0; i < Operators.Count; i++) {
131        sum += probabilities[i];
132        if(sum > r) {
133          successor = Operators[i];
134          break;
135        }
136      }
137      OperationCollection next = new OperationCollection(base.Apply());
138      if (successor != null) {
139        if (CreateChildOperation)
140          next.Insert(0, ExecutionContext.CreateChildOperation(successor));
141        else next.Insert(0, ExecutionContext.CreateOperation(successor));
142      }
143      return next;
144    }
145  }
146}
Note: See TracBrowser for help on using the repository browser.