public static double CalculateSimilarity(BinaryVector left, BinaryVector right) { if (left == null || right == null) { throw new ArgumentException("Cannot calculate similarity because one or both of the provided solutions is null."); } if (left.Length != right.Length) { throw new ArgumentException("Cannot calculate similarity because the provided solutions have different lengths."); } if (left.Length == 0) { throw new ArgumentException("Cannot calculate similarity because solutions are of length 0."); } if (ReferenceEquals(left, right)) { return(1.0); } double similarity = 0.0; for (int i = 0; i < left.Length; i++) { if (left[i] == right[i]) { similarity++; } } return(similarity / left.Length); }
public override IOperation Apply() { BinaryVector binaryVector = BinaryVectorParameter.ActualValue; OneBitflipMove move = OneBitflipMoveParameter.ActualValue; BoolMatrix interactions = GeneInteractionsParameter.ActualValue; DoubleArray weights = WeightsParameter.ActualValue; int seed = InteractionSeedParameter.ActualValue.Value; double moveQuality = QualityParameter.ActualValue.Value; int q = QParameter.ActualValue.Value; double p = PParameter.ActualValue.Value; List<int> affectedFitnessComponents = new List<int>(); for (int c = 0; c < interactions.Columns; c++) if (interactions[move.Index, c]) affectedFitnessComponents.Add(c); BinaryVector moved = new BinaryVector(binaryVector); MovedBinaryVectorParameter.ActualValue = moved; moved[move.Index] = !moved[move.Index]; if (affectedFitnessComponents.Count * 2 > interactions.Columns) { double[] f_i; moveQuality = NKLandscape.Evaluate(moved, interactions, weights, seed, out f_i, q, p); } else { long x = NKLandscape.Encode(binaryVector); long y = NKLandscape.Encode(moved); long[] g = NKLandscape.Encode(interactions); double[] w = NKLandscape.Normalize(weights); foreach (var c in affectedFitnessComponents) { moveQuality -= w[c%w.Length]*NKLandscape.F_i(x, c, g[c], seed, q, p); moveQuality += w[c%w.Length]*NKLandscape.F_i(y, c, g[c], seed, q, p); } } if (MoveQualityParameter.ActualValue == null) MoveQualityParameter.ActualValue = new DoubleValue(moveQuality); else MoveQualityParameter.ActualValue.Value = moveQuality; return base.Apply(); }
/// <summary> /// Performs the some positions bitflip mutation on a binary vector. /// </summary> /// <param name="random">The random number generator to use.</param> /// <param name="vector">The vector that should be manipulated.</param> /// <param name="pm">The probability a bit is flipped.</param> public static void Apply(IRandom random, BinaryVector vector, DoubleValue pm) { for (int i = 0; i < vector.Length; i++) { if (random.NextDouble() < pm.Value) { vector[i] = !vector[i]; } } }
private static int MedianBit(BinaryVector x) { var activeIndices = x.Select((b, i) => new { b, i }).Where(v => v.b).ToList(); if (activeIndices.Count > 0) return activeIndices[activeIndices.Count / 2].i; else return 0; }
public static OneBitflipMove Apply(BinaryVector binaryVector, IRandom random) { int length = binaryVector.Length; int index = random.Next(length); return(new OneBitflipMove(index)); }
public BoolMatrix InitializeInterations(int length, int nComponents, int nInteractions, IRandom random) { Dictionary<int, int> bitInteractionCounts = new Dictionary<int, int>(); for (int i = 0; i < length; i++) { int count = nInteractions * 2 * i / length; if (count > 0) bitInteractionCounts[i] = count; } List<BinaryVector> components = new List<BinaryVector>(); while (bitInteractionCounts.Count > 0) { BinaryVector component = new BinaryVector(length); for (int i = 0; i < nInteractions; i++) { while (bitInteractionCounts.Count > 0) { int bit = bitInteractionCounts.ElementAt(random.Next(bitInteractionCounts.Count)).Key; if (bitInteractionCounts[bit]-- <= 0) bitInteractionCounts.Remove(bit); if (!component[bit]) { component[bit] = true; break; } } } components.Add(component); } BoolMatrix m = new BoolMatrix(length, components.Count); foreach (var c in components.Select((v, j) => new { v, j })) { for (int i = 0; i < c.v.Length; i++) { m[i, c.j] = c.v[i]; } } return m; }
public static OneBitflipMove[] Apply(BinaryVector binaryVector, IRandom random, int sampleSize) { OneBitflipMove[] moves = new OneBitflipMove[sampleSize]; for (int i = 0; i < sampleSize; i++) { moves[i] = StochasticOneBitflipSingleMoveGenerator.Apply(binaryVector, random); } return moves; }
/// <summary> /// Performs a uniform crossover between two binary vectors. /// </summary> /// <param name="random">A random number generator.</param> /// <param name="parent1">The first parent for crossover.</param> /// <param name="parent2">The second parent for crossover.</param> /// <returns>The newly created binary vector, resulting from the uniform crossover.</returns> public static BinaryVector Apply(IRandom random, BinaryVector parent1, BinaryVector parent2) { if (parent1.Length != parent2.Length) { throw new ArgumentException("UniformCrossover: The parents are of different length."); } int length = parent1.Length; bool[] result = new bool[length]; for (int i = 0; i < length; i++) { if (random.NextDouble() < 0.5) { result[i] = parent1[i]; } else { result[i] = parent2[i]; } } return(new BinaryVector(result)); }
/// <summary> /// Forwards the call to <see cref="Apply(IRandom, BinaryVector)"/>. /// </summary> /// <param name="random">The random number generator to use.</param> /// <param name="realVector">The vector of binary values to manipulate.</param> protected override void Manipulate(IRandom random, BinaryVector binaryVector) { if (MutationProbabilityParameter.ActualValue == null) { throw new InvalidOperationException("SomePositionsBitflipManipulator: Parameter " + MutationProbabilityParameter.ActualName + " could not be found."); } Apply(random, binaryVector, MutationProbabilityParameter.ActualValue); }
public static OneBitflipMove[] Apply(BinaryVector binaryVector) { int length = binaryVector.Length; int totalMoves = length; OneBitflipMove[] moves = new OneBitflipMove[totalMoves]; for (int i = 0; i < length; i++) moves[i] = new OneBitflipMove(i); return moves; }
public static OneBitflipMove[] Apply(BinaryVector binaryVector, IRandom random, int sampleSize) { OneBitflipMove[] moves = new OneBitflipMove[sampleSize]; for (int i = 0; i < sampleSize; i++) { moves[i] = StochasticOneBitflipSingleMoveGenerator.Apply(binaryVector, random); } return(moves); }
protected OneIndexMove(OneIndexMove original, Cloner cloner) : base(original, cloner) { this.Index = original.Index; if (original.BinaryVector != null) { this.BinaryVector = cloner.Clone(original.BinaryVector); } }
private EvaluationTracker(EvaluationTracker original, Cloner cloner) : base(original, cloner) { problem = cloner.Clone(original.problem); maxEvaluations = original.maxEvaluations; BestQuality = original.BestQuality; Evaluations = original.Evaluations; BestFoundOnEvaluation = original.BestFoundOnEvaluation; BestSolution = cloner.Clone(BestSolution); }
public override double Evaluate(BinaryVector individual, IRandom random) { if (individual.Length != Length) throw new ArgumentException("The individual has not the correct length."); int total = 0; var trapSize = TrapSize; for (int i = 0; i < individual.Length; i += trapSize) { total += Score(individual, i, trapSize); } return (double)(total * trapSize) / (TrapMaximum * individual.Length); }
protected override OneBitflipMove[] GenerateMoves(BinaryVector binaryVector) { IRandom random = RandomParameter.ActualValue; if (SampleSizeParameter.ActualValue == null) { throw new InvalidOperationException("StochasticOneBitflipMultiMoveGenerator: Parameter " + SampleSizeParameter.ActualName + " could not be found."); } return(Apply(binaryVector, random, SampleSizeParameter.ActualValue.Value)); }
public EvaluationTracker(BinaryProblem problem, int maxEvaluations) { this.problem = problem; this.maxEvaluations = maxEvaluations; BestSolution = new BinaryVector(Length); BestQuality = double.NaN; Evaluations = 0; BestFoundOnEvaluation = 0; if (Parameters.ContainsKey("Maximization")) Parameters.Remove("Maximization"); Parameters.Add(new FixedValueParameter<BoolValue>("Maximization", "Set to false if the problem should be minimized.", (BoolValue)new BoolValue(Maximization).AsReadOnly()) { Hidden = true }); }
public override double Evaluate(BinaryVector vector, IRandom random) { if (Evaluations >= maxEvaluations) throw new OperationCanceledException("Maximum Evaluation Limit Reached"); Evaluations++; double fitness = problem.Evaluate(vector, random); if (double.IsNaN(BestQuality) || problem.IsBetter(fitness, BestQuality)) { BestQuality = fitness; BestSolution = (BinaryVector)vector.Clone(); BestFoundOnEvaluation = Evaluations; } return fitness; }
public void Add(BinaryVector solution) { if (solution.Length != length) throw new ArgumentException("The individual has not the correct length."); for (int i = 1; i < solution.Length; i++) { for (int j = 0; j < i; j++) { // Updates the entry of the 4 long array based on the two bits var pattern = (Convert.ToByte(solution[j]) << 1) + Convert.ToByte(solution[i]); occurances[i][j][pattern]++; } } rebuildRequired = true; }
public static double CalculateSimilarity(BinaryVector left, BinaryVector right) { if (left == null || right == null) throw new ArgumentException("Cannot calculate similarity because one or both of the provided scopes is null."); if (left.Length != right.Length) throw new ArgumentException("Cannot calculate similarity because the provided solutions have different lengths."); if (left == right) return 1.0; double similarity = 0.0; for (int i = 0; i < left.Length; i++) if (left[i] == right[i]) similarity++; return similarity / left.Length; }
// In the GECCO paper, calculates Equation 3 protected virtual int Score(BinaryVector individual, int trapIndex, int trapSize) { int result = 0; // count number of bits in trap set to 1 for (int index = trapIndex; index < trapIndex + trapSize; index++) { if (individual[index]) result++; } // Make it deceptive if (result < trapSize) { result = trapSize - result - 1; } return result; }
public override IOperation Apply() { OneBitflipMove move = OneBitflipMoveParameter.ActualValue; BinaryVector binaryVector = BinaryVectorParameter.ActualValue; DoubleValue moveQuality = MoveQualityParameter.ActualValue; DoubleValue quality = QualityParameter.ActualValue; binaryVector[move.Index] = !binaryVector[move.Index]; quality.Value = moveQuality.Value; return(base.Apply()); }
public static OneBitflipMove[] Apply(BinaryVector binaryVector) { int length = binaryVector.Length; int totalMoves = length; OneBitflipMove[] moves = new OneBitflipMove[totalMoves]; for (int i = 0; i < length; i++) { moves[i] = new OneBitflipMove(i); } return(moves); }
public int Compare(BinaryVector x, BinaryVector y) { for (int i = 0; i < Math.Min(x.Length, y.Length); i++) { if (!x[i] && y[i]) return -1; if (x[i] && !y[i]) return 1; } if (x.Length > y.Length) return 1; if (x.Length < y.Length) return -1; return 0; }
/// <summary> /// Performs a N point crossover at randomly chosen positions of the two /// given parent binary vectors. /// </summary> /// <exception cref="ArgumentException">Thrown when the value for N is invalid or when the parent vectors are of different length.</exception> /// <param name="random">A random number generator.</param> /// <param name="parent1">The first parent for crossover.</param> /// <param name="parent2">The second parent for crossover.</param> /// <param name="n">Number of crossover points.</param> /// <returns>The newly created binary vector, resulting from the N point crossover.</returns> public static BinaryVector Apply(IRandom random, BinaryVector parent1, BinaryVector parent2, IntValue n) { if (parent1.Length != parent2.Length) throw new ArgumentException("NPointCrossover: The parents are of different length."); if (n.Value > parent1.Length) throw new ArgumentException("NPointCrossover: There cannot be more breakpoints than the size of the parents."); if (n.Value < 1) throw new ArgumentException("NPointCrossover: N cannot be < 1."); int length = parent1.Length; bool[] result = new bool[length]; int[] breakpoints = new int[n.Value]; //choose break points List<int> breakpointPool = new List<int>(); for (int i = 0; i < length; i++) breakpointPool.Add(i); for (int i = 0; i < n.Value; i++) { int index = random.Next(breakpointPool.Count); breakpoints[i] = breakpointPool[index]; breakpointPool.RemoveAt(index); } Array.Sort(breakpoints); //perform crossover int arrayIndex = 0; int breakPointIndex = 0; bool firstParent = true; while (arrayIndex < length) { if (breakPointIndex < breakpoints.Length && arrayIndex == breakpoints[breakPointIndex]) { breakPointIndex++; firstParent = !firstParent; } if (firstParent) result[arrayIndex] = parent1[arrayIndex]; else result[arrayIndex] = parent2[arrayIndex]; arrayIndex++; } return new BinaryVector(result); }
// In the GECCO paper, Figure 3 public static double ImproveUsingTree(LinkageTree tree, IList<BinaryVector> donors, BinaryVector solution, double fitness, BinaryProblem problem, IRandom rand) { var options = Enumerable.Range(0, donors.Count).ToArray(); foreach (var cluster in tree.Clusters) { // Find a donor which has at least one gene value different // from the current solution for this cluster of genes bool donorFound = false; foreach (var donorIndex in options.ShuffleList(rand)) { // Attempt the donation fitness = Donate(solution, fitness, donors[donorIndex], cluster, problem, rand, out donorFound); if (donorFound) break; } } return fitness; }
public override IOperation Apply() { BinaryVector v = BinaryVectorParameter.ActualValue; OneBitflipMove[] moves = GenerateMoves(v); Scope[] moveScopes = new Scope[moves.Length]; for (int i = 0; i < moveScopes.Length; i++) { moveScopes[i] = new Scope(i.ToString()); moveScopes[i].Variables.Add(new Variable(OneBitflipMoveParameter.ActualName, moves[i])); } CurrentScopeParameter.ActualValue.SubScopes.AddRange(moveScopes); return(base.Apply()); }
/// <summary> /// Generates a new random binary vector with the given <paramref name="length"/>. /// </summary> /// <param name="random">The random number generator.</param> /// <param name="length">The length of the binary vector.</param> /// <param name="trueProbability">The propability for true to occur at a certain position in the binary vector</param> /// <returns>The newly created binary vector.</returns> public static BinaryVector Apply(IRandom random, int length, double trueProbability = 0.5) { BinaryVector result; //Backwards compatiblity code to ensure the same behavior for existing algorithm runs //remove with HL 3.4 if (trueProbability.IsAlmost(0.5)) result = new BinaryVector(length, random); else { var values = new bool[length]; for (int i = 0; i < length; i++) values[i] = random.NextDouble() < trueProbability; result = new BinaryVector(values); } return result; }
/// <summary> /// Performs a uniform crossover between two binary vectors. /// </summary> /// <param name="random">A random number generator.</param> /// <param name="parent1">The first parent for crossover.</param> /// <param name="parent2">The second parent for crossover.</param> /// <returns>The newly created binary vector, resulting from the uniform crossover.</returns> public static BinaryVector Apply(IRandom random, BinaryVector parent1, BinaryVector parent2) { if (parent1.Length != parent2.Length) throw new ArgumentException("UniformCrossover: The parents are of different length."); int length = parent1.Length; bool[] result = new bool[length]; for (int i = 0; i < length; i++) { if (random.NextDouble() < 0.5) result[i] = parent1[i]; else result[i] = parent2[i]; } return new BinaryVector(result); }
protected override void Run(CancellationToken cancellationToken) { var BestQuality = new DoubleValue(double.NaN); Results.Add(new Result("Best quality", BestQuality)); for (int iteration = 0; iteration < Iterations; iteration++) { var solution = new BinaryVector(Problem.Length); for (int i = 0; i < solution.Length; i++) { solution[i] = random.Next(2) == 1; } var fitness = Problem.Evaluate(solution, random); fitness = ImproveToLocalOptimum(Problem, solution, fitness, random); if (double.IsNaN(BestQuality.Value) || Problem.IsBetter(fitness, BestQuality.Value)) { BestQuality.Value = fitness; } } }
public override IOperation Apply() { BinaryVector binaryVector = BinaryVectorParameter.ActualValue; OneBitflipMove move = OneBitflipMoveParameter.ActualValue; BinaryVector newSolution = new BinaryVector(binaryVector); newSolution[move.Index] = !newSolution[move.Index]; DoubleValue quality = KnapsackEvaluator.Apply(newSolution, KnapsackCapacityParameter.ActualValue, PenaltyParameter.ActualValue, WeightsParameter.ActualValue, ValuesParameter.ActualValue).Quality; double moveQuality = quality.Value; if (MoveQualityParameter.ActualValue == null) MoveQualityParameter.ActualValue = new DoubleValue(moveQuality); else MoveQualityParameter.ActualValue.Value = moveQuality; return base.Apply(); }
/// <summary> /// Generates a new random binary vector with the given <paramref name="length"/>. /// </summary> /// <param name="random">The random number generator.</param> /// <param name="length">The length of the binary vector.</param> /// <param name="trueProbability">The propability for true to occur at a certain position in the binary vector</param> /// <returns>The newly created binary vector.</returns> public static BinaryVector Apply(IRandom random, int length, double trueProbability = 0.5) { BinaryVector result; //Backwards compatiblity code to ensure the same behavior for existing algorithm runs //remove with HL 3.4 if (trueProbability.IsAlmost(0.5)) { result = new BinaryVector(length, random); } else { var values = new bool[length]; for (int i = 0; i < length; i++) { values[i] = random.NextDouble() < trueProbability; } result = new BinaryVector(values); } return(result); }
// In the GECCO paper, Section 4.1 public override double Evaluate(BinaryVector individual, IRandom random) { int[] level = new int[individual.Length]; int levelLength = individual.Length; // Initialize the level to the current solution for (int i = 0; i < levelLength; i++) { level[i] = Convert.ToInt32(individual[i]); } int power = 1; int nextLength = levelLength / 2; int total = 0; int maximum = 0; // Keep going while the next level actual has bits in it while (nextLength > 0) { int[] nextLevel = new int[nextLength]; // Construct the next level using the current level for (int i = 0; i + 1 < levelLength; i += 2) { if (level[i] == level[i + 1] && level[i] != -1) { // Score points for a correct setting at this level total += power; nextLevel[i / 2] = level[i]; } else { nextLevel[i / 2] = -1; } // Keep track of the maximum possible score maximum += power; } level = nextLevel; levelLength = nextLength; nextLength = levelLength / 2; power *= 2; } // Convert to percentage of total return (double)total / maximum; }
private static double Donate(BinaryVector solution, double fitness, BinaryVector source, IEnumerable<int> cluster, BinaryProblem problem, IRandom rand, out bool changed) { // keep track of which bits flipped to make the donation List<int> flipped = new List<int>(); foreach (var index in cluster) { if (solution[index] != source[index]) { flipped.Add(index); solution[index] = !solution[index]; } } changed = flipped.Count > 0; if (changed) { double newFitness = problem.Evaluate(solution, rand); // if the original is strictly better, revert the change if (problem.IsBetter(fitness, newFitness)) { foreach (var index in flipped) { solution[index] = !solution[index]; } } else { // new solution is no worse than original, keep change to solution fitness = newFitness; } } return fitness; }
protected override OneBitflipMove[] GenerateMoves(BinaryVector binaryVector) { return(Apply(binaryVector)); }
/// <summary> /// Forwards the call to <see cref="Apply(IRandom, BinaryVector)"/>. /// </summary> /// <param name="random">The random number generator to use.</param> /// <param name="realVector">The vector of binary values to manipulate.</param> protected override void Manipulate(IRandom random, BinaryVector binaryVector) { Apply(random, binaryVector); }
/// <summary> /// Performs the single position bitflip mutation on a binary vector. /// </summary> /// <param name="random">The random number generator to use.</param> /// <param name="vector">The vector that should be manipulated.</param> public static void Apply(IRandom random, BinaryVector vector) { int position = random.Next(vector.Length); vector[position] = !vector[position]; }
protected override OneBitflipMove[] GenerateMoves(BinaryVector binaryVector) { IRandom random = RandomParameter.ActualValue; return new OneBitflipMove[] { Apply(binaryVector, random) }; }
public static OneBitflipMove Apply(BinaryVector binaryVector, IRandom random) { int length = binaryVector.Length; int index = random.Next(length); return new OneBitflipMove(index); }
public int Compare(BinaryVector x, BinaryVector y) { return (AverageBit(x) - AverageBit(y)).CompareTo(0); }
public OneIndexMove(int index, BinaryVector binaryVector) : base() { Index = index; BinaryVector = binaryVector; }
protected abstract void Manipulate(IRandom random, BinaryVector binaryVector);
protected abstract OneBitflipMove[] GenerateMoves(BinaryVector binaryVector);
protected BinaryVector(BinaryVector original, Cloner cloner) : base(original, cloner) { }
/// <summary> /// Performs a N point crossover at randomly chosen positions of the two /// given parent binary vectors. /// </summary> /// <exception cref="ArgumentException">Thrown when the value for N is invalid or when the parent vectors are of different length.</exception> /// <param name="random">A random number generator.</param> /// <param name="parent1">The first parent for crossover.</param> /// <param name="parent2">The second parent for crossover.</param> /// <param name="n">Number of crossover points.</param> /// <returns>The newly created binary vector, resulting from the N point crossover.</returns> public static BinaryVector Apply(IRandom random, BinaryVector parent1, BinaryVector parent2, IntValue n) { if (parent1.Length != parent2.Length) { throw new ArgumentException("NPointCrossover: The parents are of different length."); } if (n.Value > parent1.Length) { throw new ArgumentException("NPointCrossover: There cannot be more breakpoints than the size of the parents."); } if (n.Value < 1) { throw new ArgumentException("NPointCrossover: N cannot be < 1."); } int length = parent1.Length; bool[] result = new bool[length]; int[] breakpoints = new int[n.Value]; //choose break points List <int> breakpointPool = new List <int>(); for (int i = 0; i < length; i++) { breakpointPool.Add(i); } for (int i = 0; i < n.Value; i++) { int index = random.Next(breakpointPool.Count); breakpoints[i] = breakpointPool[index]; breakpointPool.RemoveAt(index); } Array.Sort(breakpoints); //perform crossover int arrayIndex = 0; int breakPointIndex = 0; bool firstParent = true; while (arrayIndex < length) { if (breakPointIndex < breakpoints.Length && arrayIndex == breakpoints[breakPointIndex]) { breakPointIndex++; firstParent = !firstParent; } if (firstParent) { result[arrayIndex] = parent1[arrayIndex]; } else { result[arrayIndex] = parent2[arrayIndex]; } arrayIndex++; } return(new BinaryVector(result)); }
public OneBitflipMove(int index, BinaryVector binaryVector) : base(index, binaryVector) { }
private static double AverageBit(BinaryVector x) { return x.Select((b, i) => new { b, i }).Where(v => v.b).Average(v => v.i); }
public void Add(BinaryVector solution) { Solutions.Add(solution); Tree.Add(solution); }
protected override OneBitflipMove[] GenerateMoves(BinaryVector binaryVector) { IRandom random = RandomParameter.ActualValue; return(new OneBitflipMove[] { Apply(binaryVector, random) }); }