/******************************************************************************* * This file is part of ProbCog. * * ProbCog is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * ProbCog is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with ProbCog. If not, see <http://www.gnu.org/licenses/>. ******************************************************************************/ package probcog.bayesnets.core.io; import edu.ksu.cis.bnj.ver3.core.BeliefNetwork; import edu.ksu.cis.bnj.ver3.streams.*; import java.io.*; import java.util.*; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.w3c.dom.*; /** * Converter (Exporter/Importer) for the XML-BIF format (XML Bayesian Interchange Format) * This class need not be used directly. BeliefNetworkEx implements the loading and storing * of XML-BIF files using this class. * (This class was obtained through decompilation of the BNJ plugin) */ public class Converter_xmlbif implements OmniFormatV1, Exporter, Importer { public Converter_xmlbif() { w = null; curBeliefNode = 0; } public OmniFormatV1 getStream1() { return this; } public void load(InputStream stream, OmniFormatV1 writer) { _Writer = writer; _Writer.Start(); bn_cnt = 0; bnode_cnt = 0; _nodenames = new HashMap(); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setValidating(true); factory.setNamespaceAware(true); org.w3c.dom.Document doc; try { DocumentBuilder parser = factory.newDocumentBuilder(); doc = parser.parse(stream); } catch(Exception e) { throw new RuntimeException(e); } visitDocument(doc); System.gc(); } public void visitDocument(Node parent) { NodeList l = parent.getChildNodes(); if(l == null) throw new RuntimeException("Unexpected end of document!"); int max = l.getLength(); for(int i = 0; i < max;) { Node node = l.item(i); switch(node.getNodeType()) { case 1: // '\001' String name = node.getNodeName(); if(name.equals("BIF")) { NamedNodeMap attrs = node.getAttributes(); if(attrs != null) { int amax = attrs.getLength(); for(int j = 0; j < amax; j++) { Node attr = attrs.item(j); String aname = attr.getNodeName().toUpperCase(); if(aname.equals("VERSION")) try { int ver = (int)(Double.parseDouble(attr.getNodeValue()) * 100D); if(ver != 30) System.out.println("version " + ver + " is not supported"); } catch(Exception exx) { } else System.out.println("property:" + aname + " not handled"); } } visitDocument(node); } else if(name.equals("NETWORK")) { _Writer.CreateBeliefNetwork(bn_cnt); visitModel(node); bn_cnt++; } else { throw new RuntimeException("Unhandled element " + name); } // fall through case 2: // '\002' case 3: // '\003' case 4: // '\004' case 5: // '\005' case 6: // '\006' case 7: // '\007' case 8: // '\b' case 9: // '\t' case 10: // '\n' default: i++; break; } } } public void visitModel(Node parent) { NodeList l = parent.getChildNodes(); if(l == null) throw new RuntimeException("Unexpected end of document!"); int max = l.getLength(); for(int i = 0; i < max;) { Node node = l.item(i); switch(node.getNodeType()) { case 1: // '\001' String name = node.getNodeName(); if(name.equals("NAME")) _Writer.SetBeliefNetworkName(bn_cnt, getElementValue(node)); else if(!name.equals("PRM_CLASS") && name.equals("VARIABLE")) { _Writer.BeginBeliefNode(bnode_cnt); visitVariable(node); _Writer.EndBeliefNode(); bnode_cnt++; } // fall through case 2: // '\002' case 3: // '\003' case 4: // '\004' case 5: // '\005' case 6: // '\006' case 7: // '\007' case 8: // '\b' case 9: // '\t' case 10: // '\n' default: i++; break; } } for(int i = 0; i < max;) { Node node = l.item(i); switch(node.getNodeType()) { case 1: // '\001' String name = node.getNodeName(); if(name.equals("DEFINITION") || name.equals("PROBABILITY")) visitDefinition(node); // fall through case 2: // '\002' case 3: // '\003' case 4: // '\004' case 5: // '\005' case 6: // '\006' case 7: // '\007' case 8: // '\b' case 9: // '\t' case 10: // '\n' default: i++; break; } } } protected void visitVariable(Node parent) { NodeList l = parent.getChildNodes(); String propType = "nature"; NamedNodeMap attrs = parent.getAttributes(); int max; if(attrs != null) { max = attrs.getLength(); for(int i = 0; i < max; i++) { Node attr = attrs.item(i); String name = attr.getNodeName(); String value = attr.getNodeValue(); if(name.equals("TYPE")) { propType = value; if(value.equals("decision")) _Writer.SetType("decision"); else if(value.equals("utility")) _Writer.SetType("utility"); } else { System.out.println("Unhandled variable property attribute " + name); } } } max = l.getLength(); for(int i = 0; i < max;) { Node node = l.item(i); switch(node.getNodeType()) { case 1: // '\001' String name = node.getNodeName(); if(name.equals("NAME")) { String desc = getElementValue(node); _nodenames.put(desc, new Integer(bnode_cnt)); _Writer.SetBeliefNodeName(desc); } else if(name.equals("OUTCOME") || name.equals("VALUE")) { String value = getElementValue(node); _Writer.BeliefNodeOutcome(value); } else if(name.equals("PROPERTY")) { String assignment = getElementValue(node); int eq = assignment.indexOf("="); String var = assignment.substring(0, eq).trim().toUpperCase(); String val = assignment.substring(eq + 1).trim(); if(var.equals("POSITION")) { int cma = val.indexOf(","); int left = val.indexOf("("); int right = val.indexOf(")"); String X = val.substring(left + 1, cma).trim(); String Y = val.substring(cma + 1, right).trim(); _Writer.SetBeliefNodePosition(Integer.parseInt(X), Integer.parseInt(Y)); } else if (var.equals("DOMAINCLASS")) { String domainClassName = val.trim(); _Writer.SetBeliefNodeDomainClass(domainClassName); } } // fall through case 2: // '\002' case 3: // '\003' case 4: // '\004' case 5: // '\005' case 6: // '\006' case 7: // '\007' case 8: // '\b' case 9: // '\t' default: i++; break; } } } protected void visitDefinition(Node parent) { NodeList l = parent.getChildNodes(); if(l == null) return; LinkedList parents = new LinkedList(); int curNode = -1; String CPTString = ""; int max = l.getLength(); for(int i = 0; i < max;) { Node node = l.item(i); switch(node.getNodeType()) { case 1: // '\001' String name = node.getNodeName(); if(name.equals("FOR")) { String cNode = getElementValue(node); curNode = ((Integer)_nodenames.get(cNode)).intValue(); } else if(name.equals("GIVEN")) parents.add(_nodenames.get(getElementValue(node))); else if(name.equals("TABLE")) CPTString = getElementValue(node); // fall through case 2: // '\002' case 3: // '\003' case 4: // '\004' case 5: // '\005' case 6: // '\006' case 7: // '\007' case 8: // '\b' case 9: // '\t' default: i++; break; } } if(curNode >= 0) { int p; for(Iterator i = parents.iterator(); i.hasNext(); _Writer.Connect(p, curNode)) p = ((Integer)i.next()).intValue(); _Writer.BeginCPF(curNode); StringTokenizer tok = new StringTokenizer(CPTString); int maxz = tok.countTokens(); for(int c = 0; c < maxz; c++) { String SSS = tok.nextToken(); _Writer.ForwardFlat_CPFWriteValue(SSS); } _Writer.EndCPF(); } } protected String getElementValue(Node parent) { NodeList l = parent.getChildNodes(); if(l == null) return null; StringBuffer buf = new StringBuffer(); int max = l.getLength(); for(int i = 0; i < max; i++) { Node node = l.item(i); switch(node.getNodeType()) { case 3: // '\003' buf.append(node.getNodeValue()); break; default: System.out.println("Unhandled node " + node.getNodeName()); break; case 1: // '\001' case 8: // '\b' break; } } return buf.toString().trim(); } public void save(BeliefNetwork bn, OutputStream os) { w = new OutputStreamWriter(os); OmniFormatV1_Writer.Write(bn, this); } public void fwrite(String x) { try { w.write(x); w.flush(); } catch(Exception e) { System.out.println("unable to write?"); } } public void Start() { netDepth = 0; BeliefNames = new HashMap(); AdjList = new HashMap(); fwrite("<?xml version=\"1.0\" encoding=\"US-ASCII\"?>\n"); fwrite("<!--\n"); fwrite("Bayesian network in XMLBIF v0.3 (BayesNet Interchange Format)\n"); fwrite("Produced by BNJ 3.0 (http://bndev.sourceforge.net/\n"); fwrite("-->\n"); fwrite("\t\t<!-- DTD for the XMLBIF 0.3 format -->\n"); fwrite("<!DOCTYPE BIF [\n"); fwrite("<!ELEMENT BIF ( NETWORK )*>\n"); fwrite("<!ATTLIST BIF VERSION CDATA #REQUIRED>\n"); fwrite("<!ELEMENT NETWORK ( NAME, ( PROPERTY | VARIABLE | DEFINITION )* )>\n"); fwrite("<!ELEMENT NAME (#PCDATA)>\n"); fwrite("<!ELEMENT VARIABLE ( NAME, ( OUTCOME | PROPERTY )* ) >\n"); fwrite("\t<!ATTLIST VARIABLE TYPE (nature|decision|utility) \"nature\">\n"); fwrite("<!ELEMENT OUTCOME (#PCDATA)>\n"); fwrite("<!ELEMENT DEFINITION ( FOR | GIVEN | TABLE | PROPERTY )* >\n"); fwrite("<!ELEMENT FOR (#PCDATA)>\n"); fwrite("<!ELEMENT GIVEN (#PCDATA)>\n"); fwrite("<!ELEMENT TABLE (#PCDATA)>\n"); fwrite("<!ELEMENT PROPERTY (#PCDATA)>\n"); fwrite("]>\n"); fwrite("<BIF VERSION=\"0.3\">\n"); } public void CreateBeliefNetwork(int idx) { if(netDepth > 0) { netDepth = 0; fwrite("</NETWORK>\n"); } fwrite("<NETWORK>\n"); netDepth = 1; } public void SetBeliefNetworkName(int idx, String name) { fwrite("<NAME>" + name + "</NAME>\n"); } public void BeginBeliefNode(int idx) { nodeType = "nature"; internalNode = ""; curBeliefNode = idx; AdjList.put(new Integer(curBeliefNode), new ArrayList()); } public void SetType(String type) { if(!type.equals("chance")) nodeType = type; } public void SetBeliefNodePosition(int x, int y) { internalNode += "\t\t<PROPERTY>position = (" + x + "," + y + ")</PROPERTY>\n"; } public void SetBeliefNodeDomainClass(String domainClassName) { internalNode += "\t\t<PROPERTY>domainclass = " + domainClassName + "</PROPERTY>\n"; } public void BeliefNodeOutcome(String outcome) { internalNode += "\t\t<OUTCOME>" + outcome.replaceAll("<", "<").replaceAll(">", ">") + "</OUTCOME>\n"; } public void SetBeliefNodeName(String name) { internalNode += "\t\t<NAME>" + name + "</NAME>\n"; BeliefNames.put(new Integer(curBeliefNode), name); } public void MakeContinuous(String s) { } public void EndBeliefNode() { fwrite("\t<VARIABLE TYPE=\"" + nodeType + "\">\n"); fwrite(internalNode); fwrite("\t</VARIABLE>\n"); } public void Connect(int par_idx, int chi_idx) { ArrayList adj = (ArrayList)AdjList.get(new Integer(chi_idx)); adj.add(new Integer(par_idx)); } public void BeginCPF(int idx) { ArrayList adj = (ArrayList)AdjList.get(new Integer(idx)); String name = (String)BeliefNames.get(new Integer(idx)); fwrite("\t<DEFINITION>\n"); fwrite("\t\t<FOR>" + name + "</FOR>\n"); String gname; for(Iterator it = adj.iterator(); it.hasNext(); fwrite("\t\t<GIVEN>" + gname + "</GIVEN>\n")) { Integer given = (Integer)it.next(); gname = (String)BeliefNames.get(given); } fwrite("\t\t<TABLE>"); } public void ForwardFlat_CPFWriteValue(String x) { fwrite(x + " "); } public void EndCPF() { fwrite("\t\t</TABLE>"); fwrite("\t</DEFINITION>"); } public int GetCPFSize() { return 0; } public void Finish() { if(netDepth > 0) { netDepth = 0; fwrite("</NETWORK>\n"); } fwrite("</BIF>\n"); try { w.close(); } catch(Exception exception) { } } public String getExt() { return "*.xml;*.xbif"; } public String getDesc() { return "XML Bayesian Network Interchange Format"; } private OmniFormatV1 _Writer; private int bn_cnt; private int bnode_cnt; private HashMap _nodenames; Writer w; public int netDepth; int curBeliefNode; HashMap BeliefNames; HashMap AdjList; String internalNode; String nodeType; }