Skip to content

Native access violation in SCIP 10.0.1 on Windows when optimizing a quadratic model #1238

Description

@dave-cz

Describe the bug

On one Windows 10 IoT machine, PySCIPOpt terminates the Python process with a
native access violation during the first Model.optimize() call for the
standalone quadratic model below. No Python exception is raised.

Windows Error Reporting identifies the faulting module as the libscip DLL
bundled with PySCIPOpt:

Faulting application: python.exe
Faulting module: libscip-1a4d5a21deba20278cffa088924e6323.dll
Exception code: 0xc0000005
Fault offset: 0x0000000000a047bf
Event ID: 1000

The same script completes on another Windows machine with the same reported
Python, PySCIPOpt, and SCIP versions.

To Reproduce

  1. Install PySCIPOpt 6.1.0 for Python 3.10 on Windows using pip.

  2. Save the following script as
    tuning_scip_quadratic_crash_minimal.py.

  3. Run:

    python tuning_scip_quadratic_crash_minimal.py
import faulthandler
import math

from pyscipopt import Model, quicksum


STEPS = 120
CAPACITY = 1306.8
PERIOD_HOURS = 15 / 3600


faulthandler.enable(all_threads=True)

model = Model()
model.hideOutput()
model.setIntParam("lp/threads", 1)
model.setBoolParam("nlp/disable", True)
model.setRealParam("limits/time", 5.0)
model.setRealParam("limits/gap", 0.001)
model.setRealParam("limits/absgap", 10.0)

charge = [
    model.addVar(lb=-300.0, ub=300.0, name=f"charge_{i}")
    for i in range(STEPS)
]
purchase = [
    model.addVar(lb=0.0, ub=200.0, name=f"purchase_{i}")
    for i in range(STEPS)
]
sell = [
    model.addVar(lb=0.0, ub=400.0, name=f"sell_{i}")
    for i in range(STEPS)
]
soc = [
    model.addVar(lb=130.68, ub=CAPACITY, name=f"soc_{i}")
    for i in range(STEPS + 1)
]
high_penalty = [
    model.addVar(lb=0.0, ub=100000.0, name=f"high_penalty_{i}")
    for i in range(STEPS + 1)
]
cost = [
    model.addVar(lb=-1.0e7, ub=1.0e7, name=f"cost_{i}")
    for i in range(STEPS)
]

model.addCons(soc[0] == 0.60 * CAPACITY)
for i in range(STEPS):
    phase = 2.0 * math.pi * i / STEPS
    load = 140.0 + 30.0 * math.sin(phase)
    pv = max(0.0, 180.0 * math.sin(phase))

    model.addCons(purchase[i] - sell[i] - charge[i] == load - pv)
    model.addCons(soc[i + 1] == soc[i] + PERIOD_HOURS * charge[i])
    model.addCons(
        high_penalty[i + 1] >= soc[i + 1] - 0.98 * CAPACITY
    )
    model.addCons(
        cost[i]
        == 5.0 * PERIOD_HOURS * purchase[i]
        - 2.0 * PERIOD_HOURS * sell[i]
        + 0.1 * high_penalty[i + 1]
        + 0.0001 * charge[i] * charge[i]
        + 0.0001 * purchase[i] * purchase[i]
        + 0.0001 * sell[i] * sell[i]
    )

model.setObjective(quicksum(cost), "minimize")
model.optimize()

objective = model.getObjVal() if model.getNSols() else None
print(f"status={model.getStatus()} objective={objective}")

Actual console output on the affected machine:

Windows fatal exception: access violation

Current thread (most recent call first):
  File "tuning_scip_quadratic_crash_minimal.py", line 73 in main
  File "tuning_scip_quadratic_crash_minimal.py", line 80 in <module>

The following isolation results were obtained on the affected machine:

Variant Result
Full quadratic model, main thread, lp/threads=1 Access violation
Full quadratic model, main thread, lp/threads=8 Access violation
Full quadratic model, ThreadPoolExecutor, lp/threads=1 Access violation
Full quadratic model, ThreadPoolExecutor, lp/threads=8 Access violation
Full quadratic model with nlp/disable=True Access violation
Full quadratic model with NLP enabled Access violation
Full quadratic model reformulated as cost >= quadratic expression Access violation
Same model with all quadratic terms removed Completes successfully
Two-variable model with one quadratic equality Completes successfully

The failure therefore does not require ThreadPoolExecutor, thread
migration, multiple solves, multiple LP threads, the NLP relaxation, or
quadratic equality constraints. The current reproducer requires the larger
family of quadratic expressions; changing them to convex epigraph
inequalities does not prevent the failure.

Expected behavior

Model.optimize() should return normally with a SCIP status, or report a
solver error without terminating the Python process.

On the unaffected Windows machine, the script returns:

status=gaplimit objective=109.35277613193799

Screenshots

No screenshot is required to reproduce the problem. The relevant Windows
Event 1000 fields are included above. A Windows "About" screenshot confirms
the OS version and build listed below. A minidump can be provided privately if
it is useful.

System

  • OS: Windows 10 Enterprise LTSC, version 1809, build 17763.3287, x86-64
  • CPU: Intel Atom Processor E3950 @ 1.60 GHz, 4 cores / 4 logical
    processors, x86-64 (Win32_Processor.Architecture = 9)
  • Python: 3.10.11
  • PySCIPOpt: 6.1.0
  • SCIP: 10.0.1
  • SoPlex: 8.0.1
  • Installation: pip-installed Windows binary wheel from PyPI
  • Faulting DLL:
    pyscipopt.libs\libscip-1a4d5a21deba20278cffa088924e6323.dll

Version probe:

Python=3.10.11 PySCIPOpt=6.1.0 SCIP=10.0.1
SCIP version 10.0.1
LP solver: SoPlex 8.0.1

SHA-256 hashes of the installed PySCIPOpt extension and bundled DLLs:

81C4BF11E65768928AA141F81054688FA492A570B20D7532DAA88902BD7D72B2  coinmumps-3-179ba8bf43f95bbadacde7fbc058c4df.dll
E3ACF4FF81319F2174E836F37F2BF7990F2810E25E060B90FF026DB255EBFEB1  ipopt-3-9948be002064791f542b117490eb329a.dll
FF9842AA45EFF7B6C19AB03FB529C37F7343648EE95066C2F995EE0FCEF9904A  libifcoremd-0f996d3c2ff10fe7dd667dc6228dd4f0.dll
999E2141F7E6C20E7B5FC78B0E0A47AAF40E219F611E77D2423BBD4F0AAABD7E  libiomp5md-999e2141f7e6c20e7b5fc78b0e0a47aa.dll
D69808FFF3D92CAB6246B30C6FE90BD3F521A095E2D8BB9417F83F6FBDE574D7  libmmd-d69808fff3d92cab6246b30c6fe90bd3.dll
402C3BDCB3E2781791D205CB1B333A965C2B69699BF6A355656407C70E3157A8  libscip-1a4d5a21deba20278cffa088924e6323.dll
A4C2229BDC2A2A630ACDC095B4D86008E5C3E3BC7773174354F3DA4F5BEB9CDE  msvcp140-a4c2229bdc2a2a630acdc095b4d86008.dll
DF5493FC29B0D98F8C0B06B852908B2BACB7130C5E634B4A9A53B97C6C970F27  svml_dispmd-df5493fc29b0d98f8c0b06b852908b2b.dll
240CCB13E3CF5F18A5C04A7DF0F4B40A6F2795DCFB24B54093F2F9E2A7C5E192  scip.cp310-win_amd64.pyd

Additional context

This was originally observed in a production optimization application. Its
older minidumps consistently show a write access violation in the same named
libscip DLL at module offset 0xA037D0. The standalone reproducer faults at
0xA047BF, which is 0xFEF (4079 bytes) away. These are module-relative
offsets, so they identify the same native component but not necessarily the
same instruction or internal function.

The standalone reproducer contains no application imports, scheduler, shared
state, or I/O. Because it succeeds on another Windows machine with the same
reported versions, comparing the hashes above with a working installation may
help distinguish a binary-build issue from an OS-specific runtime issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions