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

org.jgrapht.alg.MinSourceSinkCut Maven / Gradle / Ivy

There is a newer version: 1.5.2
Show newest version
/*
 * (C) Copyright 2012-2016, by Joris Kinable and Contributors.
 *
 * JGraphT : a free Java graph-theory library
 *
 * This program and the accompanying materials are dual-licensed under
 * either
 *
 * (a) the terms of the GNU Lesser General Public License version 2.1
 * as published by the Free Software Foundation, or (at your option) any
 * later version.
 *
 * or (per the licensee's choosing)
 *
 * (b) the terms of the Eclipse Public License v1.0 as published by
 * the Eclipse Foundation.
 */
package org.jgrapht.alg;

import java.util.*;

import org.jgrapht.*;
import org.jgrapht.alg.flow.*;
import org.jgrapht.alg.interfaces.*;
import org.jgrapht.alg.interfaces.MaximumFlowAlgorithm.*;

/**
 * Given a weighted graph G(V,E) (directed or undirected). This class computes a minimum s-t cut.
 * For this purpose this class relies on Edmonds' Karp Maximum Flow Algorithm. Note: it is not
 * recommended to use this class to calculate the overall minimum cut in a graph by iteratively
 * invoking this class for all source-sink pairs. This is computationally expensive. Instead, use
 * the StoerWagnerMinimumCut implementation.
 *
 * Runtime: O(E)
 *
 * Warning: this implementation cannot be used with the PushRelabel max flow implementation!
 *
 * @param  the graph vertex type
 * @param  the graph edge type
 *
 * @author Joris Kinable
 * @deprecated Use {@link MinimumSTCutAlgorithm} instead
 */
@Deprecated
public class MinSourceSinkCut
{
    MaximumFlowAlgorithm ekMaxFlow;
    Set minCut = null;
    DirectedGraph graph;
    double cutWeight;
    V source = null;
    V sink = null;
    double epsilon = MaximumFlowAlgorithmBase.DEFAULT_EPSILON;

    /**
     * Create a new minimum s-t cut algorithm.
     * 
     * @param graph the input graph
     */
    public MinSourceSinkCut(DirectedGraph graph)
    {
        this.ekMaxFlow = new PushRelabelMFImpl<>(graph);
        this.graph = graph;
    }

    /**
     * Create a new minimum s-t cut algorithm.
     * 
     * @param graph the input graph
     * @param epsilon tolerance used when comparing floating point values
     */
    public MinSourceSinkCut(DirectedGraph graph, double epsilon)
    {
        this(graph, new PushRelabelMFImpl<>(graph), epsilon);
    }

    /**
     * Create a new minimum s-t cut algorithm.
     * 
     * @param graph the input graph
     * @param maximumFlowAlgorithm the maximum flow algorithm to use
     * @param epsilon tolerance used when comparing floating point values
     */
    public MinSourceSinkCut(
        DirectedGraph graph, MaximumFlowAlgorithm maximumFlowAlgorithm, double epsilon)
    {
        this.ekMaxFlow = maximumFlowAlgorithm;
        this.graph = graph;
        this.epsilon = epsilon;
    }

    /**
     * Compute a minimum s-t cut
     *
     * @param source the source
     * @param sink the sink
     */
    public void computeMinCut(V source, V sink)
    {
        this.source = source;
        this.sink = sink;
        minCut = new HashSet<>();

        // First compute a maxFlow from source to sink
        MaximumFlow maxFlow = ekMaxFlow.buildMaximumFlow(source, sink);

        this.cutWeight = maxFlow.getValue();

        Queue processQueue = new LinkedList<>();
        processQueue.add(source);

        while (!processQueue.isEmpty()) {
            V vertex = processQueue.remove();
            if (minCut.contains(vertex)) {
                continue;
            } else {
                minCut.add(vertex);
            }

            // 1. Get the forward edges with residual capacity
            Set outEdges = new HashSet<>(graph.outgoingEdgesOf(vertex));
            for (Iterator it = outEdges.iterator(); it.hasNext();) {
                E edge = it.next();
                double edgeCapacity = graph.getEdgeWeight(edge);
                double flowValue = maxFlow.getFlow().get(edge);
                if (Math.abs(edgeCapacity - flowValue) <= epsilon) { // No residual capacity on the
                                                                     // edge
                    it.remove();
                }
            }
            for (E edge : outEdges) {
                processQueue.add(Graphs.getOppositeVertex(graph, edge, vertex));
            }

            // 2. Get the backward edges with non-zero flow
            Set inEdges = new HashSet<>(graph.incomingEdgesOf(vertex));
            for (Iterator it = inEdges.iterator(); it.hasNext();) {
                E edge = it.next();

                // double edgeCapacity=graph.getEdgeWeight(edge);
                double flowValue = maxFlow.getFlow().get(edge);
                if (flowValue <= epsilon) { // There is no flow on this edge
                    it.remove();
                }
            }
            for (E edge : inEdges) {
                processQueue.add(Graphs.getOppositeVertex(graph, edge, vertex));
            }
        }
    }

    /**
     * Get the minimum cut partition containing the source.
     * 
     * @return Returns the minimum cut partition containing the source, or null if there was no call
     *         to computeMinCut(V source, V sink)
     */
    public Set getSourcePartition()
    {
        return Collections.unmodifiableSet(minCut);
    }

    /**
     * Returns the minimum cut partition containing the sink
     *
     * @return returns the minimum cut partition containing the sink
     */
    public Set getSinkPartition()
    {
        if (minCut == null) {
            return null;
        }
        Set set = new HashSet<>(graph.vertexSet());
        set.removeAll(minCut);
        return Collections.unmodifiableSet(set);
    }

    /**
     * Get the cut weight. This is equal to the max s-t flow
     *
     * @return cut weight
     */
    public double getCutWeight()
    {
        return cutWeight;
    }

    /**
     * Let S be the set containing the source, and T be the set containing the sink, i.e. T=V\S.
     * This method returns the edges which have their tail in S, and their head in T
     *
     * @return all edges which have their tail in S, and their head in T. If computeMinCut(V source,
     *         V sink) has not been invoked, this method returns null.
     */
    public Set getCutEdges()
    {
        if (minCut == null) {
            return null;
        }
        Set cutEdges = new HashSet<>();
        for (V vertex : minCut) {
            for (E edge : graph.outgoingEdgesOf(vertex)) {
                if (!minCut.contains(Graphs.getOppositeVertex(graph, edge, vertex))) {
                    cutEdges.add(edge);
                }
            }
        }
        return Collections.unmodifiableSet(cutEdges);
    }

    /**
     * Returns the source of the last call
     *
     * @return source of last minCut call, null if there was no call
     */
    public V getCurrentSource()
    {
        return source;
    }

    /**
     * Returns the sink of the last call
     *
     * @return sink of last minCut call, null if there was no call
     */
    public V getCurrentSink()
    {
        return sink;
    }
}

// End MinSourceSinkCut.java




© 2015 - 2025 Weber Informatics LLC | Privacy Policy