Overview

The purpose of this page is to demonstrate basic usage of the API. The following examples will be based on the context efect model described in Busemeyer & Wang (2018). A brief description of the model can be found here and a more detailed description can be found here.

Make Predictions

The function predict will generate all possible joint probability tables of a dimensionality specified by n_way.

Two-way Tables

The code block below demonstrates how to generate predictions for 2-way joint probability tables. Each table is of size $2 \times 2$ because each attribute is binary. Given four attributes and n_way=2, there are $P(4,2) = 12$ joint probability tables in total (including the order of attributes within a pair).

using QuantumContextEffectModels
n_way = 2
parms = (
    Ψ = sqrt.([.3,.1,.2,.4]),
    θil = .3,
    θpb = .3,
)

model = QuantumModel(; parms...)
preds = predict(model; n_way)
6-element Vector{Vector{Vector{Float64}}}:
 [[0.29999999999999993, 0.19999999999999998, 0.1, 0.4], [0.29999999999999993, 0.19999999999999998, 0.1, 0.4]]
 [[0.3296242254116391, 0.6244490954320945, 0.03005940175537921, 0.015867277400887215], [0.13819660112501053, 0.3927050983124843, 0.2618033988749895, 0.2072949016875158]]
 [[0.33382612127177164, 0.5999011042230776, 0.06617387872822834, 9.889577692232744e-5], [0.33382612127177164, 0.5999011042230776, 0.06617387872822834, 9.889577692232744e-5]]
 [[0.46750946842846075, 0.4865638524152729, 0.03249053157153925, 0.013436147584727174], [0.46750946842846075, 0.4865638524152729, 0.03249053157153925, 0.013436147584727174]]
 [[0.3225948223531861, 0.6111324031416632, 0.043376094045810484, 0.02289668045934019], [0.17274575140626314, 0.3272542485937369, 0.32725424859373686, 0.17274575140626316]]
 [[0.9335790596597751, 0.00014816583507435547, 0.02049426118395861, 0.04577851332119207], [0.9335790596597751, 0.00014816583507435547, 0.02049426118395861, 0.04577851332119207]]

The nested vector preds contains $C(4,2) = 6$ combinations of attributes (ignoring order). As shown below, each sub-vector contains a flattened joint probability table, one for each order.

preds[1]
2-element Vector{Vector{Float64}}:
 [0.29999999999999993, 0.19999999999999998, 0.1, 0.4]
 [0.29999999999999993, 0.19999999999999998, 0.1, 0.4]

Three-way Tables

The code block below shows how to create all possible joint probability tables of dimensionality 3 by changing n_way=2 to n_way=3. In this example,there are $P(4,3) = 24$ joint probability tables (6 orders for each unique set of 3 attributes).

preds = predict(model; n_way = 3)
4-element Vector{Vector{Vector{Float64}}}:
 [[0.1615205488264342, 0.30598891960202657, 0.1681036765852049, 0.31846017583006797, 0.02126532899171032, 0.011225202579828931, 0.00879407276366889, 0.004642074821058283], [0.1615205488264342, 0.30598891960202657, 0.1681036765852049, 0.31846017583006797, 0.02126532899171032, 0.011225202579828931, 0.00879407276366889, 0.004642074821058283], [0.1615205488264342, 0.30598891960202657, 0.1681036765852049, 0.31846017583006797, 0.02126532899171032, 0.011225202579828931, 0.00879407276366889, 0.004642074821058283], [0.10364745084375789, 0.13090169943749475, 0.03454915028125263, 0.26180339887498955, 0.19635254915624212, 0.06909830056250527, 0.06545084971874739, 0.13819660112501053], [0.10364745084375789, 0.13090169943749475, 0.03454915028125263, 0.26180339887498955, 0.19635254915624212, 0.06909830056250527, 0.06545084971874739, 0.13819660112501053], [0.10364745084375789, 0.13090169943749475, 0.03454915028125263, 0.26180339887498955, 0.19635254915624212, 0.06909830056250527, 0.06545084971874739, 0.13819660112501053]]
 [[0.11533408831626103, 0.20726073403692505, 0.21849203295551062, 0.3926403701861526, 0.043311365919478866, 6.472812633162075e-5, 0.022862512808749482, 3.4167650590706694e-5], [0.10364745084375789, 0.06909830056250527, 0.06545084971874739, 0.26180339887498955, 0.19635254915624212, 0.13090169943749475, 0.03454915028125263, 0.13819660112501053], [0.11533408831626103, 0.20726073403692505, 0.21849203295551062, 0.3926403701861526, 0.043311365919478866, 6.472812633162075e-5, 0.022862512808749482, 3.4167650590706694e-5], [0.11533408831626103, 0.20726073403692505, 0.21849203295551062, 0.3926403701861526, 0.043311365919478866, 6.472812633162075e-5, 0.022862512808749482, 3.4167650590706694e-5], [0.10364745084375789, 0.06909830056250527, 0.06545084971874739, 0.26180339887498955, 0.19635254915624212, 0.13090169943749475, 0.03454915028125263, 0.13819660112501053], [0.10364745084375789, 0.06909830056250527, 0.06545084971874739, 0.26180339887498955, 0.19635254915624212, 0.13090169943749475, 0.03454915028125263, 0.13819660112501053]]
 [[0.3225436323161609, 0.6110354273436143, 9.697579804904305e-5, 5.119003702531242e-5, 0.007080593095478287, 0.013413668088480324, 0.029962425957330167, 0.015816087363861902], [0.3225436323161609, 0.6110354273436143, 9.697579804904305e-5, 5.119003702531242e-5, 0.007080593095478287, 0.013413668088480324, 0.029962425957330167, 0.015816087363861902], [0.11533408831626105, 0.3926403701861527, 0.21849203295551065, 0.20726073403692513, 0.022862512808749482, 6.47281263316202e-5, 0.04331136591947887, 3.4167650590707026e-5], [0.11533408831626105, 0.3926403701861527, 0.21849203295551065, 0.20726073403692513, 0.022862512808749482, 6.47281263316202e-5, 0.04331136591947887, 3.4167650590707026e-5], [0.3225436323161609, 0.6110354273436143, 9.697579804904305e-5, 5.119003702531242e-5, 0.007080593095478287, 0.013413668088480324, 0.029962425957330167, 0.015816087363861902], [0.11533408831626105, 0.3926403701861527, 0.21849203295551065, 0.20726073403692513, 0.022862512808749482, 6.47281263316202e-5, 0.04331136591947887, 3.4167650590707026e-5]]
 [[0.3225436323161608, 0.6110354273436143, 5.11900370253121e-5, 9.697579804904337e-5, 0.01341366808848032, 0.007080593095478291, 0.029962425957330167, 0.015816087363861902], [0.3225436323161608, 0.6110354273436143, 5.11900370253121e-5, 9.697579804904337e-5, 0.01341366808848032, 0.007080593095478291, 0.029962425957330167, 0.015816087363861902], [0.3225436323161608, 0.6110354273436143, 5.11900370253121e-5, 9.697579804904337e-5, 0.01341366808848032, 0.007080593095478291, 0.029962425957330167, 0.015816087363861902], [0.16152054882643424, 0.3184601758300681, 0.011225202579828928, 0.00879407276366889, 0.30598891960202657, 0.16810367658520492, 0.021265328991710325, 0.004642074821058287], [0.16152054882643424, 0.3184601758300681, 0.011225202579828928, 0.00879407276366889, 0.30598891960202657, 0.16810367658520492, 0.021265328991710325, 0.004642074821058287], [0.16152054882643424, 0.3184601758300681, 0.011225202579828928, 0.00879407276366889, 0.30598891960202657, 0.16810367658520492, 0.021265328991710325, 0.004642074821058287]]

In general, if there are $n_a$ attributes, the function predict can generate tables of dimensionality $[1,2,\dots, n_a]$.

Single Order

As shown below, you can assign the function get_joint_probs to the keyword joint_func to omit the orders of joint probability tables (e.g., [A,B] instead of [A,B], [B,A]).

using QuantumContextEffectModels
n_way = 2
parms = (
    Ψ = sqrt.([.3,.1,.2,.4]),
    θil = .3,
    θpb = .3,
)

model = QuantumModel(; parms...)
preds = predict(
    model;
    joint_func = get_joint_probs,
    n_way
)
6-element Vector{Vector{Float64}}:
 [0.29999999999999993, 0.19999999999999998, 0.1, 0.4]
 [0.3296242254116391, 0.6244490954320945, 0.03005940175537921, 0.015867277400887215]
 [0.33382612127177164, 0.5999011042230776, 0.06617387872822834, 9.889577692232744e-5]
 [0.46750946842846075, 0.4865638524152729, 0.03249053157153925, 0.013436147584727174]
 [0.3225948223531861, 0.6111324031416632, 0.043376094045810484, 0.02289668045934019]
 [0.9335790596597751, 0.00014816583507435547, 0.02049426118395861, 0.04577851332119207]

Simulate Model

The code block below demonstrates how to generate simulated data from the model using rand. In the example, we will generate 100 simulated trials for each condition.

using QuantumContextEffectModels
n_way = 2
n_trials = 100
parms = (
    Ψ = sqrt.([.3,.1,.2,.4]),
    θil = .3,
    θpb = .3,
)

model = QuantumModel(; parms...)
data = rand(model, n_trials; n_way)
6-element Vector{Vector{Vector{Int64}}}:
 [[28, 25, 9, 38], [25, 19, 10, 46]]
 [[44, 52, 1, 3], [19, 34, 27, 20]]
 [[40, 56, 4, 0], [38, 55, 7, 0]]
 [[51, 42, 4, 3], [47, 48, 4, 1]]
 [[37, 57, 3, 3], [10, 35, 34, 21]]
 [[91, 0, 2, 7], [92, 0, 4, 4]]

Labeled Tables

Interpreting the large number of nested arrays can be challenging. In the model illustrated here, there are 12 two-way tables embedded within the nested arrays. We can use to_table to assign labels to aid in the intepretation. In the code block below, we define two variables: var_names, which is the name of the attributes, and values which are the corresponding values for each attribute. To ensure the tables are labeled correctly, it is necessary to use the same order of attributes and values defined in make_projectors.

There are 12 tables in the full set. For ease of presentation, we will focus on the first two sets. The first set contains two tables for attributes believable and informative–-one for each order. The predictions are the same for each order because believable and informative are compatible. For example,

\[\Pr(B = -1 \cap I = 1) = \Pr(I = 1 \cap B = -1) = .20,\]

where 1 corresponds to yes and -1 correspond to no.

using QuantumContextEffectModels
n_way = 2
parms = (
    Ψ = sqrt.([.3,.1,.2,.4]),
    θil = .3,
    θpb = .3,
)

model = QuantumModel(; parms...)
preds = predict(model; n_way)

var_names = [
    :B, # believable
    :I, # informative
    :P, # persuasive
    :L  # likable
]
values = fill([:yes,:no], 4)

df = to_tables(preds, var_names, values, n_way)
df[1]
2-element Vector{DataFrames.DataFrame}:
 4×6 DataFrame
 Row │ group  order  attributes  values        val_idx  preds
     │ Int64  Int64  Array…      Array…        Int64    Float64
─────┼──────────────────────────────────────────────────────────
   1 │     1      1  [:B, :I]    [:yes, :yes]        1      0.3
   2 │     1      1  [:B, :I]    [:no, :yes]         2      0.2
   3 │     1      1  [:B, :I]    [:yes, :no]         3      0.1
   4 │     1      1  [:B, :I]    [:no, :no]          4      0.4
 4×6 DataFrame
 Row │ group  order  attributes  values        val_idx  preds
     │ Int64  Int64  Array…      Array…        Int64    Float64
─────┼──────────────────────────────────────────────────────────
   1 │     1      2  [:I, :B]    [:yes, :yes]        1      0.3
   2 │     1      2  [:I, :B]    [:yes, :no]         2      0.2
   3 │     1      2  [:I, :B]    [:no, :yes]         3      0.1
   4 │     1      2  [:I, :B]    [:no, :no]          4      0.4

The code block below shows the second set for believable and persuasive. Again, there is a $2 \times 2$ table for each order. However, in this case, the $2 \times 2$ tables are different because believable and persuasive are incompatible, resulting in order effects. For example,

\[\Pr(B = -1 \cap P = 1) \ne \Pr(P = 1 \cap B = -1).\]

df[2]
2-element Vector{DataFrames.DataFrame}:
 4×6 DataFrame
 Row │ group  order  attributes  values        val_idx  preds
     │ Int64  Int64  Array…      Array…        Int64    Float64
─────┼────────────────────────────────────────────────────────────
   1 │     2      1  [:B, :P]    [:yes, :yes]        1  0.329624
   2 │     2      1  [:B, :P]    [:no, :yes]         2  0.624449
   3 │     2      1  [:B, :P]    [:yes, :no]         3  0.0300594
   4 │     2      1  [:B, :P]    [:no, :no]          4  0.0158673
 4×6 DataFrame
 Row │ group  order  attributes  values        val_idx  preds
     │ Int64  Int64  Array…      Array…        Int64    Float64
─────┼───────────────────────────────────────────────────────────
   1 │     2      2  [:P, :B]    [:yes, :yes]        1  0.138197
   2 │     2      2  [:P, :B]    [:yes, :no]         2  0.392705
   3 │     2      2  [:P, :B]    [:no, :yes]         3  0.261803
   4 │     2      2  [:P, :B]    [:no, :no]          4  0.207295

DataFrame

In many cases, the use of a flat data structure can facilitate data analysis and plotting. The function to_dataframe converts a nested array into a flat DataFrame object. Similar to the function to_tables, to_dataframe requires attribute names and attribute values, which are specified in the same order as the projectors in make_projectors.

using QuantumContextEffectModels
n_way = 2
parms = (
    Ψ = sqrt.([.3,.1,.2,.4]),
    θil = .3,
    θpb = .3,
)

model = QuantumModel(; parms...)
preds = predict(model; n_way)

var_names = [
    :B, # believable
    :I, # informative
    :P, # persuasive
    :L  # likable
]
values = fill([:yes,:no], 4)

df = to_dataframe(preds, var_names, values, n_way)
first(df, 8)
8×6 DataFrame
Rowgrouporderattributesvaluesval_idxpreds
Int64Int64Array…Array…Int64Float64
111[:B, :I][:yes, :yes]10.3
211[:B, :I][:no, :yes]20.2
311[:B, :I][:yes, :no]30.1
411[:B, :I][:no, :no]40.4
512[:I, :B][:yes, :yes]10.3
612[:I, :B][:yes, :no]20.2
712[:I, :B][:no, :yes]30.1
812[:I, :B][:no, :no]40.4

Evaluate Log Likelihood

The log likelihood of data can be evaluated using logpdf. In the code block below, we generate simulated data and evaluate the logpdf:

using QuantumContextEffectModels
n_way = 2
n_trials = 100
parms = (
    Ψ = sqrt.([.3,.1,.2,.4]),
    θil = .3,
    θpb = .3,
)

model = QuantumModel(; parms...)
data = rand(model, n_trials; n_way)
logpdf(model, data, n_trials; n_way)
-78.58301738686018