Estructuras de datos y Algoritmos II (EDA II). 2º Grado en Ingeniería Informática. Universidad de Almería

Version curso.2022

Plantilla de implementación en Java

A continuación tenéis un esquema o plantlla de la implementación del algoritmo branch-and-bound para el problema del TSP en un grafo representado por un mapa de adyacencia. Se trata de que completéis los bloques que faltan, marcados como comentarios dentro del código.

	// return the minimum value of the edges
  	public double minimumEdgeValue() {
  		double minimum = Double.MAX_VALUE;
  		// Devuelve el menor valor de arista del grafo
  		// Dos bucles 'for' anidados


  		return minimum;
  	}

  	// TSP - BaB - Best-First
	public ArrayList<Vertex> TSPBaB(Vertex source) {
		TreeMap<Vertex, Double> neighborMap = adjacencyMap.get(source);
		if (neighborMap == null)
			return null;

		minEdgeValue = minimumEdgeValue();

		// Constructor de clase PathNode
		PathNode firstNode = new PathNode(source);

		PriorityQueue<PathNode> priorityQueue = new PriorityQueue<>();

		priorityQueue.add(firstNode);

		shortestCircuit = null;
		double bestCost = Double.MAX_VALUE;

		while(priorityQueue.size() > 0) {

			// Y (PathNode) = menorElemento de la cola de prioridad en funcion de 'estimatedCost'
			PathNode Y = priorityQueue.poll();

			if (Y.getEstimatedCost() >= bestCost)
                break;
			else {
				Vertex from = Y.lastVertexRes();
				// Si el numero de vertices visitados es n
				// y existe una arista que conecte 'from' con source
				if ((Y.getVisitedVertices() == numberOfVertices()) &&
					(containsEdge(from, source))) {
					// Actualizar 'res' en Y añadiendo el vertice 'source'
					// Actualizar 'totalCost' en Y con Y.totalCost + weight(from, source)

					if (Y.getTotalCost() < bestCost) {
						// Actualizar 'bestCost', 'shortestDistanceCircuit' y 'shortestCircuit'

					}
				}
				else {
					// Iterar para todos los vertices adyacentes a from,
					// a cada vertice lo denominamos 'to'

						if (vertice 'to' todavia no ha sido visitado en Y) { // hacer uso de la funcion 'isVertexVisited(vertex)' de PathNode


							PathNode X = new PathNode(Y); // Uso de constructor copia
							// Anadir 'to' a 'res' en X
							// Incrementar en 1 los vertices visitados en X
							// Actualizar 'totalCost' en X con Y.totalCost + weight(from, to)

							// Actualizar 'estimatedCost' en X con X.totalCost + ((nVertices - X.getVisitedVertices() + 1) * minEdgeValue)


							if (X.getEstimatedCost() < bestCost) {
								priorityQueue.add(X);
							}
						}
					}
				}
			}
		}

		return shortestCircuit;
	}

Otras clases necesarias

Además, necesitaréis la clase PathNode.java

protected class PathNode implements Comparable<PathNode> {
    private ArrayList<Vertex> res; // result
    private int visitedVertices; // The number of the visited vertices
    private double totalCost; // The total cost of the path taken so far
    private double estimatedCost; // Representing the lower bound of this state. * Priority

    PathNode(Vertex vertexToVisit) {
        res = new ArrayList<Vertex>();
        res.add(vertexToVisit);
        visitedVertices = 1;
        totalCost = 0.0;
        estimatedCost = numberOfVertices() * minEdgeValue;
    }

    PathNode(PathNode parentPathNode) {
        // Constructor copia
    }

    @Override
    public int compareTo(PathNode p) {
        // El criterio de comparacion es 'estimatedCost' que se correponde con la prioridad
    }

    public ArrayList<Vertex> getRes() {
        return res;
    }

    public void addVertexRes(Vertex v) {
        this.res.add(v);
    }

    public Vertex lastVertexRes() {
        // Devuelve el ultimo vertice que se ha anadido al camino (ultimo elemento de 'res')

	}

    public boolean isVertexVisited(Vertex v) {
    	// Se ha visitado el vertice v si esta actualmente en 'res'. Una sola linea

	}

    public int getVisitedVertices() {
        return visitedVertices;
    }

    public void setVisitedVertices(int visitedVertices) {
        this.visitedVertices = visitedVertices;
    }

    public double getTotalCost() {
        return totalCost;
    }

    public void setTotalCost(double totalCost) {
        this.totalCost = totalCost;
    }

    public double getEstimatedCost() {
        return estimatedCost;
    }

    public void setEstimatedCost(double estimatedCost) {
        this.estimatedCost = estimatedCost;
    }
}