source: branches/HeuristicLab.Problems.BioBoost/HeuristicLab.Problems.BioBoost/3.3/Operators/Mutation/PlantBasedUtilizationModifier.cs @ 13069

Last change on this file since 13069 was 13069, checked in by gkronber, 5 years ago

#2499: imported source code for HeuristicLab.BioBoost from private repository with some changes

File size: 6.6 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using HeuristicLab.BioBoost.ProblemDescription;
5using HeuristicLab.BioBoost.Representation;
6using HeuristicLab.Common;
7using HeuristicLab.Core;
8using HeuristicLab.Data;
9using HeuristicLab.Encodings.IntegerVectorEncoding;
10using HeuristicLab.Encodings.RealVectorEncoding;
11using HeuristicLab.Operators;
12using HeuristicLab.Optimization;
13using HeuristicLab.Parameters;
14using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
15
16namespace HeuristicLab.BioBoost.Operators.Mutation {
17  [StorableClass]
18  public abstract class PlantBasedUtilizationModifier : SingleSuccessorOperator, IManipulator, IStochasticOperator {
19
20    #region Parameters
21    public LookupParameter<BioBoostProblemData> ProblemDataParameter { get { return (LookupParameter<BioBoostProblemData>) Parameters["ProblemData"]; } }
22    public LookupParameter<DistanceMatrix> DistanceMatrixParameter { get { return (LookupParameter<DistanceMatrix>) Parameters["DistanceMatrix"]; } }
23    public ValueParameter<BoolValue> DistanceMatrixInProblemDataParameter { get { return (ValueParameter<BoolValue>) Parameters["DistanceMatrixInProblemData"]; } }
24    public ValueLookupParameter<IntMatrix> RegionBoundsParameter { get { return (ValueLookupParameter<IntMatrix>) Parameters["RegionBounds"]; } }
25    public ILookupParameter<IRandom> RandomParameter { get { return (ILookupParameter<IRandom>) Parameters["Random"]; } }
26    public IValueLookupParameter<DoubleMatrix> BoundsParameter { get { return (IValueLookupParameter<DoubleMatrix>) Parameters["Bounds"]; } }
27    #endregion
28
29    #region Parameter Values
30    public BioBoostProblemData ProblemData { get { return ProblemDataParameter.ActualValue; } }
31    public IntMatrix RegionBounds { get { return RegionBoundsParameter.ActualValue; } }
32    public DoubleMatrix Bounds { get { return BoundsParameter.ActualValue; } }
33    public IRandom Random { get { return RandomParameter.ActualValue; } }
34    public bool DistanceMatrixInProblemData { get { return DistanceMatrixInProblemDataParameter.Value.Value; } }
35    public DistanceMatrix DistanceMatrix {
36      get {
37        if (DistanceMatrixInProblemData)
38          return ((IValueParameter<DistanceMatrix>) ProblemData.Parameters[DistanceMatrixParameter.ActualName]).Value;
39        else return DistanceMatrixParameter.ActualValue;
40      }
41    }
42    #endregion
43
44    #region Construction & Cloning
45
46    [StorableConstructor]
47    public PlantBasedUtilizationModifier(bool isDeserializing) {}
48    public PlantBasedUtilizationModifier(PlantBasedUtilizationModifier orig, Cloner cloner) : base(orig, cloner) {}
49    public PlantBasedUtilizationModifier() {
50      Parameters.Add(new LookupParameter<BioBoostProblemData>("ProblemData", "The data store of the detailed problem description."));
51      Parameters.Add(new LookupParameter<DistanceMatrix>("DistanceMatrix", "The distance matrix to use", "StreetDistanceMatrix")); // TODO: check this
52      Parameters.Add(new ValueParameter<BoolValue>("DistanceMatrixInProblemData", "Whether to look for the distance matrix in problem data or in scope.", new BoolValue(true)));
53      Parameters.Add(new ValueLookupParameter<IntMatrix>("RegionBounds", "The limits of valid region ids."));
54      Parameters.Add(new ValueLookupParameter<DoubleMatrix>("Bounds", "The limits for manipulating utilizations.", new DoubleMatrix(new [,]{{0d, 1d}})));
55      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator."));
56    }
57
58    #endregion
59
60    public override IOperation Apply() {
61      var scope = ExecutionContext.Scope;
62      var productLinks = ProblemData.ProductLinks;
63      var feedstock =
64        ProblemData.TransportTargets.CheckedItems.ElementAt(
65          Random.Next(ProblemData.TransportTargets.CheckedItems.Count())).Value.Value;
66      var supplyTransports = scope.Variables[LayerDescriptor.TransportTargets.NameWithPrefix(feedstock)].Value as IntegerVector;
67      if (supplyTransports == null) return base.Apply();
68      var plants = supplyTransports.Select((target, source) => new {target, source}).GroupBy(p => p.target).ToList();
69      var plant = plants.ElementAt(Random.Next(plants.Count));
70      var suppliers = plant.Select(s => s.source).ToList();
71      var utilizations = GetUtilizations(scope, feedstock);
72      var preceedingFeedstock = GetPreceedingFeedstock(scope, feedstock, productLinks);
73      while (utilizations == null && preceedingFeedstock != null) {
74        var transportTargets = GetTransportTargets(scope, preceedingFeedstock);
75        if (transportTargets == null)
76          throw new InvalidOperationException("Error preceeding feedstock \"" + preceedingFeedstock + "\" of \"" + feedstock + "\" has no transport targets");
77        suppliers = // collect supplier's suppliers
78          suppliers.Select(s => transportTargets.Select((target, source) => new {source, target}).Where(p => p.target == s).Select(p => p.source))
79            .Aggregate((x, y) => x.Concat(y))
80            .ToList();
81        utilizations = GetUtilizations(scope, preceedingFeedstock);
82        preceedingFeedstock = GetPreceedingFeedstock(scope, preceedingFeedstock, productLinks);
83      }
84      if (utilizations == null) {
85        throw new InvalidOperationException("Error in supply chain: product " + feedstock +
86                                            " does not have an underlying feedstock");
87      }
88      if (suppliers.Count > 0)
89        Redistribute(utilizations, suppliers);
90      return base.Apply();
91    }
92
93    private string GetPreceedingFeedstock(IScope scope, string feedstock, StringMatrix productLinks) {
94      for (int i = 0; i < productLinks.Rows; i++) {
95        if (productLinks[i, 1] == feedstock)
96          return productLinks[i, 0];
97      }
98      return null;
99    }
100
101    private IntegerVector GetTransportTargets(IScope scope, string feedstock) {
102      IVariable v = null;
103      if (scope.Variables.TryGetValue(LayerDescriptor.TransportTargets.NameWithPrefix(feedstock), out v))
104        return v.Value as IntegerVector;
105      return null;
106    }
107
108
109    private RealVector GetUtilizations(IScope scope, string feedstock) {
110      IVariable v = null;
111      if (scope.Variables.TryGetValue(LayerDescriptor.Utilizations.NameWithPrefix(feedstock), out v))
112        return v.Value as RealVector;
113      return null;
114    }
115
116    public abstract void Redistribute(RealVector utilizations, List<int> supplierIndices);
117
118    public double EnforceBounds(double value, int idx) {
119      var min = Bounds[idx%Bounds.Rows, 0];
120      var max = Bounds[idx%Bounds.Rows, 1];
121      if (value < min) return min;
122      if (value > max) return max;
123      return value;
124    }
125  }
126}
Note: See TracBrowser for help on using the repository browser.