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

org.jgrapht.alg.matching.GreedyMaximumCardinalityMatching Maven / Gradle / Ivy

/*
 * (C) Copyright 2017-2021, by Joris Kinable and Contributors.
 *
 * JGraphT : a free Java graph-theory library
 *
 * See the CONTRIBUTORS.md file distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0, or the
 * GNU Lesser General Public License v2.1 or later
 * which is available at
 * http://www.gnu.org/licenses/old-licenses/lgpl-2.1-standalone.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR LGPL-2.1-or-later
 */
package org.jgrapht.alg.matching;

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

import java.util.*;

/**
 * The greedy algorithm for computing a maximum cardinality matching. The algorithm can run in two
 * modes: sorted or unsorted. When unsorted, the matching is obtained by iterating through the edges
 * and adding an edge if it doesn't conflict with the edges already in the matching. When sorted,
 * the edges are first sorted by the sum of degrees of their endpoints. After that, the algorithm
 * proceeds in the same manner. Running this algorithm in sorted mode can sometimes produce better
 * results, albeit at the cost of some additional computational overhead.
 * 

* Independent of the mode, the resulting matching is maximal, and is therefore guaranteed to * contain at least half of the edges that a maximum cardinality matching has ($\frac{1}{2}$ * approximation). Runtime complexity: $O(m)$ when the edges are not sorted, $O(m + m \log n)$ * otherwise, where $n$ is the number of vertices, and $m$ the number of edges. * * @param the graph vertex type * @param the graph edge type * * @author Joris Kinable */ public class GreedyMaximumCardinalityMatching implements MatchingAlgorithm { private final Graph graph; private final boolean sort; /** * Creates a new GreedyMaximumCardinalityMatching instance. * * @param graph graph * @param sort sort the edges prior to starting the greedy algorithm */ public GreedyMaximumCardinalityMatching(Graph graph, boolean sort) { this.graph = GraphTests.requireUndirected(graph); this.sort = sort; } /** * Get a matching that is a $\frac{1}{2}$-approximation of the maximum cardinality matching. * * @return a matching */ @Override public Matching getMatching() { Set matched = new HashSet<>(); Set edges = new LinkedHashSet<>(); double cost = 0; if (sort) { // sort edges in increasing order of the total degree of their endpoints List allEdges = new ArrayList<>(graph.edgeSet()); allEdges.sort(new EdgeDegreeComparator()); for (E e : allEdges) { V v = graph.getEdgeSource(e); V w = graph.getEdgeTarget(e); if (!v.equals(w) && !matched.contains(v) && !matched.contains(w)) { edges.add(e); matched.add(v); matched.add(w); cost += graph.getEdgeWeight(e); } } } else { for (V v : graph.vertexSet()) { if (matched.contains(v)) continue; for (E e : graph.edgesOf(v)) { V w = Graphs.getOppositeVertex(graph, e, v); if (!v.equals(w) && !matched.contains(w)) { edges.add(e); matched.add(v); matched.add(w); cost += graph.getEdgeWeight(e); break; } } } } return new MatchingImpl<>(graph, edges, cost); } private class EdgeDegreeComparator implements Comparator { @Override public int compare(E e1, E e2) { int degreeE1 = graph.degreeOf(graph.getEdgeSource(e1)) + graph.degreeOf(graph.getEdgeTarget(e1)); int degreeE2 = graph.degreeOf(graph.getEdgeSource(e2)) + graph.degreeOf(graph.getEdgeTarget(e2)); return Integer.compare(degreeE1, degreeE2); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy