Skip to content

Commit

Permalink
Update HiGHS to version 1.6.0 (#35)
Browse files Browse the repository at this point in the history
* Update HiGHS to version 1.6.0

* Use HiGHS interface to check if model is linear or quadratic

* Use HighsModel.isMip to check if model is an LP or MILP

This fixes an issue in the earlier commit; the property "isLinear" means
"MILP but not LP".

* Remove unused parameter

* Remove "IsLinear" and "IsQuadratic" from solution object

The information is rather superfluous, as, on one hand, the user will
likely be aware which model they are solving, and on the other, since we
can include the types of all variables now, the information on whether
a model has integer variables can be determined from that.

Indeed, we update all tests to contain the type information as well.

* Update a test showcasing an error as the test now actually works

* Update a few tests that contain now-invalid formatting

* Remove information on linearity from a test

* Remove a few unused methods/types

* Destroy highs object as early as possible

* Add an example of an invalid input in tests
  • Loading branch information
fuglede authored Oct 10, 2023
1 parent 0f2694d commit e25a423
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 36 deletions.
2 changes: 1 addition & 1 deletion HiGHS
Submodule HiGHS updated 537 files
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,6 @@ Bounds
End`;

const EXPECTED_SOLUTION = {
IsLinear: true,
IsQuadratic: false,
Status: 'Optimal',
ObjectiveValue: 87.5,
Columns: {
Expand All @@ -44,6 +42,7 @@ const EXPECTED_SOLUTION = {
Status: 'BS',
Lower: 0,
Upper: 40,
Type: 'Continuous',
Primal: 17.5,
Dual: -0,
Name: 'x1'
Expand All @@ -53,6 +52,7 @@ const EXPECTED_SOLUTION = {
Status: 'BS',
Lower: 0,
Upper: Infinity,
Type: 'Continuous',
Primal: 1,
Dual: -0,
Name: 'x2'
Expand All @@ -62,6 +62,7 @@ const EXPECTED_SOLUTION = {
Status: 'BS',
Lower: 0,
Upper: Infinity,
Type: 'Continuous',
Primal: 16.5,
Dual: -0,
Name: 'x3'
Expand All @@ -71,6 +72,7 @@ const EXPECTED_SOLUTION = {
Status: 'LB',
Lower: 2,
Upper: 3,
Type: 'Continuous',
Primal: 2,
Dual: -8.75,
Name: 'x4'
Expand Down
8 changes: 0 additions & 8 deletions src/post.js
Original file line number Diff line number Diff line change
Expand Up @@ -165,18 +165,10 @@ function parseResult(lines, status) {

let headers = headersForNonEmptyColumns(lines[1], lines[2]);

// We identity whether the problem is a QP by the available headers: For infeasible
// problems, "Status", "Dual", and "Primal" are missing, for integer linear programs,
// "Status" and "Dual" are missing, and for QPs, only "Status" is missing
const isQuadratic = !headers.includes("Status") && headers.includes("Dual");
const isLinear = !headers.includes("Type") && !isQuadratic;

var result = {
"Status": /** @type {"Infeasible"} */(status),
"Columns": {},
"Rows": [],
"IsLinear": isLinear,
"IsQuadratic": isQuadratic,
"ObjectiveValue": NaN
};

Expand Down
77 changes: 53 additions & 24 deletions tests/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,14 @@ Bounds
End`;

const SOLUTION = {
IsLinear: true,
IsQuadratic: false,
Status: 'Optimal',
ObjectiveValue: 87.5,
Columns: {
x1: {
Index: 0,
Status: 'BS',
Lower: 0,
Type: 'Continuous',
Upper: 40,
Primal: 17.5,
Dual: -0,
Expand All @@ -33,6 +32,7 @@ const SOLUTION = {
Index: 1,
Status: 'BS',
Lower: 0,
Type: 'Continuous',
Upper: Infinity,
Primal: 1,
Dual: -0,
Expand All @@ -42,6 +42,7 @@ const SOLUTION = {
Index: 2,
Status: 'BS',
Lower: 0,
Type: 'Continuous',
Upper: Infinity,
Primal: 16.5,
Dual: -0,
Expand All @@ -51,6 +52,7 @@ const SOLUTION = {
Index: 3,
Status: 'LB',
Lower: 2,
Type: 'Continuous',
Upper: 3,
Primal: 2,
Dual: -8.75,
Expand Down Expand Up @@ -110,13 +112,31 @@ function test_options(Module) {
assert.deepStrictEqual(sol, SOLUTION);
}

/**
* @param {import("../types").Highs} Module
*/
function test_empty_model(Module) {
// Arguably, this example should not be considered valid at all, but
// HiGHS parses it as an empty model; see
// https://github.com/ERGO-Code/HiGHS/issues/1451
const sol = Module.solve("blah blah not a good file");
assert.deepStrictEqual(sol, {
Columns: {},
ObjectiveValue: 0,
Rows: [],
Status: 'Empty'
});
}

/**
* @param {import("../types").Highs} Module
*/
function test_invalid_model(Module) {
assert.throws(
(_) => Module.solve("blah blah not a good file"),
/Unable to read LP model/
(_) => Module.solve(`Minimize
] 2 [
End`),
/Unable to read LP model/
);
}

Expand All @@ -132,8 +152,6 @@ function test_integer_problem(Module) {
a
End`);
assert.deepStrictEqual(sol, {
IsLinear: false,
IsQuadratic: false,
Status: 'Optimal',
ObjectiveValue: 3.5,
Columns: {
Expand Down Expand Up @@ -168,8 +186,6 @@ function test_case_with_no_constraints(Module) {
2 <= x2 <= 3
End`);
assert.deepStrictEqual(sol, {
"IsLinear": true,
"IsQuadratic": false,
"Status": "Optimal",
"ObjectiveValue": 46,
"Columns": {
Expand All @@ -178,6 +194,7 @@ function test_case_with_no_constraints(Module) {
"Status": "UB",
"Lower": 0,
"Upper": 40,
"Type": "Continuous",
"Primal": 40,
"Dual": 1,
"Name": "x1"
Expand All @@ -186,6 +203,7 @@ function test_case_with_no_constraints(Module) {
"Index": 1,
"Status": "UB",
"Lower": 2,
"Type": "Continuous",
"Upper": 3,
"Primal": 3,
"Dual": 2,
Expand All @@ -208,14 +226,14 @@ Subject To
c1: a + b >= 10
End`);
assert.deepStrictEqual(sol, {
IsLinear: false,
IsQuadratic: true,
Status: 'Optimal',
ObjectiveValue: 60,
Columns: {
a: {
Index: 0,
Lower: 0,
Status: "BS",
Type: 'Continuous',
Upper: Infinity,
Primal: 10,
Dual: 0,
Expand All @@ -224,13 +242,15 @@ End`);
b: {
Index: 1,
Lower: 0,
Status: "LB",
Type: 'Continuous',
Upper: Infinity,
Primal: 0,
Dual: 10,
Name: 'b'
}
},
Rows: [{ Index: 0, Lower: 10, Upper: Infinity, Primal: 10, Dual: 11, Name: 'c1' }]
Rows: [{ Index: 0, Lower: 10, Upper: Infinity, Primal: 10, Dual: 11, Status: "LB", Name: 'c1' }]
});
}

Expand All @@ -253,17 +273,22 @@ function test_quadratic_program_not_positive_semidefinite(Module) {
* @param {import("../types").Highs} Module
*/
function test_infeasible(Module) {
const sol = Module.solve(`Maximize a subject to a >= 1 bounds a <= 0`);
const sol = Module.solve(`Maximize
a
subject to
a >= 1
bounds
a <= 0
End`);
assert.deepStrictEqual(sol, {
IsLinear: true,
IsQuadratic: false,
Status: 'Infeasible',
ObjectiveValue: 0,
Columns: {
a: {
Index: 0,
Lower: 0,
Upper: 0,
Type: 'Continuous',
Name: 'a'
}
},
Expand All @@ -288,8 +313,6 @@ General
a
end`);
assert.deepStrictEqual(sol, {
IsLinear: false,
IsQuadratic: false,
Status: 'Infeasible',
ObjectiveValue: Infinity,
Columns: {
Expand All @@ -312,16 +335,18 @@ end`);
* @param {import("../types").Highs} Module
*/
function test_unbounded(Module) {
const sol = Module.solve(`Maximize a subject to a >= 1`);
const sol = Module.solve(`Maximize a
subject to
a >= 1
end`);
assert.deepStrictEqual(sol, {
IsLinear: true,
IsQuadratic: false,
Status: 'Unbounded',
ObjectiveValue: 1,
Columns: {
a: {
Index: 0,
Lower: 0,
Type: 'Continuous',
Upper: Infinity,
Primal: 1,
Dual: -0,
Expand Down Expand Up @@ -349,32 +374,31 @@ Bounds
1.1 <= x2 <= 1
End`);
assert.deepStrictEqual(sol, {
IsLinear: true,
IsQuadratic: false,
Status: 'Infeasible',
ObjectiveValue: 0,
Columns: {
x0: {
Index: 1,
Lower: 0,
Name: 'x0',
Type: 'Continuous',
Upper: Infinity
},
x1: {
Index: 0,
Lower: 0,
Name: 'x1',
Type: 'Continuous',
Upper: 1
},
x2: {
Index: 2,
Lower: 1.1,
Name: 'x2',
Type: 'Continuous',
Upper: 1
}
},
IsLinear: true,
IsQuadratic: false,
Rows: [
{
Index: 0,
Expand All @@ -398,13 +422,18 @@ function test_big(Module) {
function test_many_solves(Module) {
// See https://github.com/lovasoa/highs-js/issues/10
for (let i = 0; i < 5000; i++) {
Module.solve(`Maximize a subject to a <= 1`);
Module.solve(`Maximize
a
subject to
a <= 1
end`);
}
}

async function test() {
const Module = await highs();
test_optimal(Module);
test_empty_model(Module);
test_invalid_model(Module);
test_options(Module);
test_integer_problem(Module);
Expand Down
1 change: 0 additions & 1 deletion types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,6 @@ type HighsSolution =
>;

type GenericHighsSolution<IsLinear extends boolean, ColType, RowType, Status extends HighsModelStatus = HighsModelStatus> = {
IsLinear: IsLinear,
Status: Status;
ObjectiveValue: number;
Columns: Record<string, ColType>;
Expand Down

0 comments on commit e25a423

Please sign in to comment.