Skip to content

Commit

Permalink
Crude initial implementation of an orbit-saturating degree sequence g…
Browse files Browse the repository at this point in the history
…enerator
  • Loading branch information
gilleain committed Aug 11, 2012
1 parent 1458de3 commit 6d43db1
Show file tree
Hide file tree
Showing 2 changed files with 287 additions and 0 deletions.
250 changes: 250 additions & 0 deletions src/degreeseq/OrbitSaturatingGenerator.java
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;
}
}
37 changes: 37 additions & 0 deletions src/test/degreeseq/OrbitSaturatingGeneratorTest.java
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);
}

}

0 comments on commit 6d43db1

Please sign in to comment.