Проблема оптимизации колонии муравьев

1

У меня есть эта проблема: постройте башню, образованную n цветными кубами с заданной стороной. Не может быть куба с небольшой стороной на кубе с большей стороной, и ни один из двух соседних кубов не может быть одного цвета. Я пытаюсь решить это, используя Ant Colony Optimization. Беда в том, что у меня с ней есть то, что я не знаю, как выбрать следующий куб, чтобы переместить муравей и оставить на нем феромон.

Example: For the following cubes:
C1 - side = 5, Color = Red
C2 - side = 2, Color = Green
C3 - side = 10, Color = Blue
C4 - side = 1, Color = Red
the solution would be: C3, C1, C2, C4

This is what I've done so far:

Класс Ant:

     public class Ant {

        private int[] visited;
        private int size;

        public Ant(int size) {
            this.size = size;
            this.visited = new int[size];
        }

        public void clearVisited(){
            for(int i=0; i < size; i++){
                visited[i] = -1;
            }
        }

        public void visit(int index, int cube) {
            visited[index] = cube;
        }

        public int visited(int index){
            return visited[index];
        }

        public boolean contains(int cube){
            for(int i=0; i < size; i++){
                if(visited[i] == cube){
                    return true;
                }
            }

            return false;
        }
    }

Класс куба:

    public class Cube {

        private int length;
        private String color;


        public Cube(int length, String color){
            this.length = length;
            this.color = color;
        }

        public Cube(String color){
            this.length = (int)Math.round(Math.random() * 200);
            this.color = color;
        }

        public int getLength(){
            return this.length;
        }

        public String getColor(){
            return this.color;
        }

        public void setLength(int length){
            this.length = length;
        }

        public void setColor(String color){
            this.color = color;
        }

        public String toString(){
            String str = "";
            str += "Cub: l = " + length + ", " + "c = " + color;
            return str;
        }

        public boolean equals(Object o){
            if(o == null){
                return false;
            }

            if(!(o instanceof Cube)){
                return false;
            }

            Cube c = (Cube)o;
            if((c.getColor().equals(this.getColor())) && (c.getLength() == this.getLength())){
                return true;
            }

            return false;
        }
    }

Класс Cube Repository: здесь я храню кубы

    public class CubeRepository {

        private static ArrayList<Cube> availableCubes = new ArrayList<Cube>();

        public static void addCube(Cube cube){
            if(!availableCubes.contains(cube)){
                availableCubes.add(cube);
            }
        }

        public static Cube getCube(int index){
            return availableCubes.get(index);
        }

        public static int getSize(){
            return availableCubes.size();
        }
    }

Алгоритм ACO:

    public class ACO {

        private int nrAnts;
        private int nrCubes;
        private Ant[] ants;
        private int currentIndex;
        private double[] pheromoneTrail;
        private double ph = 1; //pheromon trace on every cube at start
        private int alpha = 1;
        private int beta = 5;
        private int Q = 500;
        private double q0 = 0.01;

        public ACO(int nrAnts, int nrCubes){
            this.nrAnts = nrAnts;
            this.nrCubes = nrCubes;
            ants = new Ant[nrAnts];
            pheromoneTrail = new double[nrCubes];
        }

        public void createAnts(){//creeaza toate furnicile
            currentIndex = 0;
            for(int i=0; i < nrAnts; i++){
                ants[i] = new Ant(nrCubes);
            }
        }

        public Ant getAnt(int index){//return an ant
            return ants[index];
        }

        public void setupPheromoneTrail(){ //sets pheromone trail for every cube at start
            for(int i=0; i < nrCubes; i++){
                pheromoneTrail[i] = ph;
            }
        }

        public void placeAnts(){ //place every ant on a cube
            for(int i=0; i < nrAnts; i++){
                ants[i].visit(currentIndex, (int)(Math.random() * nrCubes));
            }
            currentIndex++;
        }

        public int selectNextCube(Ant ant){
            if(Math.random() < q0){
                int cube = (int)(Math.random() * nrCubes); //pick a random cube
                while(!ant.contains(cube)){
                    if(CubeRepository.getCube(ant.visited(currentIndex-1)).getColor().equals(CubeRepository.getCube(cube).getColor())){
                        cube = (int)(Math.random() * nrCubes);
                    }
                }

                return cube;
            }

            return 1; //I didn't return a proper value
        }

        public void MoveAnts(){ //move every ant on another cube
            while(currentIndex < nrCubes){
                for(int i=0; i < nrAnts; i++){
                    ants[i].visit(currentIndex, selectNextCube(ants[i]));
                }
                currentIndex++;
            }
        }

    }
Теги:
algorithm

1 ответ

1

Не поняв всей программы (слишком много, чтобы быстро ее прочитать и найти ответ): вы можете выбрать случайный куб, который имеет другой цвет, чем предыдущий, с псевдокодом, подобным этому

private static final Random random = new Random(0);
public int selectNextCube(Ant ant)
{
    Cube previousCube = CubeRepository.getCube(ant.visited(currentIndex-1));
    List<Cube> allCubes = obtainAllCubesFromCubeRepository();
    List<Cube> sameColor = obtainAllCubesWithSameColorAs(previousCube); 
    allCubes.removeAll(sameColor);

    // EDIT>>>: You might also need this:
    allCubes.remove(computeAllCubesAlreadyVisitedBy(ant));
    // <<<EDIT: You might also need this:

    int index = random.nextInt(allCubes.size());
    Cube nextCube = allCubes.get(index);
    return indexFor(nextCube);         
}

BTW: Я бы сильно рекомендовал не использовать Math.random(). Он возвращает непредсказуемое случайное значение. Отладка программы, которая включает Math.random(), ужасна. Вместо этого вы должны использовать экземпляр java.lang.Random, как показано в приведенном выше фрагменте. Вы можете вызвать random.nextDouble(), чтобы получить double значения, например, с помощью Math.random(). Кроме того, вы можете вызвать random.nextInt(n) для получения значений int в диапазоне [0, n). Самое главное: когда вы создаете этот экземпляр как new Random(0) он всегда будет возвращать ту же последовательность случайных чисел. Это делает программу предсказуемой и позволяет действительно отлаживать программу. (Если вы хотите "непредсказуемую" последовательность случайных чисел, вы можете создать его как new Random() без случайного семени).

Ещё вопросы

Сообщество Overcoder
Наверх
Меню