1
0
This repository has been archived on 2025-03-06. You can view files and clone it, but cannot push or open issues or pull requests.

102 lines
2.9 KiB
Python

import contextlib
import json
import sys
from ctypes.util import find_library
import cffi
DEBUG = False
def debugprint(*args):
if DEBUG:
print(*args, file=sys.stderr, flush=True)
ffi = cffi.FFI()
ffi.cdef(
"""
struct _MZNInstance;
typedef struct _MZNInstance* MZNInstance;
void set_rnd_seed(int seed);
MZNInstance minizinc_instance_init(const char* mza_file, const char* data_file, const char* solver);
void minizinc_instance_destroy(MZNInstance);
void minizinc_add_call(MZNInstance, const char* call, ...);
void minizinc_set_solution(MZNInstance, int def, int sol);
void minizinc_output_dict(MZNInstance, bool);
void minizinc_print_hedge(MZNInstance);
void minizinc_set_limit(MZNInstance, int limit);
void minizinc_push_state(MZNInstance);
void minizinc_pop_state(MZNInstance);
const char* minizinc_solve(MZNInstance);
"""
)
# Set LD_LIBRARY_PATH (DYLD_LIBRARY_PATH on macOS) to the folder containing the mza library.
lib = ffi.dlopen("mza")
def set_rnd_seed(seed: int):
debugprint(f"set_rnd_seed({seed});")
lib.set_rnd_seed(seed)
class Instance:
def __init__(self, mza_file, data_file, solver):
debugprint(
f'MZNInstance inst = minizinc_instance_init("{mza_file}", "{data_file}", "{solver}");'
)
self._ptr = lib.minizinc_instance_init(
mza_file.encode(), data_file.encode(), solver.encode()
)
def __del__(self):
debugprint(f"minizinc_instance_destroy(inst);")
lib.minizinc_instance_destroy(self._ptr)
self._ptr = None
def output_dict(self, b: bool):
debugprint(f"minizinc_output_dict(inst, {int(b)});")
lib.minizinc_output_dict(self._ptr, b)
def set_incumbent(self, sol):
for k, v in sol.items():
debugprint(f"minizinc_set_solution(inst, {k}, {v});")
lib.minizinc_set_solution(self._ptr, int(k), v)
def set_limit(self, limit):
debugprint(f"minizinc_set_limit(inst, {limit});")
lib.minizinc_set_limit(self._ptr, limit)
def print(self):
debugprint(f"minizinc_print_hedge(inst);")
lib.minizinc_print_hedge(self._ptr)
@contextlib.contextmanager
def branch(self):
try:
debugprint(f"minizinc_push_state(inst);")
lib.minizinc_push_state(self._ptr)
yield self
finally:
debugprint(f"minizinc_pop_state(inst);")
lib.minizinc_pop_state(self._ptr)
def add_call(self, call: str, *args):
debugprint(
f"minizinc_add_call(inst, \"{call}\"{''.join([', '+ str(i) for i in args])});"
)
lib.minizinc_add_call(
self._ptr, call.encode(), *[ffi.cast("int", i) for i in args]
)
def solve(self):
debugprint(f"minizinc_solve(inst);")
res = ffi.string(lib.minizinc_solve(self._ptr))
tmp = json.loads(res)
return tmp["status"], tmp["solution"]