#include "interfaces/highs_c_api.h" #include #include #include // gcc call_highs_from_c.c -o highstest -I install_folder/include/ -L install_folder/lib/ -lhighs void minimal_api() { // This illustrates the use of Highs_lpCall, the simple C interface to // HiGHS. It's designed to solve the general LP problem // // Min c^Tx + d subject to L <= Ax <= U; l <= x <= u // // where A is a matrix with m rows and n columns // // The scalar n is num_col // The scalar m is num_row // // The vector c is col_cost // The scalar d is offset // The vector l is col_lower // The vector u is col_upper // The vector L is row_lower // The vector U is row_upper // // The matrix A is represented in packed vector form, either // row-wise or column-wise: only its nonzeros are stored // // * The number of nonzeros in A is num_nz // // * The indices of the nonnzeros in the vectors of A are stored in a_index // // * The values of the nonnzeros in the vectors of A are stored in a_value // // * The position in a_index/a_value of the index/value of the first // nonzero in each vector is stored in a_start // // Note that a_start[0] must be zero // // After a successful call to Highs_lpCall, the primal and dual // solution, and the simplex basis are returned as follows // // The vector x is col_value // The vector Ax is row_value // The vector of dual values for the variables x is col_dual // The vector of dual values for the variables Ax is row_dual // The basic/nonbasic status of the variables x is col_basis_status // The basic/nonbasic status of the variables Ax is row_basis_status // // The status of the solution obtained is model_status // // The use of Highs_lpCall is illustrated for the LP // // Min f = x_0 + x_1 + 3 // s.t. x_1 <= 7 // 5 <= x_0 + 2x_1 <= 15 // 6 <= 3x_0 + 2x_1 // 0 <= x_0 <= 4; 1 <= x_1 // // Although the first constraint could be expressed as an upper // bound on x_1, it serves to illustrate a non-trivial packed // column-wise matrix. // const int num_col = 2; const int num_row = 3; const int num_nz = 5; // Define the optimization sense and objective offset int sense = kHighsObjSenseMinimize; const double offset = 3; // Define the column costs, lower bounds and upper bounds const double col_cost[2] = {1.0, 1.0}; const double col_lower[2] = {0.0, 1.0}; const double col_upper[2] = {4.0, 1.0e30}; // Define the row lower bounds and upper bounds const double row_lower[3] = {-1.0e30, 5.0, 6.0}; const double row_upper[3] = {7.0, 15.0, 1.0e30}; // Define the constraint matrix column-wise const int a_format = 1; const int a_start[2] = {0, 2}; const int a_index[5] = {1, 2, 0, 1, 2}; const double a_value[5] = {1.0, 3.0, 1.0, 2.0, 2.0}; double objective_value; double* col_value = (double*)malloc(sizeof(double) * num_col); double* col_dual = (double*)malloc(sizeof(double) * num_col); double* row_value = (double*)malloc(sizeof(double) * num_row); double* row_dual = (double*)malloc(sizeof(double) * num_row); int* col_basis_status = (int*)malloc(sizeof(int) * num_col); int* row_basis_status = (int*)malloc(sizeof(int) * num_row); int model_status; int run_status; run_status = Highs_lpCall(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, col_value, col_dual, row_value, row_dual, col_basis_status, row_basis_status, &model_status); // The run must be successful, and the model status optimal assert(run_status == kHighsStatusOk); assert(model_status == kHighsModelStatusOptimal); printf("\nRun status = %d; Model status = %d\n", run_status, model_status); objective_value = offset; // Report the column primal and dual values, and basis status for (int i = 0; i < num_col; i++) { printf("Col%d = %lf; dual = %lf; status = %d\n", i, col_value[i], col_dual[i], col_basis_status[i]); objective_value += col_value[i]*col_cost[i]; } // Report the row primal and dual values, and basis status for (int i = 0; i < num_row; i++) { printf("Row%d = %lf; dual = %lf; status = %d\n", i, row_value[i], row_dual[i], row_basis_status[i]); } printf("Optimal objective value = %g\n", objective_value); // Switch the sense to maximization and solve the LP again sense = kHighsObjSenseMaximize; run_status = Highs_lpCall(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, col_value, col_dual, row_value, row_dual, col_basis_status, row_basis_status, &model_status); // The run must be successful, and the model status optimal assert(run_status == kHighsStatusOk); assert(model_status == kHighsModelStatusOptimal); printf("\nRun status = %d; Model status = %d\n", run_status, model_status); // Compute the objective value objective_value = offset; for (int i = 0; i < num_col; i++) objective_value += col_value[i]*col_cost[i]; // Report the column primal and dual values, and basis status for (int i = 0; i < num_col; i++) { printf("Col%d = %lf; dual = %lf; status = %d\n", i, col_value[i], col_dual[i], col_basis_status[i]); } // Report the row primal and dual values, and basis status for (int i = 0; i < num_row; i++) { printf("Row%d = %lf; dual = %lf; status = %d\n", i, row_value[i], row_dual[i], row_basis_status[i]); } printf("Optimal objective value = %g\n", objective_value); // // Indicate that the optimal solution for both columns must be // integer valued and solve the model as a MIP int integrality[2] = {1, 1}; run_status = Highs_mipCall(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, col_value, row_value, &model_status); // The run must be successful, and the model status optimal assert(run_status == kHighsStatusOk); assert(model_status == kHighsModelStatusOptimal); printf("\nRun status = %d; Model status = %d\n", run_status, model_status); // Compute the objective value objective_value = offset; for (int i = 0; i < num_col; i++) objective_value += col_value[i]*col_cost[i]; // Report the column primal values for (int i = 0; i < num_col; i++) { printf("Col%d = %lf\n", i, col_value[i]); } // Report the row primal values for (int i = 0; i < num_row; i++) { printf("Row%d = %lf\n", i, row_value[i]); } printf("Optimal objective value = %g\n", objective_value); free(col_value); free(col_dual); free(row_value); free(row_dual); free(col_basis_status); free(row_basis_status); } void minimal_api_qp() { // Illustrate the solution of a QP // // minimize -x_2 + (1/2)(2x_1^2 - 2x_1x_3 + 0.2x_2^2 + 2x_3^2) // // subject to x_1 + x_2 + x_3 >= 1; x>=0 const int num_col = 3; const int num_row = 1; const int num_nz = 3; // Define the optimization sense and objective offset int sense = kHighsObjSenseMinimize; const double offset = 0; // Define the column costs, lower bounds and upper bounds const double col_cost[3] = {0.0, -1.0, 0.0}; const double col_lower[3] = {0.0, 0.0, 0.0}; const double col_upper[3] = {1.0e30, 1.0e30, 1.0e30}; // Define the row lower bounds and upper bounds const double row_lower[1] = {1}; const double row_upper[1] = {1.0e30}; // Define the constraint matrix row-wise const int a_format = kHighsMatrixFormatRowwise; const int a_start[2] = {0, 3}; const int a_index[3] = {0, 1, 2}; const double a_value[3] = {1.0, 1.0, 1.0}; const int q_format = kHighsHessianFormatTriangular; const int q_num_nz = 5; const int q_start[3] = {0, 2, 3}; const int q_index[5] = {0, 2, 1, 0, 2}; const double q_value[5] = {2.0, -1.0, 0.2, -1.0, 2.0}; double objective_value; double* col_value = (double*)malloc(sizeof(double) * num_col); double* col_dual = (double*)malloc(sizeof(double) * num_col); double* row_value = (double*)malloc(sizeof(double) * num_row); double* row_dual = (double*)malloc(sizeof(double) * num_row); int* col_basis_status = (int*)malloc(sizeof(int) * num_col); int* row_basis_status = (int*)malloc(sizeof(int) * num_row); int model_status; int run_status; run_status = Highs_qpCall(num_col, num_row, num_nz, q_num_nz, a_format, q_format, sense, offset, col_cost, col_lower, col_upper, row_lower, row_upper, a_start, a_index, a_value, q_start, q_index, q_value, col_value, col_dual, row_value, row_dual, col_basis_status, row_basis_status, &model_status); // The run must be successful, and the model status optimal assert(run_status == kHighsStatusOk); assert(model_status == kHighsModelStatusOptimal); printf("\nRun status = %d; Model status = %d\n", run_status, model_status); // Compute the objective value objective_value = offset; for (int i = 0; i < num_col; i++) objective_value += col_value[i]*col_cost[i]; for (int i = 0; i < num_col; i++) { int from_el = q_start[i]; int to_el; if (i+1