Skip to content

Debugging a wrong answer

What to read when a model solves to the wrong number, or does not solve, in the order that finds the fault soonest.

1. Check the file

import specsolve as sps

sps.check('dispatch.yaml')

check raises on a construct outside the language. model.check('highs') refuses a built model the solver cannot take (what each sink takes).

2. Read the shape the build produced

model = sps.build('dispatch.yaml', sources)
report = model.diagnostics()
report.columns, report.rows, report.nonzeros  # 8, 4, 8
report.omissions  # rows a constraint declared and did not build
report.sparse_parameters  # parameters whose table is short of their coordinates

A count smaller than you expected is a mask, or a table with a row missing (diagnostics).

3. Read the row that is wrong

print(model.row('power_balance', snapshot=2))
# power_balance[snapshot=2]: +1 p[snapshot=2, generator=wind] +1 p[snapshot=2, generator=gas] == 180

The line is the row as the solver got it. A term you expected and do not see is a mask; a coefficient you did not expect is the data (Model.row).

4. When the solve is infeasible

Ask for the IIS (irreducible infeasible subsystem), the rows and bounds that cannot all hold:

model.solve().termination_condition  # 'infeasible'
print(model.infeasible_subsystem())
# power_balance[snapshot=2] == 180
# p[snapshot=2, generator=gas] <= 100 (upper bound)
# p[snapshot=2, generator=wind] <= 50 (upper bound)

Drop any one line and the rest can hold (Model.infeasible_subsystem).

HiGHS finds no IIS where integer variables cause the conflict. Solve with gurobi or xpress, or add a slack to the row and minimise it, as the feasibility model does.

5. When the number is wrong and the rows look right

The file says something other than what you meant. Render it as math: typeset.

6. When a loop of re-solves is slow

Compare the loop with the default and with start=None, as warm-starting a re-solve shows.