Main Content

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: {{}  {1x3 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.00 (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.

See Also

|

Related Topics