/*
* 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.query;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.encog.EncogError;
import org.encog.ml.bayesian.BayesianError;
import org.encog.ml.bayesian.BayesianEvent;
import org.encog.ml.bayesian.BayesianNetwork;
import org.encog.ml.bayesian.EventType;
import org.encog.ml.bayesian.query.sample.EventState;
/**
* Provides basic functionality for a Bayesian query. This class is abstract,
* and is not used directly. Rather, other queries make use of it.
*
*/
public abstract class BasicQuery implements BayesianQuery, Serializable {
/**
* The network to be queried.
*/
private final BayesianNetwork network;
/**
* A mapping of the events to event states.
*/
private final Map<BayesianEvent,EventState> events = new HashMap<BayesianEvent,EventState>();
/**
* The evidence events.
*/
private final List<BayesianEvent> evidenceEvents = new ArrayList<BayesianEvent>();
/**
* Default constructor.
*/
public BasicQuery() {
this.network = null;
}
/**
* The outcome events.
*/
private final List<BayesianEvent> outcomeEvents = new ArrayList<BayesianEvent>();
public BasicQuery(BayesianNetwork theNetwork) {
this.network = theNetwork;
finalizeStructure();
}
public void finalizeStructure() {
this.events.clear();
for(BayesianEvent event: this.network.getEvents()) {
events.put(event, new EventState(event));
}
}
/**
* {@inheritDoc}
*/
public BayesianNetwork getNetwork() {
return network;
}
/**
* {@inheritDoc}
*/
public Map<BayesianEvent, EventState> getEvents() {
return events;
}
/**
* {@inheritDoc}
*/
public List<BayesianEvent> getEvidenceEvents() {
return evidenceEvents;
}
/**
* {@inheritDoc}
*/
public List<BayesianEvent> getOutcomeEvents() {
return outcomeEvents;
}
/**
* Called to locate the evidence and outcome events.
*/
public void locateEventTypes() {
this.evidenceEvents.clear();
this.outcomeEvents.clear();
for(BayesianEvent event: this.network.getEvents()) {
switch(getEventType(event)) {
case Evidence:
this.evidenceEvents.add(event);
break;
case Outcome:
this.outcomeEvents.add(event);
break;
}
}
}
/**
* {@inheritDoc}
*/
public void reset() {
for(EventState s : this.events.values()) {
s.setCalculated(false);
}
}
/**
* {@inheritDoc}
*/
public void defineEventType(BayesianEvent event, EventType et) {
getEventState(event).setEventType(et);
}
/**
* {@inheritDoc}
*/
public EventState getEventState(BayesianEvent event) {
return this.events.get(event);
}
/**
* {@inheritDoc}
*/
public EventType getEventType(BayesianEvent event) {
return getEventState(event).getEventType();
}
/**
* @return Determines if the evidence events have values that satisfy the
* needed case. This is used for sampling.
*/
protected boolean isNeededEvidence() {
for(BayesianEvent evidenceEvent: this.evidenceEvents) {
EventState state = getEventState(evidenceEvent);
if(!state.isSatisfied() ) {
return false;
}
}
return true;
}
/**
* @return True, if the current state satisifies the desired outcome.
*/
protected boolean satisfiesDesiredOutcome() {
for(BayesianEvent outcomeEvent: this.outcomeEvents) {
EventState state = getEventState(outcomeEvent);
if(!state.isSatisfied() ) {
return false;
}
}
return true;
}
/**
* {@inheritDoc}
*/
public void setEventValue(BayesianEvent event, boolean b) {
setEventValue(event,b?0:1);
}
/**
* {@inheritDoc}
*/
public void setEventValue(BayesianEvent event, int d) {
if( getEventType(event)==EventType.Hidden) {
throw new BayesianError("You may only set the value of an evidence or outcome event.");
}
getEventState(event).setCompareValue(d);
getEventState(event).setValue(d);
}
/**
* {@inheritDoc}
*/
public String getProblem() {
if( this.outcomeEvents.size()==0 )
return "";
StringBuilder result = new StringBuilder();
result.append("P(");
boolean first = true;
for(BayesianEvent event: this.outcomeEvents) {
if( !first ) {
result.append(",");
}
first = false;
result.append(EventState.toSimpleString(getEventState(event)));
}
result.append("|");
first = true;
for(BayesianEvent event: this.evidenceEvents) {
if( !first ) {
result.append(",");
}
first = false;
EventState state = getEventState(event);
if( state==null )
break;
result.append(EventState.toSimpleString(state));
}
result.append(")");
return result.toString();
}
public BayesianQuery clone() {
throw new EncogError("Clone is not implemented");
}
}