Variable
Bases: BaseOperableBlock
A decision variable for an optimization model.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
*indexing_sets
|
SetTypes | Iterable[SetTypes]
|
If no indexing_sets are provided, a single variable with no dimensions is created. Otherwise, a variable is created for each element in the Cartesian product of the indexing_sets (see Set for details on behaviour). |
()
|
lb
|
Operable | None
|
The lower bound for all variables. |
None
|
ub
|
Operable | None
|
The upper bound for all variables. |
None
|
vtype
|
VType | VTypeValue
|
The type of the variable. Can be either a VType enum or a string. Default is VType.CONTINUOUS. |
CONTINUOUS
|
equals
|
Operable | None
|
When specified, a variable is created and a constraint is added to make the variable equal to the provided expression. |
None
|
Examples:
>>> import pandas as pd
>>> m = pf.Model()
>>> df = pd.DataFrame(
... {"dim1": [1, 1, 2, 2, 3, 3], "dim2": ["a", "b", "a", "b", "a", "b"]}
... )
>>> Variable(df)
<Variable 'unnamed' height=6>
┌──────┬──────┐
│ dim1 ┆ dim2 │
│ (3) ┆ (2) │
╞══════╪══════╡
│ 1 ┆ a │
│ 1 ┆ b │
│ 2 ┆ a │
│ 2 ┆ b │
│ 3 ┆ a │
│ 3 ┆ b │
└──────┴──────┘
Variables cannot be used until they're added to the model.
>>> m.constraint = Variable(df) <= 3
Traceback (most recent call last):
...
ValueError: Cannot use 'Variable' before it has been added to a model.
Instead, assign the variable to the model first:
>>> m.v
<Variable 'v' height=6>
┌──────┬──────┬──────────┐
│ dim1 ┆ dim2 ┆ variable │
│ (3) ┆ (2) ┆ │
╞══════╪══════╪══════════╡
│ 1 ┆ a ┆ v[1,a] │
│ 1 ┆ b ┆ v[1,b] │
│ 2 ┆ a ┆ v[2,a] │
│ 2 ┆ b ┆ v[2,b] │
│ 3 ┆ a ┆ v[3,a] │
│ 3 ┆ b ┆ v[3,b] │
└──────┴──────┴──────────┘
>>> m.v2 = Variable(df[["dim1"]])
Traceback (most recent call last):
...
ValueError: Duplicate rows found in input data.
>>> m.v3 = Variable(df[["dim1"]].drop_duplicates())
>>> m.v3
<Variable 'v3' height=3>
┌──────┬──────────┐
│ dim1 ┆ variable │
│ (3) ┆ │
╞══════╪══════════╡
│ 1 ┆ v3[1] │
│ 2 ┆ v3[2] │
│ 3 ┆ v3[3] │
└──────┴──────────┘
Methods:
Name | Description |
---|---|
next |
Creates an expression where the variable at each label is the next variable in the specified dimension. |
to_expr |
Converts the Variable to an Expression. |
Attributes:
Name | Type | Description |
---|---|---|
attr |
Container
|
Allows reading and writing variable attributes similarly to Model.attr. |
solution |
Retrieves a variable's optimal value after the model has been solved. |
|
vtype |
VType
|
|
Source code in pyoframe/_core.py
attr: Container
Allows reading and writing variable attributes similarly to Model.attr.
solution
Retrieves a variable's optimal value after the model has been solved.
Return type is a DataFrame if the variable has dimensions, otherwise it is a single value. Binary and integer variables are returned as integers.
Examples:
>>> m = pf.Model()
>>> m.var_continuous = pf.Variable({"dim1": [1, 2, 3]}, lb=5, ub=5)
>>> m.var_integer = pf.Variable(
... {"dim1": [1, 2, 3]}, lb=4.5, ub=5.5, vtype=pf.VType.INTEGER
... )
>>> m.var_dimensionless = pf.Variable(
... lb=4.5, ub=5.5, vtype=pf.VType.INTEGER
... )
>>> m.var_continuous.solution
Traceback (most recent call last):
...
RuntimeError: Failed to retrieve solution for variable. Are you sure the model has been solved?
>>> m.optimize()
>>> m.var_continuous.solution
shape: (3, 2)
┌──────┬──────────┐
│ dim1 ┆ solution │
│ --- ┆ --- │
│ i64 ┆ f64 │
╞══════╪══════════╡
│ 1 ┆ 5.0 │
│ 2 ┆ 5.0 │
│ 3 ┆ 5.0 │
└──────┴──────────┘
>>> m.var_integer.solution
shape: (3, 2)
┌──────┬──────────┐
│ dim1 ┆ solution │
│ --- ┆ --- │
│ i64 ┆ i64 │
╞══════╪══════════╡
│ 1 ┆ 5 │
│ 2 ┆ 5 │
│ 3 ┆ 5 │
└──────┴──────────┘
>>> m.var_dimensionless.solution
5
vtype: VType = VType(vtype)
next(dim: str, wrap_around: bool = False) -> Expression
Creates an expression where the variable at each label is the next variable in the specified dimension.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
dim
|
str
|
The dimension over which to shift the variable. |
required |
wrap_around
|
bool
|
If |
False
|
Examples:
>>> import pandas as pd
>>> time_dim = pd.DataFrame({"time": ["00:00", "06:00", "12:00", "18:00"]})
>>> space_dim = pd.DataFrame({"city": ["Toronto", "Berlin"]})
>>> m = pf.Model()
>>> m.bat_charge = pf.Variable(time_dim, space_dim)
>>> m.bat_flow = pf.Variable(time_dim, space_dim)
>>> # Fails because the dimensions are not the same
>>> m.bat_charge + m.bat_flow == m.bat_charge.next("time")
Traceback (most recent call last):
...
pyoframe._constants.PyoframeError: Cannot subtract the two expressions below because expression 1 has extra labels.
Expression 1: (bat_charge + bat_flow)
Expression 2: bat_charge.next(…)
Extra labels in expression 1:
┌───────┬─────────┐
│ time ┆ city │
╞═══════╪═════════╡
│ 18:00 ┆ Toronto │
│ 18:00 ┆ Berlin │
└───────┴─────────┘
Use .drop_extras() or .keep_extras() to indicate how the extra labels should be handled. Learn more at
https://bravos-power.github.io/pyoframe/latest/learn/concepts/addition
>>> (m.bat_charge + m.bat_flow).drop_extras() == m.bat_charge.next("time")
<Constraint 'unnamed' height=6 terms=18 type=linear>
┌───────┬─────────┬────────────────────────────────────────────────────────────────────────────────┐
│ time ┆ city ┆ constraint │
│ (3) ┆ (2) ┆ │
╞═══════╪═════════╪════════════════════════════════════════════════════════════════════════════════╡
│ 00:00 ┆ Toronto ┆ bat_charge[00:00,Toronto] + bat_flow[00:00,Toronto] │
│ ┆ ┆ - bat_charge[06:00,Toronto] = 0 │
│ 00:00 ┆ Berlin ┆ bat_charge[00:00,Berlin] + bat_flow[00:00,Berlin] - bat_charge[06:00,Berlin] │
│ ┆ ┆ = 0 │
│ 06:00 ┆ Toronto ┆ bat_charge[06:00,Toronto] + bat_flow[06:00,Toronto] │
│ ┆ ┆ - bat_charge[12:00,Toronto] = 0 │
│ 06:00 ┆ Berlin ┆ bat_charge[06:00,Berlin] + bat_flow[06:00,Berlin] - bat_charge[12:00,Berlin] │
│ ┆ ┆ = 0 │
│ 12:00 ┆ Toronto ┆ bat_charge[12:00,Toronto] + bat_flow[12:00,Toronto] │
│ ┆ ┆ - bat_charge[18:00,Toronto] = 0 │
│ 12:00 ┆ Berlin ┆ bat_charge[12:00,Berlin] + bat_flow[12:00,Berlin] - bat_charge[18:00,Berlin] │
│ ┆ ┆ = 0 │
└───────┴─────────┴────────────────────────────────────────────────────────────────────────────────┘
>>> (m.bat_charge + m.bat_flow) == m.bat_charge.next(
... "time", wrap_around=True
... )
<Constraint 'unnamed' height=8 terms=24 type=linear>
┌───────┬─────────┬────────────────────────────────────────────────────────────────────────────────┐
│ time ┆ city ┆ constraint │
│ (4) ┆ (2) ┆ │
╞═══════╪═════════╪════════════════════════════════════════════════════════════════════════════════╡
│ 00:00 ┆ Toronto ┆ bat_charge[00:00,Toronto] + bat_flow[00:00,Toronto] │
│ ┆ ┆ - bat_charge[06:00,Toronto] = 0 │
│ 00:00 ┆ Berlin ┆ bat_charge[00:00,Berlin] + bat_flow[00:00,Berlin] - bat_charge[06:00,Berlin] │
│ ┆ ┆ = 0 │
│ 06:00 ┆ Toronto ┆ bat_charge[06:00,Toronto] + bat_flow[06:00,Toronto] │
│ ┆ ┆ - bat_charge[12:00,Toronto] = 0 │
│ 06:00 ┆ Berlin ┆ bat_charge[06:00,Berlin] + bat_flow[06:00,Berlin] - bat_charge[12:00,Berlin] │
│ ┆ ┆ = 0 │
│ 12:00 ┆ Toronto ┆ bat_charge[12:00,Toronto] + bat_flow[12:00,Toronto] │
│ ┆ ┆ - bat_charge[18:00,Toronto] = 0 │
│ 12:00 ┆ Berlin ┆ bat_charge[12:00,Berlin] + bat_flow[12:00,Berlin] - bat_charge[18:00,Berlin] │
│ ┆ ┆ = 0 │
│ 18:00 ┆ Toronto ┆ bat_charge[18:00,Toronto] + bat_flow[18:00,Toronto] │
│ ┆ ┆ - bat_charge[00:00,Toronto] = 0 │
│ 18:00 ┆ Berlin ┆ bat_charge[18:00,Berlin] + bat_flow[18:00,Berlin] - bat_charge[00:00,Berlin] │
│ ┆ ┆ = 0 │
└───────┴─────────┴────────────────────────────────────────────────────────────────────────────────┘
Source code in pyoframe/_core.py
2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 |
|
to_expr() -> Expression
Converts the Variable to an Expression.
Comments