Skip to content

Variables

Gurobi variable definitions for the PS-BHLP models.

Each variable class wraps a VariableMetaData descriptor and a build method that creates the corresponding Gurobi variables.

ClientDecisionVariable

Bases: Variable

Client (follower) decision variable for bilevel hub location.

Binary variable that captures whether client \(z\) on route \((i,j)\) accepts the price offered by the leader:

\[y_{ij}^z \in \{0,1\} \quad \forall i,j \in V, z \in M_{ij}\]

The client accepts if and only if their utility is non-negative: \(a_{ij}^z p_{ij} - b_{ij}^z \geq 0\).

The variable is indexed by (i, j, z): origin \(i\), destination \(j\), and client index \(z\) on that route.

build(model)

Create binary Gurobi variables over all client routes.

Source code in src/oracle_paper/variables/decision_variable.py
def build(self, model: "BaseModel") -> tupledict:
    """Create binary Gurobi variables over all client routes."""
    client_keys = model.data[BilevelDataCol.CLIENT_ID_ROUTE]
    return model.model.addVars(
        client_keys,
        vtype=GRB.BINARY,
        name=str(self.var_metadata),
    )

LinearXYVariable

Bases: Variable

Linearization variable \(X_{ijkm}^z\) that reproduces the cubic term.

\[X_{ijkm}^z \;\widehat{=}\; y_{ij}^z \cdot x_{ik} \cdot x_{jm}\]
\[X_{ijkm}^z \in \{0,1\} \quad \forall i,j,k,m \in V, z \in M_{ij}\]

Used in PS-HLP and PPC-HLP. The four node indices represent: origin \(i\), destination \(j\), first hub \(k\), second hub \(m\). \(z\) is the client index on route \((i,j)\).

Related: - LinearizationConstraint - ClientDecisionVariable

PriceVariable

Bases: Variable

Price variable for the PS-HLP (Big M) model.

Continuous non-negative variable representing the price the leader (hub operator) charges for transport on route \((i,j)\):

\[p_{ij} \geq 0 \quad \forall i,j \in V\]

Works together with: - ClientDecisionVariable - BigMConstraint

build(model)

Create \(|V| imes |V|\) continuous non-negative Gurobi variables.

Source code in src/oracle_paper/variables/price_variable.py
def build(self, model: "BaseModel") -> tupledict:
    """Create $|V| \times |V|$ continuous non-negative Gurobi variables."""
    nodes = get_nodes(model)
    return model.model.addVars(
        nodes, nodes,
        vtype=GRB.CONTINUOUS,
        lb=0,
        name=str(self.var_metadata),
    )

RecursiveClientDecisionVariable

Bases: Variable

Aggregated client decision variable for the PC-HLP model.

\[y_{ij}^z \in \{0,1\} \quad \forall (i,j,z) \in K\]

where \(K\) is the set of grouped client keys. Unlike the flat ClientDecisionVariable, this variable indexes aggregated clients — \(z\) represents a merged group of original clients. Keys are read from BilevelDataCol.CLIENT_KEYS.

RecursiveLinearXYVariable

Bases: Variable

Recursive linearization variable for the PC-HLP model.

Reproduces the cubic term for merged (aggregated) clients:

\[X_{ijkm}^z \;\widehat{=}\; y_{ij}^z \cdot x_{ik} \cdot x_{jm}\]
\[X_{ijkm}^z \in \{0,1\} \quad \forall (i,j,z) \in K\]

Same structure as LinearXYVariable but uses aggregated client keys from BilevelDataCol.CLIENT_KEYS.

Related: - RecursiveLinearizationConstraint