## Create Efficient Optimization Problems

When a problem has integer constraints, `solve` calls `intlinprog` to obtain the solution. For suggestions on obtaining a faster solution or more integer-feasible points, see Tuning Integer Linear Programming.

Before you start solving the problem, sometimes you can improve the formulation of your problem constraints or objective. Usually, the software can create expressions for the objective function or constraints more quickly in a vectorized fashion rather than in a loop. This speed difference is especially large when an optimization expression is subject to automatic differentiation; see Automatic Differentiation in Optimization Toolbox.

Suppose that your objective function is

`$\sum _{i=1}^{30}\sum _{j=1}^{30}\sum _{k=1}^{10}{x}_{i,j,k}{b}_{k}{c}_{i,j},$`

where `x` is an optimization variable, and `b` and `c` are constants. Two general ways to formulate this objective function are as follows:

• Use a `for` loop.

```x = optimvar('x',30,30,10); b = optimvar('b',10); c = optimvar('c',30,30); tic expr = optimexpr; for i = 1:30 for j = 1:30 for k = 1:10 expr = expr + x(i,j,k)*b(k)*c(i,j); end end end toc```
`Elapsed time is 307.459465 seconds.`

Here, `expr` contains the objective function expression. Although this method is straightforward, it can require excessive time to loop through many levels of `for` loops.

• Use a vectorized statement. Vectorized statements generally run faster than a `for` loop. You can create a vectorized statement in several ways.

• Expand `b` and `c`. To enable term-wise multiplication, create constants that are the same size as `x`.

```tic bigb = reshape(b,1,1,10); bigb = repmat(bigb,30,30,1); bigc = repmat(c,1,1,10); expr = sum(sum(sum(x.*bigb.*bigc))); toc```
`Elapsed time is 0.013631 seconds.`
• Loop once over `b`.

```tic expr = optimexpr; for k = 1:10 expr = expr + sum(sum(x(:,:,k).*c))*b(k); end toc```
`Elapsed time is 0.044985 seconds.`
• Create an expression by looping over `b` and then summing terms after the loop.

```tic expr = optimexpr(30,30,10); for k = 1:10 expr(:,:,k) = x(:,:,k).*c*b(k); end expr = sum(expr(:)); toc```
`Elapsed time is 0.039518 seconds.`

Observe the speed difference between a vectorized and nonvectorized implementation of the example Constrained Electrostatic Nonlinear Optimization, Problem-Based. This example was timed using automatic differentiation in R2020b.

```N = 30; x = optimvar('x',N,'LowerBound',-1,'UpperBound',1); y = optimvar('y',N,'LowerBound',-1,'UpperBound',1); z = optimvar('z',N,'LowerBound',-2,'UpperBound',0); elecprob = optimproblem; elecprob.Constraints.spherec = (x.^2 + y.^2 + (z+1).^2) <= 1; elecprob.Constraints.plane1 = z <= -x-y; elecprob.Constraints.plane2 = z <= -x+y; elecprob.Constraints.plane3 = z <= x-y; elecprob.Constraints.plane4 = z <= x+y; rng default % For reproducibility x0 = randn(N,3); for ii=1:N x0(ii,:) = x0(ii,:)/norm(x0(ii,:))/2; x0(ii,3) = x0(ii,3) - 1; end init.x = x0(:,1); init.y = x0(:,2); init.z = x0(:,3); opts = optimoptions('fmincon','Display','off'); tic energy = optimexpr(1); for ii = 1:(N-1) jj = (ii+1):N; % Vectorized tempe = (x(ii) - x(jj)).^2 + (y(ii) - y(jj)).^2 + (z(ii) - z(jj)).^2; energy = energy + sum(tempe.^(-1/2)); end elecprob.Objective = energy; disp('Vectorized computation time:') [sol,fval,exitflag,output] = solve(elecprob,init,'Options',opts); toc```
```Vectorized computation time: Elapsed time is 1.838136 seconds.```
```tic energy2 = optimexpr(1); % For nonvectorized comparison for ii = 1:(N-1) for jjj = (ii+1):N; % Not vectorized energy2 = energy2 + ((x(ii) - x(jjj))^2 + (y(ii) - y(jjj))^2 + (z(ii) - z(jjj))^2)^(-1/2); end end elecprob.Objective = energy2; disp('Non-vectorized computation time:') [sol,fval,exitflag,output] = solve(elecprob,init,'Options',opts); toc```
```Non-vectorized computation time: Elapsed time is 204.615210 seconds.```

The vectorized version is about 100 times faster than the nonvectorized version.