BayesianLogic / blog

The BLOG programming language
http://bayesianlogic.github.io/
BSD 4-Clause "Original" or "Old" License
98 stars 31 forks source link

Wrong results with the Particle Filter. is this a bug? #338

Closed davidenitti closed 9 years ago

davidenitti commented 9 years ago

I need to compare my language with (D)BLOG for a paper. I wrote a Wumpus (temporal) example and I get different results using BLOG and DBLOG. My language and BLOG gives around 0.25 for a given query DBLOG gives around 0.44 (even with 100000 particles) for the same query. Is this a bug?

query Agentx(@3)==0 & Agenty(@3)==0; BLOG call: ./blog -r example/wumpus1.dblog -n 10000 DBLOG call: ./blog -r -e blog.engine.ParticleFilter example/wumpus1.dblog -n 10000

the program is this:

type Action;
distinct Action None,Up, Down, Left, Right;

type Cell;
distinct Cell free, wall;

fixed Action action(Timestep t) =
 if t==@0 then
 None
 else if t==@1 then Right
 else if t==@2 then Left
 else if t==@3 then Left;

random Cell Maze(Integer x,Integer y,Timestep t) ~
  if t == @0 then
    if x==0 & y==0 then
        free
    else
    Categorical({free -> 0.6, wall -> 0.4}) 
  else Maze(x,y,prev(t))
;

random Integer Agenty(Timestep t) ~
  if t == @0 then
    0
    else
    if action(t) == Up then
        if Maze(Agentx(prev(t)),Agenty(prev(t))+1,prev(t))==free then
            Categorical({Agenty(prev(t))+1 -> 0.9, Agenty(prev(t)) -> 0.1} )
        else
            Agenty(prev(t))
    else if action(t) == Down then
        if Maze(Agentx(prev(t)),Agenty(prev(t))-1,prev(t))==free then
            Categorical({Agenty(prev(t))-1 -> 0.9, Agenty(prev(t)) -> 0.1} )
        else
            Agenty(prev(t))
    else 
        Agenty(prev(t))
;

random Integer Agentx(Timestep t) ~
  if t == @0 then
    0
    else
    if action(t) == Left then
        if Maze(Agentx(prev(t))-1,Agenty(prev(t)),prev(t))==free then
            Categorical({Agentx(prev(t))-1 -> 0.9, Agentx(prev(t)) -> 0.1} )
        else
            Agentx(prev(t))
    else if action(t) == Right then
        if Maze(Agentx(prev(t))+1,Agenty(prev(t)),prev(t))==free then
            Categorical({Agentx(prev(t))+1 -> 0.9, Agentx(prev(t)) -> 0.1} )
        else
            Agentx(prev(t))
    else 
        Agentx(prev(t))
;

random Cell obsleft(Timestep t) ~
    if Maze(Agentx(t)-1,Agenty(t),t)==wall then
        Categorical({free -> 0.1, wall -> 0.9}) 
    else
        Categorical({free -> 0.9, wall -> 0.1}) 
;

random Cell obsright(Timestep t) ~
    if Maze(Agentx(t)+1,Agenty(t),t)==wall then
        Categorical({free -> 0.1, wall -> 0.9}) 
    else
        Categorical({free -> 0.9, wall -> 0.1}) 
;

random Cell obsup(Timestep t) ~
    if Maze(Agentx(t),Agenty(t)+1,t)==wall then
        Categorical({free -> 0.1, wall -> 0.9}) 
    else
        Categorical({free -> 0.9, wall -> 0.1}) 
;
random Cell obsdown(Timestep t) ~
    if Maze(Agentx(t),Agenty(t)-1,t)==wall then
        Categorical({free -> 0.1, wall -> 0.9}) 
    else
        Categorical({free -> 0.9, wall -> 0.1}) 
;
obs obsup(@1) = wall;
obs obsright(@1) = free;

obs obsup(@2) = free;
obs obsleft(@2) = free;

obs obsup(@3) = free;
obs obsright(@3) = wall;

query Agentx(@3)==0 & Agenty(@3)==0;
jxwuyi commented 9 years ago

The easiest solution to fix this is to replace the definition of Maze() from

random Cell Maze(Integer x,Integer y,Timestep t) ~
  if t == @0 then
    if x==0 & y==0 then
        free
    else
    Categorical({free -> 0.6, wall -> 0.4}) 
  else Maze(x,y,prev(t))
;

to

random Cell Maze(Integer x,Integer y) ~
    if x==0 & y==0 then
        free
    else
    Categorical({free -> 0.6, wall -> 0.4}) 
;

The difference is that in the previous case, Maze() is a temporal random variable while in the latter case, Maze() is a static variable.

In the current implementation of Particle Filtering, we will only contain the information for the last two timesteps. Note that some positions of Maze() might not be sampled in time 1, or time 2. So when you trace back from time 3, all the information in time 1 or time 0 has been deleted.

davidenitti commented 9 years ago

thanks for the reply, but your proposed solution does not work: now it seems that the same maze cell is sampled at every step, even if it was already sampled. Instead a cell has to be constant over time. Thus the maze cell at time t+1 has to be equal to the maze cell at time t.

jxwuyi commented 9 years ago

It actually works. You can try it. It produces the result of 0.25.

In particle filtering, all the random variables without an argument of timestep will be always reserved in every time step. They will not be cleared or resampled. In each time step you will have the same variable since they have nothing to do with timestep. That's why they are called static variables here. We are only removing temporal variables.

If you really want to make random var Maze() temporal variables, for now, the only way is to query it in each time step to ensure that it will be sampled before being removed.

davidenitti commented 9 years ago

my mistake, I forgot to remove the time. thanks!

davidenitti commented 9 years ago

It works, but if I want to query a cell maze at each step I get the same result. The maze belief should change according to the evidence, even when the maze is static. If I try to query several time e.g., maze(1,1) I get always the same result.

jxwuyi commented 9 years ago

It is true, always the same result.

If you query the static variable, the result is always the posterior distribution, namely the distribution given all the data (or saying, the posterior at the final timestep, always).

If you would like to observe how the posterior distribution varies, perhaps the only way is to firstly include a timestep argument in the definition of Maze() and then query all the necessary cells of Maze() at each timestep. In this case you will probably write dozens of queries. Yes, it is really a little bit annoying. We will try to come up with some new syntax for this.