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 showvar.
  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.

showvar(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 also set the index names for each dimension individually:

x.IndexNames{1} = {'row1', 'row2', 'row3'};
x.IndexNames{2} = {'col1', 'col2'};

You can 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 array
    {'row1'}    {'importantRow'}    {'row3'}

x.IndexNames{2}
ans = 1x2 cell array
    {'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 variable. For example, you can have constraints of these forms:

constr = sum(x) <= 100;
showconstr(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];
showconstr(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);
LP:                Optimal objective value is -1027.472366.                                         

Heuristics:        Found 1 solution using rounding.                                                 
                   Upper bound is -1027.233133.                                                     
                   Relative gap is 0.00%.                                                          

Cut Generation:    Applied 1 mir cut, and 2 strong CG cuts.                                         
                   Lower bound is -1027.233133.                                                     
                   Relative gap is 0.00%.                                                          


Optimal solution found.

Intlinprog stopped at the root node because the objective value is within a gap
tolerance of the optimal value, options.AbsoluteGapTolerance = 0 (the default
value). The intcon variables are integer within tolerance,
options.IntegerTolerance = 1e-05 (the default value).

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.0000
   70.0000         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.0000   28.0000  980.0000

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