# The paths to MPS file instances assumes that this is run in the # root directory of HiGHS import numpy as np import highspy hscb = highspy.cb h = highspy.Highs() # h.setOptionValue("log_to_console", True) inf = highspy.kHighsInf alt_inf = h.getInfinity() print('highspy.kHighsInf = ', inf, 'h.getInfinity() = ', alt_inf) # ~~~ # Read in and solve avgas h.readModel("check/instances/avgas.mps") # h.writeModel("ml.mps") h.run() lp = h.getLp() num_nz = h.getNumNz() print("LP has ", lp.num_col_, " columns", lp.num_row_, " rows and ", num_nz, " nonzeros.") # ~~~ # Clear so that incumbent model is empty h.clear() # Now define the blending model as a HighsLp instance lp = highspy.HighsLp() lp.num_col_ = 2 lp.num_row_ = 2 lp.sense_ = highspy.ObjSense.kMaximize lp.col_cost_ = np.array([8, 10], dtype=np.double) lp.col_lower_ = np.array([0, 0], dtype=np.double) lp.col_upper_ = np.array([inf, inf], dtype=np.double) lp.row_lower_ = np.array([-inf, -inf], dtype=np.double) lp.row_upper_ = np.array([120, 210], dtype=np.double) lp.a_matrix_.start_ = np.array([0, 2, 4]) lp.a_matrix_.index_ = np.array([0, 1, 0, 1]) lp.a_matrix_.value_ = np.array([0.3, 0.7, 0.5, 0.5], dtype=np.double) h.passModel(lp) # Solve h.run() # Print solution solution = h.getSolution() basis = h.getBasis() info = h.getInfo() model_status = h.getModelStatus() print("Model status = ", h.modelStatusToString(model_status)) print("Optimal objective = ", info.objective_function_value) print("Iteration count = ", info.simplex_iteration_count) print( "Primal solution status = ", h.solutionStatusToString( info.primal_solution_status) ) print("Dual solution status = ", h.solutionStatusToString(info.dual_solution_status)) print("Basis validity = ", h.basisValidityToString(info.basis_validity)) num_var = h.getNumCol() num_row = h.getNumRow() print("Variables") for icol in range(num_var): print(icol, solution.col_value[icol], h.basisStatusToString(basis.col_status[icol])) print("Constraints") for irow in range(num_row): print(irow, solution.row_value[irow], h.basisStatusToString(basis.row_status[irow])) # ~~~ # Clear so that incumbent model is empty h.clear() # Now define the test-semi-definite0 model (from TestQpSolver.cpp) # as a HighsModel instance model = highspy.HighsModel() model.lp_.model_name_ = "semi-definite" model.lp_.num_col_ = 3 model.lp_.num_row_ = 1 model.lp_.col_cost_ = np.array([1.0, 1.0, 2.0], dtype=np.double) model.lp_.col_lower_ = np.array([0, 0, 0], dtype=np.double) model.lp_.col_upper_ = np.array([inf, inf, inf], dtype=np.double) model.lp_.row_lower_ = np.array([2], dtype=np.double) model.lp_.row_upper_ = np.array([inf], dtype=np.double) model.lp_.a_matrix_.format_ = highspy.MatrixFormat.kColwise model.lp_.a_matrix_.start_ = np.array([0, 1, 2, 3]) model.lp_.a_matrix_.index_ = np.array([0, 0, 0]) model.lp_.a_matrix_.value_ = np.array([1.0, 1.0, 1.0], dtype=np.double) model.hessian_.dim_ = model.lp_.num_col_ model.hessian_.start_ = np.array([0, 2, 2, 3]) model.hessian_.index_ = np.array([0, 2, 2]) model.hessian_.value_ = np.array([2.0, -1.0, 1.0], dtype=np.double) print("test-semi-definite0 as HighsModel") h.passModel(model) h.run() # ~~~ # Clear so that incumbent model is empty h.clear() num_col = 3 num_row = 1 sense = highspy.ObjSense.kMinimize offset = 0 col_cost = np.array([1.0, 1.0, 2.0], dtype=np.double) col_lower = np.array([0, 0, 0], dtype=np.double) col_upper = np.array([inf, inf, inf], dtype=np.double) row_lower = np.array([2], dtype=np.double) row_upper = np.array([inf], dtype=np.double) a_matrix_format = highspy.MatrixFormat.kColwise a_matrix_start = np.array([0, 1, 2, 3]) a_matrix_index = np.array([0, 0, 0]) a_matrix_value = np.array([1.0, 1.0, 1.0], dtype=np.double) a_matrix_num_nz = a_matrix_start[num_col] hessian_format = highspy.HessianFormat.kTriangular hessian_start = np.array([0, 2, 2, 3]) hessian_index = np.array([0, 2, 2]) hessian_value = np.array([2.0, -1.0, 1.0], dtype=np.double) hessian_num_nz = hessian_start[num_col] integrality = np.array([0, 0, 0]) print("test-semi-definite0 as pointers") h.passModel( num_col, num_row, a_matrix_num_nz, hessian_num_nz, a_matrix_format, hessian_format, sense, offset, col_cost, col_lower, col_upper, row_lower, row_upper, a_matrix_start, a_matrix_index, a_matrix_value, hessian_start, hessian_index, hessian_value, integrality, ) h.run() h.writeSolution("", 1) # ~~~ # Clear so that incumbent model is empty h.clear() print("25fv47 as HighsModel") h.readModel("check/instances/25fv47.mps") h.presolve() presolved_lp = h.getPresolvedLp() # Create a HiGHS instance to solve the presolved LP print('\nCreate Highs instance to solve presolved LP') h1 = highspy.Highs() h1.passModel(presolved_lp) # Get and set options options = h1.getOptions() options.presolve = "off" options.solver = "ipm" h1.passOptions(options) # can be used to check option values # h1.writeOptions("") h1.run() solution = h1.getSolution() basis = h1.getBasis() print("Crossover, then postsolve using solution and basis from another instance") h.postsolve(solution, basis) # Get solution info = h.getInfo() model_status = h.getModelStatus() print("Model status = ", h.modelStatusToString(model_status)) print("Optimal objective = ", info.objective_function_value) print("Iteration count = ", info.simplex_iteration_count) run_time = h.getRunTime() print("Total HiGHS run time is ", run_time) # Get an optimal basis # Clear so that incumbent model is empty h.clear() print("25fv47 as HighsModel") h.readModel("check/instances/25fv47.mps") h.run() simplex_iteration_count = h.getInfo().simplex_iteration_count print("From initial basis, simplex iteration count =", simplex_iteration_count) basis = h.getBasis() h.clearSolver() h.setBasis(basis) h.run() simplex_iteration_count = h.getInfo().simplex_iteration_count print("From optimal basis, simplex iteration count =", simplex_iteration_count) status = h.setBasis() h.run() simplex_iteration_count = h.getInfo().simplex_iteration_count print("From logical basis, simplex iteration count =", simplex_iteration_count) # Define a callback def user_interrupt_callback( callback_type, message, data_out, data_in, user_callback_data ): # dev_run = True dev_run = False # Constants for iteration limits or objective targets, adjust as required SIMPLEX_ITERATION_LIMIT = 100 IPM_ITERATION_LIMIT = 100 EGOUT_OBJECTIVE_TARGET = 1.0 # Callback for MIP Improving Solution if callback_type == hscb.HighsCallbackType.kCallbackMipImprovingSolution: # Assuming it is a list or array assert user_callback_data is not None, "User callback data is None!" local_callback_data = user_callback_data[0] if dev_run: print(f"userCallback(type {callback_type};") print(f"data {local_callback_data:.4g}): {message}") print(f"with objective {data_out.objective_function_value}") print(f"and solution[0] = {data_out.mip_solution[0]}") # Check and update the objective function value assert ( local_callback_data >= data_out.objective_function_value ), "Objective function value is invalid!" user_callback_data[0] = data_out.objective_function_value else: # Various other callback types if callback_type == hscb.HighsCallbackType.kCallbackLogging: if dev_run: print(f"userInterruptCallback(type {callback_type}): {message}") elif callback_type == hscb.HighsCallbackType.kCallbackSimplexInterrupt: if dev_run: print(f"userInterruptCallback(type {callback_type}): {message}") print("with iteration count = ", data_out.simplex_iteration_count) data_in.user_interrupt = ( data_out.simplex_iteration_count > SIMPLEX_ITERATION_LIMIT ) elif callback_type == hscb.HighsCallbackType.kCallbackIpmInterrupt: if dev_run: print(f"userInterruptCallback(type {callback_type}): {message}") print(f"with iteration count = {data_out.ipm_iteration_count}") data_in.user_interrupt = ( data_out.ipm_iteration_count > IPM_ITERATION_LIMIT ) elif callback_type == hscb.HighsCallbackType.kCallbackMipInterrupt: if dev_run: print(f"userInterruptCallback(type {callback_type}): {message}") print(f"Dual bound = {data_out.mip_dual_bound:.4g}") print(f"Primal bound = {data_out.mip_primal_bound:.4g}") print(f"Gap = {data_out.mip_gap:.4g}") print(f"Objective = {data_out.objective_function_value:.4g}") data_in.user_interrupt = ( data_out.objective_function_value < EGOUT_OBJECTIVE_TARGET ) # Define model h.addVar(-inf, inf) h.addVar(-inf, inf) h.changeColsCost(2, np.array([0, 1]), np.array([0, 1], dtype=np.double)) num_cons = 2 lower = np.array([2, 0], dtype=np.double) upper = np.array([inf, inf], dtype=np.double) num_new_nz = 4 starts = np.array([0, 2]) indices = np.array([0, 1, 0, 1]) values = np.array([-1, 1, 1, 1], dtype=np.double) h.addRows(num_cons, lower, upper, num_new_nz, starts, indices, values) # Set callback and run h.setCallback(user_interrupt_callback, None) h.startCallback(hscb.HighsCallbackType.kCallbackLogging) h.run() h.stopCallback(hscb.HighsCallbackType.kCallbackLogging) # Get solution num_var = h.getNumCol() solution = h.getSolution() basis = h.getBasis() info = h.getInfo() model_status = h.getModelStatus() print("Model status = ", h.modelStatusToString(model_status)) print("Optimal objective = ", info.objective_function_value) print("Iteration count = ", info.simplex_iteration_count) print( "Primal solution status = ", h.solutionStatusToString( info.primal_solution_status) ) print("Dual solution status = ", h.solutionStatusToString(info.dual_solution_status)) print("Basis validity = ", h.basisValidityToString(info.basis_validity)) print("Variables:") for icol in range(0, 5): print(icol, solution.col_value[icol], h.basisStatusToString(basis.col_status[icol])) print("...") for icol in range(num_var-2, num_var): print(icol, solution.col_value[icol], h.basisStatusToString(basis.col_status[icol])) print("computing IIS for lp-incompatible-bounds") """ LP has row0 and col2 with inconsistent bounds. When prioritising rows, row0 and its constituent columns (1, 2) should be found When prioritising columns, col2 and its constituent rows (0, 1) should be found """ # Define the LP lp = highspy.HighsLp() lp.num_col_ = 3 lp.num_row_ = 2 lp.col_cost_ = np.array([0, 0, 0], dtype=np.double) lp.col_lower_ = np.array([0, 0, 0], dtype=np.double) lp.col_upper_ = np.array([1, 1, -1], dtype=np.double) lp.row_lower_ = np.array([1, 0], dtype=np.double) lp.row_upper_ = np.array([0, 1], dtype=np.double) lp.a_matrix_.format_ = highspy.MatrixFormat.kRowwise lp.a_matrix_.start_ = np.array([0, 2, 4]) lp.a_matrix_.index_ = np.array([1, 2, 0, 2]) lp.a_matrix_.value_ = np.array([1, 1, 1, 1], dtype=np.double) h.clear() h.passModel(lp) h.run() assert h.getModelStatus() == highspy.HighsModelStatus.kInfeasible # Set IIS strategy to row priority and get IIS h.setOptionValue("iis_strategy", highspy.IisStrategy.kIisStrategyFromLpRowPriority) iis = highspy.HighsIis() assert h.getIis(iis) == highspy.HighsStatus.kOk assert len(iis.col_index) == 0 assert len(iis.row_index) == 1 assert iis.row_index[0] == 0 assert iis.row_bound[0] == highspy.IisBoundStatus.kIisBoundStatusBoxed # Set IIS strategy to column priority and get IIS h.setOptionValue("iis_strategy", highspy.IisStrategy.kIisStrategyFromLpColPriority) iis.invalidate() assert h.getIis(iis) == highspy.HighsStatus.kOk assert len(iis.col_index) == 1 assert len(iis.row_index) == 0 assert iis.col_index[0] == 2 assert iis.col_bound[0] == highspy.IisBoundStatus.kIisBoundStatusBoxed print("IIS computation completed successfully") print("computing feasibility relaxation") h.clear() inf = h.getInfinity() num_col = 2 num_row = 3 num_nz = 6 a_format = highspy.MatrixFormat.kColwise sense = highspy.ObjSense.kMinimize offset = 0 col_cost = np.array([1, -2], dtype=np.double) col_lower = np.array([5, -inf], dtype=np.double) col_upper = np.array([inf, inf], dtype=np.double) row_lower = np.array([2, -inf, -inf], dtype=np.double) row_upper = np.array([inf, 1, 20], dtype=np.double) a_start = np.array([0, 3]) a_index = np.array([0, 1, 2, 0, 1, 2]) a_value = np.array([-1, -3, 20, 21, 2, 1], dtype=np.double) integrality = np.array([highspy.HighsVarType.kInteger, highspy.HighsVarType.kInteger]) h.passModel( num_col, num_row, num_nz, a_format, sense, offset, col_cost, col_lower, col_upper, row_lower, row_upper, a_start, a_index, a_value, integrality ) assert h.feasibilityRelaxation(1, 1, 1) == highspy.HighsStatus.kOk info = h.getInfo() objective_function_value = info.objective_function_value solution = h.getSolution() assert abs(objective_function_value - 5) < 1e-6, f"Expected objective value 5, got {objective_function_value}" assert abs(solution.col_value[0] - 1) < 1e-6, f"Expected solution[0] = 1, got {solution.col_value[0]}" assert abs(solution.col_value[1] - 1) < 1e-6, f"Expected solution[1] = 1, got {solution.col_value[1]}" print("Feasibility Relaxation Test Passed") # Using infeasible LP from AMPL documentation h = highspy.Highs() lp = highspy.HighsLp() lp.num_col_ = 2 lp.num_row_ = 3 lp.col_cost_ = np.array([1, -2], dtype=np.double) lp.col_lower_ = np.array([5, -h.getInfinity()], dtype=np.double) lp.col_upper_ = np.array([h.getInfinity(), h.getInfinity()], dtype=np.double) lp.col_names_ = ["X", "Y"] lp.row_lower_ = np.array([2, -h.getInfinity(), -h.getInfinity()], dtype=np.double) lp.row_upper_ = np.array([h.getInfinity(), 1, 20], dtype=np.double) lp.row_names_ = ["R0", "R1", "R2"] lp.a_matrix_.start_ = np.array([0, 3, 6]) lp.a_matrix_.index_ = np.array([0, 1, 2, 0, 1, 2]) lp.a_matrix_.value_ = np.array([-1, -3, 20, 21, 2, 1], dtype=np.double) lp.integrality_ = np.array([highspy.HighsVarType.kInteger, highspy.HighsVarType.kInteger]) h.setOptionValue("output_flag", False) h.passModel(lp) # Vanilla feasibility relaxation print("Vanilla feasibility relaxation") h.feasibilityRelaxation(1, 1, 1) solution = h.getSolution() print(f"Solution: ({solution.col_value[0]}, {solution.col_value[1]})") print(f"Slacks: ({solution.row_value[0] - lp.row_lower_[0]}, " f"{lp.row_upper_[1] - solution.row_value[1]}, " f"{lp.row_upper_[2] - solution.row_value[2]})") # Respect all lower bounds print("\nRespect all lower bounds") h.feasibilityRelaxation(-1, 1, 1) solution = h.getSolution() print(f"Solution: ({solution.col_value[0]}, {solution.col_value[1]})") print(f"Slacks: ({solution.row_value[0] - lp.row_lower_[0]}, " f"{lp.row_upper_[1] - solution.row_value[1]}, " f"{lp.row_upper_[2] - solution.row_value[2]})") # Local penalties RHS {1, -1, 10} print("\nLocal penalties RHS {1, -1, 10}") local_rhs_penalty = np.array([1, -1, 10], dtype=np.double) h.feasibilityRelaxation(1, 1, 0, None, None, local_rhs_penalty) solution = h.getSolution() print(f"Solution: ({solution.col_value[0]}, {solution.col_value[1]})") print(f"Slacks: ({solution.row_value[0] - lp.row_lower_[0]}, " f"{lp.row_upper_[1] - solution.row_value[1]}, " f"{lp.row_upper_[2] - solution.row_value[2]})") # Local penalties RHS {10, 1, 1} print("\nLocal penalties RHS {10, 1, 1}") local_rhs_penalty = np.array([10, 1, 1], dtype=np.double) h.feasibilityRelaxation(1, 1, 0, None, None, local_rhs_penalty) solution = h.getSolution() print(f"Solution: ({solution.col_value[0]}, {solution.col_value[1]})") print(f"Slacks: ({solution.row_value[0] - lp.row_lower_[0]}, " f"{lp.row_upper_[1] - solution.row_value[1]}, " f"{lp.row_upper_[2] - solution.row_value[2]})") iis = highspy.HighsIis() assert h.getIis(iis) == highspy.HighsStatus.kOk print("\nIIS") print("row_index:", iis.row_index) print("row_bound:", iis.row_bound) print("col_index:", iis.col_index) print("col_bound:", iis.col_bound)