From ac753a4f064320e17eda5ce8fe3d50c0b8686d33 Mon Sep 17 00:00:00 2001 From: Matthieu Monsch Date: Sat, 11 Nov 2023 17:41:55 -0800 Subject: [PATCH] Add addon callback support --- packages/highs-addon/index.d.ts | 32 +++++++++++++++++ packages/highs-addon/src/solver.cc | 43 +++++++++++++++++++++++ packages/highs-addon/src/solver.h | 4 +++ packages/highs-solver/test/solver.test.ts | 7 ++++ 4 files changed, 86 insertions(+) diff --git a/packages/highs-addon/index.d.ts b/packages/highs-addon/index.d.ts index f2f176f..c57eef2 100644 --- a/packages/highs-addon/index.d.ts +++ b/packages/highs-addon/index.d.ts @@ -22,6 +22,10 @@ export declare class Solver { weights: Matrix ): void; + setCallback(cb: Callback): void; + startCallback(tp: CallbackType): void; + stopCallback(tp: CallbackType): void; + run(cb: (err: Error) => void): void; getModelStatus(): ModelStatus; getInfo(): Info; @@ -168,3 +172,31 @@ export type SolutionStatus = number; // https://github.com/ERGO-Code/HiGHS/blob/master/src/lp_data/HConst.h#L127 export type SolutionStyle = number; + +// https://ergo-code.github.io/HiGHS/stable/callbacks/ +export type Callback = (inputs: CallbackInputs) => CallbackOutputs; + +// https://github.com/ERGO-Code/HiGHS/blob/master/src/lp_data/HConst.h#L209 +export type CallbackType = number; + +export interface CallbackInputs { + // Simplex interrupt + readonly simplex_iteration_count?: number; + // IPM interrupt + readonly ipm_iteration_count?: number; + // MIP improving solution + readonly mip_solution?: unknown; + // MIP interrupt + readonly running_time?: number; + readonly objective_function_value?: number; + readonly num_nodes?: number; + readonly primal_bound?: number; + readonly dual_bound?: number; + readonly mip_gap?: number; + // Unknown + readonly [name: string]: unknown; +} + +export interface CallbackOutputs { + readonly user_interrupt: number; +} diff --git a/packages/highs-addon/src/solver.cc b/packages/highs-addon/src/solver.cc index dbe8c9c..121c17b 100644 --- a/packages/highs-addon/src/solver.cc +++ b/packages/highs-addon/src/solver.cc @@ -428,6 +428,49 @@ Napi::Value Solver::GetInfo(const Napi::CallbackInfo& info) { return obj; } +// Callbacks + +void Solver::SetCallback(const Napi::CallbackInfo& info) { + // TODO. Need to figure out how best to call JS from worker. +} + +int ToCallbackType(const Napi::Env& env, const Napi::Value& val) { + int tp = val.As().Int32Value(); + if (tp < 0 || tp > HighsCallbackType::kNumCallbackType) { + ThrowError(env, "Unexpected callback type"); + return -1; + } + return tp; +} + +void Solver::StartCallback(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + int length = info.Length(); + if (length != 1 || !info[0].IsNumber()) { + ThrowTypeError(env, "Expected 1 argument [number]"); + return; + } + int tp = ToCallbackType(env, info[0]); + if (tp < 0) { + return; + } + this->highs_->startCallback(tp); +} + +void Solver::StopCallback(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + int length = info.Length(); + if (length != 1 || !info[0].IsNumber()) { + ThrowTypeError(env, "Expected 1 argument [number]"); + return; + } + int tp = ToCallbackType(env, info[0]); + if (tp < 0) { + return; + } + this->highs_->stopCallback(tp); +} + // Solutions Napi::Value ToFloat64Array(const Napi::Env& env, const std::vector& vec) { diff --git a/packages/highs-addon/src/solver.h b/packages/highs-addon/src/solver.h index d0497cd..62c2b59 100644 --- a/packages/highs-addon/src/solver.h +++ b/packages/highs-addon/src/solver.h @@ -21,6 +21,10 @@ class Solver : public Napi::ObjectWrap { void ChangeColsCost(const Napi::CallbackInfo& info); void AddRows(const Napi::CallbackInfo& info); + void SetCallback(const Napi::CallbackInfo& info); + void StartCallback(const Napi::CallbackInfo& info); + void StopCallback(const Napi::CallbackInfo& info); + void Run(const Napi::CallbackInfo& info); Napi::Value GetModelStatus(const Napi::CallbackInfo& info); Napi::Value GetInfo(const Napi::CallbackInfo& info); diff --git a/packages/highs-solver/test/solver.test.ts b/packages/highs-solver/test/solver.test.ts index 48d9bc4..287d93f 100644 --- a/packages/highs-solver/test/solver.test.ts +++ b/packages/highs-solver/test/solver.test.ts @@ -191,4 +191,11 @@ describe('solver', () => { }); } }); + + describe('handles callbacks', () => { + test('simple', async () => { + const solver = sut.Solver.create(); + await solver.setModelFromFile(loader.localUrl('simple.lp')); + }); + }); });