Skip to content

Commit

Permalink
Fix floating rounding and parallel edges issues in gmwcs
Browse files Browse the repository at this point in the history
  • Loading branch information
np96 committed Nov 29, 2021
1 parent 05b7668 commit df0ed26
Show file tree
Hide file tree
Showing 7 changed files with 50 additions and 40 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<groupId>ifmo.ru</groupId>
<artifactId>virgo-solver</artifactId>

<version>0.1.4</version>
<version>0.1.5</version>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
Expand Down
7 changes: 1 addition & 6 deletions src/main/java/ru/itmo/ctlab/virgo/Main.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package ru.itmo.ctlab.virgo;

import ilog.cplex.IloCplex;
import joptsimple.OptionParser;
import joptsimple.OptionSet;
import ru.itmo.ctlab.gmwcs.solver.TreeSolverKt;
Expand All @@ -16,12 +15,9 @@
import java.io.IOException;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
Expand All @@ -32,7 +28,7 @@
import static ru.itmo.ctlab.virgo.gmwcs.graph.Elem.extract;

public class Main {
public static final String VERSION = "0.1.4";
public static final String VERSION = "0.1.5";

private static void checkCplex() {
PrintStream stdout = System.out;
Expand All @@ -51,7 +47,6 @@ private static void checkCplex() {
System.exit(1);
} finally {
System.setOut(stdout);
System.out.println("aaa");
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/main/java/ru/itmo/ctlab/virgo/gmwcs/graph/Elem.java
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public boolean equals(Object o) {
@Override
public int compareTo(Elem u) {
if (u.weight != weight) {
return Double.compare(u.weight, weight);
return Double.compare(weight, u.weight);
}
return Integer.compare(u.getNum(), num);
}
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/ru/itmo/ctlab/virgo/sgmwcs/solver/Dijkstra.java
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ public void solve(Node u) {
Set<Node> visitedDests = new HashSet<>();
path.put(u, Collections.emptySet());
while ((cur = q.poll()) != null) {
if (visitedDests.contains(cur))
continue;
if (dests.contains(cur)
&& visitedDests.add(cur)
&& visitedDests.containsAll(dests)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,40 +6,38 @@ import ru.itmo.ctlab.virgo.gmwcs.graph.Elem
import ru.itmo.ctlab.virgo.gmwcs.graph.Node
import ru.itmo.ctlab.virgo.gmwcs.graph.Graph
import java.util.*
import kotlin.math.abs

/**
* Created by Nikolay Poperechnyi on 04/10/2017.
*/
class Dijkstra(private val graph: Graph, private val from: Node,
private val save: Boolean = false) {
class Dijkstra(private val graph: Graph, private val from: Node) {

private val s = from.num

private val n = graph.vertexSet().maxBy { it.num }!!.num + 1

private val paths = Array(n, {emptyList<Int>()})
private val visited = BooleanArray(n) { false }

private val visited = BooleanArray(n, { false })

private var d = DoubleArray(n, { Double.MAX_VALUE })
private var d = DoubleArray(n) { Double.MAX_VALUE }

private fun solve(neighbors: Set<Node>) {
if (d[s] != Double.MAX_VALUE) return
val queue = PriorityQueue<Node>(
{ n1, n2 -> (d[n1.num] - d[n2.num]).compareTo(0) }
)
val queue = PriorityQueue<Node> { n1, n2 -> (d[n1.num] - d[n2.num]).compareTo(0) }
d[s] = 0.0
queue.add(from)
while (queue.isNotEmpty()) {
val cur = queue.poll()
if (visited[cur.num])
continue
visited[cur.num] = true
// Stop searching if shortest paths are found
if (neighbors.contains(cur) && neighbors.all { visited[it.num] })
break
for (adj in graph.neighborListOf(cur).filter { !visited[it.num] }) {
// 0 for positive, -weight for negative
val e = graph.getEdge(cur, adj)
val ew = if (cur != from) maxOf(p(e, cur), p(e), p(cur)) else p(e)
val ew = p(e, adj)
val w = d[cur.num] + ew
if (d[adj.num] > w) {
d[adj.num] = w
Expand All @@ -54,26 +52,32 @@ class Dijkstra(private val graph: Graph, private val from: Node,

private fun distances(neighbors: Set<Node>): Map<Node, Double> {
solve(neighbors)
return neighbors.map({ Pair(it, d[it.num] + p(from)) }).toMap()
return neighbors.associateWith { d[it.num] + p(from) }
}

fun negativeEdges(neighbors: Set<Node>): List<Edge> {
solve(neighbors)
return graph.edgesOf(from).filter {
val end = graph.opposite(from, it)
it.weight < 0 && p(it) > d[end.num]
it.weight < 0 && !almostEquals(d[end.num] - p(it), p(end))
// it.weight <= 0 && d[end] < -it.weight
}
}

fun negativeVertex(dest: Node, candidate: Node): Boolean {
solve(setOf(dest))
// test is passed if candidate for removal is not in the solution
val candPathW = d[candidate.num] + p(graph.getEdge(candidate, dest)) + p(candidate)
return d[dest.num] != candPathW
val candPathW = p(graph.getEdge(from, candidate),
graph.getEdge(candidate, dest),
candidate)
return !almostEquals(d[dest.num], candPathW)
}

private fun almostEquals(a: Double, b: Double): Boolean {
return abs(a - b) < 1e-10
}

private fun p(vararg e: Elem): Double {
return -minOf(e.sumByDouble { it.weight }, 0.0)
return -e.sumByDouble { minOf(it.weight, 0.0) }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ fun l(graph: Graph, toRemove: MutableNodeSet = mutableSetOf()): NodeSet {
continue
val e = graph.edgesOf(n).iterator().next()
val opposite = graph.opposite(n, e)
if (n.weight + e.weight >= 0) {
if (n.weight + e.weight > 0) {
opposite.absorb(n)
opposite.absorb(e)
toRemove.add(n)
Expand All @@ -112,12 +112,19 @@ fun mergeNegative(graph: Graph, toRemove: MutableNodeSet = mutableSetOf()): Node
continue
val l = graph.opposite(v, edges[0])
val r = graph.opposite(v, edges[1])
toRemove.add(v) //TODO: 2 nodes 1 edge invariant broken here
toRemove.add(v)
graph.removeVertex(v)
if (l != r) {
edges[0].absorb(v)
edges[0].absorb(edges[1])
graph.addEdge(l, r, edges[0])
val es = graph.getAllEdges(l, r).sorted()
val maxE = es[es.size - 1]
for (e in es.subList(0, es.size - 1)) {
if (e.weight >= 0)
maxE.absorb(e)
graph.removeEdge(e)
}
}
}
return toRemove
Expand Down Expand Up @@ -183,12 +190,12 @@ private fun contract(graph: Graph, e: Edge) {

fun negativeVertices(graph: Graph,
toRemove: MutableNodeSet = mutableSetOf()): NodeSet {
graph.vertexSet().filterTo(toRemove, { vertexTest(graph, it) })
graph.vertexSet().filterTo(toRemove) { vertexTest(graph, it) }
return toRemove
}

private fun vertexTest(graph: Graph, v: Node): Boolean {
return if (v.weight <= 0
return if (v.weight < 0
&& graph.neighborListOf(v).size == 2
&& graph.edgesOf(v).all { it.weight <= 0 }) {
val neighbors = graph.neighborListOf(v)
Expand Down
28 changes: 15 additions & 13 deletions src/test/java/ru/itmo/ctlab/virgo/sgmwcs/SGMWCSTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,16 @@
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;
import ru.itmo.ctlab.virgo.sgmwcs.graph.*;
import ru.itmo.ctlab.virgo.sgmwcs.solver.*;
import ru.itmo.ctlab.virgo.SolverException;
import ru.itmo.ctlab.virgo.sgmwcs.graph.Edge;
import ru.itmo.ctlab.virgo.sgmwcs.graph.Graph;
import ru.itmo.ctlab.virgo.sgmwcs.graph.Node;
import ru.itmo.ctlab.virgo.sgmwcs.graph.Unit;
import ru.itmo.ctlab.virgo.sgmwcs.solver.*;

import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.*;
import java.util.stream.IntStream;

import static ru.itmo.ctlab.virgo.sgmwcs.solver.Utils.copy;
import static ru.itmo.ctlab.virgo.sgmwcs.solver.Utils.sum;
Expand All @@ -35,11 +37,11 @@ public class SGMWCSTest {
}
}

private List<TestCase> tests;
private ComponentSolver solver;
private ReferenceSolver referenceSolver;
private RLTSolver rltSolver;
private Random random;
private final List<TestCase> tests;
private final ComponentSolver solver;
private final ReferenceSolver referenceSolver;
private final RLTSolver rltSolver;
private final Random random;

public SGMWCSTest() {
random = new Random(SEED);
Expand Down Expand Up @@ -95,7 +97,7 @@ public void test01_empty() throws SolverException {
solver.setLogLevel(0);
List<Unit> res = solver.solve(graph, new Signals());
if (!(res == null || res.isEmpty())) {
Assert.assertTrue("An empty graph can't contain non-empty subgraph", false);
Assert.fail("An empty graph can't contain non-empty subgraph");
}
}

Expand Down Expand Up @@ -305,8 +307,8 @@ private void makeConnectedGraphs(int minSize, int maxSize) {
}
fillEdgesRandomly(graph, count, nodesArray, edges, size);
Map<Unit, Double> weights = new HashMap<>();
nodes.forEach(weights::put);
edges.forEach(weights::put);
weights.putAll(nodes);
weights.putAll(edges);
tests.add(new TestCase(graph, weights, random));
}
}
Expand All @@ -323,8 +325,8 @@ private void makeUnconnectedGraphs() {
Arrays.sort(nodesArray);
fillEdgesRandomly(graph, m, nodesArray, edges, 1);
Map<Unit, Double> weights = new HashMap<>();
nodes.forEach(weights::put);
edges.forEach(weights::put);
weights.putAll(nodes);
weights.putAll(edges);
tests.add(new TestCase(graph, weights, random));
}
}
Expand Down

0 comments on commit df0ed26

Please sign in to comment.