Getting Started

Installation

Install ChoiceDesign from PyPI using pip:

pip install choicedesign

Or, to install from source with Poetry:

git clone https://github.com/ighdez/choicedesign.git
cd choicedesign
poetry install

Basic workflow

A ChoiceDesign session has six steps.

1. Define attributes

Attribute objects represent the columns of the design matrix. Each attribute has a name and a list of discrete levels:

from choicedesign.expressions import Attribute, Parameter, ASC

alt1_cost = Attribute('alt1_cost', [100, 200, 300])
alt2_cost = Attribute('alt2_cost', [100, 200, 300])
alt1_time = Attribute('alt1_time', [10, 20, 30])
alt2_time = Attribute('alt2_time', [10, 20, 30])

2. Define parameters

Parameter objects carry a prior value used to evaluate the D-error. For models with alternative-specific constants use ASC — these are automatically excluded from the D-error computation:

beta_cost = Parameter('beta_cost', -0.01)
beta_time = Parameter('beta_time', -0.05)
asc_1     = ASC('asc_1', 0.5)

3. Write utility functions

Utility functions are built by composing expressions with ordinary Python arithmetic. The result is passed to optimise() as a dictionary keyed by alternative index:

V1 = asc_1 + beta_cost * alt1_cost + beta_time * alt1_time
V2 =         beta_cost * alt2_cost + beta_time * alt2_time

4. Create the design object and generate an initial design

EffDesign holds the design configuration. gen_initdesign() generates a random balanced starting point. Optionally pass conditions that every row must satisfy (see Concepts for the condition syntax):

from choicedesign.design import EffDesign

design = EffDesign(X=[alt1_cost, alt2_cost, alt1_time, alt2_time], ncs=18)
init   = design.gen_initdesign(
    cond=['alt1_cost > alt2_cost'],
    seed=42,
)

5. Optimise

At least one stopping criterion is required. The algorithm keeps the best design seen so far and prints live progress when verbose=True:

result = design.optimise(
    init,
    V={1: V1, 2: V2},
    time_lim=2,       # stop after 2 minutes
    verbose=True,
)

optimal_design, init_derr, final_derr, n_iter, util_balance = result

The return values are:

Value

Description

optimal_design

pandas.DataFrame with a CS column and one column per attribute.

init_derr

Criterion value of the initial (random) design.

final_derr

Criterion value of the optimised design.

n_iter

Total number of algorithm iterations.

util_balance

Utility balance ratio (100 % = equal expected shares across alternatives).

6. Optional: blocking

gen_blocks() partitions the choice situations into blocks while minimising the correlation between the block column and all attributes:

blocked_design, corr_history = design.gen_blocks(optimal_design, n_blocks=3)

Evaluating an existing design

evaluate() computes the criterion value and utility balance for any design stored in a DataFrame:

d_error, ub = design.evaluate(optimal_design, V={1: V1, 2: V2})