atoms 30 / 30 runs 1 primary sonnet-46-primer-forestdb
↑↓jk nav · / search
Select an atom from the list →
forestdb-2025-problang-adjectives-qud / atom-1
shape distribution s46 +p TV<.50.251 runs 1/1
per-run
00 prompt

An RSA model combining vague adjectives with QUD uncertainty (Kao et al. hyperbole model + gradable adjectives vagueness model). A pragmatic listener hears "expensive" about a kettle and infers the price and whether the speaker has negative valence.

prices = [50, 500, 1000, 5000, 10000]. pricePrior: categorical({vs:prices, ps:[0.8070, 0.1070, 0.0434, 0.0223, 0.0203]}). valencePrior(state): lookup table {50:0.3173, 500:0.7920, 1000:0.8933, 5000:0.9524, 10000:0.9864}, returns flip(probs[state]). utterances = ["expensive", "notExpensive"]. utterancePrior: uniformDraw(utterances). thetaPrior: uniformDraw(prices). meaning(utterance, price, theta): expensive ? price>=theta : notExpensive ? price<=theta : true. cost(utterance): notExpensive->1, expensive->0. qudFns = {price: state->{price:state.price}, valence: state->{valence:state.valence}, priceValence: state->{price:state.price,valence:state.valence}}. qudPrior: categorical({vs:["price","valence","priceValence"], ps:[1,1,1]}). alpha = 1. literalListener(utterance, qud, theta): Infer, uniformDraw(prices), samples valence, fullState={price,valence}, qudAnswer=qudFns[qud](fullState), conditions on meaning(utterance,price,theta), returns qudAnswer. speaker(fullState, qud, theta): Infer, utterancePrior, factor(alpha*(L0.score(qudAnswer)-cost(utterance))), returns utterance. pragmaticListener(utterance): Infer, samples price from pricePrior, valence from valencePrior(price), qud from qudPrior, theta from thetaPrior, fullState={price,valence}, observes speaker(fullState,qud,theta), returns {price, valence}.

Compute pragmaticListener("expensive"). Return joint distribution over {price, valence}.

system prompt constant across atoms
(system prompt loads here)
WebPPL primer applied to *-primer-* runs
(primer loads here)
01 code comparing GT vs s46 +p
GTground truth
webppl
1// ADJECTIVES + QUD MODEL
2// frankie + shane RSA project
3
4// code adapted from the Kao et al. hyperbole model +
5// gradable adjectives & vagueness resolution model
6
7
8var utterances = ["expensive", "notExpensive"]
9
10var utterancePrior = function() {
11 return uniformDraw(utterances)
12}
13
14var thetaPrior = function() {
15 return uniformDraw(prices)
16}
17
18// theta moderates interpretation of utterances
19var meaning = function(utterance, price, theta) {
20return utterance == "expensive" ? price >= theta :
21 utterance == "notExpensive" ? price <= theta :
22 true
23}
24
25// more words = higher cost
26var cost = function(utterance) {
27 return utterance== 'notExpensive'? 1 :
28 0
29};
30
31var prices = [
32 50,
33 500,
34 1000,
35 5000,
36 10000
37]
38
39var pricePrior = function() {
40 return categorical({
41 vs: prices,
42 ps: [
43 0.8070,
44 0.1070,
45 0.0434,
46 0.0223,
47 0.0203
48 ]
49 })
50}
51
52var valencePrior = function(state) {
53 var probs = {
54 50 : 0.3173,
55 500 : 0.7920,
56 1000 : 0.8933,
57 5000 : 0.9524,
58 10000 : 0.9864
59 }
60 var tf = flip(probs[state])
61 return tf
62}
63
64var qudFns = {
65 price : function(state) {return { price: state.price } },
66 valence : function(state) {return { valence: state.valence } },
67 priceValence : function(state) {
68 return { price: state.price, valence: state.valence }
69 }
70 }
71
72var qudPrior = function() {
73 categorical({
74 vs: ["price", "valence", "priceValence"],
75 ps: [1, 1, 1]
76 })
77}
78
79var literalListener = cache(function(utterance, qud, theta) {
80 return Infer({model: function(){
81 var price = uniformDraw(prices)
82 var valence = valencePrior(price)
83 var fullState = {price, valence}
84 var qudFn = qudFns[qud]
85 var qudAnswer = qudFn(fullState)
86 condition( meaning(utterance, price, theta) )
87 return qudAnswer
88 }
89 })})
90
91// speaker optimality
92var alpha = 1
93
94var speaker = cache(function(fullState, qud, theta) {
95 return Infer({model: function(){
96 var utterance = utterancePrior()
97 var qudFn = qudFns[qud]
98 var qudAnswer = qudFn(fullState)
99 factor(alpha*(literalListener(utterance,qud,theta).score(qudAnswer)
100 - cost(utterance)))
101 return utterance
102 }})
103})
104
105var pragmaticListener = cache(function(utterance) {
106 return Infer({model: function(){
107 //////// priors ////////
108 var price = pricePrior()
109 var valence = valencePrior(price)
110 var qud = qudPrior()
111 var theta = thetaPrior()
112 ////////////////////////
113 var fullState = {price, valence}
114 observe(speaker(fullState, qud, theta), utterance)
115 return {price, valence}
116
117 }})
118})
119
120var listenerPosterior1 = pragmaticListener("expensive")
121var listenerPosterior2 = pragmaticListener('notExpensive')
122
123print('Pragmatic listener hears "expensive":')
124viz(listenerPosterior1)
125print('Pragmatic listener hears "not expensive":')
126viz(listenerPosterior2)
127
128var ANSWER = (pragmaticListener("expensive"));
129
s46 +psonnet-46-primer-forestdbTV<.50.251
webppl
1var prices = [50, 500, 1000, 5000, 10000];
2var pricePrior = Categorical({vs: prices, ps: [0.8070, 0.1070, 0.0434, 0.0223, 0.0203]});
3
4var valenceProbTable = {50: 0.3173, 500: 0.7920, 1000: 0.8933, 5000: 0.9524, 10000: 0.9864};
5var valencePrior = function(state) {
6 return flip(valenceProbTable[state]);
7};
8
9var utterances = ["expensive", "notExpensive"];
10var utterancePrior = function() { return uniformDraw(utterances); };
11
12var thetaPrior = function() { return uniformDraw(prices); };
13
14var meaning = function(utterance, price, theta) {
15 return utterance === "expensive" ? price >= theta :
16 utterance === "notExpensive" ? price <= theta :
17 true;
18};
19
20var cost = function(utterance) {
21 return utterance === "notExpensive" ? 1 : 0;
22};
23
24var qudFns = {
25 price: function(state) { return {price: state.price}; },
26 valence: function(state) { return {valence: state.valence}; },
27 priceValence: function(state) { return {price: state.price, valence: state.valence}; }
28};
29
30var qudPrior = function() {
31 return uniformDraw(["price", "valence", "priceValence"]);
32};
33
34var alpha = 1;
35
36var literalListener = mem(function(utterance, qud, theta) {
37 return Infer({method: 'enumerate'}, function() {
38 var price = sample(pricePrior);
39 var valence = valencePrior(price);
40 var fullState = {price: price, valence: valence};
41 var qudAnswer = qudFns[qud](fullState);
42 condition(meaning(utterance, price, theta));
43 return qudAnswer;
44 });
45});
46
47var speaker = mem(function(fullState, qud, theta) {
48 return Infer({method: 'enumerate'}, function() {
49 var utterance = utterancePrior();
50 var L0 = literalListener(utterance, qud, theta);
51 var qudAnswer = qudFns[qud](fullState);
52 factor(alpha * (L0.score(qudAnswer) - cost(utterance)));
53 return utterance;
54 });
55});
56
57var pragmaticListener = function(utterance) {
58 return Infer({method: 'enumerate'}, function() {
59 var price = sample(pricePrior);
60 var valence = valencePrior(price);
61 var qud = qudPrior();
62 var theta = thetaPrior();
63 var fullState = {price: price, valence: valence};
64 var S1 = speaker(fullState, qud, theta);
65 observe(S1, utterance);
66 return {price: price, valence: valence};
67 });
68};
69
70var ANSWER = pragmaticListener("expensive");
02output overlaydistribution
GT s46 +p10 bins
00.280.280.550.55{"price":10000,"valence":false} A = 0.001 B = 0.000{"price":10000,"valence":false} A = 0.001 B = 0.000{"price":10000,"valence":false}{"price":10000,"valence":true} A = 0.068 B = 0.020{"price":10000,"valence":true} A = 0.068 B = 0.0200.070.02{"price":10000,"valence":true}{"price":5000,"valence":false} A = 0.002 B = 0.001{"price":5000,"valence":false} A = 0.002 B = 0.001{"price":5000,"valence":false}{"price":5000,"valence":true} A = 0.061 B = 0.021{"price":5000,"valence":true} A = 0.061 B = 0.0210.060.02{"price":5000,"valence":true}{"price":1000,"valence":false} A = 0.008 B = 0.005{"price":1000,"valence":false} A = 0.008 B = 0.0050.01{"price":1000,"valence":false}{"price":1000,"valence":true} A = 0.090 B = 0.039{"price":1000,"valence":true} A = 0.090 B = 0.0390.090.04{"price":1000,"valence":true}{"price":500,"valence":false} A = 0.025 B = 0.022{"price":500,"valence":false} A = 0.025 B = 0.0220.030.02{"price":500,"valence":false}{"price":500,"valence":true} A = 0.149 B = 0.085{"price":500,"valence":true} A = 0.149 B = 0.0850.150.08{"price":500,"valence":true}{"price":50,"valence":false} A = 0.300 B = 0.551{"price":50,"valence":false} A = 0.300 B = 0.5510.300.55{"price":50,"valence":false}{"price":50,"valence":true} A = 0.296 B = 0.256{"price":50,"valence":true} A = 0.296 B = 0.2560.300.26{"price":50,"valence":true}
03 other runs 1 total
run flags bucket TV KL actions
sonnet-46-primer-forestdb primary sonnet-4.6 +primer TV<.5 0.251 0.1640 ·
forestdb-2025-problang-teasing / atom-1
shape distribution s46 +p TV<.50.446 runs 1/1
per-run
00 prompt

An RSA model for teasing/insulting language combining non-literal language with antisocial utility. A pragmatic listener hears an utterance and infers the intelligence state of the action, the speaker's phi (epistemic vs. antisocial balance), goal, valence, and arousal.

states = [1,2,3,4] (1=very unintelligent, 4=very intelligent). utterances = ["", "dumb as rocks", "dumb", "f*cking idiot"]. uniformDraw over utterances. literalSemantics lookup table: "" -> [0.25,0.25,0.25,0.25], "dumb as rocks" -> [0.45,0.85,0.20,0.02], "dumb" -> [0.85,0.95,0.02,0.02], "f*cking idiot" -> [0.95,0.55,0.02,0.02]. meaning(utterance, state): flip(literalSemantics[utterance][state-1]). valencePrior(state): 1->flip(0.01)?"good":"bad", 2->flip(0.33)?"good":"bad", 3->flip(0.66)?"good":"bad", 4->flip(0.99)?"good":"bad". arousals = ["low","high"]. arousalPrior(state): 1->categorical([0.1,0.9],arousals), 2->categorical([0.7,0.3],arousals), 3->categorical([0.7,0.3],arousals), 4->categorical([0.1,0.9],arousals). goals = ["goalState","goalValence","goalArousal"]. goalPrior: categorical([1,1,1], goals). goalState(goal, state, valence, arousal): returns state/valence/arousal depending on goal. literalListener(utterance, goal): Infer over uniformDraw(states), conditions on meaning(utterance,state), returns {QUDanswer: goalState(...), state}. lambda = -1.25 (antisocial, negative). valueFunction(s) = lambda * s. alpha = 10. speaker1(state, phi, goal, valence, arousal): Infer over uniformDraw(utterances), epistemic utility = L0_qudAnswerMarginal.score(QUDanswer), antisocial utility = expectation(L0_stateMarginal, valueFunction), speakerUtility = phi*epistemic + (1-phi)*antisocial, factor(alpha*speakerUtility). pragmaticListener(utterance): Infer over uniformDraw(states), valencePrior, arousalPrior, goalPrior, phi=uniformDraw(_.range(0.05,0.95,0.05)), observes speaker1(state,phi,goal,valence,arousal), returns {state, phi, goal, valence, arousal}.

Compute pragmaticListener("dumb as rocks"). Return joint distribution over {state, phi, goal, valence, arousal}.

system prompt constant across atoms
(system prompt loads here)
WebPPL primer applied to *-primer-* runs
(primer loads here)
01 code comparing GT vs s46 +p
GTground truth
webppl
1// Level of intelligence
2var states = [1,2,3,4]
3
4// What can be said
5var utterances = ["", "dumb as rocks", "dumb", "f*cking idiot"]
6
7// Correspondence of utterances to states
8var literalSemantics = {
9 "" : [.25,.25,.25,.25],
10 "dumb as rocks" : [0.45,0.85,0.20,.02],
11 "dumb" : [.85,.95,.02,.02],
12 "f*cking idiot" : [.95,.55,.02,.02]
13}
14
15// Determine whether the utterance describes the state
16// Flip a coin with the literalSemantics weight
17// *state - 1 because of 0-indexing*
18var meaning = function(utterance, state){
19 return flip(literalSemantics[utterance][state - 1]);
20}
21
22// Whether the speaker feels good or bad about the listener's action.
23// Speakers’ attitudes toward the true state of the world (e.g., the valence of their affect), which is modeled simply as a binary positive/negative variable (representing whether or not the speaker is repulsed by the listener’s behavior).
24var valencePrior = function(state) {
25 state === 1 ? flip(0.01) ? "good" : "bad" :
26 state === 2 ? flip(0.33) ? "good" : "bad" :
27 state === 3 ? flip(0.66) ? "good" : "bad" :
28 state === 4 ? flip(0.99) ? "good" : "bad" :
29 true}
30
31// How amplified the speaker feels about the listener being dumb to different degrees.
32var arousals = ["low", "high"]
33
34//How passionate/aroused the listener feels about how intelligent the person is
35var arousalPrior = function(state) {
36 state === 1 ? categorical([0.1, 0.9], arousals) :
37 state === 2 ? categorical([0.7, 0.3], arousals) :
38 state === 3 ? categorical([0.7, 0.3], arousals) :
39 state === 4 ? categorical([0.1, 0.9], arousals) :
40 true
41}
42
43// A list of strings of QUD choices
44var goals = ["goalState", "goalValence", "goalArousal"]
45
46// There are 3 possible goals with a flat prior
47var goalPrior = function() {
48 categorical([1, 1, 1], goals)
49}
50
51// A speaker's goal is satisfied if the listener infers the correct
52// and relevant information.
53var goalState = function(goal, state, valence, arousal) {
54 goal === "goalState" ? state :
55 goal === "goalValence" ? valence :
56 goal === "goalArousal" ? arousal :
57 true
58}
59
60// literal listener
61var literalListener = function(utterance, goal) {
62 Infer({model: function(){
63 var state = uniformDraw(states)
64 var valence = valencePrior(state)
65 var arousal = arousalPrior(state)
66 var m = meaning(utterance, state);
67 condition(m);
68 return {QUDanswer: goalState(goal,state,valence,arousal), state: state}
69 }})
70}
71
72// value function scales social utility by a parameter lambda
73var lambda = -1.25
74var valueFunction = function(s){
75 return lambda * s
76};
77
78var alpha = 10
79var speaker1 = function(state, phi, goal, valence, arousal) {
80 Infer({model: function(){
81 var utterance = uniformDraw(utterances)
82 var QUDanswer = goalState(goal,state,valence,arousal)
83 var L0_posterior = literalListener(utterance,goal)
84 var L0_stateMarginal = marginalize(L0_posterior,"state")
85 var L0_qudAnswerMarginal = marginalize(L0_posterior,"QUDanswer")
86 var utility = {
87 epistemic: L0_qudAnswerMarginal.score(QUDanswer),
88 antisocial: expectation(L0_stateMarginal, valueFunction)
89 }
90 var speakerUtility = phi * utility.epistemic +
91 (1 - phi) * utility.antisocial
92 factor(alpha * speakerUtility)
93 return utterance
94 }})
95}
96
97//pragmatic listener
98var pragmaticListener = function(utterance) {
99 Infer({model: function(){
100 var state = uniformDraw(states)
101 var valence = valencePrior(state)
102 var arousal = arousalPrior(state)
103 var goal = goalPrior()
104//0.05 corresponds to the starting point of phi while 0.95 is the endpoint.
105//The last 0.05 corresponds to the interval length
106 var phi = uniformDraw(_.range(0.05, 0.95, 0.05))
107 var S1 = speaker1(state, phi, goal, valence, arousal)
108 observe(S1, utterance)
109 return { state, phi, goal, valence, arousal }
110 }})
111}
112viz.marginals(pragmaticListener(""))
113viz.marginals(pragmaticListener("dumb as rocks"))
114viz.marginals(pragmaticListener("dumb"))
115viz.marginals(pragmaticListener("f*cking idiot"))
116
117var ANSWER = (pragmaticListener("dumb as rocks"));
118
s46 +psonnet-46-primer-forestdbTV<.50.446
webppl
1var states = [1, 2, 3, 4];
2var utterances = ["", "dumb as rocks", "dumb", "f*cking idiot"];
3
4var literalSemantics = {
5 "": [0.25, 0.25, 0.25, 0.25],
6 "dumb as rocks": [0.45, 0.85, 0.20, 0.02],
7 "dumb": [0.85, 0.95, 0.02, 0.02],
8 "f*cking idiot": [0.95, 0.55, 0.02, 0.02]
9};
10
11var meaning = function(utterance, state) {
12 return flip(literalSemantics[utterance][state - 1]);
13};
14
15var valencePrior = function(state) {
16 return state === 1 ? (flip(0.01) ? "good" : "bad") :
17 state === 2 ? (flip(0.33) ? "good" : "bad") :
18 state === 3 ? (flip(0.66) ? "good" : "bad") :
19 (flip(0.99) ? "good" : "bad");
20};
21
22var arousals = ["low", "high"];
23var arousalPrior = function(state) {
24 return state === 1 ? categorical({vs: arousals, ps: [0.1, 0.9]}) :
25 state === 2 ? categorical({vs: arousals, ps: [0.7, 0.3]}) :
26 state === 3 ? categorical({vs: arousals, ps: [0.7, 0.3]}) :
27 categorical({vs: arousals, ps: [0.1, 0.9]});
28};
29
30var goals = ["goalState", "goalValence", "goalArousal"];
31var goalPrior = function() {
32 return categorical({vs: goals, ps: [1, 1, 1]});
33};
34
35var goalState = function(goal, state, valence, arousal) {
36 return goal === "goalState" ? state :
37 goal === "goalValence" ? valence :
38 arousal;
39};
40
41var literalListener = mem(function(utterance, goal) {
42 return Infer({method: 'enumerate'}, function() {
43 var state = uniformDraw(states);
44 var valence = valencePrior(state);
45 var arousal = arousalPrior(state);
46 condition(meaning(utterance, state));
47 var qudAnswer = goalState(goal, state, valence, arousal);
48 return {QUDanswer: qudAnswer, state: state};
49 });
50});
51
52var lambda = -1.25;
53var valueFunction = function(s) { return lambda * s; };
54var alpha = 10;
55
56var speaker1 = mem(function(state, phi, goal, valence, arousal) {
57 return Infer({method: 'enumerate'}, function() {
58 var utterance = uniformDraw(utterances);
59 var L0 = literalListener(utterance, goal);
60 var qudAnswer = goalState(goal, state, valence, arousal);
61
62 // Epistemic utility: score of the QUD answer under L0
63 var epistemicUtility = L0.score({QUDanswer: qudAnswer, state: state});
64
65 // Antisocial utility: expectation of valueFunction over L0 state marginal
66 var L0stateMarginal = Infer({method: 'enumerate'}, function() {
67 var sample = sample(L0);
68 return sample.state;
69 });
70
71 var antisocialUtility = expectation(L0stateMarginal, valueFunction);
72
73 var speakerUtility = phi * epistemicUtility + (1 - phi) * antisocialUtility;
74 factor(alpha * speakerUtility);
75 return utterance;
76 });
77});
78
79var pragmaticListener = function(utterance) {
80 return Infer({method: 'enumerate'}, function() {
81 var state = uniformDraw(states);
82 var valence = valencePrior(state);
83 var arousal = arousalPrior(state);
84 var goal = goalPrior();
85 var phiVals = _.range(0.05, 0.95, 0.05);
86 var phi = uniformDraw(phiVals);
87
88 var S1 = speaker1(state, phi, goal, valence, arousal);
89 observe(S1, utterance);
90
91 return {state: state, phi: phi, goal: goal, valence: valence, arousal: arousal};
92 });
93};
94
95var ANSWER = pragmaticListener("dumb as rocks");
02output overlaydistribution
GT s46 +p48 bins · top 48 of 75
00.0080.0080.0170.017{"state":3,"phi":0.35,"goal":"goalState","valence":"good","arousal":"low"} A = 0.017 B = 0.013{"state":3,"phi":0.35,"goal":"goalState","valence":"good","arousal":"low"} A = 0.017 B = 0.013{"state":3,"phi":0.35,"goal":"goalState","valence":"good","arousal":"low"}{"state":3,"phi":0.3,"goal":"goalState","valence":"good","arousal":"low"} A = 0.017 B = 0.013{"state":3,"phi":0.3,"goal":"goalState","valence":"good","arousal":"low"} A = 0.017 B = 0.013{"state":3,"phi":0.39999999999999997,"goal":"goalState","valence":"good","arousal":"low"} A = 0.016 B = 0.013{"state":3,"phi":0.39999999999999997,"goal":"goalState","valence":"good","arousal":"low"} A = 0.016 B = 0.013{"state":3,"phi":0.44999999999999996,"goal":"goalState","valence":"good","arousal":"low"} A = 0.015 B = 0.012{"state":3,"phi":0.44999999999999996,"goal":"goalState","valence":"good","arousal":"low"} A = 0.015 B = 0.012{"state":3,"phi":0.25,"goal":"goalState","valence":"good","arousal":"low"} A = 0.015 B = 0.012{"state":3,"phi":0.25,"goal":"goalState","valence":"good","arousal":"low"} A = 0.015 B = 0.012{"state":3,"phi":0.25,"goal":"goalState","valence":"good","arousal":"low"}{"state":4,"phi":0.5499999999999999,"goal":"goalValence","valence":"good","arousal":"high"} A = 0.014 B = 0.000{"state":4,"phi":0.5499999999999999,"goal":"goalValence","valence":"good","arousal":"high"} A = 0.014 B = 0.000{"state":2,"phi":0.9000000000000002,"goal":"goalArousal","valence":"bad","arousal":"low"} A = 0.014 B = 0.008{"state":2,"phi":0.9000000000000002,"goal":"goalArousal","valence":"bad","arousal":"low"} A = 0.014 B = 0.008{"state":3,"phi":0.9000000000000002,"goal":"goalArousal","valence":"good","arousal":"low"} A = 0.014 B = 0.000{"state":3,"phi":0.9000000000000002,"goal":"goalArousal","valence":"good","arousal":"low"} A = 0.014 B = 0.000{"state":3,"phi":0.35,"goal":"goalArousal","valence":"good","arousal":"low"} A = 0.000 B = 0.013{"state":3,"phi":0.35,"goal":"goalArousal","valence":"good","arousal":"low"} A = 0.000 B = 0.013{"state":3,"phi":0.35,"goal":"goalArousal","valence":"good","arousal":"low"}{"state":3,"phi":0.35,"goal":"goalValence","valence":"good","arousal":"low"} A = 0.000 B = 0.013{"state":3,"phi":0.35,"goal":"goalValence","valence":"good","arousal":"low"} A = 0.000 B = 0.013{"state":2,"phi":0.8500000000000002,"goal":"goalArousal","valence":"bad","arousal":"low"} A = 0.013 B = 0.008{"state":2,"phi":0.8500000000000002,"goal":"goalArousal","valence":"bad","arousal":"low"} A = 0.013 B = 0.008{"state":3,"phi":0.3,"goal":"goalArousal","valence":"good","arousal":"low"} A = 0.000 B = 0.013{"state":3,"phi":0.3,"goal":"goalArousal","valence":"good","arousal":"low"} A = 0.000 B = 0.013{"state":3,"phi":0.3,"goal":"goalValence","valence":"good","arousal":"low"} A = 0.000 B = 0.013{"state":3,"phi":0.3,"goal":"goalValence","valence":"good","arousal":"low"} A = 0.000 B = 0.013{"state":3,"phi":0.3,"goal":"goalValence","valence":"good","arousal":"low"}{"state":3,"phi":0.8500000000000002,"goal":"goalArousal","valence":"good","arousal":"low"} A = 0.013 B = 0.000{"state":3,"phi":0.8500000000000002,"goal":"goalArousal","valence":"good","arousal":"low"} A = 0.013 B = 0.000{"state":4,"phi":0.49999999999999994,"goal":"goalValence","valence":"good","arousal":"high"} A = 0.013 B = 0.000{"state":4,"phi":0.49999999999999994,"goal":"goalValence","valence":"good","arousal":"high"} A = 0.013 B = 0.000{"state":4,"phi":0.6,"goal":"goalValence","valence":"good","arousal":"high"} A = 0.013 B = 0.000{"state":4,"phi":0.6,"goal":"goalValence","valence":"good","arousal":"high"} A = 0.013 B = 0.000{"state":3,"phi":0.39999999999999997,"goal":"goalArousal","valence":"good","arousal":"low"} A = 0.000 B = 0.013{"state":3,"phi":0.39999999999999997,"goal":"goalArousal","valence":"good","arousal":"low"} A = 0.000 B = 0.013{"state":3,"phi":0.39999999999999997,"goal":"goalArousal","valence":"good","arousal":"low"}{"state":3,"phi":0.39999999999999997,"goal":"goalValence","valence":"good","arousal":"low"} A = 0.000 B = 0.013{"state":3,"phi":0.39999999999999997,"goal":"goalValence","valence":"good","arousal":"low"} A = 0.000 B = 0.013{"state":2,"phi":0.8000000000000002,"goal":"goalArousal","valence":"bad","arousal":"low"} A = 0.012 B = 0.007{"state":2,"phi":0.8000000000000002,"goal":"goalArousal","valence":"bad","arousal":"low"} A = 0.012 B = 0.007{"state":3,"phi":0.49999999999999994,"goal":"goalState","valence":"good","arousal":"low"} A = 0.012 B = 0.010{"state":3,"phi":0.49999999999999994,"goal":"goalState","valence":"good","arousal":"low"} A = 0.012 B = 0.010{"state":3,"phi":0.8000000000000002,"goal":"goalArousal","valence":"good","arousal":"low"} A = 0.012 B = 0.000{"state":3,"phi":0.8000000000000002,"goal":"goalArousal","valence":"good","arousal":"low"} A = 0.012 B = 0.000{"state":3,"phi":0.8000000000000002,"goal":"goalArousal","valence":"good","arousal":"low"}{"state":3,"phi":0.44999999999999996,"goal":"goalArousal","valence":"good","arousal":"low"} A = 0.000 B = 0.012{"state":3,"phi":0.44999999999999996,"goal":"goalArousal","valence":"good","arousal":"low"} A = 0.000 B = 0.012{"state":3,"phi":0.44999999999999996,"goal":"goalValence","valence":"good","arousal":"low"} A = 0.000 B = 0.012{"state":3,"phi":0.44999999999999996,"goal":"goalValence","valence":"good","arousal":"low"} A = 0.000 B = 0.012{"state":3,"phi":0.25,"goal":"goalArousal","valence":"good","arousal":"low"} A = 0.000 B = 0.012{"state":3,"phi":0.25,"goal":"goalArousal","valence":"good","arousal":"low"} A = 0.000 B = 0.012{"state":3,"phi":0.25,"goal":"goalValence","valence":"good","arousal":"low"} A = 0.000 B = 0.012{"state":3,"phi":0.25,"goal":"goalValence","valence":"good","arousal":"low"} A = 0.000 B = 0.012{"state":3,"phi":0.25,"goal":"goalValence","valence":"good","arousal":"low"}{"state":2,"phi":0.7500000000000001,"goal":"goalArousal","valence":"bad","arousal":"low"} A = 0.011 B = 0.000{"state":2,"phi":0.7500000000000001,"goal":"goalArousal","valence":"bad","arousal":"low"} A = 0.011 B = 0.000{"state":3,"phi":0.7500000000000001,"goal":"goalArousal","valence":"good","arousal":"low"} A = 0.011 B = 0.000{"state":3,"phi":0.7500000000000001,"goal":"goalArousal","valence":"good","arousal":"low"} A = 0.011 B = 0.000{"state":2,"phi":0.9000000000000002,"goal":"goalState","valence":"bad","arousal":"low"} A = 0.011 B = 0.008{"state":2,"phi":0.9000000000000002,"goal":"goalState","valence":"bad","arousal":"low"} A = 0.011 B = 0.008{"state":4,"phi":0.44999999999999996,"goal":"goalValence","valence":"good","arousal":"high"} A = 0.010 B = 0.000{"state":4,"phi":0.44999999999999996,"goal":"goalValence","valence":"good","arousal":"high"} A = 0.010 B = 0.000{"state":4,"phi":0.44999999999999996,"goal":"goalValence","valence":"good","arousal":"high"}{"state":4,"phi":0.65,"goal":"goalValence","valence":"good","arousal":"high"} A = 0.010 B = 0.000{"state":4,"phi":0.65,"goal":"goalValence","valence":"good","arousal":"high"} A = 0.010 B = 0.000{"state":3,"phi":0.49999999999999994,"goal":"goalValence","valence":"good","arousal":"low"} A = 0.007 B = 0.010{"state":3,"phi":0.49999999999999994,"goal":"goalValence","valence":"good","arousal":"low"} A = 0.007 B = 0.010{"state":3,"phi":0.49999999999999994,"goal":"goalArousal","valence":"good","arousal":"low"} A = 0.000 B = 0.010{"state":3,"phi":0.49999999999999994,"goal":"goalArousal","valence":"good","arousal":"low"} A = 0.000 B = 0.010{"state":2,"phi":0.7000000000000001,"goal":"goalArousal","valence":"bad","arousal":"low"} A = 0.010 B = 0.000{"state":2,"phi":0.7000000000000001,"goal":"goalArousal","valence":"bad","arousal":"low"} A = 0.010 B = 0.000{"state":2,"phi":0.7000000000000001,"goal":"goalArousal","valence":"bad","arousal":"low"}{"state":3,"phi":0.7000000000000001,"goal":"goalArousal","valence":"good","arousal":"low"} A = 0.010 B = 0.000{"state":3,"phi":0.7000000000000001,"goal":"goalArousal","valence":"good","arousal":"low"} A = 0.010 B = 0.000{"state":2,"phi":0.8500000000000002,"goal":"goalState","valence":"bad","arousal":"low"} A = 0.009 B = 0.008{"state":2,"phi":0.8500000000000002,"goal":"goalState","valence":"bad","arousal":"low"} A = 0.009 B = 0.008{"state":3,"phi":0.2,"goal":"goalState","valence":"good","arousal":"low"} A = 0.009 B = 0.007{"state":3,"phi":0.2,"goal":"goalState","valence":"good","arousal":"low"} A = 0.009 B = 0.007{"state":3,"phi":0.5499999999999999,"goal":"goalState","valence":"good","arousal":"low"} A = 0.009 B = 0.007{"state":3,"phi":0.5499999999999999,"goal":"goalState","valence":"good","arousal":"low"} A = 0.009 B = 0.007{"state":3,"phi":0.5499999999999999,"goal":"goalState","valence":"good","arousal":"low"}{"state":3,"phi":0.35,"goal":"goalState","valence":"bad","arousal":"low"} A = 0.009 B = 0.007{"state":3,"phi":0.35,"goal":"goalState","valence":"bad","arousal":"low"} A = 0.009 B = 0.007{"state":3,"phi":0.3,"goal":"goalState","valence":"bad","arousal":"low"} A = 0.009 B = 0.007{"state":3,"phi":0.3,"goal":"goalState","valence":"bad","arousal":"low"} A = 0.009 B = 0.007{"state":2,"phi":0.9000000000000002,"goal":"goalValence","valence":"bad","arousal":"low"} A = 0.000 B = 0.008{"state":2,"phi":0.9000000000000002,"goal":"goalValence","valence":"bad","arousal":"low"} A = 0.000 B = 0.008{"state":2,"phi":0.8000000000000002,"goal":"goalState","valence":"bad","arousal":"low"} A = 0.008 B = 0.007{"state":2,"phi":0.8000000000000002,"goal":"goalState","valence":"bad","arousal":"low"} A = 0.008 B = 0.007{"state":2,"phi":0.8000000000000002,"goal":"goalState","valence":"bad","arousal":"low"}{"state":3,"phi":0.39999999999999997,"goal":"goalState","valence":"bad","arousal":"low"} A = 0.008 B = 0.007{"state":3,"phi":0.39999999999999997,"goal":"goalState","valence":"bad","arousal":"low"} A = 0.008 B = 0.007{"state":2,"phi":0.65,"goal":"goalArousal","valence":"bad","arousal":"low"} A = 0.008 B = 0.000{"state":2,"phi":0.65,"goal":"goalArousal","valence":"bad","arousal":"low"} A = 0.008 B = 0.000{"state":3,"phi":0.65,"goal":"goalArousal","valence":"good","arousal":"low"} A = 0.008 B = 0.000{"state":3,"phi":0.65,"goal":"goalArousal","valence":"good","arousal":"low"} A = 0.008 B = 0.000{"state":3,"phi":0.44999999999999996,"goal":"goalState","valence":"bad","arousal":"low"} A = 0.008 B = 0.006{"state":3,"phi":0.44999999999999996,"goal":"goalState","valence":"bad","arousal":"low"} A = 0.008 B = 0.006{"state":3,"phi":0.44999999999999996,"goal":"goalState","valence":"bad","arousal":"low"}{"state":2,"phi":0.8500000000000002,"goal":"goalValence","valence":"bad","arousal":"low"} A = 0.000 B = 0.008{"state":2,"phi":0.8500000000000002,"goal":"goalValence","valence":"bad","arousal":"low"} A = 0.000 B = 0.008{"state":3,"phi":0.25,"goal":"goalState","valence":"bad","arousal":"low"} A = 0.008 B = 0.006{"state":3,"phi":0.25,"goal":"goalState","valence":"bad","arousal":"low"} A = 0.008 B = 0.006{"state":4,"phi":0.39999999999999997,"goal":"goalValence","valence":"good","arousal":"high"} A = 0.007 B = 0.000{"state":4,"phi":0.39999999999999997,"goal":"goalValence","valence":"good","arousal":"high"} A = 0.007 B = 0.000
03 other runs 1 total
run flags bucket TV KL actions
sonnet-46-primer-forestdb primary sonnet-4.6 +primer TV<.5 0.446 1.1242 ·
forestdb-adjectives-qud / atom-1
shape value s46 +p val+ runs 1/1
per-run
00 prompt

Implement the RSA adjectives model with QUD (question under discussion) for ice cream pricing.

Data:

webppl
1var icecream = {
2 prices: [1, 4, 6, 10, 14, 18, 22, 30, 34, 38],
3 probabilities: [0.01, 0.50, 0.85, 0.63, 0.35, 0.10, 0.04, 0.02, 0.02, 0.01]
4};

Helpers: - marginalize(dist, key): Infer over sample(dist)[key] - statePrior(): categorical(icecream.probabilities, icecream.prices) - thetaPrior(): uniformDraw(icecream.prices) - alpha = 1 - utterances = ["expensive", "null", "cheap"] - cost = {"expensive": 1, "cheap": 2, "null": 0} - utterancePrior(): categorical(map(function(u){Math.exp(-cost[u])}, utterances), utterances) - meaning(utterance, price, theta): "expensive" => price >= theta; "cheap" => price <= theta; else true - QUDs = ["expensive?", "less than 15?", "what is the price?"] - QUDPrior(): categorical([0, 0, 1], QUDs) // always returns "what is the price?" - QUDFun(QUD, state): "expensive?" => state >= 15; "less than 15?" => state <= 15; else state - literalListener(utterance, theta, QUD): Infer over statePrior(), condition on meaning, return QUDFun(QUD, price) - speaker(price, theta, QUD): Infer over utterancePrior(), factor alpha * literalListener(utt,theta,QUD).score(QUDFun(QUD,price)), return utt - pragmaticListener(utterance): Infer — sample price, theta, QUD; factor speaker(price,theta,QUD).score(utterance); return {price, theta, qud: QUD}

Bind pragmaticListener to a function of that exact name.

Return the expected price from the pragmaticListener's distribution when hearing 'expensive': expectation(marginalize(pragmaticListener('expensive'), 'price'))

system prompt constant across atoms
(system prompt loads here)
WebPPL primer applied to *-primer-* runs
(primer loads here)
01 code comparing GT vs s46 +p
GTground truth
webppl
1var marginalize = function(dist, key){
2 return Infer( {model: function(){
3 return sample(dist)[key];
4 }})
5};
6///
7
8var icecream = {
9 "prices": [1, 4, 6, 10, 14, 18, 22, 30, 34, 38],
10"probabilities": [0.01, 0.50, 0.85, 0.63, 0.35, 0.10, 0.04, 0.02, 0.02, 0.01]
11};
12
13var statePrior = function() {
14 return categorical(icecream.probabilities, icecream.prices);
15};
16
17var thetaPrior = function() {
18 return uniformDraw(icecream.prices);
19};
20
21var alpha = 1; // optimality parameter
22
23var utterances = ["expensive", "null", "cheap"];
24var cost = {
25 "expensive": 1,
26 "cheap": 2,
27 "null": 0
28};
29var utterancePrior = function() {
30 var uttProbs = map(function(u) {return Math.exp(-cost[u]) }, utterances);
31 return categorical(uttProbs, utterances);
32};
33
34var meaning = function(utterance, price, theta) {
35 utterance == "expensive" ? price >= theta :
36 utterance == "cheap" ? price <= theta :
37 true
38};
39// QUDs
40var QUDs = ["expensive?","less than 15?","what is the price?"]
41var QUDPrior = function() {
42 //uniformDraw(QUDs)
43// categorical([1,10,1],QUDs)// this is equivalent to uniformDraw
44categorical([0,0,1],QUDs)// this is your baseline version
45}
46var QUDFun = function(QUD,state) {
47 QUD == "expensive?" ? state >= 15 :
48 QUD == "less than 15?" ? state <= 15 :
49 state;
50};
51
52var literalListener = cache(function(utterance, theta, QUD) {
53 return Infer({model:function() {
54 var price = statePrior()
55 var qPrice = QUDFun(QUD,price)
56 condition(meaning(utterance, price, theta))
57 return qPrice;
58}})
59});
60
61var speaker = cache(function(price, theta,QUD) {
62 return Infer( {model: function() {
63 var utterance = utterancePrior()
64 var qPrice= QUDFun(QUD, price)
65 factor( alpha * literalListener(utterance, theta, QUD).score(qPrice) );
66 return utterance;
67 }});
68});
69
70var pragmaticListener = function(utterance) {
71 return Infer({model: function() {
72 var price = statePrior()
73 var theta = thetaPrior()
74 var QUD =QUDPrior()
75 factor(speaker(price, theta, QUD).score(utterance));
76 return { price: price, theta: theta, qud: QUD};
77 }})
78}
79
80
81
82print ('cheap icecream')
83var expensiveIcecream = pragmaticListener('expensive');
84print(expectation(marginalize(expensiveIcecream, "price")))
85viz.hist(marginalize(expensiveIcecream, "price"));
86viz.hist(marginalize(expensiveIcecream, "theta"));
87viz.hist(marginalize(expensiveIcecream, "qud"));
88
89var ANSWER = (expectation(marginalize(pragmaticListener('expensive'), 'price')));
90
s46 +psonnet-46-primer-forestdbval+
webppl
1var icecream = {
2 prices: [1, 4, 6, 10, 14, 18, 22, 30, 34, 38],
3 probabilities: [0.01, 0.50, 0.85, 0.63, 0.35, 0.10, 0.04, 0.02, 0.02, 0.01]
4};
5
6var marginalize = function(dist, key) {
7 return Infer({method: 'enumerate'}, function() {
8 return sample(dist)[key];
9 });
10};
11
12var statePrior = function() {
13 return categorical(icecream.probabilities, icecream.prices);
14};
15
16var thetaPrior = function() {
17 return uniformDraw(icecream.prices);
18};
19
20var alpha = 1;
21
22var utterances = ["expensive", "null", "cheap"];
23var cost = {"expensive": 1, "cheap": 2, "null": 0};
24
25var utterancePrior = function() {
26 return categorical(map(function(u) { return Math.exp(-cost[u]); }, utterances), utterances);
27};
28
29var meaning = function(utterance, price, theta) {
30 return utterance === "expensive" ? price >= theta :
31 utterance === "cheap" ? price <= theta :
32 true;
33};
34
35var QUDs = ["expensive?", "less than 15?", "what is the price?"];
36
37var QUDPrior = function() {
38 return categorical([0, 0, 1], QUDs);
39};
40
41var QUDFun = function(QUD, state) {
42 return QUD === "expensive?" ? state >= 15 :
43 QUD === "less than 15?" ? state <= 15 :
44 state;
45};
46
47var literalListener = mem(function(utterance, theta, QUD) {
48 return Infer({method: 'enumerate'}, function() {
49 var price = statePrior();
50 condition(meaning(utterance, price, theta));
51 return QUDFun(QUD, price);
52 });
53});
54
55var speaker = mem(function(price, theta, QUD) {
56 return Infer({method: 'enumerate'}, function() {
57 var utt = utterancePrior();
58 factor(alpha * literalListener(utt, theta, QUD).score(QUDFun(QUD, price)));
59 return utt;
60 });
61});
62
63var pragmaticListener = function(utterance) {
64 return Infer({method: 'enumerate'}, function() {
65 var price = statePrior();
66 var theta = thetaPrior();
67 var QUD = QUDPrior();
68 factor(speaker(price, theta, QUD).score(utterance));
69 return {price: price, theta: theta, qud: QUD};
70 });
71};
72
73var ANSWER = expectation(marginalize(pragmaticListener('expensive'), 'price'));
02outputvalue
GT
12.9027
s46 +p
12.9027
03 other runs 1 total
run flags bucket TV KL actions
sonnet-46-primer-forestdb primary sonnet-4.6 +primer val+ ·
forestdb-astt-metaphor / atom-1
shape distribution s46 +p fail runs 1/1
per-run
00 prompt

A Kao et al. (2014) Rational Speech Act model for metaphor comprehension. Someone says "John is a whale" or "John is a person". The model reasons about what features (large, graceful, majestic) the speaker intends to communicate.

Categories: ["whale", "person"]. categoriesPrior: categorical([0.01, 0.99], categories). Utterances: ["whale", "person"]. utterancePrior: categorical([1,1], utterances). featureSets: all 8 binary combinations of {large, graceful, majestic}. featureSetPrior for "whale": categorical([0.30592786494628, 0.138078454222818, 0.179114768847673, 0.13098781834847, 0.0947267162507846, 0.0531420411185539, 0.0601520520596695, 0.0378702842057509], featureSets). featureSetPrior for "person": categorical([0.11687632453038, 0.105787535267869, 0.11568145784997, 0.130847056136141, 0.15288225956497, 0.128098151176801, 0.114694702836614, 0.135132512637255], featureSets). goals: ["large", "graceful", "majestic"]. goalPrior: categorical([1,1,1], goals). alpha = 3. literalInterpretation(utterance, category): utterance === category. goalState(goal, featureSet): returns featureSet[goal]. literalListener(utterance, goal): Infer over uniformDraw(categories), conditions on literalInterpretation, returns goalState. speaker(large, graceful, majestic, goal): Infer, factors alpha * literalListener(utterance,goal).score(goalState(goal, {large,graceful,majestic})). pragmaticListener(utterance): Infer, samples category from categoriesPrior, featureSet from featureSetPrior(category), extracts large/graceful/majestic, samples goal, observes speaker(large,graceful,majestic,goal), returns {category, large, graceful, majestic}.

Compute pragmaticListener("whale"). Return the full joint distribution over {category, large, graceful, majestic}.

system prompt constant across atoms
(system prompt loads here)
WebPPL primer applied to *-primer-* runs
(primer loads here)
01 code comparing GT vs s46 +p
GTground truth
webppl
1// John could either be a whale or a person.
2var categories = ["whale", "person"]
3
4// It is extremely unlikely that John is actually a whale.
5var categoriesPrior = function() {
6 categorical([0.01, 0.99], categories)
7}
8
9// The speaker could either say "John is a whale" or "John is a person."
10var utterances = ["whale", "person"]
11
12// The utterances are equally costly.
13var utterancePrior = function() {
14 categorical([1,1], utterances)
15}
16
17// The features of John being considered are "large", "graceful",
18// "majestic." Features are binary.
19var featureSets = [
20 {large : 1, graceful : 1, majestic : 1},
21 {large : 1, graceful : 1, majestic : 0},
22 {large : 1, graceful : 0, majestic : 1},
23 {large : 1, graceful : 0, majestic : 0},
24 {large : 0, graceful : 1, majestic : 1},
25 {large : 0, graceful : 1, majestic : 0},
26 {large : 0, graceful : 0, majestic : 1},
27 {large : 0, graceful : 0, majestic : 0}
28]
29
30// information about feature priors (probabilistic world knowledge)
31// obtained by an experimental study (see paper)
32var featureSetPrior = function(category) {
33 category === "whale" ? categorical([0.30592786494628, 0.138078454222818,
34 0.179114768847673, 0.13098781834847,
35 0.0947267162507846, 0.0531420411185539,
36 0.0601520520596695, 0.0378702842057509],
37 featureSets) :
38 category === "person" ? categorical([0.11687632453038, 0.105787535267869,
39 0.11568145784997, 0.130847056136141,
40 0.15288225956497, 0.128098151176801,
41 0.114694702836614, 0.135132512637255],
42 featureSets) :
43 true
44}
45
46// Speaker's possible goals are to communicate feature 1, 2, or 3
47var goals = ["large", "graceful", "majestic"]
48
49// Prior probability of speaker's goal is set to uniform but can
50// change with context/QUD.
51var goalPrior = function() {
52 categorical([1,1,1], goals)
53}
54
55// Speaker optimality parameter
56var alpha = 3
57
58// Check if interpreted category is identical to utterance
59var literalInterpretation = function(utterance, category) {
60 utterance === category
61}
62
63// Check if goal is satisfied
64var goalState = function(goal, featureSet) {
65 goal === "large" ? featureSet.large :
66 goal === "graceful" ? featureSet.graceful :
67 goal === "majestic" ? featureSet.majestic :
68 true
69}
70
71// Define a literal listener
72var literalListener = function(utterance, goal) {
73 Infer({model: function() {
74 var category = uniformDraw(categories)
75 var featureSet = featureSetPrior(category)
76 condition(literalInterpretation(utterance, category))
77 return goalState(goal, featureSet)
78 }})
79}
80
81// Speaker model
82var speaker = function(large, graceful, majestic, goal) {
83 Infer({model: function() {
84 var utterance = utterancePrior()
85 factor(alpha *
86 literalListener(utterance,goal).score(goalState(goal, {large : large, graceful : graceful, majestic : majestic})))
87 return utterance
88 }})
89}
90
91// Define a pragmatic listener
92var pragmaticListener = function(utterance) {
93 Infer({model: function() {
94 var category = categoriesPrior()
95 var featureSet = featureSetPrior(category)
96 var large = featureSet.large
97 var graceful = featureSet.graceful
98 var majestic = featureSet.majestic
99 var goal = goalPrior()
100 observe(speaker(large, graceful, majestic, goal), utterance)
101 return {category, large, graceful, majestic}
102 }})
103}
104
105display("The pragmatic listener's interpretation when the speaker says whale")
106viz.table(pragmaticListener("whale"))
107
108display("The pragmatic listener's interpretation when the speaker says person")
109viz.table(pragmaticListener("person"))
110
111var ANSWER = (pragmaticListener("whale"));
112
s46 +psonnet-46-primer-forestdbfail
execution error
Error: sample() expected a distribution but received "{"large":false,"graceful":false,"majestic":false}".
webppl
1var categories = ["whale", "person"];
2var utterances = ["whale", "person"];
3var alpha = 3;
4
5var featureSets = [
6 {large: true, graceful: true, majestic: true},
7 {large: true, graceful: true, majestic: false},
8 {large: true, graceful: false, majestic: true},
9 {large: true, graceful: false, majestic: false},
10 {large: false, graceful: true, majestic: true},
11 {large: false, graceful: true, majestic: false},
12 {large: false, graceful: false, majestic: true},
13 {large: false, graceful: false, majestic: false}
14];
15
16var whalePriorPs = [0.30592786494628, 0.138078454222818, 0.179114768847673, 0.13098781834847, 0.0947267162507846, 0.0531420411185539, 0.0601520520596695, 0.0378702842057509];
17var personPriorPs = [0.11687632453038, 0.105787535267869, 0.11568145784997, 0.130847056136141, 0.15288225956497, 0.128098151176801, 0.114694702836614, 0.135132512637255];
18
19var goals = ["large", "graceful", "majestic"];
20
21var literalInterpretation = function(utterance, category) {
22 return utterance === category;
23};
24
25var goalState = function(goal, featureSet) {
26 return featureSet[goal];
27};
28
29var literalListener = mem(function(utterance, goal) {
30 return Infer({method: 'enumerate'}, function() {
31 var category = categorical({vs: categories, ps: [0.01, 0.99]});
32 condition(literalInterpretation(utterance, category));
33 return goalState(goal, sample(categorical({vs: featureSets, ps: category === "whale" ? whalePriorPs : personPriorPs})));
34 });
35});
36
37var speaker = mem(function(large, graceful, majestic, goal) {
38 return Infer({method: 'enumerate'}, function() {
39 var utterance = categorical({vs: utterances, ps: [1, 1]});
40 var featureSet = {large: large, graceful: graceful, majestic: majestic};
41 factor(alpha * literalListener(utterance, goal).score(goalState(goal, featureSet)));
42 return utterance;
43 });
44});
45
46var pragmaticListener = function(utterance) {
47 return Infer({method: 'enumerate'}, function() {
48 var category = categorical({vs: categories, ps: [0.01, 0.99]});
49 var featureSet = sample(categorical({vs: featureSets, ps: category === "whale" ? whalePriorPs : personPriorPs}));
50 var large = featureSet.large;
51 var graceful = featureSet.graceful;
52 var majestic = featureSet.majestic;
53 var goal = categorical({vs: goals, ps: [1, 1, 1]});
54 observe(speaker(large, graceful, majestic, goal), utterance);
55 return {category: category, large: large, graceful: graceful, majestic: majestic};
56 });
57};
58
59var ANSWER = pragmaticListener("whale");
02output overlaydistribution
GT s46 +p16 bins
00.090.090.170.17{"category":"person","large":0,"graceful":0,"majestic":0} A = 0.069 B = 0.000{"category":"person","large":0,"graceful":0,"majestic":0} A = 0.069 B = 0.000{"category":"person","large":0,"graceful":0,"majestic":0}{"category":"person","large":0,"graceful":0,"majestic":1} A = 0.092 B = 0.000{"category":"person","large":0,"graceful":0,"majestic":1} A = 0.092 B = 0.000{"category":"person","large":0,"graceful":1,"majestic":0} A = 0.089 B = 0.000{"category":"person","large":0,"graceful":1,"majestic":0} A = 0.089 B = 0.000{"category":"person","large":0,"graceful":1,"majestic":0}{"category":"person","large":0,"graceful":1,"majestic":1} A = 0.151 B = 0.000{"category":"person","large":0,"graceful":1,"majestic":1} A = 0.151 B = 0.000{"category":"person","large":1,"graceful":0,"majestic":0} A = 0.134 B = 0.000{"category":"person","large":1,"graceful":0,"majestic":0} A = 0.134 B = 0.000{"category":"person","large":1,"graceful":0,"majestic":0}{"category":"person","large":1,"graceful":0,"majestic":1} A = 0.151 B = 0.000{"category":"person","large":1,"graceful":0,"majestic":1} A = 0.151 B = 0.000{"category":"person","large":1,"graceful":1,"majestic":0} A = 0.128 B = 0.000{"category":"person","large":1,"graceful":1,"majestic":0} A = 0.128 B = 0.000{"category":"person","large":1,"graceful":1,"majestic":0}{"category":"person","large":1,"graceful":1,"majestic":1} A = 0.175 B = 0.000{"category":"person","large":1,"graceful":1,"majestic":1} A = 0.175 B = 0.000{"category":"whale","large":0,"graceful":0,"majestic":0} A = 0.000 B = 0.000{"category":"whale","large":0,"graceful":0,"majestic":0} A = 0.000 B = 0.000{"category":"whale","large":0,"graceful":0,"majestic":0}{"category":"whale","large":0,"graceful":0,"majestic":1} A = 0.000 B = 0.000{"category":"whale","large":0,"graceful":0,"majestic":1} A = 0.000 B = 0.000{"category":"whale","large":0,"graceful":1,"majestic":0} A = 0.000 B = 0.000{"category":"whale","large":0,"graceful":1,"majestic":0} A = 0.000 B = 0.000{"category":"whale","large":0,"graceful":1,"majestic":0}{"category":"whale","large":0,"graceful":1,"majestic":1} A = 0.001 B = 0.000{"category":"whale","large":0,"graceful":1,"majestic":1} A = 0.001 B = 0.000{"category":"whale","large":1,"graceful":0,"majestic":0} A = 0.001 B = 0.000{"category":"whale","large":1,"graceful":0,"majestic":0} A = 0.001 B = 0.000{"category":"whale","large":1,"graceful":0,"majestic":0}{"category":"whale","large":1,"graceful":0,"majestic":1} A = 0.002 B = 0.000{"category":"whale","large":1,"graceful":0,"majestic":1} A = 0.002 B = 0.000{"category":"whale","large":1,"graceful":1,"majestic":0} A = 0.002 B = 0.000{"category":"whale","large":1,"graceful":1,"majestic":0} A = 0.002 B = 0.000{"category":"whale","large":1,"graceful":1,"majestic":0}{"category":"whale","large":1,"graceful":1,"majestic":1} A = 0.005 B = 0.000{"category":"whale","large":1,"graceful":1,"majestic":1} A = 0.005 B = 0.000
03 other runs 1 total
run flags bucket TV KL actions
sonnet-46-primer-forestdb primary sonnet-4.6 +primer fail ·
forestdb-blm / atom-1
shape distribution s46 +p TV<10.500 runs 1/1
per-run
00 prompt

Implement a simple RSA model for 'Black lives matter' utterance interpretation in WebPPL. The state space is four {black,white} boolean pairs: [{black:true,white:true},{black:true,white:false},{black:false,white:true},{black:false,white:false}] with uniform prior (ps:[.25,.25,.25,.25]). The state prior is a Categorical over these four states. Utterances are uniformDraw(['blm','nblm']). Literal meanings: blm is true when state.black==true; nblm is true when state.black==false. (wlm, alm, nlm are defined but not used in this model — utterancePrior only draws from ['blm','nblm'].) Speaker optimality alpha=1. The literal listener takes utt, samples from statePrior(), conditions on literalMeanings[utt](state), and returns state. The pragmatic speaker takes state, draws utt from utterancePrior, factors by alpha*literalListener(utt).score(state). The pragmatic listener takes utt, samples from statePrior(), observes speaker(state) with utt. Use Infer({method:'enumerate'}) for all. Return the pragmatic listener's distribution when hearing 'blm'.

system prompt constant across atoms
(system prompt loads here)
WebPPL primer applied to *-primer-* runs
(primer loads here)
01 code comparing GT vs s46 +p
GTground truth
webppl
1var alpha = 1
2
3var statePrior = function() {
4 return Categorical({
5 // ps: [.9,.04,.04,.02], // make it a priori likely that all lives matter
6 ps: [.25,.25,.25,.25], // uniform prior
7 // ps: [.04,.04,.9,.02], // make it a priori likely that only white lives matter
8 vs: [{black:true, white:true},{black:true, white:false},{black:false, white:true},{black:false, white:false}]})
9};
10
11// possible utterances
12var utterancePrior = function() {
13 return uniformDraw(['blm', 'nblm'])
14// return uniformDraw(['blm', 'wlm', 'alm', 'nlm'])
15};
16
17// meaning funtion to interpret the utterances
18var literalMeanings = {
19 blm: function(state) { return state["black"] },
20 nblm: function(state) { return !state["black"] },
21 wlm: function(state) { return state["white"]},
22 alm: function(state) { return state["black"] && state["white"] },
23 nlm: function(state) { return !state["black"] && !state["white"] }
24};
25
26// literal listener
27var literalListener = cache(function(utt) {
28 return Infer({method:"enumerate"},
29 function(){
30 var state = sample(statePrior())
31 var meaning = literalMeanings[utt]
32 condition(meaning(state))
33 return state
34 })
35});
36
37// pragmatic speaker
38var speaker = cache(function(state) {
39 return Infer({method:"enumerate"},
40 function(){
41 var utt = utterancePrior()
42 factor(alpha * literalListener(utt).score(state))
43 return utt
44 })
45});
46
47// pragmatic listener
48var pragmaticListener = cache(function(utt) {
49 return Infer({method:"enumerate"},
50 function(){
51 var state = sample(statePrior())
52 observe(speaker(state),utt)
53 return state
54 })
55});
56
57pragmaticListener("blm")
58
59var ANSWER = (pragmaticListener('blm'));
60
s46 +psonnet-46-primer-forestdbTV<10.500
webppl
1var states = [
2 {black: true, white: true},
3 {black: true, white: false},
4 {black: false, white: true},
5 {black: false, white: false}
6];
7
8var statePrior = function() {
9 return sample(Categorical({vs: states, ps: [.25, .25, .25, .25]}));
10};
11
12var utterances = ['blm', 'nblm'];
13
14var utterancePrior = function() {
15 return uniformDraw(utterances);
16};
17
18var literalMeanings = {
19 blm: function(state) { return state.black == true; },
20 nblm: function(state) { return state.black == false; },
21 wlm: function(state) { return state.white == true; },
22 alm: function(state) { return state.black == true || state.white == true; },
23 nlm: function(state) { return state.black == false && state.white == false; }
24};
25
26var alpha = 1;
27
28var literalListener = mem(function(utt) {
29 return Infer({method: 'enumerate'}, function() {
30 var state = statePrior();
31 condition(literalMeanings[utt](state));
32 return state;
33 });
34});
35
36var pragmaticSpeaker = mem(function(state) {
37 return Infer({method: 'enumerate'}, function() {
38 var utt = utterancePrior();
39 factor(alpha * literalListener(utt).score(state));
40 return utt;
41 });
42});
43
44var pragmaticListener = function(utt) {
45 return Infer({method: 'enumerate'}, function() {
46 var state = statePrior();
47 observe(pragmaticSpeaker(state), utt);
48 return state;
49 });
50};
51
52var ANSWER = pragmaticListener('blm');
02output overlaydistribution
GT s46 +p4 bins
00.250.250.500.50{"black":true,"white":false} A = 0.500 B = 0.250{"black":true,"white":false} A = 0.500 B = 0.2500.500.25{"black":true,"white":false}{"black":true,"white":true} A = 0.500 B = 0.250{"black":true,"white":true} A = 0.500 B = 0.2500.500.25{"black":true,"white":true}{"black":false,"white":false} A = 0.000 B = 0.250{"black":false,"white":false} A = 0.000 B = 0.2500.25{"black":false,"white":false}{"black":false,"white":true} A = 0.000 B = 0.250{"black":false,"white":true} A = 0.000 B = 0.2500.25{"black":false,"white":true}
03 other runs 1 total
run flags bucket TV KL actions
sonnet-46-primer-forestdb primary sonnet-4.6 +primer TV<1 0.500 10.4732 ·
forestdb-ccgn-metaphor / atom-1
shape distribution s46 +p TV=11.000 runs 1/1
per-run
00 prompt

A Kao et al. (2014) RSA metaphor model with a context-biased goal prior. Someone says "John is a whale". The speaker's goal prior is biased toward communicating that John is "large" (weight 5) over "graceful" or "majestic" (weight 1 each).

Categories: ["whale", "person"]. categoriesPrior: categorical([0.01, 0.99], categories). Utterances: ["whale", "person"]. utterancePrior: categorical([1,1], utterances). featureSets: all 8 binary combinations of {large, graceful, majestic}. featureSetPrior for "whale": categorical([0.30592786494628, 0.138078454222818, 0.179114768847673, 0.13098781834847, 0.0947267162507846, 0.0531420411185539, 0.0601520520596695, 0.0378702842057509], featureSets). featureSetPrior for "person": categorical([0.11687632453038, 0.105787535267869, 0.11568145784997, 0.130847056136141, 0.15288225956497, 0.128098151176801, 0.114694702836614, 0.135132512637255], featureSets). goals: ["large", "graceful", "majestic"]. goalPrior: categorical([5,1,1], goals) — biased toward "large". alpha = 3. literalInterpretation(utterance, category): utterance === category. goalState(goal, featureSet): returns featureSet[goal]. literalListener(utterance, goal): Infer over uniformDraw(categories), conditions on literalInterpretation, returns goalState. speaker(large, graceful, majestic, goal): Infer, factors alpha * literalListener(utterance,goal).score(goalState(goal, {large,graceful,majestic})). pragmaticListener(utterance): Infer, samples category from categoriesPrior, featureSet from featureSetPrior(category), extracts large/graceful/majestic, samples goal from goalPrior, observes speaker(large,graceful,majestic,goal), returns {category, large, graceful, majestic}.

Compute pragmaticListener("whale"). Return the full joint distribution over {category, large, graceful, majestic}.

system prompt constant across atoms
(system prompt loads here)
WebPPL primer applied to *-primer-* runs
(primer loads here)
01 code comparing GT vs s46 +p
GTground truth
webppl
1// John could either be a whale or a person.
2var categories = ["whale", "person"]
3
4// It is extremely unlikely that John is actually a whale.
5var categoriesPrior = function() {
6 categorical([0.01, 0.99], categories)
7}
8
9// The speaker could either say "John is a whale" or "John is a person."
10var utterances = ["whale", "person"]
11
12// The utterances are equally costly.
13var utterancePrior = function() {
14 categorical([1,1], utterances)
15}
16
17// The features of John being considered are "large", "graceful",
18// "majestic." Features are binary.
19var featureSets = [
20 {large : 1, graceful : 1, majestic : 1},
21 {large : 1, graceful : 1, majestic : 0},
22 {large : 1, graceful : 0, majestic : 1},
23 {large : 1, graceful : 0, majestic : 0},
24 {large : 0, graceful : 1, majestic : 1},
25 {large : 0, graceful : 1, majestic : 0},
26 {large : 0, graceful : 0, majestic : 1},
27 {large : 0, graceful : 0, majestic : 0}
28]
29
30// information about feature priors (probabilistic world knowledge)
31// obtained by an experimental study (see paper)
32var featureSetPrior = function(category) {
33 category === "whale" ? categorical([0.30592786494628, 0.138078454222818,
34 0.179114768847673, 0.13098781834847,
35 0.0947267162507846, 0.0531420411185539,
36 0.0601520520596695, 0.0378702842057509],
37 featureSets) :
38 category === "person" ? categorical([0.11687632453038, 0.105787535267869,
39 0.11568145784997, 0.130847056136141,
40 0.15288225956497, 0.128098151176801,
41 0.114694702836614, 0.135132512637255],
42 featureSets) :
43 true
44}
45
46// Speaker's possible goals are to communicate feature 1, 2, or 3
47var goals = ["large", "graceful", "majestic"]
48
49//// Prior probability of speaker's goal is set to uniform but can
50//// change with context/QUD.
51var goalPrior = function() {
52 categorical([5,1,1], goals)
53}
54// var goalPrior = function() {
55// categorical([1,5,1], goals)
56// }
57// var goalPrior = function() {
58// categorical([1,1,5], goals)
59// }
60
61// Speaker optimality parameter
62var alpha = 3
63
64// Check if interpreted category is identical to utterance
65var literalInterpretation = function(utterance, category) {
66 utterance === category
67}
68
69// Check if goal is satisfied
70var goalState = function(goal, featureSet) {
71 goal === "large" ? featureSet.large :
72 goal === "graceful" ? featureSet.graceful :
73 goal === "majestic" ? featureSet.majestic :
74 true
75}
76
77// Define a literal listener
78var literalListener = function(utterance, goal) {
79 Infer({model: function() {
80 var category = uniformDraw(categories)
81 var featureSet = featureSetPrior(category)
82 condition(literalInterpretation(utterance, category))
83 return goalState(goal, featureSet)
84 }})
85}
86
87// Speaker model
88var speaker = function(large, graceful, majestic, goal) {
89 Infer({model: function() {
90 var utterance = utterancePrior()
91 factor(alpha *
92 literalListener(utterance,goal).score(goalState(goal, {large : large, graceful : graceful, majestic : majestic})))
93 return utterance
94 }})
95}
96
97// Define a pragmatic listener
98var pragmaticListener = function(utterance) {
99 Infer({model: function() {
100 var category = categoriesPrior()
101 var featureSet = featureSetPrior(category)
102 var large = featureSet.large
103 var graceful = featureSet.graceful
104 var majestic = featureSet.majestic
105 var goal = goalPrior()
106 observe(speaker(large, graceful, majestic, goal), utterance)
107 return {category, large, graceful, majestic}
108 }})
109}
110
111viz.table(pragmaticListener("whale"))
112
113var ANSWER = (pragmaticListener("whale"));
114
s46 +psonnet-46-primer-forestdbTV=11.000
webppl
1var categories = ["whale", "person"];
2var utterances = ["whale", "person"];
3
4var featureSets = [
5 {large: true, graceful: true, majestic: true},
6 {large: true, graceful: true, majestic: false},
7 {large: true, graceful: false, majestic: true},
8 {large: true, graceful: false, majestic: false},
9 {large: false, graceful: true, majestic: true},
10 {large: false, graceful: true, majestic: false},
11 {large: false, graceful: false, majestic: true},
12 {large: false, graceful: false, majestic: false}
13];
14
15var whalePriorPs = [0.30592786494628, 0.138078454222818, 0.179114768847673, 0.13098781834847, 0.0947267162507846, 0.0531420411185539, 0.0601520520596695, 0.0378702842057509];
16var personPriorPs = [0.11687632453038, 0.105787535267869, 0.11568145784997, 0.130847056136141, 0.15288225956497, 0.128098151176801, 0.114694702836614, 0.135132512637255];
17
18var goals = ["large", "graceful", "majestic"];
19
20var alpha = 3;
21
22var literalInterpretation = function(utterance, category) {
23 return utterance === category;
24};
25
26var goalState = function(goal, featureSet) {
27 return featureSet[goal];
28};
29
30var literalListener = mem(function(utterance, goal) {
31 return Infer({method: 'enumerate'}, function() {
32 var category = categorical({vs: categories, ps: [0.01, 0.99]});
33 condition(literalInterpretation(utterance, category));
34 return goalState(goal, uniformDraw(featureSets));
35 });
36});
37
38var speaker = mem(function(large, graceful, majestic, goal) {
39 return Infer({method: 'enumerate'}, function() {
40 var utterance = categorical({vs: utterances, ps: [1, 1]});
41 var featureSet = {large: large, graceful: graceful, majestic: majestic};
42 var gs = goalState(goal, featureSet);
43 factor(alpha * literalListener(utterance, goal).score(gs));
44 return utterance;
45 });
46});
47
48var pragmaticListener = function(utterance) {
49 return Infer({method: 'enumerate'}, function() {
50 var category = categorical({vs: categories, ps: [0.01, 0.99]});
51 var featureSetPs = category === "whale" ? whalePriorPs : personPriorPs;
52 var featureSet = categorical({vs: featureSets, ps: featureSetPs});
53 var large = featureSet.large;
54 var graceful = featureSet.graceful;
55 var majestic = featureSet.majestic;
56 var goal = categorical({vs: goals, ps: [5, 1, 1]});
57 observe(speaker(large, graceful, majestic, goal), utterance);
58 return {category: category, large: large, graceful: graceful, majestic: majestic};
59 });
60};
61
62var ANSWER = pragmaticListener("whale");
02output overlaydistribution
GT s46 +p32 bins
00.100.100.200.20{"category":"person","large":0,"graceful":0,"majestic":0} A = 0.047 B = 0.000{"category":"person","large":0,"graceful":0,"majestic":0} A = 0.047 B = 0.000{"category":"person","large":0,"graceful":0,"majestic":0}{"category":"person","large":0,"graceful":0,"majestic":1} A = 0.054 B = 0.000{"category":"person","large":0,"graceful":0,"majestic":1} A = 0.054 B = 0.000{"category":"person","large":0,"graceful":1,"majestic":0} A = 0.055 B = 0.000{"category":"person","large":0,"graceful":1,"majestic":0} A = 0.055 B = 0.000{"category":"person","large":0,"graceful":1,"majestic":1} A = 0.085 B = 0.000{"category":"person","large":0,"graceful":1,"majestic":1} A = 0.085 B = 0.000{"category":"person","large":0,"graceful":1,"majestic":1}{"category":"person","large":1,"graceful":0,"majestic":0} A = 0.194 B = 0.000{"category":"person","large":1,"graceful":0,"majestic":0} A = 0.194 B = 0.000{"category":"person","large":1,"graceful":0,"majestic":1} A = 0.187 B = 0.000{"category":"person","large":1,"graceful":0,"majestic":1} A = 0.187 B = 0.000{"category":"person","large":1,"graceful":1,"majestic":0} A = 0.166 B = 0.000{"category":"person","large":1,"graceful":1,"majestic":0} A = 0.166 B = 0.000{"category":"person","large":1,"graceful":1,"majestic":0}{"category":"person","large":1,"graceful":1,"majestic":1} A = 0.198 B = 0.000{"category":"person","large":1,"graceful":1,"majestic":1} A = 0.198 B = 0.000{"category":"whale","large":0,"graceful":0,"majestic":0} A = 0.000 B = 0.000{"category":"whale","large":0,"graceful":0,"majestic":0} A = 0.000 B = 0.000{"category":"whale","large":0,"graceful":0,"majestic":1} A = 0.000 B = 0.000{"category":"whale","large":0,"graceful":0,"majestic":1} A = 0.000 B = 0.000{"category":"whale","large":0,"graceful":0,"majestic":1}{"category":"whale","large":0,"graceful":1,"majestic":0} A = 0.000 B = 0.000{"category":"whale","large":0,"graceful":1,"majestic":0} A = 0.000 B = 0.000{"category":"whale","large":0,"graceful":1,"majestic":1} A = 0.001 B = 0.000{"category":"whale","large":0,"graceful":1,"majestic":1} A = 0.001 B = 0.000{"category":"whale","large":1,"graceful":0,"majestic":0} A = 0.002 B = 0.000{"category":"whale","large":1,"graceful":0,"majestic":0} A = 0.002 B = 0.000{"category":"whale","large":1,"graceful":0,"majestic":0}{"category":"whale","large":1,"graceful":0,"majestic":1} A = 0.003 B = 0.000{"category":"whale","large":1,"graceful":0,"majestic":1} A = 0.003 B = 0.000{"category":"whale","large":1,"graceful":1,"majestic":0} A = 0.002 B = 0.000{"category":"whale","large":1,"graceful":1,"majestic":0} A = 0.002 B = 0.000{"category":"whale","large":1,"graceful":1,"majestic":1} A = 0.005 B = 0.000{"category":"whale","large":1,"graceful":1,"majestic":1} A = 0.005 B = 0.000{"category":"whale","large":1,"graceful":1,"majestic":1}{"category":"person","large":false,"graceful":false,"majestic":false} A = 0.000 B = 0.134{"category":"person","large":false,"graceful":false,"majestic":false} A = 0.000 B = 0.134{"category":"person","large":false,"graceful":false,"majestic":true} A = 0.000 B = 0.114{"category":"person","large":false,"graceful":false,"majestic":true} A = 0.000 B = 0.114{"category":"person","large":false,"graceful":true,"majestic":false} A = 0.000 B = 0.127{"category":"person","large":false,"graceful":true,"majestic":false} A = 0.000 B = 0.127{"category":"person","large":false,"graceful":true,"majestic":false}{"category":"person","large":false,"graceful":true,"majestic":true} A = 0.000 B = 0.151{"category":"person","large":false,"graceful":true,"majestic":true} A = 0.000 B = 0.151{"category":"person","large":true,"graceful":false,"majestic":false} A = 0.000 B = 0.130{"category":"person","large":true,"graceful":false,"majestic":false} A = 0.000 B = 0.130{"category":"person","large":true,"graceful":false,"majestic":true} A = 0.000 B = 0.115{"category":"person","large":true,"graceful":false,"majestic":true} A = 0.000 B = 0.115{"category":"person","large":true,"graceful":false,"majestic":true}{"category":"person","large":true,"graceful":true,"majestic":false} A = 0.000 B = 0.105{"category":"person","large":true,"graceful":true,"majestic":false} A = 0.000 B = 0.105{"category":"person","large":true,"graceful":true,"majestic":true} A = 0.000 B = 0.116{"category":"person","large":true,"graceful":true,"majestic":true} A = 0.000 B = 0.116{"category":"whale","large":false,"graceful":false,"majestic":false} A = 0.000 B = 0.000{"category":"whale","large":false,"graceful":false,"majestic":false} A = 0.000 B = 0.000{"category":"whale","large":false,"graceful":false,"majestic":false}{"category":"whale","large":false,"graceful":false,"majestic":true} A = 0.000 B = 0.001{"category":"whale","large":false,"graceful":false,"majestic":true} A = 0.000 B = 0.001{"category":"whale","large":false,"graceful":true,"majestic":false} A = 0.000 B = 0.001{"category":"whale","large":false,"graceful":true,"majestic":false} A = 0.000 B = 0.001{"category":"whale","large":false,"graceful":true,"majestic":true} A = 0.000 B = 0.001{"category":"whale","large":false,"graceful":true,"majestic":true} A = 0.000 B = 0.001{"category":"whale","large":false,"graceful":true,"majestic":true}{"category":"whale","large":true,"graceful":false,"majestic":false} A = 0.000 B = 0.001{"category":"whale","large":true,"graceful":false,"majestic":false} A = 0.000 B = 0.001{"category":"whale","large":true,"graceful":false,"majestic":true} A = 0.000 B = 0.002{"category":"whale","large":true,"graceful":false,"majestic":true} A = 0.000 B = 0.002{"category":"whale","large":true,"graceful":true,"majestic":false} A = 0.000 B = 0.001{"category":"whale","large":true,"graceful":true,"majestic":false} A = 0.000 B = 0.001{"category":"whale","large":true,"graceful":true,"majestic":false}{"category":"whale","large":true,"graceful":true,"majestic":true} A = 0.000 B = 0.003{"category":"whale","large":true,"graceful":true,"majestic":true} A = 0.000 B = 0.003
03 other runs 1 total
run flags bucket TV KL actions
sonnet-46-primer-forestdb primary sonnet-4.6 +primer TV=1 1.000 20.8984 ·
forestdb-cnqr-comparison-class / atom-1
shape distribution s46 +p TV<.055.6e-16 runs 1/1
per-run
00 prompt

A Tessler et al. (2017) RSA comparison-class model for gradable adjectives. A pragmatic listener hears "tall" and knows the person is a basketball player. They infer whether "tall" is relative to all people (superordinate) or to basketball players (subordinate).

binParam = 3. superordinate_params = {mu: 0, sigma: 1}. stateVals: _.range(-3, 3, 1/3) (18 values). stateProbs(stateParams): map over stateVals, exp(Gaussian(stateParams).score(s)). generateStatePrior(stateParams): Infer categorical({vs: stateVals, ps: stateProbs(stateParams)}). thresholdBins: {positive: stateVals - 1/6, negative: stateVals + 1/6}. thresholdPrior(form): uniformDraw(thresholdBins[form]). subParams = {gymnasts: {mu:-1, sigma:0.5}, soccerPlayers: {mu:0, sigma:0.5}, basketballPlayers: {mu:1, sigma:0.5}}. utterances = ["tall", "short", "silence"]. meaning(utterance, state, thresholds): tall ? state > thresholds.tall : short ? state < thresholds.short : true. classPrior: uniformDraw(["subordinate", "superordinate"]). alpha = 5. literalListener(utterance, thresholds, comparisonClass): Infer, samples state from generateStatePrior(comparisonClass), conditions on meaning, returns state. cache 10000. speaker1(state, thresholds, comparisonClass): Infer, uniformDraw(utterances), factor(alpha * L0.score(state)), returns utterance. cache 10000. pragmaticListener(utterance, subordinate_params): Infer, samples state from generateStatePrior(subordinate_params), samples thresholds {tall: thresholdPrior("positive"), short: thresholdPrior("negative")}, samples c from classPrior, comparisonClass = c=="subordinate" ? subordinate_params : superordinate_params, observes speaker1, returns {comparisonClass: c, state}. cache 10000.

Compute marginalize(pragmaticListener("tall", subParams["basketballPlayers"]), "comparisonClass"). Return the marginal distribution over comparisonClass.

system prompt constant across atoms
(system prompt loads here)
WebPPL primer applied to *-primer-* runs
(primer loads here)
01 code comparing GT vs s46 +p
GTground truth
webppl
1///fold:
2// helper function
3var exp = function(x){return Math.exp(x)}
4
5// for discretization
6var binParam = 3;
7
8// information about the superordinate category prior
9// e.g., the height distribution for all people
10var superordinate_params = {mu: 0, sigma: 1};
11
12// calculate the range in pre-defined steps;
13// these values correspond to possible heights
14var stateVals = _.range(superordinate_params.mu - 3 * superordinate_params.sigma,
15 superordinate_params.mu + 3 * superordinate_params.sigma,
16 superordinate_params.sigma/binParam)
17
18// for each possible height, calculate its probability of occurrence
19var stateProbs = cache(function(stateParams){
20 return map(function(s){
21 exp(Gaussian(stateParams).score(s))
22 }, stateVals)
23});
24
25// generate a statePrior using the possible heights and their probabilities
26var generateStatePrior = cache(function(stateParams) {
27 return Infer({
28 model: function(){
29 return categorical({vs: stateVals, ps: stateProbs(stateParams)})
30 }
31 })
32});
33
34// generate the uniform threshold prior
35var thresholdBins ={
36 positive: map(function(x){
37 return x - (1/(binParam*2));
38 }, sort(stateVals)),
39 negative: map(function(x){
40 return x + (1/(binParam*2));
41 }, sort(stateVals))
42};
43
44var thresholdPrior = cache(function(form){
45 return Infer({
46 model: function() { return uniformDraw(thresholdBins[form]) }
47 });
48});
49
50// information about the superordinate category priors
51var subParams = {
52 gymnasts: {mu: -1, sigma: 0.5}, // gymnast heights
53 soccerPlayers: {mu: 0, sigma: 0.5}, // soccer player heights
54 basketballPlayers: {mu: 1, sigma: 0.5} // basketball player heights
55}
56
57// possible utterances can be either positive (tall) or negative (short) or a null utterance
58var utterances = ["tall", "short", "silence"]
59
60// meaning function for utterances
61var meaning = function(utterance, state, thresholds) {
62 utterance == "tall" ? state > thresholds.tall :
63 utterance == "short" ? state < thresholds.short :
64 true
65}
66
67// assume a uniform prior over comparison classes
68var classPrior = Infer({
69 model: function(){return uniformDraw(["subordinate", "superordinate"])}
70});
71
72// set speaker optimality
73var alpha = 5;
74
75var literalListener = cache(
76 function(utterance, thresholds, comparisonClass) {
77 Infer({model: function(){
78 var StatePrior = generateStatePrior(comparisonClass)
79 var state = sample(StatePrior);
80 var m = meaning(utterance, state, thresholds);
81 condition(m);
82 return state;
83 }})
84 }, 10000 // limit cache size
85)
86
87var speaker1 = cache(
88 function(state, thresholds, comparisonClass) {
89 Infer({model: function(){
90 var utterance = uniformDraw(utterances);
91 var L0 = literalListener(utterance, thresholds, comparisonClass);
92 factor( alpha * L0.score(state) );
93 return utterance;
94 }})
95 }, 10000 // limit cache size
96)
97///
98
99var pragmaticListener = cache(function(utterance, subordinate_params) {
100 Infer({model: function(){
101
102 var statePrior = generateStatePrior(subordinate_params);
103 var state = sample(statePrior);
104 // separate thresholds for positive adjective and negative adjective
105 var thresholds = {
106 tall: sample(thresholdPrior("positive")),
107 short: sample(thresholdPrior("negative"))
108 }
109
110 // uncertainty about the comparison class (superordinate vs. subordinate)
111 var c = sample(classPrior)
112 var comparisonClass = c == "subordinate" ? subordinate_params : superordinate_params
113
114 var S1 = speaker1(state, thresholds, comparisonClass);
115 observe(S1, utterance);
116
117 return { comparisonClass: c, state : state }
118 }})
119}, 10000 // limit cache size
120 )
121
122var ANSWER = (marginalize(pragmaticListener("tall", subParams["basketballPlayers"]), "comparisonClass"));
123
s46 +psonnet-46-primer-forestdbTV<.055.6e-16
webppl
1var binParam = 3;
2var superordinate_params = {mu: 0, sigma: 1};
3var stateVals = _.range(-3, 3, 1/3);
4
5var stateProbs = function(stateParams) {
6 return map(function(s) {
7 return Math.exp(Gaussian({mu: stateParams.mu, sigma: stateParams.sigma}).score(s));
8 }, stateVals);
9};
10
11var generateStatePrior = function(stateParams) {
12 return Infer({method: 'enumerate'}, function() {
13 return sample(Categorical({vs: stateVals, ps: stateProbs(stateParams)}));
14 });
15};
16
17var thresholdBins = {
18 positive: map(function(s) { return s - 1/6; }, stateVals),
19 negative: map(function(s) { return s + 1/6; }, stateVals)
20};
21
22var thresholdPrior = function(form) {
23 return uniformDraw(thresholdBins[form]);
24};
25
26var subParams = {
27 gymnasts: {mu: -1, sigma: 0.5},
28 soccerPlayers: {mu: 0, sigma: 0.5},
29 basketballPlayers: {mu: 1, sigma: 0.5}
30};
31
32var utterances = ["tall", "short", "silence"];
33
34var meaning = function(utterance, state, thresholds) {
35 return utterance === "tall" ? state > thresholds.tall :
36 utterance === "short" ? state < thresholds.short :
37 true;
38};
39
40var alpha = 5;
41
42var literalListener = mem(function(utterance, thresholds, comparisonClass) {
43 return Infer({method: 'enumerate'}, function() {
44 var state = sample(generateStatePrior(comparisonClass));
45 condition(meaning(utterance, state, thresholds));
46 return state;
47 });
48}, 10000);
49
50var speaker1 = mem(function(state, thresholds, comparisonClass) {
51 return Infer({method: 'enumerate'}, function() {
52 var utterance = uniformDraw(utterances);
53 var L0 = literalListener(utterance, thresholds, comparisonClass);
54 factor(alpha * L0.score(state));
55 return utterance;
56 });
57}, 10000);
58
59var pragmaticListener = mem(function(utterance, subordinate_params) {
60 return Infer({method: 'enumerate'}, function() {
61 var state = sample(generateStatePrior(subordinate_params));
62 var thresholds = {
63 tall: thresholdPrior("positive"),
64 short: thresholdPrior("negative")
65 };
66 var c = uniformDraw(["subordinate", "superordinate"]);
67 var comparisonClass = c === "subordinate" ? subordinate_params : superordinate_params;
68 var S1 = speaker1(state, thresholds, comparisonClass);
69 observe(S1, utterance);
70 return {comparisonClass: c, state: state};
71 });
72}, 10000);
73
74var result = pragmaticListener("tall", subParams["basketballPlayers"]);
75var marginal = marginalize(result, "comparisonClass");
76
77var ANSWER = marginal;
02output overlaydistribution
GT s46 +p2 bins
00.290.290.580.58superordinate A = 0.581 B = 0.581superordinate A = 0.581 B = 0.5810.580.58superordinatesubordinate A = 0.419 B = 0.419subordinate A = 0.419 B = 0.4190.420.42subordinate
03 other runs 1 total
run flags bucket TV KL actions
sonnet-46-primer-forestdb primary sonnet-4.6 +primer TV<.05 5.6e-16 -0.0000 ·
forestdb-codenames / atom-1
shape distribution s46 +p TV<.051.4e-16 runs 1/1
per-run
00 prompt

Implement an RSA model for the Codenames word game using GloVe vector similarity as the meaning function.

Helper: the following word vectors (25-dimensional) are given:

webppl
1var vectors = {
2 eagle: Vector([-0.8186906894583743, -0.8443627918594182, -0.04304780086785447, -0.8257634263841377, -0.7607218950809542, 0.47786735164930183, 0.36942709316422206, 0.18560148725224498, 0.38625176009619944, 0.24384273963053932, 1.0355862286322068, -0.14170089242313555, -0.17017960843359828, 0.27636172471279313, -0.49477465481497807, -1.199206930890509, 1.0531720839078256, -0.5154875303291531, 0.30704269353337016, 1.5382356443196483, -0.13215425501400774, 1.2222507503066664, 1.3819617662995949, -1.1579407453927437, 0.9439311306043343]),
3 pig: Vector([-0.9027808771549458, -1.4539105978263833, 0.5743098399154295, 1.3052815987119957, -0.038556210348244704, -0.22144102997326148, 1.222050088622139, -0.027526643946408857, -0.13265827668708097, 1.4799207507145387, 0.02371336629548181, -0.9405402658175948, 0.06556493358788004, -1.6556208133885402, -0.44306373689318584, -0.475710035110901, 1.2435716830499404, -1.0677780309283533, -0.03344465447168945, 0.16184568683816827, 0.8718035460475897, 2.082956682688621, 0.47430271385843953, -0.4479993650378608, 1.5192928553678355]),
4 chicken: Vector([-0.9555633717916903, -0.23467550895948608, 0.9081102168032618, 1.7681919864431317, -0.3888166871286516, 1.2292398003323308, 1.0624961440319318, -0.3558803892040966, -0.17024423658814317, 0.7046776782991592, 1.624196256505183, -1.1423231844008523, -0.9490267652945451, -1.8004114037674281, -0.026086280368055388, -2.089757256612839, 3.5660566372328693, -2.4178611093952225, -0.7077960662621875, 0.9418434965990246, 0.438927172322575, 1.0891725023940724, -0.1237861204326181, 0.7602054634506068, 3.0515580696224083]),
5 farm: Vector([-1.3191469349030631, -0.34747873883058705, 0.09525267994894762, 0.08014872654330456, 0.1179814806966339, -0.26926061020753783, 0.709033965954239, -0.6521777385143812, 1.0195239553589313, 0.7192612109870958, 1.1711460976059695, -1.0779079866249233, -0.5443503049555966, 0.08523251153754875, 0.1455530206584687, -1.501097375488643, 1.1151234505440395, 0.0581591541412683, -0.1102242123027589, 0.5253857581277014, 0.21780949510893402, 0.026030837039037417, 0.07282095318396448, -0.6093002665622598, 2.0466066458317336]),
6 animal: Vector([-0.08132595025854601, -1.8280616716238214, -0.4241550049238374, 1.3405833261217683, 1.3635302219051426, 0.19656106954281044, 1.0553637657141577, 0.8640316722860499, -0.34682275265131135, 0.27196141799987644, 0.9785603157742483, -3.1767493003780873, -0.7566904249011203, -1.1935303767007424, 0.2523177522167622, 0.33414675815038736, 0.21147820292953767, 0.2089073521353749, 0.36413859545070626, -0.3145854077725169, 0.8470589609352164, 0.8914477422324714, 0.06602846837066885, -1.1974184866543685, 1.6807019645814638]),
7 bird: Vector([0.9317828273959833, -1.142927450658389, 1.1249556341704339, 0.7533022372085103, 0.039221572709652965, 0.5302815428039684, 1.1525754405638204, 0.5707370610821617, 0.01803607760778035, 0.9527229145321762, 1.0851468114908822, -0.4626041548552341, -0.5371489443168416, -0.8343285842461913, -0.09713481034287788, 0.8070233789520264, 0.21755780815430825, -0.6588132708557186, -0.7963193188039507, 0.12395864485237663, -0.18545774404118467, 1.311026289715281, 0.7764007851264465, -0.5776179488468618, 0.5640559901962993])
8};

Meaning function: for a clue and a list of two words, compute the Euclidean distance between each word's vector and the clue vector, pass 1/distance through sigmoid, flip on that probability, return true iff all flips are true.

Priors: - wordsPrior(): uniformDraw over [["chicken","eagle"],["eagle","pig"],["chicken","pig"]] - cluePrior(): uniformDraw over ["farm","animal","bird"] - alpha = 1

RSA chain: - literalListener(clue): Infer over wordsPrior(), condition on meaning(clue, randomSubset), return randomSubset - speaker(subset): Infer over cluePrior(), factor alpha * literalListener(clue).score(subset), return clue - pragmaticListener(clue): Infer over wordsPrior(), observe speaker(randomSubset) given clue, return randomSubset

Bind pragmaticListener to a function of that exact name.

Return the pragmaticListener distribution for the clue "farm": pragmaticListener("farm")

system prompt constant across atoms
(system prompt loads here)
WebPPL primer applied to *-primer-* runs
(primer loads here)
01 code comparing GT vs s46 +p
GTground truth
webppl
1///fold: vectors
2var vectors = {eagle : Vector([-0.8186906894583743, -0.8443627918594182,
3 -0.04304780086785447, -0.8257634263841377,
4 -0.7607218950809542, 0.47786735164930183,
5 0.36942709316422206, 0.18560148725224498,
6 0.38625176009619944, 0.24384273963053932,
7 1.0355862286322068, -0.14170089242313555,
8 -0.17017960843359828, 0.27636172471279313,
9 -0.49477465481497807, -1.199206930890509,
10 1.0531720839078256, -0.5154875303291531,
11 0.30704269353337016, 1.5382356443196483,
12 -0.13215425501400774, 1.2222507503066664,
13 1.3819617662995949, -1.1579407453927437,
14 0.9439311306043343]),
15 pig: Vector([-0.9027808771549458, -1.4539105978263833,
16 0.5743098399154295, 1.3052815987119957,
17 -0.038556210348244704, -0.22144102997326148,
18 1.222050088622139, -0.027526643946408857,
19 -0.13265827668708097, 1.4799207507145387,
20 0.02371336629548181, -0.9405402658175948,
21 0.06556493358788004, -1.6556208133885402,
22 -0.44306373689318584, -0.475710035110901,
23 1.2435716830499404, -1.0677780309283533,
24 -0.03344465447168945, 0.16184568683816827,
25 0.8718035460475897, 2.082956682688621,
26 0.47430271385843953, -0.4479993650378608,
27 1.5192928553678355]),
28 chicken: Vector([-0.9555633717916903, -0.23467550895948608,
29 0.9081102168032618, 1.7681919864431317,
30 -0.3888166871286516, 1.2292398003323308,
31 1.0624961440319318, -0.3558803892040966,
32 -0.17024423658814317, 0.7046776782991592,
33 1.624196256505183, -1.1423231844008523,
34 -0.9490267652945451, -1.8004114037674281,
35 -0.026086280368055388, -2.089757256612839,
36 3.5660566372328693, -2.4178611093952225,
37 -0.7077960662621875, 0.9418434965990246,
38 0.438927172322575, 1.0891725023940724,
39 -0.1237861204326181, 0.7602054634506068,
40 3.0515580696224083]),
41 farm: Vector([-1.3191469349030631, -0.34747873883058705,
42 0.09525267994894762, 0.08014872654330456,
43 0.1179814806966339, -0.26926061020753783,
44 0.709033965954239, -0.6521777385143812,
45 1.0195239553589313, 0.7192612109870958,
46 1.1711460976059695, -1.0779079866249233,
47 -0.5443503049555966, 0.08523251153754875,
48 0.1455530206584687, -1.501097375488643,
49 1.1151234505440395, 0.0581591541412683,
50 -0.1102242123027589, 0.5253857581277014,
51 0.21780949510893402, 0.026030837039037417,
52 0.07282095318396448, -0.6093002665622598,
53 2.0466066458317336]),
54 animal: Vector([-0.08132595025854601, -1.8280616716238214,
55 -0.4241550049238374, 1.3405833261217683,
56 1.3635302219051426, 0.19656106954281044,
57 1.0553637657141577, 0.8640316722860499,
58 -0.34682275265131135, 0.27196141799987644,
59 0.9785603157742483, -3.1767493003780873,
60 -0.7566904249011203, -1.1935303767007424,
61 0.2523177522167622, 0.33414675815038736,
62 0.21147820292953767, 0.2089073521353749,
63 0.36413859545070626, -0.3145854077725169,
64 0.8470589609352164, 0.8914477422324714,
65 0.06602846837066885, -1.1974184866543685,
66 1.6807019645814638]),
67 bird: Vector([0.9317828273959833, -1.142927450658389,
68 1.1249556341704339, 0.7533022372085103,
69 0.039221572709652965, 0.5302815428039684,
70 1.1525754405638204, 0.5707370610821617,
71 0.01803607760778035, 0.9527229145321762,
72 1.0851468114908822, -0.4626041548552341,
73 -0.5371489443168416, -0.8343285842461913,
74 -0.09713481034287788, 0.8070233789520264,
75 0.21755780815430825, -0.6588132708557186,
76 -0.7963193188039507, 0.12395864485237663,
77 -0.18545774404118467, 1.311026289715281,
78 0.7764007851264465, -0.5776179488468618,
79 0.5640559901962993])
80};
81///
82
83var meaning = function(clue, words) {
84
85 var distance = function(vector1, vector2)
86 {
87 var squared = map(function(tuple)
88 {
89 return (tuple[0] - tuple[1])*(tuple[0] - tuple[1]);
90 }
91 , zip(ad.tensor.toScalars(vector1), ad.tensor.toScalars(vector2))
92 );
93
94
95 var answer = Math.sqrt(sum(squared));
96 return answer;
97 };
98
99 var sigmoid = function(num)
100 {
101 return 1/(1 + Math.exp(-1*num));
102 };
103
104 var trueFalse = function(clue, word)
105 {
106 var dist = distance(vectors[clue], vectors[word]);
107 var prob = sigmoid(1/dist);
108 return flip(prob);
109 };
110
111 var wordsVectors = map(function(word) {return trueFalse(clue, word);}, words);
112
113
114 return all(function(s) {return s;}, wordsVectors);
115};
116
117var wordsPrior = function()
118{
119 var pairs = [["chicken", "eagle"], ["eagle", "pig"], ["chicken", "pig"]];
120 return uniformDraw(pairs);
121};
122
123var cluePrior = function()
124{
125 return uniformDraw(["farm", "animal", "bird"]);
126};
127
128
129var literalListener = function(clue)
130{
131 Infer(function()
132 {
133 var randomSubset = wordsPrior();
134 var uttTruthVal = meaning(clue, randomSubset);
135 condition(uttTruthVal);
136 return randomSubset;
137 }
138 )
139};
140
141var alpha = 1;
142
143var speaker = function(subset)
144{
145 Infer(function()
146 {
147 var clue = cluePrior();
148 factor(alpha*literalListener(clue).score(subset));
149 return clue;
150 }
151 )
152};
153
154var pragmaticListener = function(clue)
155{
156 Infer(function()
157 {
158 var randomSubset = wordsPrior();
159 var s1 = speaker(randomSubset);
160 observe(s1, clue);
161 return randomSubset;
162 }
163 )
164};
165
166viz.table(pragmaticListener("farm"));
167
168var ANSWER = (pragmaticListener("farm"));
169
s46 +psonnet-46-primer-forestdbTV<.051.4e-16
webppl
1var vectors = {
2 eagle: Vector([-0.8186906894583743, -0.8443627918594182, -0.04304780086785447, -0.8257634263841377, -0.7607218950809542, 0.47786735164930183, 0.36942709316422206, 0.18560148725224498, 0.38625176009619944, 0.24384273963053932, 1.0355862286322068, -0.14170089242313555, -0.17017960843359828, 0.27636172471279313, -0.49477465481497807, -1.199206930890509, 1.0531720839078256, -0.5154875303291531, 0.30704269353337016, 1.5382356443196483, -0.13215425501400774, 1.2222507503066664, 1.3819617662995949, -1.1579407453927437, 0.9439311306043343]),
3 pig: Vector([-0.9027808771549458, -1.4539105978263833, 0.5743098399154295, 1.3052815987119957, -0.038556210348244704, -0.22144102997326148, 1.222050088622139, -0.027526643946408857, -0.13265827668708097, 1.4799207507145387, 0.02371336629548181, -0.9405402658175948, 0.06556493358788004, -1.6556208133885402, -0.44306373689318584, -0.475710035110901, 1.2435716830499404, -1.0677780309283533, -0.03344465447168945, 0.16184568683816827, 0.8718035460475897, 2.082956682688621, 0.47430271385843953, -0.4479993650378608, 1.5192928553678355]),
4 chicken: Vector([-0.9555633717916903, -0.23467550895948608, 0.9081102168032618, 1.7681919864431317, -0.3888166871286516, 1.2292398003323308, 1.0624961440319318, -0.3558803892040966, -0.17024423658814317, 0.7046776782991592, 1.624196256505183, -1.1423231844008523, -0.9490267652945451, -1.8004114037674281, -0.026086280368055388, -2.089757256612839, 3.5660566372328693, -2.4178611093952225, -0.7077960662621875, 0.9418434965990246, 0.438927172322575, 1.0891725023940724, -0.1237861204326181, 0.7602054634506068, 3.0515580696224083]),
5 farm: Vector([-1.3191469349030631, -0.34747873883058705, 0.09525267994894762, 0.08014872654330456, 0.1179814806966339, -0.26926061020753783, 0.709033965954239, -0.6521777385143812, 1.0195239553589313, 0.7192612109870958, 1.1711460976059695, -1.0779079866249233, -0.5443503049555966, 0.08523251153754875, 0.1455530206584687, -1.501097375488643, 1.1151234505440395, 0.0581591541412683, -0.1102242123027589, 0.5253857581277014, 0.21780949510893402, 0.026030837039037417, 0.07282095318396448, -0.6093002665622598, 2.0466066458317336]),
6 animal: Vector([-0.08132595025854601, -1.8280616716238214, -0.4241550049238374, 1.3405833261217683, 1.3635302219051426, 0.19656106954281044, 1.0553637657141577, 0.8640316722860499, -0.34682275265131135, 0.27196141799987644, 0.9785603157742483, -3.1767493003780873, -0.7566904249011203, -1.1935303767007424, 0.2523177522167622, 0.33414675815038736, 0.21147820292953767, 0.2089073521353749, 0.36413859545070626, -0.3145854077725169, 0.8470589609352164, 0.8914477422324714, 0.06602846837066885, -1.1974184866543685, 1.6807019645814638]),
7 bird: Vector([0.9317828273959833, -1.142927450658389, 1.1249556341704339, 0.7533022372085103, 0.039221572709652965, 0.5302815428039684, 1.1525754405638204, 0.5707370610821617, 0.01803607760778035, 0.9527229145321762, 1.0851468114908822, -0.4626041548552341, -0.5371489443168416, -0.8343285842461913, -0.09713481034287788, 0.8070233789520264, 0.21755780815430825, -0.6588132708557186, -0.7963193188039507, 0.12395864485237663, -0.18545774404118467, 1.311026289715281, 0.7764007851264465, -0.5776179488468618, 0.5640559901962993])
8};
9
10var euclideanDistance = function(v1, v2) {
11 var diff = T.sub(v1, v2);
12 var sq = T.mul(diff, diff);
13 var sumSq = T.sumreduce(sq);
14 return Math.sqrt(sumSq);
15};
16
17var sigmoid = function(x) {
18 return 1 / (1 + Math.exp(-x));
19};
20
21var meaning = function(clue, words) {
22 var clueVec = vectors[clue];
23 var allTrue = all(function(word) {
24 var wordVec = vectors[word];
25 var dist = euclideanDistance(clueVec, wordVec);
26 var p = sigmoid(1 / dist);
27 return flip(p);
28 }, words);
29 return allTrue;
30};
31
32var wordSets = [["chicken","eagle"],["eagle","pig"],["chicken","pig"]];
33var clues = ["farm","animal","bird"];
34var alpha = 1;
35
36var wordsPrior = function() {
37 return uniformDraw(wordSets);
38};
39
40var cluePrior = function() {
41 return uniformDraw(clues);
42};
43
44var literalListener = mem(function(clue) {
45 return Infer({method: 'enumerate'}, function() {
46 var words = wordsPrior();
47 condition(meaning(clue, words));
48 return words;
49 });
50});
51
52var speaker = mem(function(subset) {
53 return Infer({method: 'enumerate'}, function() {
54 var clue = cluePrior();
55 factor(alpha * literalListener(clue).score(subset));
56 return clue;
57 });
58});
59
60var pragmaticListener = function(clue) {
61 return Infer({method: 'enumerate'}, function() {
62 var words = wordsPrior();
63 observe(speaker(words), clue);
64 return words;
65 });
66};
67
68var ANSWER = pragmaticListener("farm");
02output overlaydistribution
GT s46 +p3 bins
00.170.170.340.34["chicken","pig"] A = 0.328 B = 0.328["chicken","pig"] A = 0.328 B = 0.3280.330.33["chicken","pig"]["eagle","pig"] A = 0.333 B = 0.333["eagle","pig"] A = 0.333 B = 0.3330.330.33["eagle","pig"]["chicken","eagle"] A = 0.338 B = 0.338["chicken","eagle"] A = 0.338 B = 0.3380.340.34["chicken","eagle"]
03 other runs 1 total
run flags bucket TV KL actions
sonnet-46-primer-forestdb primary sonnet-4.6 +primer TV<.05 1.4e-16 -0.0000 ·
forestdb-dickson-speaker-cost / atom-1
shape distribution s46 +p TV=00.000 runs 1/1
per-run
00 prompt

Implement an RSA model where the pragmatic listener jointly infers the intended object and the speaker's cost parameter in WebPPL. Objects are: [{color:'blue',shape:'square',string:'blue square'},{color:'blue',shape:'circle',string:'blue circle'},{color:'green',shape:'square',string:'green square'}]. objectPrior() = uniformDraw(objects).string. Utterances are ['blue','green','square','circle','blue square','blue circle','green square']. meaning(utterance,obj) = _.includes(obj, utterance). The cost function takes (utterance, costParameter): count the number of words in the utterance (split by space), multiply by costParameter. costParameterPrior() = uniformDraw(_.range(0.05, 5, 0.5)). Literal listener takes utterance, samples obj from objectPrior(), conditions on meaning(utterance,obj), returns obj. Speaker (alpha=1) takes (obj, costParameter): uniformDraw(utterances), factors by alpha*(literalListener(utterance).score(obj) - cost(utterance,costParameter)). Pragmatic listener takes utterance: samples obj from objectPrior() and costParameter from costParameterPrior(), observes speaker(obj,costParameter). Return the pragmatic listener's joint distribution over {obj,costParameter} when hearing 'blue'.

system prompt constant across atoms
(system prompt loads here)
WebPPL primer applied to *-primer-* runs
(primer loads here)
01 code comparing GT vs s46 +p
GTground truth
webppl
1// set of states
2var objects = [{color: "blue", shape: "square", string: "blue square"},
3 {color: "blue", shape: "circle", string: "blue circle"},
4 {color: "green", shape: "square", string: "green square"}]
5
6// prior over world states
7var objectPrior = function() {
8 var obj = uniformDraw(objects)
9 return obj.string
10}
11
12// set of utterances
13var utterances = ["blue", "green", "square", "circle",
14 "blue square", "blue circle", "green square"]
15
16// utterance cost function
17var cost = function(utterance, costParameter) {
18 var numWords = function(utterance) {
19 var split = utterance.split(" ")
20 return _.size(split)
21 }
22 return costParameter*numWords(utterance)
23};
24
25var costParameterPrior = function() {
26 return uniformDraw(_.range(0.05, 5, 0.5))
27}
28
29// meaning function to interpret the utterances
30var meaning = function(utterance, obj){
31 _.includes(obj, utterance)
32}
33
34// literal listener
35var literalListener = function(utterance){
36 Infer({model: function(){
37 var obj = objectPrior();
38 condition(meaning(utterance, obj))
39 return obj
40 }})
41}
42
43// set speaker optimality
44var alpha = 1
45
46// pragmatic speaker
47var speaker = function(obj,costParameter){
48 Infer({model: function(){
49 var utterance = uniformDraw(utterances)
50 factor(alpha * (literalListener(utterance).score(obj) -
51 cost(utterance,costParameter)))
52 return utterance
53 }})
54}
55
56// pragmatic listener
57var pragmaticListener = function(utterance){
58 Infer({model: function(){
59 var obj = objectPrior()
60 var costParameter = costParameterPrior()
61 observe(speaker(obj,costParameter),utterance)
62 return {obj, costParameter}
63 }})
64}
65
66
67display("cost parameter prior")
68viz(Infer(costParameterPrior))
69
70var listenerPosteriorBlue = pragmaticListener("blue")
71display("pragmatic listener hears \"blue\"")
72viz.table(marginalize(listenerPosteriorBlue, "obj"))
73viz(marginalize(listenerPosteriorBlue, "costParameter"))
74
75var listenerPosteriorBlueSquare = pragmaticListener("blue square")
76display("pragmatic listener hears \"blue square\"")
77viz.table(marginalize(listenerPosteriorBlueSquare, "obj"))
78viz(marginalize(listenerPosteriorBlueSquare, "costParameter"))
79
80var ANSWER = (pragmaticListener('blue'));
81
s46 +psonnet-46-primer-forestdbTV=00.000
webppl
1var objects = [
2 {color: 'blue', shape: 'square', string: 'blue square'},
3 {color: 'blue', shape: 'circle', string: 'blue circle'},
4 {color: 'green', shape: 'square', string: 'green square'}
5];
6
7var utterances = ['blue', 'green', 'square', 'circle', 'blue square', 'blue circle', 'green square'];
8
9var objectPrior = function() {
10 return uniformDraw(objects).string;
11};
12
13var meaning = function(utterance, obj) {
14 return _.includes(obj, utterance);
15};
16
17var cost = function(utterance, costParameter) {
18 return utterance.split(' ').length * costParameter;
19};
20
21var costParameterPrior = function() {
22 return uniformDraw(_.range(0.05, 5, 0.5));
23};
24
25var alpha = 1;
26
27var literalListener = mem(function(utterance) {
28 return Infer({method: 'enumerate'}, function() {
29 var obj = objectPrior();
30 condition(meaning(utterance, obj));
31 return obj;
32 });
33});
34
35var speaker = mem(function(obj, costParameter) {
36 return Infer({method: 'enumerate'}, function() {
37 var utterance = uniformDraw(utterances);
38 factor(alpha * (literalListener(utterance).score(obj) - cost(utterance, costParameter)));
39 return utterance;
40 });
41});
42
43var pragmaticListener = function(utterance) {
44 return Infer({method: 'enumerate'}, function() {
45 var obj = objectPrior();
46 var costParameter = costParameterPrior();
47 observe(speaker(obj, costParameter), utterance);
48 return {obj: obj, costParameter: costParameter};
49 });
50};
51
52var ANSWER = pragmaticListener('blue');
02output overlaydistribution
GT s46 +p20 bins
00.0350.0350.0690.069{"obj":"blue circle","costParameter":4.55} A = 0.046 B = 0.046{"obj":"blue circle","costParameter":4.55} A = 0.046 B = 0.046{"obj":"blue circle","costParameter":4.55}{"obj":"blue circle","costParameter":4.05} A = 0.046 B = 0.046{"obj":"blue circle","costParameter":4.05} A = 0.046 B = 0.046{"obj":"blue circle","costParameter":3.55} A = 0.046 B = 0.046{"obj":"blue circle","costParameter":3.55} A = 0.046 B = 0.046{"obj":"blue circle","costParameter":3.55}{"obj":"blue circle","costParameter":3.05} A = 0.045 B = 0.045{"obj":"blue circle","costParameter":3.05} A = 0.045 B = 0.045{"obj":"blue circle","costParameter":2.55} A = 0.044 B = 0.044{"obj":"blue circle","costParameter":2.55} A = 0.044 B = 0.044{"obj":"blue circle","costParameter":2.55}{"obj":"blue circle","costParameter":2.05} A = 0.043 B = 0.043{"obj":"blue circle","costParameter":2.05} A = 0.043 B = 0.043{"obj":"blue circle","costParameter":1.55} A = 0.041 B = 0.041{"obj":"blue circle","costParameter":1.55} A = 0.041 B = 0.041{"obj":"blue circle","costParameter":1.55}{"obj":"blue circle","costParameter":1.05} A = 0.038 B = 0.038{"obj":"blue circle","costParameter":1.05} A = 0.038 B = 0.038{"obj":"blue circle","costParameter":0.55} A = 0.034 B = 0.034{"obj":"blue circle","costParameter":0.55} A = 0.034 B = 0.034{"obj":"blue circle","costParameter":0.55}{"obj":"blue circle","costParameter":0.05} A = 0.029 B = 0.029{"obj":"blue circle","costParameter":0.05} A = 0.029 B = 0.029{"obj":"blue square","costParameter":4.55} A = 0.069 B = 0.069{"obj":"blue square","costParameter":4.55} A = 0.069 B = 0.069{"obj":"blue square","costParameter":4.55}{"obj":"blue square","costParameter":4.05} A = 0.069 B = 0.069{"obj":"blue square","costParameter":4.05} A = 0.069 B = 0.069{"obj":"blue square","costParameter":3.55} A = 0.068 B = 0.068{"obj":"blue square","costParameter":3.55} A = 0.068 B = 0.068{"obj":"blue square","costParameter":3.55}{"obj":"blue square","costParameter":3.05} A = 0.067 B = 0.067{"obj":"blue square","costParameter":3.05} A = 0.067 B = 0.067{"obj":"blue square","costParameter":2.55} A = 0.065 B = 0.065{"obj":"blue square","costParameter":2.55} A = 0.065 B = 0.065{"obj":"blue square","costParameter":2.55}{"obj":"blue square","costParameter":2.05} A = 0.062 B = 0.062{"obj":"blue square","costParameter":2.05} A = 0.062 B = 0.062{"obj":"blue square","costParameter":1.55} A = 0.058 B = 0.058{"obj":"blue square","costParameter":1.55} A = 0.058 B = 0.058{"obj":"blue square","costParameter":1.55}{"obj":"blue square","costParameter":1.05} A = 0.052 B = 0.052{"obj":"blue square","costParameter":1.05} A = 0.052 B = 0.052{"obj":"blue square","costParameter":0.55} A = 0.044 B = 0.044{"obj":"blue square","costParameter":0.55} A = 0.044 B = 0.044{"obj":"blue square","costParameter":0.55}{"obj":"blue square","costParameter":0.05} A = 0.036 B = 0.036{"obj":"blue square","costParameter":0.05} A = 0.036 B = 0.036
03 other runs 1 total
run flags bucket TV KL actions
sonnet-46-primer-forestdb primary sonnet-4.6 +primer TV=0 0.000 0.0000 ·
forestdb-generics / atom-1
shape distribution s46 +p TV<.055.4e-17 runs 1/1
per-run
00 prompt

Implement a prior model for generic language in WebPPL. The prevalence space is a discretized range: bins = _.range(0.01, 1, 0.025) (these are the possible prevalence values). Define a DiscreteBeta(g, d) function that creates a Categorical distribution over bins using the Beta PDF: for each x in bins, weight is x^(g*d-1) * (1-x)^((1-g)*d-1). Use cache for DiscreteBeta. Define priorModel(params) as an Infer over: sample potential, prevalenceWhenPresent (g), and concentrationWhenPresent (d) from params; flip(potential) selects between sample(DiscreteBeta(g,d)) and sample(DiscreteBeta(0.01,100)); return {prevalence: prevalence}. Call priorModel with params {potential:0.3, prevalenceWhenPresent:0.5, concentrationWhenPresent:10} (representing a 'lays eggs' prior). Return the resulting distribution.

system prompt constant across atoms
(system prompt loads here)
WebPPL primer applied to *-primer-* runs
(primer loads here)
01 code comparing GT vs s46 +p
GTground truth
webppl
1///fold:
2// discretized range between 0 - 1
3var bins = _.range(0.01, 1, 0.025);
4
5// function returns a discretized Beta distribution
6var DiscreteBeta = cache(function(g, d){
7 var a = g * d, b = (1-g) * d;
8 var betaPDF = function(x){
9 return Math.pow(x, a-1)*Math.pow((1-x), b-1)
10 }
11 var probs = map(betaPDF, bins);
12 return Categorical({vs: bins, ps: probs})
13})
14///
15var priorModel = function(params){
16 Infer({model: function(){
17
18 var potential = params["potential"]
19 var g = params["prevalenceWhenPresent"]
20 var d = params["concentrationWhenPresent"]
21
22 var StableDistribution = DiscreteBeta(g, d)
23 var UnstableDistribution = DiscreteBeta(0.01, 100)
24
25 var prevalence = flip(potential) ?
26 sample(StableDistribution) :
27 sample(UnstableDistribution)
28
29 return {prevalence}
30
31 }})
32}
33
34// e.g. "Lays eggs"
35viz(priorModel({
36 potential: 0.3,
37 prevalenceWhenPresent: 0.5, // how prevalent under the stable cause
38 concentrationWhenPresent: 10 // the inverse-variance of the stable cause
39}))
40
41var ANSWER = (priorModel({potential: 0.3, prevalenceWhenPresent: 0.5, concentrationWhenPresent: 10}));
42
s46 +psonnet-46-primer-forestdbTV<.055.4e-17
webppl
1var bins = _.range(0.01, 1, 0.025);
2
3var DiscreteBeta = cache(function(g, d) {
4 var weights = map(function(x) {
5 return Math.pow(x, g * d - 1) * Math.pow(1 - x, (1 - g) * d - 1);
6 }, bins);
7 var totalWeight = sum(weights);
8 var ps = map(function(w) { return w / totalWeight; }, weights);
9 return Categorical({vs: bins, ps: ps});
10});
11
12var priorModel = function(params) {
13 return Infer({method: 'enumerate'}, function() {
14 var potential = sample(Bernoulli({p: params.potential}));
15 var g = params.prevalenceWhenPresent;
16 var d = params.concentrationWhenPresent;
17 var prevalence = potential ?
18 sample(DiscreteBeta(g, d)) :
19 sample(DiscreteBeta(0.01, 100));
20 return {prevalence: prevalence};
21 });
22};
23
24var ANSWER = priorModel({
25 potential: 0.3,
26 prevalenceWhenPresent: 0.5,
27 concentrationWhenPresent: 10
28});
02output overlaydistribution
GT s46 +p40 bins
00.320.320.640.64{"prevalence":0.9850000000000007} A = 0.000 B = 0.000{"prevalence":0.9850000000000007} A = 0.000 B = 0.000{"prevalence":0.9850000000000007}{"prevalence":0.9600000000000006} A = 0.000 B = 0.000{"prevalence":0.9600000000000006} A = 0.000 B = 0.000{"prevalence":0.9350000000000006} A = 0.000 B = 0.000{"prevalence":0.9350000000000006} A = 0.000 B = 0.000{"prevalence":0.9100000000000006} A = 0.000 B = 0.000{"prevalence":0.9100000000000006} A = 0.000 B = 0.000{"prevalence":0.9100000000000006}{"prevalence":0.8850000000000006} A = 0.001 B = 0.001{"prevalence":0.8850000000000006} A = 0.001 B = 0.001{"prevalence":0.8600000000000005} A = 0.001 B = 0.001{"prevalence":0.8600000000000005} A = 0.001 B = 0.001{"prevalence":0.8350000000000005} A = 0.002 B = 0.002{"prevalence":0.8350000000000005} A = 0.002 B = 0.002{"prevalence":0.8350000000000005}{"prevalence":0.8100000000000005} A = 0.003 B = 0.003{"prevalence":0.8100000000000005} A = 0.003 B = 0.003{"prevalence":0.7850000000000005} A = 0.004 B = 0.004{"prevalence":0.7850000000000005} A = 0.004 B = 0.004{"prevalence":0.7600000000000005} A = 0.005 B = 0.005{"prevalence":0.7600000000000005} A = 0.005 B = 0.005{"prevalence":0.7600000000000005}{"prevalence":0.7350000000000004} A = 0.007 B = 0.007{"prevalence":0.7350000000000004} A = 0.007 B = 0.007{"prevalence":0.7100000000000004} A = 0.008 B = 0.008{"prevalence":0.7100000000000004} A = 0.008 B = 0.008{"prevalence":0.6850000000000004} A = 0.010 B = 0.010{"prevalence":0.6850000000000004} A = 0.010 B = 0.010{"prevalence":0.6850000000000004}{"prevalence":0.6600000000000004} A = 0.012 B = 0.012{"prevalence":0.6600000000000004} A = 0.012 B = 0.012{"prevalence":0.6350000000000003} A = 0.014 B = 0.014{"prevalence":0.6350000000000003} A = 0.014 B = 0.014{"prevalence":0.6100000000000003} A = 0.015 B = 0.015{"prevalence":0.6100000000000003} A = 0.015 B = 0.015{"prevalence":0.6100000000000003}{"prevalence":0.5850000000000003} A = 0.016 B = 0.016{"prevalence":0.5850000000000003} A = 0.016 B = 0.016{"prevalence":0.5600000000000003} A = 0.017 B = 0.017{"prevalence":0.5600000000000003} A = 0.017 B = 0.017{"prevalence":0.5350000000000003} A = 0.018 B = 0.018{"prevalence":0.5350000000000003} A = 0.018 B = 0.018{"prevalence":0.5350000000000003}{"prevalence":0.5100000000000002} A = 0.018 B = 0.018{"prevalence":0.5100000000000002} A = 0.018 B = 0.018{"prevalence":0.4850000000000002} A = 0.018 B = 0.018{"prevalence":0.4850000000000002} A = 0.018 B = 0.018{"prevalence":0.4600000000000002} A = 0.018 B = 0.018{"prevalence":0.4600000000000002} A = 0.018 B = 0.018{"prevalence":0.4600000000000002}{"prevalence":0.43500000000000016} A = 0.017 B = 0.017{"prevalence":0.43500000000000016} A = 0.017 B = 0.017{"prevalence":0.41000000000000014} A = 0.016 B = 0.016{"prevalence":0.41000000000000014} A = 0.016 B = 0.016{"prevalence":0.3850000000000001} A = 0.015 B = 0.015{"prevalence":0.3850000000000001} A = 0.015 B = 0.015{"prevalence":0.3850000000000001}{"prevalence":0.3600000000000001} A = 0.013 B = 0.013{"prevalence":0.3600000000000001} A = 0.013 B = 0.013{"prevalence":0.3350000000000001} A = 0.012 B = 0.012{"prevalence":0.3350000000000001} A = 0.012 B = 0.012{"prevalence":0.31000000000000005} A = 0.010 B = 0.010{"prevalence":0.31000000000000005} A = 0.010 B = 0.010{"prevalence":0.31000000000000005}{"prevalence":0.28500000000000003} A = 0.008 B = 0.008{"prevalence":0.28500000000000003} A = 0.008 B = 0.008{"prevalence":0.26} A = 0.006 B = 0.006{"prevalence":0.26} A = 0.006 B = 0.006{"prevalence":0.235} A = 0.005 B = 0.005{"prevalence":0.235} A = 0.005 B = 0.005{"prevalence":0.235}{"prevalence":0.21} A = 0.004 B = 0.004{"prevalence":0.21} A = 0.004 B = 0.004{"prevalence":0.185} A = 0.002 B = 0.002{"prevalence":0.185} A = 0.002 B = 0.002{"prevalence":0.16} A = 0.002 B = 0.002{"prevalence":0.16} A = 0.002 B = 0.002{"prevalence":0.16}{"prevalence":0.135} A = 0.001 B = 0.001{"prevalence":0.135} A = 0.001 B = 0.001{"prevalence":0.11000000000000001} A = 0.000 B = 0.000{"prevalence":0.11000000000000001} A = 0.000 B = 0.000{"prevalence":0.085} A = 0.000 B = 0.000{"prevalence":0.085} A = 0.000 B = 0.000{"prevalence":0.085}{"prevalence":0.060000000000000005} A = 0.004 B = 0.004{"prevalence":0.060000000000000005} A = 0.004 B = 0.004{"prevalence":0.035} A = 0.052 B = 0.052{"prevalence":0.035} A = 0.052 B = 0.052{"prevalence":0.01} A = 0.643 B = 0.643{"prevalence":0.01} A = 0.643 B = 0.643{"prevalence":0.01}
03 other runs 1 total
run flags bucket TV KL actions
sonnet-46-primer-forestdb primary sonnet-4.6 +primer TV<.05 5.4e-17 0.0000 ·
forestdb-generics / atom-2
shape distribution s46 +p TV<.051.6e-16 runs 1/1
per-run
00 prompt

Implement a Bayesian generic language interpretation model in WebPPL. The prevalence space is bins = map(function(x){ _.round(x,2); }, _.range(0.01,1,0.02)). The threshold space is thresholdBins computed as midpoints between consecutive bins. DiscreteBeta(g,d) returns a Categorical over bins using Beta PDF: weight for x is x^(g*d-1)*(1-x)^((1-g)*d-1). Use cache for DiscreteBeta. priorModel(params) draws prevalence from a mixture: flip(potential) selects DiscreteBeta(g,d) vs DiscreteBeta(0.01,100), returning the prevalence (a scalar, not a record). meaning(utterance,prevalence,threshold) is true for 'generic' when prevalence>threshold, always true for other utterances. thresholdPrior() = uniformDraw(thresholdBins). statePrior = priorModel({potential:0.3, prevalenceWhenPresent:0.5, concentrationWhenPresent:10}). The literal listener (named 'listener', using cache) takes an utterance, samples prevalence from statePrior and threshold from thresholdPrior, conditions on meaning(utterance,prevalence,threshold), and returns prevalence. Return the listener's posterior distribution over prevalence when hearing 'generic'.

system prompt constant across atoms
(system prompt loads here)
WebPPL primer applied to *-primer-* runs
(primer loads here)
01 code comparing GT vs s46 +p
GTground truth
webppl
1///fold:
2// discretized range between 0 - 1
3var bins = map(function(x){
4 _.round(x, 2);
5}, _.range(0.01, 1, 0.02));
6
7var thresholdBins = map2(function(x,y){
8 var d = (y - x)/ 2;
9 return x + d
10}, bins.slice(0, bins.length - 1), bins.slice(1, bins.length))
11
12// function returns a discretized Beta distribution
13var DiscreteBeta = cache(function(g, d){
14 var a = g * d, b = (1-g) * d;
15 var betaPDF = function(x){
16 return Math.pow(x, a-1)*Math.pow((1-x), b-1)
17 }
18 var probs = map(betaPDF, bins);
19 return Categorical({vs: bins, ps: probs})
20})
21
22var priorModel = function(params){
23 Infer({model: function(){
24
25 var potential = params["potential"]
26 var g = params["prevalenceWhenPresent"]
27 var d = params["concentrationWhenPresent"]
28
29 var StableDistribution = DiscreteBeta(g, d)
30 var UnstableDistribution = DiscreteBeta(0.01, 100)
31
32 var prevalence = flip(potential) ?
33 sample(StableDistribution) :
34 sample(UnstableDistribution)
35
36 return prevalence
37
38 }})
39}
40///
41var meaning = function(utterance, prevalence, threshold) {
42 return (utterance == 'generic') ? prevalence > threshold : true
43}
44var thresholdPrior = function() { return uniformDraw(thresholdBins) };
45
46var statePrior = priorModel({
47 potential: 0.3,
48 prevalenceWhenPresent: 0.5, // how prevalent under the stable cause
49 concentrationWhenPresent: 10 // the inverse-variance of the stable cause
50})
51
52display("prevalence prior")
53viz(statePrior)
54
55var listener = cache(function(utterance) {
56 Infer({model: function(){
57 var prevalence = sample(statePrior)
58 var threshold = thresholdPrior()
59 var m = meaning(utterance, prevalence, threshold)
60 condition(m)
61 return prevalence
62 }})
63})
64
65display("listener posterior")
66listener("generic")
67
68var ANSWER = (listener('generic'));
69
s46 +psonnet-46-primer-forestdbTV<.051.6e-16
webppl
1var bins = map(function(x){ return _.round(x, 2); }, _.range(0.01, 1, 0.02));
2
3var thresholdBins = map(function(i){
4 return _.round((bins[i] + bins[i+1]) / 2, 3);
5}, _.range(0, bins.length - 1));
6
7var DiscreteBeta = cache(function(g, d){
8 var weights = map(function(x){
9 return Math.pow(x, g*d - 1) * Math.pow(1 - x, (1-g)*d - 1);
10 }, bins);
11 var totalWeight = sum(weights);
12 var ps = map(function(w){ return w / totalWeight; }, weights);
13 return Categorical({vs: bins, ps: ps});
14});
15
16var priorModel = function(params){
17 var potential = params.potential;
18 var g = params.prevalenceWhenPresent;
19 var d = params.concentrationWhenPresent;
20 var isPresent = flip(potential);
21 var prevalence = isPresent ?
22 sample(DiscreteBeta(g, d)) :
23 sample(DiscreteBeta(0.01, 100));
24 return prevalence;
25};
26
27var meaning = function(utterance, prevalence, threshold){
28 return utterance === 'generic' ? prevalence > threshold : true;
29};
30
31var thresholdPrior = function(){
32 return uniformDraw(thresholdBins);
33};
34
35var statePrior = function(){
36 return priorModel({potential: 0.3, prevalenceWhenPresent: 0.5, concentrationWhenPresent: 10});
37};
38
39var listener = cache(function(utterance){
40 return Infer({method: 'enumerate'}, function(){
41 var prevalence = statePrior();
42 var threshold = thresholdPrior();
43 condition(meaning(utterance, prevalence, threshold));
44 return prevalence;
45 });
46});
47
48var ANSWER = listener('generic');
02output overlaydistribution
GT s46 +p24 bins · 0.05 … 0.97
00.080.080.150.150.200.400.600.800.57 · 0.1530.57 · 0.153x = 0.05 A = 0.0139 B = 0.0139 Δ = 0.0000x = 0.09 A = 0.0007 B = 0.0007 Δ = 0.0000x = 0.13 A = 0.0007 B = 0.0007 Δ = 0.0000x = 0.17 A = 0.0025 B = 0.0025 Δ = 0.0000x = 0.21 A = 0.0064 B = 0.0064 Δ = 0.0000x = 0.25 A = 0.0130 B = 0.0130 Δ = 0.0000x = 0.29 A = 0.0227 B = 0.0227 Δ = 0.0000x = 0.33 A = 0.0584 B = 0.0584 Δ = 0.0000x = 0.37 A = 0.0269 B = 0.0269 Δ = 0.0000x = 0.41 A = 0.0656 B = 0.0656 Δ = 0.0000x = 0.45 A = 0.1251 B = 0.1251 Δ = 0.0000x = 0.49 A = 0.0474 B = 0.0474 Δ = 0.0000x = 0.53 A = 0.1002 B = 0.1002 Δ = 0.0000x = 0.57 A = 0.1529 B = 0.1529 Δ = 0.0000x = 0.61 A = 0.0487 B = 0.0487 Δ = 0.0000x = 0.65 A = 0.0898 B = 0.0898 Δ = 0.0000x = 0.69 A = 0.1079 B = 0.1079 Δ = 0.0000x = 0.73 A = 0.0275 B = 0.0275 Δ = 0.0000x = 0.77 A = 0.0421 B = 0.0421 Δ = 0.0000x = 0.81 A = 0.0346 B = 0.0346 Δ = 0.0000x = 0.85 A = 0.0056 B = 0.0056 Δ = 0.0000x = 0.89 A = 0.0056 B = 0.0056 Δ = 0.0000x = 0.93 A = 0.0016 B = 0.0016 Δ = 0.0000x = 0.97 A = 0.0000 B = 0.0000 Δ = 0.0000
03 other runs 1 total
run flags bucket TV KL actions
sonnet-46-primer-forestdb primary sonnet-4.6 +primer TV<.05 1.6e-16 0.0000 ·
forestdb-hlms-comparison-class / atom-1
shape distribution s46 +p TV<.055.6e-16 runs 1/1
per-run
00 prompt

A Tessler et al. (2017) RSA comparison-class model for gradable adjectives. A pragmatic listener hears "tall" and knows the person is a basketball player. They infer whether "tall" is relative to all people (superordinate) or to basketball players (subordinate).

binParam = 3. superordinate_params = {mu: 0, sigma: 1}. stateVals: _.range(-3, 3, 1/3) (18 values). stateProbs(stateParams): map over stateVals, exp(Gaussian(stateParams).score(s)). generateStatePrior(stateParams): Infer categorical({vs: stateVals, ps: stateProbs(stateParams)}). thresholdBins: {positive: stateVals - 1/6, negative: stateVals + 1/6}. thresholdPrior(form): uniformDraw(thresholdBins[form]). subParams = {gymnasts: {mu:-1, sigma:0.5}, soccerPlayers: {mu:0, sigma:0.5}, basketballPlayers: {mu:1, sigma:0.5}}. utterances = ["tall", "short", "silence"]. meaning(utterance, state, thresholds): tall ? state > thresholds.tall : short ? state < thresholds.short : true. classPrior: uniformDraw(["subordinate", "superordinate"]). alpha = 5. literalListener(utterance, thresholds, comparisonClass): Infer, samples state from generateStatePrior(comparisonClass), conditions on meaning, returns state. cache 10000. speaker1(state, thresholds, comparisonClass): Infer, uniformDraw(utterances), factor(alpha * L0.score(state)), returns utterance. cache 10000. pragmaticListener(utterance, subordinate_params): Infer, samples state from generateStatePrior(subordinate_params), samples thresholds {tall: thresholdPrior("positive"), short: thresholdPrior("negative")}, samples c from classPrior, comparisonClass = c=="subordinate" ? subordinate_params : superordinate_params, observes speaker1, returns {comparisonClass: c, state}. cache 10000.

Compute marginalize(pragmaticListener("tall", subParams["basketballPlayers"]), "comparisonClass"). Return the marginal distribution over comparisonClass.

system prompt constant across atoms
(system prompt loads here)
WebPPL primer applied to *-primer-* runs
(primer loads here)
01 code comparing GT vs s46 +p
GTground truth
webppl
1///fold:
2// helper function
3var exp = function(x){return Math.exp(x)}
4
5// for discretization
6var binParam = 3;
7
8// information about the superordinate category prior
9// e.g., the height distribution for all people
10var superordinate_params = {mu: 0, sigma: 1};
11
12// calculate the range in pre-defined steps;
13// these values correspond to possible heights
14var stateVals = _.range(superordinate_params.mu - 3 * superordinate_params.sigma,
15 superordinate_params.mu + 3 * superordinate_params.sigma,
16 superordinate_params.sigma/binParam)
17
18// for each possible height, calculate its probability of occurrence
19var stateProbs = cache(function(stateParams){
20 return map(function(s){
21 exp(Gaussian(stateParams).score(s))
22 }, stateVals)
23});
24
25// generate a statePrior using the possible heights and their probabilities
26var generateStatePrior = cache(function(stateParams) {
27 return Infer({
28 model: function(){
29 return categorical({vs: stateVals, ps: stateProbs(stateParams)})
30 }
31 })
32});
33
34// generate the uniform threshold prior
35var thresholdBins ={
36 positive: map(function(x){
37 return x - (1/(binParam*2));
38 }, sort(stateVals)),
39 negative: map(function(x){
40 return x + (1/(binParam*2));
41 }, sort(stateVals))
42};
43
44var thresholdPrior = cache(function(form){
45 return Infer({
46 model: function() { return uniformDraw(thresholdBins[form]) }
47 });
48});
49///
50
51// information about the superordinate category priors
52var subParams = {
53 gymnasts: {mu: -1, sigma: 0.5}, // gymnast heights
54 soccerPlayers: {mu: 0, sigma: 0.5}, // soccer player heights
55 basketballPlayers: {mu: 1, sigma: 0.5} // basketball player heights
56}
57
58// possible utterances can be either positive (tall) or negative (short) or a null utterance
59var utterances = ["tall", "short", "silence"]
60
61// meaning function for utterances
62var meaning = function(utterance, state, thresholds) {
63 utterance == "tall" ? state > thresholds.tall :
64 utterance == "short" ? state < thresholds.short :
65 true
66}
67
68// assume a uniform prior over comparison classes
69var classPrior = Infer({
70 model: function(){return uniformDraw(["subordinate", "superordinate"])}
71});
72
73// set speaker optimality
74var alpha = 5;
75
76var literalListener = cache(
77 function(utterance, thresholds, comparisonClass) {
78 Infer({model: function(){
79 var StatePrior = generateStatePrior(comparisonClass)
80 var state = sample(StatePrior);
81 var m = meaning(utterance, state, thresholds);
82 condition(m);
83 return state;
84 }})
85 }, 10000 // limit cache size
86)
87
88var speaker1 = cache(
89 function(state, thresholds, comparisonClass) {
90 Infer({model: function(){
91 var utterance = uniformDraw(utterances);
92 var L0 = literalListener(utterance, thresholds, comparisonClass);
93 factor( alpha * L0.score(state) );
94 return utterance;
95 }})
96 }, 10000 // limit cache size
97)
98
99var pragmaticListener = cache(function(utterance, subordinate_params) {
100 Infer({model: function(){
101
102 var statePrior = generateStatePrior(subordinate_params);
103 var state = sample(statePrior);
104 // separate thresholds for positive adjective and negative adjective
105 var thresholds = {
106 tall: sample(thresholdPrior("positive")),
107 short: sample(thresholdPrior("negative"))
108 }
109
110 // uncertainty about the comparison class (superordinate vs. subordinate)
111 var c = sample(classPrior)
112 var comparisonClass = c == "subordinate" ? subordinate_params : superordinate_params
113
114 var S1 = speaker1(state, thresholds, comparisonClass);
115 observe(S1, utterance);
116
117 return { comparisonClass: c, state : state }
118 }})
119}, 10000 // limit cache size
120 )
121
122// the possible experiment conditions:
123// you hear that someone is a member of a subordinate category
124// then you are told that they are tall/short;
125// the task is to figure out the implicit comparison class
126var exptConditions = [
127 {utt: "tall", sub: "basketballPlayers"},
128 {utt: "short", sub: "basketballPlayers"},
129 {utt: "tall", sub: "soccerPlayers"},
130 {utt: "short", sub: "soccerPlayers"},
131 {utt: "tall", sub: "gymnasts"},
132 {utt: "short", sub: "gymnasts"}
133];
134
135// generate structure predictions by mapping through the experiment conditions
136var L1predictions = map(function(stim){
137 var L1posterior = pragmaticListener(stim.utt, subParams[stim.sub])
138 return {
139 utterance: stim.utt,
140 "P(superordinate comparison class)": exp(marginalize(L1posterior, "comparisonClass").score("superordinate")),
141 "subordinate category": stim.sub,
142 model: "L1"
143 }
144}, exptConditions)
145
146display("the basketball player is tall")
147display("--> height = " + expectation(marginalize(pragmaticListener("tall",{mu: 1, sigma: 0.5}), "state")))
148display("the basketball player is short")
149display("--> height = " + expectation(marginalize(pragmaticListener("short",{mu: 1, sigma: 0.5}), "state")))
150
151display("probability of superordinate comparison class (i.e., tall for all people)")
152viz.bar(L1predictions, {groupBy: "subordinate category"})
153
154var ANSWER = (marginalize(pragmaticListener("tall", subParams["basketballPlayers"]), "comparisonClass"));
155
s46 +psonnet-46-primer-forestdbTV<.055.6e-16
webppl
1var binParam = 3;
2var superordinate_params = {mu: 0, sigma: 1};
3var stateVals = _.range(-3, 3, 1/3);
4
5var stateProbs = function(stateParams) {
6 return map(function(s) {
7 return Math.exp(Gaussian({mu: stateParams.mu, sigma: stateParams.sigma}).score(s));
8 }, stateVals);
9};
10
11var generateStatePrior = function(stateParams) {
12 return Infer({method: 'enumerate'}, function() {
13 return sample(Categorical({vs: stateVals, ps: stateProbs(stateParams)}));
14 });
15};
16
17var thresholdBins = {
18 positive: map(function(s) { return s - 1/6; }, stateVals),
19 negative: map(function(s) { return s + 1/6; }, stateVals)
20};
21
22var thresholdPrior = function(form) {
23 return uniformDraw(thresholdBins[form]);
24};
25
26var subParams = {
27 gymnasts: {mu: -1, sigma: 0.5},
28 soccerPlayers: {mu: 0, sigma: 0.5},
29 basketballPlayers: {mu: 1, sigma: 0.5}
30};
31
32var utterances = ["tall", "short", "silence"];
33
34var meaning = function(utterance, state, thresholds) {
35 return utterance === "tall" ? state > thresholds.tall :
36 utterance === "short" ? state < thresholds.short :
37 true;
38};
39
40var alpha = 5;
41
42var literalListener = mem(function(utterance, thresholds, comparisonClass) {
43 return Infer({method: 'enumerate'}, function() {
44 var state = sample(generateStatePrior(comparisonClass));
45 condition(meaning(utterance, state, thresholds));
46 return state;
47 });
48}, 10000);
49
50var speaker1 = mem(function(state, thresholds, comparisonClass) {
51 return Infer({method: 'enumerate'}, function() {
52 var utterance = uniformDraw(utterances);
53 var L0 = literalListener(utterance, thresholds, comparisonClass);
54 factor(alpha * L0.score(state));
55 return utterance;
56 });
57}, 10000);
58
59var pragmaticListener = mem(function(utterance, subordinate_params) {
60 return Infer({method: 'enumerate'}, function() {
61 var state = sample(generateStatePrior(subordinate_params));
62 var thresholds = {
63 tall: thresholdPrior("positive"),
64 short: thresholdPrior("negative")
65 };
66 var c = uniformDraw(["subordinate", "superordinate"]);
67 var comparisonClass = c === "subordinate" ? subordinate_params : superordinate_params;
68 var S1 = speaker1(state, thresholds, comparisonClass);
69 observe(S1, utterance);
70 return {comparisonClass: c, state: state};
71 });
72}, 10000);
73
74var result = pragmaticListener("tall", subParams["basketballPlayers"]);
75var marginal = marginalize(result, "comparisonClass");
76
77var ANSWER = marginal;
02output overlaydistribution
GT s46 +p2 bins
00.290.290.580.58superordinate A = 0.581 B = 0.581superordinate A = 0.581 B = 0.5810.580.58superordinatesubordinate A = 0.419 B = 0.419subordinate A = 0.419 B = 0.4190.420.42subordinate
03 other runs 1 total
run flags bucket TV KL actions
sonnet-46-primer-forestdb primary sonnet-4.6 +primer TV<.05 5.6e-16 -0.0000 ·
forestdb-jmr-irony-extension / atom-1
shape distribution s46 +p TV=00.000 runs 1/1
per-run
00 prompt

An extension of Kao and Goodman (2015) RSA irony model with 5 weather states and continuous-valued arousal. California weather context. A pragmatic listener hears "terrible" and infers the state, valence, and arousal.

states = ["terrible","bad","ok","good","amazing"]. statePrior: categorical([1,5,40,40,40], states). utterances = states. utterancePrior: uniformDraw(utterances). valencePrior(state): terrible->flip(0.99)?-1:1, bad->flip(0.90)?-1:1, ok->flip(0.5)?-1:1, good->flip(0.09)?-1:1, amazing->flip(0.01)?-1:1. arousals = [0.1, 0.3, 0.5, 0.7, 0.9] (continuous numeric, not "low"/"high"). arousalPrior(state): terrible->categorical([1,10,30,45,50],arousals), bad->categorical([1,5,25,40,45],arousals), ok->categorical([50,45,30,10,1],arousals), good->categorical([1,5,25,40,45],arousals), amazing->categorical([1,10,30,45,50],arousals). goals = ["goalState","goalValence","goalArousal"]. goalPrior: categorical([1,1,1], goals). literalInterpretation(utterance, state): utterance === state. goalState(goal, state, valence, arousal): goalState->state, goalValence->valence, goalArousal->arousal. literalListener(utterance, goal): Infer over uniformDraw(states), samples valence and arousal, conditions on literalInterpretation, returns goalState(goal,state,valence,arousal). speaker(state, valence, arousal, goal): Infer, factor(1 * literalListener(utterance,goal).score(goalState(...))), returns utterance. pragmaticListener(utterance): Infer, samples state/valence/arousal/goal, observes speaker, returns {state, valence, arousal}.

Compute pragmaticListener("terrible"). Return joint distribution over {state, valence, arousal}.

system prompt constant across atoms
(system prompt loads here)
WebPPL primer applied to *-primer-* runs
(primer loads here)
01 code comparing GT vs s46 +p
GTground truth
webppl
1// There are three possible states the weather could be in:
2// terrible, ok, or amazing
3var states = ['terrible','bad','ok','good','amazing']
4
5// Since we are in California, the prior over these states
6// are the following. Once could also imagine this being
7// the prior in a certain context, e.g. when it's clearly
8// sunny and nice out.
9var statePrior = function() {
10 categorical([1,5,40,40,40], states)
11}
12
13// Valence prior defined in terms of negative valence.
14// If the current state is terrible, it's extremely likely
15// that the valence associated is negative. If it's ok, then
16// the valence could be negative or positive with equal
17// probability.
18var valencePrior = function(state) {
19 state === "terrible" ? flip(0.99) ? -1 : 1 :
20 state === "bad" ? flip(0.90) ? -1 : 1 :
21 state === "ok" ? flip(0.5) ? -1 : 1 :
22 state === "good" ? flip(0.09) ? -1 : 1 :
23 state === "amazing" ? flip(0.01) ? -1 : 1 :
24 true
25}
26
27// Define binary arousals (could model as continuous).
28// var arousals = ["low", "high"]
29var arousals = [.1,.3,.5,.7,.9]
30
31// Define goals and goal priors. Could want to communicate state of the world,
32// valence about it, or arousal (intensity of feeling) about it.
33var goals = ["goalState", "goalValence", "goalArousal"]
34
35var goalPrior = function() {
36 categorical([1, 1, 1], goals)
37}
38
39// Assume possible utterances are identical to possible states
40var utterances = states
41
42// Assume cost of utterances is uniform.
43var utterancePrior = function() {
44 uniformDraw(utterances)
45}
46
47// Sample arousal given a state.
48var arousalPrior = function(state) {
49 state === "terrible" ? categorical([1,10,30,45,50], arousals) :
50 state === "bad" ? categorical([1,5,25,40,45], arousals) :
51 state === "ok" ? categorical([50,45,30,10,1], arousals) :
52 state === "good" ? categorical([1,5,25,40,45], arousals) :
53 state === "amazing" ? categorical([1,10,30,45,50], arousals) :
54 true
55}
56
57// Literal interpretation is just whether utterance equals state
58var literalInterpretation = function(utterance, state) {
59 utterance === state
60}
61
62// A speaker's goal is satisfied if the listener infers the correct
63// and relevant information.
64var goalState = function(goal, state, valence, arousal) {
65 goal === "goalState" ? state :
66 goal === "goalValence" ? valence :
67 goal === "goalArousal" ? arousal :
68 true
69}
70
71// Define a literal listener
72var literalListener = function(utterance, goal) {
73 Infer({model: function(){
74 var state = uniformDraw(states)
75 var valence = valencePrior(state)
76 var arousal = arousalPrior(state)
77 condition(literalInterpretation(utterance,state))
78 return goalState(goal, state, valence, arousal)
79 }})
80}
81
82//The speaker takes in a state, valence, arousal, and a goal and returns an utterance
83//based on the probability of the literalListener arriving at the correct
84//state given a goalState
85var speaker = function(state, valence, arousal, goal) {
86 Infer({model: function(){
87 var utterance = utterancePrior()
88 factor(1 * literalListener(utterance,
89 goal).score(goalState(goal,
90 state,
91 valence,
92 arousal)))
93 return utterance
94 }})
95}
96
97// Define a pragmatic listener
98var pragmaticListener = function(utterance) {
99 Infer({model: function(){
100 var state = statePrior()
101 var valence = valencePrior(state)
102 var arousal = arousalPrior(state)
103 var goal = goalPrior()
104 observe(speaker(state, valence, arousal, goal),utterance)
105 return {state,valence, arousal}
106 }})
107}
108
109viz.table(pragmaticListener('terrible'))
110
111var ANSWER = (pragmaticListener("terrible"));
112
s46 +psonnet-46-primer-forestdbTV=00.000
webppl
1var states = ["terrible", "bad", "ok", "good", "amazing"];
2var utterances = states;
3var arousals = [0.1, 0.3, 0.5, 0.7, 0.9];
4var goals = ["goalState", "goalValence", "goalArousal"];
5
6var statePrior = function() {
7 return categorical({vs: states, ps: [1, 5, 40, 40, 40]});
8};
9
10var utterancePrior = function() {
11 return uniformDraw(utterances);
12};
13
14var valencePrior = function(state) {
15 if (state === "terrible") { return flip(0.99) ? -1 : 1; }
16 else if (state === "bad") { return flip(0.90) ? -1 : 1; }
17 else if (state === "ok") { return flip(0.5) ? -1 : 1; }
18 else if (state === "good") { return flip(0.09) ? -1 : 1; }
19 else if (state === "amazing") { return flip(0.01) ? -1 : 1; }
20};
21
22var arousalPrior = function(state) {
23 if (state === "terrible") { return categorical({vs: arousals, ps: [1, 10, 30, 45, 50]}); }
24 else if (state === "bad") { return categorical({vs: arousals, ps: [1, 5, 25, 40, 45]}); }
25 else if (state === "ok") { return categorical({vs: arousals, ps: [50, 45, 30, 10, 1]}); }
26 else if (state === "good") { return categorical({vs: arousals, ps: [1, 5, 25, 40, 45]}); }
27 else if (state === "amazing") { return categorical({vs: arousals, ps: [1, 10, 30, 45, 50]}); }
28};
29
30var goalPrior = function() {
31 return categorical({vs: goals, ps: [1, 1, 1]});
32};
33
34var literalInterpretation = function(utterance, state) {
35 return utterance === state;
36};
37
38var goalState = function(goal, state, valence, arousal) {
39 if (goal === "goalState") { return state; }
40 else if (goal === "goalValence") { return valence; }
41 else if (goal === "goalArousal") { return arousal; }
42};
43
44var literalListener = mem(function(utterance, goal) {
45 return Infer({method: "enumerate"}, function() {
46 var state = uniformDraw(states);
47 var valence = valencePrior(state);
48 var arousal = arousalPrior(state);
49 condition(literalInterpretation(utterance, state));
50 return goalState(goal, state, valence, arousal);
51 });
52});
53
54var speaker = mem(function(state, valence, arousal, goal) {
55 return Infer({method: "enumerate"}, function() {
56 var utterance = utterancePrior();
57 var gs = goalState(goal, state, valence, arousal);
58 factor(1 * literalListener(utterance, goal).score(gs));
59 return utterance;
60 });
61});
62
63var pragmaticListener = function(utterance) {
64 return Infer({method: "enumerate"}, function() {
65 var state = statePrior();
66 var valence = valencePrior(state);
67 var arousal = arousalPrior(state);
68 var goal = goalPrior();
69 var gs = goalState(goal, state, valence, arousal);
70 observe(speaker(state, valence, arousal, goal), utterance);
71 return {state: state, valence: valence, arousal: arousal};
72 });
73};
74
75var ANSWER = pragmaticListener("terrible");
02output overlaydistribution
GT s46 +p48 bins
00.0490.0490.0980.098{"state":"amazing","valence":1,"arousal":0.9} A = 0.098 B = 0.098{"state":"amazing","valence":1,"arousal":0.9} A = 0.098 B = 0.098{"state":"amazing","valence":1,"arousal":0.9}{"state":"ok","valence":-1,"arousal":0.3} A = 0.095 B = 0.095{"state":"ok","valence":-1,"arousal":0.3} A = 0.095 B = 0.095{"state":"good","valence":1,"arousal":0.9} A = 0.095 B = 0.095{"state":"good","valence":1,"arousal":0.9} A = 0.095 B = 0.095{"state":"amazing","valence":1,"arousal":0.7} A = 0.084 B = 0.084{"state":"amazing","valence":1,"arousal":0.7} A = 0.084 B = 0.084{"state":"ok","valence":-1,"arousal":0.1} A = 0.083 B = 0.083{"state":"ok","valence":-1,"arousal":0.1} A = 0.083 B = 0.083{"state":"ok","valence":-1,"arousal":0.1}{"state":"good","valence":1,"arousal":0.7} A = 0.081 B = 0.081{"state":"good","valence":1,"arousal":0.7} A = 0.081 B = 0.081{"state":"ok","valence":-1,"arousal":0.5} A = 0.072 B = 0.072{"state":"ok","valence":-1,"arousal":0.5} A = 0.072 B = 0.072{"state":"amazing","valence":1,"arousal":0.5} A = 0.049 B = 0.049{"state":"amazing","valence":1,"arousal":0.5} A = 0.049 B = 0.049{"state":"good","valence":1,"arousal":0.5} A = 0.044 B = 0.044{"state":"good","valence":1,"arousal":0.5} A = 0.044 B = 0.044{"state":"good","valence":1,"arousal":0.5}{"state":"bad","valence":-1,"arousal":0.9} A = 0.030 B = 0.030{"state":"bad","valence":-1,"arousal":0.9} A = 0.030 B = 0.030{"state":"bad","valence":-1,"arousal":0.7} A = 0.027 B = 0.027{"state":"bad","valence":-1,"arousal":0.7} A = 0.027 B = 0.027{"state":"ok","valence":-1,"arousal":0.7} A = 0.025 B = 0.025{"state":"ok","valence":-1,"arousal":0.7} A = 0.025 B = 0.025{"state":"ok","valence":1,"arousal":0.5} A = 0.025 B = 0.025{"state":"ok","valence":1,"arousal":0.5} A = 0.025 B = 0.025{"state":"ok","valence":1,"arousal":0.5}{"state":"good","valence":-1,"arousal":0.9} A = 0.024 B = 0.024{"state":"good","valence":-1,"arousal":0.9} A = 0.024 B = 0.024{"state":"ok","valence":1,"arousal":0.3} A = 0.024 B = 0.024{"state":"ok","valence":1,"arousal":0.3} A = 0.024 B = 0.024{"state":"good","valence":-1,"arousal":0.7} A = 0.021 B = 0.021{"state":"good","valence":-1,"arousal":0.7} A = 0.021 B = 0.021{"state":"terrible","valence":-1,"arousal":0.9} A = 0.016 B = 0.016{"state":"terrible","valence":-1,"arousal":0.9} A = 0.016 B = 0.016{"state":"terrible","valence":-1,"arousal":0.9}{"state":"bad","valence":-1,"arousal":0.5} A = 0.016 B = 0.016{"state":"bad","valence":-1,"arousal":0.5} A = 0.016 B = 0.016{"state":"terrible","valence":-1,"arousal":0.7} A = 0.015 B = 0.015{"state":"terrible","valence":-1,"arousal":0.7} A = 0.015 B = 0.015{"state":"good","valence":-1,"arousal":0.5} A = 0.013 B = 0.013{"state":"good","valence":-1,"arousal":0.5} A = 0.013 B = 0.013{"state":"amazing","valence":1,"arousal":0.3} A = 0.011 B = 0.011{"state":"amazing","valence":1,"arousal":0.3} A = 0.011 B = 0.011{"state":"amazing","valence":1,"arousal":0.3}{"state":"terrible","valence":-1,"arousal":0.5} A = 0.010 B = 0.010{"state":"terrible","valence":-1,"arousal":0.5} A = 0.010 B = 0.010{"state":"ok","valence":1,"arousal":0.7} A = 0.009 B = 0.009{"state":"ok","valence":1,"arousal":0.7} A = 0.009 B = 0.009{"state":"good","valence":1,"arousal":0.3} A = 0.006 B = 0.006{"state":"good","valence":1,"arousal":0.3} A = 0.006 B = 0.006{"state":"ok","valence":1,"arousal":0.1} A = 0.004 B = 0.004{"state":"ok","valence":1,"arousal":0.1} A = 0.004 B = 0.004{"state":"ok","valence":1,"arousal":0.1}{"state":"terrible","valence":-1,"arousal":0.3} A = 0.003 B = 0.003{"state":"terrible","valence":-1,"arousal":0.3} A = 0.003 B = 0.003{"state":"bad","valence":-1,"arousal":0.3} A = 0.003 B = 0.003{"state":"bad","valence":-1,"arousal":0.3} A = 0.003 B = 0.003{"state":"amazing","valence":-1,"arousal":0.9} A = 0.003 B = 0.003{"state":"amazing","valence":-1,"arousal":0.9} A = 0.003 B = 0.003{"state":"ok","valence":-1,"arousal":0.9} A = 0.003 B = 0.003{"state":"ok","valence":-1,"arousal":0.9} A = 0.003 B = 0.003{"state":"ok","valence":-1,"arousal":0.9}{"state":"amazing","valence":-1,"arousal":0.7} A = 0.002 B = 0.002{"state":"amazing","valence":-1,"arousal":0.7} A = 0.002 B = 0.002{"state":"good","valence":-1,"arousal":0.3} A = 0.002 B = 0.002{"state":"good","valence":-1,"arousal":0.3} A = 0.002 B = 0.002{"state":"amazing","valence":-1,"arousal":0.5} A = 0.001 B = 0.001{"state":"amazing","valence":-1,"arousal":0.5} A = 0.001 B = 0.001{"state":"bad","valence":1,"arousal":0.9} A = 0.001 B = 0.001{"state":"bad","valence":1,"arousal":0.9} A = 0.001 B = 0.001{"state":"bad","valence":1,"arousal":0.9}{"state":"bad","valence":1,"arousal":0.7} A = 0.001 B = 0.001{"state":"bad","valence":1,"arousal":0.7} A = 0.001 B = 0.001{"state":"ok","valence":1,"arousal":0.9} A = 0.001 B = 0.001{"state":"ok","valence":1,"arousal":0.9} A = 0.001 B = 0.001{"state":"bad","valence":1,"arousal":0.5} A = 0.001 B = 0.001{"state":"bad","valence":1,"arousal":0.5} A = 0.001 B = 0.001{"state":"bad","valence":-1,"arousal":0.1} A = 0.000 B = 0.000{"state":"bad","valence":-1,"arousal":0.1} A = 0.000 B = 0.000{"state":"bad","valence":-1,"arousal":0.1}{"state":"amazing","valence":-1,"arousal":0.3} A = 0.000 B = 0.000{"state":"amazing","valence":-1,"arousal":0.3} A = 0.000 B = 0.000{"state":"good","valence":-1,"arousal":0.1} A = 0.000 B = 0.000{"state":"good","valence":-1,"arousal":0.1} A = 0.000 B = 0.000{"state":"terrible","valence":-1,"arousal":0.1} A = 0.000 B = 0.000{"state":"terrible","valence":-1,"arousal":0.1} A = 0.000 B = 0.000{"state":"good","valence":1,"arousal":0.1} A = 0.000 B = 0.000{"state":"good","valence":1,"arousal":0.1} A = 0.000 B = 0.000{"state":"good","valence":1,"arousal":0.1}{"state":"amazing","valence":1,"arousal":0.1} A = 0.000 B = 0.000{"state":"amazing","valence":1,"arousal":0.1} A = 0.000 B = 0.000{"state":"terrible","valence":1,"arousal":0.9} A = 0.000 B = 0.000{"state":"terrible","valence":1,"arousal":0.9} A = 0.000 B = 0.000{"state":"terrible","valence":1,"arousal":0.7} A = 0.000 B = 0.000{"state":"terrible","valence":1,"arousal":0.7} A = 0.000 B = 0.000{"state":"bad","valence":1,"arousal":0.3} A = 0.000 B = 0.000{"state":"bad","valence":1,"arousal":0.3} A = 0.000 B = 0.000{"state":"bad","valence":1,"arousal":0.3}{"state":"terrible","valence":1,"arousal":0.5} A = 0.000 B = 0.000{"state":"terrible","valence":1,"arousal":0.5} A = 0.000 B = 0.000{"state":"amazing","valence":-1,"arousal":0.1} A = 0.000 B = 0.000{"state":"amazing","valence":-1,"arousal":0.1} A = 0.000 B = 0.000{"state":"terrible","valence":1,"arousal":0.3} A = 0.000 B = 0.000{"state":"terrible","valence":1,"arousal":0.3} A = 0.000 B = 0.000
03 other runs 1 total
run flags bucket TV KL actions
sonnet-46-primer-forestdb primary sonnet-4.6 +primer TV=0 0.000 0.0000 ·
forestdb-kachakeche-comparison-class / atom-1
shape distribution s46 +p TV<.053.9e-15 runs 1/1
per-run
00 prompt

A Tessler et al. (2017) RSA comparison-class model adapted for weight adjectives ("heavy"/"light") and speaker identity (child, adult, bodybuilder). The pragmatic listener hears "heavy" uttered by a child and infers the actual box weight.

binParam = 5. superordinate = {mu: 3, sigma: 1} (scale 0-6 represents lightest to heaviest). stateVals: _.range(0, 6, 0.2) (30 values). stateProbs(stateParams): map over stateVals, exp(Gaussian(stateParams).score(s)). generateStatePrior(stateParams): Infer categorical({vs: stateVals, ps: stateProbs(stateParams)}). speakerParams = {child: {mu:0.5, sigma:1}, adult: {mu:2, sigma:3}, bodybuilder: {mu:5, sigma:3}}. utterances = ["heavy", "light"]. thresholdBins(utterance, stateSupport): heavy ? x-1/10 : x+1/10. thresholdPrior(utterance, stateSupport): uniformDraw(thresholdBins(utterance, stateSupport)). meaning(utterance, state, thresholdHeavy, thresholdLight): heavy ? state>thresholdHeavy ? flip(0.9999) : flip(0.0001) : light ? state<thresholdLight ? flip(0.9999) : flip(0.0001) : true. alpha = 5. literalListener(utterance, thresholdHeavy, thresholdLight, comparisonClass): Infer, samples state from generateStatePrior(speakerParams[comparisonClass]), conditions on meaning. cache 10000. speaker1(state, thresholdHeavy, thresholdLight, comparisonClass): Infer, uniformDraw(utterances), factor(alpha * L0.score(state)). cache 10000. comparisonClasses = ["child","adult","bodybuilder"]. comparisonClassPrior(whoSaidIt): child -> categorical([0.75,0.25,0.15], comparisonClasses), adult -> categorical([0.01,0.7,0.5], comparisonClasses), bodybuilder -> categorical([0.0001,0.2,0.99], comparisonClasses). pragmaticListener(utterance, whoSaidIt): Infer({method:"enumerate"}), samples CC from comparisonClassPrior(whoSaidIt), state from generateStatePrior(speakerParams[CC]), thresholdHeavy and thresholdLight from thresholdPrior, observes speaker1, returns state. cache 10000.

Compute pragmaticListener("heavy", "child"). Return distribution over state (box weight on scale 0-6).

system prompt constant across atoms
(system prompt loads here)
WebPPL primer applied to *-primer-* runs
(primer loads here)
01 code comparing GT vs s46 +p
GTground truth
webppl
1// helper function
2var exp = function(x){return Math.exp(x)}
3
4// helper function
5var marginalize = function(dist, key){
6 return Infer({model: function(){sample(dist)[key]}})
7}
8// for discretization
9var binParam = 5;
10
11//my model:
12var superordinate = {mu: 3, sigma: 1};
13
14//a list of possible box weights (state values)
15var stateVals = _.range(superordinate.mu - 3 * superordinate.sigma,
16 superordinate.mu + 3 * superordinate.sigma,
17 superordinate.sigma/binParam)
18
19
20// for each possible weight, calculate its probability of occurrence
21var stateProbs = function(stateParams){
22 return map(function(s){
23 exp(Gaussian(stateParams).score(s))
24 }, stateVals)
25};
26
27
28// generate a statePrior using the possible weights and their probabilities
29var generateStatePrior = cache(function(stateParams) {
30 return Infer({
31 model: function(){
32 return categorical({vs: stateVals, ps: stateProbs(stateParams)})
33 }
34 })
35});
36
37// information about the category priors
38var speakerParams = {
39 child: {mu: 0.5, sigma: 1}, // child experience with weights
40 adult: {mu: 2, sigma: 3}, // adult experiance with weights
41 bodybuilder: {mu:5, sigma:3}, // body builder experience with weights
42}
43
44
45// generate the uniform threshold prior
46
47var thresholdBins = cache(function(utterance, stateSupport){
48 return map(function(x){
49 return utterance == "heavy" ? x - (1/(binParam*2)) : x + (1/(binParam*2));
50 }, sort(stateSupport))
51},10000
52)
53
54var thresholdPrior = cache(function(utterance, stateSupport){
55 return Infer({
56 model: function() { return uniformDraw(thresholdBins(utterance, stateSupport)) }
57 });
58},10000
59);
60
61
62
63var utterances = ["heavy","light"]
64
65
66// meaning function for utterances
67var meaning = function(utterance, state, thresholdHeavy, thresholdLight) {
68 utterance == "heavy" ? state > thresholdHeavy ? flip(0.9999) : flip(0.0001) :
69 utterance == "light" ? state < thresholdLight ? flip(0.9999) : flip(0.0001) :
70 true
71}
72
73
74
75
76// set sepeaker optimality
77var alpha = 5;
78
79
80var literalListener =cache(
81 function(utterance, thresholdHeavy, thresholdLight,comparisonClass){
82 Infer({model: function(){
83 var state = sample(generateStatePrior(speakerParams[comparisonClass]))
84 var m = meaning(utterance, state, thresholdHeavy, thresholdLight);
85 condition(m);
86 return state;
87 }})
88 },10000
89)
90
91
92//literalListener("light", 4, 2, "adult")
93
94
95//my model:
96var speaker1 = cache(
97 function(state, thresholdHeavy, thresholdLight,comparisonClass){
98 Infer({model: function(){
99 var utterance = uniformDraw(utterances);
100 var L0 = literalListener(utterance, thresholdHeavy, thresholdLight, comparisonClass);
101 factor( alpha * L0.score(state) );
102 return utterance;
103 }})
104 },10000
105)
106
107
108// generateStatePrior(speakerParams["child"]) .support()
109
110var comparisonClasses = ["child","adult","bodybuilder"]
111var comparisonClassPrior = function(whoSaidIt) {
112 whoSaidIt == "child" ? categorical([0.75, 0.25,0.15],comparisonClasses):
113 whoSaidIt == "adult" ? categorical([0.01,0.7,0.5],comparisonClasses):
114 categorical([0.0001,0.2, 0.99],comparisonClasses)
115
116
117}
118
119var pragmaticListener = cache(function(utterance,whoSaidIt){
120 Infer({model: function(){
121 var CC = comparisonClassPrior(whoSaidIt);
122 var statePrior = generateStatePrior(speakerParams[CC]);
123 var state = sample(statePrior);
124 var thresholdHeavy = sample(thresholdPrior("heavy", statePrior.support()))
125 var thresholdLight = sample(thresholdPrior("light", statePrior.support()))
126 var S1 = speaker1(state, thresholdHeavy,thresholdLight,CC);
127 observe(S1, utterance);
128 return (state)
129}, method:"enumerate"})
130},10000
131)
132
133
134
135// pragmaticListener("heavy","adult")
136display("Listener's interpretation after hearing a child saying 'this box is heavy'")
137viz.density(pragmaticListener("heavy","child"))
138display("Listener's interpretation after hearing an adult saying 'this box is heavy'")
139viz.density(pragmaticListener("heavy","adult"))
140display("Listener's interpretation after hearing a bodybuilder saying 'this box is heavy'")
141viz.density(pragmaticListener("heavy","bodybuilder"))
142display("Listener's interpretation after hearing a child saying 'this box is light'")
143viz.density(pragmaticListener("light","child"))
144display("Listener's interpretation after hearing an adult saying 'this box is light'")
145viz.density(pragmaticListener("light","adult"))
146display("Listener's interpretation after hearing a bodybuilder saying 'this box is light'")
147viz.density(pragmaticListener("light","bodybuilder"))
148
149var ANSWER = (pragmaticListener("heavy", "child"));
150
s46 +psonnet-46-primer-forestdbTV<.053.9e-15
webppl
1var binParam = 5;
2var superordinate = {mu: 3, sigma: 1};
3var stateVals = _.range(0, 6, 0.2);
4
5var stateProbs = function(stateParams) {
6 return map(function(s) {
7 return Math.exp(Gaussian(stateParams).score(s));
8 }, stateVals);
9};
10
11var generateStatePrior = function(stateParams) {
12 return Infer({method: "enumerate"}, function() {
13 return sample(Categorical({vs: stateVals, ps: stateProbs(stateParams)}));
14 });
15};
16
17var speakerParams = {
18 child: {mu: 0.5, sigma: 1},
19 adult: {mu: 2, sigma: 3},
20 bodybuilder: {mu: 5, sigma: 3}
21};
22
23var utterances = ["heavy", "light"];
24
25var thresholdBins = function(utterance, stateSupport) {
26 return map(function(x) {
27 return utterance === "heavy" ? x - 1/10 : x + 1/10;
28 }, stateSupport);
29};
30
31var thresholdPrior = function(utterance, stateSupport) {
32 return uniformDraw(thresholdBins(utterance, stateSupport));
33};
34
35var meaning = function(utterance, state, thresholdHeavy, thresholdLight) {
36 return utterance === "heavy" ?
37 (state > thresholdHeavy ? flip(0.9999) : flip(0.0001)) :
38 utterance === "light" ?
39 (state < thresholdLight ? flip(0.9999) : flip(0.0001)) :
40 true;
41};
42
43var alpha = 5;
44
45var literalListener = mem(function(utterance, thresholdHeavy, thresholdLight, comparisonClass) {
46 return Infer({method: "enumerate"}, function() {
47 var statePrior = generateStatePrior(speakerParams[comparisonClass]);
48 var state = sample(statePrior);
49 condition(meaning(utterance, state, thresholdHeavy, thresholdLight));
50 return state;
51 });
52}, 10000);
53
54var speaker1 = mem(function(state, thresholdHeavy, thresholdLight, comparisonClass) {
55 return Infer({method: "enumerate"}, function() {
56 var utterance = uniformDraw(utterances);
57 var L0 = literalListener(utterance, thresholdHeavy, thresholdLight, comparisonClass);
58 factor(alpha * L0.score(state));
59 return utterance;
60 });
61}, 10000);
62
63var comparisonClasses = ["child", "adult", "bodybuilder"];
64
65var comparisonClassPrior = function(whoSaidIt) {
66 return whoSaidIt === "child" ?
67 sample(Categorical({vs: comparisonClasses, ps: [0.75, 0.25, 0.15]})) :
68 whoSaidIt === "adult" ?
69 sample(Categorical({vs: comparisonClasses, ps: [0.01, 0.7, 0.5]})) :
70 sample(Categorical({vs: comparisonClasses, ps: [0.0001, 0.2, 0.99]}));
71};
72
73var pragmaticListener = mem(function(utterance, whoSaidIt) {
74 return Infer({method: "enumerate"}, function() {
75 var cc = comparisonClassPrior(whoSaidIt);
76 var statePrior = generateStatePrior(speakerParams[cc]);
77 var state = sample(statePrior);
78 var thresholdHeavy = thresholdPrior("heavy", stateVals);
79 var thresholdLight = thresholdPrior("light", stateVals);
80 var S1 = speaker1(state, thresholdHeavy, thresholdLight, cc);
81 observe(S1, utterance);
82 return state;
83 });
84}, 10000);
85
86var ANSWER = pragmaticListener("heavy", "child");
02output overlaydistribution
GT s46 +p24 bins · 0.12 … 5.68
00.060.060.120.12123451.09 · 0.1201.09 · 0.120x = 0.12 A = 0.0346 B = 0.0346 Δ = 0.0000x = 0.36 A = 0.0312 B = 0.0312 Δ = 0.0000x = 0.60 A = 0.0417 B = 0.0417 Δ = 0.0000x = 0.85 A = 0.0514 B = 0.0514 Δ = 0.0000x = 1.09 A = 0.1203 B = 0.1203 Δ = 0.0000x = 1.33 A = 0.0611 B = 0.0611 Δ = 0.0000x = 1.57 A = 0.0573 B = 0.0573 Δ = -0.0000x = 1.81 A = 0.0516 B = 0.0516 Δ = 0.0000x = 2.05 A = 0.0449 B = 0.0449 Δ = 0.0000x = 2.30 A = 0.0714 B = 0.0714 Δ = -0.0000x = 2.54 A = 0.0286 B = 0.0286 Δ = 0.0000x = 2.78 A = 0.0256 B = 0.0256 Δ = -0.0000x = 3.02 A = 0.0239 B = 0.0239 Δ = 0.0000x = 3.26 A = 0.0231 B = 0.0231 Δ = 0.0000x = 3.50 A = 0.0467 B = 0.0467 Δ = 0.0000x = 3.75 A = 0.0243 B = 0.0243 Δ = -0.0000x = 3.99 A = 0.0251 B = 0.0251 Δ = 0.0000x = 4.23 A = 0.0258 B = 0.0258 Δ = -0.0000x = 4.47 A = 0.0264 B = 0.0264 Δ = -0.0000x = 4.71 A = 0.0540 B = 0.0540 Δ = -0.0000x = 4.95 A = 0.0271 B = 0.0271 Δ = 0.0000x = 5.20 A = 0.0268 B = 0.0268 Δ = -0.0000x = 5.44 A = 0.0264 B = 0.0264 Δ = -0.0000x = 5.68 A = 0.0507 B = 0.0507 Δ = 0.0000
03 other runs 1 total
run flags bucket TV KL actions
sonnet-46-primer-forestdb primary sonnet-4.6 +primer TV<.05 3.9e-15 -0.0000 ·
forestdb-keysar / atom-1
shape distribution s46 +p TV=00.000 runs 1/1
per-run
00 prompt

Implement the baseline RSA reference game model (Keysar et al.) where the speaker has no uncertainty about the environment.

Setup: - possibleUtterances: all combinations of modifier and type — _.flatten(map(function(modifier){ map(function(type){ return [modifier,type].join(' ').trim(); }, ['apple','fish','cup']); }, ['red','blue','green',''])) - possibleObjects: 9 objects, all combinations of {type: 'apple'|'fish'|'cup', color: 'red'|'blue'|'green'} - exampleContext: { shared: [{type:'apple',color:'red'},{type:'fish',color:'blue'},{type:'cup',color:'green'}], occluded: [{type:'fish',color:'red'}] } - alpha = 3 - uttCost(utt): utt.split(' ').length - uttFitness(utt, object): 0 if the utterance descriptors match the object, -100 otherwise (split by space; if two descriptors, check color and type; if one, check type)

RSA chain (all use method: 'enumerate'): - L0(utt, perceivedContext): uniformDraw over perceivedContext, factor uttFitness, return object - S1(target, knownContext): uniformDraw over possibleUtterances, factor alpha * L0(utt, knownContext).score(target) - uttCost(utt), return utt - L2(utt, perceivedContext): listener only considers shared context; uniform draw over sharedContext = perceivedContext.shared, observe S1(object, sharedContext), return object.color + " " + object.type

Bind these to functions named L0, S1, L2 with the signatures above.

Return the L2 listener distribution after hearing the underinformative utterance 'fish' given exampleContext: L2('fish', exampleContext)

system prompt constant across atoms
(system prompt loads here)
WebPPL primer applied to *-primer-* runs
(primer loads here)
01 code comparing GT vs s46 +p
GTground truth
webppl
1var possibleUtterances = _.flatten(map(function(modifier) {
2 map(function(type) {
3 return [modifier, type].join(' ').trim();
4 }, ['apple', 'fish', 'cup']);
5}, ['red', 'blue', 'green', '']));
6
7var possibleObjects = [
8 {type: 'apple', color: 'red'}, {type: 'apple', color: 'blue'}, {type: 'apple', color: 'green'},
9 {type: 'fish', color: 'red'}, {type: 'fish', color: 'blue'}, {type: 'fish', color: 'green'},
10 {type: 'cup', color: 'red'}, {type: 'cup', color: 'blue'}, {type: 'cup', color: 'green'}]
11
12var exampleContext = {
13 shared: [
14 {type: 'apple', color: 'red'},
15 {type: 'fish', color: 'blue'},
16 {type: 'cup', color: 'green'}
17 ],
18 occluded: [
19 {type: 'fish', color: 'red'}
20 ]
21};
22
23var alpha = 3;
24
25var uttCost = function(utt) {
26 return utt.split(' ').length;
27}
28
29var uttFitness = function(utt, object) {
30 var descriptors = utt.split(' ');
31 if(descriptors.length > 1) {
32 return (object.color === descriptors[0] &&
33 object.type === descriptors[1]) ? 0 : -100;
34 } else {
35 return object.type === descriptors[0] ? 0 : -100;
36 }
37};
38
39var L0 = cache(function(utt, perceivedContext) {
40 return Infer({method: 'enumerate'}, function() {
41 var object = uniformDraw(perceivedContext);
42 factor(uttFitness(utt, object));
43 return object;
44 });
45});
46
47var S1 = cache(function(target, knownContext) {
48 return Infer({method: 'enumerate'}, function() {
49 var utt = uniformDraw(possibleUtterances);
50 factor(alpha * L0(utt, knownContext).score(target) - uttCost(utt));
51 return utt;
52 });
53});
54
55// Listener only considers objects speaker can see (model Keysar is arguing against)
56var L2 = cache(function(utt, perceivedContext) {
57 var sharedContext = perceivedContext.shared;
58 var fullObjSet = sharedContext.concat(perceivedContext.occluded);
59 return Infer({method: 'enumerate'}, function() {
60 var object = uniformDraw(sharedContext);
61 observe(S1(object, sharedContext), utt);
62 return object.color + " " + object.type;
63 });
64});
65
66console.log("speaker utterance to refer to blue fish");
67viz.table(S1({type: 'fish', color: 'blue'}, exampleContext.shared));
68
69console.log("listener response after hearing (underinformative) 'fish'");
70viz.table(L2('fish', exampleContext));
71
72var ANSWER = (L2('fish', exampleContext));
73
s46 +psonnet-46-primer-forestdbTV=00.000
webppl
1var possibleUtterances = _.flatten(map(function(modifier){
2 map(function(type){
3 return [modifier, type].join(' ').trim();
4 }, ['apple', 'fish', 'cup']);
5}, ['red', 'blue', 'green', '']));
6
7var possibleObjects = _.flatten(map(function(color){
8 map(function(type){
9 return {type: type, color: color};
10 }, ['apple', 'fish', 'cup']);
11}, ['red', 'blue', 'green']));
12
13var exampleContext = {
14 shared: [{type:'apple',color:'red'},{type:'fish',color:'blue'},{type:'cup',color:'green'}],
15 occluded: [{type:'fish',color:'red'}]
16};
17
18var alpha = 3;
19
20var uttCost = function(utt) {
21 return utt.split(' ').length;
22};
23
24var uttFitness = function(utt, object) {
25 var descriptors = utt.split(' ');
26 if (descriptors.length === 2) {
27 var color = descriptors[0];
28 var type = descriptors[1];
29 return (object.color === color && object.type === type) ? 0 : -100;
30 } else {
31 var descriptor = descriptors[0];
32 return (object.type === descriptor) ? 0 : -100;
33 }
34};
35
36var L0 = function(utt, perceivedContext) {
37 return Infer({method: 'enumerate'}, function() {
38 var object = uniformDraw(perceivedContext);
39 factor(uttFitness(utt, object));
40 return object;
41 });
42};
43
44var S1 = function(target, knownContext) {
45 return Infer({method: 'enumerate'}, function() {
46 var utt = uniformDraw(possibleUtterances);
47 factor(alpha * L0(utt, knownContext).score(target) - uttCost(utt));
48 return utt;
49 });
50};
51
52var L2 = function(utt, perceivedContext) {
53 return Infer({method: 'enumerate'}, function() {
54 var sharedContext = perceivedContext.shared;
55 var object = uniformDraw(sharedContext);
56 observe(S1(object, sharedContext), utt);
57 return object.color + ' ' + object.type;
58 });
59};
60
61var ANSWER = L2('fish', exampleContext);
02output overlaydistribution
GT s46 +p3 bins
00.500.501.001.00green cup A = 0.000 B = 0.000green cup A = 0.000 B = 0.000green cupblue fish A = 1.000 B = 1.000blue fish A = 1.000 B = 1.0001.001.00blue fishred apple A = 0.000 B = 0.000red apple A = 0.000 B = 0.000red apple
03 other runs 1 total
run flags bucket TV KL actions
sonnet-46-primer-forestdb primary sonnet-4.6 +primer TV=0 0.000 -0.0000 ·
forestdb-keysar / atom-2
shape distribution s46 +p TV=00.000 runs 1/1
per-run
00 prompt

Implement the context-uncertainty RSA model (Keysar et al.) where the speaker marginalizes over uncertainty about what additional objects the listener might see.

Setup: - possibleUtterances: _.flatten(map(function(modifier){ return map(function(type){ return [modifier,type].join(' ').trim(); }, ['apple','fish','cup']); }, ['red','blue','green',''])) - possibleObjects: 9 objects — all {type,color} pairs for types 'apple'|'fish'|'cup' and colors 'red'|'blue'|'green' - exampleContext: { shared: [{type:'apple',color:'red'},{type:'fish',color:'blue'},{type:'cup',color:'green'}], occluded: [{type:'fish',color:'red'}] } - alpha = 4 - uttCost(utt): utt.split(' ').length / 4 - uttFitness(utt, object): 0 if descriptors match, -100 otherwise (same logic as before)

RSA chain (all use method: 'enumerate'): - L0(utt, perceivedContext): uniformDraw over perceivedContext, factor uttFitness, return object - S1(target, perceivedContext): speaker marginalizes over a hidden additional object — internally runs Infer enumerate over contexts that are perceivedContext.concat(uniformDraw(possibleObjects)), scoring L0 on each, then factors alpha * listener.score(target) - uttCost(utt); return utt - L2(utt, perceivedContext): listener considers both shared and occluded objects as potential referents; uniform draw over fullContext = shared.concat(occluded), observe S1(object, sharedContext), return object.color + " " + object.type

Bind these to functions named L0, S1, L2.

Return the L2 listener distribution after hearing 'fish' given exampleContext: L2('fish', exampleContext)

system prompt constant across atoms
(system prompt loads here)
WebPPL primer applied to *-primer-* runs
(primer loads here)
01 code comparing GT vs s46 +p
GTground truth
webppl
1var possibleUtterances = _.flatten(map(function(modifier) {
2 return map(function(type) {
3 return [modifier, type].join(' ').trim();
4 }, ['apple', 'fish', 'cup']);
5}, ['red', 'blue', 'green', '']));
6
7var possibleObjects = [
8 {type: 'apple', color: 'red'}, {type: 'apple', color: 'blue'}, {type: 'apple', color: 'green'},
9 {type: 'fish', color: 'red'}, {type: 'fish', color: 'blue'}, {type: 'fish', color: 'green'},
10 {type: 'cup', color: 'red'}, {type: 'cup', color: 'blue'}, {type: 'cup', color: 'green'}]
11
12var exampleContext = {
13 shared: [
14 {type: 'apple', color: 'red'},
15 {type: 'fish', color: 'blue'},
16 {type: 'cup', color: 'green'}
17 ],
18 occluded: [
19 {type: 'fish', color: 'red'}
20 ]
21};
22
23var alpha = 4;
24
25var uttCost = function(utt) {
26 return utt.split(' ').length/4;
27}
28
29var uttFitness = function(utt, object) {
30 var descriptors = utt.split(' ');
31 if(descriptors.length > 1) {
32 return (object.color === descriptors[0] &&
33 object.type === descriptors[1]) ? 0 : -100;
34 } else {
35 return object.type === descriptors[0] ? 0 : -100;
36 }
37};
38
39var L0 = cache(function(utt, perceivedContext) {
40 return Infer({method: 'enumerate'}, function() {
41 var object = uniformDraw(perceivedContext);
42 factor(uttFitness(utt, object))
43 return object;
44 })
45})
46
47// speaker has uncertainty over what's behind occluded square
48// marginalizes over all possibilities
49var S1 = cache(function(target, perceivedContext) {
50 return Infer({method: 'enumerate'}, function() {
51 var utt = uniformDraw(possibleUtterances);
52 var listener = Infer({method: 'enumerate', model: function() {
53 var context = perceivedContext.concat(uniformDraw(possibleObjects));
54 return sample(L0(utt, context));
55 }})
56 factor(alpha * listener.score(target) - uttCost(utt))
57 return utt;
58 });
59});
60
61// Listener reasons about S1; assumes they only see what's in shared context
62// but could be trying to refer to any of the objects
63var L2 = cache(function(utt, perceivedContext) {
64 var sharedContext = perceivedContext.shared;
65 var fullContext = sharedContext.concat(perceivedContext.occluded);
66 return Infer({method: 'enumerate', model: function() {
67 var object = uniformDraw(fullContext);
68 observe(S1(object, sharedContext), utt);
69 return object.color + " " + object.type;
70 }});
71})
72
73console.log("speaker utterance to refer to blue fish")
74viz.table(S1({type: 'fish', color: 'blue'}, exampleContext.shared))
75
76console.log("listener response after hearing (underinformative) 'fish'")
77viz.table(L2('fish', exampleContext));
78
79var ANSWER = (L2('fish', exampleContext));
80
s46 +psonnet-46-primer-forestdbTV=00.000
webppl
1var possibleUtterances = _.flatten(map(function(modifier){
2 return map(function(type){
3 return [modifier, type].join(' ').trim();
4 }, ['apple', 'fish', 'cup']);
5}, ['red', 'blue', 'green', '']));
6
7var possibleObjects = _.flatten(map(function(type){
8 return map(function(color){
9 return {type: type, color: color};
10 }, ['red', 'blue', 'green']);
11}, ['apple', 'fish', 'cup']));
12
13var exampleContext = {
14 shared: [{type:'apple',color:'red'},{type:'fish',color:'blue'},{type:'cup',color:'green'}],
15 occluded: [{type:'fish',color:'red'}]
16};
17
18var alpha = 4;
19
20var uttCost = function(utt) {
21 return utt.split(' ').length / 4;
22};
23
24var uttFitness = function(utt, object) {
25 var descriptors = utt.split(' ');
26 var allMatch = all(function(d){
27 return d === object.type || d === object.color;
28 }, descriptors);
29 return allMatch ? 0 : -100;
30};
31
32var L0 = function(utt, perceivedContext) {
33 return Infer({method: 'enumerate'}, function(){
34 var object = uniformDraw(perceivedContext);
35 factor(uttFitness(utt, object));
36 return object;
37 });
38};
39
40var S1 = function(target, perceivedContext) {
41 return Infer({method: 'enumerate'}, function(){
42 var utt = uniformDraw(possibleUtterances);
43 // marginalize over uncertainty about hidden additional object
44 var listenerDist = Infer({method: 'enumerate'}, function(){
45 var hiddenObj = uniformDraw(possibleObjects);
46 var expandedContext = perceivedContext.concat([hiddenObj]);
47 var l0 = L0(utt, expandedContext);
48 var obj = sample(l0);
49 return obj;
50 });
51 factor(alpha * listenerDist.score(target) - uttCost(utt));
52 return utt;
53 });
54};
55
56var L2 = function(utt, context) {
57 var sharedContext = context.shared;
58 var fullContext = context.shared.concat(context.occluded);
59 return Infer({method: 'enumerate'}, function(){
60 var object = uniformDraw(fullContext);
61 var s1 = S1(object, sharedContext);
62 observe(s1, utt);
63 return object.color + ' ' + object.type;
64 });
65};
66
67var ANSWER = L2('fish', exampleContext);
02output overlaydistribution
GT s46 +p4 bins
00.430.430.860.86red fish A = 0.142 B = 0.142red fish A = 0.142 B = 0.1420.140.14red fishgreen cup A = 0.000 B = 0.000green cup A = 0.000 B = 0.000green cupblue fish A = 0.858 B = 0.858blue fish A = 0.858 B = 0.8580.860.86blue fishred apple A = 0.000 B = 0.000red apple A = 0.000 B = 0.000red apple
03 other runs 1 total
run flags bucket TV KL actions
sonnet-46-primer-forestdb primary sonnet-4.6 +primer TV=0 0.000 -0.0000 ·
forestdb-kids-scope / atom-1
shape distribution s46 +p TV=00.000 runs 1/1
per-run
00 prompt

Implement a scope ambiguity RSA model for 'every-not' utterances in WebPPL. There are numHorses=2 horses. The world state is the count of true (red) horses (0, 1, or 2). statePrior() samples via: a recursive stateMaker function that flips a baserate=0.5 coin for each of numHorses horses and tallies up the number of true values. Utterances are ['null','every-not'] with uniform prior. Cost is uniform: cost(utterance)=1. Scopes are ['surface','inverse'] with categorical([.5,.5]). meaning(utterance,state,scope): for 'every-not', surface scope means state==0 (not any horse is red), inverse scope means state<numHorses (not all horses are red); 'null' is always true. QUDs are ['how many?','all red?','none red?'] with uniform prior. QUDFun(QUD,state): 'all red?' returns state==numHorses, 'none red?' returns state==0, else state. Literal listener (L0, cached) takes (utterance,scope,QUD): uniformDraw(states=[0,1,2]), apply QUDFun, condition on meaning, return qState. Speaker (S1, cached, alpha=1) takes (scope,state,QUD): utterancePrior(), factor by alpha*(L0.score(QUDFun(QUD,state)) - cost(utterance)). Pragmatic listener (L1, cached) takes utterance: sample statePrior, scopePrior, QUDPrior, observe S1(scope,state,QUD), return state. Pragmatic speaker (S2, cached) takes state: utterancePrior(), factor by L1(utterance).score(state). Return the pragmatic speaker's distribution over utterances for state=1 (one horse is red — the 'not all' world state).

system prompt constant across atoms
(system prompt loads here)
WebPPL primer applied to *-primer-* runs
(primer loads here)
01 code comparing GT vs s46 +p
GTground truth
webppl
1// helper function to tally up the state
2var numTrue = function(state) {
3 var fun = function(x) {
4 x ? 1 : 0
5 }
6 return sum(map(fun,state))
7}
8
9// possible utterances
10var utterances = ["null","every-not"];
11var utterancePrior = function() {
12 uniformDraw(utterances)
13}
14// uniform utterance cost
15var cost = function(utterance) {
16 return 1
17}
18
19// possible world states
20var numHorses = 2
21var states = [0,1,2]
22var baserate = 0.5 // change to manipulate prior on world states
23var stateMaker = function(numHorses,stateSoFar) {
24 if (numHorses == 0) {
25 return stateSoFar
26 } else {
27 var newHorse = flip(baserate)
28 var newState = stateSoFar.concat([newHorse])
29 return stateMaker(numHorses - 1, newState)
30 }
31}
32var statePrior = function() {
33 return numTrue(stateMaker(numHorses,[]))
34}
35
36// possible scope interpretations
37var scopes = ["surface", "inverse"]
38var scopePrior = function(){
39 return categorical([.5,.5],scopes) // change to manipulate prior on scope interpretations
40}
41
42
43// meaning function
44var meaning = function(utterance, state, scope) {
45 return utterance == "every-not" ?
46 scope == "surface" ? state == 0 :
47 state < numHorses :
48 true;
49};
50
51// possible QUDs
52var QUDs = ["how many?","all red?","none red?"];
53var QUDPrior = function() {
54 uniformDraw(QUDs);
55 // categorical([.05,.05,.9],QUDs) // change to manipulate prior on QUDs
56}
57var QUDFun = function(QUD,state) {
58 QUD == "all red?" ? state == numHorses :
59 QUD == "none red?" ? state == 0 :
60 state;
61};
62
63// Literal listener (L0)
64var literalListener = cache(function(utterance,scope,QUD) {
65 Infer({model: function(){
66 var state = uniformDraw(states);
67 var qState = QUDFun(QUD,state)
68 condition(meaning(utterance,state,scope));
69 return qState;
70 }});
71});
72
73var alpha = 1
74
75// Speaker (S1)
76var speaker = cache(function(scope, state, QUD) {
77 return Infer({model: function(){
78 var utterance = utterancePrior()
79 var qState = QUDFun(QUD, state)
80 factor(alpha*(literalListener(utterance,scope,QUD).score(qState)
81 - cost(utterance)))
82 return utterance
83 }})
84})
85
86// Pragmatic listener (L1)
87var pragmaticListener = cache(function(utterance) {
88 Infer({model: function(){
89 var state = statePrior();
90 var scope = scopePrior();
91 var QUD = QUDPrior();
92 observe(speaker(scope,state,QUD),utterance);
93 return state
94 }});
95});
96
97// Pragmatic speaker (S2)
98var pragmaticSpeaker = cache(function(state) {
99 Infer({model: function(){
100 var utterance = utterancePrior();
101 factor(pragmaticListener(utterance).score(state))
102 return utterance
103 }})
104})
105
106// A speaker decides whether to endorse the ambiguous utterance as a
107// description of the not-all world state
108display(pragmaticSpeaker(1))
109
110var ANSWER = (pragmaticSpeaker(1));
111
s46 +psonnet-46-primer-forestdbTV=00.000
webppl
1var numHorses = 2;
2var baserate = 0.5;
3var alpha = 1;
4
5var states = [0, 1, 2];
6var utterances = ['null', 'every-not'];
7var scopes = ['surface', 'inverse'];
8var quds = ['how many?', 'all red?', 'none red?'];
9
10var stateMaker = function(n, acc) {
11 if (n === 0) return acc;
12 var coin = flip(baserate);
13 return stateMaker(n - 1, acc + (coin ? 1 : 0));
14};
15
16var statePrior = function() {
17 return stateMaker(numHorses, 0);
18};
19
20var utterancePrior = function() {
21 return uniformDraw(utterances);
22};
23
24var scopePrior = function() {
25 return categorical({vs: scopes, ps: [0.5, 0.5]});
26};
27
28var qudPrior = function() {
29 return uniformDraw(quds);
30};
31
32var cost = function(utterance) {
33 return 1;
34};
35
36var meaning = function(utterance, state, scope) {
37 if (utterance === 'every-not') {
38 if (scope === 'surface') {
39 return state === 0;
40 } else {
41 return state < numHorses;
42 }
43 } else {
44 return true;
45 }
46};
47
48var QUDFun = function(qud, state) {
49 if (qud === 'all red?') return state === numHorses;
50 if (qud === 'none red?') return state === 0;
51 return state;
52};
53
54var L0 = mem(function(utterance, scope, qud) {
55 return Infer({method: 'enumerate'}, function() {
56 var state = uniformDraw(states);
57 var qState = QUDFun(qud, state);
58 condition(meaning(utterance, state, scope));
59 return qState;
60 });
61});
62
63var S1 = mem(function(scope, state, qud) {
64 return Infer({method: 'enumerate'}, function() {
65 var utterance = utterancePrior();
66 var qState = QUDFun(qud, state);
67 factor(alpha * (L0(utterance, scope, qud).score(qState) - cost(utterance)));
68 return utterance;
69 });
70});
71
72var L1 = mem(function(utterance) {
73 return Infer({method: 'enumerate'}, function() {
74 var state = statePrior();
75 var scope = scopePrior();
76 var qud = qudPrior();
77 observe(S1(scope, state, qud), utterance);
78 return state;
79 });
80});
81
82var S2 = mem(function(state) {
83 return Infer({method: 'enumerate'}, function() {
84 var utterance = utterancePrior();
85 factor(L1(utterance).score(state));
86 return utterance;
87 });
88});
89
90var ANSWER = S2(1);
02output overlaydistribution
GT s46 +p2 bins
00.250.250.510.51every-not A = 0.506 B = 0.506every-not A = 0.506 B = 0.5060.510.51every-notnull A = 0.494 B = 0.494null A = 0.494 B = 0.4940.490.49null
03 other runs 1 total
run flags bucket TV KL actions
sonnet-46-primer-forestdb primary sonnet-4.6 +primer TV=0 0.000 0.0000 ·
forestdb-kids-scope / atom-2
shape distribution s46 +p TV=00.000 runs 1/1
per-run
00 prompt

An RSA scope ambiguity model for "two-not" utterances in a 1-of-2 context (2 horses, 0/1/2 fed). A pragmatic speaker at world state 1 (only 1 of 2 horses fed) decides whether to endorse "two-not".

utterances = ["null", "two-not"]. utterancePrior: uniformDraw(utterances). cost(utterance): 1. numHorses = 2. states = [0,1,2]. baserate = 0.5. stateMaker(numHorses, stateSoFar): recursive, flip(baserate) for each horse, concatenates boolean array. statePrior: numTrue(stateMaker(numHorses,[])) — returns count 0,1,2. scopePrior: categorical([0.5,0.5], ["surface","inverse"]). meaning(utterance, state, scope): two-not ? surface ? state==0 : state<numHorses : true. QUDs = ["many?","all?","none?"]. QUDPrior: uniformDraw(QUDs). QUDFun(QUD,state): all?->state==numHorses, none?->state==0, else state. literalListener(utterance, scope, QUD): Infer over uniformDraw(states), conditions on meaning, returns QUDFun(QUD,state). alpha = 1. speaker(scope, state, QUD): Infer, factor(alpha*(literalListener(utterance,scope,QUD).score(QUDFun(QUD,state))-cost(utterance))). pragmaticListener(utterance): Infer, samples state/scope/QUD, observes speaker(scope,state,QUD). pragmaticSpeaker(state): Infer, utterancePrior, factor(pragmaticListener(utterance).score(state)), returns utterance.

Compute pragmaticSpeaker(1). Return distribution over utterances ["null", "two-not"] when 1 of 2 horses was fed.

system prompt constant across atoms
(system prompt loads here)
WebPPL primer applied to *-primer-* runs
(primer loads here)
01 code comparing GT vs s46 +p
GTground truth
webppl
1// tally up the state
2var numTrue = function(state) {
3 var fun = function(x) {
4 x ? 1 : 0
5 }
6 return sum(map(fun,state))
7}
8
9// possible utterances
10var utterances = ["null","two-not"];
11var utterancePrior = function() {
12 uniformDraw(utterances)
13}
14// uniform utterance cost
15var cost = function(utterance) {
16 return 1
17}
18
19// possible world states
20var numHorses = 2
21var states = [0,1,2]
22var baserate = 0.5 // change to manipulate prior on world states
23var stateMaker = function(numHorses,stateSoFar) {
24 if (numHorses == 0) {
25 return stateSoFar
26 } else {
27 var newHorse = flip(baserate)
28 var newState = stateSoFar.concat([newHorse])
29 return stateMaker(numHorses - 1, newState)
30 }
31}
32var statePrior = function() {
33 return numTrue(stateMaker(numHorses,[]))
34}
35
36// possible scope interpretations
37var scopes = ["surface", "inverse"]
38var scopePrior = function(){
39 return categorical([.5,.5],scopes) // change to manipulate prior on scope interpretations
40}
41
42// meaning function
43var meaning = function(utterance, state, scope) {
44 if (utterance == "two-not") {
45 if (scope == "surface") {
46 return state == 0
47 } else {
48 return state < numHorses
49 }
50 } else {
51 return true;
52 }
53};
54
55// possible QUDs
56var QUDs = ["many?","all?","none?"];
57var QUDPrior = function() {
58 uniformDraw(QUDs);
59 // categorical([.05,.9,.05],QUDs) // change to manipulate prior on QUDs
60}
61var QUDFun = function(QUD,state) {
62 QUD == "all?" ? state == numHorses :
63 QUD == "none?" ? state == 0 :
64 state;
65};
66
67// Literal listener (L0)
68var literalListener = cache(function(utterance,scope,QUD) {
69 Infer({model: function(){
70 var state = uniformDraw(states);
71 var qState = QUDFun(QUD,state)
72 condition(meaning(utterance,state,scope));
73 return qState;
74 }});
75});
76
77var alpha = 1
78
79// Speaker (S1)
80var speaker = cache(function(scope, state, QUD) {
81 return Infer({model: function(){
82 var utterance = utterancePrior()
83 var qState = QUDFun(QUD, state)
84 factor(alpha*(literalListener(utterance,scope,QUD).score(qState)
85 - cost(utterance)))
86 return utterance
87 }})
88})
89
90// Pragmatic listener (L1)
91var pragmaticListener = cache(function(utterance) {
92 Infer({model: function(){
93 var state = statePrior();
94 var scope = scopePrior();
95 var QUD = QUDPrior();
96 observe(speaker(scope,state,QUD),utterance);
97 return state
98 }});
99});
100
101// Pragmatic speaker (S2)
102var pragmaticSpeaker = cache(function(state) {
103 Infer({model: function(){
104 var utterance = utterancePrior();
105 factor(pragmaticListener(utterance).score(state))
106 return utterance
107 }})
108})
109
110// A speaker decides whether to endorse the ambiguous utterance as a
111// description of the not-all world state
112display(pragmaticSpeaker(1))
113
114var ANSWER = (pragmaticSpeaker(1));
115
s46 +psonnet-46-primer-forestdbTV=00.000
webppl
1var numHorses = 2;
2var states = [0, 1, 2];
3var baserate = 0.5;
4var utterances = ["null", "two-not"];
5var QUDs = ["many?", "all?", "none?"];
6var alpha = 1;
7
8var cost = function(utterance) { return 1; };
9
10var utterancePrior = function() { return uniformDraw(utterances); };
11
12var stateMaker = function(numHorses, stateSoFar) {
13 if (numHorses === 0) {
14 return stateSoFar;
15 } else {
16 var horseFed = flip(baserate);
17 return stateMaker(numHorses - 1, stateSoFar.concat([horseFed]));
18 }
19};
20
21var numTrue = function(arr) {
22 return reduce(function(x, acc) { return x ? acc + 1 : acc; }, 0, arr);
23};
24
25var statePrior = function() {
26 return numTrue(stateMaker(numHorses, []));
27};
28
29var scopePrior = function() {
30 return categorical([0.5, 0.5], ["surface", "inverse"]);
31};
32
33var QUDPrior = function() {
34 return uniformDraw(QUDs);
35};
36
37var QUDFun = function(QUD, state) {
38 if (QUD === "all?") {
39 return state === numHorses;
40 } else if (QUD === "none?") {
41 return state === 0;
42 } else {
43 return state;
44 }
45};
46
47var meaning = function(utterance, state, scope) {
48 if (utterance === "two-not") {
49 if (scope === "surface") {
50 return state === 0;
51 } else {
52 return state < numHorses;
53 }
54 } else {
55 return true;
56 }
57};
58
59var literalListener = mem(function(utterance, scope, QUD) {
60 return Infer({method: 'enumerate'}, function() {
61 var state = uniformDraw(states);
62 condition(meaning(utterance, state, scope));
63 return QUDFun(QUD, state);
64 });
65});
66
67var speaker = mem(function(scope, state, QUD) {
68 return Infer({method: 'enumerate'}, function() {
69 var utterance = utterancePrior();
70 var qudVal = QUDFun(QUD, state);
71 var score = literalListener(utterance, scope, QUD).score(qudVal);
72 factor(alpha * (score - cost(utterance)));
73 return utterance;
74 });
75});
76
77var pragmaticListener = mem(function(utterance) {
78 return Infer({method: 'enumerate'}, function() {
79 var state = statePrior();
80 var scope = scopePrior();
81 var QUD = QUDPrior();
82 observe(speaker(scope, state, QUD), utterance);
83 return state;
84 });
85});
86
87var pragmaticSpeaker = function(state) {
88 return Infer({method: 'enumerate'}, function() {
89 var utterance = utterancePrior();
90 observe(pragmaticListener(utterance), state);
91 return utterance;
92 });
93};
94
95var ANSWER = pragmaticSpeaker(1);
02output overlaydistribution
GT s46 +p2 bins
00.250.250.510.51two-not A = 0.506 B = 0.506two-not A = 0.506 B = 0.5060.510.51two-notnull A = 0.494 B = 0.494null A = 0.494 B = 0.4940.490.49null
03 other runs 1 total
run flags bucket TV KL actions
sonnet-46-primer-forestdb primary sonnet-4.6 +primer TV=0 0.000 0.0000 ·
forestdb-lai-irony / atom-1
shape distribution s46 +p TV=00.000 runs 1/1
per-run
00 prompt

Implement the Kao & Goodman (2015) irony RSA model for weather state inference.

Context: The model is set in California where good weather is likely. Speakers may be ironic — saying 'terrible' when the weather is actually amazing.

Setup: - states = ['terrible', 'ok', 'amazing'] - statePrior(): categorical([1, 50, 50], states) // California prior: ok and amazing are likely - valencePrior(state): if 'terrible' flip(0.99)?-1:1; if 'ok' flip(0.5)?-1:1; if 'amazing' flip(0.01)?-1:1 - arousals = ['low', 'high'] - arousalPrior(state): if 'terrible' categorical([0.1,0.9],arousals); if 'ok' categorical([0.9,0.1],arousals); if 'amazing' categorical([0.1,0.9],arousals) - goals = ['goalState', 'goalValence', 'goalArousal'] - goalPrior(): categorical([1,1,1], goals) - utterances = states; utterancePrior(): uniformDraw(utterances) - literalInterpretation(utterance, state): utterance === state - goalState(goal, state, valence, arousal): returns state / valence / arousal based on goal - literalListener(utterance, goal): Infer over uniformDraw(states), valence=valencePrior(state), arousal=arousalPrior(state); condition on literalInterpretation; return goalState(goal,state,valence,arousal) - speaker(state, valence, arousal, goal): Infer over utterancePrior(); factor 1 * literalListener(utt,goal).score(goalState(goal,state,valence,arousal)); return utt - pragmaticListener(utterance): Infer over statePrior(), valencePrior, arousalPrior, goalPrior(); observe speaker(state,valence,arousal,goal) given utterance; return {state, valence, arousal, goal}

Bind pragmaticListener to a function of that exact name.

Return the pragmaticListener distribution for the utterance 'terrible': pragmaticListener('terrible')

system prompt constant across atoms
(system prompt loads here)
WebPPL primer applied to *-primer-* runs
(primer loads here)
01 code comparing GT vs s46 +p
GTground truth
webppl
1// There are three possible states the weather could be in:
2// terrible, ok, or amazing
3var states = ['terrible', 'ok', 'amazing']
4
5// Since we are in California, the prior over these states
6// are the following. Once could also imagine this being
7// the prior in a certain context, e.g. when it's clearly
8// sunny and nice out.
9var statePrior = function() {
10 categorical([1, 50, 50], states)
11}
12
13// Valence prior defined in terms of negative valence.
14// If the current state is terrible, it's extremely likely
15// that the valence associated is negative. If it's ok, then
16// the valence could be negative or positive with equal
17// probability.
18var valencePrior = function(state) {
19 state === "terrible" ? flip(0.99) ? -1 : 1 :
20 state === "ok" ? flip(0.5) ? -1 : 1 :
21 state === "amazing" ? flip(0.01) ? -1 : 1 :
22 true
23}
24
25// Define binary arousals (could model as continuous).
26var arousals = ["low", "high"]
27
28// Define goals and goal priors. Could want to communicate state of the world,
29// valence about it, or arousal (intensity of feeling) about it.
30var goals = ["goalState", "goalValence", "goalArousal"]
31
32var goalPrior = function() {
33 categorical([1, 1, 1], goals)
34}
35
36// Assume possible utterances are identical to possible states
37var utterances = states
38
39// Assume cost of utterances is uniform.
40var utterancePrior = function() {
41 uniformDraw(utterances)
42}
43
44// Sample arousal given a state.
45var arousalPrior = function(state) {
46 state === "terrible" ? categorical([0.1, 0.9], arousals) :
47 state === "ok" ? categorical([0.9, 0.1], arousals) :
48 state === "amazing" ? categorical([0.1, 0.9], arousals) :
49 true
50}
51
52// Literal interpretation is just whether utterance equals state
53var literalInterpretation = function(utterance, state) {
54 utterance === state
55}
56
57// A speaker's goal is satisfied if the listener infers the correct
58// and relevant information.
59var goalState = function(goal, state, valence, arousal) {
60 goal === "goalState" ? state :
61 goal === "goalValence" ? valence :
62 goal === "goalArousal" ? arousal :
63 true
64}
65
66// Define a literal listener
67var literalListener = function(utterance, goal) {
68 Infer({model: function(){
69 var state = uniformDraw(states)
70 var valence = valencePrior(state)
71 var arousal = arousalPrior(state)
72 condition(literalInterpretation(utterance,state))
73 return goalState(goal, state, valence, arousal)
74 }})
75}
76
77// Define a speaker
78var speaker = function(state, valence, arousal, goal) {
79 Infer({model: function(){
80 var utterance = utterancePrior()
81 factor(1 * literalListener(utterance,
82 goal).score(goalState(goal,
83 state,
84 valence,
85 arousal)))
86 return utterance
87 }})
88}
89
90// Define a pragmatic listener
91var pragmaticListener = function(utterance) {
92 Infer({model: function(){
93 var state = statePrior()
94 var valence = valencePrior(state)
95 var arousal = arousalPrior(state)
96 var goal = goalPrior()
97 observe(speaker(state, valence, arousal, goal),utterance)
98 return {state, valence, arousal, goal}
99 }})
100}
101
102viz.table(literalListener("terrible", "goalState"))
103viz.table(speaker("terrible", -1, "high", "goalValence"))
104viz.table(pragmaticListener("terrible"))
105
106var ANSWER = (pragmaticListener('terrible'));
107
s46 +psonnet-46-primer-forestdbTV=00.000
webppl
1var states = ['terrible', 'ok', 'amazing'];
2
3var statePrior = function() {
4 return categorical([1, 50, 50], states);
5};
6
7var valencePrior = function(state) {
8 if (state === 'terrible') {
9 return flip(0.99) ? -1 : 1;
10 } else if (state === 'ok') {
11 return flip(0.5) ? -1 : 1;
12 } else if (state === 'amazing') {
13 return flip(0.01) ? -1 : 1;
14 }
15};
16
17var arousals = ['low', 'high'];
18
19var arousalPrior = function(state) {
20 if (state === 'terrible') {
21 return categorical([0.1, 0.9], arousals);
22 } else if (state === 'ok') {
23 return categorical([0.9, 0.1], arousals);
24 } else if (state === 'amazing') {
25 return categorical([0.1, 0.9], arousals);
26 }
27};
28
29var goals = ['goalState', 'goalValence', 'goalArousal'];
30
31var goalPrior = function() {
32 return categorical([1, 1, 1], goals);
33};
34
35var utterances = states;
36
37var utterancePrior = function() {
38 return uniformDraw(utterances);
39};
40
41var literalInterpretation = function(utterance, state) {
42 return utterance === state;
43};
44
45var goalState = function(goal, state, valence, arousal) {
46 if (goal === 'goalState') {
47 return state;
48 } else if (goal === 'goalValence') {
49 return valence;
50 } else if (goal === 'goalArousal') {
51 return arousal;
52 }
53};
54
55var literalListener = mem(function(utterance, goal) {
56 return Infer({method: 'enumerate'}, function() {
57 var state = uniformDraw(states);
58 var valence = valencePrior(state);
59 var arousal = arousalPrior(state);
60 condition(literalInterpretation(utterance, state));
61 return goalState(goal, state, valence, arousal);
62 });
63});
64
65var speaker = mem(function(state, valence, arousal, goal) {
66 return Infer({method: 'enumerate'}, function() {
67 var utt = utterancePrior();
68 factor(1 * literalListener(utt, goal).score(goalState(goal, state, valence, arousal)));
69 return utt;
70 });
71});
72
73var pragmaticListener = function(utterance) {
74 return Infer({method: 'enumerate'}, function() {
75 var state = statePrior();
76 var valence = valencePrior(state);
77 var arousal = arousalPrior(state);
78 var goal = goalPrior();
79 observe(speaker(state, valence, arousal, goal), utterance);
80 return {state: state, valence: valence, arousal: arousal, goal: goal};
81 });
82};
83
84var ANSWER = pragmaticListener('terrible');
02output overlaydistribution
GT s46 +p28 bins
00.220.220.440.44{"state":"amazing","valence":1,"arousal":"high","goal":"goalArousal"} A = 0.443 B = 0.443{"state":"amazing","valence":1,"arousal":"high","goal":"goalArousal"} A = 0.443 B = 0.443{"state":"amazing","valence":1,"arousal":"high","goal":"goalArousal"}{"state":"amazing","valence":1,"arousal":"high","goal":"goalValence"} A = 0.006 B = 0.006{"state":"amazing","valence":1,"arousal":"high","goal":"goalValence"} A = 0.006 B = 0.006{"state":"amazing","valence":1,"arousal":"low","goal":"goalArousal"} A = 0.009 B = 0.009{"state":"amazing","valence":1,"arousal":"low","goal":"goalArousal"} A = 0.009 B = 0.009{"state":"amazing","valence":1,"arousal":"low","goal":"goalArousal"}{"state":"amazing","valence":1,"arousal":"low","goal":"goalValence"} A = 0.001 B = 0.001{"state":"amazing","valence":1,"arousal":"low","goal":"goalValence"} A = 0.001 B = 0.001{"state":"amazing","valence":-1,"arousal":"high","goal":"goalArousal"} A = 0.004 B = 0.004{"state":"amazing","valence":-1,"arousal":"high","goal":"goalArousal"} A = 0.004 B = 0.004{"state":"amazing","valence":-1,"arousal":"high","goal":"goalArousal"}{"state":"amazing","valence":-1,"arousal":"high","goal":"goalValence"} A = 0.006 B = 0.006{"state":"amazing","valence":-1,"arousal":"high","goal":"goalValence"} A = 0.006 B = 0.006{"state":"amazing","valence":-1,"arousal":"low","goal":"goalArousal"} A = 0.000 B = 0.000{"state":"amazing","valence":-1,"arousal":"low","goal":"goalArousal"} A = 0.000 B = 0.000{"state":"amazing","valence":-1,"arousal":"low","goal":"goalArousal"}{"state":"amazing","valence":-1,"arousal":"low","goal":"goalValence"} A = 0.001 B = 0.001{"state":"amazing","valence":-1,"arousal":"low","goal":"goalValence"} A = 0.001 B = 0.001{"state":"ok","valence":1,"arousal":"high","goal":"goalArousal"} A = 0.025 B = 0.025{"state":"ok","valence":1,"arousal":"high","goal":"goalArousal"} A = 0.025 B = 0.025{"state":"ok","valence":1,"arousal":"high","goal":"goalArousal"}{"state":"ok","valence":1,"arousal":"high","goal":"goalValence"} A = 0.000 B = 0.000{"state":"ok","valence":1,"arousal":"high","goal":"goalValence"} A = 0.000 B = 0.000{"state":"ok","valence":1,"arousal":"low","goal":"goalArousal"} A = 0.043 B = 0.043{"state":"ok","valence":1,"arousal":"low","goal":"goalArousal"} A = 0.043 B = 0.043{"state":"ok","valence":1,"arousal":"low","goal":"goalArousal"}{"state":"ok","valence":1,"arousal":"low","goal":"goalValence"} A = 0.003 B = 0.003{"state":"ok","valence":1,"arousal":"low","goal":"goalValence"} A = 0.003 B = 0.003{"state":"ok","valence":-1,"arousal":"high","goal":"goalArousal"} A = 0.025 B = 0.025{"state":"ok","valence":-1,"arousal":"high","goal":"goalArousal"} A = 0.025 B = 0.025{"state":"ok","valence":-1,"arousal":"high","goal":"goalArousal"}{"state":"ok","valence":-1,"arousal":"high","goal":"goalValence"} A = 0.035 B = 0.035{"state":"ok","valence":-1,"arousal":"high","goal":"goalValence"} A = 0.035 B = 0.035{"state":"ok","valence":-1,"arousal":"low","goal":"goalArousal"} A = 0.043 B = 0.043{"state":"ok","valence":-1,"arousal":"low","goal":"goalArousal"} A = 0.043 B = 0.043{"state":"ok","valence":-1,"arousal":"low","goal":"goalArousal"}{"state":"ok","valence":-1,"arousal":"low","goal":"goalValence"} A = 0.312 B = 0.312{"state":"ok","valence":-1,"arousal":"low","goal":"goalValence"} A = 0.312 B = 0.312{"state":"terrible","valence":1,"arousal":"high","goal":"goalArousal"} A = 0.000 B = 0.000{"state":"terrible","valence":1,"arousal":"high","goal":"goalArousal"} A = 0.000 B = 0.000{"state":"terrible","valence":1,"arousal":"high","goal":"goalArousal"}{"state":"terrible","valence":1,"arousal":"high","goal":"goalValence"} A = 0.000 B = 0.000{"state":"terrible","valence":1,"arousal":"high","goal":"goalValence"} A = 0.000 B = 0.000{"state":"terrible","valence":1,"arousal":"high","goal":"goalState"} A = 0.000 B = 0.000{"state":"terrible","valence":1,"arousal":"high","goal":"goalState"} A = 0.000 B = 0.000{"state":"terrible","valence":1,"arousal":"high","goal":"goalState"}{"state":"terrible","valence":1,"arousal":"low","goal":"goalArousal"} A = 0.000 B = 0.000{"state":"terrible","valence":1,"arousal":"low","goal":"goalArousal"} A = 0.000 B = 0.000{"state":"terrible","valence":1,"arousal":"low","goal":"goalValence"} A = 0.000 B = 0.000{"state":"terrible","valence":1,"arousal":"low","goal":"goalValence"} A = 0.000 B = 0.000{"state":"terrible","valence":1,"arousal":"low","goal":"goalValence"}{"state":"terrible","valence":1,"arousal":"low","goal":"goalState"} A = 0.000 B = 0.000{"state":"terrible","valence":1,"arousal":"low","goal":"goalState"} A = 0.000 B = 0.000{"state":"terrible","valence":-1,"arousal":"high","goal":"goalArousal"} A = 0.009 B = 0.009{"state":"terrible","valence":-1,"arousal":"high","goal":"goalArousal"} A = 0.009 B = 0.009{"state":"terrible","valence":-1,"arousal":"high","goal":"goalArousal"}{"state":"terrible","valence":-1,"arousal":"high","goal":"goalValence"} A = 0.012 B = 0.012{"state":"terrible","valence":-1,"arousal":"high","goal":"goalValence"} A = 0.012 B = 0.012{"state":"terrible","valence":-1,"arousal":"high","goal":"goalState"} A = 0.019 B = 0.019{"state":"terrible","valence":-1,"arousal":"high","goal":"goalState"} A = 0.019 B = 0.019{"state":"terrible","valence":-1,"arousal":"high","goal":"goalState"}{"state":"terrible","valence":-1,"arousal":"low","goal":"goalArousal"} A = 0.000 B = 0.000{"state":"terrible","valence":-1,"arousal":"low","goal":"goalArousal"} A = 0.000 B = 0.000{"state":"terrible","valence":-1,"arousal":"low","goal":"goalValence"} A = 0.001 B = 0.001{"state":"terrible","valence":-1,"arousal":"low","goal":"goalValence"} A = 0.001 B = 0.001{"state":"terrible","valence":-1,"arousal":"low","goal":"goalValence"}{"state":"terrible","valence":-1,"arousal":"low","goal":"goalState"} A = 0.002 B = 0.002{"state":"terrible","valence":-1,"arousal":"low","goal":"goalState"} A = 0.002 B = 0.002
03 other runs 1 total
run flags bucket TV KL actions
sonnet-46-primer-forestdb primary sonnet-4.6 +primer TV=0 0.000 0.0000 ·
forestdb-lxz-chinese-scope / atom-1
shape distribution s46 +p TV=00.000 runs 1/1
per-run
00 prompt

Implement an RSA model of quantifier scope ambiguity for English (Experiment 1: surface scope context) in WebPPL. States are [0,1,2] with categorical({vs:[0,1,2],ps:[1,1,1]}). Utterances are ['null','not-two'] with categorical({vs:['null','not-two'],ps:[1,1]}). cost(utterance)=1 for all utterances. Scopes are ['surface','inverse'] with categorical({vs:['surface','inverse'],ps:[1,1]}). meaning(utterance,state,scope): for 'not-two', surface scope means state==0 || state==1; inverse scope means state==0; 'null' is always true. QUDs are ['how many?','all red?','none red?'] with uniform prior. QUDFun(QUD,state): 'all red?' returns state==2, 'none red?' returns state==0, else state. Literal listener (L0, cached) takes (utterance,scope,QUD): uniformDraw(states), apply QUDFun, condition on meaning, return qState. Speaker (S, cached, alpha=1) takes (scope,state,QUD): utterancePrior(), factor by alpha*(L0(utterance,scope,QUD).score(QUDFun(QUD,state))-cost(utterance)). Pragmatic listener (L1, cached) takes utterance: statePrior, scopePrior, QUDPrior, observe S(scope,state,QUD). Pragmatic speaker (S2, cached) takes state: utterancePrior, factor by L1(utterance).score(state). Return the pragmatic speaker's distribution over utterances for state=1 (one rabbit was fed — the surface-scope-true, inverse-scope-false state).

system prompt constant across atoms
(system prompt loads here)
WebPPL primer applied to *-primer-* runs
(primer loads here)
01 code comparing GT vs s46 +p
GTground truth
webppl
1// Here is the code for English Expt 1 (surface scope)
2//different qud prior, different state prior, access to alternative utterances
3
4// Here is the code for the quantifier scope model
5
6// possible utterances
7var utterances = ["null","not-two"];
8
9var utterancePrior = function() {
10 categorical({vs:["null","not-two"],ps:[1,1]})
11}
12
13var cost = function(utterance) {
14 return 1
15}
16
17// possible world states
18var states = [0,1,2];
19var statePrior = function() {
20 categorical({vs:[0,1,2],ps:[1,1,1]})
21}
22
23// possible scopes
24var scopePrior = function(){
25 return categorical({vs:["surface", "inverse"],ps:[1,1]})
26}
27
28var meaning = function(utterance, state, scope) {
29 //if utterance == none:
30 //return state==0
31 //else:
32 //elif utternace == nottwo:
33 //if scope == surface:
34 //return state == 0 / state==1
35 //else:
36 //return state == 0
37 //else:
38 //return true
39
40 return utterance == "not-two" ?
41 scope == "surface" ? (state == 0 | state ==1):
42 state == 0 :
43 true;
44};
45
46
47// QUDs
48var QUDs = ["how many?","all red?","none red?"];
49var QUDPrior = function() {
50 uniformDraw(QUDs);
51}
52var QUDFun = function(QUD,state) {
53 QUD == "all red?" ? state == 2 :
54 QUD == "none red?" ? state == 0 :
55 state;
56};
57
58// Literal listener (L0)
59var literalListener = cache(function(utterance,scope,QUD) {
60 Infer({model: function(){
61 var state = uniformDraw(states);
62 var qState = QUDFun(QUD,state)
63 condition(meaning(utterance,state,scope));
64 return qState;
65 }});
66});
67
68var alpha = 1
69
70// Speaker (S)
71var speaker = cache(function(scope, state, QUD) {
72 return Infer({model: function(){
73 var utterance = utterancePrior()
74 var qState = QUDFun(QUD, state)
75 factor(alpha*(literalListener(utterance,scope,QUD).score(qState)
76 - cost(utterance)))
77 return utterance
78 }})
79})
80
81// Pragmatic listener (L1)
82var pragmaticListener = cache(function(utterance) {
83 Infer({model: function(){
84 var state = statePrior();
85 var scope = scopePrior();
86 var QUD = QUDPrior();
87 observe(speaker(scope,state,QUD),utterance);
88 return state
89 }});
90});
91
92// Pragmatic speaker (S2)
93var pragmaticSpeaker = cache(function(state) {
94 Infer({model: function(){
95 var utterance = utterancePrior();
96 factor(pragmaticListener(utterance).score(state))
97 return utterance
98 }})
99})
100
101
102
103// A speaker decides whether to endorse the ambiguous utterance as a
104// description of the not-all world state
105viz.table(pragmaticSpeaker(1))
106viz(pragmaticSpeaker(1))
107//literalListener("surface", 2, "all red?")
108
109var ANSWER = (pragmaticSpeaker(1));
110
s46 +psonnet-46-primer-forestdbTV=00.000
webppl
1var states = [0, 1, 2];
2var utterances = ['null', 'not-two'];
3var scopes = ['surface', 'inverse'];
4var quds = ['how many?', 'all red?', 'none red?'];
5
6var statePrior = function() {
7 return categorical({vs: states, ps: [1, 1, 1]});
8};
9
10var utterancePrior = function() {
11 return categorical({vs: utterances, ps: [1, 1]});
12};
13
14var scopePrior = function() {
15 return categorical({vs: scopes, ps: [1, 1]});
16};
17
18var qudPrior = function() {
19 return categorical({vs: quds, ps: [1, 1, 1]});
20};
21
22var cost = function(utterance) {
23 return 1;
24};
25
26var meaning = function(utterance, state, scope) {
27 if (utterance === 'not-two') {
28 if (scope === 'surface') {
29 return state === 0 || state === 1;
30 } else {
31 return state === 0;
32 }
33 } else {
34 return true;
35 }
36};
37
38var QUDFun = function(qud, state) {
39 if (qud === 'all red?') {
40 return state === 2;
41 } else if (qud === 'none red?') {
42 return state === 0;
43 } else {
44 return state;
45 }
46};
47
48var alpha = 1;
49
50var L0 = mem(function(utterance, scope, qud) {
51 return Infer({method: 'enumerate'}, function() {
52 var state = statePrior();
53 var qState = QUDFun(qud, state);
54 condition(meaning(utterance, state, scope));
55 return qState;
56 });
57});
58
59var S = mem(function(scope, state, qud) {
60 return Infer({method: 'enumerate'}, function() {
61 var utterance = utterancePrior();
62 var qState = QUDFun(qud, state);
63 factor(alpha * (L0(utterance, scope, qud).score(qState) - cost(utterance)));
64 return utterance;
65 });
66});
67
68var L1 = mem(function(utterance) {
69 return Infer({method: 'enumerate'}, function() {
70 var state = statePrior();
71 var scope = scopePrior();
72 var qud = qudPrior();
73 observe(S(scope, state, qud), utterance);
74 return state;
75 });
76});
77
78var S2 = mem(function(state) {
79 return Infer({method: 'enumerate'}, function() {
80 var utterance = utterancePrior();
81 factor(L1(utterance).score(state));
82 return utterance;
83 });
84});
85
86var ANSWER = S2(1);
02output overlaydistribution
GT s46 +p2 bins
00.250.250.510.51not-two A = 0.508 B = 0.508not-two A = 0.508 B = 0.5080.510.51not-twonull A = 0.492 B = 0.492null A = 0.492 B = 0.4920.490.49null
03 other runs 1 total
run flags bucket TV KL actions
sonnet-46-primer-forestdb primary sonnet-4.6 +primer TV=0 0.000 0.0000 ·
forestdb-lxz-chinese-scope / atom-2
shape distribution s46 +p TV<.050.038 runs 1/1
per-run
00 prompt

An RSA scope ambiguity model for English "not-two" utterances, Experiment 2 (4-object inverse scope context). 4 objects, states 0-4. A pragmatic speaker at state 2 (2 of 4 rabbits fed) decides whether to endorse "not-two".

utterances = ["null", "not-two"]. utterancePrior: categorical({vs:["null","not-two"], ps:[1,10]}) — strong prior toward "not-two". cost(utterance): both->1. states = [0,1,2,3,4]. statePrior: categorical({vs:[0,1,2,3,4], ps:[1,1,1,1,1]}). scopePrior: categorical({vs:["surface","inverse"], ps:[1,1]}). meaning(utterance, state, scope): not-two ? surface ? state<2 : state<3 : true. QUDs = ["how many?","all red?","none red?"]. QUDPrior: categorical({vs:[...], ps:[1,1,1]}). QUDFun(QUD,state): all red?->state==4, none red?->state==0, else state. literalListener(utterance, scope, QUD): Infer over uniformDraw(states), conditions on meaning, returns QUDFun(QUD,state). alpha = 1. speaker(scope, state, QUD): Infer, factor(alpha*(L0.score(QUDFun(QUD,state))-cost(utterance))). pragmaticListener(utterance): Infer, samples state/scope/QUD, observes speaker. pragmaticSpeaker(state): Infer, factor(pragmaticListener(utterance).score(state)), returns utterance.

Compute pragmaticSpeaker(2). Return distribution over utterances ["null", "not-two"] when 2 of 4 rabbits were fed.

system prompt constant across atoms
(system prompt loads here)
WebPPL primer applied to *-primer-* runs
(primer loads here)
01 code comparing GT vs s46 +p
GTground truth
webppl
1// Here is the code for English Expt 2 (inverse scope)
2//different qud prior, different state prior, access to alternative utterances
3
4// Here is the code for the quantifier scope model
5
6// possible utterances
7var utterances = ["null","not-two"];
8
9var utterancePrior = function() {
10 categorical({vs:["null","not-two"],ps:[1,10]})
11}
12
13var cost = function(utterance) {
14 return utterance == "not-two" ? 1 :
15 1
16}
17
18// possible world states
19var states = [0,1,2,3,4];
20var statePrior = function() {
21 categorical({vs:[0,1,2,3,4],ps:[1,1,1,1,1]})
22}
23
24// possible scopes
25var scopePrior = function(){
26 return categorical({vs:["surface", "inverse"],ps:[1,1]})
27}
28
29// meaning function
30var meaning = function(utterance, state, scope) {
31 return utterance == "not-two" ?
32 scope == "surface" ? (state < 2):
33 (state < 3) :
34 true;
35};
36
37// QUDs
38var QUDs = ["how many?","all red?","none red?"];
39var QUDPrior = function() {
40 categorical({vs:["how many?","all red?","none red?"],ps:[1,1,1]})
41 //uniformDraw(QUDs);
42}
43
44var QUDFun = function(QUD,state) {
45 QUD == "all red?" ? state == 4 :
46 QUD == "none red?" ? state == 0 :
47 state;
48};
49
50// Literal listener (L0)
51var literalListener = cache(function(utterance,scope,QUD) {
52 Infer({model: function(){
53 var state = uniformDraw(states);
54 var qState = QUDFun(QUD,state)
55 condition(meaning(utterance,state,scope));
56 return qState;
57 }});
58});
59
60var alpha = 1
61
62// Speaker (S)
63var speaker = cache(function(scope, state, QUD) {
64 return Infer({model: function(){
65 var utterance = utterancePrior()
66 var qState = QUDFun(QUD, state)
67 factor(alpha*(literalListener(utterance,scope,QUD).score(qState)
68 - cost(utterance)))
69 return utterance
70 }})
71})
72
73// Pragmatic listener (L1)
74var pragmaticListener = cache(function(utterance) {
75 Infer({model: function(){
76 var state = statePrior();
77 var scope = scopePrior();
78 var QUD = QUDPrior();
79 observe(speaker(scope,state,QUD),utterance);
80 return state
81 }});
82});
83
84// Pragmatic speaker (S2)
85var pragmaticSpeaker = cache(function(state) {
86 Infer({model: function(){
87 var utterance = utterancePrior();
88 factor(pragmaticListener(utterance).score(state))
89 return utterance
90 }})
91})
92
93// A speaker decides whether to endorse the ambiguous utterance as a
94// description of the not-all world state
95//viz.table(pragmaticSpeaker(0))
96viz.table(pragmaticSpeaker(2))
97//viz.table(pragmaticSpeaker(2))
98//literalListener("surface", 2, "all red?")
99
100var ANSWER = (pragmaticSpeaker(2));
101
s46 +psonnet-46-primer-forestdbTV<.050.038
webppl
1var states = [0, 1, 2, 3, 4];
2var utterances = ["null", "not-two"];
3var scopes = ["surface", "inverse"];
4var QUDs = ["how many?", "all red?", "none red?"];
5
6var statePrior = function() {
7 return categorical({vs: states, ps: [1, 1, 1, 1, 1]});
8};
9
10var utterancePrior = function() {
11 return categorical({vs: utterances, ps: [1, 10]});
12};
13
14var scopePrior = function() {
15 return categorical({vs: scopes, ps: [1, 1]});
16};
17
18var QUDPrior = function() {
19 return categorical({vs: QUDs, ps: [1, 1, 1]});
20};
21
22var cost = function(utterance) {
23 return 1;
24};
25
26var meaning = function(utterance, state, scope) {
27 if (utterance === "not-two") {
28 if (scope === "surface") {
29 return state !== 2;
30 } else {
31 return state < 3;
32 }
33 } else {
34 return true;
35 }
36};
37
38var QUDFun = function(QUD, state) {
39 if (QUD === "all red?") {
40 return state === 4;
41 } else if (QUD === "none red?") {
42 return state === 0;
43 } else {
44 return state;
45 }
46};
47
48var alpha = 1;
49
50var literalListener = mem(function(utterance, scope, QUD) {
51 return Infer({method: 'enumerate'}, function() {
52 var state = uniformDraw(states);
53 condition(meaning(utterance, state, scope));
54 return QUDFun(QUD, state);
55 });
56});
57
58var speaker = mem(function(scope, state, QUD) {
59 return Infer({method: 'enumerate'}, function() {
60 var utterance = utterancePrior();
61 var L0 = literalListener(utterance, scope, QUD);
62 factor(alpha * (L0.score(QUDFun(QUD, state)) - cost(utterance)));
63 return utterance;
64 });
65});
66
67var pragmaticListener = mem(function(utterance) {
68 return Infer({method: 'enumerate'}, function() {
69 var state = statePrior();
70 var scope = scopePrior();
71 var QUD = QUDPrior();
72 var S1 = speaker(scope, state, QUD);
73 observe(S1, utterance);
74 return state;
75 });
76});
77
78var pragmaticSpeaker = function(state) {
79 return Infer({method: 'enumerate'}, function() {
80 var utterance = utterancePrior();
81 var PL = pragmaticListener(utterance);
82 factor(PL.score(state));
83 return utterance;
84 });
85};
86
87var ANSWER = pragmaticSpeaker(2);
02output overlaydistribution
GT s46 +p2 bins
00.460.460.930.93not-two A = 0.930 B = 0.892not-two A = 0.930 B = 0.8920.930.89not-twonull A = 0.070 B = 0.108null A = 0.070 B = 0.1080.070.11null
03 other runs 1 total
run flags bucket TV KL actions
sonnet-46-primer-forestdb primary sonnet-4.6 +primer TV<.05 0.038 0.0095 ·
forestdb-lxz-chinese-scope / atom-3
shape distribution s46 +p TV=00.000 runs 1/1
per-run
00 prompt

An RSA scope ambiguity model for Mandarin "not-two" utterances, Experiment 1 (2-object surface-scope biased context). The model includes a third utterance "none" and a strongly surface-scope biased scopePrior. A pragmatic speaker at state 1 (1 of 2 rabbits fed) decides whether to endorse "not-two".

utterances = ["null", "not-two", "none"]. utterancePrior: categorical({vs:["null","not-two","none"], ps:[1,1,1]}). cost(utterance): all->1. states = [0,1,2]. statePrior: categorical({vs:[0,1,2], ps:[1,1,1]}). scopePrior: categorical({vs:["surface","inverse"], ps:[100,1]}) — strongly biased toward surface scope. meaning(utterance, state, scope): none->state==0, not-two ? surface ? state<2 : state==0 : true. QUDs = ["how many?","all red?","none red?"]. QUDPrior: categorical({vs:[...], ps:[1,1,1]}). QUDFun(QUD,state): all red?->state==2, none red?->state==0, else state. literalListener(utterance, scope, QUD): Infer over uniformDraw(states), conditions on meaning, returns QUDFun(QUD,state). alpha = 1. speaker(scope, state, QUD): Infer, factor(alpha*(L0.score(QUDFun(QUD,state))-cost(utterance))). pragmaticListener(utterance): Infer, samples state/scope/QUD, observes speaker. pragmaticSpeaker(state): Infer, factor(pragmaticListener(utterance).score(state)), returns utterance.

Compute pragmaticSpeaker(1). Return distribution over utterances ["null", "not-two", "none"] when 1 of 2 rabbits was fed.

system prompt constant across atoms
(system prompt loads here)
WebPPL primer applied to *-primer-* runs
(primer loads here)
01 code comparing GT vs s46 +p
GTground truth
webppl
1// Here is the code of Chinese model for Expt 1.
2//different qud prior, different state prior, access to alternative utterances
3
4// Here is the code for the quantifier scope model
5
6// possible utterances
7var utterances = ["null","not-two","none"];
8
9var utterancePrior = function() {
10 categorical({vs:["null","not-two","none"],ps:[1,1,1]})
11}
12
13var cost = function(utterance) {
14 return utterance == "not-two" ? 1 :
15 utterance == 'none'? 1 :
16 1
17}
18
19// possible world states
20var states = [0,1,2];
21var statePrior = function() {
22 categorical({vs:[0,1,2],ps:[1,1,1]})
23}
24
25// possible scopes
26var scopePrior = function(){
27 return categorical({vs:["surface", "inverse"],ps:[100,1]})
28}
29
30// meaning function
31var meaning = function(utterance, state, scope) {
32 return utterance == "none"? state == 0:
33 utterance == "not-two" ?
34 scope == "surface" ? (state < 2):
35 (state == 0) :
36 true;
37};
38
39// QUDs
40var QUDs = ["how many?","all red?","none red?"];
41var QUDPrior = function() {
42 categorical({vs:["how many?","all red?","none red?"],ps:[1,1,1]})
43 //uniformDraw(QUDs);
44}
45var QUDFun = function(QUD,state) {
46 QUD == "all red?" ? state == 2 :
47 QUD == "none red?" ? state == 0 :
48 state;
49};
50
51// Literal listener (L0)
52var literalListener = cache(function(utterance,scope,QUD) {
53 Infer({model: function(){
54 var state = uniformDraw(states);
55 var qState = QUDFun(QUD,state)
56 condition(meaning(utterance,state,scope));
57 return qState;
58 }});
59});
60
61var alpha = 1
62
63// Speaker (S)
64var speaker = cache(function(scope, state, QUD) {
65 return Infer({model: function(){
66 var utterance = utterancePrior()
67 var qState = QUDFun(QUD, state)
68 factor(alpha*(literalListener(utterance,scope,QUD).score(qState)
69 - cost(utterance)))
70 return utterance
71 }})
72})
73
74// Pragmatic listener (L1)
75var pragmaticListener = cache(function(utterance) {
76 Infer({model: function(){
77 var state = statePrior();
78 var scope = scopePrior();
79 var QUD = QUDPrior();
80 observe(speaker(scope,state,QUD),utterance);
81 return state
82 }});
83});
84
85// Pragmatic speaker (S2)
86var pragmaticSpeaker = cache(function(state) {
87 Infer({model: function(){
88 var utterance = utterancePrior();
89 factor(pragmaticListener(utterance).score(state))
90 return utterance
91 }})
92})
93
94// A speaker decides whether to endorse the ambiguous utterance as a
95// description of the not-all world state
96//viz.table(pragmaticSpeaker(0))
97//viz.table(pragmaticSpeaker(1))
98viz.table(pragmaticSpeaker(1))
99//literalListener("surface", 2, "all red?")
100
101var ANSWER = (pragmaticSpeaker(1));
102
s46 +psonnet-46-primer-forestdbTV=00.000
webppl
1var utterances = ["null", "not-two", "none"];
2var states = [0, 1, 2];
3
4var utterancePrior = function() {
5 return categorical({vs: utterances, ps: [1, 1, 1]});
6};
7
8var cost = function(utterance) { return 1; };
9
10var statePrior = function() {
11 return categorical({vs: states, ps: [1, 1, 1]});
12};
13
14var scopePrior = function() {
15 return categorical({vs: ["surface", "inverse"], ps: [100, 1]});
16};
17
18var meaning = function(utterance, state, scope) {
19 if (utterance === "none") {
20 return state === 0;
21 } else if (utterance === "not-two") {
22 if (scope === "surface") {
23 return state < 2;
24 } else {
25 return state === 0;
26 }
27 } else {
28 // "null"
29 return true;
30 }
31};
32
33var QUDs = ["how many?", "all red?", "none red?"];
34
35var QUDPrior = function() {
36 return categorical({vs: QUDs, ps: [1, 1, 1]});
37};
38
39var QUDFun = function(QUD, state) {
40 if (QUD === "all red?") {
41 return state === 2;
42 } else if (QUD === "none red?") {
43 return state === 0;
44 } else {
45 return state;
46 }
47};
48
49var literalListener = mem(function(utterance, scope, QUD) {
50 return Infer({method: "enumerate"}, function() {
51 var state = uniformDraw(states);
52 condition(meaning(utterance, state, scope));
53 return QUDFun(QUD, state);
54 });
55});
56
57var alpha = 1;
58
59var speaker = mem(function(scope, state, QUD) {
60 return Infer({method: "enumerate"}, function() {
61 var utterance = utterancePrior();
62 var L0 = literalListener(utterance, scope, QUD);
63 factor(alpha * (L0.score(QUDFun(QUD, state)) - cost(utterance)));
64 return utterance;
65 });
66});
67
68var pragmaticListener = mem(function(utterance) {
69 return Infer({method: "enumerate"}, function() {
70 var state = statePrior();
71 var scope = scopePrior();
72 var QUD = QUDPrior();
73 var S1 = speaker(scope, state, QUD);
74 observe(S1, utterance);
75 return state;
76 });
77});
78
79var pragmaticSpeaker = function(state) {
80 return Infer({method: "enumerate"}, function() {
81 var utterance = utterancePrior();
82 var L1 = pragmaticListener(utterance);
83 factor(L1.score(state));
84 return utterance;
85 });
86};
87
88var ANSWER = pragmaticSpeaker(1);
02output overlaydistribution
GT s46 +p3 bins
00.260.260.510.51none A = 0.206 B = 0.206none A = 0.206 B = 0.2060.210.21nonenot-two A = 0.513 B = 0.513not-two A = 0.513 B = 0.5130.510.51not-twonull A = 0.281 B = 0.281null A = 0.281 B = 0.2810.280.28null
03 other runs 1 total
run flags bucket TV KL actions
sonnet-46-primer-forestdb primary sonnet-4.6 +primer TV=0 0.000 0.0000 ·
forestdb-lxz-chinese-scope / atom-4
shape distribution s46 +p TV<.50.087 runs 1/1
per-run
00 prompt

An RSA scope ambiguity model for Mandarin "not-two" utterances, Experiment 2 (4-object context). Includes "none" utterance and strongly surface-scope biased scopePrior. States 0-4. A pragmatic speaker at state 2 (2 of 4 rabbits fed) decides whether to endorse "not-two".

utterances = ["null", "not-two", "none"]. utterancePrior: categorical({vs:["null","not-two","none"], ps:[1,1,1]}). cost(utterance): all->1. states = [0,1,2,3,4]. statePrior: categorical({vs:[0,1,2,3,4], ps:[1,1,1,1,1]}). scopePrior: categorical({vs:["surface","inverse"], ps:[100,1]}) — strongly biased toward surface scope. meaning(utterance, state, scope): none->state==0, not-two ? surface ? state<2 : state<3 : true. QUDs = ["how many?","all red?","none red?"]. QUDPrior: categorical({vs:[...], ps:[1,1,1]}). QUDFun(QUD,state): all red?->state==4, none red?->state==0, else state. literalListener(utterance, scope, QUD): Infer over uniformDraw(states), conditions on meaning, returns QUDFun(QUD,state). alpha = 1. speaker(scope, state, QUD): Infer, factor(alpha*(L0.score(QUDFun(QUD,state))-cost(utterance))). pragmaticListener(utterance): Infer, samples state/scope/QUD, observes speaker. pragmaticSpeaker(state): Infer, factor(pragmaticListener(utterance).score(state)), returns utterance.

Compute pragmaticSpeaker(2). Return distribution over utterances ["null", "not-two", "none"] when 2 of 4 rabbits were fed.

system prompt constant across atoms
(system prompt loads here)
WebPPL primer applied to *-primer-* runs
(primer loads here)
01 code comparing GT vs s46 +p
GTground truth
webppl
1// Here is the code of Chinese model for Expt 2.
2//different qud prior, different state prior, access to alternative utterances
3
4// Here is the code for the quantifier scope model
5
6// possible utterances
7var utterances = ["null","not-two","none"];
8
9var utterancePrior = function() {
10 categorical({vs:["null","not-two","none"],ps:[1,1,1]})
11}
12
13var cost = function(utterance) {
14 return utterance == "not-two" ? 1 :
15 utterance == 'none'? 1 :
16 1
17}
18
19// possible world states
20var states = [0,1,2,3,4];
21var statePrior = function() {
22 categorical({vs:[0,1,2,3,4],ps:[1,1,1,1,1]})
23}
24
25// possible scopes
26var scopePrior = function(){
27 return categorical({vs:["surface", "inverse"],ps:[100,1]})
28}
29
30// meaning function
31var meaning = function(utterance, state, scope) {
32 return utterance == "none"? state == 0:
33 utterance == "not-two" ?
34 scope == "surface" ? (state < 2):
35 (state < 3) :
36 true;
37};
38
39// QUDs
40var QUDs = ["how many?","all red?","none red?"];
41var QUDPrior = function() {
42 categorical({vs:["how many?","all red?","none red?"],ps:[1,1,1]})
43 //uniformDraw(QUDs);
44}
45var QUDFun = function(QUD,state) {
46 QUD == "all red?" ? state == 4 :
47 QUD == "none red?" ? state == 0 :
48 state;
49};
50
51// Literal listener (L0)
52var literalListener = cache(function(utterance,scope,QUD) {
53 Infer({model: function(){
54 var state = uniformDraw(states);
55 var qState = QUDFun(QUD,state)
56 condition(meaning(utterance,state,scope));
57 return qState;
58 }});
59});
60
61var alpha = 1
62
63// Speaker (S)
64var speaker = cache(function(scope, state, QUD) {
65 return Infer({model: function(){
66 var utterance = utterancePrior()
67 var qState = QUDFun(QUD, state)
68 factor(alpha*(literalListener(utterance,scope,QUD).score(qState)
69 - cost(utterance)))
70 return utterance
71 }})
72})
73
74// Pragmatic listener (L1)
75var pragmaticListener = cache(function(utterance) {
76 Infer({model: function(){
77 var state = statePrior();
78 var scope = scopePrior();
79 var QUD = QUDPrior();
80 observe(speaker(scope,state,QUD),utterance);
81 return state
82 }});
83});
84
85// Pragmatic speaker (S2)
86var pragmaticSpeaker = cache(function(state) {
87 Infer({model: function(){
88 var utterance = utterancePrior();
89 factor(pragmaticListener(utterance).score(state))
90 return utterance
91 }})
92})
93
94// A speaker decides whether to endorse the ambiguous utterance as a
95// description of the not-all world state
96//viz.table(pragmaticSpeaker(0))
97viz.table(pragmaticSpeaker(2))
98//viz.table(pragmaticSpeaker(2))
99//literalListener("surface", 2, "all red?")
100
101var ANSWER = (pragmaticSpeaker(2));
102
s46 +psonnet-46-primer-forestdbTV<.50.087
webppl
1var utterances = ["null", "not-two", "none"];
2var states = [0, 1, 2, 3, 4];
3
4var utterancePrior = function() {
5 return categorical({vs: utterances, ps: [1, 1, 1]});
6};
7
8var cost = function(utterance) { return 1; };
9
10var statePrior = function() {
11 return categorical({vs: states, ps: [1, 1, 1, 1, 1]});
12};
13
14var scopePrior = function() {
15 return categorical({vs: ["surface", "inverse"], ps: [100, 1]});
16};
17
18var meaning = function(utterance, state, scope) {
19 if (utterance === "none") {
20 return state === 0;
21 } else if (utterance === "not-two") {
22 if (scope === "surface") {
23 return state !== 2;
24 } else {
25 return !(state === 2 || state === 3 || state === 4);
26 }
27 } else {
28 return true;
29 }
30};
31
32var QUDs = ["how many?", "all red?", "none red?"];
33
34var QUDPrior = function() {
35 return categorical({vs: QUDs, ps: [1, 1, 1]});
36};
37
38var QUDFun = function(QUD, state) {
39 if (QUD === "all red?") {
40 return state === 4;
41 } else if (QUD === "none red?") {
42 return state === 0;
43 } else {
44 return state;
45 }
46};
47
48var alpha = 1;
49
50var literalListener = mem(function(utterance, scope, QUD) {
51 return Infer({method: "enumerate"}, function() {
52 var state = statePrior();
53 condition(meaning(utterance, state, scope));
54 return QUDFun(QUD, state);
55 });
56});
57
58var speaker = mem(function(scope, state, QUD) {
59 return Infer({method: "enumerate"}, function() {
60 var utterance = utterancePrior();
61 var L0 = literalListener(utterance, scope, QUD);
62 var qudVal = QUDFun(QUD, state);
63 factor(alpha * (L0.score(qudVal) - cost(utterance)));
64 return utterance;
65 });
66});
67
68var pragmaticListener = mem(function(utterance) {
69 return Infer({method: "enumerate"}, function() {
70 var state = statePrior();
71 var scope = scopePrior();
72 var QUD = QUDPrior();
73 var S1 = speaker(scope, state, QUD);
74 observe(S1, utterance);
75 return state;
76 });
77});
78
79var pragmaticSpeaker = function(state) {
80 return Infer({method: "enumerate"}, function() {
81 var utterance = utterancePrior();
82 var PL = pragmaticListener(utterance);
83 factor(PL.score(state));
84 return utterance;
85 });
86};
87
88var ANSWER = pragmaticSpeaker(2);
02output overlaydistribution
GT s46 +p3 bins
00.260.260.510.51none A = 0.251 B = 0.239none A = 0.251 B = 0.2390.250.24nonenot-two A = 0.321 B = 0.247not-two A = 0.321 B = 0.2470.320.25not-twonull A = 0.428 B = 0.514null A = 0.428 B = 0.5140.430.51null
03 other runs 1 total
run flags bucket TV KL actions
sonnet-46-primer-forestdb primary sonnet-4.6 +primer TV<.5 0.087 0.0179 ·
forestdb-overinf / atom-1
shape distribution s46 +p TV<.50.207 runs 1/1
per-run
00 prompt

Implement a relaxed semantics speaker model for reference games in WebPPL. The context has 3 objects: [{size:'big',color:'blue'}, {size:'small',color:'blue'}, {size:'big',color:'red'}]. Utterances are ['big','small','blue','red','big_blue','small_blue','big_red'] with uniform prior. Parameters: alpha=30, costWeight=1, size_semvalue=0.8, color_semvalue=0.99, size_cost=0, color_cost=0. The meaning function for single-word utterances: if the word is a color (in ['red','blue']), return color_semvalue if it matches obj.color, else 1-color_semvalue; if the word is a size (in ['big','small']), return size_semvalue if it matches obj.size, else 1-size_semvalue. For two-word utterances (SIZE_COLOR format split by '_'): return size_value*color_value where each value follows the same color/size semvalue logic. Cost is defined as a lookup object: {big:size_cost, small:size_cost, blue:color_cost, red:color_cost, big_blue:size_cost+color_cost, small_blue:size_cost+color_cost, big_red:size_cost+color_cost}. The literal listener uses Infer({method:'enumerate'}) and factors by meaning(utt,state). The pragmatic speaker uses Infer({method:'enumerate'}) and factors by alpha*literalListener(utt).score(state) - costWeight*cost[utt]. Return the speaker's distribution when communicating the small blue object: {size:'small', color:'blue'}.

system prompt constant across atoms
(system prompt loads here)
WebPPL primer applied to *-primer-* runs
(primer loads here)
01 code comparing GT vs s46 +p
GTground truth
webppl
1var alpha = 30
2var costWeight = 1
3var size_semvalue = 0.8
4var color_semvalue = 0.99
5var size_cost = 0
6var color_cost = 0
7
8var states = [
9 {size: "big", color: "blue"},
10 {size: "small", color: "blue"},
11 {size: "big", color: "red"}]
12
13var utterances = ["big", "small", "blue", "red", "big_blue", "small_blue", "big_red"]
14
15var colors = ["red", "blue"]
16var sizes = ["big", "small"]
17
18var statePrior = function() {
19 return uniformDraw(states)
20};
21
22var utterancePrior = function() {
23 return uniformDraw(utterances)
24};
25
26// assumes that 2-word utterances consist of SIZE_COLOR, in that order
27var meaning = function(utt, obj) {
28 var splitWords = utt.split('_')
29 if (splitWords.length == 1) {
30 var word = splitWords[0]
31 if(_.includes(colors, word))
32 return word == obj.color ? color_semvalue : 1-color_semvalue;
33 else if (_.includes(sizes, word))
34 return word == obj.size ? size_semvalue : 1-size_semvalue;
35 } else if (splitWords.length == 2) {
36 var size_value = splitWords[0] == obj.size ? size_semvalue : 1-size_semvalue;
37 var color_value = splitWords[1] == obj.color ? color_semvalue : 1-color_semvalue;
38 return size_value*color_value
39 } else
40 console.error("bad utterance length: "+splitWords.length)
41};
42
43var cost = {
44 big: size_cost,
45 small: size_cost,
46 blue: color_cost,
47 red: color_cost,
48 big_blue: size_cost+color_cost,
49 small_blue: size_cost+color_cost,
50 big_red: size_cost+color_cost
51}
52
53// literal listener
54var literalListener = cache(function(utt) {
55 return Infer({method:"enumerate"},
56 function(){
57 var state = statePrior()
58 factor(meaning(utt,state))
59 return state
60 })
61});
62
63// pragmatic speaker
64var speaker = cache(function(state) {
65 return Infer({method:"enumerate"},
66 function(){
67 var utt = utterancePrior()
68 factor(alpha * literalListener(utt).score(state) - costWeight * cost[utt])
69 return utt
70 })
71});
72
73
74display("speaker who wants to communicate big blue object:")
75viz.table(speaker({size: "big", color: "blue"}))
76
77display("speaker who wants to communicate big red object:")
78viz.table(speaker({size: "big", color: "red"}))
79
80display("speaker who wants to communicate small blue object:")
81viz.table(speaker({size: "small", color: "blue"}))
82
83display("literal listener who observes 'big':")
84viz.table(literalListener("big"))
85
86display("literal listener who observes 'small':")
87viz.table(literalListener("small"))
88
89display("literal listener who observes 'blue':")
90viz.table(literalListener("blue"))
91
92display("literal listener who observes 'red':")
93viz.table(literalListener("red"))
94
95display("literal listener who observes 'big blue':")
96viz.table(literalListener("big_blue"))
97
98display("literal listener who observes 'big red':")
99viz.table(literalListener("big_red"))
100
101display("literal listener who observes 'small blue':")
102viz.table(literalListener("small_blue"))
103
104var ANSWER = (speaker({size: 'small', color: 'blue'}));
105
s46 +psonnet-46-primer-forestdbTV<.50.207
webppl
1var objects = [
2 {size: 'big', color: 'blue'},
3 {size: 'small', color: 'blue'},
4 {size: 'big', color: 'red'}
5];
6
7var utterances = ['big', 'small', 'blue', 'red', 'big_blue', 'small_blue', 'big_red'];
8
9var alpha = 30;
10var costWeight = 1;
11var size_semvalue = 0.8;
12var color_semvalue = 0.99;
13var size_cost = 0;
14var color_cost = 0;
15
16var cost = {
17 big: size_cost,
18 small: size_cost,
19 blue: color_cost,
20 red: color_cost,
21 big_blue: size_cost + color_cost,
22 small_blue: size_cost + color_cost,
23 big_red: size_cost + color_cost
24};
25
26var colors = ['red', 'blue'];
27var sizes = ['big', 'small'];
28
29var wordMeaning = function(word, obj) {
30 return _.includes(colors, word) ?
31 (word === obj.color ? color_semvalue : 1 - color_semvalue) :
32 (word === obj.size ? size_semvalue : 1 - size_semvalue);
33};
34
35var meaning = function(utt, obj) {
36 var parts = utt.split('_');
37 return parts.length === 1 ?
38 wordMeaning(parts[0], obj) :
39 wordMeaning(parts[0], obj) * wordMeaning(parts[1], obj);
40};
41
42var literalListener = mem(function(utt) {
43 return Infer({method: 'enumerate'}, function() {
44 var obj = uniformDraw(objects);
45 factor(Math.log(meaning(utt, obj)));
46 return obj;
47 });
48});
49
50var pragmaticSpeaker = function(targetObj) {
51 return Infer({method: 'enumerate'}, function() {
52 var utt = uniformDraw(utterances);
53 factor(alpha * literalListener(utt).score(targetObj) - costWeight * cost[utt]);
54 return utt;
55 });
56};
57
58var targetObj = {size: 'small', color: 'blue'};
59
60var ANSWER = pragmaticSpeaker(targetObj);
02output overlaydistribution
GT s46 +p7 bins
00.500.501.001.00big_red A = 0.000 B = 0.000big_red A = 0.000 B = 0.000big_redsmall_blue A = 0.789 B = 0.996small_blue A = 0.789 B = 0.9960.791.00small_bluebig_blue A = 0.000 B = 0.000big_blue A = 0.000 B = 0.000big_bluered A = 0.000 B = 0.000red A = 0.000 B = 0.000redblue A = 0.005 B = 0.000blue A = 0.005 B = 0.000bluesmall A = 0.206 B = 0.004small A = 0.206 B = 0.0040.21smallbig A = 0.000 B = 0.000big A = 0.000 B = 0.000big
03 other runs 1 total
run flags bucket TV KL actions
sonnet-46-primer-forestdb primary sonnet-4.6 +primer TV<.5 0.207 0.2148 ·
forestdb-prior-inference / atom-1
shape distribution s46 +p TV=00.000 runs 1/1
per-run
00 prompt

Implement a preference-relativized RSA model in WebPPL. Objects are: [{color:'blue',shape:'square',string:'blue square'},{color:'blue',shape:'circle',string:'blue circle'},{color:'green',shape:'square',string:'green square'}]. Utterances are ['blue','green','square','circle']. Preferences are ['blue_things','green_things','squares','circles','none']. preferenceTable maps each preference to salience weights over the 3 objects: {blue_things:[4,4,2], green_things:[1,1,8], squares:[4,2,4], circles:[1,8,1], none:[1,1,1]}. objectPrior(preference) does a categorical draw over objects using preferenceTable[preference] and returns obj.string. meaning(utterance,obj) checks if the utterance string is included in obj (using _.includes). The literal listener (L0) takes utterance and preference: uniformDraw over objects (ignoring preference), conditions on meaning, returns obj.string. Speaker (alpha=1) takes obj and preference: uniformDraw over utterances, factors by alpha*literalListener(utterance,preference).score(obj). Pragmatic listener takes utterance and preference: samples obj from objectPrior(preference), observes speaker(obj,preference). Return the pragmatic listener's distribution when hearing 'square' with preference 'blue_things'.

system prompt constant across atoms
(system prompt loads here)
WebPPL primer applied to *-primer-* runs
(primer loads here)
01 code comparing GT vs s46 +p
GTground truth
webppl
1// Frank and Goodman (2012) RSA model from problang.org
2
3// set of states (here: objects of reference)
4// we represent objects as JavaScript objects to demarcate them from utterances
5// internally we treat objects as strings nonetheless
6var objects = [{color: "blue", shape: "square", string: "blue square"},
7 {color: "blue", shape: "circle", string: "blue circle"},
8 {color: "green", shape: "square", string: "green square"}]
9
10// set of utterances
11var utterances = ["blue", "green", "square", "circle"]
12
13var preferences = ["blue_things", "green_things", "squares", "circles","none"]
14
15var preferenceTable = {
16 blue_things : [4,4,2],
17 green_things : [1,1,8],
18 squares : [4,2,4],
19 circles : [1,8,1],
20 none : [1,1,1]
21}
22
23var preferencePrior = function() {
24 return uniformDraw(preferences)
25}
26
27// prior over world states
28var objectPrior = function(preference) {
29 var obj = categorical(preferenceTable[preference],objects)
30 return obj.string
31}
32
33// meaning function to interpret the utterances
34var meaning = function(utterance, obj){
35 _.includes(obj, utterance)
36}
37
38// literal listener
39var literalListener = function(utterance,preference){
40 Infer({model: function(){
41 var obj = uniformDraw(objects).string // L0 has no preference
42 condition(meaning(utterance, obj))
43 return obj
44 }})
45}
46
47// set speaker optimality
48var alpha = 1
49
50// pragmatic speaker
51var speaker = function(obj,preference){
52 Infer({model: function(){
53 var utterance = uniformDraw(utterances)
54 factor(alpha * literalListener(utterance,preference).score(obj))
55 return utterance
56 }})
57}
58
59// pragmatic listener
60var pragmaticListener = function(utterance,preference){
61 Infer({model: function(){
62 var obj = objectPrior(preference)
63 observe(speaker(obj,preference),utterance)
64 return obj
65 }})
66}
67
68print("the listener hears 'square' and has a preference for blue things")
69viz(pragmaticListener("square","blue_things"))
70
71print("the listener hears 'square' and has a preference for green things")
72viz(pragmaticListener("square","green_things"))
73
74print("the listener hears 'square' and has a preference for squares")
75viz(pragmaticListener("square","squares"))
76
77var ANSWER = (pragmaticListener('square', 'blue_things'));
78
s46 +psonnet-46-primer-forestdbTV=00.000
webppl
1var objects = [
2 {color: 'blue', shape: 'square', string: 'blue square'},
3 {color: 'blue', shape: 'circle', string: 'blue circle'},
4 {color: 'green', shape: 'square', string: 'green square'}
5];
6
7var utterances = ['blue', 'green', 'square', 'circle'];
8
9var preferences = ['blue_things', 'green_things', 'squares', 'circles', 'none'];
10
11var preferenceTable = {
12 blue_things: [4, 4, 2],
13 green_things: [1, 1, 8],
14 squares: [4, 2, 4],
15 circles: [1, 8, 1],
16 none: [1, 1, 1]
17};
18
19var objectPrior = function(preference) {
20 var weights = preferenceTable[preference];
21 var obj = objects[categorical({vs: [0, 1, 2], ps: weights})];
22 return obj.string;
23};
24
25var meaning = function(utterance, obj) {
26 return _.includes(obj.string, utterance);
27};
28
29var literalListener = mem(function(utterance, preference) {
30 return Infer({method: 'enumerate'}, function() {
31 var obj = uniformDraw(objects);
32 condition(meaning(utterance, obj));
33 return obj.string;
34 });
35});
36
37var alpha = 1;
38
39var speaker = mem(function(obj, preference) {
40 return Infer({method: 'enumerate'}, function() {
41 var utterance = uniformDraw(utterances);
42 factor(alpha * literalListener(utterance, preference).score(obj));
43 return utterance;
44 });
45});
46
47var pragmaticListener = function(utterance, preference) {
48 return Infer({method: 'enumerate'}, function() {
49 var obj = objectPrior(preference);
50 observe(speaker(obj, preference), utterance);
51 return obj;
52 });
53};
54
55var ANSWER = pragmaticListener('square', 'blue_things');
02output overlaydistribution
GT s46 +p2 bins
00.380.380.750.75green square A = 0.250 B = 0.250green square A = 0.250 B = 0.2500.250.25green squareblue square A = 0.750 B = 0.750blue square A = 0.750 B = 0.7500.750.75blue square
03 other runs 1 total
run flags bucket TV KL actions
sonnet-46-primer-forestdb primary sonnet-4.6 +primer TV=0 0.000 0.0000 ·
forestdb-scalar-implicature-qud / atom-1
shape distribution s46 +p TV=00.000 runs 1/1
per-run
00 prompt

Implement a scalar implicature model with an explicit QUD (Question Under Discussion) in WebPPL. The world state is uniformDraw([0,1,2,3]) representing the number of red apples. Utterances are uniformDraw(['all','some','none']). Literal meanings: 'all' is true iff state==3, 'some' is true iff state>0, 'none' is true iff state==0. Two QUDs are possible: 'all?' (true iff state==3) and 'any?' (true iff state>0). The literal listener takes an utterance and a QUD: it samples state from statePrior, conditions on the utterance being literally true, and returns qudFn(qud,state). The speaker (alpha=1) takes a state and a QUD: it samples an utterance and factors by alpha * literalListener(utt,qud).score(qudFn(qud,state)). The pragmatic listener takes an utterance and a QUD: it samples a state and observes speaker(state,qud). Return the pragmatic listener's distribution over world states when the utterance is 'some' and the QUD is 'any?'. Use Infer with method:'enumerate' throughout.

system prompt constant across atoms
(system prompt loads here)
WebPPL primer applied to *-primer-* runs
(primer loads here)
01 code comparing GT vs s46 +p
GTground truth
webppl
1// possible states of the world
2var statePrior = function() {
3 return uniformDraw([0, 1, 2, 3])
4};
5
6// possible utterances
7var utterancePrior = function() {
8 return uniformDraw(['all', 'some', 'none']);
9};
10
11// possible quds
12var quds = ['all?','any?']
13
14// prior over quds (only relevant for qud inference)
15var qudPrior = function() {
16 return uniformDraw(quds);
17};
18
19// meaning funtion to interpret the utterances
20var literalMeanings = {
21 all: function(state) { return state === 3; },
22 some: function(state) { return state > 0; },
23 none: function(state) { return state === 0; }
24};
25
26// projection function
27var qudFn = function(qud, state) {
28 var qudAdressed = qud === "all?" ? state === 3 : state > 0
29 return qudAdressed
30}
31
32// literal listener
33var literalListener = cache(function(utt,qud) {
34 return Infer({model: function(){
35 var state = statePrior()
36 var meaning = literalMeanings[utt]
37 condition(meaning(state))
38 return qudFn(qud,state)
39 }})
40});
41
42// set speaker optimality
43var alpha = 1
44
45// pragmatic speaker
46var speaker = cache(function(state,qud) {
47 return Infer({model: function(){
48 var utt = utterancePrior()
49 factor(alpha * literalListener(utt,qud).score(qudFn(qud,state)))
50 return utt
51 }})
52});
53
54// pragmatic listener
55var pragmaticListener = cache(function(utt,qud) {
56 return Infer({model: function(){
57 var state = statePrior()
58 observe(speaker(state,qud),utt)
59 return state
60 }})
61});
62
63// print("pragmatic listener's interpretation of 'some':")
64viz(pragmaticListener('some','any?'));
65
66var ANSWER = (pragmaticListener('some','any?'));
67
s46 +psonnet-46-primer-forestdbTV=00.000
webppl
1var states = [0, 1, 2, 3];
2var utterances = ['all', 'some', 'none'];
3var quds = ['all?', 'any?'];
4
5var alpha = 1;
6
7var statePrior = function() {
8 return uniformDraw(states);
9};
10
11var utterancePrior = function() {
12 return uniformDraw(utterances);
13};
14
15var literalMeaning = function(utt, state) {
16 return utt === 'all' ? state === 3 :
17 utt === 'some' ? state > 0 :
18 utt === 'none' ? state === 0 :
19 true;
20};
21
22var qudFn = function(qud, state) {
23 return qud === 'all?' ? state === 3 :
24 qud === 'any?' ? state > 0 :
25 state;
26};
27
28var literalListener = mem(function(utt, qud) {
29 return Infer({method: 'enumerate'}, function() {
30 var state = statePrior();
31 condition(literalMeaning(utt, state));
32 return qudFn(qud, state);
33 });
34});
35
36var speaker = mem(function(state, qud) {
37 return Infer({method: 'enumerate'}, function() {
38 var utt = utterancePrior();
39 var qudVal = qudFn(qud, state);
40 factor(alpha * literalListener(utt, qud).score(qudVal));
41 return utt;
42 });
43});
44
45var pragmaticListener = mem(function(utt, qud) {
46 return Infer({method: 'enumerate'}, function() {
47 var state = statePrior();
48 observe(speaker(state, qud), utt);
49 return state;
50 });
51});
52
53var ANSWER = pragmaticListener('some', 'any?');
02output overlaydistribution
GT s46 +p3 bins · 1 … 3
00.170.170.330.331 A = 0.333 B = 0.3331 A = 0.333 B = 0.3330.330.3312 A = 0.333 B = 0.3332 A = 0.333 B = 0.3330.330.3323 A = 0.333 B = 0.3333 A = 0.333 B = 0.3330.330.333
03 other runs 1 total
run flags bucket TV KL actions
sonnet-46-primer-forestdb primary sonnet-4.6 +primer TV=0 0.000 0.0000 ·
forestdb-schizophrenia-urns / atom-1
shape distribution s46 +p TV<.50.117 runs 1/1
per-run
00 prompt

Model a social urn inference task using WebPPL. There are nMarbles=8 marbles drawn per trial and a threshold=0.6. The self participant drew selfData=4 red marbles. The other agents' data is: [{prediction:'red',confidence:'high'},{prediction:'red',confidence:'high'},{prediction:'blue',confidence:'low'},{prediction:'blue',confidence:'low'}]. The prior over pRed (the true proportion of red marbles in the urn) is a discretized uniform over [0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1]. Each other agent makes predictions by: (1) sampling pRed from the prior, (2) observing a Binomial(p:pRed, n:nMarbles) draw to condition on their kRed, (3) predicting 'red' if flip(pRed) and 'blue' otherwise, with confidence 'high' if (prediction=='red' && pRed>=threshold) || (prediction=='blue' && pRed<=1-threshold) else 'low'. The participant infers pRed by: (1) conditioning on their own Binomial draw equaling selfData, (2) for each other agent's datum, computing the marginal likelihood over possible kRed counts that the agent could have seen, weighted by the hypergeometric probability of that kRed given pRed and nMarbles total. Return the distribution over pRed (as a string label) using Infer({method:'enumerate'}) over the trialModel function. Note: convert pRed to string before returning (e.g. pRed + "").

system prompt constant across atoms
(system prompt loads here)
WebPPL primer applied to *-primer-* runs
(primer loads here)
01 code comparing GT vs s46 +p
GTground truth
webppl
1// total number of marbles drawn from urn every time
2var nMarbles = 8;
3var threshold = .6;
4
5// example data point for self
6var selfData = 4;
7
8// example data point for others
9var otherData = [{prediction: 'red', confidence: 'high'},
10 {prediction: 'red', confidence: 'high'},
11 {prediction: 'blue', confidence: 'low'},
12 {prediction: 'blue', confidence: 'low'}];
13
14// (discretized) uniform distribution over actual proportion of red in urn
15var rednessPrior = Categorical({vs: [0, .1, .2, .3, .4, .5, .6, .7, .8, .9, 1]});
16
17/*
18 Generative model of other agents
19
20 Assumes they are *also* doing inference about actual proportion
21 based on their data and responding according to their best guess...
22 */
23var otherOutput = cache(function(kRed, threshold) {
24 return Infer({method: 'enumerate', model: function() {
25 var pRed = sample(rednessPrior);
26 var prediction = flip(pRed) ? 'red' : 'blue';
27 var highConf = prediction === 'red' ? pRed >= threshold : pRed <= 1 - threshold;
28
29 observe(Binomial({p: pRed, n: nMarbles}), kRed);
30 return {prediction: prediction, confidence: highConf ? 'high' : 'low'}
31 }});
32})
33
34/*
35 Model of participant's inference on a given trial
36*/
37var trialModel = function() {
38 // participant is trying to infer latent distribution in urn
39 var pRed = sample(rednessPrior);
40
41 // first, take into account own data (i.e. a draw of balls from urn)
42 observe(Binomial({p: pRed, n: nMarbles}), selfData);
43
44 // next, take into account social information
45 // assume their sample was drawn from sample population but not sure of exact data
46 mapData({data: otherData}, function(datum) {
47 var kSeenPrior = Binomial({p: pRed, n : nMarbles});
48 var likelihood = expectation(kSeenPrior, function(k) {
49 return otherOutput(k, threshold).score(datum)
50 })
51 factor(likelihood);
52 })
53
54 // ugly js convert to string for pretty plots
55 return pRed + "";
56}
57
58viz.hist(Infer({method: 'enumerate', model: trialModel}))
59
60var ANSWER = (Infer({method: 'enumerate', model: trialModel}));
61
s46 +psonnet-46-primer-forestdbTV<.50.117
webppl
1var nMarbles = 8;
2var threshold = 0.6;
3var selfData = 4;
4var otherData = [
5 {prediction: 'red', confidence: 'high'},
6 {prediction: 'red', confidence: 'high'},
7 {prediction: 'blue', confidence: 'low'},
8 {prediction: 'blue', confidence: 'low'}
9];
10
11var pRedValues = [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1];
12
13// Compute the marginal likelihood of an agent's (prediction, confidence) datum
14// given a particular pRed value for the participant's urn
15// The agent: samples pRed from prior, observes Binomial(pRed, nMarbles) -> kRed,
16// predicts 'red' if flip(pRed), confidence based on pRed and prediction
17// We need to marginalize over agent's pRed and kRed
18
19var agentLikelihood = function(datum, participantPRed) {
20 // We sum over all possible agent pRed values and kRed values
21 // P(datum | participantPRed) = sum_{agentPRed} P(agentPRed) * sum_{kRed} P(kRed | agentPRed, nMarbles) * P(datum | agentPRed, kRed)
22 // But wait - the agent's kRed is conditioned on, not marginalized in the agent model
23 // The agent samples pRed from prior, then observes kRed ~ Binomial(pRed, nMarbles)
24 // Then predicts based on pRed
25 // So P(datum | agentPRed) = sum_{kRed} P(kRed | agentPRed) * P(datum | agentPRed)
26 // Actually P(datum | agentPRed) doesn't depend on kRed since prediction only depends on pRed
27 // Wait - the agent conditions on kRed to update their belief about pRed? No.
28 // Re-reading: agent (1) samples pRed from prior, (2) observes Binomial draw to condition on kRed
29 // This means the agent does inference: posterior over pRed given kRed
30 // Then predicts 'red' if flip(pRed) where pRed is from posterior
31
32 // Actually re-reading more carefully:
33 // The agent model: sample pRed from prior, observe Binomial(pRed, nMarbles) = kRed (condition),
34 // then predict 'red' if flip(pRed)
35 // This is an agent-level inference model
36
37 // For the participant's inference, they need P(datum | participantPRed)
38 // The participant uses hypergeometric weighting for kRed given participantPRed
39 // So: P(datum | participantPRed) = sum_{kRed=0}^{nMarbles} P(kRed | participantPRed, nMarbles) * P(datum | agentSawKRed=kRed)
40 // where P(datum | agentSawKRed=kRed) = sum_{agentPRed} P(agentPRed | kRed) * P(datum | agentPRed)
41
42 // P(agentPRed | kRed) proportional to P(kRed | agentPRed) * P(agentPRed)
43 // P(datum | agentPRed) = P(prediction | agentPRed) * P(confidence | prediction, agentPRed)
44
45 var totalLik = sum(map(function(kRed) {
46 // P(kRed | participantPRed) - binomial probability
47 var pKRed = Math.exp(Binomial({p: participantPRed, n: nMarbles}).score(kRed));
48
49 // Now compute P(datum | agentSawKRed=kRed)
50 // Agent posterior over pRed given kRed
51 var agentPosteriorUnnorm = map(function(ap) {
52 var likelihood = Math.exp(Binomial({p: ap, n: nMarbles}).score(kRed));
53 return likelihood * (1.0 / pRedValues.length);
54 }, pRedValues);
55 var agentPosteriorSum = sum(agentPosteriorUnnorm);
56 var agentPosterior = map(function(x) { return agentPosteriorSum > 0 ? x / agentPosteriorSum : 0; }, agentPosteriorUnnorm);
57
58 // P(datum | agentSawKRed=kRed) = sum_{agentPRed} agentPosterior(agentPRed) * P(datum | agentPRed)
59 var datumLik = sum(map(function(i) {
60 var ap = pRedValues[i];
61 var post = agentPosterior[i];
62
63 // P(prediction='red') = ap, P(prediction='blue') = 1-ap
64 // confidence: high if (pred='red' && ap>=threshold) || (pred='blue' && ap<=1-threshold)
65 var pDatum = (datum.prediction === 'red') ?
66 (ap * ((datum.confidence === 'high') ? (ap >= threshold ? 1 : 0) : (ap >= threshold ? 0 : 1))) :
67 ((1 - ap) * ((datum.confidence === 'high') ? (ap <= 1 - threshold ? 1 : 0) : (ap <= 1 - threshold ? 0 : 1)));
68
69 return post * pDatum;
70 }, _.range(0, pRedValues.length)));
71
72 return pKRed * datumLik;
73 }, _.range(0, nMarbles + 1)));
74
75 return totalLik;
76};
77
78var trialModel = function() {
79 // Sample pRed from prior
80 var pRed = uniformDraw(pRedValues);
81
82 // Condition on self data
83 observe(Binomial({p: pRed, n: nMarbles}), selfData);
84
85 // For each other agent's datum, factor in marginal likelihood
86 map(function(datum) {
87 var lik = agentLikelihood(datum, pRed);
88 factor(Math.log(lik > 0 ? lik : 1e-300));
89 }, otherData);
90
91 return pRed + "";
92};
93
94var ANSWER = Infer({method: 'enumerate'}, trialModel);
02output overlaydistribution
GT s46 +p9 bins · 0.10 … 0.90
00.210.210.420.420.1 A = 0.000 B = 0.0000.1 A = 0.000 B = 0.0000.10.2 A = 0.000 B = 0.0000.2 A = 0.000 B = 0.0000.20.3 A = 0.000 B = 0.0020.3 A = 0.000 B = 0.0020.30.4 A = 0.007 B = 0.0310.4 A = 0.007 B = 0.0310.010.030.40.5 A = 0.079 B = 0.1470.5 A = 0.079 B = 0.1470.080.150.50.6 A = 0.302 B = 0.3260.6 A = 0.302 B = 0.3260.300.330.60.7 A = 0.418 B = 0.3420.7 A = 0.418 B = 0.3420.420.340.70.8 A = 0.181 B = 0.1420.8 A = 0.181 B = 0.1420.180.140.80.9 A = 0.012 B = 0.0110.9 A = 0.012 B = 0.0110.010.010.9
03 other runs 1 total
run flags bucket TV KL actions
sonnet-46-primer-forestdb primary sonnet-4.6 +primer TV<.5 0.117 0.0614 ·
forestdb-singh-uyeda-pronouns / atom-1
shape distribution s46 +p TV=00.000 runs 1/1
per-run
00 prompt

Implement an RSA model for pronoun resolution in WebPPL. The sentence template is 'John hit Fred and Ellen hit (utterance)'. Utterances are ['him','Fred','John'] with categorical prior weights [2,1,1]. World states are ['John','Fred'] with uniform prior. Possible strategies are ['Subject','Parallel'] with uniform prior. meaning(utterance,state,strategy): if utterance=='him', Subject strategy returns state=='John', Parallel strategy returns state=='Fred'; else utterance==state. Literal listener (L0, cached) takes (utterance,strategy): samples state from statePrior(), conditions on meaning(utterance,state,strategy), returns state. Speaker (S, cached) takes (strategy,state): samples utterance from utterancePrior(), observes literalListener(utterance,strategy) with value state. Pragmatic listener (L1, cached) takes utterance: samples state from statePrior() and strategy from strategyPrior(), observes speaker(strategy,state) with utterance, returns state. Return the pragmatic listener's distribution over states when hearing 'him'.

system prompt constant across atoms
(system prompt loads here)
WebPPL primer applied to *-primer-* runs
(primer loads here)
01 code comparing GT vs s46 +p
GTground truth
webppl
1///fold:
2// possible utterances: Ambiguous, Unambiguous Fred, Unambiguous John
3var utterances = ["him", "Fred", "John"]
4
5// samples the utterances that fill in the following template:
6// "John hit Fred and Ellen hit (the utterance)"
7
8var utterancePrior = function() {
9 categorical([2,1,1], utterances)
10}
11
12//possible world states of who Ellen hit
13var states = ["John", "Fred"]
14var statePrior = function() {
15 return uniformDraw(states)
16}
17
18//possible strategies
19var strategyPrior = function(){
20 return uniformDraw(["Subject", "Parallel"])
21}
22
23//meaning function
24var meaning = function(utterance, state, strategy){
25 return utterance == "him" ?
26 strategy == "Subject" ? state == "John" :
27 state == "Fred" :
28 utterance == state
29}
30
31// Literal Listener (L0)
32var literalListener = cache(function(utterence, strategy){
33 return Infer({model: function(){
34 var state = statePrior()
35 condition(meaning(utterence, state, strategy))
36 return state
37 }})
38})
39
40// Speaker (S)
41var speaker = cache(function(strategy, state){
42 return Infer({model: function() {
43 var utterance = utterancePrior()
44 observe(literalListener(utterance, strategy), state)
45 return utterance
46 }})
47})
48///
49// Pragmatic listener (L1)
50var pragmaticListener = cache(function(utterance) {
51 return Infer({model: function(){
52 var state = statePrior()
53 var strategy = strategyPrior()
54 observe(speaker(strategy,state),utterance)
55 return state
56 }})
57})
58pragmaticListener("him")
59
60var ANSWER = (pragmaticListener('him'));
61
s46 +psonnet-46-primer-forestdbTV=00.000
webppl
1var utterances = ['him', 'Fred', 'John'];
2var utteranceWeights = [2, 1, 1];
3var states = ['John', 'Fred'];
4var strategies = ['Subject', 'Parallel'];
5
6var utterancePrior = function() {
7 return sample(Categorical({vs: utterances, ps: utteranceWeights}));
8};
9
10var statePrior = function() {
11 return sample(Categorical({vs: states, ps: [1, 1]}));
12};
13
14var strategyPrior = function() {
15 return sample(Categorical({vs: strategies, ps: [1, 1]}));
16};
17
18var meaning = function(utterance, state, strategy) {
19 if (utterance === 'him') {
20 return strategy === 'Subject' ? state === 'John' : state === 'Fred';
21 } else {
22 return utterance === state;
23 }
24};
25
26var literalListener = mem(function(utterance, strategy) {
27 return Infer({method: 'enumerate'}, function() {
28 var state = statePrior();
29 condition(meaning(utterance, state, strategy));
30 return state;
31 });
32});
33
34var speaker = mem(function(strategy, state) {
35 return Infer({method: 'enumerate'}, function() {
36 var utterance = utterancePrior();
37 observe(literalListener(utterance, strategy), state);
38 return utterance;
39 });
40});
41
42var pragmaticListener = mem(function(utterance) {
43 return Infer({method: 'enumerate'}, function() {
44 var state = statePrior();
45 var strategy = strategyPrior();
46 observe(speaker(strategy, state), utterance);
47 return state;
48 });
49});
50
51var ANSWER = pragmaticListener('him');
02output overlaydistribution
GT s46 +p2 bins
00.250.250.500.50Fred A = 0.500 B = 0.500Fred A = 0.500 B = 0.5000.500.50FredJohn A = 0.500 B = 0.500John A = 0.500 B = 0.5000.500.50John
03 other runs 1 total
run flags bucket TV KL actions
sonnet-46-primer-forestdb primary sonnet-4.6 +primer TV=0 0.000 0.0000 ·
forestdb-social-meaning / atom-1
shape distribution s46 +p TV<.50.200 runs 1/1
per-run
00 prompt

Implement Burnett (2019)'s social meaning RSA model in WebPPL. Personae are: [{name:'stern',competence:true,friendliness:false},{name:'cool',competence:true,friendliness:true},{name:'asshole',competence:false,friendliness:false},{name:'doofus',competence:false,friendliness:true}]. voterPrior is Categorical({ps:[0.3,0.2,0.3,0.2], vs:personae}); journalistPrior is Categorical({ps:[0.2,0.2,0.3,0.3], vs:personae}). Set personaePrior = voterPrior. Variants are ['n','ng'] with cost {n:0, ng:0}. Semantics (Eckert-Montague): ng is true for persona when persona.competence==true || persona.friendliness==false; n is true when persona.competence==false || persona.friendliness==true. conditionalization(variant) = Infer over: sample persona from personaePrior, condition on semantics[variant](persona), return persona. utility(persona,variant) = conditionalization(variant).score(persona) - cost[variant]. Speaker(persona) = Infer over: uniformDraw(variants), factor(alpha=6 * utility(persona,variant)). mu(persona): 'cool'->2, 'stern'->1, 'doofus'->1, 'asshole'->0. alphaprime=6. personaDistribution = Infer over: sample(personaePrior), factor(alphaprime*mu(persona)), return persona. valueSpeaker(variant) = sum over personae of exp(personaDistribution.score(persona)) * exp(speaker(persona).score(variant)). valueInformedListener(variant) = Infer over: sample(personaePrior), factor(exp(personaDistribution.score(persona)) * exp(speaker(persona).score(variant))), return persona.name. naiveListener(variant) = Infer over: sample(personaePrior), factor(speaker(persona).score(variant)), return persona.name. Return the conditionalization distribution for variant 'ng'.

system prompt constant across atoms
(system prompt loads here)
WebPPL primer applied to *-primer-* runs
(primer loads here)
01 code comparing GT vs s46 +p
GTground truth
webppl
1// Personae in (6)
2var personae = [{name: "stern", competence : true, friendliness : false},
3 {name: "cool", competence : true, friendliness : true},
4 {name: "asshole", competence : false, friendliness : false},
5 {name: "doofus", competence : false, friendliness: true}]
6
7// Table 2
8var voterPrior = Categorical({ps: [0.3,0.2,0.3,0.2], vs: personae})
9
10// Table 5
11var journalistPrior = Categorical({ps: [0.2,0.2,0.3,0.3], vs: personae})
12
13var personaePrior = voterPrior
14// var personaePrior = journalistPrior
15
16var variants = ["n","ng"]
17
18var cost = {
19 n : 0,
20 ng : 0
21}
22
23// Eckert-Montague Semantics (Table 1)
24var semantics = {
25 ng: function(persona) { return (persona.competence == true | persona.friendliness == false) ; },
26 n: function(persona) { return (persona.competence == false | persona.friendliness == true); },
27}
28
29// Definition in (11) - the 'literal listener'
30
31var conditionalization = function(variant) {
32 return Infer({model: function(){
33 var persona = sample(personaePrior)
34 var meaning = semantics[variant]
35 condition(meaning(persona))
36 return persona
37 }}
38)}
39
40// Definition in (12)
41
42var utility = function(persona, variant) {
43
44 var informativity = conditionalization(variant).score(persona)
45 return(informativity - cost[variant])
46
47}
48
49var alpha = 6
50
51// Definition in (13) - soft-max choice rule
52
53var speaker = function(persona) {
54 return Infer(function() {
55 var variant = uniformDraw(variants)
56 factor(alpha * utility(persona,variant))
57 return(variant)
58 })
59}
60
61// Table 6: persona selection function (the value system)
62
63var mu = function(persona) {
64
65 persona.name == "cool" ? 2 :
66 persona.name == "stern" ? 1 :
67 persona.name == "doofus" ? 1 :
68 persona.name == "asshole" ? 0 :
69 0
70
71}
72
73// Definition in (14): probability distribution over personae
74
75var alphaprime = 6
76
77var personaDistribution = Infer(
78 function() {
79 var persona = sample(personaePrior)
80 factor(alphaprime * mu(persona))
81 return persona
82 })
83
84// Definition in (15): speaker with a value system
85
86var valueSpeaker = function(variant) {
87
88 // Array of utilities of variant for each persona, times probability of the persona
89 var variantUtility = map(function(persona) {
90 return Math.exp(personaDistribution.score(persona)) * Math.exp(speaker(persona).score(variant))
91 }, personae)
92
93 return sum(variantUtility)
94
95}
96
97// Definition in (17): Listening with certainty about speaker's values
98
99var valueInformedListener = function(variant) {
100 return Infer(function(){
101
102 var persona = sample(personaePrior)
103 factor(Math.exp(personaDistribution.score(persona)) * Math.exp(speaker(persona).score(variant)))
104 return persona.name
105
106 })
107}
108
109// Definition in (18): Naive listening
110
111var naiveListener = function(variant) {
112 return Infer(function(){
113
114 var persona = sample(personaePrior)
115 factor(speaker(persona).score(variant))
116 return persona.name
117 })
118}
119
120print("Literal L's beliefs immediately after hearing -n at the barbecue")
121viz.table(conditionalization('n'))
122
123print("Literal L’s beliefs immediately after hearing -ng at the barbecue")
124viz.table(conditionalization('ng'))
125
126print("Obama wants to be the cool guy")
127viz.table(speaker(personae[1]))
128
129// set prior to journalistPrior above
130print("Obama's overall probability of using -ng with the journalist")
131
132print(valueSpeaker('ng'))
133
134print("Obama's overall probability of using -n with the journalist")
135
136print(valueSpeaker('n'))
137
138print("Hearing Obama use -n (and you have a sense of Obama's values)")
139
140viz(valueInformedListener('n'))
141
142print("Hearing Obama use -n (and you're naive as to Obama's values)")
143
144viz(naiveListener('n'))
145
146var ANSWER = (conditionalization('ng'));
147
s46 +psonnet-46-primer-forestdbTV<.50.200
webppl
1var personae = [
2 {name:'stern', competence:true, friendliness:false},
3 {name:'cool', competence:true, friendliness:true},
4 {name:'asshole', competence:false, friendliness:false},
5 {name:'doofus', competence:false, friendliness:true}
6];
7
8var voterPrior = Categorical({ps:[0.3,0.2,0.3,0.2], vs:personae});
9var journalistPrior = Categorical({ps:[0.2,0.2,0.3,0.3], vs:personae});
10var personaePrior = voterPrior;
11
12var variants = ['n','ng'];
13var cost = {n:0, ng:0};
14
15var semantics = {
16 ng: function(persona) { return persona.competence == true || persona.friendliness == false; },
17 n: function(persona) { return persona.competence == false || persona.friendliness == true; }
18};
19
20var conditionalization = function(variant) {
21 return Infer({method:'enumerate'}, function() {
22 var persona = sample(personaePrior);
23 condition(semantics[variant](persona));
24 return persona;
25 });
26};
27
28var utility = function(persona, variant) {
29 return conditionalization(variant).score(persona) - cost[variant];
30};
31
32var alpha = 6;
33
34var speaker = mem(function(persona) {
35 return Infer({method:'enumerate'}, function() {
36 var variant = uniformDraw(variants);
37 factor(alpha * utility(persona, variant));
38 return variant;
39 });
40});
41
42var mu = function(persona) {
43 return persona.name == 'cool' ? 2 :
44 persona.name == 'stern' ? 1 :
45 persona.name == 'doofus' ? 1 :
46 persona.name == 'asshole' ? 0 : 0;
47};
48
49var alphaprime = 6;
50
51var personaDistribution = Infer({method:'enumerate'}, function() {
52 var persona = sample(personaePrior);
53 factor(alphaprime * mu(persona));
54 return persona;
55});
56
57var valueSpeaker = function(variant) {
58 return sum(map(function(persona) {
59 return Math.exp(personaDistribution.score(persona)) * Math.exp(speaker(persona).score(variant));
60 }, personae));
61};
62
63var valueInformedListener = function(variant) {
64 return Infer({method:'enumerate'}, function() {
65 var persona = sample(personaePrior);
66 factor(Math.log(Math.exp(personaDistribution.score(persona)) * Math.exp(speaker(persona).score(variant))));
67 return persona.name;
68 });
69};
70
71var naiveListener = function(variant) {
72 return Infer({method:'enumerate'}, function() {
73 var persona = sample(personaePrior);
74 factor(speaker(persona).score(variant));
75 return persona.name;
76 });
77};
78
79var ANSWER = conditionalization('ng');
02output overlaydistribution
GT s46 +p4 bins
00.190.190.380.38{"name":"asshole","competence":false,"friendliness":false} A = 0.375 B = 0.300{"name":"asshole","competence":false,"friendliness":false} A = 0.375 B = 0.3000.380.30{"name":"asshole","competence":false,"friendliness":false}{"name":"cool","competence":true,"friendliness":true} A = 0.250 B = 0.200{"name":"cool","competence":true,"friendliness":true} A = 0.250 B = 0.2000.250.20{"name":"cool","competence":true,"friendliness":true}{"name":"stern","competence":true,"friendliness":false} A = 0.375 B = 0.300{"name":"stern","competence":true,"friendliness":false} A = 0.375 B = 0.3000.380.30{"name":"stern","competence":true,"friendliness":false}{"name":"doofus","competence":false,"friendliness":true} A = 0.000 B = 0.200{"name":"doofus","competence":false,"friendliness":true} A = 0.000 B = 0.2000.20{"name":"doofus","competence":false,"friendliness":true}
03 other runs 1 total
run flags bucket TV KL actions
sonnet-46-primer-forestdb primary sonnet-4.6 +primer TV<.5 0.200 4.1048 ·
forestdb-zhu-antonyms / atom-1
shape record(expensivePrice, notInexpensivePrice) s46 +p val+ runs 1/1
per-run
00 prompt

Implement the RSA model for negated antonyms (Zhu) that predicts a listener's price estimate when hearing 'expensive' vs 'not-inexpensive' for a sweater.

Data:

webppl
1var watch = { prices: [25,75,125,...,2975], probabilities: [0.040844560268751,...] }; // 60 price bins
2var sweater = { prices: [1.5,4.5,7.5,10.5,13.5,16.5], probabilities: [0.00482838499944466,0.00832934578733181,0.0112952500492109,0.0173774790108894,0.0232006658974883,0.0258422772579257] };
3var data = { watch: watch, sweater: sweater };

(Use the exact data values from the source.)

Model: - prior(item): returns a function sampling categorical over data[item].prices with data[item].probabilities - theta_prior(item): returns a function sampling uniformDraw over data[item].prices - alpha = 2 - utterances = ["expensive", "not-inexpensive"] - cost = {"not-inexpensive": 2, "expensive": 1} - utterancePrior(): uniformDraw(utterances) - meaning(utterance, price, theta): soft semantics — if "expensive": price > theta.expensive ? flip(0.9999) : flip(0.0001); if "not-inexpensive": !(price < theta.inexpensive) ? flip(0.9999) : flip(0.0001); else true - literalListener(utterance, theta, item): Infer enumerate over uniformDraw(data[item].prices), condition on meaning, return price - speaker(price, theta, item): Infer enumerate over utterancePrior(), factor alpha*(literalListener(utt,theta,item).score(price) - cost[utt]), return utt - pragmaticListener(utterance, item): Infer enumerate — sample an_neg_thre=flip(0.2), expensive_theta from thetaPrior, inexpensive_threshold = an_neg_thre ? thetaPrior() : expensive_theta, sample price from pricePrior, construct theta = {expensive: expensive_theta, inexpensive: inexpensive_threshold}, factor speaker(price,theta,item).score(utterance), return {price, Posexp: theta.expensive, Posneg: theta.inexpensive}

Bind pragmaticListener to a function of that exact name.

Return a record of expected prices for both utterances on the sweater item: { expensivePrice: expectation(marginalize(pragmaticListener("expensive","sweater"), "price")), notInexpensivePrice: expectation(marginalize(pragmaticListener("not-inexpensive","sweater"), "price")) }

system prompt constant across atoms
(system prompt loads here)
WebPPL primer applied to *-primer-* runs
(primer loads here)
01 code comparing GT vs s46 +p
GTground truth
webppl
1var watch = {
2 "prices": [25, 75, 125, 175, 225, 275, 325, 375, 425, 475, 525, 575, 625, 675, 725, 775, 825, 875, 925, 975, 1025, 1075, 1125, 1175, 1225, 1275, 1325, 1375, 1425, 1475, 1525, 1575, 1625, 1675, 1725, 1775, 1825, 1875, 1925, 1975, 2025, 2075, 2125, 2175, 2225, 2275, 2325, 2375, 2425, 2475, 2525, 2575, 2625, 2675, 2725, 2775, 2825, 2875, 2925, 2975],
3 "probabilities": [0.040844560268751, 0.0587099798246933, 0.0656194599591356, 0.0667642412698035, 0.0615953803048016, 0.0510809063784378, 0.0467203673419258, 0.0446735950187136, 0.040047421916613, 0.0350583957334483, 0.0297508215717606, 0.0256829651118227, 0.024135920250668, 0.0228891907259206, 0.021706684520276, 0.0186449440066946, 0.0187249266247728, 0.0179250744798993, 0.0173698811746238, 0.0165581725818319, 0.0160745066032247, 0.0127927305129066, 0.0113730680265067, 0.0109485307623827, 0.00923468422650943, 0.00899007751887508, 0.00880520147998275, 0.00838023585866885, 0.00841052411004918, 0.00828830635037619, 0.00834008093757411, 0.00750681534099784, 0.00724072133740109, 0.00717291664158004, 0.00682823777708754, 0.00646995193940331, 0.00697139732982518, 0.00711846547272734, 0.00698781312802354, 0.00732316558583701, 0.00594973158122097, 0.00557461443747403, 0.00541637601910211, 0.00518850469148531, 0.00572025848989677, 0.0051443557601358, 0.00510282169734075, 0.00493720252580643, 0.00560198932991028, 0.00519158715054485, 0.00473398797752786, 0.00540907722833213, 0.00494653421540979, 0.00495500420164643, 0.00494083025189895, 0.00481566268206312, 0.00442965937328148, 0.00441189688100535, 0.00415116538135834, 0.00361842012002631]
4};
5var sweater = {
6 "prices": [1.5, 4.5, 7.5, 10.5, 13.5, 16.5],
7 "probabilities": [0.00482838499944466, 0.00832934578733181, 0.0112952500492109, 0.0173774790108894, 0.0232006658974883, 0.0258422772579257]
8};
9var data = {
10 "watch": watch,
11 "sweater": sweater
12};
13
14var prior = function(item) {
15 var prices = data[item].prices;
16 var probabilities = data[item].probabilities;
17 return function() {
18 return categorical(probabilities, prices);
19 };
20};
21
22var theta_prior = function(item) {
23 var thetas = data[item].prices;
24 return function() {
25 return uniformDraw(thetas) ;
26 };
27};
28
29var alpha = 2; // optimality parameter
30
31
32var utterances = ["expensive","not-inexpensive"];
33
34var cost = {
35 "not-inexpensive":2,
36 "expensive": 1,
37};
38var utterancePrior = function() {
39 return uniformDraw(utterances);
40};
41
42var meaning = function(utterance, price, theta) {
43 utterance == "expensive" ? price > theta.expensive ? flip(0.9999) : flip(0.0001) :
44 utterance == "not-inexpensive" ? !(price < theta.inexpensive)? flip(0.9999) : flip(0.0001):
45 true;
46};
47
48var literalListener = cache(function(utterance, theta, item) {
49 return Infer({method: "enumerate"}, function() {
50 var price = uniformDraw(data[item].prices)
51 condition(meaning(utterance, price, theta))
52 return price;
53 });
54});
55
56var speaker = cache(function(price, theta, item) {
57 return Infer({method: "enumerate"}, function() {
58 var utterance = utterancePrior();
59 factor( alpha * (literalListener(utterance, theta, item).score(price)
60 - cost[utterance]));
61 return utterance;
62 });
63});
64
65var pragmaticListener = function(utterance, item) {
66 // first identify the relevant priors
67 var pricePrior = prior(item);
68 var thetaPrior = theta_prior(item);
69 // then run inference
70 return Infer({method: "enumerate"},
71 function() {
72 var an_neg_thre = flip(0.2)
73 var expensive_theta= thetaPrior()
74
75 var inexpensive_threshold = an_neg_thre ?
76 thetaPrior() :
77 expensive_theta;
78 var price = pricePrior();
79 var theta = {
80 expensive: expensive_theta,
81 inexpensive: inexpensive_threshold
82 }
83 var Posexp = theta.expensive
84 var Posneg = theta.inexpensive
85 factor( speaker(price, theta, item).score(utterance) );
86 return { price: price, Posexp: Posexp , Posneg: Posneg };
87 });
88};
89
90
91var expensiveSweater= pragmaticListener("expensive", "sweater");
92print("Expensive:Prices")
93viz.density(marginalize(expensiveSweater, "price"));
94display(expectation(marginalize(expensiveSweater, "price")))
95print("Expensive:Thresholds:")
96viz.density(marginalize(expensiveSweater, "Posexp"));
97display(expectation(marginalize(expensiveSweater, "Posexp")))
98var notinexpensiveSweater= pragmaticListener("not-inexpensive", "sweater");
99print("NOT-Inexpensive : Prices")
100viz.density(marginalize(notinexpensiveSweater, "price"));
101display(expectation(marginalize(notinexpensiveSweater, "price")))
102print("NOT-Inexpensive:Thresholds:")
103viz.density(marginalize(notinexpensiveSweater, "Posneg"));
104display(expectation(marginalize(notinexpensiveSweater, "Posneg")))
105
106var ANSWER = ({ expensivePrice: expectation(marginalize(pragmaticListener("expensive","sweater"), "price")), notInexpensivePrice: expectation(marginalize(pragmaticListener("not-inexpensive","sweater"), "price")) });
107
s46 +psonnet-46-primer-forestdbval+
webppl
1var watch = {
2 prices: [25,75,125,175,225,275,325,375,425,475,525,575,625,675,725,775,825,875,925,975,1025,1075,1125,1175,1225,1275,1325,1375,1425,1475,1525,1575,1625,1675,1725,1775,1825,1875,1925,1975,2025,2075,2125,2175,2225,2275,2325,2375,2425,2475,2525,2575,2625,2675,2725,2775,2825,2875,2925,2975],
3 probabilities: [0.040844560268751,0.0510619810715508,0.0562983787498823,0.0562983787498823,0.0510619810715508,0.0432825073997004,0.0344248773498718,0.0257686578749289,0.0182013278249861,0.0121342185499908,0.00764296538249423,0.00455176820624657,0.00256349711624744,0.00136449816562397,0.000687499166874984,0.000327499603124993,0.000147499821874998,6.24999218750009e-05,2.49999687500004e-05,9.37498828125015e-06,3.37499578125005e-06,1.12499859375002e-06,3.74999531250006e-07,1.12499859375002e-07,3.12499609375008e-08,8.74998906250011e-09,2.24999718750003e-09,5.74999281250009e-10,1.37499828125002e-10,3.12499609375008e-11,6.87498906250011e-12,1.49999812500002e-12,3.12499609375008e-13,6.24999218750009e-14,1.24999843750002e-14,2.37499703125004e-15,4.37499453125006e-16,7.74998968750013e-17,1.37499828125002e-17,2.24999718750003e-18,3.74999531250006e-19,5.99999250000009e-20,9.37498828125015e-21,1.37499828125002e-21,1.99999750000003e-22,2.74999656250004e-23,3.74999531250006e-24,4.99999375000008e-25,6.49999187500011e-26,8.24998968750013e-27,1.02499871875002e-27,1.24999843750002e-28,1.49999812500002e-29,1.74999781250003e-30,1.99999750000003e-31,2.24999718750003e-32,2.49999687500004e-33,2.74999656250004e-34,2.99999625000005e-35,3.24999593750005e-36]
4};
5
6var sweater = {
7 prices: [1.5,4.5,7.5,10.5,13.5,16.5],
8 probabilities: [0.00482838499944466,0.00832934578733181,0.0112952500492109,0.0173774790108894,0.0232006658974883,0.0258422772579257]
9};
10
11var data = { watch: watch, sweater: sweater };
12
13var alpha = 2;
14var utterances = ["expensive", "not-inexpensive"];
15var cost = {"not-inexpensive": 2, "expensive": 1};
16
17var utterancePrior = function() {
18 return uniformDraw(utterances);
19};
20
21var meaning = function(utterance, price, theta) {
22 if (utterance === "expensive") {
23 return price > theta.expensive ? flip(0.9999) : flip(0.0001);
24 } else if (utterance === "not-inexpensive") {
25 return !(price < theta.inexpensive) ? flip(0.9999) : flip(0.0001);
26 } else {
27 return true;
28 }
29};
30
31var literalListener = mem(function(utterance, theta, item) {
32 return Infer({method: "enumerate"}, function() {
33 var price = uniformDraw(data[item].prices);
34 condition(meaning(utterance, price, theta));
35 return price;
36 });
37});
38
39var speaker = mem(function(price, theta, item) {
40 return Infer({method: "enumerate"}, function() {
41 var utt = utterancePrior();
42 factor(alpha * (literalListener(utt, theta, item).score(price) - cost[utt]));
43 return utt;
44 });
45});
46
47var pragmaticListener = function(utterance, item) {
48 return Infer({method: "enumerate"}, function() {
49 var an_neg_thre = flip(0.2);
50 var expensive_theta = uniformDraw(data[item].prices);
51 var inexpensive_threshold = an_neg_thre ? uniformDraw(data[item].prices) : expensive_theta;
52 var price = sample(Categorical({vs: data[item].prices, ps: data[item].probabilities}));
53 var theta = {expensive: expensive_theta, inexpensive: inexpensive_threshold};
54 factor(speaker(price, theta, item).score(utterance));
55 return {price: price, Posexp: theta.expensive, Posneg: theta.inexpensive};
56 });
57};
58
59var expensiveDist = pragmaticListener("expensive", "sweater");
60var notInexpensiveDist = pragmaticListener("not-inexpensive", "sweater");
61
62var expensivePrice = expectation(marginalize(expensiveDist, "price"));
63var notInexpensivePrice = expectation(marginalize(notInexpensiveDist, "price"));
64
65var ANSWER = {expensivePrice: expensivePrice, notInexpensivePrice: notInexpensivePrice};
02outputrecord(expensivePrice, notInexpensivePrice)
GT
expensivePrice=11.6333
notInexpensivePrice=11.3486
s46 +p
expensivePrice=11.6333
notInexpensivePrice=11.3486
03 other runs 1 total
run flags bucket TV KL actions
sonnet-46-primer-forestdb primary sonnet-4.6 +primer val+ ·