All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opentcs.strategies.basic.routing.jgrapht.AbstractModelGraphMapper Maven / Gradle / Ivy

/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.routing.jgrapht;

import static java.util.Objects.requireNonNull;

import jakarta.annotation.Nonnull;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.jgrapht.Graph;
import org.jgrapht.graph.DirectedWeightedMultigraph;
import org.opentcs.components.kernel.routing.Edge;
import org.opentcs.data.model.Path;
import org.opentcs.data.model.Point;
import org.opentcs.data.model.Vehicle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Mapper to translate a collection of points and paths into a weighted graph.
 */
public abstract class AbstractModelGraphMapper
    implements
      ModelGraphMapper {

  private static final Logger LOG = LoggerFactory.getLogger(AbstractModelGraphMapper.class);
  private final PointVertexMapper pointVertexMapper;
  private final PathEdgeMapper pathEdgeMapper;

  /**
   * Creates a new instance.
   *
   * @param pointVertexMapper Translates a collection of points to vertices.
   * @param pathEdgeMapper Translates a collection of paths to weighted edges.
   */
  public AbstractModelGraphMapper(
      @Nonnull
      PointVertexMapper pointVertexMapper,
      @Nonnull
      PathEdgeMapper pathEdgeMapper
  ) {
    this.pointVertexMapper = requireNonNull(pointVertexMapper, "pointVertextMapper");
    this.pathEdgeMapper = requireNonNull(pathEdgeMapper, "pathEdgeMapper");
  }

  @Override
  public Graph translateModel(
      Collection points,
      Collection paths,
      Vehicle vehicle
  ) {
    requireNonNull(points, "points");
    requireNonNull(paths, "paths");
    requireNonNull(vehicle, "vehicle");

    LOG.debug("Translating model for {}...", vehicle.getName());
    long timeStampBefore = System.currentTimeMillis();

    Graph graph = new DirectedWeightedMultigraph<>(Edge.class);

    for (String vertex : pointVertexMapper.translatePoints(points)) {
      graph.addVertex(vertex);
    }

    for (Map.Entry edgeEntry : pathEdgeMapper.translatePaths(paths, vehicle)
        .entrySet()) {
      graph.addEdge(
          edgeEntry.getKey().getSourceVertex(),
          edgeEntry.getKey().getTargetVertex(),
          edgeEntry.getKey()
      );
      graph.setEdgeWeight(edgeEntry.getKey(), edgeEntry.getValue());
    }

    LOG.debug(
        "Translated model for {} in {} milliseconds.",
        vehicle.getName(),
        System.currentTimeMillis() - timeStampBefore
    );

    return graph;
  }

  @Override
  public Graph updateGraph(
      Collection paths,
      Vehicle vehicle,
      Graph graph
  ) {
    requireNonNull(paths, "paths");
    requireNonNull(vehicle, "vehicle");
    requireNonNull(graph, "graph");

    LOG.debug("Updating graph for {}...", vehicle.getName());
    long timeStampBefore = System.currentTimeMillis();

    Graph updatedGraph = new DirectedWeightedMultigraph<>(Edge.class);

    // First, copy all points from the original graph.
    for (String vertex : graph.vertexSet()) {
      updatedGraph.addVertex(vertex);
    }

    // Then, determine the edges that have not changed and copy these from the original graph as
    // well.
    Set pathNames = paths.stream()
        .map(Path::getName)
        .collect(Collectors.toSet());
    Set unchangedEdges = graph.edgeSet().stream()
        .filter(edge -> !pathNames.contains(edge.getPath().getName()))
        .collect(Collectors.toSet());
    LOG.debug(
        "Adding {} (unchanged) edges (out of originally {}) to the graph...",
        unchangedEdges.size(),
        graph.edgeSet().size()
    );
    for (Edge edge : unchangedEdges) {
      updatedGraph.addEdge(edge.getSourceVertex(), edge.getTargetVertex(), edge);
      updatedGraph.setEdgeWeight(edge, graph.getEdgeWeight(edge));
    }

    // Finally, map all paths that have changed and add the corresponding edges.
    Map changedEdges = pathEdgeMapper.translatePaths(paths, vehicle);
    LOG.debug("Adding {} (changed) edges to the graph...", changedEdges.size());
    for (Map.Entry edgeEntry : changedEdges.entrySet()) {
      updatedGraph.addEdge(
          edgeEntry.getKey().getSourceVertex(),
          edgeEntry.getKey().getTargetVertex(),
          edgeEntry.getKey()
      );
      updatedGraph.setEdgeWeight(edgeEntry.getKey(), edgeEntry.getValue());
    }

    LOG.debug(
        "Updated graph for {} in {} milliseconds.",
        vehicle.getName(),
        System.currentTimeMillis() - timeStampBefore
    );

    return updatedGraph;
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy