Skip to content

Commit f0f4b74

Browse files
authored
Merge pull request #2227 from ERGO-Code/fix-2223
Added conversion of solution values to lists, with comments about ine…
2 parents 5970ac2 + cdaa9b7 commit f0f4b74

File tree

1 file changed

+21
-163
lines changed

1 file changed

+21
-163
lines changed

examples/call_highs_from_python.py

Lines changed: 21 additions & 163 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,13 @@
5454
solution = h.getSolution()
5555
basis = h.getBasis()
5656
info = h.getInfo()
57+
# basis.col_status and basis.row_status are already lists, but
58+
# accessing values in solution.col_value and solution.row_value
59+
# directly is very inefficient, so convert them to lists
60+
col_status = basis.col_status
61+
row_status = basis.row_status
62+
col_value = list(solution.col_value)
63+
row_value = list(solution.row_value)
5764
model_status = h.getModelStatus()
5865
print("Model status = ", h.modelStatusToString(model_status))
5966
print("Optimal objective = ", info.objective_function_value)
@@ -69,12 +76,12 @@
6976
num_row = h.getNumRow()
7077
print("Variables")
7178
for icol in range(num_var):
72-
print(icol, solution.col_value[icol],
73-
h.basisStatusToString(basis.col_status[icol]))
79+
print(icol, col_value[icol],
80+
h.basisStatusToString(col_status[icol]))
7481
print("Constraints")
7582
for irow in range(num_row):
76-
print(irow, solution.row_value[irow],
77-
h.basisStatusToString(basis.row_status[irow]))
83+
print(irow, row_value[irow],
84+
h.basisStatusToString(row_status[irow]))
7885

7986
# ~~~
8087
# Clear so that incumbent model is empty
@@ -320,6 +327,12 @@ def user_interrupt_callback(
320327
solution = h.getSolution()
321328
basis = h.getBasis()
322329
info = h.getInfo()
330+
#
331+
col_status = basis.col_status
332+
col_value = list(solution.col_value)
333+
# basis.col_status is already a list, but accessing values in
334+
# solution.col_value directly is very inefficient, so convert it to a
335+
# list
323336
model_status = h.getModelStatus()
324337
print("Model status = ", h.modelStatusToString(model_status))
325338
print("Optimal objective = ", info.objective_function_value)
@@ -333,167 +346,12 @@ def user_interrupt_callback(
333346
print("Basis validity = ", h.basisValidityToString(info.basis_validity))
334347
print("Variables:")
335348
for icol in range(0, 5):
336-
print(icol, solution.col_value[icol],
337-
h.basisStatusToString(basis.col_status[icol]))
349+
print(icol, col_value[icol],
350+
h.basisStatusToString(col_status[icol]))
338351
print("...")
339352
for icol in range(num_var-2, num_var):
340-
print(icol, solution.col_value[icol],
341-
h.basisStatusToString(basis.col_status[icol]))
342-
343-
print("computing IIS for lp-incompatible-bounds")
344-
"""
345-
LP has row0 and col2 with inconsistent bounds.
346-
347-
When prioritising rows, row0 and its constituent columns (1, 2) should be found
348-
When prioritising columns, col2 and its constituent rows (0, 1) should be found
349-
"""
350-
# Define the LP
351-
lp = highspy.HighsLp()
352-
lp.num_col_ = 3
353-
lp.num_row_ = 2
354-
lp.col_cost_ = np.array([0, 0, 0], dtype=np.double)
355-
lp.col_lower_ = np.array([0, 0, 0], dtype=np.double)
356-
lp.col_upper_ = np.array([1, 1, -1], dtype=np.double)
357-
lp.row_lower_ = np.array([1, 0], dtype=np.double)
358-
lp.row_upper_ = np.array([0, 1], dtype=np.double)
359-
lp.a_matrix_.format_ = highspy.MatrixFormat.kRowwise
360-
lp.a_matrix_.start_ = np.array([0, 2, 4])
361-
lp.a_matrix_.index_ = np.array([1, 2, 0, 2])
362-
lp.a_matrix_.value_ = np.array([1, 1, 1, 1], dtype=np.double)
363-
364-
h.clear()
365-
h.passModel(lp)
366-
h.run()
367-
assert h.getModelStatus() == highspy.HighsModelStatus.kInfeasible
368-
369-
# Set IIS strategy to row priority and get IIS
370-
h.setOptionValue("iis_strategy", highspy.IisStrategy.kIisStrategyFromLpRowPriority)
371-
372-
iis = highspy.HighsIis()
373-
assert h.getIis(iis) == highspy.HighsStatus.kOk
374-
assert len(iis.col_index) == 0
375-
assert len(iis.row_index) == 1
376-
assert iis.row_index[0] == 0
377-
assert iis.row_bound[0] == highspy.IisBoundStatus.kIisBoundStatusBoxed
378-
379-
# Set IIS strategy to column priority and get IIS
380-
h.setOptionValue("iis_strategy", highspy.IisStrategy.kIisStrategyFromLpColPriority)
381-
iis.invalidate()
382-
assert h.getIis(iis) == highspy.HighsStatus.kOk
383-
assert len(iis.col_index) == 1
384-
assert len(iis.row_index) == 0
385-
assert iis.col_index[0] == 2
386-
assert iis.col_bound[0] == highspy.IisBoundStatus.kIisBoundStatusBoxed
387-
388-
print("IIS computation completed successfully")
389-
390-
print("computing feasibility relaxation")
391-
h.clear()
392-
inf = h.getInfinity()
393-
394-
num_col = 2
395-
num_row = 3
396-
num_nz = 6
397-
a_format = highspy.MatrixFormat.kColwise
398-
sense = highspy.ObjSense.kMinimize
399-
offset = 0
400-
col_cost = np.array([1, -2], dtype=np.double)
401-
col_lower = np.array([5, -inf], dtype=np.double)
402-
col_upper = np.array([inf, inf], dtype=np.double)
403-
row_lower = np.array([2, -inf, -inf], dtype=np.double)
404-
row_upper = np.array([inf, 1, 20], dtype=np.double)
405-
a_start = np.array([0, 3])
406-
a_index = np.array([0, 1, 2, 0, 1, 2])
407-
a_value = np.array([-1, -3, 20, 21, 2, 1], dtype=np.double)
408-
integrality = np.array([highspy.HighsVarType.kInteger, highspy.HighsVarType.kInteger])
409-
410-
h.passModel(
411-
num_col, num_row, num_nz, a_format, sense, offset,
412-
col_cost, col_lower, col_upper,
413-
row_lower, row_upper,
414-
a_start, a_index, a_value,
415-
integrality
416-
)
417-
418-
assert h.feasibilityRelaxation(1, 1, 1) == highspy.HighsStatus.kOk
419-
420-
info = h.getInfo()
421-
objective_function_value = info.objective_function_value
422-
423-
solution = h.getSolution()
424-
425-
assert abs(objective_function_value - 5) < 1e-6, f"Expected objective value 5, got {objective_function_value}"
426-
assert abs(solution.col_value[0] - 1) < 1e-6, f"Expected solution[0] = 1, got {solution.col_value[0]}"
427-
assert abs(solution.col_value[1] - 1) < 1e-6, f"Expected solution[1] = 1, got {solution.col_value[1]}"
428-
429-
print("Feasibility Relaxation Test Passed")
430-
431-
# Using infeasible LP from AMPL documentation
432-
h = highspy.Highs()
433-
lp = highspy.HighsLp()
434-
lp.num_col_ = 2
435-
lp.num_row_ = 3
436-
lp.col_cost_ = np.array([1, -2], dtype=np.double)
437-
lp.col_lower_ = np.array([5, -h.getInfinity()], dtype=np.double)
438-
lp.col_upper_ = np.array([h.getInfinity(), h.getInfinity()], dtype=np.double)
439-
lp.col_names_ = ["X", "Y"]
440-
lp.row_lower_ = np.array([2, -h.getInfinity(), -h.getInfinity()], dtype=np.double)
441-
lp.row_upper_ = np.array([h.getInfinity(), 1, 20], dtype=np.double)
442-
lp.row_names_ = ["R0", "R1", "R2"]
443-
lp.a_matrix_.start_ = np.array([0, 3, 6])
444-
lp.a_matrix_.index_ = np.array([0, 1, 2, 0, 1, 2])
445-
lp.a_matrix_.value_ = np.array([-1, -3, 20, 21, 2, 1], dtype=np.double)
446-
lp.integrality_ = np.array([highspy.HighsVarType.kInteger, highspy.HighsVarType.kInteger])
447-
h.setOptionValue("output_flag", False)
448-
h.passModel(lp)
449-
450-
# Vanilla feasibility relaxation
451-
print("Vanilla feasibility relaxation")
452-
h.feasibilityRelaxation(1, 1, 1)
453-
solution = h.getSolution()
454-
print(f"Solution: ({solution.col_value[0]}, {solution.col_value[1]})")
455-
print(f"Slacks: ({solution.row_value[0] - lp.row_lower_[0]}, "
456-
f"{lp.row_upper_[1] - solution.row_value[1]}, "
457-
f"{lp.row_upper_[2] - solution.row_value[2]})")
458-
459-
# Respect all lower bounds
460-
print("\nRespect all lower bounds")
461-
h.feasibilityRelaxation(-1, 1, 1)
462-
solution = h.getSolution()
463-
print(f"Solution: ({solution.col_value[0]}, {solution.col_value[1]})")
464-
print(f"Slacks: ({solution.row_value[0] - lp.row_lower_[0]}, "
465-
f"{lp.row_upper_[1] - solution.row_value[1]}, "
466-
f"{lp.row_upper_[2] - solution.row_value[2]})")
467-
468-
# Local penalties RHS {1, -1, 10}
469-
print("\nLocal penalties RHS {1, -1, 10}")
470-
local_rhs_penalty = np.array([1, -1, 10], dtype=np.double)
471-
h.feasibilityRelaxation(1, 1, 0, None, None, local_rhs_penalty)
472-
solution = h.getSolution()
473-
print(f"Solution: ({solution.col_value[0]}, {solution.col_value[1]})")
474-
print(f"Slacks: ({solution.row_value[0] - lp.row_lower_[0]}, "
475-
f"{lp.row_upper_[1] - solution.row_value[1]}, "
476-
f"{lp.row_upper_[2] - solution.row_value[2]})")
477-
478-
# Local penalties RHS {10, 1, 1}
479-
print("\nLocal penalties RHS {10, 1, 1}")
480-
local_rhs_penalty = np.array([10, 1, 1], dtype=np.double)
481-
h.feasibilityRelaxation(1, 1, 0, None, None, local_rhs_penalty)
482-
solution = h.getSolution()
483-
print(f"Solution: ({solution.col_value[0]}, {solution.col_value[1]})")
484-
print(f"Slacks: ({solution.row_value[0] - lp.row_lower_[0]}, "
485-
f"{lp.row_upper_[1] - solution.row_value[1]}, "
486-
f"{lp.row_upper_[2] - solution.row_value[2]})")
487-
488-
iis = highspy.HighsIis()
489-
assert h.getIis(iis) == highspy.HighsStatus.kOk
490-
491-
print("\nIIS")
492-
print("row_index:", iis.row_index)
493-
print("row_bound:", iis.row_bound)
494-
495-
print("col_index:", iis.col_index)
496-
print("col_bound:", iis.col_bound)
353+
print(icol, col_value[icol],
354+
h.basisStatusToString(col_status[icol]))
497355

498356
# ~~~
499357
# Clear so that incumbent model is empty

0 commit comments

Comments
 (0)