## Separate Optimization Model from Data

To obtain a scalable, reusable optimization problem, create the problem in a way that separates the problem data from the model structure.

Suppose that you have a multiperiod scheduling problem with several products. The time periods are in a vector, `periods`, and the products are in a string vector, `products`.

```periods = 1:10; products = ["strawberry","cherry","red grape",... "green grape","nectarine","apricot"];```

To create variables that represent the number of products used in each period, use statements that take sizes from the data. For example:

```usage = optimvar('usage',length(periods),products,... 'Type','integer','LowerBound',0);```

To later change the time periods or products, you need to change the data only in `periods` and `products`. You can then run the same code to create `usage`.

In other words, to maintain flexibility and allow for reuse, do not use a statement that has hard-coded data sizes. For example:

```usage = optimvar('usage',10,6,... % DO NOT DO THIS 'Type','Integer','LowerBound',0);```

The same consideration holds for expressions as well as variables. Suppose that the costs for the products are in a data matrix, `costs`, of size `length(periods)`-by-`length(products)`. To simulate valid data, create a random integer matrix of the appropriate size.

```rng default % For reproducibility costs = randi(8,length(periods),length(products));```

The best practice is to create cost expressions that take sizes from the data.

```costPerYear = sum(costs.*usage,2); totalCost = sum(costPerYear);```

In this way, if you ever change the data sizes, the statements that create `costPerYear` and `totalCost` do not change. In other words, to maintain flexibility and allow for reuse, do not use a statement that has hard-coded data sizes. For example:

```costPerYear = optimexpr(10,1); % DO NOT DO THIS totalcost = 0; for yr = 1:10 % DO NOT DO THIS costPerYear(i) = sum(costs(i,:).*usage(i,:)); totalcost = totalcost + costPerYear(i); end```