Esempio n. 1
0
double JointBeliefSparse::Update(const MultiAgentDecisionProcessDiscreteInterface &pu,
                                 Index lastJAI, Index newJOI)
{
    //const TransitionModelDiscrete* T=pu.GetTransitionModelDiscretePtr();
    const ObservationModelDiscrete* O=pu.GetObservationModelDiscretePtr();

    //pointer to the transition probability Get funtion:
    TGet* T = pu.GetTGet();
    if(T==0)
    {
        return(UpdateSlow(pu,lastJAI,newJOI));
    }

    double Po_ba = 0.0; // P(o|b,a) with o=newJO
    double Ps_ba, Po_as, Pso_ba;
    size_t nrS = _m_b.size();
    BS newJB_unnorm(nrS);
    for(Index sI=0; sI < nrS; sI++)
    {
        //P(sI | b, a) = sum_(prec_s) P(sI | prec_s, a)*JB(prec_s)
        Ps_ba = 0.0;

        for(BScit it=_m_b.begin(); it!=_m_b.end(); ++it)
            Ps_ba += T->Get(it.index(), lastJAI, sI) * *it;

        if(Ps_ba>0) // if it is zero, Pso_ba will be zero anyway
        {
            //P(newJOI | lastJAI, sI) :
            Po_as = O->Get(lastJAI, sI, newJOI);

            //the new (unormalized) belief P(s,o|b,a)
            Pso_ba = Po_as * Ps_ba;

            if(Pso_ba>PROB_PRECISION) // we don't want to store very
                                      // small probabilities in a
                                      // sparse representation
            {
                newJB_unnorm[sI]=Pso_ba; //unnormalized new belief
                Po_ba += Pso_ba; //running sum of P(o|b,a)
            }
        }
    }
    
    //normalize:    
    if(Po_ba>0)
        for(BSit it=newJB_unnorm.begin(); it!=newJB_unnorm.end(); ++it)
            *it/=Po_ba;

    _m_b=newJB_unnorm;

#if JointBeliefSparse_doSanityCheckAfterEveryUpdate
    if(!SanityCheck())
        throw(E("JointBeliefSparse::Update SanityCheck failed"));
#endif

    return(Po_ba);
}
Esempio n. 2
0
double JointBeliefEventDriven::Update(const MultiAgentDecisionProcessDiscreteInterface &pu,
                                      Index lastJAI, Index newJOI)
{
    using namespace boost::numeric::ublas;

    if(!pu.GetEventObservability())
        throw E("Trying to use a JointBeliefEventDriven on a model without event observability.");

    size_t nrS = pu.GetNrStates();
    
    const TransitionModelMapping *T = dynamic_cast<const TransitionModelMapping *>(pu.GetTransitionModelDiscretePtr());
    const EventObservationModelMapping *O = dynamic_cast<const EventObservationModelMapping *>(pu.GetObservationModelDiscretePtr());
    double eta = 0;
    if(T != 0 && O != 0)
    {
        using namespace boost::numeric::ublas;
      
        //we need to break the abstraction here since we'll be using ublas over T and O.
        //Ideally, we could have some kind of built in conversion.
        const matrix<double>* Ta = T->GetMatrixPtr(lastJAI);
        const matrix<double>* Oao = O->GetMatrixPtr(lastJAI,newJOI);
        matrix<double>* Hao = new matrix<double>(element_prod(*Ta,*Oao));
      
        matrix<double> H = *Hao;
      
        double epsilon, last_epsilon = 0;
      
        //We need b in ublas form.
        boost::numeric::ublas::vector<double> b(nrS);
        std::copy(_m_b.begin(), _m_b.end(), b.begin());

        boost::numeric::ublas::vector<double> res = zero_vector<double>(nrS);
        boost::numeric::ublas::vector<double> bUpdated = prod(b,H);
        epsilon = JointBeliefEventDriven_convergenceTh;
        if(_m_falseNegativeObs >= 0)
        {
            const matrix<double>* Oaf = O->GetMatrixPtr(lastJAI,_m_falseNegativeObs);
            //At this point we have two |S|x|S| matrices
            //What we want to do is; 
            //Hao = Ta.*Oao;
            //Haf = Ta.*Oaf;
            //b' = (b^T * (inv(I - Haf) * Hao))/n
            //Since we can't compute the inverse of arbitrarily large matrices, we have to approximate this
            //by cutting off the respective power series (I + Haf + Haf^2 + Haf^3 + ...) at some point.
            //Since Ta, Oao, Oaf are defined over (s,s') and we want to avoid having to transpose,
            //we have to left-multiply this by b^T to get the update
            //We also cannot rely on determinant / trace, so we have to keep track of b' and see if it is converging.

            matrix<double>* Haf = new matrix<double>(element_prod(*Ta,*Oaf));
            for(int safety_s=0, safety_h=0; 
                epsilon >= JointBeliefEventDriven_convergenceTh && safety_h < JointBeliefEventDriven_hardCap;
                safety_h++)
            {
                noalias(H) = prod(*Haf, H); //remember that we are implicitly using transposes.
                res = prod(b,H);
              
                bUpdated = bUpdated + res;
                last_epsilon = epsilon;
                if(sum(bUpdated) > 0)
                    epsilon = sum(res);
              
                if(last_epsilon != 0 && epsilon >= last_epsilon){
                    safety_s++;
                }else{
                    safety_s=0;
                }
                if(safety_s >= JointBeliefEventDriven_softCap){
                    cout << "Warning: Event-driven belief update not converging! - The system has non-observable chains." << endl;
                    break;
                }
            }
      
            delete Haf;
        }
        //only the normalization factor remains
        eta = sum(bUpdated);

        if(eta > 0)
        {
            bUpdated = bUpdated / eta;
      
            _m_b.clear();
            _m_b.insert(_m_b.end(), bUpdated.begin(), bUpdated.end());
        }
        else
        {
            cout << "Event-driven belief update failed: The system is badly conditioned. There is 0 probability of observing this symbol given this belief." << endl;
        }  
      
        delete Hao;      
    }
    
#if JointBeliefEventDriven_doSanityCheckAfterEveryUpdate
    if(!SanityCheck())
        throw(E("JointBeliefEventDriven::Update SanityCheck failed"));
#endif

    return(eta);
}