基于遗传算法求解CVRP问题(待修正)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

package CVRP;


import CVRP.algorithms.SimpleGA;


public class CVRP {

	
	public static void test(){// check
		LimitedPriorityQueue lpq = new LimitedPriorityQueue(5, new Double(1));// capacity of this queue is 5,
		// the second param provides they type of fitness for this lpq
		lpq.printArray(0);
		
		lpq.push(2, new Double(45));// <index, fitness>
		lpq.push(4, new Double(50));// 'lpq' puts the one with smaller fitness in the front
		lpq.push(5, new Double(34));
		lpq.push(6, new Double(20));
		lpq.push(7, new Double(59));
		lpq.push(8, new Double(12));
		lpq.push(9, new Double(30));
		
		lpq.printArray(1);
	}
	
	public static void main(String[] args) {
		
		test();// test the function of lpq

		SimpleGA sga = new SimpleGA();
		sga.randomise(); // get 2000 initial populations
		sga.run(30000);
		sga.printBestPath();

	}

}
package CVRP;

import java.util.ArrayList;

public class LimitedPriorityQueue {

	private ArrayList<WeightLookup> values;
	private int size;// max #population this queue can store
	
	public LimitedPriorityQueue(int size, Number sample){// 'sample' provides the type of fitness for this priorityQueue
		values = new ArrayList<WeightLookup>(size);
		this.size = size;
		if(sample instanceof Integer)
			for(int i = 0; i < size; i++)
				values.add(i, new WeightLookup(0, (Number) new Integer(Integer.MAX_VALUE)));
		else if (sample instanceof Double)
			for(int i = 0; i < size; i++)
				values.add(i, new WeightLookup(0, (Number) new Double(Integer.MAX_VALUE)));
		else if (sample instanceof Float)
			for(int i = 0; i < size; i++)
				values.add(i, new WeightLookup(0, (Number) new Float(Integer.MAX_VALUE)));
	}
	
	public boolean push(int index, Number newVal){// sort those populations by 'fitness', the smaller one is in the front
		// put this newVal on its proper position in 'values'
		for(int i = 0; i < values.size(); i++){
			if(lessThan(newVal,values.get(i).weight)){
				for(int j = values.size() - 1; j > i; j--){ // move backward to make room for 'newVal'
					values.set(j, values.get(j - 1));
				}
				values.set(i, new WeightLookup(index, newVal));
				return true;
			}
		}
		return false;
	}

	public void printArray(int iteration){
		// at the 'iteration' iteration,  print the indices and fitness of all the populations in the current LimitedPriorityQueue
		String s = iteration + ": ";
		for(int i = 0; i < values.size(); i++){
			s = s.concat("{" + String.valueOf(values.get(i).index) + ", " + String.valueOf(values.get(i).weight + "}"));
			if(i < values.size() - 1) s = s.concat(", ");
		}
		
		System.out.println(s);
	}
	
	public int[] getIndices(){// from weights sorted from small to large, get their indices
		int[] indices = new int[size];
		
		for(int i = 0; i < size; i++){
			indices[i] = values.get(i).index;
		}
		
		return indices;
	}
	
	private boolean lessThan(Number a, Number b){
		if(a instanceof Integer){
			if((Integer)a < (Integer)b) return true;
		} else if(a instanceof Double){
			if((Double)a < (Double)b) return true;
		} else if(a instanceof Float){
			if((Float)a < (Float)b) return true;
		}
		return false;
	}
	
	private class WeightLookup{
		public int index;
		public Number weight;
		
		public WeightLookup(int index, Number weight){
			this.index = index;
			this.weight = weight;
		}
	}
}


package CVRP;


public class CVRPData {

    /** The capacity that all vehicles in fruitybun-data.vrp have. */
    public static final int VEHICLE_CAPACITY = 220;

	public static final int VEHICLE_AMOUNT = 20;

    /** The number of nodes in the fruitybun CVRP i.e. the depot and the customers */
    public static final int NUM_NODES = 76; // add the constraint about #vehicles available to use

    /** Return the demand for a given node. */
    public static int getDemand(int node) {
	if (!nodeIsValid(node)) {
	    System.err.println("Error: demand for node " + node + 
			       " was requested from getDemand() but only nodes 1.." + NUM_NODES + " exist");
	    System.exit(-1);
	}	    
	return demand[node];
    }
        
    /** Return the Euclidean distance between the two given nodes */
    public static double getDistance(int node1, int node2) {
	if (!nodeIsValid(node1)) {
	    System.err.println("Error: distance for node " + node1 + 
			       " was requested from getDistance() but only nodes 1.." + NUM_NODES + " exist");
	    System.exit(-1);
	}	    
	
	if (!nodeIsValid(node2)) {
	    System.err.println("Error: distance for node " + node2 + 
			       " was requested from getDistance() but only nodes 1.." + NUM_NODES + " exist");
	    System.exit(-1);
	}	    

	int x1 = coords[node1][X_COORDINATE];
	int y1 = coords[node1][Y_COORDINATE];
	int x2 = coords[node2][X_COORDINATE];
	int y2 = coords[node2][Y_COORDINATE];

	// compute Euclidean distance
	return Math.sqrt(Math.pow((x1-x2),2) + Math.pow((y1-y2),2));

    }    
    
    public static double getPathDistance(int[] path){
    	
    	double dist = 0;
    	
    	for (int i = 0; i < path.length - 1; i++){
    		dist += getDistance(path[i], path[i+1]);
    	}
    	
    	return dist;
    }

    /** Return true if the given node is within the valid range (1..NUM_NODES), false otherwise */
    private static boolean nodeIsValid(int node) {
	if (node < 1 || node > NUM_NODES)
	    return false;
	else
	    return true;
    }
    
    public static final int X_COORDINATE = 0; // x-axis coordinate is dimension 0 in coords[][]
    public static final int Y_COORDINATE = 1; // y-axis coordinate is dimension 1 in coords[][]

    
    // Return the coordinates for rendering
    public static int[][] getCoords(){
    	return coords;
    }

    
    public static int getPathDemand(int[] path){
    	int totalDemand = 0;
    	for(int i = 1; i < path.length; i++){
    		totalDemand += demand[path[i]];
    	}
    	return totalDemand;
    }
    
    // Return whether the path is valid
    public static boolean pathIsValid(int[] path){
    	return getPathDemand(path) <= VEHICLE_CAPACITY;
    }
    
    // Strip the depot from the input [][] and return a single []
    public static int[] stripDepots(int[][] paths){ // flatten all the path in this population 'paths'
    	
    	int[] chromosome = new int[NUM_NODES - 1];// !! +VEHICLE_AMOUNT-1
    	int k = 0;
    	for(int i = 0; i < paths.length; i++){
    		if(paths[i] == null) break;// recall that we create paths as new int[76][], but we may not use so much in practice

    		for(int j = 1; j < paths[i].length - 1; j++){
				chromosome[k] = paths[i][j];
				k++;
    		}
//			// add depot
//			chromosome[k] = 1;
    	}
    	
    	return chromosome;
    }
    
    // 2-dimensional array with the coordinates of each node in fruitybun-data.vrp. 
    // coords[0] is a dummy entry which is not used. Node 1 is at coords[1], node 2 is at coords[2] and so on.
    // A more Object-Oriented solution would have been to create coordinate objects but that may be overkill.
    private static int [][] coords = new int[][] 
	{{-1, -1}, // dummy entry to make index of array match indexing of nodes in fruitybun-data.vrp
	 {40, 40}, // the coordinates of node 1 (the depot)
	 {22, 22}, // the coordinates of node 2 ...
	 {36, 26},
	 {21, 45},
	 {45, 35},
	 {55, 20},
	 {33, 34},
	 {50, 50},
	 {55, 45},
	 {26, 59}, // node 10
	 {40, 66},
	 {55, 65},
	 {35, 51},
	 {62, 35},
	 {62, 57},
	 {62, 24},
	 {21, 36},
	 {33, 44},
	 {9, 56},
	 {62, 48}, // node 20
	 {66, 14},
	 {44, 13},
	 {26, 13},
	 {11, 28},
	 {7, 43},
	 {17, 64},
	 {41, 46},
	 {55, 34},
	 {35, 16},
	 {52, 26}, // node 30
	 {43, 26},
	 {31, 76},
	 {22, 53},
	 {26, 29},
	 {50, 40},
	 {55, 50},
	 {54, 10},
	 {60, 15},
	 {47, 66},
	 {30, 60}, // node 40
	 {30, 50},
	 {12, 17},
	 {15, 14},
	 {16, 19},
	 {21, 48},
	 {50, 30},
	 {51, 42},
	 {50, 15},
	 {48, 21},
	 {12, 38}, // node 50
	 {15, 56},
	 {29, 39},
	 {54, 38},
	 {55, 57},
	 {67, 41},
	 {10, 70},
	 {6, 25},
	 {65, 27},
	 {40, 60},
	 {70, 64}, // node 60
	 {64, 4},
	 {36, 6},
	 {30, 20},
	 {20, 30},
	 {15, 5},
	 {50, 70},
	 {57, 72},
	 {45, 42},
	 {38, 33},
	 {50, 4},  // node 70
	 {66, 8},
	 {59, 5},
	 {35, 60},
	 {27, 24},
	 {40, 20},
	 {40, 37}};// node 76
    
    private static int[] demand = new int[]
	{9999999,  // dummy entry to make index of array match indexing of nodes in fruitybun-data.vrp
	 0,  // node 1
	 18, // node 2
	 26, // node 3
	 11, // node 4
	 30, // node 5
	 21, // node 6
	 19, // node 7
	 15, // node 8
	 16, // node 9
	 29, // node 10
	 26, // node 11
	 37, // node 12
	 16, // node 13
	 12, // node 14
	 31, // node 15
	 8,  // node 16
	 19, // node 17
	 20, // node 18
	 13, // node 19
	 15, // node 20
	 22, // node 21
	 28, // node 22
	 12, // node 23
	 6,  // node 24
	 27, // node 25
	 14, // node 26
	 18, // node 27
	 17, // node 28
	 29, // node 29
	 13, // node 30
	 22, // node 31
	 25, // node 32
	 28, // node 33
	 27, // node 34
	 19, // node 35
	 10, // node 36
	 12, // node 37
	 14, // node 38
	 24, // node 39
	 16, // node 40
	 33, // node 41
	 15, // node 42
	 11, // node 43
	 18, // node 44
	 17, // node 45
	 21, // node 46
	 27, // node 47
	 19, // node 48
	 20, // node 49
	 5,  // node 50
	 22, // node 51
	 12, // node 52
	 19, // node 53
	 22, // node 54
	 16, // node 55
	 7,  // node 56
	 26, // node 57
	 14, // node 58
	 21, // node 59
	 24, // node 60
	 13, // node 61
	 15, // node 62
	 18, // node 63
	 11, // node 64
	 28, // node 65
	 9,  // node 66
	 37, // node 67
	 30, // node 68
	 10, // node 69
	 8,  // node 70
	 11, // node 71
	 3,  // node 72
	 1,  // node 73
	 6,  // node 74
	 10, // node 75
	 20};// node 76    

}
package CVRP.algorithms;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Random;

import CVRP.CVRPData;

public abstract class Algorithm {
	
	protected ArrayList<Double> weights = new ArrayList<Double>();
	protected ArrayList<int[][]> chromosomes = new ArrayList<int[][]>();
	protected ArrayList<Score> scores = new ArrayList<Score>();

	// Private method for converting arraylist<Integer> to int[]
	protected static int[] convertIntegers(List<Integer> integers)	{
	    int[] ret = new int[integers.size()];
	    Iterator<Integer> iterator = integers.iterator();
	    for (int i = 0; i < ret.length; i++)
	    {
	        ret[i] = iterator.next().intValue();
	    }
	    return ret;
	}
	
	private static double[] convertDoubles(List<Double> doubles)	{
	    double[] ret = new double[doubles.size()];
	    Iterator<Double> iterator = doubles.iterator();
	    for (int i = 0; i < ret.length; i++)
	    {
	        ret[i] = iterator.next().doubleValue();
	    }
	    return ret;
	}
	
	// Abstract method for path calculation
	// Must be overriden by sub classes
	// This method should store on each iteration the best weight path 
	// it has achieved in the weights arraylist
	public abstract void run(int iterations);
	
	// Abstract method for returning the name of the algorithm
	public abstract String getName();
	
	// Randomise trucks
	public void randomise(){// randomly generate 2000 populations
		for(int j = 0; j < 2000; j++){
			int[][] paths = new int[76][];
			ArrayList<Integer> nodes = new ArrayList<Integer>();
			for(int i = 2; i < CVRPData.getCoords().length; i++){
				nodes.add(new Integer(i));
			}
			ArrayList<Integer> path = new ArrayList<Integer>();// new path
			path.add(new Integer(1)); // starts with Depot1
			Random rand = new Random();
			int pos = 0;
			while(CVRPData.pathIsValid(convertIntegers(path)) && nodes.size() > 0){
				// Choose a random number from the ArrayList
				int getNodeVal = rand.nextInt(nodes.size());
				//System.out.println(getNodeVal);
				Integer i = nodes.get(getNodeVal);
				path.add(i);
				if(CVRPData.pathIsValid(convertIntegers(path))){
					// The path is valid, so we need to remove the node from the set
					nodes.remove(getNodeVal);//
				} else {
					path.remove(path.size() - 1); // Remove the last item
					path.add(new Integer(1));
					paths[pos++] = convertIntegers(path);
					
					path = new ArrayList<Integer>();
					path.add(new Integer(1));
				}
			}
				
			// Store the last path as well
			path.add(new Integer(1));
			paths[pos++] = convertIntegers(path);
			
			chromosomes.add(paths);
		}
	}
	
	// Return the scores arraylist
	public ArrayList<Score> getScores(){
		return scores;
	}
	
	public void addScore(double best, double mean, double median){
		scores.add(new Score(best, mean, median));
	}
	
	// Return the ArrayList of Chromosomes
	public ArrayList<int[][]> getChromosomes(){
		return chromosomes;
	}
	

	public class Score{
		public double best;
		public double mean;
		public double median;
		
		public Score(double best, double mean, double median){
			this.best = best;
			this.mean = mean;
			this.median = median;
		}
	}
	
}

package CVRP.algorithms;

import java.util.ArrayList;
import java.util.Random;

import CVRP.CVRPData;
import CVRP.LimitedPriorityQueue;

public class SimpleGA extends Algorithm {

	private final double probability = 0.002;
	private final double zeroDeltaAddition = 0.00015;
	private final int queueLimit = 222;

	private int zeroDeltaIterations = 1;
	private double prevWeight;

	private int[][] bestPath = generateRandomPath(); // initial population

	// Run the genetic algorithm to improve the results
	@Override
	public void run(int iterations) {// at most 'iteration' iterations
		// Do iterations
		for (int i = 0; i < iterations; i++) {
			// Find the best 5 paths of the generated paths

			LimitedPriorityQueue lpq = new LimitedPriorityQueue(queueLimit,// limit size of lpq, by default 222 // keep 222 best populations
					new Double(1));

			// shortestPathLength.
			// in main func, we've already called randomise(), so getChromosomes will return 2000 feasible populations as initial ones
			ArrayList<int[][]> chromosomes = getChromosomes();// list of populations, one population means s feasible solution
			// compute their fitness and push them into lpq, and then lpq will sort out the best 222 populations  among them
			for (int j = 0; j < chromosomes.size(); j++) {
				double length = fitness(chromosomes.get(j));
				lpq.push(j, new Double(length));// path j , its fitness // the smaller fitness, the better
			}
			if (i % 1000 == 0) { // print the fitness of the current population every 1000 iterations
				lpq.printArray(i);
				System.out.println("Best path: " + fitness(bestPath));
			}

			int[] indices = lpq.getIndices();// indices of populations sorted by key 'fitness'

			// Cross the values over to form new paths
			pmx(indices);

			if (fitness(chromosomes.get(indices[0])) < fitness(bestPath))
				bestPath = chromosomes.get(indices[0]);// best population from LimitedPriorityQueue
			
			// If iterations > 1000 then we keep the first 2 and scrap the rest.
			if (zeroDeltaIterations == 5000) {
				// If we've had 10,000 iterations with no change. Scrap all
				// (keep the best?)
				// We're probably stuck in a local minima

				randomise();
				zeroDeltaIterations = 0;
			} else if (zeroDeltaIterations % 300 == 0 && zeroDeltaIterations >= 300) {
				// We've probably hit a local minima, so generate a lot more
				// random ones
				int[][] pathA = chromosomes.get(indices[0]);// keep only the best one and generate new ones
				chromosomes.clear();
				chromosomes.add(pathA);
				for (int k = 0; k < 200; k++) {
					chromosomes.add(generateRandomPath());
				}
			}

			double delta = fitness(chromosomes.get(indices[0])) - prevWeight;
			if (Math.abs(delta) < 0.2) {
				zeroDeltaIterations++;
			} else {
				zeroDeltaIterations = 0;
			}

			prevWeight = fitness(chromosomes.get(indices[0]));// record the best fitness at the current iteration
			weights.add(new Double(fitness(bestPath)));
		}

	}

	public int[][] getBestPath() {
		return bestPath;
	}

	public void printBestPath(){// [{path1},{path2},...]
		String s = "[";
		int vehi=0;
		for(int[] path : bestPath){
			if(path == null){
				s = s.substring(0, s.length() - 1);// drops the last ','
				break;
			}
			s = s.concat("{");
			for(int i = 0; i < path.length; i++){
				s = s.concat(String.valueOf(path[i])); // append this path into s
				if(i < path.length - 1) s = s.concat(",");
			}
			s = s.concat("},\n");

			vehi++;
		}
		s = s.concat("]\t "+vehi);
		
		System.out.println(s);
	}

	private int[][] generateRandomPath() { // generate feasiable paths
		int[][] paths = new int[76][];// create 76 paths for 76 nodes, but we don't need so much in practice
		ArrayList<Integer> nodes = new ArrayList<Integer>();
		for (int i = 2; i < CVRPData.getCoords().length; i++) {
			nodes.add(new Integer(i));
		}
		ArrayList<Integer> path = new ArrayList<Integer>();
		path.add(new Integer(1)); // start with Depot 1
		Random rand = new Random();// random generator
		int pos = 0;
		while (CVRPData.pathIsValid(convertIntegers(path)) && nodes.size() > 0) {
			// Choose a random number from the ArrayList
			int getNodeVal = rand.nextInt(nodes.size());
			// System.out.println(getNodeVal);
			Integer i = nodes.get(getNodeVal);
			path.add(i);
			if (CVRPData.pathIsValid(convertIntegers(path))) {
				// The path is valid, so we need to remove the node from the set
				nodes.remove(getNodeVal);// that is, nodes.pop
			} else {
				path.remove(path.size() - 1); // Remove the last item
				path.add(new Integer(1));// end up with Depot 1
				paths[pos++] = convertIntegers(path);// paths are 2D array

				path = new ArrayList<Integer>();
				path.add(new Integer(1));// start with Depot 1
			}
		}

		// Store the last path as well
		path.add(new Integer(1));
		paths[pos++] = convertIntegers(path);

		return paths;
	}

	private int[] swap(int a, int b, int[] chromosome) { // swap two values, a and b, on chromosome
		// Find the position of a and b in each chromosome
		int aPos = 0, bPos = 0;
		for (int i = 0; i < chromosome.length; i++) {
			if (chromosome[i] == a)
				aPos = i;
			if (chromosome[i] == b)
				bPos = i;
		}
		// Swap the values
		int tmp = chromosome[aPos];
		chromosome[aPos] = chromosome[bPos];
		chromosome[bPos] = tmp;
		// Return the new chromosome
		return chromosome;
	}

	private void pmx(int[] indices) {
		// record the currently best 10 individuals and use them to generate new individuals
		// and then return the new population made up from new individuals

		// Create a new oldchromosomes object to store the current ones
		ArrayList<int[][]> oldChromosomes = new ArrayList<int[][]>();

		for (int j = 0; j < indices.length && j < 10; j++) { //at most the first 10 best populations remain
			oldChromosomes.add(chromosomes.get(indices[j]));
		}
		// Reinitialise the chromosome list
		// record newly generated individuals
		chromosomes = new ArrayList<int[][]>();

		ArrayList<int[]> tmpPaths = new ArrayList<int[]>();// temporary list of flatten populations

		//put those old populations in oldChromosome in tmpPaths
		for (int i = 0; i < oldChromosomes.size(); i++) {
			int[] strippedPath = CVRPData.stripDepots(oldChromosomes.get(i));// flatten the ith population
			tmpPaths.add(strippedPath);
		}
		// crossover each of the 5 with each other to give 25
		Random rnd = new Random();

		for (int i = 0; i < tmpPaths.size(); i++) { // Population i V.S Population j
			for (int j = 0; j < tmpPaths.size(); j++) {
				// Cross the 2 indices over
				int start = rnd.nextInt() % (CVRPData.NUM_NODES - 2);
				int end = rnd.nextInt() % (CVRPData.NUM_NODES - 2);
				if (start < 0)
					start = start * -1;
				if (end < 0)
					end = end * -1;
				while (start == end)
					end = rnd.nextInt() & CVRPData.NUM_NODES - 1;// a random int no more than CVRPData.NUM_NODES - 1
				if (start > end) {
					// We need to swap them
					int tmp = start;
					start = end;
					end = tmp;
				}
				// now, we can be sure that start<end
				int[] newPathA = tmpPaths.get(i);// Population i
				int[] newPathB = tmpPaths.get(j); //Population j

				// Between start and end we need to swap the values
				for (int k = start; k < end; k++) {
					int a = tmpPaths.get(i)[k];
					int b = tmpPaths.get(j)[k];
					newPathA = swap(a, b, newPathA);
					newPathB = swap(a, b, newPathB);
				}

				// Randomly apply a mutation
				newPathA = mutate(newPathA);
				newPathB = mutate(newPathB);

				chromosomes.add(makeValidPaths(newPathA));// from a flatten population, generate a series of paths
				chromosomes.add(makeValidPaths(newPathB));
			}
		}
	}

	private int[] mutate(int[] path) {// operator

		Random rnd = new Random();

		for (int i = 0; i < path.length; i++) {
			if (rnd.nextDouble() < (probability + (zeroDeltaIterations % 1000)
					* zeroDeltaAddition)) {
				// We are swapping two values, path[i] and path[swapWith]
				int swapWith = rnd.nextInt() % (CVRPData.NUM_NODES - 2) + 1;
				if (swapWith < 0)
					swapWith = swapWith * -1;
				path = swap(path[i], path[swapWith], path);
			}
		}

		return path;
	}

	private int[][] makeValidPaths(int[] inpath) {
		// from inpath, a flatten population, make valid paths and add them into paths, that is, the current population
		//!! skip that depot
		ArrayList<Integer> nodes = new ArrayList<Integer>();
		for (int i = 0; i < inpath.length; i++) {
//			if(inpath[i]==1){// ! newly add
//				continue;
//			}
			nodes.add(new Integer(inpath[i]));
		}

		int[][] paths = new int[76][];// at most 76 vehicles are needed

		ArrayList<Integer> path = new ArrayList<Integer>();
		path.add(new Integer(1));
		int j = 0;// ?? why add this variable
		int pos = 0;
		while (CVRPData.pathIsValid(convertIntegers(path)) && nodes.size() > 0) {
			Integer i = nodes.get(0);
			path.add(i);
			if (CVRPData.pathIsValid(convertIntegers(path))) {
				// The path is valid, so we need to remove the node from the set
				nodes.remove(0);// we take this node away
				j++;
			} else {
				path.remove(path.size() - 1); // Remove the last item, which is that newly added node
				path.add(new Integer(1));// end this path
				paths[pos++] = convertIntegers(path);// and put this path in `paths`
				// prepare  for the next iteration
				path = new ArrayList<Integer>();// create a new path
				path.add(new Integer(1));
			}
		}

		// Store the last path as well
		path.add(new Integer(1));// end this last path
		paths[pos++] = convertIntegers(path);

		return paths;
	}

	// Calculate the fitness of this current population, that is, a given paths_array
	private double fitness(int[][] paths) {// input several paths
		// We want to minimise the path weight

		double weight = 0.0;
		int vehi=0;
		int clientNum=0;
		for (int[] path : paths) {
			if (path == null){
				if(vehi<=CVRPData.VEHICLE_AMOUNT){
					return weight; // we want the total distance smaller
				}else{
					return -clientNum;// we want the amount of clients served larger
				}
//				return weight;
			}
			weight += CVRPData.getPathDistance(path); // !! add max #clientsServed
			vehi++;
			clientNum+=path.length-2; // except two depots
		}
		if(vehi<=CVRPData.VEHICLE_AMOUNT){
			return weight; // we want the total distance smaller
		}else{
			return -clientNum;// we want the amount of clients served larger
		}
//		return weight;
	}

	@Override
	public String getName() {
		return "SimpleGA-" + (int)fitness(bestPath);
	}

}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值