$npx -y skills add matlab/matlab-agentic-toolkit --skill matlab-solve-optimizationUse when writing, solving, or debugging MATLAB optimization code — formulating problems (optimproblem, optimvar, fcn2optimexpr), selecting and configuring solvers (fmincon, linprog, quadprog, intlinprog, lsqnonlin, ga, surrogateopt, optimoptions), or validating results (exitflag,
| 1 | # MATLAB Optimization Workflow |
| 2 | |
| 3 | Guide the full optimization lifecycle: classify the problem, formulate it, select and configure a solver, and validate the results. |
| 4 | |
| 5 | ## When to Use |
| 6 | |
| 7 | - User is defining an optimization problem in MATLAB (variables, objectives, constraints) |
| 8 | - User asks about `optimproblem`, `optimvar`, `optimconstr`, `optimexpr`, or `fcn2optimexpr` |
| 9 | - User is selecting or configuring a solver (`optimoptions`, algorithm choice, tuning) |
| 10 | - User is interpreting results, debugging convergence, or checking exitflags |
| 11 | - User is deciding between problem-based and solver-based approaches |
| 12 | - User is writing optimization code with for-loops over decision variables or constraints |
| 13 | |
| 14 | ## When NOT to Use |
| 15 | |
| 16 | - User is asking to solve a problem that doesn't require numerical optimization solvers (e.g., finding the minimum value in an array or table) |
| 17 | - User is working with non-optimization MATLAB code (data analysis, plotting, signal processing) |
| 18 | - User is using a third-party optimization toolbox (not MathWorks) |
| 19 | - User is solving symbolic equations with `solve(eqns, vars)`, ODE systems, or linear system solves (`A\b`) |
| 20 | |
| 21 | --- |
| 22 | |
| 23 | ## Stage 1: Classify & Formulate |
| 24 | |
| 25 | ### 1.1 Classify the Problem |
| 26 | |
| 27 | Before formulating, identify the problem class — it determines which solver to use, what guarantee you can promise (global vs local), and whether a domain-specific tool should replace the generic path. |
| 28 | |
| 29 | See [references/classify.md](references/classify.md) for the class→solver→guarantee table, convexity quick-checks, and "hidden easier class" heuristics. Key actions: |
| 30 | - Check if a purpose-built domain tool exists before falling back to `optimproblem` |
| 31 | - Watch for hidden easier classes (sum-of-squares disguised as NLP, linear structure missed) |
| 32 | - For QPs, check `eig(H)` — nonconvex QPs cannot use `quadprog` reliably |
| 33 | - Watch for hidden nonsmoothness: `max`, `min`, `abs`, `sort`, `if`/branching, or norms other than squared-2-norm |
| 34 | |
| 35 | ### 1.2 Choose Approach |
| 36 | |
| 37 | **Use problem-based by default** for readable definitions, N-D modeling, and every LP, QP, conic, and mixed-integer problem (unless coefficients are already in matrix-vector form). Problem-based provides automatic differentiation and is less error-prone. |
| 38 | |
| 39 | Even when AD is blocked (e.g., `ode45` in the objective), `fcn2optimexpr` can still wrap the function as a black-box — problem-based remains useful. |
| 40 | |
| 41 | Only fall back to solver-based when one of these applies: |
| 42 | |
| 43 | | Use solver-based when... | Reason | |
| 44 | |---|---| |
| 45 | | Trivial mapping to solver API — one vector `x`, pre-coded objective with exact gradients/Hessian | No benefit from abstraction; solver-based is direct | |
| 46 | | Overhead of building problem-based expressions dominates computation | Avoid tracing/transformation overhead | |
| 47 | | Need a solver feature problem-based doesn't expose (`CheckpointFile`, exact Hessians, custom `OutputFcn`) | Only available via solver-based calls | |
| 48 | | C code generation for embedded deployment is required | Problem-based does not support codegen | |
| 49 | |
| 50 | **Converting between approaches:** `prob2struct(prob)` converts problem-based to solver-based form for deployment or performance. |
| 51 | |
| 52 | **References:** |
| 53 | - Problem-based: [references/problem-based-guide.md](references/problem-based-guide.md) |
| 54 | - Solver-based (class→solver mapping): [references/classify.md](references/classify.md) |
| 55 | |
| 56 | ### 1.3 Formulate the Problem |
| 57 | |
| 58 | **Problem-based canonical template:** |
| 59 | |
| 60 | ```matlab |
| 61 | % 1. Define decision variables |
| 62 | x = optimvar("x", N, LowerBound=lb, UpperBound=ub); |
| 63 | |
| 64 | % 2. Create problem |
| 65 | prob = optimproblem("Objective", sum(x,"all")); |
| 66 | |
| 67 | % 3. Add constraints |
| 68 | prob.Constraints.linear = A*x <= b; |
| 69 | prob.Constraints.nonlinear = fcn2optimexpr(@myNonlinFcn, x) <= rhs; |
| 70 | |
| 71 | % 4. Set initial guess (must be struct with field names matching optimvar names) |
| 72 | x0.x = initialValues; |
| 73 | |
| 74 | % 5. Solve |
| 75 | [sol, fval, exitflag, output] = solve(prob, x0); |
| 76 | ``` |
| 77 | |
| 78 | **Solver-based key differences:** |
| 79 | - Initial guess is a **numeric vector**, not a struct |
| 80 | - You manage variable indexing manually (flat vector `x`) |
| 81 | - Supply gradients manually for best performance (`SpecifyObjectiveGradient=true`) |
| 82 | - Linear/quadratic solvers require explicit coefficient matrices |
| 83 | |
| 84 | ### 1.4 Validate at the Start Point |
| 85 | |
| 86 | Before calling any solver, evaluate the objective and constraints at `x0` to catch sign/size/NaN errors early: |
| 87 | |
| 88 | ```matlab |
| 89 | % Problem-based |
| 90 | fval0 = evaluate(prob.Objective, x0); |
| 91 | assert(isfinite(fval0), 'Objective is not finite at x0'); |
| 92 | infeas0 = infeasibility(prob.Constraint |