public static ItemArray<IItem> Apply(IItem initiator, IItem guide, IntValue k, PercentValue n) {
      if (!(initiator is RealVector) || !(guide is RealVector))
        throw new ArgumentException("Cannot relink path because one of the provided solutions or both have the wrong type.");
      if (n.Value <= 0.0)
        throw new ArgumentException("RelinkingAccuracy must be greater than 0.");

      RealVector v1 = initiator.Clone() as RealVector;
      RealVector v2 = guide as RealVector;

      if (v1.Length != v2.Length)
        throw new ArgumentException("The solutions are of different length.");

      IList<RealVector> solutions = new List<RealVector>();
      for (int i = 0; i < k.Value; i++) {
        RealVector solution = v1.Clone() as RealVector;
        for (int j = 0; j < solution.Length; j++)
          solution[j] = v1[j] + 1 / (k.Value - i) * (v2[j] - v1[j]);
        solutions.Add(solution);
      }

      IList<IItem> selection = new List<IItem>();
      if (solutions.Count > 0) {
        int noSol = (int)(solutions.Count * n.Value);
        if (noSol <= 0) noSol++;
        double stepSize = (double)solutions.Count / (double)noSol;
        for (int i = 0; i < noSol; i++)
          selection.Add(solutions.ElementAt((int)((i + 1) * stepSize - stepSize * 0.5)));
      }

      return new ItemArray<IItem>(selection);
    }
    public static ItemArray<IItem> Apply(IItem initiator, IItem[] guides, DistanceMatrix distances, PercentValue n) {
      if (!(initiator is Permutation) || guides.Any(x => !(x is Permutation)))
        throw new ArgumentException("Cannot relink path because some of the provided solutions have the wrong type.");
      if (n.Value <= 0.0)
        throw new ArgumentException("RelinkingAccuracy must be greater than 0.");

      Permutation v1 = initiator.Clone() as Permutation;
      Permutation[] targets = new Permutation[guides.Length];
      Array.Copy(guides, targets, guides.Length);

      if (targets.Any(x => x.Length != v1.Length))
        throw new ArgumentException("At least one solution is of different length.");

      IList<Permutation> solutions = new List<Permutation>();
      for (int i = 0; i < v1.Length; i++) {
        int currCityIndex = i;
        int bestCityIndex = (i + 1) % v1.Length;
        double currDistance = distances[v1[currCityIndex], v1[bestCityIndex]];
        // check each guiding solution
        targets.ToList().ForEach(solution => {
          // locate current city
          var node = solution.Select((x, index) => new { Id = x, Index = index }).Single(x => x.Id == v1[currCityIndex]);
          int pred = solution[(node.Index - 1 + solution.Length) % solution.Length];
          int succ = solution[(node.Index + 1) % solution.Length];
          // get distances to neighbors
          var results = new[] { pred, succ }.Select(x => new { Id = x, Distance = distances[x, node.Id] });
          var bestCity = results.Where(x => x.Distance < currDistance).OrderBy(x => x.Distance).FirstOrDefault();
          if (bestCity != null) {
            bestCityIndex = v1.Select((x, index) => new { Id = x, Index = index }).Single(x => x.Id == bestCity.Id).Index;
            currDistance = bestCity.Distance;
          }
        });
        Invert(v1, currCityIndex + 1, bestCityIndex);
        solutions.Add(v1.Clone() as Permutation);
      }

      IList<IItem> selection = new List<IItem>();
      if (solutions.Count > 0) {
        int noSol = (int)(solutions.Count * n.Value);
        if (noSol <= 0) noSol++;
        double stepSize = (double)solutions.Count / (double)noSol;
        for (int i = 0; i < noSol; i++)
          selection.Add(solutions.ElementAt((int)((i + 1) * stepSize - stepSize * 0.5)));
      }

      return new ItemArray<IItem>(selection);
    }
    public static ItemArray<IItem> Apply(IItem initiator, IItem guide, PercentValue n) {
      if (!(initiator is Permutation) || !(guide is Permutation))
        throw new ArgumentException("Cannot relink path because one of the provided solutions or both have the wrong type.");
      if (n.Value <= 0.0)
        throw new ArgumentException("RelinkingAccuracy must be greater than 0.");

      Permutation firstInitiator = initiator.Clone() as Permutation;
      Permutation firstGuide = guide.Clone() as Permutation;
      Permutation secondInitiator = firstGuide.Clone() as Permutation;
      Permutation secondGuide = firstInitiator.Clone() as Permutation;

      if (firstInitiator.Length != firstGuide.Length)
        throw new ArgumentException("The solutions are of different length.");

      IList<Permutation> solutions = new List<Permutation>();
      for (int i = 0; i < firstInitiator.Length / 2; i++) {
        if (firstInitiator[i] != firstGuide[i]) {
          var target = firstInitiator.Select((x, index) => new { Value = x, ValueIndex = index }).First(x => x.Value == firstGuide[i]);
          // XOR swap
          firstInitiator[i] ^= firstInitiator[target.ValueIndex];
          firstInitiator[target.ValueIndex] ^= firstInitiator[i];
          firstInitiator[i] ^= firstInitiator[target.ValueIndex];
          solutions.Add(firstInitiator.Clone() as Permutation);
        }
        int j = secondInitiator.Length - 1 - i;
        if (secondInitiator[j] != secondGuide[j]) {
          var target = secondInitiator.Select((x, index) => new { Value = x, ValueIndex = index }).First(x => x.Value == secondGuide[j]);
          // XOR swap
          secondInitiator[j] ^= secondInitiator[target.ValueIndex];
          secondInitiator[target.ValueIndex] ^= secondInitiator[j];
          secondInitiator[j] ^= secondInitiator[target.ValueIndex];
          solutions.Add(secondInitiator.Clone() as Permutation);
        }
      }

      IList<IItem> selection = new List<IItem>();
      if (solutions.Count > 0) {
        int noSol = (int)(solutions.Count * n.Value);
        if (noSol <= 0) noSol++;
        double stepSize = (double)solutions.Count / (double)noSol;
        for (int i = 0; i < noSol; i++)
          selection.Add(solutions.ElementAt((int)((i + 1) * stepSize - stepSize * 0.5)));
      }

      return new ItemArray<IItem>(selection);
    }
 public override IOperation Apply() {
   ItemArray<BoolValue> tabu = IsTabuParameter.ActualValue;
   if (tabu.Length > 0) {
     PercentValue value = PercentTabuParameter.ActualValue;
     if (value == null) {
       value = new PercentValue();
       PercentTabuParameter.ActualValue = value;
     }
     value.Value = tabu.Where(x => x.Value).Count() / (double)tabu.Length;
     ResultCollection results = ResultsParameter.ActualValue;
     if (results != null) {
       IResult result = null;
       results.TryGetValue(PercentTabuParameter.ActualName, out result);
       if (result != null)
         result.Value = value;
       else
         results.Add(new Result(PercentTabuParameter.ActualName, "Indicates how much of the neighborhood is tabu.", (IItem)value.Clone()));
     }
   }
   return base.Apply();
 }
    public static ItemArray<IItem> Apply(IItem initiator, IItem guide, PercentValue n) {
      if (!(initiator is BinaryVector) || !(guide is BinaryVector))
        throw new ArgumentException("Cannot relink path because one of the provided solutions or both have the wrong type.");
      if (n.Value <= 0.0)
        throw new ArgumentException("RelinkingAccuracy must be greater than 0.");

      BinaryVector firstInitiator = initiator.Clone() as BinaryVector;
      BinaryVector firstGuide = guide.Clone() as BinaryVector;
      BinaryVector secondInitiator = firstGuide.Clone() as BinaryVector;
      BinaryVector secondGuide = firstInitiator.Clone() as BinaryVector;

      if (firstInitiator.Length != firstGuide.Length)
        throw new ArgumentException("The solutions are of different length.");

      IList<BinaryVector> solutions = new List<BinaryVector>();
      for (int i = 0; i < firstInitiator.Length / 2; i++) {
        if (firstInitiator[i] != firstGuide[i]) {
          firstInitiator[i] = firstGuide[i];
          solutions.Add(firstInitiator.Clone() as BinaryVector);
        }
        int j = secondInitiator.Length - 1 - i;
        if (secondInitiator[j] != secondGuide[j]) {
          secondInitiator[j] = secondGuide[j];
          solutions.Add(secondInitiator.Clone() as BinaryVector);
        }
      }

      IList<IItem> selection = new List<IItem>();
      if (solutions.Count > 0) {
        int noSol = (int)(solutions.Count * n.Value);
        if (noSol <= 0) noSol++;
        double stepSize = (double)solutions.Count / (double)noSol;
        for (int i = 0; i < noSol; i++)
          selection.Add(solutions.ElementAt((int)((i + 1) * stepSize - stepSize * 0.5)));
      }

      return new ItemArray<IItem>(selection);
    }
 protected override ItemArray<IItem> Relink(ItemArray<IItem> parents, PercentValue n) {
   if (parents.Length != 2)
     throw new ArgumentException("The number of parents is not equal to 2.");
   return Apply(parents[0], parents[1], RelinkingIntensity, n);
 }
    private void AfterDeserialization() {
      #region conversion of old NSM parameters
      if (Parameters.ContainsKey(SelectorParameterName)) { // change SelectorParameter type from ISelector to ISingleObjectiveSelector
        ValueParameter<ISelector> param = Parameters[SelectorParameterName] as ValueParameter<ISelector>;
        if (param != null) {
          ISingleObjectiveSelector selector = param.Value as ISingleObjectiveSelector;
          if (selector == null) selector = new TournamentSelector();
          Parameters.Remove(SelectorParameterName);
          Parameters.Add(new ValueParameter<ISingleObjectiveSelector>(SelectorParameterName, "The inner selection operator to select the parents.", selector));
        }
      }
      // FixedValueParameter for quality difference percentage, max attempts, use range
      if (Parameters.ContainsKey(QualityDifferencePercentageParameterName)) {
        ValueParameter<PercentValue> param = Parameters[QualityDifferencePercentageParameterName] as ValueParameter<PercentValue>;
        if (!(param is FixedValueParameter<PercentValue>)) {
          PercentValue diff = param != null ? param.Value as PercentValue : null;
          if (diff == null) diff = new PercentValue(0.05);
          Parameters.Remove(QualityDifferencePercentageParameterName);
          Parameters.Add(new FixedValueParameter<PercentValue>(QualityDifferencePercentageParameterName, "The minimum quality difference from parent1 to parent2 to accept the selection.", diff));
        }
      }
      if (Parameters.ContainsKey(QualityDifferenceMaxAttemptsParameterName)) {
        ValueParameter<IntValue> param = Parameters[QualityDifferenceMaxAttemptsParameterName] as ValueParameter<IntValue>;
        if (!(param is FixedValueParameter<IntValue>)) {
          IntValue attempts = param != null ? param.Value as IntValue : null;
          if (attempts == null) attempts = new IntValue(5);
          Parameters.Remove(QualityDifferenceMaxAttemptsParameterName);
          Parameters.Add(new FixedValueParameter<IntValue>(QualityDifferenceMaxAttemptsParameterName, "The maximum number of attempts to find parents which differ in quality.", attempts));
        }
      }
      if (Parameters.ContainsKey(QualityDifferenceUseRangeParameterName)) {
        ValueParameter<BoolValue> param = Parameters[QualityDifferenceUseRangeParameterName] as ValueParameter<BoolValue>;
        if (!(param is FixedValueParameter<BoolValue>)) {
          BoolValue range = param != null ? param.Value as BoolValue : null;
          if (range == null) range = new BoolValue(true);
          Parameters.Remove(QualityDifferenceUseRangeParameterName);
          Parameters.Add(new FixedValueParameter<BoolValue>(QualityDifferenceUseRangeParameterName, "Use the range from minimum to maximum quality as basis for QualityDifferencePercentage.", range));
        }
      }
      if (!Parameters.ContainsKey(QualityDifferenceUseRangeParameterName)) // add use range parameter
        Parameters.Add(new FixedValueParameter<BoolValue>(QualityDifferenceUseRangeParameterName, "Use the range from minimum to maximum quality as basis for QualityDifferencePercentage.", new BoolValue(true)));
      #endregion

      RegisterParameterEventHandlers();
    }
    public static ItemArray<IItem> Apply(PotvinEncoding initiator, PotvinEncoding guide, PercentValue n, int sampleSize, int iterations, IRandom rand, IVRPProblemInstance problemInstance) {
      if (initiator == null || guide == null)
        throw new ArgumentException("Cannot relink path because one of the provided solutions or both are null.");

      double sigma = 1.5;
      double minPenalty = 0.001;
      double maxPenalty = 1000000000;

      var originalOverloadPenalty = new DoubleValue();
      if (problemInstance is IHomogenousCapacitatedProblemInstance)
        originalOverloadPenalty.Value = (problemInstance as IHomogenousCapacitatedProblemInstance).OverloadPenalty.Value;
      var originalTardinessPenalty = new DoubleValue();
      if (problemInstance is ITimeWindowedProblemInstance)
        originalTardinessPenalty.Value = (problemInstance as ITimeWindowedProblemInstance).TardinessPenalty.Value;

      PotvinEncoding current = MatchTours(initiator, guide, problemInstance);
      double currentSimilarity = VRPSimilarityCalculator.CalculateSimilarity(current, guide);

      IList<PotvinEncoding> solutions = new List<PotvinEncoding>();
      int i = 0;
      while (i < iterations && !currentSimilarity.IsAlmost(1.0)) {
        var currentEval = problemInstance.Evaluate(current);
        currentSimilarity = VRPSimilarityCalculator.CalculateSimilarity(current, guide);

        if (currentSimilarity < 1.0) {
          for (int sample = 0; sample < sampleSize; sample++) {
            var next = current.Clone() as PotvinEncoding;

            int neighborhood = rand.Next(3);
            switch (neighborhood) {
              case 0: next = RouteBasedXOver(next, guide, rand,
                problemInstance);
                break;
              case 1: next = SequenceBasedXOver(next, guide, rand,
                problemInstance);
                break;
              case 2: GuidedRelocateMove(next, guide, rand);
                break;
            }

            next = MatchTours(next, guide, problemInstance);

            var nextEval = problemInstance.Evaluate(next);
            if ((nextEval.Quality < currentEval.Quality)) {
              current = next;
              solutions.Add(current);
              break;
            }
          }

          if (problemInstance is IHomogenousCapacitatedProblemInstance) {
            if (((CVRPEvaluation)currentEval).Overload > 0) {
              (problemInstance as IHomogenousCapacitatedProblemInstance).OverloadPenalty.Value =
                Math.Min(maxPenalty,
                (problemInstance as IHomogenousCapacitatedProblemInstance).OverloadPenalty.Value * sigma);
            } else {
              (problemInstance as IHomogenousCapacitatedProblemInstance).OverloadPenalty.Value =
                Math.Max(minPenalty,
                (problemInstance as IHomogenousCapacitatedProblemInstance).OverloadPenalty.Value * sigma);
            }
          }


          if (problemInstance is ITimeWindowedProblemInstance) {
            if (((CVRPTWEvaluation)currentEval).Tardiness > 0) {
              (problemInstance as ITimeWindowedProblemInstance).TardinessPenalty.Value =
                Math.Min(maxPenalty,
              (problemInstance as ITimeWindowedProblemInstance).TardinessPenalty.Value * sigma);
            } else {
              (problemInstance as ITimeWindowedProblemInstance).TardinessPenalty.Value =
                Math.Max(minPenalty,
                (problemInstance as ITimeWindowedProblemInstance).TardinessPenalty.Value / sigma);
            }
          }

          i++;
        }
      }

      if (problemInstance is IHomogenousCapacitatedProblemInstance)
        (problemInstance as IHomogenousCapacitatedProblemInstance).OverloadPenalty.Value = originalOverloadPenalty.Value;
      if (problemInstance is ITimeWindowedProblemInstance)
        (problemInstance as ITimeWindowedProblemInstance).TardinessPenalty.Value = originalTardinessPenalty.Value;

      return new ItemArray<IItem>(ChooseSelection(solutions, n));
    }
    protected override ItemArray<IItem> Relink(ItemArray<IItem> parents, PercentValue n) {
      if (parents.Length != 2)
        throw new ArgumentException("The number of parents is not equal to 2.");

      if (!(parents[0] is PotvinEncoding))
        parents[0] = PotvinEncoding.ConvertFrom(parents[0] as IVRPEncoding, ProblemInstanceParameter.ActualValue);
      if (!(parents[1] is PotvinEncoding))
        parents[1] = PotvinEncoding.ConvertFrom(parents[1] as IVRPEncoding, ProblemInstanceParameter.ActualValue);

      return Apply(parents[0] as PotvinEncoding, parents[1] as PotvinEncoding, n,
        SampleSizeParameter.Value.Value, IterationsParameter.Value.Value, RandomParameter.ActualValue, ProblemInstanceParameter.ActualValue);
    }
    private static IList<IItem> ChooseSelection(IList<PotvinEncoding> solutions, PercentValue n) {
      IList<IItem> selection = new List<IItem>();
      if (solutions.Count > 0) {
        int noSol = (int)(solutions.Count * n.Value);
        if (noSol <= 0) noSol++;
        double stepSize = (double)solutions.Count / (double)noSol;
        for (int i = 0; i < noSol; i++)
          selection.Add(solutions.ElementAt((int)((i + 1) * stepSize - stepSize * 0.5)));
      }

      return selection;
    }
 protected override ItemArray<IItem> Relink(ItemArray<IItem> parents, PercentValue n) {
   if (parents.Length < 2)
     throw new ArgumentException("The number of parents is smaller than 2.");
   return Apply(parents[0], parents.Skip(1).ToArray(), DistanceMatrix, n);
 }
 protected abstract ItemArray<IItem> Relink(ItemArray<IItem> parents, PercentValue n);
Beispiel #13
0
 protected PercentValue(PercentValue original, Cloner cloner)
   : base(original, cloner) {
   restrictToUnitInterval = original.restrictToUnitInterval;
 }