Tutorial 3: Unknown Vending Machine

Build Models in PSI

The following program models the behavior of an unknown vending machine with two buttons a and b selling only bagels and cookies. We do not know which button is for bagels, but we observe Sally, who wants a cookie, presses button b. Suppose Sally knows the how the machine works, how can we infer the probability that b gives bagels from Sally’s action?

a := 0;
b := 1;
actionPrior := [0.5, 0.5];
def vendingMachine(action: R, aEffects: R[], bEffects: R[]){
        if(action == a) {return categorical(aEffects);}
        else if(action == b){return categorical(bEffects);}
        else{return 2;}
}
def chooseAction(goal: R, aEffects: R[], bEffects: R[]){
        action := categorical(actionPrior);
        observe(goal == vendingMachine(action, aEffects, bEffects));
        return action;
}
def main(){
        aEffects := [beta(1,1), 0];
        bEffects := [beta(1,1), 0];
        aEffects[1] = 1-aEffects[0];
        bEffects[1] = 1-bEffects[0];
        goal := flip(0.5);
        observe(goal == 1 && sample(Marginal(chooseAction(goal, aEffects, bEffects)== b)));
        return bEffects[0];
}

Here is what the program does:

The code snippet can be found here. This model is modified from one example in Probabilistic Models of Cognition (2nd Edition) Chapter 06.

Find Sensitivity with PSense

Notice that we suppose the probability that pressing the button giving bagels follows the distribution is given by beta(1,1). There are two constant parameters 1 in the Beta distribution, changing which would give us different results. We want to analyze the sensitivity of this program if we change the parameters of the prior. Specifically, we model the change with ?eps. For example, we can change the first parameter of aEffects[0]’s prior by:

        aEffects := [beta(1+?eps,1), 0];
        ...

The change in the prior distribution (when ?eps = 0.1) is shown in the following figure. We want to know how does this change affects the output distribution.

Drawing

PSense can automatically add ?eps to each constant parameters and find the sensitivity of the probabilistic program. Run the following in shell prompt:

psense -f examples/unknown_vending_machine.psi

After changing the first parameter, PSense outputs:

Function Type:
Continuous
┌Analyzed parameter 1────────
│ ...

Then PSense gives the results for different metrics:

User Specified Disturbance

You can set a value for the disturbance eps. Running the following to set eps to:

psense -f examples/unknown_vending_machine.psi -e 0.01

PSense would add 0.01 to each parameter in this program. It outputs the following:

Function Type:
Continuous
┌Analyzed parameter 1────────────┬─────────────┬─────────┬─────────┐
│         │ Expectation Distance │ KS Distance │ TVD     │ KL      │
├─────────┼──────────────────────┼─────────────┼─────────┼─────────┤
│ Maximum │ 1/4812               │ 0.00031     │ 0.00010 │ 0.00029 │
│         │                      │ 1720698     │ 3906899 │ 9884255 │
│         │                      │ 254 r1      │ 4181213 │ 3219106 │
│         │                      │ -> 0.50     │ 9       │ 3       │
│         │                      │ 0000000     │         │         │
│         │                      │ 000         │         │         │
└─────────┴──────────────────────┴─────────────┴─────────┴─────────┘
...

Notice now that eps becomes a concrete value, PSense directly outputs the numerical distances instead of a symbolic expression containing eps. For KS statistic, PSense further outputs which $r1$ value results in the maximum value.


Return to Tutorials