/*
* 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.parse;
import java.util.ArrayList;
import java.util.List;
import org.encog.EncogError;
import org.encog.ml.bayesian.BayesianError;
import org.encog.ml.bayesian.BayesianNetwork;
import org.encog.util.SimpleParser;
import org.encog.util.csv.CSVFormat;
/**
* Used to parse probability strings for the Bayes networks.
*/
public class ParseProbability {
/**
* The network used.
*/
private final BayesianNetwork network;
/**
* Parse the probability for the specified network.
* @param theNetwork THe network to parse for.
*/
public ParseProbability(BayesianNetwork theNetwork) {
this.network = theNetwork;
}
/**
* Add events, as they are pased.
* @param parser The parser.
* @param results The events found.
* @param delim The delimiter to use.
*/
private void addEvents(SimpleParser parser, List<ParsedEvent> results, String delim) {
boolean done = false;
StringBuilder l = new StringBuilder();
while( !done && !parser.eol()) {
char ch = parser.peek();
if( delim.indexOf(ch) != -1 ) {
if( ch==')' || ch=='|' )
done = true;
ParsedEvent parsedEvent;
// deal with a value specified by + or -
if( l.length()>0 && l.charAt(0)=='+' ) {
String l2 = l.toString().substring(1);
parsedEvent = new ParsedEvent(l2.trim());
parsedEvent.setValue("0");
} else if( l.length()>0 && l.charAt(0)=='-') {
String l2 = l.toString().substring(1);
parsedEvent = new ParsedEvent(l2.trim());
parsedEvent.setValue("1");
} else {
String l2 = l.toString();
parsedEvent = new ParsedEvent(l2.trim());
}
// parse choices
if( ch=='[' ) {
parser.advance();
int index = 0;
while( ch!=']' && !parser.eol() ) {
String labelName = parser.readToChars(":,]");
if( parser.peek()==':' ) {
parser.advance();
parser.eatWhiteSpace();
double min = Double.parseDouble(parser.readToWhiteSpace());
parser.eatWhiteSpace();
if(!parser.lookAhead("to", true) ) {
throw new BayesianError("Expected \"to\" in probability choice range.");
}
parser.advance(2);
double max = CSVFormat.EG_FORMAT.parse(parser.readToChars(",]"));
parsedEvent.getList().add(new ParsedChoice(labelName,min,max));
} else {
parsedEvent.getList().add(new ParsedChoice(labelName,index++));
}
parser.eatWhiteSpace();
ch = parser.peek();
if( ch==',' ) {
parser.advance();
}
}
}
// deal with a value specified by =
if( parser.peek()=='=' ) {
parser.readChar();
String value = parser.readToChars(delim);
// BayesianEvent evt = this.network.getEvent(parsedEvent.getLabel());
parsedEvent.setValue(value);
}
if( ch==',') {
parser.advance();
}
if( ch==']') {
parser.advance();
}
if( parsedEvent.getLabel().length()>0 ) {
results.add(parsedEvent);
}
l.setLength(0);
} else {
parser.advance();
l.append(ch);
}
}
}
/**
* Parse the given line.
* @param line The line to parse.
* @return The parsed probability.
*/
public ParsedProbability parse(String line) {
ParsedProbability result = new ParsedProbability();
SimpleParser parser = new SimpleParser(line);
parser.eatWhiteSpace();
if (!parser.lookAhead("P(", true)) {
throw new EncogError("Bayes table lines must start with P(");
}
parser.advance(2);
// handle base
addEvents(parser, result.getBaseEvents(), "|,)=[]");
// handle conditions
if (parser.peek() == '|') {
parser.advance();
addEvents(parser, result.getGivenEvents(), ",)=[]");
}
if (parser.peek() != ')') {
throw new BayesianError("Probability not properly terminated.");
}
return result;
}
/**
* Parse a probability list.
* @param network The network to parse for.
* @param line The line to parse.
* @return The parsed list.
*/
public static List<ParsedProbability> parseProbabilityList(BayesianNetwork network, String line) {
List<ParsedProbability> result = new ArrayList<ParsedProbability>();
StringBuilder prob = new StringBuilder();
for(int i=0;i<line.length();i++) {
char ch = line.charAt(i);
if( ch==')') {
prob.append(ch);
ParseProbability parse = new ParseProbability(network);
ParsedProbability parsedProbability = parse.parse(prob.toString());
result.add(parsedProbability);
prob.setLength(0);
}
else {
prob.append(ch);
}
}
return result;
}
}