Author Topic: How to sum two numbered nodes?  (Read 24929 times)

Offline rosthoej

  • Newbie
  • *
  • Posts: 4
    • View Profile
How to sum two numbered nodes?
« on: April 16, 2008, 17:28:37 »
Suppose you consider two numberedDCNodes, node1 and node2, with 3 and 4 states respectively and want to add a (numbered) child summing the two nodes.

How is that done with Java-code? I have tried the following, and my "Sum"-node has 3*4=12 states as expected, but it only contains all -1's. Somehow I can't figure out how to put the different combinations in the "Sum"-node.

            int t1 = node1.getNumberOfStates();
            int t2 = node2.getNumberOfStates();
            int combinations = t1*t2;

            NumberedDCNode node = new NumberedDCNode(domain);
            node.setNumberOfStates(combinations);

            nodeNavn = "Sum";
            node.setName(nodeNavn);
            node.setLabel(nodeNavn);

            node.addParent(node1);
            node.addParent(node2);

            NodeExpression exprNode1 = new NodeExpression(node1);
            NodeExpression exprNode2 = new NodeExpression(node2);

            NodeList modelNodes = new NodeList();
            Model model = new Model(node, modelNodes);

            AddExpression exprNode = new AddExpression(exprNode1,exprNode2);

            model.setExpression(0, exprNode);

Maybe the "Model"-feature is not even valid for numbered nodes? Or am I missing something?  ???

Thanks in advance

Offline Anders L Madsen

  • HUGIN Expert
  • Hero Member
  • *****
  • Posts: 2295
    • View Profile
Re: How to sum two numbered nodes?
« Reply #1 on: April 17, 2008, 08:58:29 »
You need to define the state values of "node".

The tool does not automatically identify the states of a node given its expression. Thus, you have to specify the possible states of the child. This is done using the method:

Code: [Select]
setStateValue (int s, double v) 

If "node1" and "node2" have states 0,2,4 and 1,2,3, respectively, then the possible values of their sum are 1,2,3,4,5,6,7. This implies that "node" has to have seven states (not nine) with values 1,2,3,4,5,6,7.

Notice that different combinations of parent values may map to the same state in the child given the expression.
HUGIN EXPERT A/S

Offline rosthoej

  • Newbie
  • *
  • Posts: 4
    • View Profile
Re: How to sum two numbered nodes?
« Reply #2 on: April 17, 2008, 11:58:33 »
Thanks for the fast reply.

In the specific case I have to sum 5 nodes with 2,3,4,5 and 19 different states summing up to (a maximum of) 2.280 states of "node".

Do I understand it right, if I have to calculate all the possible states of "node", sort the values and set them afterwards using the setStateValue? That would include 5 for-loops over the number of states for each node. There is no way to automatically sum NumberedDCNodes?

In that case I assume it would be easier to use IntervalDCNodes instead and sum using the Model/Expression-features?

Offline Anders L Madsen

  • HUGIN Expert
  • Hero Member
  • *****
  • Posts: 2295
    • View Profile
Re: How to sum two numbered nodes?
« Reply #3 on: April 17, 2008, 12:41:55 »
Quote
Do I understand it right, if I have to calculate all the possible states of "node", sort the values and set them afterwards using the setStateValue?

This is correct. You would have to do exactly the same in the HUGIN Graphical User Interface if creating the model by hand.

Quote
That would include 5 for-loops over the number of states for each node. There is no way to automatically sum NumberedDCNodes?

There is no way to automatically identify the states of a node from its expression in the HUGIN APIs. Implementing a method to identify the possible state values is not too difficult in the case where the parents are NumberedDCnodes and the expression is sum. If you decide to use this approach, I would not mind to create a simple example for you.

Quote
In that case I assume it would be easier to use IntervalDCNodes instead and sum using the Model/Expression-features?

If it is sufficient to know the range of possible values, then IntervalDCCnodes may be used, i.e. you do not need to know the exact value of the sum. You will have to define the states of the IntervalDCNode too.

You may still use the model/expression-features to define the expression for a NumberedDCNode.
HUGIN EXPERT A/S

Offline rosthoej

  • Newbie
  • *
  • Posts: 4
    • View Profile
Re: How to sum two numbered nodes?
« Reply #4 on: April 17, 2008, 12:56:39 »
Hi again,

An example would be great - if you've got time for it.

Thanks!

Offline Anders L Madsen

  • HUGIN Expert
  • Hero Member
  • *****
  • Posts: 2295
    • View Profile
Re: How to sum two numbered nodes?
« Reply #5 on: April 17, 2008, 15:11:25 »
The code fragment below identifies the states of a sum node when the node has two parents:

Code: [Select]
// create states in "sum" node
HashSet<Double> states = new HashSet<Double> ();
for (int i = 0; i < node1.getNumberOfStates (); i++)
   for (int j = 0; j < node2.getNumberOfStates (); j++) {
       states.add(new Double (node1.getStateValue (i) + node2.getStateValue (j)));
   }
   Object [] sortedStates  = states.toArray ();
   Arrays.sort (sortedStates, new Comparator <Object>() {
                                 public int compare (Object o1, Object o2) {
                                    double d1 = ((Double)o1).doubleValue ();
                                    double d2 = ((Double)o2).doubleValue ();
                                    return (d1==d2 ? 0 : d1 < d2 ? -1 : 1);
                                 }} );
  int i = 0;
  for (Object d : sortedStates)
     node.setStateValue (i++, ((Double)d).doubleValue ());

There may well be other ways to do this more elegantly, but it illustrates the principle. The example is specific to two parents and the sum operator. It is possible to extend the example to the more general case with a variable number of parents and a different operator.
HUGIN EXPERT A/S

Offline rosthoej

  • Newbie
  • *
  • Posts: 4
    • View Profile
Re: How to sum two numbered nodes?
« Reply #6 on: April 21, 2008, 08:58:54 »
Is there any easy way to set the data of the CPT table in this case?

Offline Anders L Madsen

  • HUGIN Expert
  • Hero Member
  • *****
  • Posts: 2295
    • View Profile
Re: How to sum two numbered nodes?
« Reply #7 on: April 21, 2008, 12:25:20 »
Yes, you simply use the expression you have already created. Here is an example based on your code:
Code: [Select]
import COM.hugin.HAPI.*;
import java.util.*;

class SumExample {
 Domain _domain = null;
 DefaultClassParseListener parser = new DefaultClassParseListener ();

 public SumExample (String netFile)
  {
   try {
   //  load network
    _domain = new Domain (netFile, parser);

    // get handles to nodes
    NumberedDCNode node1 = (NumberedDCNode)_domain.getNodeByName ("node1");
    NumberedDCNode node2 = (NumberedDCNode)_domain.getNodeByName ("node2");
    int t1 = node1.getNumberOfStates();
    int t2 = node2.getNumberOfStates();

    NumberedDCNode node = new NumberedDCNode(_domain);

    String nodeName = "Sum";
    node.setName(nodeName);
    node.setLabel(nodeName);

    // add parents
    node.addParent(node1);
    node.addParent(node2);

    // create states in "sum" node
    HashSet<Double> states = new HashSet<Double> ();
    for (int i = 0; i < node1.getNumberOfStates (); i++)
       for (int j = 0; j < node2.getNumberOfStates (); j++) {
                 states.add(new Double (node1.getStateValue (i) + node2.getStateValue (j)));
}
    node.setNumberOfStates (states.size ());
    Object [] sortedStates  = states.toArray ();
    Arrays.sort (sortedStates, new Comparator <Object>() {
      public int compare (Object o1, Object o2) {
        double d1 = ((Double)o1).doubleValue ();
        double d2 = ((Double)o2).doubleValue ();
          return (d1==d2 ? 0 : d1 < d2 ? -1 : 1);
        }
       } );
    int i = 0;
    for (Object d : sortedStates)
       node.setStateValue (i++, ((Double)d).doubleValue ());
   
    try{
    // create expression
           NodeExpression exprNode1 = new NodeExpression(node1);
           NodeExpression exprNode2 = new NodeExpression(node2);
           NodeList modelNodes = new NodeList();
           Model model = new Model(node, modelNodes);
           AddExpression exprNode = new AddExpression(exprNode1,exprNode2);
           model.setExpression(0, exprNode);
   
  } catch (Exception e) {
    e.printStackTrace();
    System.out.println(e.getMessage());
  }
  _domain.saveAsNet ("q.net");    
 } catch (Exception e) {
    e.printStackTrace();
    System.out.println(e.getMessage());
  }
}

 static public void main(String args[]) {
  if (args.length != 1) {
   System.out.println ("usage: <net file>");
   System.exit (-1);
  }
  new SumExample (args[0]);
 }
}

The program takes as input a network file with two nodes "node1" and "node2" and creates a node representing the sum "node1+node2"
HUGIN EXPERT A/S