jsbayes
Version:
Simple Bayesian Belief Network (BBN) library in JavaScript.
464 lines (381 loc) • 12.3 kB
JavaScript
var should = require('chai').should()
expect = require('chai').expect;
var jsbayes = require('../jsbayes');
describe('#graph', function() {
it('verifies no node', function() {
var g = jsbayes.newGraph();
expect(g.nodes.length).to.equal(0);
});
it('verifies nodes added', function() {
var g = jsbayes.newGraph();
var n1 = g.addNode('n1', ['t', 'f']);
var n2 = g.addNode('n2', ['t', 'f']);
var n3 = g.addNode('n3', ['t', 'f']);
expect(g.nodes.length).to.equal(3);
});
it('verifies parent nodes added', function() {
var g = jsbayes.newGraph();
var n1 = g.addNode('n1', ['t', 'f']);
var n2 = g.addNode('n2', ['t', 'f']);
var n3 = g.addNode('n3', ['t', 'f']);
n2.addParent(n1);
n3.addParent(n1).addParent(n2);
expect(n1.parents.length).to.equal(0);
expect(n2.parents.length).to.equal(1);
expect(n3.parents.length).to.equal(2);
});
it('verifies binary cpt initialization', function() {
var g = jsbayes.newGraph();
var n1 = g.addNode('n1', ['t', 'f']);
var n2 = g.addNode('n2', ['t', 'f']);
var n3 = g.addNode('n3', ['t', 'f']);
n2.addParent(n1);
n3.addParent(n1).addParent(n2);
g.reinit();
expect(n1.cpt.length).to.equal(2);
expect(n2.cpt.length).to.equal(2);
expect(n2.cpt[0].length).to.equal(2);
expect(n2.cpt[1].length).to.equal(2);
expect(n3.cpt.length).to.equal(2);
expect(n3.cpt[0].length).to.equal(2);
expect(n3.cpt[0][0].length).to.equal(2);
expect(n3.cpt[0][1].length).to.equal(2);
expect(n3.cpt[1].length).to.equal(2);
expect(n3.cpt[1][0].length).to.equal(2);
expect(n3.cpt[1][1].length).to.equal(2);
});
it('verifies non-binary cpt initialization', function() {
var g = jsbayes.newGraph();
var n1 = g.addNode('n1', ['a', 'b', 'c']);
var n2 = g.addNode('n2', ['a', 'b']);
var n3 = g.addNode('n3', ['a', 'b', 'c']);
n2.addParent(n1);
n3.addParent(n2);
g.reinit();
expect(n1.cpt.length).to.equals(3);
expect(n2.cpt.length).to.equals(3);
expect(n2.cpt[0].length).to.equals(2);
expect(n2.cpt[1].length).to.equals(2);
expect(n2.cpt[2].length).to.equals(2);
expect(n3.cpt.length).to.equals(2);
expect(n3.cpt[0].length).to.equals(3);
expect(n3.cpt[1].length).to.equals(3);
});
it('verfies sampling', function() {
var g = jsbayes.newGraph();
var n1 = g.addNode('n1', ['t', 'f']);
var n2 = g.addNode('n2', ['t', 'f']);
var n3 = g.addNode('n3', ['t', 'f']);
n2.addParent(n1);
n3.addParent(n2);
n1.cpt = [ 0.5, 0.5 ];
n2.cpt = [ [ 0.5, 0.5 ], [ 0.5, 0.5 ] ];
n3.cpt = [ [ 0.5, 0.5 ], [ 0.5, 0.5 ] ];
var r = g.sample(10000)
.then(function(r) {
expect(r).to.equals(10000);
expect(n1.sampledLw.length).to.equal(2);
var s1 = n1.sampledLw[0];
var s2 = n1.sampledLw[1];
var v1 = s1 / (s1 + s2);
var v2 = s2 / (s1 + s2);
expect(v1).to.be.within(0.49, 0.51);
expect(v2).to.be.within(0.49, 0.51);
expect(n2.sampledLw.length).to.equal(2);
s1 = n2.sampledLw[0];
s2 = n2.sampledLw[1];
v1 = s1 / (s1 + s2);
v2 = s2 / (s1 + s2);
expect(v1).to.be.within(0.49, 0.51);
expect(v2).to.be.within(0.49, 0.51);
expect(n3.sampledLw.length).to.equal(2);
s1 = n3.sampledLw[0];
s2 = n3.sampledLw[1];
v1 = s1 / (s1 + s2);
v2 = s2 / (s1 + s2);
expect(v1).to.be.within(0.49, 0.51);
expect(v2).to.be.within(0.49, 0.51);
})
.catch(function(e) {
assert(true == false, 'Exception occurred: ' + e);
});
});
it('verifies sampling with observation', function() {
var g = jsbayes.newGraph();
var n1 = g.addNode('n1', ['t', 'f']);
var n2 = g.addNode('n2', ['t', 'f']);
var n3 = g.addNode('n3', ['t', 'f']);
n2.addParent(n1);
n3.addParent(n2);
n1.cpt = [ 0.5, 0.5 ];
n2.cpt = [ [ 0.2, 0.8 ], [ 0.5, 0.5 ] ];
n3.cpt = [ [ 0.5, 0.5 ], [ 0.5, 0.5 ] ];
n1.value = 0;
n1.isObserved = true;
g.sample(10000);
var probs = n1.probs();
var p1 = probs[0];
var p2 = probs[1];
expect(p1).to.be.within(0.99, 1.0);
expect(p2).to.be.within(0.0, 0.0);
probs = n2.probs();
p1 = probs[0];
p2 = probs[1];
expect(p1).to.be.within(0.19,0.21);
expect(p2).to.be.within(0.79,0.81);
probs = n3.probs();
p1 = probs[0];
p2 = probs[1];
expect(p1).to.be.within(0.49,0.51);
expect(p2).to.be.within(0.49,0.51);
n1.isObserved = false;
g.sample(10000);
probs = n1.probs();
p1 = probs[0];
p2 = probs[1];
expect(p1).to.be.within(0.49,0.51);
expect(p2).to.be.within(0.49,0.51);
probs = n2.probs();
p1 = probs[0];
p2 = probs[1];
expect(p1).to.be.within(0.34,0.36);
expect(p2).to.be.within(0.64,0.66);
probs = n3.probs();
p1 = probs[0];
p2 = probs[1];
expect(p1).to.be.within(0.49,0.51);
expect(p2).to.be.within(0.49,0.51);
});
it('verifies sampling with observation alternative method', function() {
var g = jsbayes.newGraph();
var n1 = g.addNode('n1', ['t', 'f']);
var n2 = g.addNode('n2', ['t', 'f']);
var n3 = g.addNode('n3', ['t', 'f']);
n2.addParent(n1);
n3.addParent(n2);
n1.cpt = [ 0.5, 0.5 ];
n2.cpt = [ [ 0.2, 0.8 ], [ 0.5, 0.5 ] ];
n3.cpt = [ [ 0.5, 0.5 ], [ 0.5, 0.5 ] ];
g.observe('n1', 't');
g.sample(10000);
var probs = n1.probs();
var p1 = probs[0];
var p2 = probs[1];
expect(p1).to.be.within(0.99, 1.0);
expect(p2).to.be.within(0.0, 0.0);
probs = n2.probs();
p1 = probs[0];
p2 = probs[1];
expect(p1).to.be.within(0.19,0.21);
expect(p2).to.be.within(0.79,0.81);
probs = n3.probs();
p1 = probs[0];
p2 = probs[1];
expect(p1).to.be.within(0.49,0.51);
expect(p2).to.be.within(0.49,0.51);
g.unobserve('n1');
g.sample(10000);
probs = n1.probs();
p1 = probs[0];
p2 = probs[1];
expect(p1).to.be.within(0.49,0.52);
expect(p2).to.be.within(0.49,0.52);
probs = n2.probs();
p1 = probs[0];
p2 = probs[1];
expect(p1).to.be.within(0.34,0.36);
expect(p2).to.be.within(0.64,0.66);
probs = n3.probs();
p1 = probs[0];
p2 = probs[1];
expect(p1).to.be.within(0.49,0.51);
expect(p2).to.be.within(0.49,0.51);
});
it('verifies samples are saved when requested', function() {
var g = jsbayes.newGraph();
var n1 = g.addNode('n1', ['t', 'f']);
var n2 = g.addNode('n2', ['t', 'f']);
var n3 = g.addNode('n3', ['t', 'f']);
n2.addParent(n1);
n3.addParent(n2);
n1.cpt = [ 0.5, 0.5 ];
n2.cpt = [ [ 0.2, 0.8 ], [ 0.5, 0.5 ] ];
n3.cpt = [ [ 0.5, 0.5 ], [ 0.5, 0.5 ] ];
g.observe('n1', 't');
g.sample(10000);
expect(g.samples.length).to.equals(0);
g.saveSamples = true;
g.sample(1000);
expect(g.samples.length).to.equals(1000);
g.sample(1000);
//samples should not increase but be resetted and readded
expect(g.samples.length).to.equals(1000);
g.sample(500);
//samples should not increase but be resetted and readded
expect(g.samples.length).to.equals(500);
});
it('verifies samples are converted to csv', function() {
var g = jsbayes.newGraph();
g.saveSamples = true;
var n1 = g.addNode('n1', ['t', 'f']);
var n2 = g.addNode('n2', ['t', 'f']);
var n3 = g.addNode('n3', ['t', 'f']);
n2.addParent(n1);
n3.addParent(n2);
n1.cpt = [ 0.5, 0.5 ];
n2.cpt = [ [ 0.2, 0.8 ], [ 0.5, 0.5 ] ];
n3.cpt = [ [ 0.5, 0.5 ], [ 0.5, 0.5 ] ];
g.sample(10);
var csv = g.samplesAsCsv();
var rows = csv.split('\n');
expect(rows.length).to.equals(11);
for(var i=0; i < rows.length; i++) {
var cols = rows[i].split(',');
expect(cols.length).to.equals(3);
}
})
});
describe('#nodes', function() {
it('verifies get node by id', function() {
var g = jsbayes.newGraph();
var n1 = g.addNode('n1', ['t', 'f']);
var n2 = g.addNode('n2', ['t', 'f']);
var n3 = g.addNode('n3', ['t', 'f']);
n2.addParent(n1);
n3.addParent(n2);
var n = g.node('n1');
expect(n.name).to.equals('n1');
n = g.node('n2');
expect(n.name).to.equals('n2');
n = g.node('n3');
expect(n.name).to.equals('n3');
});
it('verifies get index of values', function() {
var g = jsbayes.newGraph();
var n1 = g.addNode('n1', ['t', 'f']);
var n2 = g.addNode('n2', ['t', 'f']);
var n3 = g.addNode('n3', ['f', 't']); //swapped
var i1 = n1.valueIndex('t');
var i2 = n1.valueIndex('f');
expect(i1).to.equals(0);
expect(i2).to.equals(1);
i1 = n2.valueIndex('t');
i2 = n2.valueIndex('f');
expect(i1).to.equals(0);
expect(i2).to.equals(1);
i1 = n3.valueIndex('t');
i2 = n3.valueIndex('f');
expect(i1).to.equals(1);
expect(i2).to.equals(0);
});
it('verifies set cpt one parent', function() {
var g = jsbayes.newGraph();
var n1 = g.addNode('n1', ['0', '1']);
var n2 = g.addNode('n2', ['0', '1']);
var n3 = g.addNode('n3', ['0', '1', '2']);
n2.addParent(n1);
n3.addParent(n2);
n1.setCpt([ 0.5, 0.5 ]);
n2.setCpt([
[ 0.5, 0.5 ],
[ 0.2, 0.8 ]
]);
n3.setCpt([
[ 0.3000997008973081, 0.5992023928215354, 0.10069790628115655 ],
[ 0.10069790628115653, 0.30009970089730803, 0.5992023928215353 ]
]);
expect(n1.cpt).to.deep.equal([ 0.5, 0.5 ]);
expect(n2.cpt).to.deep.equal([ [ 0.5, 0.5 ], [ 0.20059880239520958, 0.7994011976047904 ] ]);
expect(n3.cpt).to.deep.equal([
[ 0.3001991035865484, 0.5984071713076126, 0.10139372510583902 ],
[ 0.10139372510583902, 0.30019910358654844, 0.5984071713076126 ] ]);
});
it('verifies set cpt two parents', function() {
var g = jsbayes.newGraph();
var n1 = g.addNode('n1', ['0', '1']);
var n2 = g.addNode('n2', ['0', '1']);
var n3 = g.addNode('n3', ['0', '1']);
n3.addParent(n1);
n3.addParent(n2);
n1.setCpt([ 0.5, 0.5 ]);
n2.setCpt([ 0.5, 0.5 ]);
n3.setCpt([
[ 0.9, 0.1 ],
[ 0.8, 0.2 ],
[ 0.7, 0.3 ],
[ 0.6, 0.4 ]
]);
expect(n1.cpt).to.deep.equal([ 0.5, 0.5 ]);
expect(n2.cpt).to.deep.equal([ 0.5, 0.5 ]);
expect(n3.cpt).to.deep.equal([
[ [ 0.8992015968063872, 0.10079840319361279 ], [ 0.7994011976047904, 0.20059880239520958 ] ],
[ [ 0.6996007984031936, 0.3003992015968064 ], [ 0.5998003992015968, 0.4001996007984032 ] ]
]);
});
it('verifies set cpt three parents', function() {
var g = jsbayes.newGraph();
var n1 = g.addNode('n1', ['0', '1']);
var n2 = g.addNode('n2', ['0', '1']);
var n3 = g.addNode('n3', ['0', '1']);
var n4 = g.addNode('n4', ['0', '1']);
n4.addParent(n1);
n4.addParent(n2);
n4.addParent(n3);
n1.setCpt([ 0.5, 0.5 ]);
n2.setCpt([ 0.5, 0.5 ]);
n3.setCpt([ 0.5, 0.5 ]);
n4.setCpt([
[ 0.9, 0.1 ],
[ 0.8, 0.2 ],
[ 0.7, 0.3 ],
[ 0.6, 0.4 ],
[ 0.5, 0.5 ],
[ 0.4, 0.6 ],
[ 0.3, 0.7 ],
[ 0.2, 0.8 ]
]);
expect(n1.cpt).to.deep.equal([ 0.5, 0.5 ]);
expect(n2.cpt).to.deep.equal([ 0.5, 0.5 ]);
expect(n3.cpt).to.deep.equal([ 0.5, 0.5 ]);
expect(n4.cpt).to.deep.equal(
[//n1
[//n1=0
[//n2=0
[//n3=0
0.8992015968063872, 0.10079840319361279
],
[//n3=1
0.7994011976047904, 0.20059880239520958
]
],
[//n2=1
[//n3=0
0.6996007984031936, 0.3003992015968064
],
[//n3=1
0.5998003992015968, 0.4001996007984032
]
]
],
[//n1=1
[//n2=0
[//n3=0
0.5,0.5
],
[//n3=1
0.4001996007984032, 0.5998003992015968
]
],
[//n2=1
[//n3=0
0.3003992015968064, 0.6996007984031936
],
[//n3=1
0.20059880239520958, 0.7994011976047904
]
]
]
]
);
});
});