From e87793438cd6ffd6f0912060d708362dfd7eb15f Mon Sep 17 00:00:00 2001 From: Claudio Bonesana Date: Mon, 25 Jan 2021 18:38:11 +0100 Subject: [PATCH] Added BIFParser. --- models/bif/asia.bif | 61 +++++ models/bif/cancer.bif | 38 +++ models/bif/earthquake.bif | 38 +++ models/bif/sachs.bif | 147 +++++++++++ .../crema/model/io/bif/BIFAttribute.java | 16 ++ .../ch/idsia/crema/model/io/bif/BIFBlock.java | 23 ++ .../idsia/crema/model/io/bif/BIFObject.java | 24 ++ .../idsia/crema/model/io/bif/BIFParser.java | 233 ++++++++++++++++++ .../crema/model/io/bif/BIFParserTest.java | 133 ++++++++++ 9 files changed, 713 insertions(+) create mode 100644 models/bif/asia.bif create mode 100644 models/bif/cancer.bif create mode 100644 models/bif/earthquake.bif create mode 100644 models/bif/sachs.bif create mode 100644 src/main/java/ch/idsia/crema/model/io/bif/BIFAttribute.java create mode 100644 src/main/java/ch/idsia/crema/model/io/bif/BIFBlock.java create mode 100644 src/main/java/ch/idsia/crema/model/io/bif/BIFObject.java create mode 100644 src/main/java/ch/idsia/crema/model/io/bif/BIFParser.java create mode 100644 src/test/java/ch/idsia/crema/model/io/bif/BIFParserTest.java diff --git a/models/bif/asia.bif b/models/bif/asia.bif new file mode 100644 index 00000000..77b4c857 --- /dev/null +++ b/models/bif/asia.bif @@ -0,0 +1,61 @@ +// source: https://www.bnlearn.com/bnrepository/discrete-small.html#asia +network unknown { +} +variable asia { + type discrete [ 2 ] { yes, no }; +} +variable tub { + type discrete [ 2 ] { yes, no }; +} +variable smoke { + type discrete [ 2 ] { yes, no }; +} +variable lung { + type discrete [ 2 ] { yes, no }; +} +variable bronc { + type discrete [ 2 ] { yes, no }; +} +variable either { + type discrete [ 2 ] { yes, no }; +} +variable xray { + type discrete [ 2 ] { yes, no }; +} +variable dysp { + type discrete [ 2 ] { yes, no }; +} +probability ( asia ) { + table 0.01, 0.99; +} +probability ( tub | asia ) { + (yes) 0.05, 0.95; + (no) 0.01, 0.99; +} +probability ( smoke ) { + table 0.5, 0.5; +} +probability ( lung | smoke ) { + (yes) 0.1, 0.9; + (no) 0.01, 0.99; +} +probability ( bronc | smoke ) { + (yes) 0.6, 0.4; + (no) 0.3, 0.7; +} +probability ( either | lung, tub ) { + (yes, yes) 1.0, 0.0; + (no, yes) 1.0, 0.0; + (yes, no) 1.0, 0.0; + (no, no) 0.0, 1.0; +} +probability ( xray | either ) { + (yes) 0.98, 0.02; + (no) 0.05, 0.95; +} +probability ( dysp | bronc, either ) { + (yes, yes) 0.9, 0.1; + (no, yes) 0.7, 0.3; + (yes, no) 0.8, 0.2; + (no, no) 0.1, 0.9; +} diff --git a/models/bif/cancer.bif b/models/bif/cancer.bif new file mode 100644 index 00000000..7e0113de --- /dev/null +++ b/models/bif/cancer.bif @@ -0,0 +1,38 @@ +// source: https://www.bnlearn.com/bnrepository/discrete-small.html#cancer +network unknown { +} +variable Pollution { + type discrete [ 2 ] { low, high }; +} +variable Smoker { + type discrete [ 2 ] { True, False }; +} +variable Cancer { + type discrete [ 2 ] { True, False }; +} +variable Xray { + type discrete [ 2 ] { positive, negative }; +} +variable Dyspnoea { + type discrete [ 2 ] { True, False }; +} +probability ( Pollution ) { + table 0.9, 0.1; +} +probability ( Smoker ) { + table 0.3, 0.7; +} +probability ( Cancer | Pollution, Smoker ) { + (low, True) 0.03, 0.97; + (high, True) 0.05, 0.95; + (low, False) 0.001, 0.999; + (high, False) 0.02, 0.98; +} +probability ( Xray | Cancer ) { + (True) 0.9, 0.1; + (False) 0.2, 0.8; +} +probability ( Dyspnoea | Cancer ) { + (True) 0.65, 0.35; + (False) 0.3, 0.7; +} diff --git a/models/bif/earthquake.bif b/models/bif/earthquake.bif new file mode 100644 index 00000000..ff765d48 --- /dev/null +++ b/models/bif/earthquake.bif @@ -0,0 +1,38 @@ +// source: https://www.bnlearn.com/bnrepository/discrete-small.html#earthquake +network unknown { +} +variable Burglary { + type discrete [ 2 ] { True, False }; +} +variable Earthquake { + type discrete [ 2 ] { True, False }; +} +variable Alarm { + type discrete [ 2 ] { True, False }; +} +variable JohnCalls { + type discrete [ 2 ] { True, False }; +} +variable MaryCalls { + type discrete [ 2 ] { True, False }; +} +probability ( Burglary ) { + table 0.01, 0.99; +} +probability ( Earthquake ) { + table 0.02, 0.98; +} +probability ( Alarm | Burglary, Earthquake ) { + (True, True) 0.95, 0.05; + (False, True) 0.29, 0.71; + (True, False) 0.94, 0.06; + (False, False) 0.001, 0.999; +} +probability ( JohnCalls | Alarm ) { + (True) 0.9, 0.1; + (False) 0.05, 0.95; +} +probability ( MaryCalls | Alarm ) { + (True) 0.7, 0.3; + (False) 0.01, 0.99; +} diff --git a/models/bif/sachs.bif b/models/bif/sachs.bif new file mode 100644 index 00000000..67cd5046 --- /dev/null +++ b/models/bif/sachs.bif @@ -0,0 +1,147 @@ +// source: https://www.bnlearn.com/bnrepository/discrete-small.html#sachs +network unknown { +} +variable Akt { + type discrete [ 3 ] { LOW, AVG, HIGH }; +} +variable Erk { + type discrete [ 3 ] { LOW, AVG, HIGH }; +} +variable Jnk { + type discrete [ 3 ] { LOW, AVG, HIGH }; +} +variable Mek { + type discrete [ 3 ] { LOW, AVG, HIGH }; +} +variable P38 { + type discrete [ 3 ] { LOW, AVG, HIGH }; +} +variable PIP2 { + type discrete [ 3 ] { LOW, AVG, HIGH }; +} +variable PIP3 { + type discrete [ 3 ] { LOW, AVG, HIGH }; +} +variable PKA { + type discrete [ 3 ] { LOW, AVG, HIGH }; +} +variable PKC { + type discrete [ 3 ] { LOW, AVG, HIGH }; +} +variable Plcg { + type discrete [ 3 ] { LOW, AVG, HIGH }; +} +variable Raf { + type discrete [ 3 ] { LOW, AVG, HIGH }; +} +probability ( Akt | Erk, PKA ) { + (LOW, LOW) 0.6721176592, 0.3277794919, 0.0001028489; + (AVG, LOW) 0.3349505840, 0.6648697215, 0.0001796945; + (HIGH, LOW) 7.682262e-05, 1.183068e-01, 8.816163e-01; + (LOW, AVG) 0.62038586, 0.37950262, 0.00011152; + (AVG, AVG) 0.8214081840, 0.1782019687, 0.0003898473; + (HIGH, AVG) 0.177105936, 0.813732581, 0.009161483; + (LOW, HIGH) 0.9750859107, 0.0240549828, 0.0008591065; + (AVG, HIGH) 9.483619e-01, 5.154733e-02, 9.075234e-05; + (HIGH, HIGH) 0.1703412073, 0.8293963255, 0.0002624672; +} +probability ( Erk | Mek, PKA ) { + (LOW, LOW) 0.85051343, 0.13872433, 0.01076224; + (AVG, LOW) 0.3870326, 0.4836913, 0.1292761; + (HIGH, LOW) 0.008682883, 0.187958884, 0.803358233; + (LOW, AVG) 0.1177122, 0.6919357, 0.1903521; + (AVG, AVG) 0.04895789, 0.72823961, 0.22280250; + (HIGH, AVG) 0.001153403, 0.748558247, 0.250288351; + (LOW, HIGH) 0.07405991, 0.70044614, 0.22549395; + (AVG, HIGH) 0.003663004, 0.102564103, 0.893772894; + (HIGH, HIGH) 0.03333333, 0.03333333, 0.93333333; +} +probability ( Jnk | PKA, PKC ) { + (LOW, LOW) 0.2899262, 0.2457641, 0.4643097; + (AVG, LOW) 5.766701e-01, 4.232872e-01, 4.271314e-05; + (HIGH, LOW) 9.961240e-01, 3.806755e-03, 6.921373e-05; + (LOW, AVG) 0.5794436587, 0.4203206035, 0.0002357379; + (AVG, AVG) 6.129037e-01, 3.870808e-01, 1.543138e-05; + (HIGH, AVG) 0.8623005877, 0.1368597817, 0.0008396306; + (LOW, HIGH) 0.00456621, 0.99086758, 0.00456621; + (AVG, HIGH) 0.04468980, 0.93495569, 0.02035451; + (HIGH, HIGH) 0.155367232, 0.841807910, 0.002824859; +} +probability ( Mek | PKA, PKC, Raf ) { + (LOW, LOW, LOW) 0.7451772095, 0.2545984747, 0.0002243158; + (AVG, LOW, LOW) 7.576915e-01, 2.422767e-01, 3.181572e-05; + (HIGH, LOW, LOW) 9.977281e-01, 2.244485e-03, 2.737176e-05; + (LOW, AVG, LOW) 0.7066581578, 0.2931291215, 0.0002127207; + (AVG, AVG, LOW) 7.148153e-01, 2.851753e-01, 9.338376e-06; + (HIGH, AVG, LOW) 0.9689835575, 0.0306427504, 0.0003736921; + (LOW, HIGH, LOW) 0.854385965, 0.143859649, 0.001754386; + (AVG, HIGH, LOW) 8.256463e-01, 1.743254e-01, 2.831337e-05; + (HIGH, HIGH, LOW) 0.725950783, 0.272930649, 0.001118568; + (LOW, LOW, AVG) 0.3846008, 0.1231368, 0.4922624; + (AVG, LOW, AVG) 0.343172087, 0.649403298, 0.007424615; + (HIGH, LOW, AVG) 0.9996370895, 0.0001814553, 0.0001814553; + (LOW, AVG, AVG) 0.2692763938, 0.7304863582, 0.0002372479; + (AVG, AVG, AVG) 0.27465766, 0.72002723, 0.00531511; + (HIGH, AVG, AVG) 0.854385965, 0.143859649, 0.001754386; + (LOW, HIGH, AVG) 0.01190476, 0.97619048, 0.01190476; + (AVG, HIGH, AVG) 0.1054112554, 0.8943722944, 0.0002164502; + (HIGH, HIGH, AVG) 0.006060606, 0.987878788, 0.006060606; + (LOW, LOW, HIGH) 0.262181426, 0.001450275, 0.736368299; + (AVG, LOW, HIGH) 0.8652899, 0.1010029, 0.0337072; + (HIGH, LOW, HIGH) 0.9361046959, 0.0007698229, 0.0631254811; + (LOW, AVG, HIGH) 0.85065617, 0.10656168, 0.04278215; + (AVG, AVG, HIGH) 0.2814957, 0.5851161, 0.1333882; + (HIGH, AVG, HIGH) 0.498470948, 0.498470948, 0.003058104; + (LOW, HIGH, HIGH) 0.3333333, 0.3333333, 0.3333333; + (AVG, HIGH, HIGH) 0.3333333, 0.3333333, 0.3333333; + (HIGH, HIGH, HIGH) 0.3333333, 0.3333333, 0.3333333; +} +probability ( P38 | PKA, PKC ) { + (LOW, LOW) 0.30691159, 0.06458648, 0.62850193; + (AVG, LOW) 0.919186742, 0.078464036, 0.002349223; + (HIGH, LOW) 0.80737818, 0.09163898, 0.10098283; + (LOW, AVG) 0.6558227251, 0.3439415370, 0.0002357379; + (AVG, AVG) 8.149777e-01, 1.850069e-01, 1.543138e-05; + (HIGH, AVG) 0.3862301, 0.1595298, 0.4542401; + (LOW, HIGH) 0.86757991, 0.12785388, 0.00456621; + (AVG, HIGH) 0.80313955, 0.19272946, 0.00413099; + (HIGH, HIGH) 0.765536723, 0.231638418, 0.002824859; +} +probability ( PIP2 | PIP3, Plcg ) { + (LOW, LOW) 9.967915e-01, 3.169817e-03, 3.865631e-05; + (AVG, LOW) 9.867112e-01, 1.326991e-02, 1.887612e-05; + (HIGH, LOW) 0.872401162, 0.120070734, 0.007528104; + (LOW, AVG) 0.997890295, 0.001054852, 0.001054852; + (AVG, AVG) 0.9571651090, 0.0424454829, 0.0003894081; + (HIGH, AVG) 0.52180956, 0.46245517, 0.01573528; + (LOW, HIGH) 0.2218092, 0.4936493, 0.2845415; + (AVG, HIGH) 0.07672787, 0.39110315, 0.53216898; + (HIGH, HIGH) 0.02641691, 0.05235351, 0.92122959; +} +probability ( PIP3 | Plcg ) { + (LOW) 0.2184310, 0.4473238, 0.3342453; + (AVG) 0.07796694, 0.21120158, 0.71083148; + (HIGH) 0.4237055, 0.4396535, 0.1366411; +} +probability ( PKA | PKC ) { + (LOW) 0.3864255, 0.3794243, 0.2341501; + (AVG) 0.06039638, 0.92264651, 0.01695712; + (HIGH) 0.01577014, 0.95873839, 0.02549147; +} +probability ( PKC ) { + table 0.42313152, 0.48163920, 0.09522928; +} +probability ( Plcg ) { + table 0.81213356, 0.08337962, 0.10448682; +} +probability ( Raf | PKA, PKC ) { + (LOW, LOW) 0.06232176, 0.14724878, 0.79042946; + (AVG, LOW) 0.4475056, 0.3125747, 0.2399197; + (HIGH, LOW) 0.84288483, 0.12714563, 0.02996955; + (LOW, AVG) 0.3694012, 0.3312117, 0.2993871; + (AVG, AVG) 0.55082326, 0.39291391, 0.05626283; + (HIGH, AVG) 0.74895046, 0.15952981, 0.09151973; + (LOW, HIGH) 0.86757991, 0.12785388, 0.00456621; + (AVG, HIGH) 8.842572e-01, 1.156677e-01, 7.510891e-05; + (HIGH, HIGH) 0.841807910, 0.155367232, 0.002824859; +} diff --git a/src/main/java/ch/idsia/crema/model/io/bif/BIFAttribute.java b/src/main/java/ch/idsia/crema/model/io/bif/BIFAttribute.java new file mode 100644 index 00000000..980e49fb --- /dev/null +++ b/src/main/java/ch/idsia/crema/model/io/bif/BIFAttribute.java @@ -0,0 +1,16 @@ +package ch.idsia.crema.model.io.bif; + +/** + * Author: Claudio "Dna" Bonesana + * Project: crema + * Date: 25.01.2021 10:41 + */ +class BIFAttribute { + String name; + String value; + + @Override + public String toString() { + return " " + name + " " + value; + } +} diff --git a/src/main/java/ch/idsia/crema/model/io/bif/BIFBlock.java b/src/main/java/ch/idsia/crema/model/io/bif/BIFBlock.java new file mode 100644 index 00000000..cf9dfc0f --- /dev/null +++ b/src/main/java/ch/idsia/crema/model/io/bif/BIFBlock.java @@ -0,0 +1,23 @@ +package ch.idsia.crema.model.io.bif; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * Author: Claudio "Dna" Bonesana + * Project: crema + * Date: 25.01.2021 10:41 + */ +class BIFBlock { + String type; + String name; + List attributes = new ArrayList<>(); + + @Override + public String toString() { + return type + " " + String.join(" ", name) + " {\n" + + attributes.stream().map(Object::toString).collect(Collectors.joining("\n ")) + + "\n}"; + } +} diff --git a/src/main/java/ch/idsia/crema/model/io/bif/BIFObject.java b/src/main/java/ch/idsia/crema/model/io/bif/BIFObject.java new file mode 100644 index 00000000..172bfef1 --- /dev/null +++ b/src/main/java/ch/idsia/crema/model/io/bif/BIFObject.java @@ -0,0 +1,24 @@ +package ch.idsia.crema.model.io.bif; + +import ch.idsia.crema.factor.bayesian.BayesianFactor; +import ch.idsia.crema.model.graphical.BayesianNetwork; + +import java.util.HashMap; +import java.util.Map; + +/** + * Author: Claudio "Dna" Bonesana + * Project: crema + * Date: 25.01.2021 09:38 + */ +public class BIFObject { + + public String name; + public BayesianNetwork network = new BayesianNetwork(); + public BayesianFactor[] factors = null; + + public Map variableName = new HashMap<>(); + public Map variableStates = new HashMap<>(); + public Map variableFactors = new HashMap<>(); + +} diff --git a/src/main/java/ch/idsia/crema/model/io/bif/BIFParser.java b/src/main/java/ch/idsia/crema/model/io/bif/BIFParser.java new file mode 100644 index 00000000..46c64eab --- /dev/null +++ b/src/main/java/ch/idsia/crema/model/io/bif/BIFParser.java @@ -0,0 +1,233 @@ +package ch.idsia.crema.model.io.bif; + +import ch.idsia.crema.factor.bayesian.BayesianFactor; +import org.apache.commons.lang3.NotImplementedException; + +import java.io.IOException; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.Scanner; +import java.util.stream.IntStream; + +/** + * Author: Claudio "Dna" Bonesana + * Project: crema + * Date: 25.01.2021 09:22 + *

+ * Source of the BIF structure: http://www.cs.washington.edu/dm/vfml/appendixes/bif.htm + */ +public class BIFParser { + + private static final String DEFAULT_DELIMITER = "[\\r\\n]+|//.*$"; + + public static BIFObject read(String filename) throws IOException { + if (!(filename.endsWith(".bif"))) { + throw new IllegalArgumentException("Unknown file extension"); + } + + return new BIFParser(filename) + .scan() + .getResult(); + } + + String filename; + BIFObject result; + + public BIFParser(String filename) { + this.filename = filename; + } + + public BIFObject getResult() { + return result; + } + + public BIFParser scan() throws IOException { + result = new BIFObject(); + + try (Scanner scanner = new Scanner(Paths.get(filename))) { + scanner.useDelimiter(DEFAULT_DELIMITER); + + while (scanner.hasNext()) { + final BIFBlock block = block(scanner); + process(block); + } + } + + // complete network with factors + result.factors = new BayesianFactor[result.network.getVariables().length]; + result.variableFactors.forEach((varName, f) -> { + final Integer varId = result.variableName.get(varName); + result.factors[varId] = f; + }); + result.network.setFactors(result.factors); + + return this; + } + + private BIFBlock block(Scanner scanner) { + BIFBlock block = new BIFBlock(); + String line = scanner.nextLine(); + + block.type = line.substring(0, line.indexOf(" ")).trim(); + block.name = line.substring(line.indexOf(" "), line.lastIndexOf(" ")).trim(); + + if (line.startsWith("//")) + return null; + + while (!line.equals("}")) { + line = scanner.nextLine().trim(); + + BIFAttribute attribute = new BIFAttribute(); + + if (line.startsWith("(")) { + attribute.name = ""; + attribute.value = line; + block.attributes.add(attribute); + } else if (line.endsWith(";")) { + final String[] tokens = line.trim().split(" ", 2); + attribute.name = tokens[0].trim(); + attribute.value = tokens[1]; + block.attributes.add(attribute); + } + } + + return block; + } + + private void process(BIFBlock block) { + if (block == null) + return; + + switch (block.type) { + case "network": + parseForNetwork(block); + break; + case "variable": + parseForVariable(block); + break; + case "probability": + parseForProbability(block); + break; + default: + throw new IllegalArgumentException("This library does not support the BIF block type \"" + block.name + "\""); + } + } + + private void parseForNetwork(BIFBlock block) { + result.name = String.join(" ", block.name); + // TODO: add support for properties + } + + private void parseForVariable(BIFBlock block) { + String varName = block.name; + int varId; + + for (BIFAttribute attribute : block.attributes) { + switch (attribute.name) { + case "type": + final String[] tokens = attribute.value.split(" ", 2); + final String type = tokens[0]; + final String v = tokens[1]; + if (!type.equals("discrete")) { + throw new NotImplementedException("This library supports only \"discrete\" variables for Bayesian Networks. Found unsupported type \"" + type + "\" in \"variable\" block \"" + block.name + "\"."); + } + int states = Integer.parseInt(v.substring(v.indexOf('[') + 1, v.indexOf(']')).trim()); + varId = result.network.addVariable(states); + result.variableName.put(varName, varId); + + // map states + String[] s = v.substring(v.indexOf('{') + 1, v.indexOf('}')).split(","); + for (int i = 0; i < s.length; i++) { + result.variableStates.put(varName + "$" + s[i].trim(), i); + } + + break; + case "property": + // TODO: add support for other properties + break; + default: + throw new NotImplementedException("Attribute \"" + attribute.name + "\" in block \"" + block.name + "\" not supported yet."); + } + } + + } + + private void parseForProbability(BIFBlock block) { + final String line = block.name; + final String[] varNames = Arrays.stream(line.split("[\\s|,()]+")) + .filter(x -> !x.isEmpty()) + .toArray(String[]::new); + final int[] varIds = Arrays.stream(varNames) + .mapToInt(result.variableName::get) + .toArray(); + + final String varName = varNames[0]; + + final BayesianFactor f = new BayesianFactor(result.network.getDomain(varIds)); + result.variableFactors.put(varName, f); + + // create parents + for (int i = 1; i < varIds.length; i++) { + result.network.addParent(varIds[0], varIds[i]); + } + + if (varNames.length == 1) { + // table + for (BIFAttribute attribute : block.attributes) { + switch (attribute.name) { + case "table": + final double[] values = Arrays.stream(attribute.value.split("[ ,;]")) + .filter(x -> !x.isEmpty()) + .mapToDouble(Double::parseDouble) + .toArray(); + f.setData(values); + break; + case "property": + // TODO: add support for other properties + break; + case "default": + // TODO: add support for default value in data + default: + throw new NotImplementedException("Found unsupported attribute \"" + attribute.name + "\" in \"probability\" block \"" + line + "\"."); + } + } + + } else { + // conditioned + for (BIFAttribute attribute : block.attributes) { + if (!attribute.value.startsWith("(")) { + // TODO: add support for other properties + continue; + } + + // parent variables + final String[] vars = Arrays.stream(attribute.value.substring(attribute.value.indexOf('(') + 1, attribute.value.indexOf(')')).split("[,]")) + .filter(x -> !x.isEmpty()) + .map(String::trim) + .toArray(String[]::new); + + // parent states + int[] states = IntStream.range(1, varNames.length) + .mapToObj(i -> varNames[i] + "$" + vars[i - 1]) + .mapToInt(result.variableStates::get) + .toArray(); + + // data values + final double[] vals = Arrays.stream(attribute.value.substring(attribute.value.indexOf(')') + 1).split("[,;]")) + .filter(x -> !x.isEmpty()) + .map(String::trim) + .mapToDouble(Double::parseDouble) + .toArray(); + + int[] ints = new int[varNames.length]; + System.arraycopy(states, 0, ints, 1, states.length); + + for (int i = 0; i < vals.length; i++) { + ints[0] = i; + f.setValue(vals[i], ints); + } + } + } + } + +} diff --git a/src/test/java/ch/idsia/crema/model/io/bif/BIFParserTest.java b/src/test/java/ch/idsia/crema/model/io/bif/BIFParserTest.java new file mode 100644 index 00000000..a442f82f --- /dev/null +++ b/src/test/java/ch/idsia/crema/model/io/bif/BIFParserTest.java @@ -0,0 +1,133 @@ +package ch.idsia.crema.model.io.bif; + +import ch.idsia.crema.model.graphical.BayesianNetwork; +import org.junit.Test; + +import java.io.IOException; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * Author: Claudio "Dna" Bonesana + * Project: crema + * Date: 25.01.2021 09:31 + */ +public class BIFParserTest { + + @Test + public void testReadAsiaBif() throws IOException { + String filename = "models/bif/asia.bif"; + + BIFObject obj = BIFParser.read(filename); + + final BayesianNetwork bn = obj.network; + final Map map = obj.variableName; + + assertEquals(8, bn.getVariables().length); + for (int v : bn.getVariables()) { + assertEquals(2, bn.getSize(v)); + } + + assertEquals(0, bn.getParents(map.get("asia")).length, "asia"); + assertEquals(1, bn.getParents(map.get("tub")).length, "tub"); + assertEquals(0, bn.getParents(map.get("smoke")).length, "smoke"); + assertEquals(1, bn.getParents(map.get("lung")).length, "lung"); + assertEquals(1, bn.getParents(map.get("bronc")).length, "bronc"); + assertEquals(2, bn.getParents(map.get("either")).length, "either"); + assertEquals(1, bn.getParents(map.get("xray")).length, "xray"); + assertEquals(2, bn.getParents(map.get("dysp")).length, "dysp"); + + assertArrayEquals(new double[]{.01, .99}, obj.variableFactors.get("asia").getData()); + assertArrayEquals(new double[]{.05, .95, .01, .99}, obj.variableFactors.get("tub").getData()); + assertArrayEquals(new double[]{.5, .5}, obj.variableFactors.get("smoke").getData()); + assertArrayEquals(new double[]{.1, .9, .01, .99}, obj.variableFactors.get("lung").getData()); + assertArrayEquals(new double[]{.6, .4, .3, .7}, obj.variableFactors.get("bronc").getData()); + assertArrayEquals(new double[]{1., 0., 1., 0., 1., 0., 0., 1.}, obj.variableFactors.get("either").getData()); + assertArrayEquals(new double[]{.98, .02, .05, .95}, obj.variableFactors.get("xray").getData()); + assertArrayEquals(new double[]{.9, .1, .7, .3, .8, .2, .1, .9}, obj.variableFactors.get("dysp").getData()); + } + + @Test + public void testReadCancerBif() throws IOException { + String filename = "models/bif/cancer.bif"; + + BIFObject obj = BIFParser.read(filename); + + final BayesianNetwork bn = obj.network; + final Map map = obj.variableName; + + assertEquals(5, bn.getVariables().length); + for (int v : bn.getVariables()) { + assertEquals(2, bn.getSize(v)); + } + + assertEquals(0, bn.getParents(map.get("Pollution")).length); + assertEquals(0, bn.getParents(map.get("Smoker")).length); + assertEquals(2, bn.getParents(map.get("Cancer")).length); + assertEquals(1, bn.getParents(map.get("Xray")).length); + assertEquals(1, bn.getParents(map.get("Dyspnoea")).length); + + assertArrayEquals(new double[]{.9, .1}, obj.variableFactors.get("Pollution").getData()); + assertArrayEquals(new double[]{.3, .7}, obj.variableFactors.get("Smoker").getData()); + assertArrayEquals(new double[]{.03, .97, .05, .95, .001, .999, .02, .98}, obj.variableFactors.get("Cancer").getData()); + assertArrayEquals(new double[]{.9, .1, .2, .8}, obj.variableFactors.get("Xray").getData()); + assertArrayEquals(new double[]{.65, .35, .3, .7}, obj.variableFactors.get("Dyspnoea").getData()); + } + + @Test + public void testReadEarthquakeBif() throws IOException { + String filename = "models/bif/earthquake.bif"; + + BIFObject obj = BIFParser.read(filename); + + final BayesianNetwork bn = obj.network; + final Map map = obj.variableName; + + assertEquals(5, bn.getVariables().length); + for (int v : bn.getVariables()) { + assertEquals(2, bn.getSize(v)); + } + + assertEquals(0, bn.getParents(map.get("Burglary")).length); + assertEquals(0, bn.getParents(map.get("Earthquake")).length); + assertEquals(2, bn.getParents(map.get("Alarm")).length); + assertEquals(1, bn.getParents(map.get("JohnCalls")).length); + assertEquals(1, bn.getParents(map.get("MaryCalls")).length); + + assertArrayEquals(new double[]{.01, .99}, obj.variableFactors.get("Burglary").getData()); + assertArrayEquals(new double[]{.02, .98}, obj.variableFactors.get("Earthquake").getData()); + assertArrayEquals(new double[]{.95, .05, .29, .71, .94, .06, .001, .999}, obj.variableFactors.get("Alarm").getData()); + assertArrayEquals(new double[]{.9, .1, .05, .95}, obj.variableFactors.get("JohnCalls").getData()); + assertArrayEquals(new double[]{.7, .3, .01, .99}, obj.variableFactors.get("MaryCalls").getData()); + } + + @Test + public void testReadSachsBif() throws IOException { + String filename = "models/bif/sachs.bif"; + + BIFObject obj = BIFParser.read(filename); + + final BayesianNetwork bn = obj.network; + final Map map = obj.variableName; + + assertEquals(11, bn.getVariables().length); + for (int v : bn.getVariables()) { + assertEquals(3, bn.getSize(v)); + } + + assertEquals(2, bn.getParents(map.get("Akt")).length); + assertEquals(2, bn.getParents(map.get("Erk")).length); + assertEquals(2, bn.getParents(map.get("Jnk")).length); + assertEquals(3, bn.getParents(map.get("Mek")).length); + assertEquals(2, bn.getParents(map.get("P38")).length); + assertEquals(2, bn.getParents(map.get("PIP2")).length); + assertEquals(1, bn.getParents(map.get("PIP3")).length); + assertEquals(1, bn.getParents(map.get("PKA")).length); + assertEquals(0, bn.getParents(map.get("PKC")).length); + assertEquals(0, bn.getParents(map.get("Plcg")).length); + assertEquals(2, bn.getParents(map.get("Raf")).length); + } + +} \ No newline at end of file