Нахождение кратчайшего пути с генетическим алгоритмом - PullRequest
0 голосов
/ 02 июля 2019

Я пытаюсь разработать Java-программу для поиска кратчайшего пути с генетическим алгоритмом в взвешенном графике.У меня возникли трудности в кодировании на основе этого алгоритма.Может кто-нибудь показать мне примеры кодов для этой проблемы.Любой язык в порядке.Любая информация, такая как библиотеки или другая, которая может быть полезна для этой проблемы, тоже подойдет.Самая важная вещь сейчас - это проверить время, чтобы найти кратчайший путь на основе этого алгоритма, и мне нужно выяснить это до наступления срока моего назначения.Так что, если кто-нибудь может мне помочь, пожалуйста.

Я занимался кодированием на основе Java, и у меня есть трудности в основном в процессе перехода и мутации.А также определение фитнес-функции также является проблемой.

1 Ответ

0 голосов
/ 02 июля 2019

Вот пример Java генетического алгоритма кратчайшего пути

package ga;

import java.util.ArrayList;
import java.util.Arrays;

public class GA {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        //computation time
        long start = System.nanoTime();
        //population size
        int populationSize = 30;
        //Number of Cities
        int numCities = 15;
        //Mutation rate
        double mutationRate = 0.05;
        //Crossover Rate
        double crossoverRate = 0.8;
        //Choose File path or if false randomly created Path
        boolean useFile = false;
        //Name the file to be used
        String fileName = "Data.txt";
        //Current Number of Generations
        int numberOfGenerations = 0;
        //Stop Condition
        int stopAt=2500;
        //Population
        Population pop;
        //use GA or Brute Force
        boolean GAuse=true;



        //Selecting File mode or Random Mode
        if (useFile == false) {

            pop = new Population(populationSize, numCities, crossoverRate, mutationRate);

        } else {
            FileReader file = new FileReader(fileName);
            numCities=file.getNumCities();
            crossoverRate=file.getCrossoverRate();
            mutationRate=file.getMutationRate();
            populationSize=file.getCities().length;
            Path p = new Path(file.getNumCities());
            p.setPath(file.getCities());
            pop = new Population(populationSize, numCities, p,crossoverRate ,mutationRate );

        }
        if(GAuse==true){

      //Sorting the population from Finess / Evaluating
        pop.FitnessOrder();

                //Prints each path ID/Cost/Fitness/City order(with coordinates)
         for (int i = 0; i < pop.getPopulation().length; i++) {
            System.out.println("Path ID: "+i+" | Cost: "+pop.getPopulation()[i].getCost()+" | Fitness: "+pop.getPopulation()[i].getFitness()+"%");
            System.out.print("Path is: ");
            for (int j = 0; j < pop.getPopulation()[i].getPath().length; j++) {
                System.out.print(pop.getPopulation()[i].getPath()[j].getId() +"("+pop.getPopulation()[i].getPath()[j].getX()+","+pop.getPopulation()[i].getPath()[j].getY()+")  ");

         }System.out.println("\n -----------------------------------------------------");
        }

      //Start looking for possible solution
        while (numberOfGenerations !=stopAt) {

            //Select / Crossover
            while (pop.Mate() == false);              
            //Mutate
            for (int i = 0; i < pop.getNextGen().length; i++) {
            pop.getNextGen()[i].setPath(pop.Mutation(pop.getNextGen()[i].getPath()));

            }

            //Setting the new Generation to current Generation
            pop.setPopulation(pop.getNextGen());
            pop.setDone(0);
            //Sorting the new population from Finess / Evaluating
            pop.FitnessOrder();
            //Incremente number of Generations
            numberOfGenerations++;
        }


      //Prints out the fitness of each path
        double valor=0;
        for (int i = 0; i < pop.getPopulation().length; i++) {
            valor += pop.getPopulation()[i].getFitness();
            System.out.println("Value of Fitness: "+pop.getPopulation()[i].getFitness()+"%");
        }
        System.out.println("");
        System.out.println("Total Fitness: "+valor+"%");

        System.out.println("\n-----------------------------------------------");


        //Prints each path ID/Cost/Fitness/City order(with coordinates)
         for (int i = 0; i < pop.getPopulation().length; i++) {
            System.out.println("Path ID: "+i+" | Cost: "+pop.getPopulation()[i].getCost()+" | Fitness: "+pop.getPopulation()[i].getFitness()+"%");
            System.out.print("Path is: ");
            for (int j = 0; j < pop.getPopulation()[i].getPath().length; j++) {
                System.out.print(pop.getPopulation()[i].getPath()[j].getId() +"("+pop.getPopulation()[i].getPath()[j].getX()+","+pop.getPopulation()[i].getPath()[j].getY()+")  ");

         }System.out.println("\n -----------------------------------------------------");
        }

        }



        else{//USING BRUTE FORTE METHOD

         FileReader file = new FileReader(fileName);
         ArrayList<City> cities = new ArrayList<City>();

            for (int i = 0; i <file.getNumCities(); i++) {
            cities.add(file.getCities()[i]);
            }           

        ArrayList<City> best = new ArrayList<City>();
        Permutations permu = new Permutations();
        permu.permutations(cities);
            System.out.print("The shortest path is: ");
            for (int i = 0; i < permu.getBest().size(); i++) {
                System.out.print(permu.getBest().get(i).getId()+"("+permu.getBest().get(i).getX()+","+permu.getBest().get(i).getY()+")");
            }
            System.out.println("");
            System.out.println("It would Cost: "+permu.getCost());
        }

        long elapsedTime = System.nanoTime() - start; 
        System.out.println("Algorithm took: "+elapsedTime+" nano seconds to find a solution");
    }



    }
package ga;

import java.util.ArrayList;

public class Permutations {
    private int cost=999999;
    private ArrayList<City> best;



    public void permutations(ArrayList<City> list){
       permutations(null, list, null);
    }

    public int getCost() {
        return cost;
    }

    public void setCost(int cost) {
        this.cost = cost;
    }

    public ArrayList<City> getBest() {
        return best;
    }

    public void setBest(ArrayList<City> best) {
        this.best = best;
    }

    public  ArrayList<City> permutations(ArrayList<City> prefix, ArrayList<City> suffix, ArrayList<ArrayList<City>> output){
       if(prefix == null)
          prefix = new ArrayList<City>();
       if(output == null)
          output = new ArrayList<ArrayList<City>>();
       if(suffix.size() == 1){
          ArrayList<City> newElement = new ArrayList<City>(prefix);
          newElement.addAll(suffix);
          int costNow=cost(newElement);
          if(costNow<this.cost){
              best=newElement;
              this.cost=costNow;
          }
          return best;
       }
       for(int i = 0; i < suffix.size(); i++){
          ArrayList<City> newPrefix = new ArrayList<City>(prefix);
          newPrefix.add(suffix.get(i));
          ArrayList<City> newSuffix = new ArrayList<City>(suffix);
          newSuffix.remove(i);
          permutations(newPrefix,newSuffix,output);
       }



       return best;
    }

    public  int cost(ArrayList<City> path){
       int cost=0;
        int i=0;
        while(i<path.size()-1){
           cost+=path.get(i).distance(path.get(i+1).getX(),path.get(i+1).getY());
            i++;
        }
        cost+=path.get(path.size()-1).distance(path.get(0).getX(), path.get(0).getY());
        return cost;
    }

}
package ga;

import java.util.Random;

public class Path implements Comparable {
    private City [] path;
    private int numCities;
    private int cost;
    private int fitness;

    public Path(int numCities) {
        this.numCities = numCities;
        CreatePath();
        cost =0;
        calculateCost();
        fitness =0;

    }
    public void calculateCost(){
        cost=0;
        int i=0;
        while(i<numCities-1){
           cost+=path[i].distance(path[i+1].getX(),path[i+1].getY());
            i++;
        }
        cost+=path[path.length-1].distance(path[0].getX(), path[0].getY());
    }

    public int getFitness() {
        return fitness;
    }

    public void setFitness(int fitness) {
        this.fitness = fitness;
    }
    public int getCost() {
        return cost;
    }

    public void setCost(int distance) {
        this.cost = distance;
    }
    /* Overload compareTo method */
    public int compareTo(Object obj){
     Path tmp = (Path) obj;
     if(this.cost < tmp.cost){
         return 1;
     }
     else if(this.cost > tmp.cost){
         return -1;
     }
     else{
         return 0;
     }
    }
     public void CreatePath(){
        path= new City[numCities];
        for (int i = 0; i < path.length; i++) {
            path[i]=new City(i,RandomNum(1, 99),RandomNum(1, 99));            
        }
    }

    public int RandomNum(int min, int max){
        return min+ (new Random()).nextInt(max-min);        
    }

    public City[] getPath() {
        return path;
    }

    public void setPath(City[] path) {
        this.path = path;
        calculateCost();
    }

    public int getNumCities() {
        return numCities;
    }

    public void setNumCities(int numCities) {
        this.numCities = numCities;
    }

}
package ga;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.util.StringTokenizer;

public class FileReader {

    private int numCities;
    private double mutationRate;
    private City[] cities;
    private int curLine;
    private StringTokenizer st;
    private int arrayCount;
    private int x, y;
    private double crossoverRate;
    private String fileName;

    public FileReader(String fileName) {
        numCities = 0;
        mutationRate = 0;
        City[] cities = new City[0];
        curLine = 1;
        arrayCount = 0;        
        this.fileName=fileName;
        read();
    }

    public int getNumCities() {
        return numCities;
    }

    public void setNumCities(int numCities) {
        this.numCities = numCities;
    }

    public double getMutationRate() {
        return mutationRate;
    }

    public void setMutationRate(double mutationRate) {
        this.mutationRate = mutationRate;
    }

    public City[] getCities() {
        return cities;
    }

    public void setCities(City[] cities) {
        this.cities = cities;
    }

    public int getCurLine() {
        return curLine;
    }

    public void setCurLine(int curLine) {
        this.curLine = curLine;
    }

    public StringTokenizer getSt() {
        return st;
    }

    public void setSt(StringTokenizer st) {
        this.st = st;
    }

    public int getArrayCount() {
        return arrayCount;
    }

    public void setArrayCount(int arrayCount) {
        this.arrayCount = arrayCount;
    }

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }

    public void read() {

        try {
            BufferedReader in = new BufferedReader(new java.io.FileReader("./"+fileName));
            String line;
            try {
                while ((line = in.readLine()) != null) {
                    if (curLine == 1) {
                        st = new StringTokenizer(line, "=");
                        st.nextToken();
                        numCities = Integer.parseInt(st.nextToken());
                        cities = new City[numCities];
                    } else if (curLine == 2) {
                        st = new StringTokenizer(line, "=");
                        st.nextToken();
                        mutationRate = Double.parseDouble(st.nextToken());
                    }else if(curLine==3){
                        st = new StringTokenizer(line, "=");
                        st.nextToken();
                       crossoverRate = Double.parseDouble(st.nextToken());
                    }
                    else {
                        st = new StringTokenizer(line, "|");
                        st.nextToken();
                        String a = st.nextToken();
                        StringTokenizer stmp = new StringTokenizer(a, "=");
                        stmp.nextToken();
                        x = Integer.parseInt(stmp.nextToken());
                        String l = st.nextToken();
                        stmp = new StringTokenizer(l, "=");
                        stmp.nextToken();
                        y = Integer.parseInt(stmp.nextToken());

                        cities[arrayCount] = new City(arrayCount, x, y);
                        arrayCount++;
                    }
                    curLine++;

                }
            } catch (Exception e) {
            }

        } catch (FileNotFoundException e) {
            System.out.println("File not found!!");
        }
    }

    public double getCrossoverRate() {
        return crossoverRate;
    }

    public void setCrossoverRate(double crossoverRate) {
        this.crossoverRate = crossoverRate;
    }
}
package ga;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Random;

public class Population {

    private int populationSize;
    private int numCities;
    private Path[] population;
    private double crossoverRate;
    private City[] child1;
    private City[] child2;
    private double mutationRate;
    private Path[] nextGen;
    private int done;

    public Population(int populationSize, int numCities, double crossoverRage, double mutationRate) {
        this.populationSize = populationSize;
        this.numCities = numCities;
        population = new Path[populationSize];
        this.crossoverRate = crossoverRage;
        this.mutationRate = mutationRate;
        this.nextGen = new Path[populationSize];
        Path p = new Path(numCities);
        done = 0;
        CreatePopulation(p);

    }

    public Population(int populationSize, int numCities, Path path, double crossoverRage, double mutationRate) {
        this.populationSize = populationSize;
        this.numCities = numCities;
        this.crossoverRate = crossoverRage;
        population = new Path[populationSize];
        this.mutationRate = mutationRate;
        this.nextGen = new Path[populationSize];
        done = 0;
        CreatePopulation(path);

    }

    public void CreatePopulation(Path p) {
        int i = 0;

        while (i < populationSize) {
            City[] tmpCity = new City[numCities];
            for (int j = 0; j < tmpCity.length; j++) {
                tmpCity[j] = p.getPath()[j];
            }
            Collections.shuffle(Arrays.asList(tmpCity));
            Path tmpPath = new Path(numCities);
            tmpPath.setPath(tmpCity);
            population[i] = tmpPath;
            i++;
        }
    }

    public int SelectParent() {
        int total = 0;
        //Selecting parents
        int totalCost = calculateTotalFitness();

        int fit = RandomNum(0, totalCost);
        int value = 0;
        for (int i = 0; i < population.length; i++) {
            value += population[i].getFitness();
            if (fit <= value) {
                return i;
            }//if(fit<=value){
        }
        return -1;

    }

    public boolean Mate() {
        //Generate a random number to check if the parents cross
        int check = RandomNum(0, 100);
        int parent1 = SelectParent();
        int parent2 = SelectParent();
        while (parent1 == parent2) {
            parent2 = SelectParent();
        }

        //check if there is going to be a crossover
        if (check <= (crossoverRate * 100)) {

            int crossoverPoint = RandomNum(0, population[parent1].getPath().length - 1);
            child1 = new City[numCities];
            child2 = new City[numCities];

            //crossing over
            for (int i = 0; i < crossoverPoint; i++) {
                child1[i] = population[parent2].getPath()[i];
                child2[i] = population[parent1].getPath()[i];
            }
            for (int i = crossoverPoint; i < numCities; i++) {
                child1[i] = population[parent1].getPath()[i];
                child2[i] = population[parent2].getPath()[i];
            }


            //Rearrange childs considering city repetition
            int cityChild1;
            int cityChild2;
            ArrayList<Integer> list1 = new ArrayList<Integer>();
            ArrayList<Integer> list2 = new ArrayList<Integer>();

            for (int i = 0; i < crossoverPoint; i++) {
                cityChild1 = child1[i].getId();
                cityChild2 = child2[i].getId();

                //Get the positions of repeated values
                for (int j = crossoverPoint; j < numCities; j++) {
                    if (cityChild1 == child1[j].getId()) {
                        list1.add(j);
                    }
                    if (cityChild2 == child2[j].getId()) {
                        list2.add(j);
                    }
                }
            }

            //Find the missing values
            for (int i = 0; i < numCities; i++) {
                boolean found = false;
                //Fixing Child1
                for (int j = 0; j < numCities; j++) {
                    if (population[parent2].getPath()[i] == child1[j]) {
                        found = true;
                        break;
                    }
                }
                if (found == false) {
                    child1[list1.remove(list1.size() - 1)] = population[parent2].getPath()[i];
                }
                found = false;
                //Fixing Child2
                for (int j = 0; j < numCities; j++) {
                    if (population[parent1].getPath()[i] == child2[j]) {
                        found = true;
                        break;
                    }
                }
                if (found == false) {
                    child2[list2.remove(list2.size() - 1)] = population[parent1].getPath()[i];
                }
            }

//                     System.out.print("Parent 1: ");
//            for (int i = 0; i < numCities; i++) {
//                if (i == crossoverPoint) {
//                    System.out.print("| ");
//                }
//                System.out.print(population[parent1].getPath()[i].getId() + " ");
//            }
//            System.out.print("\nParent 2: ");
//            for (int i = 0; i < numCities; i++) {
//                if (i == crossoverPoint) {
//                    System.out.print("| ");
//                }
//                System.out.print(population[parent2].getPath()[i].getId() + " ");
//            }
//            System.out.print("\nChild 1: ");
//            for (int i = 0; i < numCities; i++) {
//                if (i == crossoverPoint) {
//                    System.out.print("| ");
//                }
//                System.out.print(child1[i].getId() + " ");
//            }
//            System.out.print("\nChild 2: ");
//            for (int i = 0; i < numCities; i++) {
//                if (i == crossoverPoint) {
//                    System.out.print("| ");
//                }
//                System.out.print(child2[i].getId() + " ");
//            }
//            System.out.println("");
//
//            //Repeated Values
//            for (int i = 0; i < list1.size(); i++) {
//                System.out.print(list1.get(i) + " ");
//            }
//            System.out.println("");
//            for (int i = 0; i < list2.size(); i++) {
//                System.out.print(list2.get(i) + " ");
//            }


            if (AddToGenerationCheckFull(child1, child2) == false) {
                return false;
            } else {
                return true;
            }


        } else {

            if (AddToGenerationCheckFull(population[parent1].getPath(), population[parent1].getPath()) == false) {
                return false;
            } else {
                return true;
            }
        }
    }

    public int getDone() {
        return done;
    }

    public void setDone(int done) {
        this.done = done;
    }

    public boolean AddToGenerationCheckFull(City[] child1, City[] child2) {
        if (done == populationSize) {
            return true;
        }
        Path newGenChild1 = new Path(numCities);
        Path newGenChild2 = new Path(numCities);
        newGenChild1.setPath(child1);
        newGenChild2.setPath(child2);
        if (done < populationSize - 2) {
            this.nextGen[done] = newGenChild1;
            this.nextGen[done + 1] = newGenChild2;
            this.done += 2;
            return false;
        } else if (done == populationSize - 2) {
            this.nextGen[done] = newGenChild1;
            this.nextGen[done + 1] = newGenChild2;
            done += 2;
            return true;
        } else {
            this.nextGen[done] = newGenChild1;
            done += 1;
            return true;
        }

    }

    public Path[] getNextGen() {
        return nextGen;
    }

    public void setNextGen(Path[] nextGen) {
        this.nextGen = nextGen;
    }

    public City[] Mutation(City[] child) {
        int check = RandomNum(0, 100);

        //Checks if its going to mutate
        if (check <= (mutationRate * 100)) {

            //finds the 2 cities that "mutate"
            int point1 = RandomNum(0, numCities - 1);
            int point2 = RandomNum(0, numCities - 1);
            while (point2 == point1) {
                point2 = RandomNum(0, numCities - 1);
            }

            //Cities are switched as result of mutation
            City city1 = child[point1];
            City city2 = child[point2];
            child[point1] = city2;
            child[point2] = city1;

        }
        return child;
    }

    public int RandomNum(int min, int max) {
        return min + (new Random()).nextInt(max - min);
    }

    public void FitnessOrder() {
        Arrays.sort(population);
        // double cost = calculateTotalCost();
        for (int i = 0; i < population.length; i++) {
//            double total = cost - population[i].getCost();
//            double fitness = (total * 100) / cost; 
//            fitness = 100 - fitness;
//            population[i].setFitness(fitness);
            int lol = 100000 / (population[i].getCost() + 1);
            population[i].setFitness(lol);
            //       System.out.println("Total: "+total + " "+" Cost: "+cost+" "+" Fitness: "+fitness+"%" );
        }

    }

    public int calculateTotalFitness() {
        int cost = 0;
        for (int i = 0; i < population.length; i++) {
            cost += population[i].getFitness();
        }
        return cost;
    }

    public double getCrossoverRate() {
        return crossoverRate;
    }

    public void setCrossoverRate(double crossoverRage) {
        this.crossoverRate = crossoverRage;
    }

    public Path[] getPopulation() {
        return population;
    }

    public void setPopulation(Path[] population) {
        this.population = population;
    }

    public int getPopulationSize() {
        return populationSize;
    }

    public void setPopulationSize(int populationSize) {
        this.populationSize = populationSize;
    }

    public int getNumCities() {
        return numCities;
    }

    public void setNumCities(int numCities) {
        this.numCities = numCities;
    }
}
package ga;

public class City {
    private int x;
    private int y;
    private int id;

    public City(int id,int x, int y){
        this.x=x;
        this.y=y;
        this.id=id;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }
    public int distance(int xOther,int yOther){
        return (int) Math.sqrt(((this.x-xOther)*(this.x-xOther))+((this.y-yOther)*(this.y-yOther)));
    }
}
...