Author Topic: How to pass database using JAVA HUgin API for EM learning.  (Read 64090 times)

Offline jack

  • Newbie
  • *
  • Posts: 18
    • View Profile
Hi,
can anybody please tell me how to pass database for EM learning using JAVA HUGIN API.
I realized that you should do with the method learnTable () of the class domain ,
but I haven't understand how to pass to the method my database (MySQL).

Please help!
Thanks

Offline Martin

  • HUGIN Expert
  • Hero Member
  • *****
  • Posts: 613
    • View Profile
Re: How to pass database using JAVA HUgin API for EM learning.
« Reply #1 on: July 22, 2011, 11:16:09 »
There is no direct method for inserting cases from a mysql database.

What you have to do is to write some code that first creates the cases in the Domain from your mysql data, and then invokes the learnTables method.

In code you will have to iterate each case in your mysql database, and use HUGIN API methods for creating the case in the Domain.

Add a new case to the domain
Code: [Select]
int Domain.newCase()
Set a discrete node to a specific state for a given case
Code: [Select]
void DiscreteNode.setCaseState(int c, int state)
When all cases have been created in the Domain, invoke learnTables.

Hugin Expert A/S

Offline jack

  • Newbie
  • *
  • Posts: 18
    • View Profile
Re: How to pass database using JAVA HUgin API for EM learning.
« Reply #2 on: July 26, 2011, 18:48:18 »
thanks for the quick answer.
« Last Edit: July 30, 2011, 18:13:08 by jack »

Offline jack

  • Newbie
  • *
  • Posts: 18
    • View Profile
Re: How to pass database using JAVA HUgin API for EM learning.
« Reply #3 on: September 05, 2011, 17:24:43 »
I must to add a new case for each state of node with:
"int Domain.newCase() "??
Another, instead of using:
void DiscreteNode.setCaseState(int c, int state)
I used
void LabelledDCNode.setStateLabel(int state, java.lang.String newLabel)
because the state of my node are words and they aren't number

Offline Anders L Madsen

  • HUGIN Expert
  • Hero Member
  • *****
  • Posts: 2295
    • View Profile
Re: How to pass database using JAVA HUgin API for EM learning.
« Reply #4 on: September 07, 2011, 09:28:36 »
Code: [Select]
int Domain.newCase()This method creates a new empty case in Domain.

Code: [Select]
void DiscreteNode.setCaseState(int c, int state)This method sets the state of a node in a specific case. It is necessary to invoke this method for each node in each case to construct a complete set of cases (i.e., a set of cases with no missing values). You may consider using DiscreteNode.getStateIndex (String) to identify the state index corresponding to a particular String.

Code: [Select]
void LabelledDCNode.setStateLabel(int state, java.lang.String newLabel)This method sets the state label of a LabelledDCNode to newLabel.
HUGIN EXPERT A/S

Offline jack

  • Newbie
  • *
  • Posts: 18
    • View Profile
Re: How to pass database using JAVA HUgin API for EM learning.
« Reply #5 on: September 09, 2011, 18:40:12 »
Thanks for the quick answer....
My codes generates error :
"Errore: An Api function was called with an invalid argument(e.g., a NULL object was passed to a function that expects a non-NULL argument).
I have written some code that creates the cases in the Domain from your mysql data:

...................
String a;
int p=0;
LabelledDCNode node1 = new LabelledDCNode(myDomain);
node1.setName.........
node1.setLabel...........
......................
Resulset rset = stmt.executeQuery("SELECT ....... FROM .......;")
int statenode1=0;
while(rset.next()){
p.myDomain.newCase();
node1.setCaseState(p,statenode1);
a = rset.getString("node1");
node1.setStateLabel(statenode1,a);
statenode1++;
 }
Resulset rset2............
.........................
.................
myDomain.compile();
myDomain.learnTables();
.............


and I have written some code that print tables for all discrete node
public static void printTable(Table CPT)..........
..................
...................

You could help me solve this problem?
Thanks a lot
P.S. ...and to use the algorythm PC?
I use void Domain.learnStructure() instead learnTable?
« Last Edit: September 10, 2011, 17:09:57 by jack »

Offline Anders L Madsen

  • HUGIN Expert
  • Hero Member
  • *****
  • Posts: 2295
    • View Profile
Re: How to pass database using JAVA HUgin API for EM learning.
« Reply #6 on: September 13, 2011, 13:40:28 »
The error message ""Error: An Api function was called with an invalid argument(e.g., a NULL object was passed to a function that expects a non-NULL argument)" states that one of the arguments to a HUGIN method is NULL. From your code example it is difficult to say which one. (I assume 
Code: [Select]
p.myDomain.newCase(); is in fact
Code: [Select]
p=myDomain.newCase();).

The error could be caused by "a" being NULL. It is good practice to including error testing code and printing a stack-trace will help to locate the cause of the problem. You should test for NULL arguments before calling HUGIN methods.

The learn the structure of a network using the PC algorithm you invoke "learnStructure ()".
HUGIN EXPERT A/S

Offline jack

  • Newbie
  • *
  • Posts: 18
    • View Profile
Re: How to pass database using JAVA HUgin API for EM learning.
« Reply #7 on: September 13, 2011, 15:15:51 »
thank you for the quick answer but the error isn't that......
i have the same error
My code complete is:

import java.sql.*;
import java.util.*;
import COM.hugin.HAPI.*;

public class Test{
public static void main (String []args throws ExceptionHugin{
try{
java.lang.Class.forName("com.mysql.jdbc.Driver");
}
catch (Exception exc){
System.out.println("Error - Driver jdbc not present: "+exc.getMessage());
}
try{
String a,b;
Domain myDomain=new Domain();
int p=0;
int q=0;

LabelledDCNode one = new LabelledDCNode(myDomain);
one.setLabel("one");
one.setName("one");
one.setNumberOfStates(40);

LabelledDCNode two = new LabelledDCNode(myDomain);
two.addParent(one);
two.setLabel("two");
two.setName("two");
two.setNumberOfStates(40);

Connection conn = DriverManager.getConnection("url","user","password");
Statement stmt = conn.createStatement();

Resulset rset = stmt.executeQuery("SELECT one FROM table;");
int statenode1 = 0;
while(rset.next()){
p=myDomain.newCase();
one.setCaseState(p,statenode1);
a = rset.getString("one");
//System.out.println(a);
one.setStateLabel(statenode1,a);
statenode1++
}

Resulset rset2 = stmt.executeQuery("SELECT two FROM table;");
int statenode2 = 0;
while(rset2.next()){
q=myDomain.newCase();
two.setCaseState(q,statenode2);
b=rset2.getString("two");
//System.out.println(b);
two.setStateLabel(statenode2,b);
statenode2++
}

myDomain.compile();
myDomain.learnTable();  // or myDomain.learnStructure();

Table t = two.getTable();
printTable(t);

Table t1 = one.getTable();
printTable(t1);

rset.close();
rset2.close();
stmt.close();
conn.close();
}
catch(Exception exc){
System.out.println("Error:"+exc.getMessage());
}
}

public static void printTable(Table CPT) throws ExceptionHugin{
NodeList nodes = CPT.getNodes();
int[] configuration = new int [nodes.size()];
int tableSize = CPT.getSize();
for(int i=0;i<tableSize;i++){
CPT.getConfiguration(configuration,i);
for (int j=0;j<nodes.size();j++){
Node n = (Node)nodes.get(j);
System.out.print(n.getName()+"="+configuration[j]+" ");
}
System.out.println(":= "+CPT.getDataItem(i));
}
}
}




...........If I print a and b, I can see which they are the values ​​of my databases.
I think which the error is generated by learntable() or learnStructure()
« Last Edit: September 13, 2011, 18:23:00 by jack »

Offline Anders L Madsen

  • HUGIN Expert
  • Hero Member
  • *****
  • Posts: 2295
    • View Profile
Re: How to pass database using JAVA HUgin API for EM learning.
« Reply #8 on: September 15, 2011, 10:41:57 »
I cannot test your code at I do not have a database connection...

The error message indicates an error in a parameter to a HUGIN method. Domain.learnTables and Domain.learnStrcucture does not take any argument. Please test the input values to each HUGIN method invocation.

Here is a working example showing how to enter and learn (CPTs) from data:
Code: [Select]
/*
 * This simple Java program illustrates how to learn (the parameters)
 * of a Bayesian network from data
 *
 * The result is stored in a file name learning.net
 *
 *
 * Author: Anders L Madsen @ HUGIN EXPERT A/S
 *
 * For any questions or comments, please contact the author at
 * alm@hugin.com
 */
import COM.hugin.HAPI.*;
import java.text.DecimalFormat;

class EnterDataExample {
    // the model
    Domain dom = null;

    // the nodes / variables in the model
    LabelledDCNode Sex, Height;

    public EnterDataExample ()
    {
try {
    // Create domain. Done once.
    dom = new Domain ();
   
    Sex = new LabelledDCNode(dom); Sex.setName ("Sex");
    Height = new LabelledDCNode(dom); Height.setName ("Height");

    Sex.setNumberOfStates (2);
    Sex.setStateLabel (0, "Female");
    Sex.setStateLabel (1, "Male");

    Height.setNumberOfStates (2);
    Height.setStateLabel (0, "Low");
    Height.setStateLabel (1, "High");

    // Add Sex as parent of Height. Comment this line if you
    // uncomment "dom.learnStructure ();" below
    Height.addParent (Sex);

    // create Experience tables to enable CPT estimatio
    Sex.getExperienceTable ();
    Height.getExperienceTable ();

} catch (Exception e) {
    e.printStackTrace ();
    System.err.println (e.getMessage ());    
}
    }

    // Data is an array of strings. First entry is Sex and second is
    // Height;
    String dataArray[][]  =
{
    {"Male", "High"},
    {"Male", "High"},
    {"Male", "High"},
    {"Female", "High"},
    {"Female", "Low"},
    {"Male", "Low"},
    {"Female", "Low"},
    {"Male", "High"},
    {"Male", ""},
    {"Female", "Low"}
};
;
    int N=10;

    // Main procedure. 
    protected void doLearning () {
try{
    // enter data
    enterData ();

    // (learn structure) compile and estimate parameters
    // dom.learnStructure (); // uncomment this line (and the
    // addParent line) above to learn structure from data
    dom.compile ();
    dom.learnTables ();

    // save domain in file
    dom.saveAsNet ("learning.net");
} catch (Exception e) {
    e.printStackTrace ();
    System.err.println (e.getMessage ());    
}
    }

    //
    protected void enterData () {
try{
    long j, s;
    for (int i = 0; i < N; i++) {
j = dom.newCase ();

s = Sex.getStateIndex (dataArray[i][0]);
if (s >= 0)
    Sex.setCaseState (j, s);

s = Height.getStateIndex (dataArray[i][1]);
if (s >= 0)
    Height.setCaseState (j, s);
    }
    //... more data
} catch (Exception e) {
    e.printStackTrace ();
    System.err.println (e.getMessage ());    
}
    }
   
    static public void main (String args[])
    {
EnterDataExample ede = new EnterDataExample ();
ede.doLearning ();
    }
}

HUGIN EXPERT A/S

Offline jack

  • Newbie
  • *
  • Posts: 18
    • View Profile
Re: How to pass database using JAVA HUgin API for EM learning.
« Reply #9 on: September 15, 2011, 15:14:28 »
thanks a lot.............
I added
one.getExperienceTable();
two.getExperienceTable();
before of myDomain.compile() and now my code is running with learnTable().
If I use learnStructure() (algorithm PC) get the same output:
"Error: An Api function was called with an invalid argument(e.g., a NULL object was passed to a function that expects a non-NULL argument)".


Offline Anders L Madsen

  • HUGIN Expert
  • Hero Member
  • *****
  • Posts: 2295
    • View Profile
Re: How to pass database using JAVA HUgin API for EM learning.
« Reply #10 on: September 15, 2011, 22:42:00 »
please send me you updated code.
HUGIN EXPERT A/S

Offline jack

  • Newbie
  • *
  • Posts: 18
    • View Profile
Re: How to pass database using JAVA HUgin API for EM learning.
« Reply #11 on: September 16, 2011, 17:05:58 »
import java.sql.*;
import java.util.*;
import COM.hugin.HAPI.*;

public class Test{
public static void main (String []args throws ExceptionHugin{
try{
java.lang.Class.forName("com.mysql.jdbc.Driver");
}
catch (Exception exc){
System.out.println("Error - Driver jdbc not present: "+exc.getMessage());
}
try{
String a,b;
Domain myDomain=new Domain();
int p=0;
int q=0;

LabelledDCNode one = new LabelledDCNode(myDomain);
one.setLabel("one");
one.setName("one");
one.setNumberOfStates(40);

LabelledDCNode two = new LabelledDCNode(myDomain);

two.setLabel("two");
two.setName("two");
two.setNumberOfStates(40);

Connection conn = DriverManager.getConnection("url","user","password");
Statement stmt = conn.createStatement();

Resulset rset = stmt.executeQuery("SELECT one FROM table;");
int statenode1 = 0;
while(rset.next()){
p=myDomain.newCase();
one.setCaseState(p,statenode1);
a = rset.getString("one");
//System.out.println(a);
one.setStateLabel(statenode1,a);
statenode1++
}

Resulset rset2 = stmt.executeQuery("SELECT two FROM table;");
int statenode2 = 0;
while(rset2.next()){
q=myDomain.newCase();
two.setCaseState(q,statenode2);
b=rset2.getString("two");
//System.out.println(b);
two.setStateLabel(statenode2,b);
statenode2++
}

two.addParent(one);
one.getExperienceTable();
two.getExperienceTable();
myDomain.compile();
myDomain.learnStructure();

Table t = two.getTable();
printTable(t);

Table t1 = one.getTable();
printTable(t1);

rset.close();
rset2.close();
stmt.close();
conn.close();
}
catch(Exception exc){
System.out.println("Error:"+exc.getMessage());
}
}

public static void printTable(Table CPT) throws ExceptionHugin{
NodeList nodes = CPT.getNodes();
int[] configuration = new int [nodes.size()];
int tableSize = CPT.getSize();
for(int i=0;i<tableSize;i++){
CPT.getConfiguration(configuration,i);
for (int j=0;j<nodes.size();j++){
DiscreteNode n = (DiscreteNode)nodes.get(j);
int h=configuration[j];
System.out.print(n.getStateLabel(h)+" ");
}
System.out.println(":= "+CPT.getDataItem(i));
}
}
}


P.S.On your code EnterDataExample i have two error:
Sex.setCaseState(j,s);   
Height.setCaseState(j,s);

Error:The metod setCaseState(int,int) in the type DiscreteNode is not applicable for the arguments(long,long)

Offline Anders L Madsen

  • HUGIN Expert
  • Hero Member
  • *****
  • Posts: 2295
    • View Profile
Re: How to pass database using JAVA HUgin API for EM learning.
« Reply #12 on: September 16, 2011, 20:26:53 »
You should not call Domain.compile before Domain.learnStructure. This will make Domain.learnStructure fail. Call Domain.compile after Domain.learnStructure.

Quote
P.S.On your code EnterDataExample i have two error:
Sex.setCaseState(j,s);   
Height.setCaseState(j,s);

Error:The metod setCaseState(int,int) in the type DiscreteNode is not applicable for the arguments(long,long)

I'm using 64-bit version. If you use 32-bit, then change the long to int.
HUGIN EXPERT A/S

Offline jack

  • Newbie
  • *
  • Posts: 18
    • View Profile
Re: How to pass database using JAVA HUgin API for EM learning.
« Reply #13 on: September 18, 2011, 21:50:51 »
Thank you.
If I call Domain.compile after Domain.learnStructure I have always the same output:
"Error: An API function was called with an invalid argument (e.g., a NULL object was passed to a function that expects a non-NULL argument)."
.......I can't understand wher's this error.


Offline Anders L Madsen

  • HUGIN Expert
  • Hero Member
  • *****
  • Posts: 2295
    • View Profile
Re: How to pass database using JAVA HUgin API for EM learning.
« Reply #14 on: September 19, 2011, 10:04:04 »
Put in some error handling code (try-catch with a printStackTrace call) and identify which line produces the error.

Also, it would be useful as debugging to save the data entered into the domain as file - use Domain.saveCases ().

Please reread the example I posted previously and adapt this example to your situation. Notice the method setStateLabel should not be used as part of entering data and read the documentation on setCaseState.

« Last Edit: September 21, 2011, 10:22:00 by Anders L Madsen »
HUGIN EXPERT A/S