problem with setPTabular in pnlHigh

  • Gunnar Vagotis

    Gunnar Vagotis - 2007-12-17

    I am getting a really strange behavior with pnlHigh. I tried to search for related bugs on the forum but did not find it. It's hard to imagine that there is something this wrong in the PNL code but maybe I am misusing the library somehow. The problem is that the wrong cells in the CPTs seem to be getting modified when I call setPTabular on some nodes.

    The setup: I have a small network for diagnosing system errors. The behavior occurs in a node called "response.resetSensor", which has incoming links from three other sensors: "indication.sensorVerifiedWorking", "indication.sensorVerifiedBroken", and "response.plantResponse".

    The test scenario is simple, here is the code that simply makes one call to SetPTabular and prints some output/checks the results:

        BayesNet*  the_bayes_net = f->getBayesNet();
        TokArr this_node_pnl_ref("response.resetSensor^true response.resetSensor^false");
        TokArr cpi("indication.sensorVerifiedBroken^true indication.sensorVerifiedWorking^false response.plantResponse^false");
        the_bayes_net->SetPTabular(this_node_pnl_ref,"0.7 0.3",cpi);

        cout << "init = " << cpi << endl;

        cout << "cpt: " << the_bayes_net->GetPTabular("response.resetSensor") << endl;
        cout << "p(sensorVerifiedWorking)="
         << the_bayes_net->GetJPD("indication.sensorVerifiedWorking")
         << endl
         << "p(sensorVerifiedBroken) ="
         << the_bayes_net->GetJPD("indication.sensorVerifiedBroken")
         << endl
         << "p(plantResponse)        ="
         << the_bayes_net->GetJPD("response.plantResponse")
         << endl
         << "p(resetSensor)          ="
         << the_bayes_net->GetJPD("response.resetSensor")
         << endl;

    And here is the output:
    init = indication.sensorVerifiedBroken^true indication.sensorVerifiedWorking^false response.plantResponse^false
    cpt: indication.sensorVerifiedBroken^true^indication.sensorVerifiedWorking^true^response.plantResponse^true^response.resetSensor^true^0.500000 indication.sensorVerifiedBroken^true^indication.sensorVerifiedWorking^true^response.plantResponse^true^response.resetSensor^false^0.500000 indication.sensorVerifiedBroken^true^indication.sensorVerifiedWorking^true^response.plantResponse^false^response.resetSensor^true^0.500000 indication.sensorVerifiedBroken^true^indication.sensorVerifiedWorking^true^response.plantResponse^false^response.resetSensor^false^0.500000 indication.sensorVerifiedBroken^true^indication.sensorVerifiedWorking^false^response.plantResponse^true^response.resetSensor^true^0.500000 indication.sensorVerifiedBroken^true^indication.sensorVerifiedWorking^false^response.plantResponse^true^response.resetSensor^false^0.500000 indication.sensorVerifiedBroken^true^indication.sensorVerifiedWorking^false^response.plantResponse^false^response.resetSensor^true^0.500000 indication.sensorVerifiedBroken^true^indication.sensorVerifiedWorking^false^response.plantResponse^false^response.resetSensor^false^0.500000 indication.sensorVerifiedBroken^false^indication.sensorVerifiedWorking^true^response.plantResponse^true^response.resetSensor^true^0.500000 indication.sensorVerifiedBroken^false^indication.sensorVerifiedWorking^true^response.plantResponse^true^response.resetSensor^false^0.500000 **indication.sensorVerifiedBroken^false^indication.sensorVerifiedWorking^true^response.plantResponse^false^response.resetSensor^true^0.700000** **indication.sensorVerifiedBroken^false^indication.sensorVerifiedWorking^true^response.plantResponse^false^response.resetSensor^false^0.300000** indication.sensorVerifiedBroken^false^indication.sensorVerifiedWorking^false^response.plantResponse^true^response.resetSensor^true^0.500000 indication.sensorVerifiedBroken^false^indication.sensorVerifiedWorking^false^response.plantResponse^true^response.resetSensor^false^0.500000 indication.sensorVerifiedBroken^false^indication.sensorVerifiedWorking^false^response.plantResponse^false^response.resetSensor^true^0.500000 indication.sensorVerifiedBroken^false^indication.sensorVerifiedWorking^false^response.plantResponse^false^response.resetSensor^false^0.500000
    p(sensorVerifiedWorking)=indication.sensorVerifiedWorking^true^0.000000 indication.sensorVerifiedWorking^false^1.000000
    p(sensorVerifiedBroken) =indication.sensorVerifiedBroken^true^1.000000 indication.sensorVerifiedBroken^false^0.000000
    p(plantResponse)        =response.plantResponse^true^0.000000 response.plantResponse^false^1.000000
    p(resetSensor)          =response.resetSensor^true^0.500000 response.resetSensor^false^0.500000

    I apologize for not having a simpler example but if you look for the 0.7 as set in the SetPTabular call you will find it is in a different row of the CPT (for the opposite sensorVerifed values that it should be). But when I look at the JPDs for the associated nodes after setting evidence they seem to use the correct row in the CPT.

    I'm really perplexed by this behavior and I have no idea where to start. I can't imagine what could be going on as I would imagine anyone using PNLhigh would encounter it immediately if there was something wrong there.

    Thanks in advance for any help I can get!

    • Gunnar Vagotis

      Gunnar Vagotis - 2007-12-17

      I am looking at report #1354021 ("GetPTabular(node,parents) requires certain order of parents") and wondering if it is related.

      My experience with SetPTabular is that it does not appear to be sensitive to the order in which parents are specified, i.e.

      "indication.sensorVerifiedBroken^true indication.sensorVerifiedWorking^false response.plantResponse^false" and
      "indication.sensorVerifiedWorking^false indication.sensorVerifiedBroken^true response.plantResponse^false"

      as the third argument to SetPTabular produce the same results.

    • Gunnar Vagotis

      Gunnar Vagotis - 2007-12-17

      Okay, another update. The strange behavior appears to follow the following pattern. The conditional probabilities get written to the table cell represented by shifting the actual input vector one slot to the right. That is

      "0.9 0.1" , "indication.sensorVerifiedBroken^true indication.sensorVerifiedWorking^false response.plantResponse^false"
      as arguments 2 and 3 to SetPTabular will cause
      "0.9 0.1" to be written to the cell specified by "indication.sensorVerifiedBroken^false indication.sensorVerifiedWorking^true response.plantResponse^false"

      This observation is confirmed in all 6 cases in my example in which shifting to the right does not result in the same row (i.e. everything but true,true,true and false,false,false)

      Does this seem like a real bug in the code now? Somehow I am misusing PNLHigh?

    • Gunnar Vagotis

      Gunnar Vagotis - 2007-12-17

      Okay, so I can recreate the bug pretty easily in a 63 line c++ file. It appears that the order in which nodes are added to the Bayes Net matters w.r.t the TokArr "parent-values" argument for SetPTabular. It appears as though the parent node names in that TokArr are essentially ignored and it is assumed parent-values are specified for SetPTabular in the order in which the parents were created. I can't comprehend how this could have been programmed. I am about to submit a bug report, but here is code that allows me to recreate the error myself.

      #include "pnlHigh.hpp"

      using namespace std;
      using namespace pnl;


      void wetgrass(BayesNet& net) {
        // this would be fine:
        // net.AddNode("discrete^test.n1", "true false");
        // net.AddNode("discrete^test.n2", "true false");
        // net.AddNode("discrete^test.n3", "true false");

        // this is not:
        net.AddNode("discrete^test.n3", "true false");
        net.AddNode("discrete^test.n2", "true false");
        net.AddNode("discrete^test.n1", "true false");

        net.AddNode("discrete^child.n1", "true false");
        net.AddArc("test.n1 test.n2 test.n3", "child.n1");
        net.SetPTabular("test.n1^true test.n1^false", "0.9 0.1");
        net.SetPTabular("test.n2^true test.n2^false", "0.9 0.1");
        net.SetPTabular("test.n3^true test.n3^false", "0.9 0.1");
        net.SetPTabular("child.n1^true child.n1^false",
                "0.6 0.4",
                "test.n1^false test.n2^false test.n3^false");
        net.SetPTabular("child.n1^true child.n1^false",
                "0.65 0.35",
                "test.n1^false test.n2^false test.n3^true");
        net.SetPTabular("child.n1^true child.n1^false",
                "0.7 0.3",
                "test.n1^false test.n2^true test.n3^false");
        net.SetPTabular("child.n1^true child.n1^false",
                "0.75 0.25",
                "test.n1^false test.n2^true test.n3^true");
        net.SetPTabular("child.n1^true child.n1^false",
                "0.8 0.2",
                "test.n1^true test.n2^false test.n3^false");
        net.SetPTabular("child.n1^true child.n1^false",
                "0.85 0.15",
                "test.n1^true test.n2^false test.n3^true");
        net.SetPTabular("child.n1^true child.n1^false",
                "0.9 0.1",
                "test.n1^true test.n2^true test.n3^false");
        net.SetPTabular("child.n1^true child.n1^false",
                "0.95 0.05",
                "test.n1^true test.n2^true test.n3^true");

      int main(int argc,char* argv[]) {
        BayesNet wgNet;

        TokArr v("child.n1");
        TokArr q = wgNet.GetPTabular(v);
        const char* qcp = String(q).c_str();
        string qs = qcp;
        std::replace(qs.begin(),qs.end(),' ','\n');
        std::replace(qs.begin(),qs.end(),'^',' ');
        cout << "cpt: " << endl << qs << endl;

      • Imme Ebert-Uphoff


        > I am looking at report #1354021 ("GetPTabular(node,parents) requires certain
        > order of parents") and wondering if it is related.

        I'm the author of that bug report and, yes, the incorrect behavior you describe for SetPTabular is exactly the same as I found for GetPTabular.

        You phrased it very well:

        > It appears as though the parent node names in that TokArr are essentially ignored and it
        > is assumed parent-values are specified for SetPTabular in the order in which the parents
        > were created.

        That's exactly what it does for GetPTabular as well.

        I wonder whether PNLHigh isn't used by as many people as the low-level interface?  Otherwise I don't understand either why no one else has noticed - or fixed - this problem.  One would think that more people would have fallen into this trap.

        I noticed that you already submitted a bug report.  Good!


Get latest updates about Open Source Projects, Conferences and News.

Sign up for the SourceForge newsletter:

No, thanks