forked from lingeringsocket/jgrapht
-
Notifications
You must be signed in to change notification settings - Fork 822
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactoring ChordalityInspector and interface revision #547
Merged
Merged
Changes from 7 commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
7e4cb64
Added new interfaces
d90bf5b
fixed typo in clique interface
ea077cd
fixed typo in documentation
137ec43
Implemented WeightedUnmodifiableSet
jkinable 79a0d42
Deprecated MinimumVertexCoverAlgorithm and MinimumWeightedVertexCover…
jkinable e592d99
Updated SpannerAlgorithm interface
jkinable 590eb7b
moved vertex cover test classes to corresponding vertexcover test pac…
jkinable 99d2552
updated comments
jkinable a1da34c
Merge branch 'master' of https://github.com/jkinable/jgrapht into ref…
jkinable be3f442
added change proposed in PR 489
jkinable d3197d3
fixed merge conflict
jkinable File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
160 changes: 160 additions & 0 deletions
160
jgrapht-core/src/main/java/org/jgrapht/alg/clique/ChordalGraphMaxCliqueFinder.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
/* | ||
* (C) Copyright 2018-2018, by Timofey Chudakov 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.clique; | ||
|
||
import org.jgrapht.Graph; | ||
import org.jgrapht.Graphs; | ||
import org.jgrapht.alg.color.ChordalGraphColoring; | ||
import org.jgrapht.alg.cycle.ChordalityInspector; | ||
import org.jgrapht.alg.interfaces.CliqueAlgorithm; | ||
import org.jgrapht.alg.interfaces.VertexColoringAlgorithm; | ||
import org.jgrapht.traverse.LexBreadthFirstIterator; | ||
import org.jgrapht.traverse.MaximumCardinalityIterator; | ||
|
||
import java.util.*; | ||
|
||
/** | ||
* Calculates a <a href = "http://mathworld.wolfram.com/MaximumClique.html">maximum cardinality clique</a> in a <a href="https://en.wikipedia.org/wiki/Chordal_graph">chordal graph</a>. | ||
* A chordal graph is a simple graph in which all <a href="http://mathworld.wolfram.com/GraphCycle.html"> | ||
* cycles</a> of four or more vertices have a <a href="http://mathworld.wolfram.com/CycleChord.html"> | ||
* chord</a>. A chord is an edge that is not part of the cycle but connects two vertices of the cycle. | ||
* | ||
* To compute the clique, this implementation relies on the {@link ChordalityInspector} to compute a | ||
* <a href="https://en.wikipedia.org/wiki/Chordal_graph#Perfect_elimination_and_efficient_recognition"> | ||
* perfect elimination order</a>. | ||
* | ||
* The maximum clique for a chordal graph is computed in $\mathcal{O}(|V| + |E|)$ time. | ||
* | ||
* All the methods in this class are invoked in a lazy fashion, meaning that computations are only | ||
* started once the method gets invoked. | ||
* | ||
* @param <V> the graph vertex type. | ||
* @param <E> the graph edge type. | ||
* | ||
* @author Timofey Chudakov | ||
* @since March 2018 | ||
*/ | ||
public class ChordalGraphMaxCliqueFinder<V,E> implements CliqueAlgorithm<V>{ | ||
|
||
private final Graph<V,E> graph; | ||
|
||
private final ChordalityInspector<V,E> chordalityInspector; | ||
|
||
private final VertexColoringAlgorithm<V> coloringAlgorithm; | ||
|
||
private Clique<V> maximumClique; | ||
private boolean isChordal=true; | ||
|
||
/** | ||
* Creates a new ChordalGraphMaxCliqueFinder instance. The {@link ChordalityInspector} used in this implementation uses | ||
* the default {@link MaximumCardinalityIterator} iterator. | ||
* | ||
* @param graph graph | ||
*/ | ||
public ChordalGraphMaxCliqueFinder(Graph<V, E> graph) { | ||
this(graph, ChordalityInspector.IterationOrder.MCS); | ||
} | ||
|
||
/** | ||
* Creates a new ChordalGraphMaxCliqueFinder instance. The {@link ChordalityInspector} used in this implementation uses | ||
* either the {@link MaximumCardinalityIterator} iterator or the {@link LexBreadthFirstIterator} iterator, depending | ||
* on the parameter {@code iterationOrder}. | ||
* | ||
* @param graph graph | ||
* @param iterationOrder constant which defines iterator to be used by the {@code ChordalityInspector} in this implementation. | ||
*/ | ||
public ChordalGraphMaxCliqueFinder(Graph<V, E> graph, ChordalityInspector.IterationOrder iterationOrder) { | ||
this.graph = Objects.requireNonNull(graph); | ||
chordalityInspector= new ChordalityInspector<>(graph, iterationOrder); | ||
coloringAlgorithm = new ChordalGraphColoring<>(graph, iterationOrder); | ||
} | ||
|
||
/** | ||
* Lazily computes some maximum clique of the {@code graph}. Returns null if the graph isn't chordal. | ||
*/ | ||
private void lazyComputeMaximumClique() { | ||
if (maximumClique == null && isChordal) { | ||
ChordalGraphColoring<V,E> cgc= new ChordalGraphColoring<>(graph); | ||
VertexColoringAlgorithm.Coloring<V> coloring = cgc.getColoring(); | ||
List<V> perfectEliminationOrder=cgc.getPerfectEliminationOrder(); | ||
if (coloring == null) { | ||
isChordal = false; //Graph isn't chordal | ||
return; | ||
} | ||
// finds the vertex with the maximum cardinality predecessor list | ||
Map<V, Integer> vertexInOrder = getVertexInOrder(perfectEliminationOrder); | ||
Map.Entry<V, Integer> maxEntry = coloring.getColors().entrySet().stream().max( | ||
Comparator.comparing(Map.Entry::getValue)).orElse(null); | ||
if (maxEntry == null) { | ||
maximumClique = new CliqueImpl<>(Collections.emptySet()); | ||
} else { | ||
Set<V> cliqueSet= getPredecessors(vertexInOrder, maxEntry.getKey()); | ||
cliqueSet.add(maxEntry.getKey()); | ||
maximumClique= new CliqueImpl<>(cliqueSet); | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* Returns a map containing vertices from the {@code vertexOrder} mapped to their | ||
* indices in {@code vertexOrder}. | ||
* | ||
* @param vertexOrder a list with vertices. | ||
* @return a mapping of vertices from {@code vertexOrder} to their indices in {@code vertexOrder}. | ||
*/ | ||
private Map<V, Integer> getVertexInOrder(List<V> vertexOrder) { | ||
Map<V, Integer> vertexInOrder = new HashMap<>(vertexOrder.size()); | ||
int i = 0; | ||
for (V vertex : vertexOrder) { | ||
vertexInOrder.put(vertex, i++); | ||
} | ||
return vertexInOrder; | ||
} | ||
|
||
/** | ||
* Returns the predecessors of {@code vertex} in the order defined by {@code map}. More precisely, | ||
* returns those of {@code vertex}, whose mapped index in {@code map} is less then the index of {@code vertex}. | ||
* | ||
* @param vertexInOrder defines the mapping of vertices in {@code graph} to their indices in order. | ||
* @param vertex the vertex whose predecessors in order are to be returned. | ||
* @return the predecessors of {@code vertex} in order defines by {@code map}. | ||
*/ | ||
private Set<V> getPredecessors(Map<V, Integer> vertexInOrder, V vertex) { | ||
Set<V> predecessors = new HashSet<>(); | ||
Integer vertexPosition = vertexInOrder.get(vertex); | ||
Set<E> edges = graph.edgesOf(vertex); | ||
for (E edge : edges) { | ||
V oppositeVertex = Graphs.getOppositeVertex(graph, edge, vertex); | ||
Integer destPosition = vertexInOrder.get(oppositeVertex); | ||
if (destPosition < vertexPosition) | ||
predecessors.add(oppositeVertex); | ||
} | ||
return predecessors; | ||
} | ||
|
||
/** | ||
* Returns a <a href="http://mathworld.wolfram.com/MaximumClique.html">maximum cardinality clique</a> | ||
* of the inspected {@code graph}. If the graph isn't chordal, returns null. | ||
* | ||
* @return a maximum clique of the {@code graph} if it is chordal, null otherwise. | ||
*/ | ||
public Clique<V> getClique() { | ||
lazyComputeMaximumClique(); | ||
return maximumClique; | ||
} | ||
} |
167 changes: 167 additions & 0 deletions
167
jgrapht-core/src/main/java/org/jgrapht/alg/color/ChordalGraphColoring.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
/* | ||
* (C) Copyright 2018-2018, by Timofey Chudakov 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.color; | ||
|
||
import org.jgrapht.Graph; | ||
import org.jgrapht.Graphs; | ||
import org.jgrapht.alg.cycle.ChordalityInspector; | ||
import org.jgrapht.alg.interfaces.VertexColoringAlgorithm; | ||
import org.jgrapht.traverse.LexBreadthFirstIterator; | ||
import org.jgrapht.traverse.MaximumCardinalityIterator; | ||
|
||
import java.util.*; | ||
|
||
/** | ||
* Calculates a <a href="http://mathworld.wolfram.com/MinimumVertexColoring.html">minimum vertex coloring</a> for a <a href="https://en.wikipedia.org/wiki/Chordal_graph">chordal graph</a>. | ||
* A chordal graph is a simple graph in which all <a href="http://mathworld.wolfram.com/GraphCycle.html"> | ||
* cycles</a> of four or more vertices have a <a href="http://mathworld.wolfram.com/CycleChord.html"> | ||
* chord</a>. A chord is an edge that is not part of the cycle but connects two vertices of the cycle. | ||
* | ||
* To compute the vertex coloring, this implementation relies on the {@link ChordalityInspector} to compute a | ||
* <a href="https://en.wikipedia.org/wiki/Chordal_graph#Perfect_elimination_and_efficient_recognition"> | ||
* perfect elimination order</a>. | ||
* | ||
* The vertex coloring for a chordal graph is computed in $\mathcal{O}(|V| + |E|)$ time. | ||
* | ||
* All the methods in this class are invoked in a lazy fashion, meaning that computations are only | ||
* started once the method gets invoked. | ||
* | ||
* @param <V> the graph vertex type. | ||
* @param <E> the graph edge type. | ||
* | ||
* @author Timofey Chudakov | ||
* @since March 2018 | ||
*/ | ||
public class ChordalGraphColoring<V,E> implements VertexColoringAlgorithm<V> { | ||
|
||
private final Graph<V,E> graph; | ||
|
||
private final ChordalityInspector<V,E> chordalityInspector; | ||
|
||
private Coloring<V> coloring; | ||
|
||
/** | ||
* Creates a new ChordalGraphColoring instance. The {@link ChordalityInspector} used in this implementation uses | ||
* the default {@link MaximumCardinalityIterator} iterator. | ||
* | ||
* @param graph graph | ||
*/ | ||
public ChordalGraphColoring(Graph<V, E> graph) { | ||
this(graph, ChordalityInspector.IterationOrder.MCS); | ||
} | ||
|
||
/** | ||
* Creates a new ChordalGraphColoring instance. The {@link ChordalityInspector} used in this implementation uses | ||
* either the {@link MaximumCardinalityIterator} iterator or the {@link LexBreadthFirstIterator} iterator, depending | ||
* on the parameter {@code iterationOrder}. | ||
* | ||
* @param graph graph | ||
* @param iterationOrder constant which defines iterator to be used by the {@code ChordalityInspector} in this implementation. | ||
*/ | ||
public ChordalGraphColoring(Graph<V, E> graph, ChordalityInspector.IterationOrder iterationOrder) { | ||
this.graph = Objects.requireNonNull(graph); | ||
chordalityInspector= new ChordalityInspector<>(graph, iterationOrder); | ||
} | ||
|
||
|
||
/** | ||
* Lazily computes the coloring of the graph. | ||
*/ | ||
private void lazyComputeColoring() { | ||
if (coloring == null && chordalityInspector.isChordal()) { | ||
List<V> perfectEliminationOrder=chordalityInspector.getPerfectEliminationOrder(); | ||
|
||
Map<V, Integer> vertexColoring = new HashMap<>(perfectEliminationOrder.size()); | ||
Map<V, Integer> vertexInOrder = getVertexInOrder(perfectEliminationOrder); | ||
for (V vertex : perfectEliminationOrder) { | ||
Set<V> predecessors = getPredecessors(vertexInOrder, vertex); | ||
Set<Integer> predecessorColors = new HashSet<>(predecessors.size()); | ||
predecessors.forEach(v -> predecessorColors.add(vertexColoring.get(v))); | ||
|
||
// find the minimum unused color in the set of predecessors | ||
int minUnusedColor = 0; | ||
while (predecessorColors.contains(minUnusedColor)) { | ||
++minUnusedColor; | ||
} | ||
vertexColoring.put(vertex, minUnusedColor); | ||
} | ||
int maxColor = (int) vertexColoring.values().stream().distinct().count(); | ||
coloring = new ColoringImpl<>(vertexColoring, maxColor); | ||
} | ||
} | ||
|
||
/** | ||
* Returns a map containing vertices from the {@code vertexOrder} mapped to their | ||
* indices in {@code vertexOrder}. | ||
* | ||
* @param vertexOrder a list with vertices. | ||
* @return a mapping of vertices from {@code vertexOrder} to their indices in {@code vertexOrder}. | ||
*/ | ||
private Map<V, Integer> getVertexInOrder(List<V> vertexOrder) { | ||
Map<V, Integer> vertexInOrder = new HashMap<>(vertexOrder.size()); | ||
int i = 0; | ||
for (V vertex : vertexOrder) { | ||
vertexInOrder.put(vertex, i++); | ||
} | ||
return vertexInOrder; | ||
} | ||
|
||
/** | ||
* Returns the predecessors of {@code vertex} in the order defined by {@code map}. More precisely, | ||
* returns those of {@code vertex}, whose mapped index in {@code map} is less then the index of {@code vertex}. | ||
* | ||
* @param vertexInOrder defines the mapping of vertices in {@code graph} to their indices in order. | ||
* @param vertex the vertex whose predecessors in order are to be returned. | ||
* @return the predecessors of {@code vertex} in order defines by {@code map}. | ||
*/ | ||
private Set<V> getPredecessors(Map<V, Integer> vertexInOrder, V vertex) { | ||
Set<V> predecessors = new HashSet<>(); | ||
Integer vertexPosition = vertexInOrder.get(vertex); | ||
Set<E> edges = graph.edgesOf(vertex); | ||
for (E edge : edges) { | ||
V oppositeVertex = Graphs.getOppositeVertex(graph, edge, vertex); | ||
Integer destPosition = vertexInOrder.get(oppositeVertex); | ||
if (destPosition < vertexPosition) | ||
predecessors.add(oppositeVertex); | ||
} | ||
return predecessors; | ||
} | ||
|
||
/** | ||
* Returns a <a href="http://mathworld.wolfram.com/MinimumVertexColoring.html">minimum vertex coloring</a> | ||
* of the inspected {@code graph}. If the graph isn't chordal, returns null. The number of colors used in | ||
* the coloring equals the chromatic number of the input graph. | ||
* | ||
* @return a coloring of the {@code graph} if it is chordal, null otherwise. | ||
*/ | ||
@Override | ||
public Coloring<V> getColoring() { | ||
lazyComputeColoring(); | ||
return coloring; | ||
} | ||
|
||
/** | ||
* Returns the <a href="https://en.wikipedia.org/wiki/Chordal_graph#Perfect_elimination_and_efficient_recognition"> | ||
* perfect elimination order</a> used to create the coloring (if one exists). This method returns null if the graph is not chordal. | ||
* | ||
* @return the perfect elimination order used to create the coloring, or null if graph is not chordal. | ||
*/ | ||
public List<V> getPerfectEliminationOrder(){ | ||
return chordalityInspector.getPerfectEliminationOrder(); | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method doesn't return anything.