Ford Fulkerson算法最大流算法-这个Java实现有什么问题?

Ford Fulkerson算法最大流算法-这个Java实现有什么问题?,java,python,algorithm,ford-fulkerson,Java,Python,Algorithm,Ford Fulkerson,我正在尝试实现Ford Fulkerson的java版本。我使用来自的python实现作为基础: class Edge(object): def __init__(self, u, v, w): self.source = u self.sink = v self.capacity = w def __repr__(self): return "%s->%s:%s" % (self.source, self

我正在尝试实现Ford Fulkerson的java版本。我使用来自的python实现作为基础:

class Edge(object):
    def __init__(self, u, v, w):
        self.source = u
        self.sink = v  
        self.capacity = w
    def __repr__(self):
        return "%s->%s:%s" % (self.source, self.sink, self.capacity)

class FlowNetwork(object):
    def __init__(self):
        self.adj = {}
        self.flow = {}

    def add_vertex(self, vertex):
        self.adj[vertex] = []

    def get_edges(self, v):
        return self.adj[v]

    def add_edge(self, u, v, w=0):
        if u == v:
            raise ValueError("u == v")
        edge = Edge(u,v,w)
        redge = Edge(v,u,0)
        edge.redge = redge
        redge.redge = edge
        self.adj[u].append(edge)
        self.adj[v].append(redge)
        self.flow[edge] = 0
        self.flow[redge] = 0

    def find_path(self, source, sink, path):
        if source == sink:
            return path
        for edge in self.get_edges(source):
            residual = edge.capacity - self.flow[edge]
            if residual > 0 and edge not in path:
                result = self.find_path( edge.sink, sink, path + [edge]) 
                if result != None:
                    return result

    def max_flow(self, source, sink):
        path = self.find_path(source, sink, [])
        while path != None:
            residuals = [edge.capacity - self.flow[edge] for edge in path]
            flow = min(residuals)
            for edge in path:
                self.flow[edge] += flow
                self.flow[edge.redge] -= flow
            path = self.find_path(source, sink, [])
        return sum(self.flow[edge] for edge in self.get_edges(source))
这是我的java实现:

import org.junit.Test;

import java.util.*;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;

public class MaxFlowTest {

    @Test
    public void maxFlowTest() {
        FlowNetwork unit = new FlowNetwork(Arrays.asList(0, 1, 2, 3, 4, 5));

        unit.addEdge(0, 1, 16);
        unit.addEdge(0, 2, 13);
        unit.addEdge(1, 3, 12);
        unit.addEdge(1, 2, 10);
        unit.addEdge(2, 1, 4);
        unit.addEdge(2, 4, 14);
        unit.addEdge(3, 2, 9);
        unit.addEdge(4, 3, 7);
        unit.addEdge(3, 5, 20);
        unit.addEdge(4, 5, 4);

        assertThat(unit.maxFlow(0, 5), is(23)); //algorithm incorrectly returning 7
    }
}

class FlowNetwork {
    Map<Integer, List<Edge>> edges = new HashMap<>();
    Map<Edge, Integer> flow = new HashMap<>();

    public FlowNetwork(List<Integer> vertices) {
        vertices.forEach(v -> this.edges.put(v, new ArrayList<>()));
    }

    public Integer maxFlow(Integer source, Integer sink) {
        List<Edge> path = null;
        while (! (path=findAugmentedPath(source,sink,new ArrayList<>())).isEmpty()) {
            int flow = path.stream().mapToInt(e -> e.capacity - this.flow.get(e)).min().getAsInt();
            path.forEach(e -> {
                this.flow.put(e, this.flow.get(e) + flow);
                this.flow.put(e.reverseEdge, this.flow.get(e.reverseEdge) - flow);
            });
        }
        return edges.get(source).stream().mapToInt(e -> flow.get(e)).sum();

    }

    List<Edge> findAugmentedPath(Integer source, Integer sink, List<Edge> pathSoFar) {
        if (source == sink) {
            return pathSoFar;
        }
        for (Edge neighbourEdge : this.edges.get(source)) {
            int residual = neighbourEdge.capacity - flow.get(neighbourEdge);
            if (residual > 0 && !pathSoFar.contains(neighbourEdge)) {
                pathSoFar.add(neighbourEdge);
                List<Edge> path = findAugmentedPath(neighbourEdge.b, sink, pathSoFar);
                if (!path.isEmpty()) {
                    return path;
                }
            }
        }
        return Collections.emptyList();
    }


    public void addEdge(int source, int sink, int capacity) {
        Edge edge = new Edge(source, sink, capacity);
        Edge reverseEdge = new Edge(sink, source, 0);

        edge.reverseEdge = reverseEdge;

        reverseEdge.reverseEdge = edge;

        this.edges.get(source).add(edge);
        this.edges.get(sink).add(reverseEdge);

        flow.put(edge, 0);
        flow.put(reverseEdge, 0);
    }
}


class Edge {

    Integer capacity;
    Edge reverseEdge;
    int b;
    int a;

    public Edge(Integer a, Integer b, Integer capacity) {
        this.a = a;
        this.b = b;
        this.capacity = capacity;
    }
}
import org.junit.Test;
导入java.util.*;
导入静态org.hamcrest.CoreMatchers.is;
导入静态org.hamcrest.matcherasert.assertThat;
公共类MaxFlowTest{
@试验
公共无效maxFlowTest(){
FlowNetwork单元=新的FlowNetwork(Arrays.asList(0,1,2,3,4,5));
单位加总(0,1,16);
单位。附录(0、2、13);
单位。附录(1、3、12);
单位。附录(1、2、10);
单位。附录(2、1、4);
单位。附录(2、4、14);
单位。附录(3、2、9);
单位。附录(4、3、7);
单位。附录(3、5、20);
单位。附录(4、5、4);
断言(unit.maxFlow(0,5)是(23));//算法错误地返回7
}
}
类流网络{
映射边=新的HashMap();
映射流=新的HashMap();
公共流网络(列出顶点){
vertices.forEach(v->this.edges.put(v,newArrayList());
}
公共整数maxFlow(整数源、整数接收器){
列表路径=空;
while(!(path=findaumgedPath(源、接收器、新ArrayList()).isEmpty()){
int flow=path.stream().mapToInt(e->e.capacity-this.flow.get(e)).min().getAsInt();
path.forEach(e->{
this.flow.put(e,this.flow.get(e)+flow);
this.flow.put(e.reverseEdge,this.flow.get(e.reverseEdge)-flow);
});
}
返回edges.get(source.stream().mapToInt(e->flow.get(e)).sum();
}
列表FindUpgmentedPath(整数源、整数接收器、列表路径){
如果(源==接收器){
返回路径;
}
for(Edge NextureEdge:this.edges.get(源)){
int残差=nextureEdge.capacity-flow.get(nextureEdge);
if(剩余>0&!路径包含(邻域边缘)){
路径far.add(邻居边缘);
列表路径=FindUpgmentedPath(nextureEdge.b、sink、pathSoFar);
如果(!path.isEmpty()){
返回路径;
}
}
}
返回集合。emptyList();
}
公共无效添加(整数源、整数接收器、整数容量){
边缘=新边缘(源、汇、容量);
Edge reverseEdge=新边(接收器、源、0);
edge.reverseEdge=reverseEdge;
reverseEdge.reverseEdge=边;
this.edges.get(source).add(edge);
this.edges.get(sink).add(reverseEdge);
流动。放置(边缘,0);
流量输入(反向输入,0);
}
}
阶级边缘{
整数容量;
边缘反转;
int b;
INTA;
公共边缘(整数a、整数b、整数容量){
这个a=a;
这个.b=b;
这个。容量=容量;
}
}
问题是java算法输出的是7,而不是测试用例中给出的正确的23。 代码运行时没有错误。 在调试算法时,我看不到任何错误行为。我不确定这是怎么回事

我的问题是,谁能帮助我理解它是如何出错的以及为什么出错的


如果有助于此pdf中示例图形的可视化表示:

我发现了问题…调用FindAgentedPath时,我没有创建pathSoFar的副本。哎呀

List<Edge> findAugmentedPath(Integer source, Integer sink, List<Edge> pathSoFar) {
    if (source == sink) {
        return pathSoFar;
    }
    for (Edge neighbourEdge : this.edges.get(source)) {
        int residual = neighbourEdge.capacity - flow.get(neighbourEdge);
        if (residual > 0 && !pathSoFar.contains(neighbourEdge)) {
            List<Edge> pathSoFarCopy = new ArrayList<>(pathSoFar);
            pathSoFarCopy.add(neighbourEdge);
            List<Edge> path = findAugmentedPath(neighbourEdge.b, sink, pathSoFarCopy);
            if (!path.isEmpty()) {
                return path;
            }
        }
    }
    return Collections.emptyList();
}
列出FindAgentedPath(整数源、整数接收器、列表路径){
如果(源==接收器){
返回路径;
}
for(Edge NextureEdge:this.edges.get(源)){
int残差=nextureEdge.capacity-flow.get(nextureEdge);
if(剩余>0&!路径包含(邻域边缘)){
List pathSoFarCopy=新阵列列表(pathSoFar);
路径farcopy.add(邻居边缘);
列表路径=FindUpgmentedPath(nextureEdge.b、sink、pathSoFarCopy);
如果(!path.isEmpty()){
返回路径;
}
}
}
返回集合。emptyList();
}

如今,大多数面向Java的IDE都包含一个分步调试工具,这样您就可以逐步调试代码,并在发生分支和变量更改时观察它们。也许你可以试试这个?