Skip to content

Commit

Permalink
Implement force-forward edges in baharev.
Browse files Browse the repository at this point in the history
This may lead to upper-bound inconsistencies, thus we need a
force-forward implementation in eades, as well.
  • Loading branch information
thvitt committed Mar 5, 2019
1 parent 5738961 commit 6d865c7
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 2 deletions.
10 changes: 8 additions & 2 deletions src/macrogen/fes.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
import itertools
from collections import defaultdict
from typing import Tuple, List, Generator, TypeVar, Iterable, Sequence
from typing import Tuple, List, Generator, TypeVar, Iterable, Sequence, Optional
from .config import config
import networkx as nx
import numpy as np
Expand Down Expand Up @@ -167,7 +167,7 @@ class FES_Baharev:
http://www.mat.univie.ac.at/~neum/ms/minimum_feedback_arc_set.pdf.
"""

def __init__(self, graph: nx.DiGraph):
def __init__(self, graph: nx.DiGraph, force_forward_edges: Optional[List[Tuple[V, V]]] = None):
self.original_graph = graph
self.logger = config.getLogger(__name__ + '.' + self.__class__.__name__)

Expand All @@ -188,10 +188,15 @@ def __init__(self, graph: nx.DiGraph):
weights.append(w)
edges.append((u, v))

if force_forward_edges is None:
force_forward_edges = []

self.graph = G
self.weights = np.array(weights)
self.edges = edges
self.m = len(self.edges)
self.force_forward_edges = force_forward_edges
self.force_forward_vec = self.edge_vector(force_forward_edges)
self.solver_args = {}
self.solution_vector = None
self.solution = None
Expand Down Expand Up @@ -277,6 +282,7 @@ def solve(self):

cycle_vectors = [self.edge_vector(nx.utils.pairwise(cycle)) for cycle in simple_cycles]
constraints = [cp.sum(a * y) >= 1 for a in cycle_vectors]
constraints.append(cp.sum(y * self.force_forward_vec) == 0) # no force forward vec may be in the result set
problem = cp.Problem(objective, constraints)
resolution = problem.solve(**self.solver_args)
if problem.status != 'optimal':
Expand Down
14 changes: 14 additions & 0 deletions tests/test_fes.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,17 @@ def test_baharev(graph1):
solver = FES_Baharev(graph1)
result = solver.solve()
assert set(result) == {(3, 2)} or set(result) == {(2, 3)}


def test_baharev_ff():
g = nx.DiGraph()
g.add_path([1, 2, 3, 4, 5], weight=1)
g.add_edge(3, 2, weight=2)

# This would normally remove (2,3) since its more lightweight than (3,2):
result = FES_Baharev(g).solve()
assert set(result) == {(2, 3)}

# However, when we forbid this, the next best solution will occur:
result = FES_Baharev(g, [(2, 3)]).solve()
assert set(result) == {(3, 2)}

0 comments on commit 6d865c7

Please sign in to comment.