1
0
Fork 0
mirror of https://github.com/pgpainless/pgpainless.git synced 2024-06-25 04:54:49 +02:00

Remove old Dijkstra implementation

This commit is contained in:
Paul Schaub 2023-06-25 10:59:36 +02:00
parent 1723830565
commit 5d613ab6a6
Signed by: vanitasvitae
GPG key ID: 62BEE9264BF17311
12 changed files with 0 additions and 641 deletions

View file

@ -1,76 +0,0 @@
// SPDX-FileCopyrightText: 2023 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package org.pgpainless.wot.dijkstra;
public class Cost {
public static class SimpleCost extends Cost {
private final double weight;
public SimpleCost(double weight) {
this.weight = weight;
}
public double getWeight() {
return weight;
}
@Override
public String toString() {
return Double.toString(getWeight());
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (this == obj) {
return true;
}
if (!(obj instanceof SimpleCost)) {
return false;
}
SimpleCost other = (SimpleCost) obj;
return getWeight() == other.getWeight();
}
@Override
public int hashCode() {
return (int) getWeight();
}
}
public static class TrustCost extends Cost {
private final int depth;
private final int amount;
private final String regex;
public TrustCost(int depth, int amount, String regex) {
this.depth = depth;
this.amount = amount;
this.regex = regex;
}
public int getDepth() {
return depth;
}
public int getAmount() {
return amount;
}
public String getRegex() {
return regex;
}
@Override
public String toString() {
return "d=" + getDepth() + ",a=" + getAmount() + (regex == null ? "" : ",r=" + getRegex());
}
}
}

View file

@ -1,12 +0,0 @@
// SPDX-FileCopyrightText: 2023 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package org.pgpainless.wot.dijkstra;
import javax.annotation.Nullable;
public abstract class Dijkstra<T, E extends Edge<T, C>, C extends Cost> {
@Nullable
public abstract Path<T, Node<T>, C, E> findPath(Node<T> to);
}

View file

@ -1,30 +0,0 @@
// SPDX-FileCopyrightText: 2023 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package org.pgpainless.wot.dijkstra;
public abstract class Edge<T, C extends Cost> implements Comparable<C> {
protected final Node<T> from;
protected final Node<T> to;
protected final C cost;
public Edge(Node<T> from, Node<T> to, C cost) {
this.from = from;
this.to = to;
this.cost = cost;
}
public Node<T> getFrom() {
return from;
}
public Node<T> getTo() {
return to;
}
public C getCost() {
return cost;
}
}

View file

@ -1,26 +0,0 @@
// SPDX-FileCopyrightText: 2023 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package org.pgpainless.wot.dijkstra;
import java.util.Collection;
public class Graph<T, N extends Node<T>, E extends Edge<T, C>, C extends Cost> {
private final Collection<N> nodes;
private final Collection<E> edges;
public Graph(Collection<N> nodes, Collection<E> edges) {
this.nodes = nodes;
this.edges = edges;
}
public Collection<N> getNodes() {
return nodes;
}
public Collection<E> getEdges() {
return edges;
}
}

View file

@ -1,44 +0,0 @@
// SPDX-FileCopyrightText: 2023 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package org.pgpainless.wot.dijkstra;
public class Node<T> {
private final T item;
public Node(T item) {
this.item = item;
}
private T getItem() {
return item;
}
@Override
public String toString() {
return "(" + getItem().toString() + ")";
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (this == obj) {
return true;
}
if (!(obj instanceof Node)) {
return false;
}
Node<?> other = (Node<?>) obj;
return getItem().equals(other.getItem());
}
@Override
public int hashCode() {
return getItem().hashCode();
}
}

View file

@ -1,63 +0,0 @@
// SPDX-FileCopyrightText: 2023 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package org.pgpainless.wot.dijkstra;
import java.util.Arrays;
import java.util.List;
public class Path<T, N extends Node<T>, C extends Cost, E extends Edge<T, C>> {
private final N from;
private final N to;
private final List<E> edges;
public Path(N from, N to, List<E> edges) {
this.from = from;
this.to = to;
this.edges = edges;
}
public Node<T> getFrom() {
return from;
}
public Node<T> getTo() {
return to;
}
public List<E> getEdges() {
return edges;
}
@Override
public String toString() {
return Arrays.toString(getEdges().toArray());
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (this == obj) {
return true;
}
if (!(obj instanceof Path)) {
return false;
}
Path<?, ?, ?, ?> other = (Path<?, ?, ?, ?>) obj;
return getFrom().equals(other.getFrom())
&& getTo().equals(other.getTo())
&& getEdges().equals(other.getEdges());
}
@Override
public int hashCode() {
return getFrom().hashCode()
+ 13 * getTo().hashCode()
+ 31 * getEdges().hashCode();
}
}

View file

@ -1,114 +0,0 @@
// SPDX-FileCopyrightText: 2023 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package org.pgpainless.wot.dijkstra;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ShortestPathDijkstra<T> extends Dijkstra<T, SimpleEdge<T>, Cost.SimpleCost> {
private final Node<T> root;
private final Graph<T, Node<T>, SimpleEdge<T>, Cost.SimpleCost> graph;
private final List<Node<T>> queue = new ArrayList<>();
private final Map<Node<T>, Double> distances = new HashMap<>();
private final Map<Node<T>, SimpleEdge<T>> precursors = new HashMap<>();
public ShortestPathDijkstra(Graph<T, Node<T>, SimpleEdge<T>, Cost.SimpleCost> graph, Node<T> root) {
// INITIALIZE
this.graph = graph;
this.root = root;
for (Node<T> node : graph.getNodes()) {
// dist[v] := infinity
distances.put(node, Double.MAX_VALUE);
// precursor[v] := null
precursors.put(node, null);
}
// dist[root] := 0
distances.put(root, 0d);
// Q := set of all nodes in graph
queue.addAll(graph.getNodes());
while (!queue.isEmpty()) {
Node<T> closest = closest();
queue.remove(closest);
for (SimpleEdge<T> edge : graph.getEdges()) {
if (!closest.equals(edge.getFrom())) {
// Skip non-neighbors
continue;
}
if (queue.contains(edge.getTo())) {
distUpdate(closest, edge.getTo());
}
}
}
}
private Node<T> closest() {
Double minDist = Double.MAX_VALUE;
int index = 0;
Double dist;
for (int i = 0; i < queue.size(); i++) {
if ((dist = distances.get(queue.get(i))) <= minDist) {
index = i;
minDist = dist;
}
}
return queue.get(index);
}
private void distUpdate(Node<T> from, Node<T> to) {
SimpleEdge<T> edge = getEdgeBetween(from, to);
if (edge == null) {
// No direct path
return;
}
Double distance = distances.get(from) + edge.getCost().getWeight();
if (distance < distances.get(to)) {
distances.put(to, distance);
precursors.put(to, edge);
}
}
private SimpleEdge<T> getEdgeBetween(Node<T> from, Node<T> to) {
for (SimpleEdge<T> edge : graph.getEdges()) {
if (!from.equals(edge.getFrom())) {
continue;
}
if (to.equals(edge.getTo())) {
return edge;
}
}
return null;
}
@Override
@Nullable
public Path<T, Node<T>, Cost.SimpleCost, SimpleEdge<T>> findPath(Node<T> to) {
List<SimpleEdge<T>> pathEdges = new ArrayList<>();
Node<T> waypoint = to;
SimpleEdge<T> edge;
while ((edge = precursors.get(waypoint)) != null) {
waypoint = precursors.get(waypoint).getFrom();
pathEdges.add(0, edge);
}
if (pathEdges.isEmpty()) {
return null;
}
return new Path<>(root, to, pathEdges);
}
}

View file

@ -1,45 +0,0 @@
// SPDX-FileCopyrightText: 2023 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package org.pgpainless.wot.dijkstra;
public class SimpleEdge<T> extends Edge<T, Cost.SimpleCost> {
public SimpleEdge(Node<T> from, Node<T> to, Double edgeWeight) {
super(from, to, new Cost.SimpleCost(edgeWeight));
}
@Override
public String toString() {
return getFrom().toString() + " " + getCost() + "> " + getTo().toString();
}
@Override
public int compareTo(Cost.SimpleCost o) {
return Double.compare(getCost().getWeight(), o.getWeight());
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (this == obj) {
return true;
}
if (!(obj instanceof SimpleEdge)) {
return false;
}
SimpleEdge<?> other = (SimpleEdge<?>) obj;
return getFrom().equals(other.getFrom())
&& getTo().equals(other.getTo())
&& getCost().equals(other.getCost());
}
@Override
public int hashCode() {
return getFrom().hashCode() + 13 * getTo().hashCode() + 17 * getCost().hashCode();
}
}

View file

@ -1,23 +0,0 @@
// SPDX-FileCopyrightText: 2023 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package org.pgpainless.wot.dijkstra;
import javax.annotation.Nonnull;
public class TrustEdge<T> extends Edge<T, Cost.TrustCost> {
public TrustEdge(Node<T> from, Node<T> to, Cost.TrustCost cost) {
super(from, to, cost);
}
@Override
public int compareTo(@Nonnull Cost.TrustCost o) {
int depthCompare = Double.compare(cost.getDepth(), o.getDepth());
if (depthCompare != 0) {
return -depthCompare;
}
return Double.compare(cost.getAmount(), o.getAmount());
}
}

View file

@ -1,17 +0,0 @@
// SPDX-FileCopyrightText: 2023 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package org.pgpainless.wot.dijkstra;
import javax.annotation.Nullable;
public class WotDijkstra<T> extends Dijkstra<T, TrustEdge<T>, Cost.TrustCost> {
@Override
@Nullable
public Path<T, Node<T>, Cost.TrustCost, TrustEdge<T>> findPath(Node<T> to) {
return null;
}
}

View file

@ -1,156 +0,0 @@
// SPDX-FileCopyrightText: 2023 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package org.pgpainless.wot.dijkstra;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.junit.jupiter.api.Test;
public class BasicShortestPathDijkstraTest {
/**
* Generate a test graph from a string definition.
* The definition might look like this:
* <pre>
* Alice
* Bob -1> Charlie
* Charlie -4> Dieter -1> Alice
* Dieter -2> Charlie
* </pre>
* @param definition definition
* @return graph
*/
private Graph<String, Node<String>, SimpleEdge<String>, Cost.SimpleCost> generate(String definition) {
Set<Node<String>> nodes = new HashSet<>();
Set<SimpleEdge<String>> edges = new HashSet<>();
String[] lines = definition.split("\n");
for (String line : lines) {
line = line.trim();
if (line.isEmpty()) {
continue;
}
String[] fromTo = line.split(" -\\d+> ");
if (fromTo.length == 1) {
// Unconnected node
nodes.add(new Node<>(fromTo[0]));
continue;
}
int searchOffset = 0;
for (int i = 0; i < fromTo.length - 1; i++) {
Node<String> from = new Node<>(fromTo[i]);
nodes.add(from);
searchOffset += fromTo[i].length() + " -".length();
int costStop = line.indexOf("> ", searchOffset);
String costString = line.substring(searchOffset, costStop);
Double cost = Double.parseDouble(costString);
searchOffset += costString.length() + "> ".length();
Node<String> to = new Node<>(fromTo[i + 1]);
nodes.add(to);
edges.add(new SimpleEdge<>(from, to, cost));
}
}
return new Graph<>(nodes, edges);
}
private Path<String, Node<String>, Cost.SimpleCost, SimpleEdge<String>> path(String definition) {
definition = definition.trim();
String[] fromTo = definition.split(" -\\d+> ");
if (fromTo.length == 1) {
// Unconnected node
Node<String> node = new Node<>(fromTo[0]);
return new Path<>(node, node, Collections.singletonList(new SimpleEdge<>(node, node, 0d)));
}
Node<String> start = null;
Node<String> end = null;
List<SimpleEdge<String>> edges = new ArrayList<>();
int searchOffset = 0;
for (int i = 0; i < fromTo.length - 1; i++) {
Node<String> from = new Node<>(fromTo[i]);
if (start == null) {
start = from;
}
searchOffset += fromTo[i].length() + " -".length();
int costStop = definition.indexOf("> ", searchOffset);
String costString = definition.substring(searchOffset, costStop);
Double cost = Double.parseDouble(costString);
searchOffset += costString.length() + "> ".length();
Node<String> to = new Node<>(fromTo[i + 1]);
edges.add(new SimpleEdge<>(from, to, cost));
end = to;
}
Path<String, Node<String>, Cost.SimpleCost, SimpleEdge<String>> path = new Path<>(start, end, edges);
return path;
}
@Test
public void exampleGraphTest() {
Graph<String, Node<String>, SimpleEdge<String>, Cost.SimpleCost> g = generate(
"Alice\n" +
"Bob -1> Charlie\n" +
"Bob -3> Dieter -1> Marlene\n" +
"Dieter -1> Alice\n" +
"Mallory\n");
Set<Node<String>> expectedNodes = new HashSet<>();
expectedNodes.add(new Node<>("Alice"));
expectedNodes.add(new Node<>("Bob"));
expectedNodes.add(new Node<>("Charlie"));
expectedNodes.add(new Node<>("Dieter"));
expectedNodes.add(new Node<>("Marlene"));
expectedNodes.add(new Node<>("Mallory"));
assertEquals(expectedNodes, g.getNodes());
Set<SimpleEdge<String>> expectedEdges = new HashSet<>();
expectedEdges.add(new SimpleEdge<>(new Node<>("Bob"), new Node<>("Charlie"), 1d));
expectedEdges.add(new SimpleEdge<>(new Node<>("Bob"), new Node<>("Dieter"), 3d));
expectedEdges.add(new SimpleEdge<>(new Node<>("Dieter"), new Node<>("Marlene"), 1d));
expectedEdges.add(new SimpleEdge<>(new Node<>("Dieter"), new Node<>("Alice"), 1d));
assertEquals(g.getEdges(), expectedEdges);
}
@Test
public void emptyNetworkTest() {
Graph<String, Node<String>, SimpleEdge<String>, Cost.SimpleCost> graph = generate("");
Node<String> root = new Node<>("root");
Node<String> target = new Node<>("target");
ShortestPathDijkstra<String> dijkstra = new ShortestPathDijkstra<>(graph, root);
Path<String, Node<String>, Cost.SimpleCost, SimpleEdge<String>> path = dijkstra.findPath(target);
assertNull(path);
}
@Test
public void pathFindingTest() {
Graph<String, Node<String>, SimpleEdge<String>, Cost.SimpleCost> graph = generate(
"Pablo\n" +
"Root -2> Alice -3> Alexandra\n" +
"Root -1> Karlos -1> Alexandra\n" +
"Karlos -2> Malte -4> Sven");
ShortestPathDijkstra<String> dijkstra = new ShortestPathDijkstra<>(graph, new Node<>("Root"));
assertEquals(path("Root -1> Karlos -2> Malte -4> Sven"), dijkstra.findPath(new Node<>("Sven")));
assertEquals(path("Root -1> Karlos"), dijkstra.findPath(new Node<>("Karlos")));
assertEquals(path("Root -1> Karlos -1> Alexandra"), dijkstra.findPath(new Node<>("Alexandra")));
dijkstra = new ShortestPathDijkstra<>(graph, new Node<>("Karlos"));
assertEquals(path("Karlos -2> Malte -4> Sven"), dijkstra.findPath(new Node<>("Sven")));
}
}

View file

@ -1,35 +0,0 @@
// SPDX-FileCopyrightText: 2023 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package org.pgpainless.wot.dijkstra;
import org.junit.jupiter.api.Test;
import java.util.HashMap;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
public class NodeTest {
@Test
public void equalsTest() {
Node<String> n1 = new Node<>("foo");
Node<String> n1_ = new Node<>("foo");
Node<String> n2 = new Node<>("bar");
assertEquals(n1, n1_);
assertEquals(n1, n1);
assertNotEquals(n1, n2);
Map<Node<String>, String> map = new HashMap<>();
map.put(n1, "foo");
map.put(n2, "bar");
assertEquals("foo", map.get(n1));
assertEquals("bar", map.get(n2));
assertEquals("foo", map.get(n1_));
}
}