weka.classifiers.bayes.net.search.SearchAlgorithm Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of weka-stable Show documentation
Show all versions of weka-stable Show documentation
The Waikato Environment for Knowledge Analysis (WEKA), a machine
learning workbench. This is the stable version. Apart from bugfixes, this version
does not receive any other updates.
/*
* This program 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.
*
* This program 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 this program. If not, see .
*/
/*
* SearchAlgorithm.java
* Copyright (C) 2003-2012 University of Waikato, Hamilton, New Zealand
*
*/
package weka.classifiers.bayes.net.search;
import java.io.Serializable;
import java.util.Enumeration;
import java.util.Vector;
import weka.classifiers.bayes.BayesNet;
import weka.classifiers.bayes.net.BIFReader;
import weka.classifiers.bayes.net.ParentSet;
import weka.core.Instances;
import weka.core.Option;
import weka.core.OptionHandler;
import weka.core.RevisionHandler;
import weka.core.RevisionUtils;
/**
* This is the base class for all search algorithms for learning Bayes networks.
* It contains some common code, used by other network structure search
* algorithms, and should not be used by itself.
*
*
*
* @author Remco Bouckaert
* @version $Revision: 10153 $
*/
public class SearchAlgorithm implements OptionHandler, Serializable,
RevisionHandler {
/** for serialization */
static final long serialVersionUID = 6164792240778525312L;
/**
* Holds upper bound on number of parents
*/
protected int m_nMaxNrOfParents = 1;
/**
* determines whether initial structure is an empty graph or a Naive Bayes
* network
*/
protected boolean m_bInitAsNaiveBayes = true;
/**
* Determines whether after structure is found a MarkovBlanketClassifier
* correction should be applied If this is true, m_bInitAsNaiveBayes is
* overridden and interpreted as false.
*/
protected boolean m_bMarkovBlanketClassifier = false;
/**
* File name containing initial network structure. This can be used as
* starting point for structure search It will be ignored if not speficied.
* When specified, it overrides the InitAsNaivBayes flag.
*/
protected String m_sInitalBIFFile;
/** c'tor **/
public SearchAlgorithm() {
} // SearchAlgorithm
/**
* AddArcMakesSense checks whether adding the arc from iAttributeTail to
* iAttributeHead does not already exists and does not introduce a cycle
*
* @param bayesNet
* @param instances
* @param iAttributeHead index of the attribute that becomes head of the arrow
* @param iAttributeTail index of the attribute that becomes tail of the arrow
* @return true if adding arc is allowed, otherwise false
*/
protected boolean addArcMakesSense(BayesNet bayesNet, Instances instances,
int iAttributeHead, int iAttributeTail) {
if (iAttributeHead == iAttributeTail) {
return false;
}
// sanity check: arc should not be in parent set already
if (isArc(bayesNet, iAttributeHead, iAttributeTail)) {
return false;
}
// sanity check: arc should not introduce a cycle
int nNodes = instances.numAttributes();
boolean[] bDone = new boolean[nNodes];
for (int iNode = 0; iNode < nNodes; iNode++) {
bDone[iNode] = false;
}
// check for cycles
bayesNet.getParentSet(iAttributeHead).addParent(iAttributeTail, instances);
for (int iNode = 0; iNode < nNodes; iNode++) {
// find a node for which all parents are 'done'
boolean bFound = false;
for (int iNode2 = 0; !bFound && iNode2 < nNodes; iNode2++) {
if (!bDone[iNode2]) {
boolean bHasNoParents = true;
for (int iParent = 0; iParent < bayesNet.getParentSet(iNode2)
.getNrOfParents(); iParent++) {
if (!bDone[bayesNet.getParentSet(iNode2).getParent(iParent)]) {
bHasNoParents = false;
}
}
if (bHasNoParents) {
bDone[iNode2] = true;
bFound = true;
}
}
}
if (!bFound) {
bayesNet.getParentSet(iAttributeHead).deleteLastParent(instances);
return false;
}
}
bayesNet.getParentSet(iAttributeHead).deleteLastParent(instances);
return true;
} // AddArcMakesCycle
/**
* reverseArcMakesSense checks whether the arc from iAttributeTail to
* iAttributeHead exists and reversing does not introduce a cycle
*
* @param bayesNet
* @param instances
* @param iAttributeHead index of the attribute that is head of the arrow
* @param iAttributeTail index of the attribute that is tail of the arrow
* @return true if the arc from iAttributeTail to iAttributeHead exists and
* reversing does not introduce a cycle
*/
protected boolean reverseArcMakesSense(BayesNet bayesNet,
Instances instances, int iAttributeHead, int iAttributeTail) {
if (iAttributeHead == iAttributeTail) {
return false;
}
// sanity check: arc should be in parent set already
if (!isArc(bayesNet, iAttributeHead, iAttributeTail)) {
return false;
}
// sanity check: arc should not introduce a cycle
int nNodes = instances.numAttributes();
boolean[] bDone = new boolean[nNodes];
for (int iNode = 0; iNode < nNodes; iNode++) {
bDone[iNode] = false;
}
// check for cycles
bayesNet.getParentSet(iAttributeTail).addParent(iAttributeHead, instances);
for (int iNode = 0; iNode < nNodes; iNode++) {
// find a node for which all parents are 'done'
boolean bFound = false;
for (int iNode2 = 0; !bFound && iNode2 < nNodes; iNode2++) {
if (!bDone[iNode2]) {
ParentSet parentSet = bayesNet.getParentSet(iNode2);
boolean bHasNoParents = true;
for (int iParent = 0; iParent < parentSet.getNrOfParents(); iParent++) {
if (!bDone[parentSet.getParent(iParent)]) {
// this one has a parent which is not 'done' UNLESS it is the arc
// to be reversed
if (!(iNode2 == iAttributeHead && parentSet.getParent(iParent) == iAttributeTail)) {
bHasNoParents = false;
}
}
}
if (bHasNoParents) {
bDone[iNode2] = true;
bFound = true;
}
}
}
if (!bFound) {
bayesNet.getParentSet(iAttributeTail).deleteLastParent(instances);
return false;
}
}
bayesNet.getParentSet(iAttributeTail).deleteLastParent(instances);
return true;
} // ReverseArcMakesCycle
/**
* IsArc checks whether the arc from iAttributeTail to iAttributeHead already
* exists
*
* @param bayesNet
* @param iAttributeHead index of the attribute that becomes head of the arrow
* @param iAttributeTail index of the attribute that becomes tail of the arrow
* @return true if the arc from iAttributeTail to iAttributeHead already
* exists
*/
protected boolean isArc(BayesNet bayesNet, int iAttributeHead,
int iAttributeTail) {
for (int iParent = 0; iParent < bayesNet.getParentSet(iAttributeHead)
.getNrOfParents(); iParent++) {
if (bayesNet.getParentSet(iAttributeHead).getParent(iParent) == iAttributeTail) {
return true;
}
}
return false;
} // IsArc
/**
* Returns an enumeration describing the available options.
*
* @return an enumeration of all the available options.
*/
@Override
public Enumeration