- Timestamp:
- 04/19/10 23:34:34 (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/sources/HeuristicLab.Operators/3.3/StochasticMultiBranch.cs
r3418 r3425 20 20 #endregion 21 21 22 using System;23 using System.Collections.Generic;24 using System.Collections.ObjectModel;25 using System.Linq;26 using HeuristicLab.Collections;27 using HeuristicLab.Common;28 22 using HeuristicLab.Core; 29 using HeuristicLab.Data;30 using HeuristicLab.Parameters;31 23 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; 32 24 … … 37 29 [Item("StochasticMultiBranch", "Branch of operators that have different probabilities to get executed.")] 38 30 [StorableClass] 39 public class StochasticMultiBranch : MultiOperator<IOperator> { 40 public ValueLookupParameter<DoubleArray> ProbabilitiesParameter { 41 get { return (ValueLookupParameter<DoubleArray>)Parameters["Probabilities"]; } 42 } 43 public ILookupParameter<IRandom> RandomParameter { 44 get { return (ILookupParameter<IRandom>)Parameters["Random"]; } 45 } 46 47 public DoubleArray Probabilities { 48 get { return ProbabilitiesParameter.Value; } 49 set { ProbabilitiesParameter.Value = value; } 50 } 51 52 [StorableConstructor] 53 public StochasticMultiBranch(bool deserializing) : base() { } 54 /// <summary> 55 /// Initializes a new instance of <see cref="StochasticMultiBranch"/> with two parameters 56 /// (<c>Probabilities</c> and <c>Random</c>). 57 /// </summary> 58 public StochasticMultiBranch() 59 : base() { 60 Parameters.Add(new ValueLookupParameter<DoubleArray>("Probabilities", "The array of relative probabilities for each operator.", new DoubleArray())); 61 Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator to use.")); 62 Initialize(); 63 } 64 65 [StorableHook(HookType.AfterDeserialization)] 66 private void Initialize() { 67 Operators.ItemsAdded += new CollectionItemsChangedEventHandler<IndexedItem<IOperator>>(Operators_ItemsAdded); 68 Operators.ItemsRemoved += new CollectionItemsChangedEventHandler<IndexedItem<IOperator>>(Operators_ItemsRemoved); 69 Operators.ItemsMoved += new CollectionItemsChangedEventHandler<IndexedItem<IOperator>>(Operators_ItemsMoved); 70 } 71 72 void Operators_ItemsMoved(object sender, CollectionItemsChangedEventArgs<IndexedItem<IOperator>> e) { 73 if (Probabilities != null) { 74 DoubleArray oldProb = (DoubleArray)Probabilities.Clone(); 75 foreach (IndexedItem<IOperator> old in e.OldItems) { 76 foreach (IndexedItem<IOperator> item in e.Items) { 77 if (old.Value == item.Value && item.Index < Probabilities.Length && old.Index < oldProb.Length) 78 Probabilities[item.Index] = oldProb[old.Index]; 79 } 80 } 81 } 82 } 83 84 void Operators_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IndexedItem<IOperator>> e) { 85 if (Probabilities != null && Probabilities.Length > Operators.Count) { 86 List<double> probs = new List<double>(Probabilities.Cast<DoubleValue>().Select(x => x.Value)); 87 var sorted = e.Items.OrderByDescending(x => x.Index); 88 foreach (IndexedItem<IOperator> item in sorted) 89 if (probs.Count > item.Index) probs.RemoveAt(item.Index); 90 Probabilities = new DoubleArray(probs.ToArray()); 91 } 92 } 93 94 private void Operators_ItemsAdded(object sender, HeuristicLab.Collections.CollectionItemsChangedEventArgs<IndexedItem<IOperator>> e) { 95 if (Probabilities != null && Probabilities.Length < Operators.Count) { 96 DoubleArray probs = new DoubleArray(Operators.Count); 97 double avg = 0; 98 if (Probabilities.Length > 0) { 99 for (int i = 0; i < Probabilities.Length; i++) 100 avg += Probabilities[i]; 101 avg /= (double)Probabilities.Length; 102 } else avg = 1; 103 104 var added = e.Items.OrderBy(x => x.Index).ToList(); 105 int insertCount = 0; 106 for (int i = 0; i < Operators.Count; i++) { 107 if (insertCount < added.Count && i == added[insertCount].Index) { 108 probs[i] = avg; 109 insertCount++; 110 } else if (i - insertCount < Probabilities.Length) { 111 probs[i] = Probabilities[i - insertCount]; 112 } else probs[i] = avg; 113 } 114 Probabilities = probs; 115 } 116 } 117 118 /// <summary> 119 /// Applies an operator of the branches to the current scope with a 120 /// specific probability. 121 /// </summary> 122 /// <exception cref="InvalidOperationException">Thrown when the list of probabilites does not 123 /// match the number of operators.</exception> 124 /// <returns>A new operation with the operator that was selected followed by the current operator's successor.</returns> 125 public override IOperation Apply() { 126 IRandom random = RandomParameter.ActualValue; 127 DoubleArray probabilities = ProbabilitiesParameter.ActualValue; 128 if(probabilities.Length != Operators.Count) { 129 throw new InvalidOperationException("StochasticMultiBranch: The list of probabilities has to match the number of operators"); 130 } 131 double sum = 0; 132 for (int i = 0; i < Operators.Count; i++) { 133 sum += probabilities[i]; 134 } 135 double r = random.NextDouble() * sum; 136 sum = 0; 137 IOperator successor = null; 138 for(int i = 0; i < Operators.Count; i++) { 139 sum += probabilities[i]; 140 if(sum > r) { 141 successor = Operators[i]; 142 break; 143 } 144 } 145 OperationCollection next = new OperationCollection(base.Apply()); 146 if (successor != null) { 147 next.Insert(0, ExecutionContext.CreateOperation(successor)); 148 } 149 return next; 31 public class StochasticMultiBranch : StochasticMultiOperator<IOperator> { 32 protected override bool CreateChildOperation { 33 get { return false; } 150 34 } 151 35 }
Note: See TracChangeset
for help on using the changeset viewer.