/*
 *
 * Header file for Hugin C++ API, version 6.1.
 *
 * Copyright (C) 2000-2003, Hugin Expert A/S. All Rights Reserved.
 *
 */

#ifndef _HUGIN_
#define _HUGIN_

#ifndef __cplusplus
#define __cplusplus
#endif

#include <string>
#include <vector>
#include <utility>
#include <exception>

#include <cstdio>

namespace HAPI {
  class Clique;
  class Domain;
  class ExceptionHugin;
  class Expression;
  class JunctionTree;
  class Node;
  class UtilityNode;
  class DiscreteChanceNode;
  class DiscreteDecisionNode;
  class ContinuousChanceNode;
  class LabelledDCNode;
  class BooleanDCNode;
  class NumberedDCNode;
  class IntervalDCNode;
  class LabelledDDNode;
  class BooleanDDNode;
  class NumberedDDNode;
  class IntervalDDNode;
  class Table;
  class CGDistribution;
  class ParseListener;
  class Attribute;



  /** Standard C++ Library container for holding nodes.
  */
  class NodeList : public std::vector<Node *> {};

  /** Standard C++ Library container for holding cliques.
  */
  class CliqueList : public std::vector<Clique *> {};

  /** Standard C++ Library container for holding expressions.
  */
  class ExpressionList : public std::vector<Expression *> {};

  /** Standard C++ Library container for holding junction trees.
  */
  class JunctionTreeList : public std::vector<JunctionTree *> {};


  class ICGDistribution;
  class IClique;
  class IDomain;
  class IException;
  class IExpression;
  class IJunctionTree;
  class INode;
  class IModel;
  class ITable;
  class IUncompile;
  class IAttribute;

  // new to 6.0
  class ClassCollection;
  class NetworkModel;
  class Class;
  class InstanceNode;
  /** Standard C++ Library container for holding Classes.
  */
  class ClassList : public std::vector<Class* >{};
  class ClassParseListener;
  class NetParseListener;
  //  class ExpressionParseListener;

  class IClassCollection;
  class INetworkModel;
  class IClass;

  // end to new

  /** Modes of propagation.
      Either normal or fast retraction
  */
  enum EvidenceMode {
    H_MODE_NORMAL = 20,
    H_MODE_FAST_RETRACTION = 21
  };


  /** Node categories.
      Either utility, decision, chance, or instance
  */
  enum Category {
    // new to 6.0
    H_CATEGORY_INSTANCE = 6,
    // end new
    H_CATEGORY_CHANCE = 7,
    H_CATEGORY_DECISION = 8,
    H_CATEGORY_UTILITY = 9,
    H_CATEGORY_ERROR = -1
  };


  /** Node kinds.
      Either discrete or continuous
  */
  enum Kind {
	H_KIND_DISCRETE = 0,
	H_KIND_CONTINUOUS = 1,
	H_KIND_ERROR = 2
  };


  /** Types of equilibrium in the junction trees.
      Either sum or max.
  */
  enum Equilibrium {
    H_EQUILIBRIUM_SUM = 11,
    H_EQUILIBRIUM_MAX = 12
  };


  /** Possible triangulation methods.
      The possible triangulation methods.
      @see Domain::triangulate()
  */
  enum TriangulationMethod {
    H_TM_TOTAL_WEIGHT = 19,
		H_TM_CLIQUE_SIZE = 15,
		H_TM_CLIQUE_WEIGHT = 16,
		H_TM_FILL_IN_SIZE = 17,
		H_TM_FILL_IN_WEIGHT = 18
  };


  /** Byte order.
      The byte order of the written files
  */
  enum Endian {
    H_ENDIAN_BIG = 1,
    H_ENDIAN_LITTLE = 2,
    H_ENDIAN_HOST = 0
  };

 /** Constraints used in structural learning.
     Before performing structural learning, it is possible to
     put some constraints on the network to be learned.
     @see Node::setEdgeConstraint()
 */  
  enum Constraint {
		H_CONSTRAINT_NONE = 100,
		H_CONSTRAINT_EDGE_REQUIRED = 101,
		H_CONSTRAINT_FORWARD_EDGE_REQUIRED = 102,
		H_CONSTRAINT_BACKWARD_EDGE_REQUIRED = 103,
		H_CONSTRAINT_EDGE_FORBIDDEN = 104,
		H_CONSTRAINT_FORWARD_EDGE_FORBIDDEN = 105,
		H_CONSTRAINT_BACKWARD_EDGE_FORBIDDEN = 106,
		H_CONSTRAINT_ERROR = 107
  };


  /** Operators to be used in expressions.

     @see Expression and sub-classes hereof.
  */
  enum Operator {
		H_OPERATOR_ABS = 85,
		H_OPERATOR_ADD = 93,
		H_OPERATOR_AND = 90,
		H_OPERATOR_BETA = 61,
		H_OPERATOR_BINOMIAL = 66,
		H_OPERATOR_BOOLEAN = 108,
		H_OPERATOR_CEIL = 87,
		H_OPERATOR_DIVIDE = 96,
		H_OPERATOR_EQUALS = 99,
		H_OPERATOR_ERROR = 109,
		H_OPERATOR_EXP = 77,
		H_OPERATOR_EXPONENTIAL = 63,
		H_OPERATOR_FLOOR = 86,
		H_OPERATOR_DISTRIBUTION = 70,
		H_OPERATOR_GAMMA = 62,
		H_OPERATOR_GEOMETRIC = 69,
		H_OPERATOR_GREATER_THAN = 101,
		H_OPERATOR_GREATER_THAN_OR_EQUALS = 104,
		H_OPERATOR_IF = 89,
		H_OPERATOR_LABEL = 106,
		H_OPERATOR_LESS_THAN = 100,
		H_OPERATOR_LESS_THAN_OR_EQUALS = 103,
		H_OPERATOR_LOG = 74,
		H_OPERATOR_MAX = 73,
		H_OPERATOR_MIN = 72,
		H_OPERATOR_MOD = 88,
		H_OPERATOR_MULTIPLY = 95,
		H_OPERATOR_NEGATE = 98,
		H_OPERATOR_NODE = 107,
		H_OPERATOR_NOISYOR = 71,
		H_OPERATOR_NORMAL = 60,
		H_OPERATOR_NOT = 92,
		H_OPERATOR_NOT_EQUALS = 102,
		H_OPERATOR_NUMBER = 105,
		H_OPERATOR_OR = 91,
		H_OPERATOR_POISSON = 67,
		H_OPERATOR_POWER = 97,
		H_OPERATOR_SQRT = 84,
		H_OPERATOR_SUBTRACT = 94,
		H_OPERATOR_UNIFORM = 65,
		H_OPERATOR_WEIBULL = 64,
		H_OPERATOR_LOG2 = 75,
		H_OPERATOR_LOG10 = 76,
		H_OPERATOR_SIN = 78,
		H_OPERATOR_COS = 79,
		H_OPERATOR_TAN = 80,
		H_OPERATOR_SINH = 81,
		H_OPERATOR_COSH = 82,
		H_OPERATOR_TANH = 83,
		H_OPERATOR_NEGATIVEBINOMIAL = 68
 };


  /** The generic Hugin Exception. All other Hugin specific exceptions are derived from this.
   */
  class ExceptionHugin : public exception {
  public:
    ExceptionHugin() throw () {}
    ExceptionHugin(const ExceptionHugin& rhs) throw () {}
    virtual ~ExceptionHugin() throw() {}
    ExceptionHugin& operator=(const ExceptionHugin& rhs) throw () { return *this; }
    virtual const char *what() const throw();
  };


  /** Represents the cliques in the junction tree.

     @see JunctionTree
     @see Node
  */
  class Clique
    {
      friend IClique;
      friend IJunctionTree;
      
    protected:
      Clique() throw(HAPI::ExceptionHugin);
      Clique(IClique *newIClique) throw(ExceptionHugin);
      IClique * iClique;
      virtual ~Clique();
      void init(IClique *newIClique) throw(ExceptionHugin);
    public:

      /** Return the JunctionTree to which this Clique belongs.
       */
      JunctionTree *getJunctionTree() throw( ExceptionHugin );
    
      /** Return a vector of pointers to Nodes comprising the members of this Clique.
       */
      NodeList getMembers() throw( ExceptionHugin );
		
      /** Return a vector of pointers to Cliques comprising the neighbors of this Clique.
       */
      CliqueList getNeighbors() throw( ExceptionHugin );
    };

  /** A ClassCollection is one of the principal structures in HUGIN.
      All classes must be contained in a ClassCollection, and Classes
      can only contain instances of Classes contained in the same
      ClassCollection. That is, each Class may contain instances of
      other Classes of the ClassCollection, but not of Classes of
      other ClassCollections.
      @see Class */
  class ClassCollection {
    friend IClass;
  protected:
    IClassCollection* iClassCollection;
  public:
    /** Construct a new empty ClassCollection object.
     */
    ClassCollection()  throw(ExceptionHugin);
    
    /** Retrieve a ClassList containing all the Classes contained
	in this ClassCollection.
	@return A ClassList containing all members of the ClassCollection.
    */
    ClassList getMembers() throw(ExceptionHugin);
    
    /** Retrieves a Class from the ClassCollection, identified by its name.
	
    @param name The name of the Class to return.
    @return A reference to the Class with the given name. On error an 
    exception will be thrown.
    */
    
    Class* getClassByName( const std::string& name) const throw(ExceptionHugin);
    
    /** Save the ClassCollection as a net file. This will write the definition
	of each Class from the ClassCollection into the same netfile.
	
	@param fileName The name of the file in which to save the ClassCollection.
    */
    void saveAsNet( const std::string& fileName ) throw(ExceptionHugin);
    
    /** Parse the given net into a Class. This may involve parsing
	additional nets located in the same file, or in separate files.
	All the created Classes are inserted into the ClassCollection.
	When the Class to load references other classes, placed in
	different files, it is the responsibility of the user to
	provide a function for locating the files for these classes,
	and insert them into the ClassCollection. This is done by
	overloading the insertClass() function in the ClassParseListener class.
	@see ClassParseListener
    */
    void parseClasses(const std::string& fileName, ClassParseListener* listener )throw(ExceptionHugin);
    
    ~ClassCollection() throw(ExceptionHugin);
  };
  
  /** NetworkModel is the ancestor of both Domain and Class. Since 
      Class and Domain are, in many ways, conceptually and functionally
      similar, the NetworkModel class is introduced to capture this
      similarity. It contains functionality and variables that are
      identical for the two classes.
      @see Class
      @see Domain
  */
  class NetworkModel {
    friend INetworkModel;
    friend IDomain;
    friend IClass;
    friend IExpression;
  private:
    INetworkModel* iNetworkModel;
  protected:
    ~NetworkModel() throw( ExceptionHugin ) ;
    virtual void* getPeer()=0;
  
    IDomain *iDomain;
    IClass *iClass;
  public:
    double INFINITY();
    /** Write a NET description of the networkModel to a file. 
	@param filename The name of the file to save to.
    */
    virtual void saveAsNet(const std::string& filename) throw (ExceptionHugin)=0 ;
    /** Return the value associated with key in the attribute list for this NetworkModel.
	@return Standard C++ Library string containing the attribure value.
    */
    virtual std::string getAttribute(std::string& key) const throw ( ExceptionHugin )=0 ;
    /** Return the file name most recently used for loading or
	saving this NetworkModel.
	@return A Standard C++ Library string.  
    */
    virtual std::string getFileName() throw( ExceptionHugin )=0;
    
    /** Return the Nodes of this NetworkModel. No ordering can be
	inferred by the user.
	@return NodeList containing the Nodes of this Domain.
    */
    virtual NodeList getNodes() const throw(ExceptionHugin)=0 ;
    /** Return the node in the NetworkModel, which is identified by the given name.
	@param name A Standard C++ string containing the name of the node to be found in this NetworkModel.
	@output Reference to a node in the NetworkModel carrying the
	name specified by the input. On error an exception will be
	thrown.  
    */
    virtual Node *getNodeByName(const std::string& name) const throw( ExceptionHugin )=0;
    /** Return the value stored within the user data slot of this
	NetworkModel. If the stored value is NULL, or if no value has
	been stored, NULL is returned.
	It is the responsibility of the application programmer to
	ensure that the data is valid, that pointers are accessed
	correctly, etc.
	
	Also note that when you delete a NetworkModel, Hugin does not
	attempt to delete the data pointed to by the user data
	slot. It is the responsibility of the user.
	
	@return Pointer stored within the NetworkModel object as a reference 
	to user data associated with this NetworkModel.
    */
    void* getUserData() throw(ExceptionHugin);
    /** Insert the key/value pair in the attribute list for this
	NetworkModel. If the key is already defined, the value is
	updated. If no value is provided, the attribute is
	removed.
	
	@param key A Standard C++ Library string.
	@param value A Standard C++ Library string.
    */
    virtual void setAttribute(std::string& key, std::string& value) throw (ExceptionHugin)=0;
    /** Set the file to be used for logging by subsequent compilation, 
	triangulation, and table generation operations.
	
	@param log File pointer to an opened file to be used as
	log. log must be a text file opened for writing or
	appending. Writing is done sequentially.  
    */
    virtual void setLogFile(FILE *log) throw( ExceptionHugin )=0;
    /** Set the user data field of this NetworkModel. The Hugin API
	provides a slot within each NetworkModel object for use
	exclusively by the user/application. This slot can hold a
	pointer to arbitrary data, such as a file, a function
	pointer, etc. Please note that Hugin does not do anything
	to the user data. Data is not even copied. Only the
	pointer to the data is stored.
	
	@param data Pointer to user-defined data associated with 
	<tt>*this</tt> NetworkModel.
    */
    void setUserData(void *data) throw(ExceptionHugin) ;
    /** Test if this NetworkModel contains an attribute with the specified key.
	@param key A Standar C++ Library string.
	@return boolean
    */
    virtual bool hasAttribute(const std::string& key) throw(ExceptionHugin)=0;
    /** Return the size of the displayed nodes.
	@return Standard C++ Library pair<int,int>.
    */
    virtual std::pair<unsigned int,unsigned int> getNodeSize() throw(ExceptionHugin) =0;
    /** Set the size of the nodes.
	@param width 
	@param height 
    */
    virtual void setNodeSize(unsigned int width, unsigned int height) throw (ExceptionHugin) =0;
    /** Return all the attributes associated with this NetworkModel.
	@return A vector of all Attributes
    */
    virtual std::vector<Attribute*>  getAttributes() throw ( ExceptionHugin ) =0;
    /** Generate tables for all Nodes, having a Model, in the NetworkModeL.
	This is done by calling Node::GenerateTable() for each applicable Node.
	The operation is aborted, if table generation fails for some Node. This
	may leave the NetworkModel in a state, where some Nodes have got 
	generated Tables, some have not got generated Tables, and one has
	a partially generated Table. In this case, an Exception is thrown.
    */
    virtual void generateTables() throw( ExceptionHugin ) =0;

    /* Create an Expression from a given string. To ease the creation
	of complex expressions, it is possible to specify these as 
	strings, instead of building them with objects. 
	
	Example: The following code
	
	Expression *result=new IfExpression(new BooleanExpression(true), new NumberExpression(1), new DistributionDistribution(new NumberExpression(1), new NumberExpression(2)));
	
	can be written like this:
	
	Expression *result=NetworkModel::stringToExpression("if(true, 1, Distribution(1,2))");
	@param exp The textual representation of the Expression to be generated
	@param listener An ExpressionparseListener which handles any errors generated
	by the function
	@see ExpressionParseListener
    */ 
    /*     virtual Expression* stringToExpression(const std::string& exp,  */
    /* 					   ExpressionParseListener* listener)  */
    /*       throw (ExceptionHugin); */
    
  };

  /** The Class class is one of the principal structures in HUGIN.
      When using the Object Oriented features of HUGIN, Classes
      must be used for creating the networks. Furthermore, all
      Classes which are to be used as instances in a given Class
      must be contained in the same ClassCollection as this.

      Classes can not, however, be used for inference. For this
      purpose, it is necessary to instantiate the Class into a 
      Domain, which can be used for performing inference.
      @see ClassCollection
      @see Domain
      @see Node
  */
  class Class : public NetworkModel{
    friend IClass;
    friend INode;

  protected:
    IClass * iClass;
    Class(IClass* iClass);
    void* getPeer();

  public:
    /** Create a new Class object, contained in the given
	ClassCollection. 
	@param cColl A pointer to the ClassCollection in which
	the newly constructed Class should be placed.
    */
    Class(ClassCollection *cColl) throw (ExceptionHugin);
    /** @see NetworkModel::saveAsNet
     */
    void saveAsNet(const std::string& filename) throw (ExceptionHugin) ;
    /** @see NetworkModel::getAttribute
     */
    std::string getAttribute(std::string& key) const throw ( ExceptionHugin ) ;
    /** @see NetworkModel::getFileName
     */
    std::string getFileName() throw( ExceptionHugin );
    /** @see NetworkModel::getNodes
     */
    NodeList getNodes() const throw(ExceptionHugin) ;
    /** @see NetworkModel::getNodeByName
     */
    Node *getNodeByName(const std::string& name) const throw( ExceptionHugin );
    /** @see NetworkModel::setAttribute
     */
    void setAttribute(std::string& key, std::string& value) throw (ExceptionHugin);
    /** @see NetworkModel::setLogFile
     */
    void setLogFile(FILE *log) throw( ExceptionHugin );
    /** @see NetworkModel::hasAttribute
     */
    bool hasAttribute(const std::string& key) throw(ExceptionHugin);
    /** @see NetworkModel::getNodeSize
     */
    std::pair<unsigned int,unsigned int> getNodeSize() throw(ExceptionHugin) ;
    /** @see NetworkModel::setNodeSize
     */
    void setNodeSize(unsigned int width, unsigned int height) throw (ExceptionHugin) ;
    /** @see NetworkModel::getAttributes
     */
    std::vector<Attribute*>  getAttributes() throw ( ExceptionHugin ) ;
    /** @see NetworkModel::generateTables
     */
    void generateTables() throw( ExceptionHugin ) ;

    /** Set the name of this Class
	@param name The name which is given to this Class
    */
    void setName(const std::string& name) throw (ExceptionHugin);
    /** Set the name of this Class
	@param name The name which is given to this Class
    */
    void setName(char* name) throw (ExceptionHugin);
    /** Retrieve the name of this Class. If no name has been assigned
	to the Class, one will be automatically generated by HUGIN.
	
	@return The name of this Class
    */
    std::string getName() const throw (ExceptionHugin);
    /** Get a list of all Nodes in this Class, which have
	been added to the inputs of the Class.
	@return A NodeList containing all input nodes for the Class.
	@see Node::addToInputs
    */
    NodeList getInputs() throw (ExceptionHugin);
    /** Get a list of all Nodes in this Class, which have
	been added to the outputs of the Class.
	@return A NodeList containing all output nodes for the Class.
	@see Node::addToOutputs
    */
    NodeList getOutputs() throw (ExceptionHugin);
    /** Get a list of all InstanceNodes created from this Class.
	@return A NodeList containing the instances
	@see InstanceNode
    */
    NodeList getInstances() throw (ExceptionHugin);
    /** Instantiate this Class to a Domain. This is required
	before any inference can be made. This operation will
	"unfold" the object oriented parts of the network, so that
	the Domain will be a standard HUGIN Domain.

	Note: The Nodes in the Domain will not be immediately identifiable
	as the Nodes from the Class (i.e., they will not have meaningfull
	names). To determine what Node in the Class a given domain-node 
	is derived from, you should use Node::getSource().
	@see Node::getSource
	@return The newly constructed Domain.
    */
    Domain* createDomain() throw (ExceptionHugin);
    /** Return the ClassCollection, in which this Class is contained.
	A Class can only be contained in a single ClassCollection, so
	if a given Class definition is needed in more than one 
	ClassCollection, a copy of the Class must be created in each
	ClassCollection, and changes to one version of the Class will
	not be reflected in the others.
	@return The ClassCollection containing this Class 
    */
    ClassCollection* getClassCollection() throw (ExceptionHugin);

    ~Class()throw ();
  };


  /** A domain is the HUGIN representation of a network. It is one of
     the principal structures in HUGIN. It must be constructed before
     any nodes belonging to the network.
     @see Node
     @see JunctionTree 
  */
  class Domain : public NetworkModel {
    friend INode;
    friend IUncompile;
    friend IExpression;
    friend IClass;
    
  public:
    /** Construct a new, empty Domain object.
     */
    Domain() throw(ExceptionHugin);
    
    /** Construct a domain by loading the corresponding Hugin Knowledge Base from file.
	@param filename A Standard C++ Library string.
    */
    Domain(const std::string& filename) throw( ExceptionHugin );
    
    /** Construct a domain by reading a NET file description.
	@param filename  Standard C++ Library string containing the name of the NET file.
	@param pl Pointer to object derived from class ParseListener. 
    */
    Domain(const std::string& filename, ParseListener *pl) throw (ExceptionHugin);
    
    /** Destruct a Domain object.
     */
    virtual ~Domain() throw(); 
    
    /** Adapts this Domain according to the evidence entered. 
     */
    void adapt() throw (HAPI::ExceptionHugin);
    
    /** Remove "near-zero" probabilities from the clique
	probability tables.  For each Clique object in
	this domain, a value delta is computed
	such that the sum of all elements less than delta
	in the (discrete part) of the clique table is less than
	epsilon.  These elements (less than
	delta) are then set to 0.  
	
	@param epsilon The threshold value. Maximal probability mass
	to eradicate from each clique.  
	
	@return A double value which is the sum of all entries in
	clique probability tables that have been zeroed.  
    */
    double approximate(double epsilon) throw( HAPI::ExceptionHugin );
    
    
    /** Test if CG evidence has been propagated for this Domain.
	@return boolean
    */
    bool cgEvidenceIsPropagated() const throw( HAPI::ExceptionHugin );


    /** Compile this Domain using the default triangulation
	method. If the domain already is triangulated, nothing is
	changed. The domain must contain at least one chance or
	decision node.  */
    void compile() throw( HAPI::ExceptionHugin );


    /** Remove the zero entries from the clique and separator
	tables of the junction trees in this Domain.  Compression
	can only be applied to (compiled) ordinary belief
	networks. Continuous nodes are allowed, but compression
	only applies to configurations of states of the discrete
	nodes.
	  
	@return A double value which indicates a measure of
	compression achieved. The measure should be less than 1,
	indicating that the compressed domain requires less space
	than the uncompressed domain. An output greater than 1
	means that the "compressed " domainrequires more space
	than the uncompressed domain.
    */
    double compress() throw( HAPI::ExceptionHugin );


    /** Test for Equilibrium type. If the equilibrium of all
	junction trees of this Domain is eq, return true.

	@param eq Type of Equilibrium to test for.
	@return A boolean.  */
    bool equilibriumIs(Equilibrium eq) const throw( HAPI::ExceptionHugin );


    /** Test if evidence has been propagated for this Domain.
	    
    @return A boolean.
    */
    bool evidenceIsPropagated() const throw( HAPI::ExceptionHugin );

    /** Test for evidence mode. Test if the equilibrium of all
	junction trees of this Domain could have been obtained
	through a propagation using ev as the evidence
	incorporation mode.

	@param ev Type of EvidenceMode to test for.  
	@return boolean
    */
    bool evidenceModeIs(EvidenceMode ev) const throw( HAPI::ExceptionHugin );

    /** Return the approximation constant. The number returned is
	based on the most recent (explicit or implicit)
	approximation operation. An implicit approximation takes
	place when you change some conditional probability tables
	of acompressed domain, and then perform a propagation
	operation. Since some (discree) state configurations have
	been removed from a compressed domain, the probability
	mass of the remaining configurations will typically be
	less than 1. This probability mass is returned by
	getApproximationConstant().

	@return A double expressing the probability mass remaining in the approximated domain.  
    */
    double getApproximationConstant() const throw( HAPI::ExceptionHugin );

    /** Return an attrubute value. Return the value associated with key in the attribute 
	list for this Domain.

	@param key A Standard C++ Library string.
	@return A Standard C++ Library string containing the attribute value.
    */
    std::string getAttribute(std::string& key) const throw( HAPI::ExceptionHugin );

    /** Retrieve the case count associate with the case config in this domain.

    @param config long.
    */
    long getCaseCount(long config);

    /** Get the current level of concurrency. 

    @return Unsigned integer.

    @see setConcurrencyLevel
    */
    unsigned int getConcurrencyLevel() const throw ( HAPI::ExceptionHugin );

    /** Return the conflict value. The conflict value is valid for
	this Domain computed during the most recent
	propagation. If no propagation has been performed, 1 is
	returned.  
	@return A double-precision real value expressing the
	conflict measure in the domain.  
    */
    double getConflict() const throw( HAPI::ExceptionHugin );

    /** Return the triangulation order. A NodeList containing a list of nodes in the order
	used to triangulate the network of this Domain is returned.
	@return NodeList containing Nodes representing the elimination order used.  
    */
    NodeList getEliminationOrder() const throw( HAPI::ExceptionHugin );


    /** Return the file name most recently used for loading or
	saving this Domain.
	@return A Standard C++ Library string.  
    */
    std::string getFileName() throw( HAPI::ExceptionHugin );


    /** Return the current value of the grain size parameter.

    @return Positive integer.
    */
    unsigned int getGrainSize() const throw ( HAPI::ExceptionHugin );

    /** Return the JunctionTrees of this Domain.

    @return JunctionTreeList .
    */
    JunctionTreeList getJunctionTrees() const  throw( HAPI::ExceptionHugin );

    /** Get the log-likelihood of the domain.
     */
    double getLogLikelihood() throw (HAPI::ExceptionHugin);

    /** Get current setting of the log-likelihood tolerance in this domain.
     */
    double getLogLikelihoodTolerance() throw (HAPI::ExceptionHugin);


    /** Get current setting of the significance level in this domain.
     */
    double getSignificanceLevel() throw (HAPI::ExceptionHugin);

    /** Get the logarithm to the normalization constant.
     */
    double getLogNormalizationConstant() throw (HAPI::ExceptionHugin);

    /** Compute the marginal distribution. for the Nodes provided
	as arguments (which must all be chance nodes) with respect to the
	(imaginary) joint potential, determined by the current potentials on
	the junction tree(s) of this Domain. If <em>nodes</em> contains
	continuous nodes, they must be last in the list. This operation is not
	allowed on compressed domains.

	@param nodes NodeList containing the Node objects over which to compute the marginal.
	@return A Table which contains the marginal distribution over the nodes provided.
    */
    Table *getMarginal(const NodeList& nodes) const throw( HAPI::ExceptionHugin );

    /** Retrieve the current maximum number of iterations for the EM algorithm.
     */
    int getMaxNumberOfEMIterations() throw (HAPI::ExceptionHugin);

    /** Retrieve the current maximum number of separators allowed during triangulation.
     */
    int getMaxNumberOfSeparators() throw (HAPI::ExceptionHugin);


    /** Get Node by name.

    @param name A Standard C++ string containing the name of the node to be found in this Domain.

    @output Reference to a node in the domain carrying the
    name specified by the input. On error an exception will be
    thrown.  
    */
    Node * getNodeByName(const std::string &) const throw( HAPI::ExceptionHugin );

    /** Return the Nodes of this Domain. No ordering can be
	inferred by the user.
	@return NodeList containing the Nodes of this Domain.
    */
    NodeList getNodes() const throw( HAPI::ExceptionHugin );  
	
    /** Return the size of the displayed nodes.

    throw(ExceptionHugin)@return Standard C++ Library pair<int,int>.
    */
    std::pair<unsigned int,unsigned int> getNodeSize() throw(ExceptionHugin);

    /** Retrieve the normalization constant. from the most recent
	propagation.  
	For sum-propagation, the normalization constant is equal
	to the probability of the evidence propagated.  
	For max-propagation, the normalization constant is the
	probability of the most probable configuration with the
	evidence incorporated.

	@return A double-precision real number.
    */
    double getNormalizationConstant() const throw( ExceptionHugin );

    /** Return the number of cases currently allocated for this domain.
     */
    long getNumberOfCases() throw (HAPI::ExceptionHugin) ;

    /** Return the value stored within the user data slot of this
	Domain. If the stored value is NULL, or if no value has
	been stored, NULL is returned.
	It is the responsibility of the application programmer to
	ensure that the data is valid, that pointers are accessed
	correctly, etc.
	    
	Also note that when you delete a domain, Hugin does not
	attempt to delete the data pointed to by the user data
	slot. It is the responsibility of the user.

	@return Pointer stored within the Domain object as a reference to user data associated with this Domain.
    */
    // void *getUserData() throw(ExceptionHugin);     

    /** Test if this Domain contains an attribute with the specified key.
	@param key A Standar C++ Library string.
	@return boolean
    */
    bool hasAttribute(const std::string& key) throw(ExceptionHugin);

    /** Test if evidence has been entered since last propagation.

    @return A boolean.
    */
    bool hasEvidenceToPropagate() const throw(ExceptionHugin);

    /** Test for new node tables. Are there any nodes in this
	Domain having (a conditional probability or utility) table
	that has changed since the most recent compilation or
	propagation.

	@return boolean
    */
    bool hasTablesToPropagate() const throw( ExceptionHugin );

    /** Establish the initial values for all tables. of this
	Domain (which must be compiled). Using this method will erase all
	evidence previously entered.
    */
    void initialize() throw( ExceptionHugin );


    /** Learn the structure of a net from a text file
     */
	
    void learnStructure() throw( ExceptionHugin );


    /** Test whether this Domain is compiled.

    @return bool
    */
    bool isCompiled() const throw( ExceptionHugin );

    /** Test whether this Domain is compressed.
	    
    @return bool
    */
    bool isCompressed() const throw( ExceptionHugin );

    /** Learn the conditional probability tables for each node in this domain
	that has an experience table.
    */
    void learnTables() throw (HAPI::ExceptionHugin);

    /** Test if likelihood eveidence has been propagated. for this Domain.
     
    @return bool
    */
    bool likelihoodIsPropagated() const throw( ExceptionHugin );

    /** Allocate storage within this domain to a new case.

    @return New case index.
    */
    long newCase() throw (HAPI::ExceptionHugin);

    /** Establish the specified equilibrium. using the evidence
	mode indicated for incorporation of evidence on all
	junction trees in this Domain. Also, revised beliefs will
	be computed for all nodes.

	@param eq Equilibrium type. Defaults to EQ_SUM.
	@param ev EvidenceMode type. Defaults to EV_NORMAL
    */
    void propagate(Equilibrium eq = H_EQUILIBRIUM_SUM, EvidenceMode ev = H_MODE_NORMAL) throw( ExceptionHugin );

    /** Establish the initial state of the inference engine.:
	sum-equilibrium with no evidence incorporated. Any
	propagated findings will thus be removed from the junction
	tree potentials, but entered findings will still be
	"registred" (i.e., they will be incorporated in the next
	propagation).
    */
    void resetInferenceEngine() throw( ExceptionHugin );

    /** Retract (all) findings for all nodes. in this Domain.
     */
    void retractFindings() throw( ExceptionHugin );    

    /** Save this Domain as a Hugin Knowledge Base. to a file
	named by the parameter. The byte order of the Hugin KB is
	determined by <format>. If <tt>*this</tt> domain is
	compiled, it can only be saved if the current equilibrium
	is "sum", and the current evidence incorporation mode is
	"normal".

	@param filename Name of the file to save the knowledge base into.
	@param format Byte-order in the saved file. 
    */
    void save(const std::string& filename, Endian format = H_ENDIAN_HOST) throw( ExceptionHugin );

    /** Create a copy in memory of the belief and junction tree
	tables of this Domain (which is compiled). This operation
	can only be performed if the current equilibrium is "sum",
	the current evidence mode is "normal", and no CG evidence
	has been incorporated.
    */
    void saveToMemory() throw( ExceptionHugin );
	
    /** Insert the key/value pair in the attribute list for this
	Domain. If the key is already defined, the value is
	updated. If no value is provided, the attribute is
	removed.

	@param key A Standard C++ Library string.
	@param value A Standard C++ Library string.
    */
    void setAttribute(std::string& key, std::string& value) throw(ExceptionHugin);

    /** Set the case count for the configuration config to count.
	@param config long.
	@param count double.
    */
    void setCaseCount(long config, double count) throw (HAPI::ExceptionHugin);

    /** Set the level of concurrency. The level of concurrency specifies the maximum 
	number of threads to create when performing a specific table operation.
	Setting the level of concurrency to 1 will cause all table operations to be 
	performed sequentially. The initial parameter value is 1.

	@param level Unsigned integer.
    */
    void setConcurrencyLevel(unsigned int level) throw ( HAPI::ExceptionHugin );

    /** Set the grains size parameter. The grain size parameter specifies a lower limit
	of the tasks to be performed by each thread. The size of a task is approximately 
	equal to the number of floating-point operations needed to perform the task (e.g. 
	the number of elements to sum when performing a marginalization task).

	The initial value of the grain size parameter is 10000.
	@param size Unsigned integer.
    */
    void setGrainSize(unsigned int size) throw ( HAPI::ExceptionHugin );

    /** Set the file to be used for logging by subsequent compilation and triangulation 
	operations.

	@param log File pointer to an opened file to be used as
	log. log must be a text file opened for writing or
	appending. Writing is done sequentially.  
    */
    void setLogFile(FILE* log) throw( HAPI::ExceptionHugin );

    /** Specify the tolerance of the log-likelihood. Terminate the EM learning when
	the relative difference between the log-likelihood of two successive iterations 
	becomes less than tolerance.

	@param tolerance double.
    */
    void setLogLikelihoodTolerance(double tolerance) throw (HAPI::ExceptionHugin);



    /** Specify the Significance Level used for the structurel learning aglorithm

    @param significancelevel double.
    */
    void setSignificanceLevel(double significancelevel) throw (HAPI::ExceptionHugin);



    /** Set the maximal number of iterations allowed for the EM algorithm. The 
	algorithm termnates when this number is reached or when the relative improvement
	becomes lower than the log-likelihood tolerance.

	@param iterations Maximum allowed number of iterations.
    */
    void setMaxNumberOfEMIterations(int iterations) throw (HAPI::ExceptionHugin);


    /** Set the maximal number of separators allowed during triangulation.

    @param separators Maximum number of separators allowed durring triangulation  .
    */
    void setMaxNumberOfSeparators(int separators) throw (HAPI::ExceptionHugin);

    /** Set the size of the nodes.

    @param width long
    @param height long
    */
    void setNodeSize(unsigned int width, unsigned int height) throw (ExceptionHugin);

    /**	Adjust the storage capacity for cases in this domain.

    @param number Storage capacity.
    */
    void setNumberOfCases(long number) throw(HAPI::ExceptionHugin);

    /** Set the user data field of this Domain. The Hugin API
	provides a slot within each Domain object for use
	exclusively by the user/application. This slot can hold a
	pointer to arbitrary data, such as a file, a function
	pointer, etc. Please note that Hugin does not do anything
	to the user data. Data is not even copied. Only the
	pointer to the data is stored.

	@param data Pointer to user-defined data associated with <tt>*this</tt> domain.
    */
    void setUserData(void *data) throw(HAPI::ExceptionHugin);

    /** Sample a configuration for this Domain with respect to the
	current distribution.e The current distribution must be in
	sum-equilibrium and with evidence incorporated in normal
	mode.
    */
    void simulate() throw( ExceptionHugin );


    /** Transforms a network into a triangulated graph. First, the
	network of this Domain is tranformed into its moral graph,
	and then this moral graph is triangulated using the
	triangulation method tm.

	@param tm TriangulationMethod
    */
    void triangulate(TriangulationMethod tm = H_TM_FILL_IN_WEIGHT) throw (ExceptionHugin);

    /** Transforms a network into a triangulated graph using a
	specified elimination order. First, the network of this
	Domain is transformed into its moral graph. Second, this
	moral graph is triangulated using the Nodes in the
	NodeList order as elimination sequence. order must contain
	each chance and decision node of this Domain exactly once
	and it must respect the restrictions for influence
	diagrams and networks containing continuous chance nodes.

	@param order NodeList containing the Nodes of the network in the order of elimination.
    */
    void triangulateWithOrder(const NodeList& order) throw( ExceptionHugin );

    /** Remove the data structures of this Domain. The data
	structures are produced by Domain::compile(),
	Domain::triangulate(), and
	Domain::triangulateWithOrder(). Note that any references
	to objects within the compiled structure (e.g., Clique and
	JunctionTree objects) are invalidated by a call to
	uncompile(). Also note that many of the editing functions
	automatically performs an uncompile() operation. When this
	happens, the domain must be compiled (using
	Domain::compile()) before it can be used for
	inference.
    */
    void uncompile() throw( ExceptionHugin );
	
    /** Write a NET description of the Domain to a file.
	@param filename A Standard C++ Library string containing the name of the file to write.
    */
    void writeNet(const std::string& filename) throw (ExceptionHugin);

    /** Write a NET description of the Domain to a file.
	@param filename A Standard C++ Library string containing the name of the file to write.
	@see NetworkModel::saveAsNet
    */
    void saveAsNet(const std::string& filename) throw (ExceptionHugin);

    /** Generate tables for all applicable Nodes in this Domain
	@see NetworkModel::generateTables
    */
    void generateTables( ) throw (ExceptionHugin) ;
    /** The random number generator used by HUGIN, generates a set
	of numbers, which look random, but are in fact deterministic.
	However, the set of numbers depend on the seed of the random
	generator. This can be set by this function.
	@param seed The seed which determines the outcome of the
	random number generator.
    */
    void seedRandom(	unsigned long seed ) throw ( ExceptionHugin ) ;
    /** getAttributes
	@see NetworkModel::getAttributes
    */
    std::vector<Attribute*> getAttributes() throw ( ExceptionHugin ) ;

    /** 
     * Saves all evidence entered in this Domain in file
     * <fileName> (if the file exists, it is overwritten).
     * @param fileName the name of the file in which the case is going
     * to be saved.
     */
    void saveCase(const std::string& filename) throw (ExceptionHugin);

     /**
     * Parses the case stored in file <fileName> and enters
     * the associated findings into this Domain.  All existing
     * evidence in the Domain is retracted before entering the case
     * findings.
     * @param fileName the name of the file containing the case.
     * @param parseListener the ParseListener used for handling
     * parse errors.
     */
    void parseCase(const std::string& filename, ParseListener* pl) throw (ExceptionHugin);

  protected:
    IDomain *iDomain;
    void* getPeer();
  };
  
  /*
    Expression* stringToExpression(const std::string& exp, 
    ExpressionParseListener* listener) throw (ExceptionHugin);
    
    
    };
    
  */
    /** An API function was called with a bad argument or while in a
    state that is inconsistent with the function, e.g., asking for
    approximation in a domain that requires propagation.  */

  class ExceptionUsage : public ExceptionHugin {
      //	h_error_usage,
    public:
      ExceptionUsage() throw () {}
      ExceptionUsage(const ExceptionUsage& rhs) throw () {}
      virtual ~ExceptionUsage() throw() {}
      ExceptionUsage& operator=(const ExceptionUsage& rhs) throw () { return *this; }
      virtual const char *what() const throw();
    };

    /** A fatal error occurred during an input or output operation.
	This could be a failure to open a specified file, a failure to
	create a file due to wrong permissions, a failure during a write
	operation due to the disk running full, etc.
    */
    class ExceptionIO : public ExceptionHugin {
      //	h_error_io,
    public:
      ExceptionIO() throw() {}
      ExceptionIO(const ExceptionIO& rhs) throw () {}
      virtual ~ExceptionIO() throw() {}
      ExceptionIO& operator=(const ExceptionIO& rhs) throw () { return *this; }
      virtual const char *what() const throw();
    };


    /** Hugin ran out of memory while carrying out some operation.
     */
    class ExceptionMemory : public ExceptionHugin {
      //	h_error_no_memory,
    public:
      ExceptionMemory() throw () {}
      ExceptionMemory(const ExceptionMemory& rhs) throw () {}
      virtual ~ExceptionMemory() throw() {}
      ExceptionMemory& operator=(const ExceptionMemory& rhs) throw () { return *this; }
      virtual const char *what() const throw();
    };


    /** An attempt has been made to create a node with a name that is
	already in use in the domain.
    */
    class ExceptionTwice : public ExceptionHugin {
      //	h_error_twice,
    public:
      ExceptionTwice() throw () {}
      ExceptionTwice(const ExceptionTwice& rhs) throw () {}
      virtual ~ExceptionTwice() throw() {}
      ExceptionTwice& operator=(const ExceptionTwice& rhs) throw () { return *this; }
      virtual const char *what() const throw();
    };


    /** Names used as node identifiers or attribute names must have the
	same form as a C identifier.  
    */
    class ExceptionInvalidName : public ExceptionHugin {
      //	h_error_invalid_name,
    public:
      ExceptionInvalidName() throw () {}
      ExceptionInvalidName(const ExceptionInvalidName& rhs) throw () {}
      virtual ~ExceptionInvalidName() throw() {}
      ExceptionInvalidName& operator=(const ExceptionInvalidName& rhs) throw () { return *this; }
      virtual const char *what() const throw();
    };

    /** An attempt has been made to connect two nodes that are already
	connected through a link of different type or direction.
    */
    class ExceptionAlreadyConnected : public ExceptionHugin {
      //	h_error_already_connected,
    public:
      ExceptionAlreadyConnected() throw () {}
      ExceptionAlreadyConnected(const ExceptionAlreadyConnected& rhs) throw () {}
      virtual ~ExceptionAlreadyConnected() throw() {}
      ExceptionAlreadyConnected& operator=(const ExceptionAlreadyConnected& rhs) throw () { return *this; }
      virtual const char *what() const throw();
    };


    /** The true size is too large to represent within type `size_t'.
     */
    class ExceptionSizeTooLarge : public ExceptionHugin {
      //	h_error_size_too_large,
    public:
      ExceptionSizeTooLarge() throw () {}
      ExceptionSizeTooLarge(const ExceptionSizeTooLarge& rhs) throw () {}
      virtual ~ExceptionSizeTooLarge() throw() {}
      ExceptionSizeTooLarge& operator=(const ExceptionSizeTooLarge& rhs) throw () { return *this; }
      virtual const char *what() const throw();
    };


    /** Logical relations in the distribution has caused a
	fast-retraction propagation to fail. 
    */
    class ExceptionFastRetraction : public ExceptionHugin {
      //	h_error_fast_retraction,
    public:
      ExceptionFastRetraction() throw () {}
      ExceptionFastRetraction(const ExceptionFastRetraction& rhs) throw () {}
      virtual ~ExceptionFastRetraction() throw() {}
      ExceptionFastRetraction& operator=(const ExceptionFastRetraction& rhs) throw () { return *this; }
      virtual const char *what() const throw();
    };


    /** Zero variance detected during a conditioning operation.
     */
    class ExceptionZeroVariance : public ExceptionHugin {
      //	h_error_zero_variance,
    public:
      ExceptionZeroVariance() throw () {}
      ExceptionZeroVariance(const ExceptionZeroVariance& rhs) throw () {}
      virtual ~ExceptionZeroVariance() throw() {}
      ExceptionZeroVariance& operator=(const ExceptionZeroVariance& rhs) throw () { return *this; }
      virtual const char *what() const throw();
    };


    /** Zero variance detected during a conditioning operation.
     */
    class ExceptionNoValue : public ExceptionHugin {
      //	h_error_no_value,
    public:
      ExceptionNoValue() throw () {}
      ExceptionNoValue(const ExceptionNoValue& rhs) throw () {}
      virtual ~ExceptionNoValue() throw() {}
      ExceptionNoValue& operator=(const ExceptionNoValue& rhs) throw () { return *this; }
      virtual const char *what() const throw();
    };


    /** Possibly significant floating-point rounding error detected. */
    class ExceptionRounding : public ExceptionHugin {
      //	h_error_rounding,
    public:
      ExceptionRounding() throw () {}
      ExceptionRounding(const ExceptionRounding& rhs) throw () {}
      virtual ~ExceptionRounding() throw() {}
      ExceptionRounding& operator=(const ExceptionRounding& rhs) throw () { return *this; }
      virtual const char *what() const throw();
    };


    /** An attempt to load a domain failed due to a bad file.  The file
	was probably not a knowledge base file.  Knowledge base files
	have a header with a magic number, i.e., a two-byte code that
	identifies the file as a knowledge base file.  This error code
	will be given if the magic number was incorrect or not present. 
    */
    class ExceptionBadFile : public ExceptionHugin {
      //	h_error_bad_file,
    public:
      ExceptionBadFile() throw () {}
      ExceptionBadFile(const ExceptionBadFile& rhs) throw () {}
      virtual ~ExceptionBadFile() throw() {}
      ExceptionBadFile& operator=(const ExceptionBadFile& rhs) throw () { return *this; }
      virtual const char *what() const throw();
    };


    /** The knowledgde base has a wrong version number. Knowledge base files have a 
	header that includes a version
	number identifying the version of the Hugin API with which the
	knowledge base is intended to be used.  This error code is given
	if a knowledge base incompatible with the current version of the
	Hugin API is loaded.  To recover from this error, the domain
	must be recompiled with the current version of the Hugin system.  
    */
    class ExceptionBadVersion : public ExceptionHugin {
      //	h_error_bad_version,
    public:
      ExceptionBadVersion() throw () {}
      ExceptionBadVersion(const ExceptionBadVersion& rhs) throw () {}
      virtual ~ExceptionBadVersion() throw() {}
      ExceptionBadVersion& operator=(const ExceptionBadVersion& rhs) throw () { return *this; }
      virtual const char *what() const throw();
    };


    /** Some data item had a bad format.  This could happen while
	reading a domain if the knowledge base file has been corrupted
	or otherwise has an invalid format.
    */
    class ExceptionFormat : public ExceptionHugin {
      //	h_error_format,
    public:
      ExceptionFormat() throw () {}
      ExceptionFormat(const ExceptionFormat& rhs) throw () {}
      virtual ~ExceptionFormat() throw () {}
      ExceptionFormat& operator=(const ExceptionFormat& rhs) throw () { return *this; }
      virtual const char *what() const throw();
    };


    /** The operation requires a compiled domain.
     */
    class ExceptionNotCompiled : public ExceptionHugin {
      //	h_error_not_compiled,
    public:
      ExceptionNotCompiled() throw () {}
      ExceptionNotCompiled(const ExceptionNotCompiled& rhs) throw () {}
      virtual ~ExceptionNotCompiled() throw() {}
      ExceptionNotCompiled& operator=(const ExceptionNotCompiled& rhs) throw () { return *this; }
      virtual const char *what() const throw();
    };


    /** A cycle has been detected in the network of a domain.
     */
    class ExceptionCyclicNetwork : public ExceptionHugin {
      //	h_error_cyclic_network,
    public:
      ExceptionCyclicNetwork() throw () {}
      ExceptionCyclicNetwork(const ExceptionCyclicNetwork& rhs) throw () {}
      virtual ~ExceptionCyclicNetwork() throw () {}
      ExceptionCyclicNetwork& operator=(const ExceptionCyclicNetwork& rhs) throw () { return *this; }
      virtual const char *what() const throw();
    };


    /** The set of decisions in an influence diagram must be linearly
	ordered. There must exist a path containing all
	decisions.
    */
    class ExceptionDecisionOrder : public ExceptionHugin {
      //	h_error_decision_order,
    public:
      ExceptionDecisionOrder() throw () {}
      ExceptionDecisionOrder(const ExceptionDecisionOrder& rhs) throw () {}
      virtual ~ExceptionDecisionOrder() throw() {}
      ExceptionDecisionOrder& operator=(const ExceptionDecisionOrder& rhs) throw () { return *this; }
      virtual const char *what() const throw();
    };


    /** The specified elimination sequence is invalid.  Possible causes:
	a utility node is found, a node appears twice, the nodes are
	`out-of-order', or the sequence is incomplete.
    */
    class ExceptionEnumeration : public ExceptionHugin {
      //	h_error_enumeration,
    public:
      ExceptionEnumeration() throw () {}
      ExceptionEnumeration(const ExceptionEnumeration& rhs) throw () {}
      virtual ~ExceptionEnumeration() throw () {}
      ExceptionEnumeration& operator=(const ExceptionEnumeration& rhs) throw () { return *this; }
      virtual const char *what() const throw();
    };


    /** A zero sum was found in a conditional probability potential.
     */
    class ExceptionZeroSum : public ExceptionHugin {
      //	h_error_zero_sum
    public:
      ExceptionZeroSum() throw () {}
      ExceptionZeroSum(const ExceptionZeroSum& rhs) throw () {}
      virtual ~ExceptionZeroSum() throw () {}
      ExceptionZeroSum& operator=(const ExceptionZeroSum& rhs) throw () { return *this; }
      virtual const char *what() const throw();
    };


    /** A negative probability was found in a conditional probability or
	a chain graph potential.
    */
    class ExceptionNegativeProbability : public ExceptionHugin {
      //	h_error_negative_probability,
    public:
      ExceptionNegativeProbability() throw () {}
      ExceptionNegativeProbability(const ExceptionNegativeProbability& rhs) throw () {}
      virtual ~ExceptionNegativeProbability() throw () {}
      ExceptionNegativeProbability& operator=(const ExceptionNegativeProbability& rhs) throw () { return *this; }
      virtual const char *what() const throw();
    };


    /** Chain graph: Zero probability found in parent potential.
     */
    class ExceptionChainGraph : public ExceptionHugin {
      //	h_error_chain_graph,
    public:
      ExceptionChainGraph() throw () {}
      ExceptionChainGraph(const ExceptionChainGraph& rhs) throw () {}
      virtual ~ExceptionChainGraph() throw () {}
      ExceptionChainGraph& operator=(const ExceptionChainGraph& rhs) throw () { return *this; }
      virtual const char *what() const throw();
    };

	
    /* An error was found in the node elimination file.  The specified
	node did not exist.  This happens if you have added or changed
	the nodes in the belief network since the last time you saved
	the elimination order.  Compile normally (and save the new
	triangulation of the belief network).
    */
    /*   class ExceptionNumberingUnknownNode : public ExceptionHugin { */
    /*     //	h_error_numbering_unknown_node */
    /* 	  public: */
    /*     ExceptionNumberingUnknownNode() throw () {} */
    /*     ExceptionNumberingUnknownNode(const ExceptionNumberingUnknownNode& rhs) throw () {} */
    /*     virtual ~ExceptionNumberingUnknownNode() throw () {} */
    /*     ExceptionNumberingUnknownNode& operator=(const ExceptionNumberingUnknownNode& rhs) throw () { return *this; } */
    /*     virtual const char *what() const throw(); */
    /*   }; */

	
    /* An error was found in the node elimination file.  A node was
	specified twice (If you edit the triangulation files by hand,
	please be very careful).
    */
    /*   class ExceptionNumberingTwice : public ExceptionHugin { */
    /*     //	h_error_numbering_twice */
    /* 	  public: */
    /*     ExceptionNumberingTwice() throw () {} */
    /*     ExceptionNumberingTwice(const ExceptionNumberingTwice& rhs) throw () {} */
    /*     virtual ~ExceptionNumberingTwice() throw () {} */
    /*     ExceptionNumberingTwice& operator=(const ExceptionNumberingTwice& rhs) throw () { return *this; } */
    /*     virtual const char *what() const throw(); */
    /*   }; */

	
    /* Wrong number of nodes used in elimination order. The number of nodes specified 
	in the node elimination file did not match the number of nodes in the belief 
	network.
    */
    /*   class ExceptionNumberingBadNumber : public ExceptionHugin { */
    /*     //	h_error_numbering_bad_number */
    /* 	  public: */
    /*     ExceptionNumberingBadNumber() throw () {} */
    /*     ExceptionNumberingBadNumber(const ExceptionNumberingBadNumber& rhs) throw () {} */
    /*     virtual ~ExceptionNumberingBadNumber() throw () {} */
    /*     ExceptionNumberingBadNumber& operator=(const ExceptionNumberingBadNumber& rhs) throw () { return *this; } */
    /*     virtual const char *what() const throw(); */
    /*   }; */

	
    /** The junction tree potentials are inconsistent. 
     */
    class ExceptionNoEquilibrium : public ExceptionHugin {
      //	h_error_no_equilibrium
    public:
      ExceptionNoEquilibrium() throw () {}
      ExceptionNoEquilibrium(const ExceptionNoEquilibrium& rhs) throw () {}
      virtual ~ExceptionNoEquilibrium() throw () {}
      ExceptionNoEquilibrium& operator=(const ExceptionNoEquilibrium& rhs) throw () { return *this; }
      virtual const char *what() const throw();
    };

	
    /** Propagation of inconsistent evidence has been attempted. Or
	perhaps (but unlikely) underflow has occurred.
    */
    class ExceptionInconsistencyOrUnderflow : public ExceptionHugin {
      //	h_error_inconsistency_or_underflow
    public:
      ExceptionInconsistencyOrUnderflow() throw () {}
      ExceptionInconsistencyOrUnderflow(const ExceptionInconsistencyOrUnderflow& rhs) throw () {}
      virtual ~ExceptionInconsistencyOrUnderflow() throw () {}
      ExceptionInconsistencyOrUnderflow& operator=(const ExceptionInconsistencyOrUnderflow& rhs) throw () { return *this; }
      virtual const char *what() const throw();
    };

	
    /** Overflow occurred during propagation. 
     */
    class ExceptionOverflow : public ExceptionHugin {
      //	h_error_overflow
    public:
      ExceptionOverflow() throw () {}
      ExceptionOverflow(const ExceptionOverflow& rhs) throw () {}
      virtual ~ExceptionOverflow() throw() {}
      ExceptionOverflow& operator=(const ExceptionOverflow& rhs) throw () { return *this; }
      virtual const char *what() const throw();
    };

	
    /** The density of the evidence presented is too low to represent as
	a positive floating-point number.
    */
    class ExceptionLowDensity : public ExceptionHugin {
      //	h_error_low_density
    public:
      ExceptionLowDensity() throw () {}
      ExceptionLowDensity(const ExceptionLowDensity& rhs) throw () {}
      virtual ~ExceptionLowDensity() throw () {}
      ExceptionLowDensity& operator=(const ExceptionLowDensity& rhs) throw () { return *this; }
      virtual const char *what() const throw();
    };


    /** This operation is not supported when the junction tree
	potentials have CG evidence incorporated.
    */
    class ExceptionCGEvidenceIncorporated : public ExceptionHugin {
      //	h_error_cg_evidence_incorporated
    public:
      ExceptionCGEvidenceIncorporated() throw () {}
      ExceptionCGEvidenceIncorporated(const ExceptionCGEvidenceIncorporated& rhs) throw () {}
      virtual ~ExceptionCGEvidenceIncorporated() throw () {}
      ExceptionCGEvidenceIncorporated& operator=(const ExceptionCGEvidenceIncorporated& rhs) throw () { return *this; }
      virtual const char *what() const throw();
    };


    /** Normalization with a zero normalization constant has been
	attempted.
    */
    class ExceptionNormalization : public ExceptionHugin {
      //	h_error_normalization,
    public:
      ExceptionNormalization() throw () {}
      ExceptionNormalization(const ExceptionNormalization& rhs) throw () {}
      virtual ~ExceptionNormalization() throw () {}
      ExceptionNormalization& operator=(const ExceptionNormalization& rhs) throw () { return *this; }
      virtual const char *what() const throw();
    };


    /** The operation is not supported on compressed domains.
     */
    class ExceptionCompressed : public ExceptionHugin {
      //	h_error_compressed
    public:
      ExceptionCompressed() throw () {}
      ExceptionCompressed(const ExceptionCompressed& rhs) throw () {}
      virtual ~ExceptionCompressed() throw () {}
      ExceptionCompressed& operator=(const ExceptionCompressed& rhs) throw () { return *this; }
      virtual const char *what() const throw();
    };


    /** The compressed version of some non-clique table is too large. 
     */
    class ExceptionTableTooLarge : public ExceptionHugin {
      //	h_error_table_too_large
    public:
      ExceptionTableTooLarge() throw () {}
      ExceptionTableTooLarge(const ExceptionTableTooLarge& rhs) throw () {}
      virtual ~ExceptionTableTooLarge() throw () {}
      ExceptionTableTooLarge& operator=(const ExceptionTableTooLarge& rhs) throw () { return *this; }
      virtual const char *what() const throw();
    };


    /** An error occurred while parsing a NET specification.  If a
	parsing error handling function was specified, it will have been
	called with a description of the error and its location in the
	NET specification.
    */
    class ExceptionParse : public ExceptionHugin {
      //	h_error_parse
    public:
      ExceptionParse() throw () {}
      ExceptionParse(const ExceptionParse& rhs) throw () {}
      virtual ~ExceptionParse() throw () {}
      ExceptionParse& operator=(const ExceptionParse& rhs) throw () { return *this; }
      virtual const char *what() const throw();
    };


    /** The Hugin API could not establish the C locale. 
     */
    class ExceptionLocale : public ExceptionHugin {
      //	h_error_locale
    public:
      ExceptionLocale() throw () {}
      ExceptionLocale(const ExceptionLocale& rhs) throw () {}
      virtual ~ExceptionLocale() throw () {}
      ExceptionLocale& operator=(const ExceptionLocale& rhs) throw () { return *this; }
      virtual const char *what() const throw();
    };


    /** The supplied expression is invalid (for example, wrong type).
     */
    class ExceptionInvalidExpression : public ExceptionHugin {
      //	h_error_invalid_expression
    public:
      ExceptionInvalidExpression() throw () {}
      ExceptionInvalidExpression(const ExceptionInvalidExpression& rhs) throw () {}
      virtual ~ExceptionInvalidExpression() throw () {}
      ExceptionInvalidExpression& operator=(const ExceptionInvalidExpression& rhs) throw () { return *this; }
      virtual const char *what() const throw();
    };


    /** A syntax error has been detected while parsing an expression.
     */
    class ExceptionSyntax : public ExceptionHugin {
      //	h_error_syntax
    public:
      ExceptionSyntax() throw () {}
      ExceptionSyntax(const ExceptionSyntax& rhs) throw () {}
      virtual ~ExceptionSyntax() throw () {}
      ExceptionSyntax& operator=(const ExceptionSyntax& rhs) throw () { return *this; }
      virtual const char *what() const throw();
    };


    /** Division by zero has been attempted.
     */
    class ExceptionDivisionByZero : public ExceptionHugin {
      //	h_error_division_by_zero
    public:
      ExceptionDivisionByZero() throw () {}
      ExceptionDivisionByZero(const ExceptionDivisionByZero& rhs) throw () {}
      virtual ~ExceptionDivisionByZero() throw () {}
      ExceptionDivisionByZero& operator=(const ExceptionDivisionByZero& rhs) throw () { return *this; }
      virtual const char *what() const throw();
    };


    /** Illegal arguments have been given to a standard
	probability/density function.
    */
    class ExceptionInappropriateArguments : public ExceptionHugin {
      //	h_error_inappropriate_arguments
    public:
      ExceptionInappropriateArguments() throw () {}
      ExceptionInappropriateArguments(const ExceptionInappropriateArguments& rhs) throw () {}
      virtual ~ExceptionInappropriateArguments() throw () {}
      ExceptionInappropriateArguments& operator=(const ExceptionInappropriateArguments& rhs) throw () { return *this; }
      virtual const char *what() const throw();
    };


    /** The probability/density function could not be computed.
     */
    class ExceptionComputationFailed : public ExceptionHugin {
      //	h_error_computation_failed
    public:
      ExceptionComputationFailed() throw () {}
      ExceptionComputationFailed(const ExceptionComputationFailed& rhs) throw () {}
      virtual ~ExceptionComputationFailed() throw () {}
      ExceptionComputationFailed& operator=(const ExceptionComputationFailed& rhs) throw () { return *this; }
      virtual const char *what() const throw();
    };


    /** The state range of the node is insufficient for the chosen
	standard distribution.
    */
    class ExceptionInsufficientStateRange : public ExceptionHugin {
      //	h_error_insufficient_state_range
    public:
      ExceptionInsufficientStateRange() throw () {}
      ExceptionInsufficientStateRange(const ExceptionInsufficientStateRange& rhs) throw () {}
      virtual ~ExceptionInsufficientStateRange() throw () {}
      ExceptionInsufficientStateRange& operator=(const ExceptionInsufficientStateRange& rhs) throw () { return *this; }
      virtual const char *what() const throw();
    };


    /** The state values of a numeric node do not form an increasing
	sequence.
    */
    class ExceptionInvalidStateValues : public ExceptionHugin {
      //	h_error_invalid_state_values
    public:
      ExceptionInvalidStateValues() throw () {}
      ExceptionInvalidStateValues(const ExceptionInvalidStateValues& rhs) throw () {}
      virtual ~ExceptionInvalidStateValues() throw () {}
      ExceptionInvalidStateValues& operator=(const ExceptionInvalidStateValues& rhs) throw () { return *this; }
      virtual const char *what() const throw();
    };


    /* Some Serene information is inconsistent.
     */
    /*   class ExceptionSerene : public ExceptionHugin { */
    /*     //	h_error_serene */
    /* 	  public: */
    /*     ExceptionSerene() throw () {} */
    /*     ExceptionSerene(const ExceptionSerene& rhs) throw () {} */
    /*     virtual ~ExceptionSerene() throw () {} */
    /*     ExceptionSerene& operator=(const ExceptionSerene& rhs) throw () { return *this; } */
    /*     virtual const char *what() const throw(); */
    /*   }; */


    /* An old style API function has been called while no domain was
	selected.
    */
    /*   class ExceptionNoCurrentDomain : public ExceptionHugin { */
    /*     //	h_error_no_current_domain */
    /* 	  public: */
    /*     ExceptionNoCurrentDomain() throw () {} */
    /*     ExceptionNoCurrentDomain(const ExceptionNoCurrentDomain& rhs) throw () {} */
    /*     virtual ~ExceptionNoCurrentDomain() throw () {} */
    /*     ExceptionNoCurrentDomain& operator=(const ExceptionNoCurrentDomain& rhs) throw () { return *this; } */
    /*     virtual const char *what() const throw(); */
    /*   }; */


    /* The state name given as argument does not occur at the node
	given as argument.  Can happen if bad arguments are given to
	`enterFinding()'.
    */
    /*   class ExceptionUnknownState : public ExceptionHugin { */
    /*     //	h_error_unknown_state */
    /* 	  public: */
    /*     ExceptionUnknownState() throw () {} */
    /*     ExceptionUnknownState(const ExceptionUnknownState& rhs) throw () {} */
    /*     virtual ~ExceptionUnknownState() throw () {} */
    /*     ExceptionUnknownState& operator=(const ExceptionUnknownState& rhs) throw () { return *this; } */
    /*     virtual const char *what() const throw(); */
    /*   }; */


    /** Use of invalid pointer attempted.
     */
    class ExceptionBadPointer : public ExceptionHugin {
    public:
      ExceptionBadPointer() throw () {}
      ExceptionBadPointer(const ExceptionBadPointer& rhs) throw () {}
      virtual ~ExceptionBadPointer() throw () {}
      ExceptionBadPointer& operator=(const ExceptionBadPointer& rhs) throw () { return *this; }
      virtual const char *what() const throw();
    };


    /** Attempted to read a value associate with a non-existing
	attribute.
    */
    class ExceptionAttribute : public ExceptionHugin {
    public:
      ExceptionAttribute() throw () {}
      ExceptionAttribute(const ExceptionAttribute& rhs) throw() {}
      virtual ~ExceptionAttribute() throw () {}
      ExceptionAttribute& operator=(const ExceptionAttribute& rhs) throw ();
      virtual const char *what() const throw();
    };


    /** Attempted to use a table of wrong dimensions, e.g., while
	setting data of a table.
    */
    class ExceptionTableSize : public ExceptionHugin {
    public:
      ExceptionTableSize() throw () {}
      ExceptionTableSize(const ExceptionTableSize& rhs) throw() {}
      virtual ~ExceptionTableSize() throw () {}
      ExceptionTableSize& operator=(const ExceptionTableSize& rhs) throw ();
      virtual const char *what() const throw();
    };


    /** Attempted to work on domain, with invalid license information,
     */
    class ExceptionInvalidLicense : public ExceptionHugin {
    public:
      ExceptionInvalidLicense() throw () {}
      ExceptionInvalidLicense(const ExceptionInvalidLicense& rhs) throw() {}
      virtual ~ExceptionInvalidLicense() throw () {}
      ExceptionInvalidLicense& operator=(const ExceptionInvalidLicense& rhs) throw ();
      virtual const char *what() const throw();
    };


    /** Attempted to work on domain, which, 
     */
    class ExceptionDemo : public ExceptionHugin {
    public:
      ExceptionDemo() throw () {}
      ExceptionDemo(const ExceptionDemo& rhs) throw() {}
      virtual ~ExceptionDemo() throw () {}
      ExceptionDemo& operator=(const ExceptionDemo& rhs) throw ();
      virtual const char *what() const throw();
    };


    /** This is an impossible error.  It should never occur.  It might
	be caused by an error in the Hugin API.
    */
    class ExceptionError : public ExceptionHugin {
      //	h_error_error
    public:
      ExceptionError() throw () {}
      ExceptionError(const ExceptionError& rhs) throw() {}
      virtual ~ExceptionError() throw () {}
      ExceptionError& operator=(const ExceptionError& rhs) throw () { return *this; }
      virtual const char *what() const throw();
    };


    /** Expression is the ancestor of all expression classes.
     * Expression classes are used to build expressions for
     * discrete chance node tables and utility tables (see
     * also class Model).*/
    class Expression {           
    public:
      Expression();
      Expression(const Expression& exprSrc) throw(HAPI::ExceptionHugin);
      virtual ~Expression() throw( ExceptionHugin );
      virtual Expression * clone() =0;
      /** Test whether this Expression is an instance of CompositeExpression
       */
      virtual bool isCompositeExpression() =0;
      /** Test whether this Expression is an instance of ConstantExpression
       */
      virtual bool isConstantExpression() =0;
      /** Test whether this Expression is an instance of NodeExpression
       */
      virtual bool isNodeExpression() =0;
      Expression& operator=(const Expression& rightExpr) throw( ExceptionHugin );
      /** Create an Expression from a given string. To ease the creation
	  of complex expressions, it is possible to specify these as 
	  strings, instead of building them with objects. 
	  
	  Example: The following code
	  
	  Expression *result=new IfExpression(new BooleanExpression(true), new NumberExpression(1), new DistributionDistribution(new NumberExpression(1), new NumberExpression(2)));
	  
	  can be written like this:
	  
	  Expression *result=NetworkModel::stringToExpression("if(true, 1, Distribution(1,2))", domain);
	  @param str The string containing a textual representation
	  of the expression
	  @param dom The domain in which the Expression is generated
       */
      static Expression * stringToExpression(const std::string& str, Domain dom) throw( ExceptionHugin );

      /** Equivalent to stringToExpression(string, Domain) except that it will accept
	  both a Class and a Domain as parameter. 
      */
      static Expression * stringToExpression(const std::string& str, NetworkModel* dom) throw( ExceptionHugin );


      std::string toString() throw( ExceptionHugin );
    protected:
      friend class IModel;
      friend class IExpression;

      IExpression* internalExpression;
    };


    /** The ancestor of all expression classes representing a
     * constant (label, number, or Boolean).*/
    class ConstantExpression : public Expression {
    public:
      virtual Expression * clone() throw( ExceptionHugin ) =0;
      virtual bool isBooleanExpression() =0;

      /** Test if the the expression is a ConstantExpression.
	  @return boolean
      */
      bool isConstantExpression() throw();

      /** Test if the the expression is a CompositeExpression.
	  @return boolean
      */
      bool isCompositeExpression() throw();

      /** Test if the the expression is a LabelExpression.
	  @return boolean
      */
      virtual bool isLabelExpression() =0;

      /** Test if the the expression is a NodeExpression.
	  @return boolean
      */
      bool isNodeExpression() throw();

      /** Test if the the expression is a NumberExpression.
	  @return boolean
      */
      virtual bool isNumberExpression() =0;



    };



    /** An expression representing the value of a discrete chance
     * node or decision node.*/
    class NodeExpression : public Expression {
    public:
      NodeExpression(Node *nd) throw(HAPI::ExceptionHugin);

      /** Clone the NodeExpression.
	  @return Expression*
      */
      virtual Expression * clone() throw(HAPI::ExceptionHugin);

      /** Return the node used to build the expression.
	  @return Node*
      */
      virtual Node *getNode() throw(HAPI::ExceptionHugin);

      /** Return the node used to build the expression.
	  @return Node*
      */
      virtual Node *getValue() throw(HAPI::ExceptionHugin);

      /** Test if the the expression is a CompositeExpression.
	  @return boolean
      */
      bool isCompositeExpression() throw();

      /** Test if the the expression is a ConstantExpression.
	  @return boolean
      */
      bool isConstantExpression() throw();

      /** Test if the the expression is a NodeExpression.
	  @return boolean
      */
      bool isNodeExpression() throw();

    };


    /** The ancestor class of all composite expression (for example arithmetic operators or 
	standard distribution functions).
    */
    class CompositeExpression : public Expression {
    public:

      /** Create a composite expression from a list of expressions
       */
      CompositeExpression(const ExpressionList &newArgs, Operator op) throw(HAPI::ExceptionHugin);

      /** Copy construct a composite expression. 
       */
      CompositeExpression(const CompositeExpression& src) throw( ExceptionHugin );

      /** Construct a composite expression from a single expression. 
       */
      CompositeExpression(Expression *newArg, Operator op) throw( ExceptionHugin );

      /** Construct a composite expression from two expressions.
       */
      CompositeExpression(Expression *newArg1, Expression *newArg2, Operator op) throw( ExceptionHugin );

      /** Construct a composite expression from three expressions.
       */
      CompositeExpression(Expression *newArg1, Expression *newArg2, Expression *newArg3, Operator op) throw( ExceptionHugin );

      /** Construct a composite expression from four expressions.
       */
      CompositeExpression(Expression *newArg1, Expression *newArg2, Expression *newArg3, Expression *newArg4, Operator op) throw( ExceptionHugin );

      /** Destruct CompositeExpression. 
       */
      virtual ~CompositeExpression();

      /** Clone the expression. 
	  @return Pointer to Expression
      */
      virtual Expression * clone() =0;

      /** Return an ExpressionList containing the Expressions in the CompositeExpression. 
       */
      virtual ExpressionList getOperands() throw();

      virtual Operator getOperator() =0;

      /** Test if the the expression is a CompositeExpression.
	  @return boolean
      */
      virtual bool isCompositeExpression() throw();

      /** Test if the the expression is a ConstantExpression.
	  @return boolean
      */
      virtual bool isConstantExpression() throw();

      /** Test if the the expression is a NodeExpression.
	  @return boolean
      */
      virtual bool isNodeExpression() throw();

    protected:
      void initArguments(const ExpressionList& newArgs) throw( ExceptionHugin );
      ExpressionList args;
    };


    /** A label constant expression. This type of expression is
     * used to compare with state labels of labelled discrete
     * chance nodes or decision nodes.*/
    class LabelExpression : public ConstantExpression {
    public:
      /** Construct a LabelExpression from a string. 
	  @param newLabel A Standard C++ Library string.
      */
      LabelExpression(const std::string& newLabel) throw(HAPI::ExceptionHugin);

      /** Clone the expression. 
	  @return Pointer to Expression
      */
      virtual Expression * clone() throw(HAPI::ExceptionHugin);

      /** Return the label of the expresion. 
	  @return string
      */
      std::string getLabel() throw(HAPI::ExceptionHugin);

      /** Return the label of the expresion. 
	  @return string
      */
      std::string getValue() throw(HAPI::ExceptionHugin);

      /** Test if the the expression is a BooleanExpression.
	  @return boolean
      */
      bool isBooleanExpression() throw();

      /** Test if the the expression is a LabelExpression.
	  @return boolean
      */
      bool isLabelExpression() throw();

      /** Test if the the expression is a NumberExpression.
	  @return boolean
      */
      bool isNumberExpression() throw();
    
    };


    /** A Boolean constant expression. This type of expression is
     * used to compare with state values of Boolean discrete
     * chance nodes or decision nodes.*/
    class BooleanExpression : public ConstantExpression {
    public:
      /** Construct a BooleanExpression from a string. 
	  @param newvalue boolean
      */
      BooleanExpression(bool newValue) throw( ExceptionHugin );

      /** Clone the expression. 
	  @return Pointer to Expression
      */
      virtual Expression * clone() throw( ExceptionHugin );

      /** Return the value of the BooleanExpression 
	  @return boolean
      */
      bool getBoolean() throw( ExceptionHugin );
	
      /** Return the Operator for this Expression.
	  @return Operator
      */
      Operator getOperator() throw (ExceptionHugin);

      /** Return the value of teh Expression.
	  @return bool
      */
      bool getValue() throw(ExceptionHugin);

      /** Test if the the expression is a BooleanExpression.
	  @return boolean
      */
      bool isBooleanExpression() throw();

      /** Test if the the expression is a LabelExpression.
	  @return boolean
      */
      bool isLabelExpression() throw();

      /** Test if the the expression is a NumberExpression.
	  @return boolean
      */
      bool isNumberExpression() throw();

    };


    /** A numeric constant expression. This type of expression is
     * used to compare with state values of numbered or interbal
     * discrete chance nodes or decision nodes.*/
    class NumberExpression : public ConstantExpression {
    public:
      NumberExpression(double newValue) throw(HAPI::ExceptionHugin);

      /** Clone the expression. 
	  @return Pointer to Expression
      */
      virtual Expression * clone() throw(HAPI::ExceptionHugin);

      /** Return the number respresented by the expression.
	  @return double
      */
      double getNumber() throw(HAPI::ExceptionHugin);

      /** Return the number respresented by the expression.
	  @return double
      */
      double getValue() throw(HAPI::ExceptionHugin);

      /** Test if the the expression is a BooleanExpression.
	  @return boolean
      */
      bool isBooleanExpression() throw();

      /** Test if the the expression is a LabelExpression.
	  @return boolean
      */
      bool isLabelExpression() throw();

      /** Test if the the expression is a NumberExpression.
	  @return boolean
      */
      bool isNumberExpression() throw();

    };


    /** Expression class representing the + operator.*/
    class AddExpression : public CompositeExpression {
    public:
      /** Construct a new AddExpression */
      AddExpression(Expression *newArg1, Expression *newArg2) throw( HAPI::ExceptionHugin );

      /** Copy construct a new AddExpression. */
      AddExpression(const ExpressionList& newArgs) throw( HAPI::ExceptionHugin );

      /** Clone the expression. 
	  @return Pointer to Expression
      */
      virtual Expression * clone() throw(HAPI::ExceptionHugin);

      /** Return the operator of the expression */
      Operator getOperator() throw();
    };


    /** Expression class representing the binary - operator.*/
    class SubtractExpression : public CompositeExpression {
    public:
      /** Construct a new SubtractExpression */
      SubtractExpression(Expression *newArg1, Expression *newArg2) throw(HAPI::ExceptionHugin);

      /** Clone the expression. 
	  @return Pointer to Expression
      */
      virtual Expression * clone() throw(HAPI::ExceptionHugin);

      /** Return the operator of the expression */
      Operator getOperator() throw();
    };


    /** Expression class representing the unary - operator.*/
    class NegateExpression : public CompositeExpression {
    public:
      /** Construct a new NegateExpression */
      NegateExpression(Expression *newArg) throw(HAPI::ExceptionHugin);

      /** Clone the expression. 
	  @return Pointer to Expression
      */
      virtual Expression * clone() throw(HAPI::ExceptionHugin);

      /** Return the operator of the expression */
      Operator getOperator() throw();
    };


    /** Expression class representing the * operator.*/
    class MultiplyExpression : public CompositeExpression {
    public:
      /** Construct a new MultiplicationExpression */
      MultiplyExpression(const ExpressionList& newArgs) throw(HAPI::ExceptionHugin);
      /** Construct a new MultiplicationExpression */
      MultiplyExpression(Expression *newArg1, Expression *newArg2) throw(HAPI::ExceptionHugin);

      /** Clone the expression. 
	  @return Pointer to Expression
      */
      virtual Expression * clone() throw(HAPI::ExceptionHugin);
    
      /** Return the operator of the expression */
      Operator getOperator() throw();

    };


    /** Expression class representing the / operator.*/
    class DivideExpression : public CompositeExpression {
    public:
      /** Construct a new DivisionExpression */
      DivideExpression(Expression *newArg1, Expression *newArg2) throw( ExceptionHugin );

      /** Clone the expression. 
	  @return Pointer to Expression
      */
      virtual Expression * clone() throw( ExceptionHugin );
    
      /** Return the operator of the expression */
      Operator getOperator() throw();
    };


    /** Expression class representing the ^ operator.*/
    class PowerExpression : public CompositeExpression {
    public:
      /** Construct a new PowerExpression */
      PowerExpression(Expression *newArg1, Expression *newArg2) throw(HAPI::ExceptionHugin);

      /** Clone the expression. 
	  @return Pointer to Expression
      */
      virtual Expression * clone() throw(HAPI::ExceptionHugin);

      /** Return the operator of the expression */
      Operator getOperator() throw();
    };


    /** Expression class representing the == operator.*/
    class EqualsExpression : public CompositeExpression {
    public:
      /** Construct a new EqualsExpression */
      EqualsExpression(Expression *newArg1, Expression *newArg2) throw( ExceptionHugin );

      /** Clone the expression. 
	  @return Pointer to Expression
      */
      virtual Expression * clone() throw( ExceptionHugin );

      /** Return the operator of the expression */
      Operator getOperator() ;
    };


    /** Expression class representing the < operator.*/
    class LessThanExpression : public CompositeExpression {
    public:
      /** Construct a new LessThanExpression */
      LessThanExpression(Expression *newArg1, Expression *newArg2) throw(HAPI::ExceptionHugin);
      /** Return the operator of the expression */
      Operator getOperator() throw();

      /** Clone the expression. 
	  @return Pointer to Expression
      */
      virtual Expression * clone() throw(HAPI::ExceptionHugin);
    };


    /** Expression class representing the > operator.*/
    class GreaterThanExpression : public CompositeExpression {
    public:
      /** Construct a new GreaterThanExpression */
      GreaterThanExpression(Expression *newArg1, Expression *newArg2) throw( ExceptionHugin );

      /** Clone the expression. 
	  @return Pointer to Expression
      */
      virtual Expression * clone() throw( ExceptionHugin );

      /** Return the operator of the expression */
      Operator getOperator() throw();
    };


    /** Expression class representing the != operator.*/
    class NotEqualsExpression : public CompositeExpression {
    public:
      /** Construct a new NotEqualsExpression */
      NotEqualsExpression(Expression *newArg1, Expression *newArg2) throw(HAPI::ExceptionHugin);

      /** Clone the expression. 
	  @return Pointer to Expression
      */
      virtual Expression * clone() throw(HAPI::ExceptionHugin);

      /** Return the operator of the expression */
      Operator getOperator() throw();
    };


    /** Expression class representing the <= operator.*/
    class LessThanOrEqualsExpression : public CompositeExpression {
    public:
      /** Construct a new LessThanOrEqualsExpression */
      LessThanOrEqualsExpression(Expression *newArg1, Expression *newArg2) throw(HAPI::ExceptionHugin);

      /** Clone the expression. 
	  @return Pointer to Expression
      */
      virtual Expression * clone() throw(HAPI::ExceptionHugin);

      /** Return the operator of the expression */
      Operator getOperator() throw();
    };


    /** Expression class representing the >= operator.*/
    class GreaterThanOrEqualsExpression : public CompositeExpression {
    public:
      /** Construct a new GreaterThanOrEqualsExpression */
      GreaterThanOrEqualsExpression(Expression *newArg1, Expression *newArg2) throw( ExceptionHugin );

      /** Clone the expression. 
	  @return Pointer to Expression
      */
      virtual Expression * clone() throw( ExceptionHugin );

      /** Return the operator of the expression */
      Operator getOperator() throw();
    };


    /** Expression class representing the min() function.*/
    class MinExpression : public CompositeExpression {
    public:
      /** Construct a new MinExpression */
      MinExpression(const ExpressionList& newArgs) throw(HAPI::ExceptionHugin);
      /** Construct a new MinExpression */
      MinExpression(Expression *newArg1, Expression *newArg2) throw(HAPI::ExceptionHugin);

      /** Clone the expression. 
	  @return Pointer to Expression
      */
      virtual Expression * clone() throw(HAPI::ExceptionHugin);

      /** Return the operator of the expression */
      Operator getOperator() throw();
    };


    /** Expression class representing the max() function.*/
    class MaxExpression : public CompositeExpression {
    public:
      /** Construct a new MaxExpression */
      MaxExpression(Expression *newArg1, Expression *newArg2) throw(HAPI::ExceptionHugin);
      /** Construct a new MaxExpression */
      MaxExpression(const ExpressionList& newArgs) throw(HAPI::ExceptionHugin);

      /** Clone the expression. 
	  @return Pointer to Expression
      */
      virtual Expression * clone() throw(HAPI::ExceptionHugin);

      /** Return the operator of the expression */
      Operator getOperator() throw();
    };


    /** Expression class representing the Abs() function.*/
    class AbsExpression : public CompositeExpression {
    public:
      /** Construct a new AbsExpression */
      AbsExpression(Expression *newArg1) throw(HAPI::ExceptionHugin);

      /** Clone the expression. 
	  @return Pointer to Expression
      */
      virtual Expression * clone() throw(HAPI::ExceptionHugin);

      /** Return the operator of the expression */
      Operator getOperator() throw();
    };



    /** Expression class representing the mod() function.*/
    class ModExpression : public CompositeExpression {
    public:
      /** Construct a new ModExpression */
      ModExpression(Expression *newArg1, Expression *newArg2  ) throw(HAPI::ExceptionHugin);

      /** Clone the expression. 
	  @return Pointer to Expression
      */
      virtual Expression * clone() throw(HAPI::ExceptionHugin);

      /** Return the operator of the expression */
      Operator getOperator() throw();
    };


    /** Expression class representing the ceil() function.*/
    class CeilExpression : public CompositeExpression {
    public:
      /** Construct a new CeilExpression */
      CeilExpression(Expression *newArg1) throw(HAPI::ExceptionHugin);
    

      /** Clone the expression. 
	  @return Pointer to Expression
      */
      virtual Expression * clone() throw(HAPI::ExceptionHugin);

      /** Return the operator of the expression */
      Operator getOperator() throw();
    };



    /** Expression class representing the floor() function.*/
    class FloorExpression : public CompositeExpression {
    public:
      /** Construct a new FloorExpression */
      FloorExpression(Expression *newArg1) throw(HAPI::ExceptionHugin);
    
      /** Clone the expression. 
	  @return Pointer to Expression
      */
      virtual Expression * clone() throw(HAPI::ExceptionHugin);

      /** Return the operator of the expression */
      Operator getOperator() throw();
    };




    /** Expression class representing the log() function.*/
    class LogExpression : public CompositeExpression {
    public:
      /** Construct a new LogExpression */
      LogExpression(Expression *newArg) throw(HAPI::ExceptionHugin);

      /** Clone the expression. 
	  @return Pointer to Expression
      */
      virtual Expression * clone() throw(HAPI::ExceptionHugin);

      /** Return the operator of the expression */
      Operator getOperator() throw();
    };


    /** Expression class representing the exp() function.*/
    class ExpExpression : public CompositeExpression {
    public:
      /** Construct a new ExpExpression */
      ExpExpression(Expression *newArg) throw( ExceptionHugin );

      /** Clone the expression. 
	  @return Pointer to Expression
      */
      virtual Expression * clone() throw( ExceptionHugin );

      /** Return the operator of the expression */
      Operator getOperator() throw();
    };


    /** Expression class representing the sqrt() function.*/
    class SqrtExpression : public CompositeExpression {
    public:
      /** Construct a new SqrtExpression */
      SqrtExpression(Expression *newArg) throw(HAPI::ExceptionHugin);

      /** Clone the expression. 
	  @return Pointer to Expression
      */
      virtual Expression * clone() throw(HAPI::ExceptionHugin);

      /** Return the operator of the expression */
      Operator getOperator() throw();
    };


    /** Expression class representing the log2() function.*/
    class Log2Expression : public CompositeExpression {
    public:
      /** Construct a new Log2Expression */
      Log2Expression(Expression *newArg) throw(HAPI::ExceptionHugin);

      /** Clone the expression. 
	  @return Pointer to Expression
      */
      virtual Expression * clone() throw(HAPI::ExceptionHugin);

      /** Return the operator of the expression */
      Operator getOperator() throw();
    };


    /** Expression class representing the Log10() function.*/
    class Log10Expression : public CompositeExpression {
    public:
      /** Construct a new Log10Expression */
      Log10Expression(Expression *newArg) throw(HAPI::ExceptionHugin);

      /** Clone the expression. 
	  @return Pointer to Expression
      */
      virtual Expression * clone() throw(HAPI::ExceptionHugin);

      /** Return the operator of the expression */
      Operator getOperator() throw();
    };


    /** Expression class representing the Sin() function.*/
    class SinExpression : public CompositeExpression {
    public:
      /** Construct a new SinExpression */
      SinExpression(Expression *newArg) throw(HAPI::ExceptionHugin);

      /** Clone the expression. 
	  @return Pointer to Expression
      */
      virtual Expression * clone() throw(HAPI::ExceptionHugin);

      /** Return the operator of the expression */
      Operator getOperator() throw();
    };


    /** Expression class representing the Cos() function.*/
    class CosExpression : public CompositeExpression {
    public:
      /** Construct a new CosExpression */
      CosExpression(Expression *newArg) throw(HAPI::ExceptionHugin);

      /** Clone the expression. 
	  @return Pointer to Expression
      */
      virtual Expression * clone() throw(HAPI::ExceptionHugin);

      /** Return the operator of the expression */
      Operator getOperator() throw();
    };


    /** Expression class representing the Tan() function.*/
    class TanExpression : public CompositeExpression {
    public:
      /** Construct a new TanExpression */
      TanExpression(Expression *newArg) throw(HAPI::ExceptionHugin);

      /** Clone the expression. 
	  @return Pointer to Expression
      */
      virtual Expression * clone() throw(HAPI::ExceptionHugin);

      /** Return the operator of the expression */
      Operator getOperator() throw();
    };

    /** Expression class representing the Sinh() function.*/
    class SinhExpression : public CompositeExpression {
    public:
      /** Construct a new SinhExpression */
      SinhExpression(Expression *newArg) throw(HAPI::ExceptionHugin);

      /** Clone the expression. 
	  @return Pointer to Expression
      */
      virtual Expression * clone() throw(HAPI::ExceptionHugin);

      /** Return the operator of the expression */
      Operator getOperator() throw();
    };

    /** Expression class representing the Cosh() function.*/
    class CoshExpression : public CompositeExpression {
    public:
      /** Construct a new CoshExpression */
      CoshExpression(Expression *newArg) throw(HAPI::ExceptionHugin);

      /** Clone the expression. 
	  @return Pointer to Expression
      */
      virtual Expression * clone() throw(HAPI::ExceptionHugin);

      /** Return the operator of the expression */
      Operator getOperator() throw();
    };

    /** Expression class representing the Tanh() function.*/
    class TanhExpression : public CompositeExpression {
    public:
      /** Construct a new TanhExpression */
      TanhExpression(Expression *newArg) throw(HAPI::ExceptionHugin);

      /** Clone the expression. 
	  @return Pointer to Expression
      */
      virtual Expression * clone() throw(HAPI::ExceptionHugin);

      /** Return the operator of the expression */
      Operator getOperator() throw();
    };




    /** Expression class representing the
     * if(cond-expr,true-expr,false-expr) function.*/
    class IfExpression : public CompositeExpression {
    public:
      /** Construct a new IfExpression */
      IfExpression(Expression *newCondition, Expression *newTrueExpr, Expression *newFalseExpr) throw( ExceptionHugin );

      /** Clone the expression. 
	  @return Pointer to Expression
      */
      virtual Expression * clone() throw( ExceptionHugin );

      /** Return the operator of the expression */
      Operator getOperator() throw();
    };


    /** Expression class representing the and() function.*/
    class AndExpression : public CompositeExpression {
    public:
      /** Construct a new AndExpression */
      AndExpression(const ExpressionList& newArgs) throw(HAPI::ExceptionHugin);
      /** Construct a new AndExpression */
      AndExpression(Expression *newArg1, Expression *newArg2) throw(HAPI::ExceptionHugin);

      /** Clone the expression. 
	  @return Pointer to Expression
      */
      virtual Expression * clone() throw(HAPI::ExceptionHugin);

      /** Return the operator of the expression */
      Operator getOperator() throw();
    };


    /** Expression class representing the Boolean or() function.*/
    class OrExpression : public CompositeExpression {
    public:
      /** Construct a new OrExpression */
      OrExpression(Expression *newArg1, Expression *newArg2) throw(HAPI::ExceptionHugin);
      /** Construct a new OrExpression */
      OrExpression(const ExpressionList& newArgs) throw(HAPI::ExceptionHugin);

      /** Clone the expression. 
	  @return Pointer to Expression
      */
      virtual Expression * clone() throw(HAPI::ExceptionHugin);

      /** Return the operator of the expression */
      Operator getOperator() throw();
    };


    /** Expression class representing the Distribution() function.*/
    class DistributionDistribution : public CompositeExpression {
    public:

      /** Construct a new Distribution */
      DistributionDistribution(const ExpressionList& newArgs) throw(HAPI::ExceptionHugin);

      /** Clone the expression. 
	  @return Pointer to Expression
      */
      virtual Expression * clone() throw(HAPI::ExceptionHugin);

      /** Return the operator of the expression */
      Operator getOperator() throw();
    };


    /** Expression class representing the NoisyOr() function.*/
    class NoisyOrExpression : public CompositeExpression {
    public:
      /** Construct a new NoisyOrExpression */
      NoisyOrExpression(Expression *newArg1, Expression *newArg2) throw(HAPI::ExceptionHugin);
      /** Construct a new NoisyOrExpression */
      NoisyOrExpression(const ExpressionList& newArgs) throw(HAPI::ExceptionHugin);

      /** Clone the expression. 
	  @return Pointer to Expression
      */
      virtual Expression * clone() throw(HAPI::ExceptionHugin);

      /** Return the operator of the expression */
      Operator getOperator() throw();
    };


    /** Expression class representing the Boolean not() function.*/
    class NotExpression : public CompositeExpression {
    public:
      /** Construct a new NotExpression */
      NotExpression(Expression *newArg) throw(HAPI::ExceptionHugin);

      /** Clone the expression. 
	  @return Pointer to Expression
      */
      virtual Expression * clone() throw(HAPI::ExceptionHugin);

      /** Return the operator of the expression */
      Operator getOperator() throw();
    };


    /** Expression class representing the Gaussian normal
     * distribution function.*/
    class NormalDistribution : public CompositeExpression {
    public:
      /** Construct a new NormalDistribution */
      NormalDistribution(Expression *newMean, Expression *newVariance) throw(HAPI::ExceptionHugin);

      /** Clone the expression. 
	  @return Pointer to Expression
      */
      virtual Expression * clone() throw(HAPI::ExceptionHugin);

      /** Return the operator of the expression */
      Operator getOperator() throw();
    };


    /** Expression class representing the Beta distribution function.*/
    class BetaDistribution : public CompositeExpression {
    public:
      /** Construct a new BetaDistribution */
      BetaDistribution(Expression *newAlpha, Expression *newBeta, Expression *newLower, Expression *newUpper) throw( ExceptionHugin );
      /** Construct a new BetaDistribution */
      BetaDistribution(Expression *newAlpha, Expression *newBeta) throw( ExceptionHugin );

      /** Clone the expression. 
	  @return Pointer to Expression
      */
      virtual Expression * clone() throw( ExceptionHugin );

      /** Return the operator of the expression */
      Operator getOperator() throw();
    };


    /** Expression class representing the Gamma distribution function.*/
    class GammaDistribution : public CompositeExpression {
    public:
      /** Construct a new GammaDistribution */
      GammaDistribution(Expression *newShape, Expression *newScale) throw( ExceptionHugin );

      /** Clone the expression. 
	  @return Pointer to Expression
      */
      virtual Expression * clone() throw( ExceptionHugin );

      /** Return the operator of the expression */
      Operator getOperator() throw(HAPI::ExceptionHugin);
    };


    /** Expression class representing the Exponential distribution
     * function.*/
    class ExponentialDistribution : public CompositeExpression {
    public:
      /** Construct a new ExponentialDistribution */
      ExponentialDistribution(Expression *newLambda) throw( ExceptionHugin );

      /** Clone the expression. 
	  @return Pointer to Expression
      */
      virtual Expression * clone() throw( ExceptionHugin );

      /** Return the operator of the expression */
      Operator getOperator() throw();
    };


    /** Expression class representing the Weibull distribution
     * function.*/
    class WeibullDistribution : public CompositeExpression {
    public:
      /** Construct a new WeibullDistribution */
      WeibullDistribution(Expression *newShape, Expression *newScale) throw(HAPI::ExceptionHugin);

      /** Clone the expression. 
	  @return Pointer to Expression
      */
      virtual Expression * clone() throw(HAPI::ExceptionHugin);

      /** Return the operator of the expression */
      Operator getOperator() throw();
    };


    /** Expression class representing the Uniform distribution
     * function.*/
    class UniformDistribution : public CompositeExpression {
    public:
      /** Construct a new UniformDistribution */
      UniformDistribution(Expression *newLower, Expression *newUpper) throw(HAPI::ExceptionHugin);

      /** Clone the expression. 
	  @return Pointer to Expression
      */
      virtual Expression * clone() throw(HAPI::ExceptionHugin);

      /** Return the operator of the expression */
      Operator getOperator() throw();
    };


    /** Expression class representing the Binomial distribution
     * function.*/
    class BinomialDistribution : public CompositeExpression {
    public:
      /** Construct a new GeometricDistribution */
      BinomialDistribution(Expression *newN, Expression *newP) throw(HAPI::ExceptionHugin);

      /** Clone the expression. 
	  @return Pointer to Expression
      */
      virtual Expression * clone() throw(HAPI::ExceptionHugin);

      /** Return the operator of the expression */
      Operator getOperator()  throw();
    };

    /** Expression class representing the Negative Binomial distribution
     * function.*/
    class NegativeBinomialDistribution : public CompositeExpression {
    public:
      /** Construct a new GeometricDistribution */
      NegativeBinomialDistribution(Expression *newN, Expression *newP) throw(HAPI::ExceptionHugin);

      /** Clone the expression. 
	  @return Pointer to Expression
      */
      virtual Expression * clone() throw(HAPI::ExceptionHugin);

      /** Return the operator of the expression */
      Operator getOperator()  throw();
    };





    /** Expression class representing the Poisson distribution
     * function.*/
    class PoissonDistribution : public CompositeExpression {
    public:
      /** Construct a new PoissonDistribution */
      PoissonDistribution(Expression *newLambda) throw(HAPI::ExceptionHugin);

      /** Clone the expression. 
	  @return Pointer to Expression
      */
      virtual Expression * clone() throw(HAPI::ExceptionHugin);

      /** Return the operator of the expression */
      Operator getOperator() throw();
    };


    /** Expression class representing the Geometric distribution
     * function.*/
    class GeometricDistribution : public CompositeExpression {
    public:
      /** Construct a new GeometricDistribution */
      GeometricDistribution(Expression *newP) throw(HAPI::ExceptionHugin);

      /** Clone the expression. 
	  @return Pointer to Expression
      */
      virtual Expression * clone() throw(HAPI::ExceptionHugin);

      /** Return the operator of the expression */
      Operator getOperator() throw();
    };


    /// Thic class represents the junction trees in the compiled domain.
    class JunctionTree {
      friend IJunctionTree;
      friend IUncompile;
    protected:
      JunctionTree() throw(HAPI::ExceptionHugin);
      JunctionTree(IJunctionTree *newIJT) throw(HAPI::ExceptionHugin);
      IJunctionTree * iJT;
      virtual ~JunctionTree() throw(HAPI::ExceptionHugin);
      void init(IJunctionTree *newIJT) throw(HAPI::ExceptionHugin);
    public:
      /** Return the Cliques in the junction tree.

      @return CliqueList
      */
      CliqueList getCliques() throw(HAPI::ExceptionHugin);

      /** Return the conflict measure of the data inserted in the junction tree.

      @return double
      */
      double getConflict() throw(HAPI::ExceptionHugin);

      /** Get the root clique of the junction tree.
	  @return Clique* - pointer to Clique object.
      */
      Clique * getRoot() throw(HAPI::ExceptionHugin);

      /** Does the junction tree contain evidence that has not been propagated?

      @return boolean
      */
      bool hasEvidenceToPropagate() throw(HAPI::ExceptionHugin);

      /** Does the junction tree contain updated tables that have not been propagated?

      @return boolean
      */
      bool hasTablesToPropagate() throw(HAPI::ExceptionHugin);

      /** Was CG evidence propagated through the junction tree?

      @return boolean
      */
      bool isCGEvidencePropagated() throw(HAPI::ExceptionHugin);

      /** Test the Equilibrium type. Can the equilibrium of the junction tree be obtained 
	  through a propagation using eq as the Equilibrium type?

	  @param eq Equilibrium
	  @return boolean
      */
      bool isEquilibrium(Equilibrium eq) throw(HAPI::ExceptionHugin);
    
      /** Test the EvidenceMode. Does the EvidenceMode match the EvidenceMode given as parameter?

      @param em EvidenceMode
      @return boolean
      */
      bool isEvidenceMode(EvidenceMode em) throw(HAPI::ExceptionHugin);

      /** Was evidence propagated through the junction tree?

      @return boolean
      */
      bool isEvidencePropagated() throw(HAPI::ExceptionHugin);

      /** Were likelihoods propagated through the junction tree?

      @return boolean
      */
      bool isLikelihoodPropagated() throw(HAPI::ExceptionHugin);

      /** Propagate evidence in the junction tree. 

      @param eq The type of Equilibrium to reach after the propagation.
      @param em The EvidenceMode used.
      */
      void propagate(Equilibrium eq = H_EQUILIBRIUM_SUM, EvidenceMode em = H_MODE_NORMAL) throw(HAPI::ExceptionHugin);
    };


    /** A Model is a compact description of a table. A model consists of
	a list of discrete nodes and a set of expressions (one expresion
	per configuration of states in the nodes.

	@see Expression
	@see Node
	@see NodeList
    */
    class Model 
      {    
	friend INode;
      protected:
	Model(IModel *newIModel) throw(HAPI::ExceptionHugin);
	IModel * iModel;
      public:
	/** Construct a model over a discrete chance node given a set of Nodes. */
	Model(DiscreteChanceNode *belongsToNode, const NodeList& modelNodes) throw(HAPI::ExceptionHugin);
	/** Construct a model over a utility node given a set of Nodes. */
	Model(UtilityNode *belongsToNode, const NodeList& modelNodes) throw(HAPI::ExceptionHugin);
	/** Delete the Model */
	virtual ~Model();
	/** Return the Expression associated with a pecific configuration of the Nodes in the Model */
	Expression * getExpression(int index) throw(HAPI::ExceptionHugin);
	/** Return a NodeList containing the Nodes in Model */
	NodeList getNodes() throw(HAPI::ExceptionHugin);
	/** Associate an Expression with a specific configuration of the Model Nodes */
	void setExpression(int index, Expression *newExpr) throw(HAPI::ExceptionHugin);
	/** Return the number of configuration of the Nodes of Model */
	int size() throw(HAPI::ExceptionHugin);

	/** Sets the number of values taken within each bounded
	    interval of an interval parent when generating the
	    conditional probability table for a node with interval
	    parents.

	    When generating the conditional probability table for a
	    node with interval nodes as parents, a number of values
	    are taken within each bounded interval of an interval
	    parent. By default, the interval is divided into 25
	    subintervals, and the midpoints of these subintervals are
	    then used in the computation of the value of the child.
	    @param count The number of subintervals
	*/
	void setNumberOfSamplesPerInterval( int count  ) throw(HAPI::ExceptionHugin) ;
	/** Returns the number of values per interval used when
            generating the conditional probability table for a node
            with interval parents.
	    @return int specifying the number of samples per interval
	*/
	int getNumberOfSamplesPerInterval( ) throw(HAPI::ExceptionHugin) ;

      };


    /** Nodes are one of the fundamental objects used in the
	construction of Bayesian belief networks and influence
	diagrams. All nodes need a Domain* as argument, that
	is, the domain must exist before nodes can be created
	into it.
    */
    class Node {
      friend ICGDistribution;
      friend IModel;
      friend INode;
      friend ITable;
      friend NodeExpression;
    protected:
      Node() throw(HAPI::ExceptionHugin);
      Node(INode *newINode) throw(HAPI::ExceptionHugin);
    public:
      /** Delete Node. The node is deleted from its domain. If the
	  domain was compiled, the corresponding compiled structure is
	  deleted. All references and pointers to the node become
	  invalid.
      */
      virtual ~Node();
		
      /** Add the DiscreteChanceNode parent as a new parent of this node. That is, add 
	  a directed link from parent to this.

	  @param parent DiscreteChanceNode*
      */
      void addParent(DiscreteChanceNode *parent) throw(HAPI::ExceptionHugin); 

      /** Return the value associated with key in the attribute list for this node.

      @return Standard C++ Library string containing the attribure value.
      */
      std::string getAttribute(std::string& key) const throw(HAPI::ExceptionHugin);

      /** Return the node category.

      @return Category
      */
      virtual Category getCategory() throw() { return H_CATEGORY_ERROR; }

      /** Return the Domain this Node belongs to. This Node must reside in an existing Hugin 
	  domain.

	  @return Domain* - A reference to the Domain where this Node resides.
      */
      Domain *getDomain() const  throw(HAPI::ExceptionHugin);	
    
      /** Return the JunctionTree to which this node belongs.

      @return Reference to JunctionTree object.
      */
      JunctionTree * getJunctionTree() const throw(HAPI::ExceptionHugin);

      /** Return the node kind.

      @return Kind
      */
      virtual Kind getKind() throw(ExceptionHugin) { return H_KIND_ERROR; }

      /** Get the label of this node.
	
      @return Standard C++ Library string.
      */
      std::string getLabel() const throw(HAPI::ExceptionHugin);

      /** Return the Model of this Node.

      @return Model
      */
      Model * getModel() throw(HAPI::ExceptionHugin);

      /** Retrieve the name of this Node. If this node has not previously been assigned a name, 
	  a valid name will automatically be assigned.

	  @return A Standard C++ Library string containing the name of this node.
      */
      std::string getName() const throw(HAPI::ExceptionHugin);
		
      /** Return a NodeList with references to the parents of this node. If no parents exist, 
	  an empty NodeList is returned.
		
	  @return NodeList
      */
      NodeList getParents() const throw(HAPI::ExceptionHugin);

      /** Return the position of the node.
	
      @return Standard C++ Library pair<long,long>
      */
      std::pair<long, long> getPosition() const throw(HAPI::ExceptionHugin);

      /** Return the value stored within the user data slot of this node. If the stored value 
	  is NULL, or if no value has been stored, NULL is returned. It is the responsibility 
	  of the application programmer to ensure that the data is valid, that pointers are 
	  accessed correctly, etc. Also note that when you delete a node, Hugin does not 
	  attempt to delete the data pointed to by the user data slot. It is the responsibility 
	  of the user.

	  @return void* Pointer stored within the Node object as a reference to user data 
	  associated with this node.
      */
      void *getUserData() throw(HAPI::ExceptionHugin);


      /** Retrieve the learning constraint specifyed for the edge.
       */
      Constraint getEdgeConstraint( Node *bNode ) ;
		
      /** Specify constraint for the edge.
       */
      void setEdgeConstraint( Node *bNode, Constraint C ) ;

      /** Generate the conditional probability table for this node,
	  as it is specified by the model (i.e., the expressions).
	  If one or more expressions are illegal in one way or
	  the other, an expression is thrown.
      */
      void generateTable() throw(HAPI::ExceptionHugin ) ;

      /** Returns a vector of attributes associated with this Node.
       */
      std::vector<Attribute*> Node::getAttributes() throw(HAPI::ExceptionHugin );

      /** Remove the directed link between parent and this node.
	  The table (if any) will be updated such that the updated table will be the portion 
	  of the old table that corresponds to parent being in its first state.

	  @param parent Reference to the parent node that will be removed.
      */
      void removeParent(DiscreteChanceNode *parent) throw(HAPI::ExceptionHugin);
                                                    
      /** Insert the key/value pair in the attribute list for this node. If key is already 
	  defined, the value is updated. If no value is provided, the attribute is removed.

	  @param key A Standard C++ Library string.
	  @param value A Standard C++ Library string.
      */
      void setAttribute(std::string& key, std::string& value) throw(HAPI::ExceptionHugin);

      /** Set the node label.

      @param label char*
      */
      void setLabel(char* label) throw(HAPI::ExceptionHugin);

      /** Set the node label.

      @param label std::string
      */
      void setLabel(std::string& label) throw(HAPI::ExceptionHugin);

      /** Create a copy of name and assign it to this node. name must be a valid name, i.e., 
	  it must follow the rules that govern the validity of C identifiers, and no other 
	  node in the domain to which <tt>*this</tt> node belongs can have the same name.

	  @param name A pointer to a zero-terminated string containing the desired name of 
	  the node.
      */
      void setName(char *name) throw(HAPI::ExceptionHugin);

      /** Create a copy of name and assign it to this node. name must be a valid name, i.e., 
	  it must follow the rules that govern the validity of C identifiers, and no other 
	  node in the domain to which <tt>*this</tt> node belongs can have the same name.

	  @param name Standard C++ Library string containing the desired name of the node.
      */
      void setName(std::string& name) throw(HAPI::ExceptionHugin);	
	
      /** Set the position of the node.

      @param x The desired x coordinate of the node.
      @param y The desired y coordinate of the node.
      */
      void setPosition(long x, long y) throw(HAPI::ExceptionHugin);

      /** Set the position of the node.

      @param pos Standard C++ Library pair of longs.
      */
      void setPosition(std::pair<long, long> pos) throw(HAPI::ExceptionHugin);

      /** The Hugin API provides a data slot within each Node object. This data slot is for 
	  use exclusively by the user/application. This slot can hold a pointer to arbitrary 
	  data, such as a file, a display window, an input buffer from hardware sensors, etc.
	  Please note that Hugin does not do anything to the user data. Data is not even 
	  copied. Only the pointer to the data is stored.

	  @param void* Pointer to user-defined data associated with this node.
      */
      void setUserData(void *) throw(HAPI::ExceptionHugin);

      // New from 6.0
      //      Domain* getHomeDomain() const throw (ExceptionHugin);

      /** Get the Domain in which this node is placed. This
	  function is equivalent to getDomain, and is only here
	  for consistency with getHomeClass.
       */
      Domain* getHomeDomain() const throw (ExceptionHugin);

      /** Get the class in which this node is placed. 
       */
      Class* getHomeClass() const throw (ExceptionHugin);

      // OO functions

      /** Add this Node to the list of input nodes in this
	  Class. I.e., make this Node an input node.
      */
      void addToInputs() throw(ExceptionHugin);
      /** Add this Node to the list of output nodes in this
	  Class. I.e., make this Node an output node.
      */
      void addToOutputs() throw(ExceptionHugin);
      /** Remove this Node from the list of input nodes in the
	  Class. I.e., make this Node an ordinary node again.
      */
      void removeFromInputs() throw(ExceptionHugin);
      /** Remove this Node from the list of output nodes in the
	  Class. I.e., make this Node an ordinary node again.
      */
      void removeFromOutputs() throw(ExceptionHugin);
      /** Returns the InstanceNode containing this (cloned) output
	  node. Note that we clone all output nodes when we create an
	  InstanceNode. This is done in order to make it possible to
	  specify conditional probability tables involving output
	  nodes from InstanceNode's.
	  @return The InstanceNode containing this output clone.
	  @see InstanceNode
      */
      Node* getInstance() throw(ExceptionHugin);
      /**
	 Returns the "master" of this (cloned) output Node of an
	 InstanceNode (i.e., the Node cloned to get this output
	 Node). Note that "master" belongs to another Class
	 object. Note also that we clone all output nodes when we
	 create an InstanceNode. This is done in order to make it
	 possible to specify conditional probability tables involving
	 output nodes from InstanceNode's.
	 
	 @return The "master" of this output clone.       */
      Node* getMaster() throw(ExceptionHugin);
      /** Returns a NodeList of Class nodes that identifies this
	  Domain node.<p>

	  The createDomain method of the Class class unfolds an
	  object-oriented (nested) specification of a Bayesian network
	  or an influence diagram into a regular Domain object.<p>
	  
	  Nodes in this Domain which originates from nodes residing in
	  nested sub-networks (via InstanceNodes) can be uniquely
	  related to a sequence of InstanceNodes and an ordinary Node
	  of the object-oriented network.<p>
	  
	  @return An ordered NodeList with the InstanceNodes and the
	  ordinary Node identifying the source of this Node that must
	  belong to a Domain.  */
      NodeList getSource() throw(ExceptionHugin);
    protected:
      INode * inode;
    };


    /// This class is the ancestor for all discrete nodes.
    class DiscreteChanceNode : public Node {
    public:
      friend INode;	
    protected:
      DiscreteChanceNode(INode *newINode) throw( HAPI::ExceptionHugin );
      DiscreteChanceNode() throw( HAPI::ExceptionHugin );
    public:
      virtual ~DiscreteChanceNode() {}

      /** Add parent as a new parent of this node. That is, add a directed link from parent
	  to this node.
		
	  @param parent DiscreteChanceNode* */
      void addParent(DiscreteChanceNode *parent) throw( HAPI::ExceptionHugin ) { Node::addParent(parent); }

      /** Add parent as a new parent of this node. That is, add a directed link from parent
	  to this node.
		
	  @param parent DiscreteDecisionNode*
      */
      void addParent(DiscreteDecisionNode *parent) throw( HAPI::ExceptionHugin );

      /** Test whether the value of this node in case index currently is set.

      @param index Case index.
      @return boolean.
      */
      bool caseIsSet(long index) throw (HAPI::ExceptionHugin);

      /** This method specifies a finding value for the specified state and
       * all
       other states are not effected.
       <P>
       *
       * @param <b>state</b> An integer designating which state to be
       * selected. States are numbered consecutively from 0 and upwards.
       *
       * @param <b>value</b> A non-negative real number as the finding value.
       */
      void enterFinding(int state, double value) throw( ExceptionHugin );  
		
      /** The belief for the specified state in this node is returned. Note that if findings 
	  have been entered since the most recent propagation, the beliefs returned may not be 
	  up-to-date.

	  @param state An interger value designating which state to examine.
      */
      double getBelief(int state) throw( ExceptionHugin );

      /** Retrieve the state value of this node associated with the case index.
       */
      int getCaseState(long index) throw (HAPI::ExceptionHugin);

      /** Return the node category.
	  @return Category
      */
      virtual Category getCategory()  throw() { return H_CATEGORY_CHANCE; }

      /** Return a NodeList containing pointers to the children of this node. If no children 
	  exist, an empty NodeList is returned.

	  @return NodeList
      */
      NodeList getChildren() const throw( HAPI::ExceptionHugin );

      /** Retrieve the finding currently registrered at this node for state.

      @param state An integer designating the state to be examined.
      @return A double-precision real number expressing the entered finding.
      */
      double getEnteredFinding(int state) const throw( ExceptionHugin );
	
      /** Return the experience table.
       */
      Table *getExperienceTable() throw (HAPI::ExceptionHugin);

      /** Return the fading table.
       */
      Table *getFadingTable() throw (HAPI::ExceptionHugin);

      /** Return the node kind.
	  @return Kind
      */
      virtual Kind getKind() throw(HAPI::ExceptionHugin) { return H_KIND_DISCRETE; }

      /** Return the number of states in this node. The states are numbered from 0 to N-1.
     
      @return int
      */
      int getNumberOfStates() const throw(ExceptionHugin);

      /** Retrieve the propagated finding. That is, retrieve the finding value incorporated 
	  within the current junction tree potentials for the specified state of this node.

	  @param state An integer designating the state to be examined.
	  @return A double-precision real number expressing the propagated finding.
      */
      double getPropagatedFinding(int state) const throw( ExceptionHugin );

      /** Return the state index generated by the latest call to Domain::simulate().
	  @return int
      */
      int getSelection() const throw (ExceptionHugin);
	
      /** Return the label of state. 0 < state < N, where N is the number of states in the node.
    
      @return Standard C++ Library string.
      */
      std::string getStateLabel(int state) const throw(HAPI::ExceptionHugin);

      /** Return the table associated with this node. The table is the conditional probability 
	  table for this node given its parents. The set of nodes associated with the table 
	  will be the (discrete) parents of this in unspecified order followed by this node.
    
	  @return Table*
      */
      virtual Table * getTable() throw(HAPI::ExceptionHugin);

      /** Check whether node has experience table.
       */
      bool hasExperienceTable() throw (HAPI::ExceptionHugin);

      /** Check whether node has fading table.
       */
      bool hasFadingTable() throw (HAPI::ExceptionHugin);

      /** Return whether or not evidence is entered into this node.

      @return Boolean.
      */
      bool isEvidenceEntered();

      /** Return whether or not evidence has been propagated from this node.

      @return Boolean.
      */
      bool isEvidencePropagated();

      /** Remove the directed link between parent and this node. The table (if any) will be 
	  updated such that the updated table will be the portion of the old table that 
	  corresponds to parent being in its first state.

	  @param parent Pointer to the parent DiscreteChanceNode that will be removed.
      */
      void removeParent(DiscreteChanceNode *parent) throw( HAPI::ExceptionHugin ) { Node::removeParent(parent); } 
		
      /** Remove the directed link between parent and this node. The table (if any) will be 
	  updated such that the updated table will be the portion of the old table that 
	  corresponds to parent being in its first state.

	  @param parent Pointer to the parent DiscreteDecisionNode that will be removed.
      */
      void removeParent(DiscreteDecisionNode *parent) throw( HAPI::ExceptionHugin ); 

      /** Retract all findings for this node. This is equivalent to setting the finding value 
	  to 1 for all states of this node.
      */
      void retractFindings() throw( ExceptionHugin );            
		
      /** Reverse the edge between this node and the specified neighbor.

      @param neighbor DiscreteChanceNode*
      */
      void reverseEdge(DiscreteChanceNode *neighbor) throw (ExceptionHugin);

      /** Select the specified state of this node. This is equivalent to specifying the finding 
	  value 1 for the specified state and 0 for all other states.

	  @param state An integer designating which state to be selected. States are numbered 
	  consecutively from 0 and upwards.
      */
      void selectState(int state) throw( ExceptionHugin );     
	
      /** Specify the case state of this node associated with case index to be state.

      @param index The case index.
      @param state The node state.
      */
      void setCaseState(long index, int state) throw (HAPI::ExceptionHugin);

      /** Set the state label of the node.

      @param state int - The state number.
      @param statelabel - The desired state label.
      */
      void setStateLabel(int state, char *statelabel) throw(HAPI::ExceptionHugin);

      /** Set the state label of the node.

      @param state int - The state number.
      @param statelabel - The desired state label.
      */
      void setStateLabel(int state, std::string& statelabel) throw(HAPI::ExceptionHugin);

      /** Specify that the value of this node for case index is unknown.

      @param index long.
      */
      void unsetCase(long index);

      /** Returns the state sampled for this
       */
      int getSampledState( ) throw (HAPI::ExceptionHugin) ;


    };


    /// Labelled discrete chance node. This is the node normally used.
    class LabelledDCNode : public DiscreteChanceNode {
      friend INode;
    protected:
      LabelledDCNode(INode *newINode) throw(HAPI::ExceptionHugin);
    public:
      LabelledDCNode(Domain *dom) throw(HAPI::ExceptionHugin);
      LabelledDCNode(Class* cls) throw(HAPI::ExceptionHugin);
      /** Set the number of states in this node to states. The corresponding domain will be 
	  uncompiled.

	  @param states int
      */
      void setNumberOfStates(int states) throw(HAPI::ExceptionHugin);
    };


    /// Numbered discrete chance node. To every state is associated a number.
    class NumberedDCNode : public DiscreteChanceNode {
      friend INode;
    public:
      NumberedDCNode(Domain *dom) throw(HAPI::ExceptionHugin);
      NumberedDCNode(Class* cls) throw(HAPI::ExceptionHugin);

      /** Return the value associated with state.

      @param state int
      */
      double getStateValue(int state) throw(HAPI::ExceptionHugin);

      /** Set the number of states in this node to states. The corresponding domain will be 
	  uncompiled.

	  @param states int
      */
      void setNumberOfStates(int states) throw(HAPI::ExceptionHugin);

      /** Set the value associated with state.

      @param state int
      @param value double
      */
      void setStateValue(int state, double value) throw(HAPI::ExceptionHugin);		
		
    protected:
      NumberedDCNode(INode *newINode) throw(HAPI::ExceptionHugin);
    };


    /// Boolean discrete chance node. Contains two states, true and false.
    class BooleanDCNode : public DiscreteChanceNode {
      friend INode;
    public:
      BooleanDCNode(Domain *dom)  throw(HAPI::ExceptionHugin);
      BooleanDCNode(Class *cls)  throw(HAPI::ExceptionHugin);
    protected:
      BooleanDCNode(INode *newINode) throw(HAPI::ExceptionHugin);
    };


    /// Interval discrete chance node. Each state represents an interval. 
    class IntervalDCNode : public DiscreteChanceNode {
      friend INode;
    protected:
      IntervalDCNode(INode *newINode) throw(HAPI::ExceptionHugin);
    public:
      IntervalDCNode(Domain *dom) throw(HAPI::ExceptionHugin);
      IntervalDCNode(Class *cls) throw(HAPI::ExceptionHugin);

      /** Return the value associated with the specified state.

      @param state int
      */
      double getStateValue(int state) throw(HAPI::ExceptionHugin);

      /** Set the number of states in this node to states. The corresponding domain will be 
	  uncompiled.

	  @param states int
      */
      void setNumberOfStates(int states) throw(HAPI::ExceptionHugin);

      /** Associate a value with the specified state.

      @param state int
      */
      void setStateValue(int state, double value) throw(HAPI::ExceptionHugin);		
    };

    /** The Continuous chance node. This node epresents continuous
        chance nodes with (conditional) Gaussian
        distributions. Continuous chance nodes are also sometimes
        called CG nodes (CG for conditional Gaussian). */
    class ContinuousChanceNode : public Node {
      friend INode;
    protected:
      ContinuousChanceNode(INode *newINode) throw(ExceptionHugin);
    public:
      ContinuousChanceNode(Domain *dom) throw( ExceptionHugin );
      ContinuousChanceNode(Class *dom) throw( ExceptionHugin );
      virtual ~ContinuousChanceNode();

      /** Add parent as a new parent of this node. That is, add a directed link from parent
	  to this node.

	  @param parent ContinuousChanceNode*
      */
      void addParent(ContinuousChanceNode *parent) throw( HAPI::ExceptionHugin );  		
  		
      /** Specify that this continuous node has the value value.

      @param value A real number as the finding value.
      */
      void enterValue(double value) throw( ExceptionHugin ); 
		 
      /** Retrieve the value of this node assoociated with case index.

      @param index Case index.
      */
      double getCaseValue(long index) throw (HAPI::ExceptionHugin);

      /** Return the node category.
       */
      virtual Category getCategory() throw() { return H_CATEGORY_CHANCE; }

      /** Get the CG distribution associated with this node.

      @return CGDistribution*
      */
      CGDistribution *getCGDistribution() throw(ExceptionHugin);

      /** Return a NodeList containing references to the children of this node. If no children 
	  exist, an empty NodeList is returned.

	  @return NodeList
      */
      NodeList getChildren() const throw( HAPI::ExceptionHugin );
		
      /** Compute the distribution for this continuous node. The distribution for a CG node 
	  is in general a mixture of several Gaussian distributions. 
	  ContinuousChanceNode::getDistribution() really computes a joint distribution of this
	  node and a set of discrete nodes. These discrete nodes are chosen such that the 
	  computed marginal is a strong marginal, but it is not necessarily minimal.

	  @return Table* - Pointer to a Table holding a strong marginal of this node and a set of 
	  discrete nodes.
      */
      Table * getDistribution() const throw( ExceptionHugin );	

      /** Retrieve the entered value for this node.

      @return A double-precision real number expressing the entered value.
      */
      double getEnteredValue() throw( ExceptionHugin );
		
      /** Return the node kind.
	  @return Kind
      */
      virtual Kind getKind() throw() { return H_KIND_CONTINUOUS; }

      /** Return the mean of the marginal distribution of this node.

      @return A double-precision real number expressing the mean.
      */
      double getMean() const throw( ExceptionHugin );	

      /** Retrieve the finding value. That is, retrieve the finding value incorporated within 
	  the current junction tree potentials for state of this node.

	  @return A double-precision real number expressing the propagated value.
      */
      double getPropagatedValue() const throw( ExceptionHugin );

      /** Return the variance of the marginal distribution of this node.

      @return A double-precision real number expressing the variance.
      */
      double getVariance() const throw( ExceptionHugin );	
	
      /** Return whether or not evidence is entered into this node.

      @return Boolean.
      */
      bool isEvidenceEntered();

      /** Return whether or not evidence has been propagated from this node.

      @return Boolean.
      */
      bool isEvidencePropagated();

      /** Remove the directed link between parent and this node. The table (if any) will be 
	  updated such that the Beta(i)-parameters will be deleted from the table.

	  @param parent Reference to the ContinuousChanceNode that will be removed as parent.
      */
      void removeParent(ContinuousChanceNode *parent) throw( HAPI::ExceptionHugin );
		
      /** Remove the directed link between parent and this node. The table (if any) will be 
	  updated such that the Beta(i)-parameters will be deleted from the table.

	  @param parent Reference to the DiscreteChanceNode that will be removed as parent.
      */
      void removeParent(DiscreteChanceNode *parent) throw( HAPI::ExceptionHugin ) { Node::removeParent(parent); } 

		
      /** Retract the entered value for this node.
       */
      void retractValue() throw( ExceptionHugin );      
		
      /** Reverse the edge between this node and the specified neighbor.

      @param neighbor ContinuousChanceNode*
      */
      void reverseEdge(ContinuousChanceNode *neighbor) throw (ExceptionHugin);

      /** Set the value associate with this node in case index to value.
       */
      void setCaseValue(long index, double value) throw (HAPI::ExceptionHugin);

      /** Specify that the value of this node for case index is unknown.

      @param index long.
      */
      void unsetCase(long index);  

      /**  Returns  the value  of  this  ContinuousChanceNode for  the
	  configuration   generated  by  the   most  recent   call  to
	  Domain.simulate().

	  @return A double - the value sampled for this during the
	  last invocation of simulate() on the Domain of this.
	  @see Domain::simulate
      */
      double getSampledValue();	

    } ; 

  
    /// The discrete decision node. Base class for all decision nodes.
    class DiscreteDecisionNode : public Node {
      friend INode;	
    protected:
      DiscreteDecisionNode(INode *newINode) throw(HAPI::ExceptionHugin);
      DiscreteDecisionNode() throw(HAPI::ExceptionHugin);
    public:
      virtual ~DiscreteDecisionNode() {}

      /** Add parent as a new parent of this node. That is, add a directed link from parent
	  to this node.

	  @param parent DiscreteChanceNode*
      */
      void addParent(DiscreteChanceNode *parent) throw( HAPI::ExceptionHugin ) { Node::addParent(parent); }

      /** Add parent as a new parent of this node. That is, add a directed link from parent
	  to this node.

	  @param parent DiscreteDecisionNode*
      */
      void addParent(DiscreteDecisionNode *parent) throw( HAPI::ExceptionHugin );

      /** This method specifies a finding value for the specified state and
       * all
       other states are not effected.
       <P>
       *
       * @param <b>state</b> An integer designating which state to be
       * selected. States are numbered consecutively from 0 and upwards.
       *
       * @param <b>value</b> A non-negative real number as the finding value.
       */
      void enterFinding(int state, double value) throw( ExceptionHugin );

      /** Retrieve the state value of this node associated with the case index.
       */
      int getCaseState(long index) throw (HAPI::ExceptionHugin);

      /** Return the node category.
       */
      virtual Category getCategory()  throw() { return H_CATEGORY_DECISION; }

      /** Return a NodeList containing references to the children of this node. If no children 
	  exist, an empty NodeList is returned.

	  @return NodeList
      */
      NodeList getChildren() const throw( HAPI::ExceptionHugin );
    
      /** Retrieve the finding currently registrered  at this node for the specified state.

      @param state An integer designating the state to be examined.
      @return A double-precision real number expressing the entered finding.
      */
      double getEnteredFinding(int state) const throw( ExceptionHugin );
    
      /** Return the expected utility associated with the specified action (state).

      @param state An interger value designating which state to examine.
      @return A double-precision floating-point value expressing the expected utility associated with state.
      */
      double getExpectedUtility(int state) const throw( ExceptionHugin );
    
      /** Return the node kind.
       */
      virtual Kind getKind() throw() { return H_KIND_DISCRETE; }

      /** Return the number of states in this node. The states are numbered from 0 to N-1.
     
      @return int
      */
      int getNumberOfStates() const throw();
		
      /** Retrieve the finding value incorporated. This value is incorporated within the 
	  current junction tree potentials for state of this node.

	  @param state An integer designating the state to be examined.
	  @return A double-precision real number expressing the propagated finding.
      */
      double getPropagatedFinding(int state) const throw( ExceptionHugin );
	
      /** Return the label of state. 0 < state < N, where N is the number of states in the node.
    
      @return Standard C++ Library string.
      */
      std::string getStateLabel(int state) const throw();

      /** Return whether or not evidence is entered into this node.

      @return Boolean.
      */
      bool isEvidenceEntered();

      /** Return whether or not evidence has been propagated from this node.

      @return Boolean.
      */
      bool isEvidencePropagated();

      /** Remove the directed link between parent and this node. The table (if any) will be 
	  updated such that the updated table will be the portion of the old table that 
	  corresponds to parent being in its first state.

	  @param parent Pointer to the DiscreteChanceNode that will be removed as parent.
      */
      void removeParent(DiscreteChanceNode *parent) throw( HAPI::ExceptionHugin ) { Node::removeParent(parent); } 

      /** Remove the directed link between parent and this node. The table (if any) will be 
	  updated such that the updated table will be the portion of the old table that 
	  corresponds to parent being in its first state.

	  @param parent Pointer to the DiscreteDecisionNode that will be removed as parent.
      */
      void removeParent(DiscreteDecisionNode *parent) throw( HAPI::ExceptionHugin );

      /** Retract all findings for this node. This is equivalent to setting the finding value 
	  to 1 for all states of this node.
      */
      void retractFindings() throw( ExceptionHugin ); 
    
      /** Select the specified state of this node. This is equivalent to specifying the finding 
	  value 1 for state and 0 for all other states.

	  @param state An integer designating which state to be selected. States are numbered 
	  consecutively from 0 and upwards.
      */
      void selectState(int state) throw( ExceptionHugin );

      /** Specify the case state of this node associated with case index to be state.

      @param index The case index.
      @param state The node state.
      */
      void setCaseState(long index, int state) throw (HAPI::ExceptionHugin);

      /** Set the state label of the node.

      @param state int - The state number.
      @param statelabel - The desired state label.
      */
      void setStateLabel(int state, std::string& statelabel) throw(HAPI::ExceptionHugin);

      /** Set the state label of the node.

      @param state int - The state number.
      @param statelabel - The desired state label.
      */
      void setStateLabel(int state, char *statelabel) throw(HAPI::ExceptionHugin);

      /** Specify that the value of this node for case index is unknown.

      @param index long.
      */
      void unsetCase(long index);



    };

    /** Labelled discrete decision node. This is the kind of DiscreteDecisionNode most oftenly used.
     */
    class LabelledDDNode : public DiscreteDecisionNode {
      friend INode;
    public:
      LabelledDDNode(Domain *dom) throw(HAPI::ExceptionHugin);

      /** Set the number of states in this node. The corresponding domain will be uncompiled.

      @param states int
      */
      void setNumberOfStates(int states) throw(HAPI::ExceptionHugin);
    protected:
      LabelledDDNode(INode *newINode) throw(HAPI::ExceptionHugin);
    };

    /** Numbered discrete decision node. Each state of an NumberedDDNode represents a number. */
    class NumberedDDNode : public DiscreteDecisionNode {
      friend INode;
    public:
      NumberedDDNode(Domain *dom) throw(HAPI::ExceptionHugin);
      /** Return the value associated with state.

      @param state int
      */
      double getStateValue(int state) throw(HAPI::ExceptionHugin);

      /** Set the number of states in this node. The corresponding domain will be uncompiled.
		
      @param states int
      */
      void setNumberOfStates(int states) throw(HAPI::ExceptionHugin);

      /** Set the value associated with state.

      @param state int
      @param value double
      */
      void setStateValue(int state, double value) throw(HAPI::ExceptionHugin);		
    protected:
      NumberedDDNode(INode *newINode) throw(HAPI::ExceptionHugin);
    };

    /** Boolean discrete decision node. A BooleanDDNode has states false and true.
     */
    class BooleanDDNode : public DiscreteDecisionNode {
      friend INode;	
    public:
      BooleanDDNode(Domain *dom) throw(ExceptionHugin);
    protected:
      BooleanDDNode(INode *newINode) throw(ExceptionHugin);
    };


    /**  Interval discrete decision node. Each state of an IntervalDDNode represents an interval. */
    class IntervalDDNode : public DiscreteDecisionNode {
      friend INode;
    public:
      IntervalDDNode(Domain *dom) throw(HAPI::ExceptionHugin);
      /** Return the value associated with state.

      @param state int
      */
      double getStateValue(int state) throw(HAPI::ExceptionHugin);

      /** Set the number of states in this node. The corresponding domain will be uncompiled.

      @param states int
      */
      void setNumberOfStates(int states) throw(HAPI::ExceptionHugin);

      /** Set the value associated with state.

      @param state int
      @param value double
      */
      void setStateValue(int state, double value) throw(HAPI::ExceptionHugin);		
    protected:
      IntervalDDNode(INode *newINode);
    };

    /** A UtilityNode represents a utility function. The utility
	function can depend on discrete chance and decision Nodes.

	UtilityNodes are used in influence diagrams to represent
	utilities associated with decision options. */
    class UtilityNode : public Node {
      friend INode;
    public:
      UtilityNode(Domain *dom) throw(HAPI::ExceptionHugin);
      /** Add parent as a new parent of this node. That is, add a directed link from parent
	  to this node.

	  @param parent DiscreteChanceNode*
      */
      void addParent(DiscreteChanceNode *parent) throw( HAPI::ExceptionHugin ) { Node::addParent(parent); }

      /** Add parent as a new parent of this node. That is, add a directed link from parent
	  to this node.

	  @param parent DiscreteDecisionNode*
      */
      void addParent(DiscreteDecisionNode *parent) throw( HAPI::ExceptionHugin );

      /** Return the table associated with this node. The table contains a utility value for 
	  every configuration of the parents of this node. The set of nodes associated with 
	  the table will be the (discrete) parents of this node in unspecified order.

	  @return Pointer to Table containing utility values.
      */
      Table * getTable() throw(HAPI::ExceptionHugin);

      /** Remove the directed link between parent and this node. The table (if any) will be 
	  updated such that the updated table will be the portion of the old table that 
	  corresponds to parent being in its first state.

	  @param param pointer to the DiscreteChanceNode that will be removed as parent.
      */
      void removeParent(DiscreteChanceNode *parent) throw( HAPI::ExceptionHugin ) { Node::removeParent(parent); } 

      /** Remove the directed link between parent and this node. The table (if any) will be 
	  updated such that the updated table will be the portion of the old table that 
	  corresponds to parent being in its first state.

	  @param param pointer to the DiscreteDecisionNode that will be removed as parent.
      */
      void removeParent(DiscreteDecisionNode *parent) throw( HAPI::ExceptionHugin );

    protected:
      UtilityNode(INode *newINode) throw(HAPI::ExceptionHugin);
    };


    /** InstanceNodes are the key building block of object-oriented
	Bayesian networks and influence diagrams.

	An InstanceNode represents an instance of a Class (i.e., a
	Bayesian network or an influence diagram). In other words, an
	instance node represents a subnetwork. The Class of which
	InstanceNodes exist in other Classes can itself contain
	InstanceNodes, whereby an object-oriented network can be
	viewed as a hierarchical description of a problem
	domain. Describing a network in a hierarchical fashion often
	makes the network much less cluttered, and thus provides a
	much better means of communicating ideas among knowledge
	engineers and users.

	As systems often are composed of collections of identical or
	similar components, models of systems often contain repetitive
	patterns. The notion of InstanceNodes makes it very easy to
	construct multiple identical instances of a network fragment.

	An InstanceNode is connected to other nodes via its <it>interface
	nodes</it>, which are the input Nodes and the output Nodes of the
	Class of which the InstanceNode is an instance. Chance nodes
	and decision nodes of the encapsulating Class (i.e., network)
	as well as output nodes of InstanceNodes of the encapsulating
	Class can be bound to input nodes of an InstanceNode.

	As the output nodes of an InstanceNode can be parents of
	non-InstanceNodes, these output nodes are represented in the
	"home Class" of the InstanceNode as clones of the output nodes
	of the "instance Class" of the InstanceNode. Therefore, the
	output nodes of InstanceNodes are sometimes referred to as
	"output clones".

    */
    class InstanceNode : public Node {
    
    public:
      InstanceNode(Class* master, Class* insertIn) throw (ExceptionHugin);
    
      /** Get the class, from which this instance was derived */
      Class* getClass() throw (ExceptionHugin);

      /** Bind an existing node to an input node in an instance.
	  @param input The input node in the instance which is to be bound.
	  @param node The node which is bound to the input node.
      */
      void setInput(Node* input, Node* node) throw (ExceptionHugin);

      /** Removes a binding to the input node given.
	  @param input The input node in the instance, which must be unbound
      */
      void unsetInput(Node* input) throw (ExceptionHugin);

      /** Returns the node, which is bound to the given input
	  @param input The input node in the instance, whose bound node is returned.
      */
      Node* getInput(Node* input) throw (ExceptionHugin);

      /** Returns the output clone from the instance for the given output node
	  frin the class.
	  @param output An output node from a class, whose output clone, from an
	  instance, is returned.
      */
      Node* getOutput(Node* output) throw (ExceptionHugin);
    };


    /** Hugin uses Tables for representing the conditional probability
	and utility potentials of individual Nodes, the probability
	and utility potentials on separators and Cliques of
	JunctionTrees, evidence potentials, etc.

	A potential is a function from the state space of a set of
	variables into the set of real numbers. A Table is a
	representation of a potential. */
    class Table {
      friend IDomain;
      friend INode;

    public: 
	

    protected:
      Table(ITable *newITable) throw(HAPI::ExceptionHugin);
    public:
      /** Release the memory resources used by the application-owned Table object.
       */
      virtual ~Table();

      /** Return the covariance of the conditional distribution. The covariance of the 
	  conditional distribution of the continuous nodes node1 and node2 given the discrete 
	  state configuration config.

	  @param config int - Index of the discrete configuration.
	  @param node1 ContinuousChanceNode*
	  @param node2 ContinuousChanceNode*

	  @return A double-precision real value.
      */
      double getCovariance(int config, ContinuousChanceNode *node1, ContinuousChanceNode *node2) throw(HAPI::ExceptionHugin);

      /** Retrieve a vector holding the actual discrete data. This vector is a one-dimensional 
	  (row-major) representation of the multi-dimensional array.

	  @return A Standard C++ Library vector of doubles.
      */
      std::vector<double> getData() const throw(HAPI::ExceptionHugin);

      /** Return the mean value of the conditional probability distribution. The mean value of 
	  the conditional probability distribution of the continuous chance node node given the 
	  discrete state configuration config is returned.

	  @param config int - Index of the discrete configuration.
	  @param node ContinuousChanceNode*

	  @return A double-precision real value.
      */
      double getMean(int config, ContinuousChanceNode *node) throw(HAPI::ExceptionHugin);

      //     /** Retrieve a NodeList containing pointers to the nodes associated with this table.

      // 		@return A Standard C++ Library vector of pointers to Nodes.
      // 	*/
      NodeList getNodes() const throw(HAPI::ExceptionHugin);

      /** Return the size of this table.

      @return int
      */
      int getSize() const throw(HAPI::ExceptionHugin);

      /** Return the variance of the conditional probability distribution. The variance of the 
	  conditional probability of the continuous node node given the discrete state 
	  configuration config.

	  @param config int - Index of the discrete configuration.
	  @param node ContinuousChanceNode*

	  @return A double-precision real value.
      */
      double getVariance(int config, ContinuousChanceNode *node) throw(HAPI::ExceptionHugin);

      /** Reorder the node list of this table to follow the order of the members in the NodeList.
	  order must be a permutation of the node list of this table.

	  @param order NodeList
      */
      void reorderNodes(const NodeList& order) throw(HAPI::ExceptionHugin);

      /** Set the table data to be a copy of the parameter.

      @param data vector<double>
      */
      void setData(const std::vector<double>& data) throw(HAPI::ExceptionHugin);

    protected:
      ITable * iTable;
    };

	
    /** The CGDistribution encapsulates all information regarding the 
	distribution of a ContinuousChanceNode.
	@see ContinuousChanceNode
    */
    class CGDistribution {
      friend ContinuousChanceNode;
      friend INode;
    protected:
      CGDistribution(ContinuousChanceNode *nd) throw( ExceptionHugin );
      virtual ~CGDistribution() throw( ExceptionHugin );
    public:
      /** Return the alpha component of the CG distribution.

      @param config int - the index of the discrete configuration
      @return double
      */
      double getAlpha(int config) throw( ExceptionHugin );

      /** Return the beta component of the CG distribution. The distribution is given the 
	  discrete configuration and the continuous parent.

	  @param parent ContinuousChanceNode*
	  @param config int - the index of the discrete configuration
	  @return double
      */
      double getBeta(ContinuousChanceNode *parent, int config) throw( ExceptionHugin );

      /** Return the gamma component of the CG distribution.

      @param config int - the index of the discrete configuration
      @return double
      */
      double getGamma(int config) throw( ExceptionHugin );

      /** Return the ContinuousChanceNode on which the CGDistribution is define.
	  @return ContinuousChanceNode*
      */
      ContinuousChanceNode * getNode() throw(ExceptionHugin);

      /** Set the alpha component of the CG distribution given a discrete configuration.

      @param config int - the index of the discrete configuration
      @return double
      */
      void setAlpha(int config, double alpha) throw( ExceptionHugin );
    
      /** Set the beta component of the CG distribution. The distribution is given a discrete 
	  configuration and the continuous parent.

	  @param oarent
	  @param config int - the index of the discrete configuration
	  @return double
      */
      void setBeta(ContinuousChanceNode *parent, int config, double beta) throw( ExceptionHugin );
    
      /** Set the gamma component of the CG distribution given a discrete configuration.

      @param config int - the index of the discrete configuration
      @return double
      */
      void setGamma(int config, double gamma) throw( ExceptionHugin );
    protected:
      ICGDistribution * iCGDist;
    };



    /*
	The parse listener used when parsing strings representing
	Expressions should be created by implementing the
	ExpressionParseListener subclass.

    */

    /** The ParseListener class is a virtual class, which
	provides an interface for the other parse listeners to
	use.

	The parse listener used when one wants to call the Domain
	constructor should be created by implementing the
	NetParseListener subclass.

	The parse listener used when calling the parseClasses method
	of the ClassCollection class should be created by implementing
	the ClassParseListener subclass.

	For backwards compatibility, however, implementations of the
	ParseListener class can be used when calling the Domain
	constructor.
    */

    class ParseListener {
    public:
      ParseListener() {}
      virtual ~ParseListener() {}

      /** Error handler for parse errors. The parseError method must
	  be provided by the user in a specialized class derived from
	  class ParseError.  The error handling itself is determined
	  by the user.

	  @param line int - The line number determining where in the
	  NET file the parse error was encountered 
	  @param mesg string
	  - The message to be issued when encountering the parse
	  error.  */
      virtual void parseError(int line, const std::string& msg) = 0;
    };


    /** The ClassParseListener interface is used when one wants to call the
	parseClasses(String, ParseListener) method of the
	ClassCollection class.

	You must implement your own subclass of ParseListener with
	your own parseError and insertClass methods.

	As an alternative to implementing the ParseListener yourself,
	you may wish to use the DefaultParseListener class.  
	@see Domain::Domain(String, ParseListener)
	@see ClassCollection::parseClasses(String, ParseListener)
	@see DefaultParseListener
    */
    class ClassParseListener : public ParseListener{
    public:
      ClassParseListener() {}
      virtual ~ClassParseListener() {}

      /* Error handler for parse errors. The parseError method must
	  be provided by the user in a specialized class derived from
	  class ParseError.  The error handling itself is determined
	  by the user.

	  @param line int - The line number determining where in the
	  NET file the parse error was encountered 
	  @param mesg string
	  - The message to be issued when encountering the parse
	  error.  */
      //      virtual void parseError(int line, const std::string& msg) = 0;

      /**
	 Whenever the Hugin net parser encounters a class not defined in
	 the NET file, the parser calls the insertClass method of the
	 ParseListener object provided as an argument to the
	 parseClasses(String, ParseListener) method. An implementation 
	 of the insertClass method is required.

	 @param ClassCollection A pointer to the ClassCollection object, 
	 in which the parsed classes must be inserted.
	 @param name The name of the Class which needs to be located and
	 inserted.
      **/
      virtual void insertClass(ClassCollection* cc, std::string name) = 0;
    };

    /** Provides a simple implementation of the ParseListener
	class. It is assumed that that the NET file for a Class for
	which an instance is required can be found in the directory
	from which the application program is started.
    */
    class DefaultParseListener : public ClassParseListener{
    public:
      DefaultParseListener();
      /** This implementation of the parseError method simply prints
          the line number and parse error message to stderr */
      void parseError(int line, const std::string& msg);
      /** This implementation of the insertClass method simply calls
          the parseClasses(String, ParseListener) method with
          arguments className + ".net" and 'this'. Note that this
          simple implementation requires that the application program
          is started in the directory where the relevant NET files are
          stored.*/
      void insertClass(ClassCollection* cc, std::string name);
      ~DefaultParseListener();
    };

    /** The NetParseListener class is used while parsing a Hugin NET file.
	The class is a pure (abstract) class, which must be derived into a user-defined class
	containing the handler to be called in case the parser returns a parse error.
    */
    class NetParseListener : public ParseListener{
    public:
      NetParseListener() {}
      virtual ~NetParseListener() {}
	
      /* Error handler for parse errors. The parseError method must
	  be provided by the user in a specialized class derived from
	  this class.  The error handling itself is determined
	  by the user.
	    
	  @param line int - The line number in 
	  which the error was encounterd
	  @param mesg string - The message to be issued when
	  encountering the parse error.  */
      //virtual void parseError(int line, const std::string& msg) = 0;
    };

    class CaseParseListener : public ParseListener{
    public:
      CaseParseListener() {}
      virtual ~CaseParseListener() {}
    };

    /* The ExpressionParseListener class is used while constructing
	Expressions from strings.
.
	The class is a pure (abstract) class, which must be derived into a user-defined class
	containing the handler to be called in case the parser returns a parse error.
    */
    //    class ExpressionParseListener : public ParseListener{
/*     public: */
/*       ExpressionParseListener() {} */
/*       virtual ~ExpressionParseListener() {} */
	
      /* Error handler for parse errors. The parseError method must
	  be provided by the user in a specialized class derived from
	  this class.  The error handling itself is determined
	  by the user.
	    
	  @param index int - The index number of the expression in 
	  which the error was encounterd
	  @param mesg string - The message to be issued when
	  encountering the parse error.  */
      //virtual void parseError(int index, const std::string& msg) = 0;
    //    };

    /** Attributes can be used to associate arbitrary data with a node
        or a NetworkModel (i.e., a Class or a Domain). Attributes are
        set using the setAttribute method on the NetworkModel and Node
        classes. Each data object must be a string and attributes are
        read-only objects. Thus, in order to change the value of a
        data object or to add a new data object, the setAttribute
        method must be used. An attribute associated with a
        NetworkModel or a Node is removed by setting the value to null
        using setAttribute. */
    class Attribute {
      friend IAttribute;
      friend INode;
      friend IDomain;
    protected:
      Attribute() ;
	  
      IAttribute * iAttribute ;
    public:
      Attribute( IAttribute *attrib ) ;
      virtual ~Attribute() ;
      
      /** Returns the key associated with this Attribute.
       @return A string containing the key*/
      std::string getKey() ;
      /** Returns the value associated with this Attribute.
       @return A string containing the value*/
      std::string getValue() ;
    };


  };


#endif

