/* * Encog(tm) Core v3.4 - Java Version * http://www.heatonresearch.com/encog/ * https://github.com/encog/encog-java-core * Copyright 2008-2016 Heaton Research, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * For more information on Heaton Research copyrights, licenses * and trademarks visit: * http://www.heatonresearch.com/copyright */ package org.encog.ml.bayesian.bif; import java.util.ArrayList; import java.util.List; import org.encog.ml.bayesian.BayesianChoice; import org.encog.ml.bayesian.BayesianEvent; import org.encog.ml.bayesian.BayesianNetwork; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; /** * Handler, used to parse the XML BIF files. */ public class BIFHandler extends DefaultHandler { /** * The current section. */ private final List<FileSection> currentSection = new ArrayList<FileSection>(); /** * BIF variables. */ private final List<BIFVariable> bifVariables = new ArrayList<BIFVariable>(); /** * BIF definitions. */ private final List<BIFDefinition> bifDefinitions = new ArrayList<BIFDefinition>(); /** * The current variable. */ private BIFVariable currentVariable; /** * The current definition. */ private BIFDefinition currentDefinition; /** * THe current string. */ private String currentString; /** * The network bing loaded. */ private BayesianNetwork network; /** * Constructor. */ public BIFHandler() { this.network = new BayesianNetwork(); } /** * Handle the beginning of the BIF tag. * @param qName The name of the tag. * @param attributes The attributes. */ private void handleBeginBIF(String qName, Attributes attributes) { if (qName.equals("NETWORK")) { this.currentSection.add(FileSection.NETWORK); } } /** * Handle the beginning of the BIF tag. * @param qName The name of the tag. * @param attributes The attributes. */ private void handleBeginNETWORK(String qName, Attributes attributes) { if (qName.equals("VARIABLE")) { this.currentSection.add(FileSection.VARIABLE); this.currentVariable = new BIFVariable(); this.bifVariables.add(this.currentVariable); } else if (qName.equals("DEFINITION")) { this.currentSection.add(FileSection.DEFINITION); this.currentDefinition = new BIFDefinition(); this.bifDefinitions.add(this.currentDefinition); } } /** * Handle the beginning of the BIF tag. * @param qName The name of the tag. * @param attributes The attributes. */ private void handleBeginVARIABLE(String qName, Attributes attributes) { if (qName.equals("VARIABLE")) { this.currentVariable = new BIFVariable(); this.bifVariables.add(this.currentVariable); } } /** * Handle the beginning of the DEFINITION tag. * @param qName The name of the tag. */ private void handleBeginDEFINITION(String qName, Attributes attributes) { if (qName.equals("DEFINITION")) { this.currentDefinition = new BIFDefinition(); this.bifDefinitions.add(this.currentDefinition); } } /** * Handle the end of the BIF tag. * @param qName The name of the tag. */ private void handleEndBIF(String qName) { if (qName.equals("BIF")) { this.currentSection.remove(this.currentSection.size() - 1); } } /** * Handle the end of the NETWORK tag. * @param qName The name of the tag. */ private void handleEndNETWORK(String qName) { if (qName.equals("NETWORK")) { this.currentSection.remove(this.currentSection.size() - 1); } } /** * Handle the end of the VARIABLE tag. * @param qName The name of the tag. */ private void handleEndVARIABLE(String qName) { if (qName.equals("NAME")) { this.currentVariable.setName(this.currentString); } else if (qName.equals("OUTCOME")) { this.currentVariable.addOption(this.currentString); } else if( qName.equals("VARIABLE") ) { this.currentSection.remove(this.currentSection.size() - 1); } } /** * Handle the end of the DEFINITION tag. * @param qName The name of the tag. */ private void handleEndDEFINITION(String qName) { if (qName.equals("FOR")) { this.currentDefinition.setForDefinition(this.currentString); } else if (qName.equals("GIVEN")) { this.currentDefinition.addGiven(this.currentString); } else if (qName.equals("TABLE")) { this.currentDefinition.setTable(this.currentString); } else if( qName.equals("DEFINITION") ) { this.currentSection.remove(this.currentSection.size() - 1); } } /** * {@inheritDoc} */ @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { super.startElement(uri, localName, qName, attributes); if (this.currentSection.size() == 0 && qName.equals("BIF")) { this.currentSection.add(FileSection.BIF); } else if (this.currentSection.size() > 0) { switch (this.currentSection.get(this.currentSection.size() - 1)) { case BIF: handleBeginBIF(qName, attributes); break; case DEFINITION: handleBeginDEFINITION(qName, attributes); break; case NETWORK: handleBeginNETWORK(qName, attributes); break; case VARIABLE: handleBeginVARIABLE(qName, attributes); break; } } } /** * @return The network being parsed. */ public BayesianNetwork getNetwork() { return network; } /** * {@inheritDoc} */ @Override public void endElement(String uri, String localName, String qName) throws SAXException { super.endElement(uri, localName, qName); if (this.currentSection.size() > 0) { switch (this.currentSection.get(this.currentSection.size() - 1)) { case BIF: handleEndBIF(qName); break; case DEFINITION: handleEndDEFINITION(qName); break; case NETWORK: handleEndNETWORK(qName); break; case VARIABLE: handleEndVARIABLE(qName); break; } } } /** * {@inheritDoc} */ @Override public void endDocument() throws SAXException { super.endDocument(); // define variables for (BIFVariable v : this.bifVariables) { List<BayesianChoice> c = new ArrayList<BayesianChoice>(); int index = 0; for(String s : v.getOptions() ) { c.add(new BayesianChoice(s,index++)); } this.network.createEvent(v.getName(), c); } // define relations for (BIFDefinition d : this.bifDefinitions) { BayesianEvent childEvent = this.network.requireEvent(d .getForDefinition()); for (String s : d.getGivenDefinitions()) { BayesianEvent parentEvent = this.network.requireEvent(s); this.network.createDependency(parentEvent, childEvent); } } this.network.finalizeStructure(); // define probabilities for (BIFDefinition d : this.bifDefinitions) { double[] t = d.getTable(); BayesianEvent childEvent = this.network.requireEvent(d.getForDefinition()); int tableIndex = 0; int[] args = new int[childEvent.getParents().size()]; do { for(int result = 0; result<childEvent.getChoices().size();result++) { childEvent.getTable().addLine(t[tableIndex++], result, args); } } while(BIFUtil.rollArgs(childEvent,args)); } } /** * {@inheritDoc} */ @Override public void characters(char[] ch, int start, int length) throws SAXException { super.characters(ch, start, length); this.currentString = new String(ch, start, length); } }