HiGHS icon indicating copy to clipboard operation
HiGHS copied to clipboard

Highs_getIis segfaults

Open odow opened this issue 1 month ago • 6 comments

Am I calling something wrong?

julia> using HiGHS

julia> unsafe_string(Highs_version())
"1.12.0"

julia> highs = Highs_create()
Ptr{Nothing}(0x000000013f53b800)

julia> Highs_readModel(highs, "/Users/odow/git/jump-dev/MathOptIIS/test/small.lp.gz")
Running HiGHS 1.12.0 (git hash: 755a8e027): Copyright (c) 2025 HiGHS under MIT licence terms
0

julia> m, n = Highs_getNumCol(highs), Highs_getNumRow(highs)
(396, 936)

julia> iis_num_col, iis_num_row = Ref{Cint}(m), Ref{Cint}(n)
(Base.RefValue{Int32}(396), Base.RefValue{Int32}(936))

julia> col_index, col_bound, col_status = zeros(Cint, m), zeros(Cint, m), zeros(Cint, m)
(Int32[0, 0, 0, 0, 0, 0, 0, 0, 0, 0  …  0, 0, 0, 0, 0, 0, 0, 0, 0, 0], Int32[0, 0, 0, 0, 0, 0, 0, 0, 0, 0  …  0, 0, 0, 0, 0, 0, 0, 0, 0, 0], Int32[0, 0, 0, 0, 0, 0, 0, 0, 0, 0  …  0, 0, 0, 0, 0, 0, 0, 0, 0, 0])

julia> row_index, row_bound, row_status = zeros(Cint, n), zeros(Cint, n), zeros(Cint, n)
(Int32[0, 0, 0, 0, 0, 0, 0, 0, 0, 0  …  0, 0, 0, 0, 0, 0, 0, 0, 0, 0], Int32[0, 0, 0, 0, 0, 0, 0, 0, 0, 0  …  0, 0, 0, 0, 0, 0, 0, 0, 0, 0], Int32[0, 0, 0, 0, 0, 0, 0, 0, 0, 0  …  0, 0, 0, 0, 0, 0, 0, 0, 0, 0])

julia> Highs_getIis(
           highs,
           iis_num_col,
           iis_num_row,
           col_index,
           row_index,
           col_bound,
           row_bound,
           col_status,
           row_status,
       )

[9037] signal 11 (2): Segmentation fault: 11
in expression starting at REPL[18]:1
Highs_getIis at /Users/odow/.julia/artifacts/927a651cf0aaaed9262d8ed83c6f9941840a837a/lib/libhighs.1.12.dylib (unknown line)

small.lp.gz

Same with the C code:

#include <stdlib.h>
#include "interfaces/highs_c_api.h"

int main() {
    void* highs = Highs_create();
    int ret = Highs_readModel(highs, "small.lp.gz");
    HighsInt m = Highs_getNumCol(highs);
    HighsInt n = Highs_getNumRow(highs);
    HighsInt iis_num_col = 0;
    HighsInt iis_num_row = 0;
    HighsInt* col_index = (HighsInt*)malloc(sizeof(HighsInt) * m);
    HighsInt* row_index = (HighsInt*)malloc(sizeof(HighsInt) * n);
    HighsInt* col_bound = (HighsInt*)malloc(sizeof(HighsInt) * m);
    HighsInt* row_bound = (HighsInt*)malloc(sizeof(HighsInt) * n);
    HighsInt* col_status = (HighsInt*)malloc(sizeof(HighsInt) * m);
    HighsInt* row_status = (HighsInt*)malloc(sizeof(HighsInt) * n);
    ret = Highs_getIis(
        highs,
        &iis_num_col,
        &iis_num_row,
        col_index,
        row_index,
        col_bound,
        row_bound,
        col_status,
        row_status);
    Highs_destroy(highs);
    return 0;
}

odow avatar Nov 04 '25 02:11 odow

Am I calling something wrong?

No, when an IIS isn't found the values of col_status and row_status from the C++ class HighsIis must be set to kIisStatusMaybeInConflict - unless the system is known to be feasible, in which case they must be set to kIisStatusNotInConflict

jajhall avatar Nov 04 '25 10:11 jajhall

@odow, I've also tested the fix on your original C code

Closed by #2636

jajhall avatar Nov 04 '25 17:11 jajhall

The problem is infeasible though?

julia> highs = Highs_create()
Ptr{Nothing}(0x00000001239a4800)

julia> Highs_readModel(highs, "/Users/odow/git/jump-dev/MathOptIIS/test/small.lp.gz")
Running HiGHS 1.12.0 (git hash: 755a8e027): Copyright (c) 2025 HiGHS under MIT licence terms
0

julia> Highs_run(highs)
LP small has 936 rows; 396 cols; 1656 nonzeros
Coefficient ranges:
  Matrix  [1e+00, 3e+02]
  Cost    [4e+00, 9e+00]
  Bound   [0e+00, 0e+00]
  RHS     [8e+02, 2e+03]
Presolving model
216 rows, 252 cols, 648 nonzeros  0s
Problem status detected on presolve: Infeasible
Model name          : small
Model status        : Infeasible
Objective value     :  0.0000000000e+00
HiGHS run time      :          0.00
0

odow avatar Nov 04 '25 18:11 odow

The problem is infeasible though?

Doesn't actually matter with the default value of iis_strategy since no IIS is found - as it wouldn't be for a feasible problem.

jajhall avatar Nov 04 '25 19:11 jajhall

Corrected IIS LP generation and checking when incumbent LP is stored rowwise: #2638

jajhall avatar Nov 05 '25 10:11 jajhall

@jajhall Replying in this issue despite it being closed as I am also running into a segfault related to getIis(), however I am not sure if it is related to the original issue and the PRs you have linked.

I am playing around with the current IIS implementation to see what information I can get out of it to see whether it will be useful for my project or not, but, unfortunately, have not been unable to get past the segfault I describe below.

Unfortunately, I don't have the capacity to debug this more than what I have listed below at the moment. I am not sure if the segfault is triggered by an incorrect configuration or LP specification on my end as I am not very familiar with the HiGHs project. At a glance, it looks as if the IIS methodology gets stuck in an infinite loop of trying to solve variations of the LP, but this is just a guess on my end.

If this is unexpected behaviour from the solver, I hope this comment might bring some value in explaining the behaviour. I wish I could contribute more at this moment. Please, don't hesitate to let me know if you decide to look into this and need more information, happy to assist as best as I can.

I have compiled HiGHs on a 2022 M2 MacBook Air on MacOS Sequoia 15.3.2 using preinstalled clang++:

Apple clang version 16.0.0 (clang-1600.0.26.6)
Target: arm64-apple-darwin24.3.0
Thread model: posix

I have attached two logs files (see further down) from my runs using this lp specification corresponding to a basic network flow problem (also illustrated in the picture below):

max
    a_sink + b_sink
st
    src_a = 10
    src_b - 0.5 a_b = 0

    src_a - a_b - a_sink = 0
    src_b + a_b - b_sink = 0

    a_sink + b_sink - src_a - src_b = 0

    \\\ a_sink + b_sink >= 20 \\\ segfault also happens with these infeasible constraints rather than the bounds
bounds
    a_sink >= 10 \\\ infeasible with next bound
    b_sink >= 10 \\\ infeasible with previous bound
end

I am using the following options file:

log_file = ./lp/logs/highs.log
iis_strategy = 1 // <-- segfault happens with both strategy=1 and strategy=2, but not with strategy=0
write_iis_model_file = ./lp/output/iis.lp
solution_file = ./lp/output/solution.txt

The first log is the standard HiGHs log:

highs.log

The second log is "expanded" in the sense that I have changed output_flag from false to true on line 942 in HighsIis::lpOk in HighsIis.cpp in an attempt to figure out what might be triggering the segfault. At the end of this log file, we see that the model name has 324 "_IIS" appended to it and 2 "_elastic". I have not dug deeper into what the IIS methodology looks like, but I would guess it runs the model 324 (326?) more times which sounds like a lot for a model with 5 constraints and 2 bounds. Maybe something related to this triggers the segfault?

highs.expanded.log

rikardfranksson avatar Nov 20 '25 11:11 rikardfranksson