-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Crude initial implementation of an orbit-saturating degree sequence g…
…enerator
- Loading branch information
Showing
2 changed files
with
287 additions
and
0 deletions.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,250 @@ | ||
package degreeseq; | ||
|
||
import group.Permutation; | ||
import group.SSPermutationGroup; | ||
|
||
import java.util.ArrayList; | ||
import java.util.BitSet; | ||
import java.util.Collections; | ||
import java.util.Comparator; | ||
import java.util.HashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.Stack; | ||
|
||
import model.Graph; | ||
|
||
public class OrbitSaturatingGenerator { | ||
|
||
private int TMP_COUNT = 0; | ||
|
||
private List<Stack<Integer>> degreeOrbits; | ||
|
||
public void generate(int[] degSeq) { | ||
degreeOrbits = getOrbits(degSeq); | ||
generate(0, getOrbits(degSeq), new Graph(), degSeq); | ||
} | ||
|
||
public void generate( | ||
int orbit, List<Stack<Integer>> orbits, Graph parent, int[] degSeq) { | ||
// System.out.println("Orbit " + orbit + " of " + orbits + "\t" + parent); | ||
List<Graph> children = new ArrayList<Graph>(); | ||
saturateOrbit(orbit, orbits, parent, children, degSeq); | ||
for (Graph child : children) { | ||
List<Stack<Integer>> nextOrbits = getOrbits(child, degSeq); | ||
int unsaturatedOrbit = getFirstUnsaturatedOrbit(child, nextOrbits, degSeq); | ||
// System.out.println(child + "\t" + nextOrbits + "\t" + unsaturatedOrbit); | ||
BitSet component = new BitSet(); | ||
findComponent(child, 0, component); | ||
boolean isSSG = isSSG(component, child, degSeq); | ||
if (isSSG) { | ||
if (component.cardinality() == degSeq.length) { | ||
if (isCanonical(child, degreeOrbits)) { | ||
System.out.println("complete " + child | ||
+ "\t" + child.esize() | ||
+ "\t" + getCert(child, new Permutation(child.vsize())) | ||
); | ||
// + "\t" + isCanonical(child, degreeOrbits)); | ||
} | ||
} else { | ||
// System.out.println("SSG " + child); | ||
} | ||
} else { | ||
generate(unsaturatedOrbit, nextOrbits, child, degSeq); | ||
} | ||
} | ||
} | ||
|
||
public void saturateOrbit( | ||
int orbitIndex, List<Stack<Integer>> orbits, Graph g, List<Graph> children, int[] degSeq) { | ||
Stack<Integer> orbit = orbits.get(orbitIndex); | ||
if (orbit.isEmpty()) { | ||
children.add(g); | ||
} else { | ||
// System.out.println("Orbit " + orbitIndex + " now " + orbit); | ||
int v = orbit.pop(); | ||
List<Graph> vchildren = new ArrayList<Graph>(); | ||
// System.out.println("saturating vertex " + v); | ||
saturateVertex(v, v + 1, g, vchildren, orbits, degSeq); | ||
for (Graph h : vchildren) { | ||
saturateOrbit(orbitIndex, orbits, h, children, degSeq); | ||
} | ||
} | ||
} | ||
|
||
public void saturateVertex(int v, int start, Graph g, | ||
List<Graph> children, List<Stack<Integer>> orbits, int[] degSeq) { | ||
// if (!isCanonical(g, orbits)) return; | ||
int degree = g.degree(v); | ||
if (degSeq[v] == degree) { | ||
children.add(g); | ||
// System.out.println(TMP_COUNT + "\t" + g); TMP_COUNT++; | ||
return; | ||
} else { | ||
for (int w = start; w < degSeq.length; w++) { | ||
if (g.degree(w) < degSeq[w]) { | ||
Graph h = g.makeNew(v, w); | ||
saturateVertex(v, w + 1, h, children, orbits, degSeq); | ||
} | ||
} | ||
} | ||
} | ||
|
||
private boolean isCanonical(Graph g, List<Stack<Integer>> orbits) { | ||
int n = g.vsize(); | ||
if (n < 3) return true; | ||
String originalCert = getCert(g, new Permutation(n)); | ||
for (Stack<Integer> orbit : orbits) { | ||
int oN = orbit.size(); | ||
if (oN > 1) { | ||
SSPermutationGroup permutations = SSPermutationGroup.makeSymN(oN); | ||
for (Permutation p : permutations.all()) { | ||
Permutation fullP = new Permutation(n); | ||
for (int i = 0; i < oN; i++) { | ||
int x = orbit.get(i); | ||
int y = orbit.get(p.get(i)); | ||
fullP.set(x, y); | ||
} | ||
String pCert = getCert(g, fullP); | ||
// System.out.println(pCert); | ||
if (originalCert.compareTo(pCert) < 0) { | ||
return false; | ||
} | ||
} | ||
} | ||
} | ||
return true; | ||
} | ||
|
||
private String getCert(Graph g, Permutation p) { | ||
StringBuffer cert = new StringBuffer(); | ||
int n = g.vsize(); | ||
for (int i = 0; i < n; i++) { | ||
for (int j = i + 1; j < n; j++) { | ||
if (g.hasEdge(p.get(i), p.get(j))) { | ||
cert.append("1"); | ||
} else { | ||
cert.append("0"); | ||
} | ||
} | ||
} | ||
return cert.toString(); | ||
} | ||
|
||
private boolean isSSG(BitSet component, Graph g, int[] degSeq) { | ||
for (int i = 0; i < degSeq.length; i++) { | ||
if (component.get(i) && g.degree(i) < degSeq[i]) { | ||
return false; | ||
} | ||
} | ||
return true; | ||
} | ||
|
||
private void findComponent(Graph g, int i, BitSet seen) { | ||
if (seen.get(i)) { | ||
return; | ||
} else { | ||
seen.set(i); | ||
for (int n : g.getConnected(i)) { | ||
findComponent(g, n, seen); | ||
} | ||
} | ||
} | ||
|
||
private int getFirstUnsaturatedOrbit(Graph g, List<Stack<Integer>> orbits, int[] degSeq) { | ||
int orbitIndex = 0; | ||
while (orbitIndex < orbits.size()) { | ||
Stack<Integer> orbit = orbits.get(orbitIndex); | ||
int rep = orbit.get(0); | ||
if (g.degree(rep) < degSeq[rep]) { | ||
return orbitIndex; | ||
} | ||
orbitIndex++; | ||
} | ||
return orbitIndex; | ||
} | ||
|
||
private List<Stack<Integer>> getOrbits(Graph g, int[] degSeq) { | ||
int n = g.getVertexCount(); | ||
|
||
// use Morgan numbers to partition vertices | ||
int[] labels = new int[n]; | ||
for (int i = 0; i < n; i++) { | ||
int d = g.degree(i); | ||
labels[i] = d; | ||
} | ||
for (int round = 0; round < n; round++) { | ||
int[] newLabels = new int[n]; | ||
for (int i = 0; i < n; i++) { | ||
for (int j : g.getConnected(i)) { | ||
newLabels[i] += labels[j]; | ||
} | ||
} | ||
labels = newLabels; | ||
} | ||
// System.out.println("labels for " + g + " = " + Arrays.toString(labels)); | ||
|
||
// convert these labels into orbits | ||
Map<Integer, Stack<Integer>> orbitMap = new HashMap<Integer, Stack<Integer>>(); | ||
for (int i = 0; i < n; i++) { | ||
int l = labels[i]; | ||
Stack<Integer> orbit; | ||
if (orbitMap.containsKey(l)) { | ||
orbit = orbitMap.get(l); | ||
} else { | ||
orbit = new Stack<Integer>(); | ||
orbitMap.put(l, orbit); | ||
} | ||
orbit.add(0, new Integer(i)); | ||
} | ||
|
||
// split the orbits using the target degree sequence | ||
List<Stack<Integer>> orbits = new ArrayList<Stack<Integer>>(); | ||
for (Stack<Integer> orbit : orbitMap.values()) { | ||
// UGH! | ||
Map<Integer, Stack<Integer>> degreeMap = new HashMap<Integer, Stack<Integer>>(); | ||
for (int i : orbit) { | ||
int d = degSeq[i]; | ||
Stack<Integer> subOrbit; | ||
if (degreeMap.containsKey(d)) { | ||
subOrbit = degreeMap.get(d); | ||
} else { | ||
subOrbit = new Stack<Integer>(); | ||
degreeMap.put(d, subOrbit); | ||
} | ||
subOrbit.add(i); | ||
} | ||
orbits.addAll(degreeMap.values()); | ||
} | ||
|
||
Collections.sort(orbits, new Comparator<Stack<Integer>>() { | ||
|
||
@Override | ||
public int compare(Stack<Integer> a, Stack<Integer> b) { | ||
return a.get(a.size() - 1).compareTo(b.get(b.size() - 1)); | ||
} | ||
|
||
}); | ||
|
||
return orbits; | ||
} | ||
|
||
private List<Stack<Integer>> getOrbits(int[] degSeq) { | ||
List<Stack<Integer>> orbits = new ArrayList<Stack<Integer>>(); | ||
Stack<Integer> currentOrbit = null; | ||
for (int i = 0; i < degSeq.length; i++) { | ||
if (i == 0) { | ||
currentOrbit = new Stack<Integer>(); | ||
currentOrbit.add(0); | ||
orbits.add(currentOrbit); | ||
} else { | ||
if (degSeq[i] != degSeq[i - 1]) { | ||
currentOrbit = new Stack<Integer>(); | ||
orbits.add(currentOrbit); | ||
} | ||
currentOrbit.add(0, new Integer(i)); | ||
} | ||
} | ||
return orbits; | ||
} | ||
} |
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,37 @@ | ||
package test.degreeseq; | ||
|
||
import org.junit.Test; | ||
|
||
import degreeseq.OrbitSaturatingGenerator; | ||
|
||
public class OrbitSaturatingGeneratorTest { | ||
|
||
@Test | ||
public void test_333333() { | ||
int[] degSeq = new int[] { 3, 3, 3, 3, 3, 3 }; | ||
OrbitSaturatingGenerator generator = new OrbitSaturatingGenerator(); | ||
generator.generate(degSeq); | ||
} | ||
|
||
@Test | ||
public void test_33_22_11() { | ||
int[] degSeq = new int[] { 3, 3, 2, 2, 1, 1 }; | ||
OrbitSaturatingGenerator generator = new OrbitSaturatingGenerator(); | ||
generator.generate(degSeq); | ||
} | ||
|
||
@Test | ||
public void test_3_22_1() { | ||
int[] degSeq = new int[] { 3, 2, 2, 1 }; | ||
OrbitSaturatingGenerator generator = new OrbitSaturatingGenerator(); | ||
generator.generate(degSeq); | ||
} | ||
|
||
@Test | ||
public void test_2222() { | ||
int[] degSeq = new int[] { 2, 2, 2, 2 }; | ||
OrbitSaturatingGenerator generator = new OrbitSaturatingGenerator(); | ||
generator.generate(degSeq); | ||
} | ||
|
||
} |