This notebook offers tricks for diagnosing problems in the optimization and debugging them.

## Finding infeasible pairs

What do you do when the model solver returns with "Infeasible model"?

Consider using the `findinfeasiblepair(house, solver)` tool. It will give you a range within the matrix for which the results become minimally infeasible. In other words, suppose that the full linear programming matrix is \$A\$. It returns \$i\$, \$j\$, such that \$A[1:i, :]\$ is infeasible, but \$A[1:i-1, :]\$ is not, and \$A[j:end, :]\$ is infeasible but \$A[j+1:end, :]\$ is not.

You can then investigate individual rows by calling `house.A[row,:]`.

Note that the linear programming problem is always solved as follows: \$\$ \max_x f' x \$\$ s.t. \$A x < b\$ and \$x > 0\$.

To find out what is constraining these values, look down at the Understanding constraints section.

# Breaking apart the matrix

The entries in the \$f\$ vector correspond to a sequences of parameter values, those of the \$b\$ vector correspond to variable values, and the rows and columns of \$A\$ correspond to variables and parameters respectively.

To find out which parameter a particular column of \$A\$ or value in \$f\$ corresponds to, use

``cumsum(varlengths(house.model, house.paramcomps, house.parameters))``

which gives the last index of each paramter.

To find out which variable a particular row of \$A\$ or value in \$b\$ corresponds to, use

``cumsum(varlengths(house.model, house.constcomps, house.constraints, house.constdictionary))``

which gives the last index of each variable.

## Understanding constraints

The `constraining` function will identify which constraints limit the value of each parameter. It's results depend on the value of the parameter lying within \$1e-6 p + 1e-6\$ of its constraining wall, for parameter value \$p\$, so the function can miss the constraint for certain solution sets.

In the most recent version of OptiMimi, you can specify an optional `subset` constraint, a vector of indices of parameters to investigate. This works well with `findinfeasiblepair`, but keep in mind that `findinfeasiblepair` returns indices of constraints while `constraining` looks at parameters. So, you need to do the following steps.

1. Suppose that `findinfeasiblepair` returns a set of bounds \$I\$ to \$J\$, and you want to understand why \$I\$ fails. You can always replace \$J\$ below with `length(house.b)`.
2. Look at the part of the \$A\$ and \$b\$ matrices directly affecting constraint \$I\$: `house.A[I,:]`. Record the range of parameter indices to investigate as \$A\$ to \$B\$.
3. Run `sol = houseoptimize(house, solver, subset=[I:J-1])` to get a valid solution.
4. Get the constraints as `constraining(house, sol.sol, subset=[A:B])`.
5. If you want to know what constrains it on the other side to be infeasible, do the same thing again from step 3 with the subset range `[I+1:J]`.