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); }
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); }