Commit 275eaf00 authored by sbalev's avatar sbalev

Trees

parent 78d6e5cd
class Breaker {
final CodeToolkit tk;
Node root;
int [] histogram;
float fitness;
Breaker(CodeToolkit tk) {
this.tk = tk;
root = new Node(tk);
train();
root.shrink();
root.triangleOpt();
computeFitness();
}
void train() {
boolean[] used = new boolean[tk.M];
int[] unused = new int[tk.M];
for (int code = 0; code < tk.M; code++) {
for (int k = 0; k < tk.M; k++) {
used[k] = false;
}
root.followPath(code, used, unused);
}
}
void display(int x, int y, int pegSize) {
root.display(x, y, pegSize);
}
int getMax() {
return histogram.length - 1;
}
float getAvg() {
return fitness;
}
int[] getDistribution() {
return histogram;
}
void computeFitness() {
int h = root.height();
histogram = new int[h + 1];
root.histogram(1, histogram);
int s = 0;
for (int i = 1; i <= h; i++) {
s += i * histogram[i];
}
fitness = s / float(tk.M);
}
}
class Node {
final int BRANCH_HEIGHT = 10;
final CodeToolkit tk;
int guess;
boolean good;
Node[] children;
Node(CodeToolkit tk) {
this.tk = tk;
guess = int(random(tk.M));
good = false;
children = new Node[tk.F];
}
void followPath(int code, boolean[] used, int[] unused) {
used[guess] = true;
int f = tk.feedback(code, guess);
if (f == 0) {
good = true;
} else if (children[f] != null) {
children[f].followPath(code, used, unused);
} else {
int count = 0;
for (int k = 0; k < tk.M; k++) {
if (!used[k]) {
unused[count++] = k;
}
}
children[f] = new Node(tk);
children[f].buildPath(code, unused, count);
}
}
void buildPath(int code, int[] unused, int count) {
int k = int(random(count));
guess = unused[k];
unused[k] = unused[count - 1];
int f = tk.feedback(code, guess);
if (f == 0) {
good = true;
} else {
children[f] = new Node(tk);
children[f].buildPath(code, unused, count - 1);
}
}
Node shrink() {
int childCount = 0;
Node lastChild = null;
for (int f = 0; f < tk.F; f++) {
if (children[f] != null) {
children[f] = children[f].shrink();
childCount++;
lastChild = children[f];
}
}
return !good && childCount == 1 ? lastChild : this;
}
int triangleOpt() {
int count = 0;
int f1 = 0;
int f2 = 0;
int s = 0;
for (int f = 0; f < tk.F; f++) {
if (children[f] != null) {
s += children[f].triangleOpt();
count++;
if (count == 1) {
f1 = f;
} else if (count == 2) {
f2 = f;
}
}
}
if (!good && count == 2 && s == 0) {
if (int(random(2)) == 1) {
int t = f1;
f1 = f2;
f2 = t;
}
guess = children[f1].guess;
good = true;
children[f1] = null;
int f = tk.feedback(guess, children[f2].guess);
if (f != f2) {
children[f] = children[f2];
children[f2] = null;
}
}
return count;
}
int height() {
int h = 0;
for (Node child : children) {
if (child != null) h = max(h, child.height());
}
return 1 + h;
}
void histogram(int level, int[] histo) {
if (good) histo[level]++;
for (Node child : children) {
if (child != null) {
child.histogram(level + 1, histo);
}
}
}
// display stuff
int breadth() {
int b = 0;
for (Node child : children) {
if (child != null) b += child.breadth();
}
return max(b, 1);
}
void display(int x, int y, int pegSize) {
IntList xc = new IntList();
xc.append(x);
for (Node child : children) {
if (child != null) {
child.display(x, y + BRANCH_HEIGHT * pegSize, pegSize);
x += (tk.N + 1) * pegSize * child.breadth();
xc.append(x);
}
}
int n = xc.size();
int x0 = (xc.get(0) + xc.get(n - 1)) / 2;
int f = 0;
for (int i = 1; i < n; i++) {
while (children[f] == null) f++;
int x1 = (xc.get(i - 1) + xc.get(i)) / 2;
stroke(0);
line(x0, y + pegSize, x1, y + BRANCH_HEIGHT * pegSize);
displayLabel(f, (x0 + x1) / 2.0, y + (BRANCH_HEIGHT + 1) / 2.0 * pegSize, pegSize);
f++;
}
if (n > 1) {
x0 -= tk.N * pegSize / 2;
} else {
x0 += pegSize / 2;
}
tk.displayCode(guess, x0, y, pegSize, !good);
}
void displayLabel(int f, float x, float y, int size) {
int[] bw = new int[2];
tk.decodeFeedback(f, bw);
String label = bw[0] + "," + bw[1];
textSize(size);
float w = textWidth(label);
noStroke();
fill(255);
rectMode(CENTER);
rect(x, y, w, size);
fill(0);
textAlign(CENTER, CENTER);
text(label, x, y);
}
}
../../lib/Breaker.pde
\ No newline at end of file
../../lib/CodeToolkit.pde
\ No newline at end of file
../../lib/Node.pde
\ No newline at end of file
CodeToolkit tk = new CodeToolkit(3, 3);
void setup() {
size(1000, 600);
// randomSeed(42); // for the first example
// randomSeed(6262); // for the second example
}
void draw() {
}
void mousePressed() {
Breaker b = new Breaker(tk);
background(255);
b.display(0, 10, 10);
println("Avg:", b.getAvg());
println("Max:", b.getMax());
println("Distribution:");
println(b.getDistribution());
println("---");
}
../../lib/Breaker.pde
\ No newline at end of file
../../lib/CodeToolkit.pde
\ No newline at end of file
../../lib/Node.pde
\ No newline at end of file
CodeToolkit tk = new CodeToolkit(4, 6);
final int POP_SIZE = 1000;
void setup() {
randomSeed(42);
float sum = 0;
float sumSq = 0;
float fMin = Float.POSITIVE_INFINITY;
float fMax = 0;
for (int i = 0; i < POP_SIZE; i++) {
if (i % 10 == 0) println(i);
Breaker b = new Breaker(tk);
float f = b.getAvg();
sum += f;
sumSq += f * f;
fMin = min(fMin, f);
fMax = max(fMax, f);
}
float avg = sum / POP_SIZE;
float sigma = sqrt((sumSq - sum * sum / POP_SIZE) / POP_SIZE);
println("Min", fMin);
println("Max", fMax);
println("Avg", avg);
println("Dev", sigma);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment