Named Index for Optimization Variables
Create Named Indices
Optimization variables can use names for indexing elements. You can give the names when you create a variable or afterward. For example, give the names while creating the variable.
x = optimvar('x',["United","Lufthansa","Virgin Air"])
x = 1x3 OptimizationVariable array with properties: Array-wide properties: Name: 'x' Type: 'continuous' IndexNames: {{} {1x2 cell}} Elementwise properties: LowerBound: [-Inf -Inf -Inf] UpperBound: [Inf Inf Inf] See variables with show. See bounds with showbounds.
optimvar
automatically maps the names you specify to index numbers in the order of your variables. For example, "United"
corresponds to index 1, "Lufthansa"
corresponds to index 2, and "Virgin Air"
corresponds to index 3. Display this last variable for confirmation.
show(x(3))
[ x('Virgin Air') ]
Index names enable you to address elements of x
by the index names. For example:
route = 2*x("United") + 3*x("Virgin Air")
route = Linear OptimizationExpression 2*x('United') + 3*x('Virgin Air')
You can create or change the index names after you create a variable. However, you cannot change the size of an optimization variable after construction. So you can change index names only by setting new names that index the same size as the original variable. For example:
x = optimvar('x',3,2); x.IndexNames = { {'row1','row2','row3'}, {'col1','col2'} };
You can set the index names for each dimension individually:
x.IndexNames{1} = {'row1', 'row2', 'row3'}; x.IndexNames{2} = {'col1', 'col2'};
You can also set an index name for a particular element:
x.IndexNames{1}{2} = 'importantRow';
Examine the index names for the variable.
x.IndexNames{1}
ans = 1x3 cell
{'row1'} {'importantRow'} {'row3'}
x.IndexNames{2}
ans = 1x2 cell
{'col1'} {'col2'}
Use Named Indices
You can create and debug some problems easily by using named index variables. For example, consider the variable x
that is indexed by the names in vars
:
vars = {'P1','P2','I1','I2','C','LE1','LE2','HE1','HE2',... 'HPS','MPS','LPS','BF1','BF2','EP','PP'}; x = optimvar('x',vars,'LowerBound',0);
Create bounds, an objective function, and linear constraints for x
by using the named indices.
x('P1').LowerBound = 2500; x('I2').UpperBound = 244000; linprob = optimproblem; linprob.Objective = 0.002614*x('HPS') + 0.0239*x('PP') + 0.009825*x('EP'); linprob.Constraints.cons1 = x('I1') - x('HE1') <= 132000;
You can use strings (" "
) or character vectors (' '
) in index variables indiscriminately. For example:
x("P2").LowerBound = 3000; x('MPS').LowerBound = 271536; showbounds(x)
2500 <= x('P1') 3000 <= x('P2') 0 <= x('I1') 0 <= x('I2') <= 244000 0 <= x('C') 0 <= x('LE1') 0 <= x('LE2') 0 <= x('HE1') 0 <= x('HE2') 0 <= x('HPS') 271536 <= x('MPS') 0 <= x('LPS') 0 <= x('BF1') 0 <= x('BF2') 0 <= x('EP') 0 <= x('PP')
There is no distinction between variables you specified with a string, such as x("P2")
, and variables you specified with a character vector, such as x('MPS')
.
Because named index variables have numeric equivalents, you can use ordinary summation and colon operators even when you have named index variables. For example, you can have constraints of these forms:
constr = sum(x) <= 100; show(constr)
x('P1') + x('P2') + x('I1') + x('I2') + x('C') + x('LE1') + x('LE2') + x('HE1') + x('HE2') + x('HPS') + x('MPS') + x('LPS') + x('BF1') + x('BF2') + x('EP') + x('PP') <= 100
y = optimvar('y',{'red','green','blue'},{'plastic','wood','metal'},... 'Type','integer','LowerBound',0); constr2 = y("red",:) == [5,7,3]; show(constr2)
(1, 1) y('red', 'plastic') == 5 (1, 2) y('red', 'wood') == 7 (1, 3) y('red', 'metal') == 3
View Solution with Index Variables
Create and solve an optimization problem using named index variables. The problem is to maximize the profit-weighted flow of fruit to various airports, subject to constraints on the weighted flows.
rng(0) % For reproducibility p = optimproblem('ObjectiveSense', 'maximize'); flow = optimvar('flow', ... {'apples', 'oranges', 'bananas', 'berries'}, {'NYC', 'BOS', 'LAX'}, ... 'LowerBound',0,'Type','integer'); p.Objective = sum(sum(rand(4,3).*flow)); p.Constraints.NYC = rand(1,4)*flow(:,'NYC') <= 10; p.Constraints.BOS = rand(1,4)*flow(:,'BOS') <= 12; p.Constraints.LAX = rand(1,4)*flow(:,'LAX') <= 35; sol = solve(p);
Solving problem using intlinprog. Running HiGHS 1.7.0: Copyright (c) 2024 HiGHS under MIT licence terms Coefficient ranges: Matrix [4e-02, 1e+00] Cost [1e-01, 1e+00] Bound [0e+00, 0e+00] RHS [1e+01, 4e+01] Presolving model 3 rows, 12 cols, 12 nonzeros 0s 3 rows, 12 cols, 12 nonzeros 0s Solving MIP model with: 3 rows 12 cols (0 binary, 12 integer, 0 implied int., 0 continuous) 12 nonzeros Nodes | B&B Tree | Objective Bounds | Dynamic Constraints | Work Proc. InQueue | Leaves Expl. | BestBound BestSol Gap | Cuts InLp Confl. | LpIters Time 0 0 0 0.00% 1160.150059 -inf inf 0 0 0 0 0.0s S 0 0 0 0.00% 1160.150059 1027.233133 12.94% 0 0 0 0 0.0s Solving report Status Optimal Primal bound 1027.23313332 Dual bound 1027.23313332 Gap 0% (tolerance: 0.01%) Solution status feasible 1027.23313332 (objective) 0 (bound viol.) 0 (int. viol.) 0 (row viol.) Timing 0.01 (total) 0.00 (presolve) 0.00 (postsolve) Nodes 1 LP iterations 3 (total) 0 (strong br.) 0 (separation) 0 (heuristics) Optimal solution found. Intlinprog stopped at the root node because the objective value is within a gap tolerance of the optimal value, options.AbsoluteGapTolerance = 1e-06. The intcon variables are integer within tolerance, options.ConstraintTolerance = 1e-06.
Find the optimal flow of oranges and berries to New York and Los Angeles.
[idxFruit,idxAirports] = findindex(flow, {'oranges','berries'}, {'NYC', 'LAX'})
idxFruit = 1×2
2 4
idxAirports = 1×2
1 3
orangeBerries = sol.flow(idxFruit, idxAirports)
orangeBerries = 2×2
0 980
70 0
This display means that no oranges are going to NYC
, 70 berries are going to NYC
, 980 oranges are going to LAX
, and no berries are going to LAX
.
List the optimal flow of the following:
Fruit Airports
----- --------
Berries NYC
Apples BOS
Oranges LAX
idx = findindex(flow, {'berries', 'apples', 'oranges'}, {'NYC', 'BOS', 'LAX'})
idx = 1×3
4 5 10
optimalFlow = sol.flow(idx)
optimalFlow = 1×3
70 28 980
This display means that 70 berries are going to NYC
, 28 apples are going to BOS
, and 980 oranges are going to LAX
.