Source code for cpmpy.tools.explain.utils

#!/usr/bin/env python
#-*- coding:utf-8 -*-
##
## utils.py
##
"""
    Utilities for explanation techniques

    =================
    List of functions
    =================

    .. autosummary::
        :nosignatures:

        make_assump_model
"""

import copy
import cpmpy as cp
from cpmpy.expressions.utils import is_any_list
from cpmpy.expressions.variables import NegBoolView
from cpmpy.transformations.normalize import toplevel_list

[docs] def make_assump_model(soft, hard=[], name=None): """ Construct implied version of all soft constraints. Can be used to extract cores (see :func:`tools.mus() <cpmpy.tools.explain.mus.mus>`). Provide name for assumption variables with `name` param. """ # ensure toplevel list soft2 = toplevel_list(soft, merge_and=False) # make assumption variables assump = cp.boolvar(shape=(len(soft2),), name=name) # hard + implied soft constraints hard = toplevel_list(hard) model = cp.Model(hard + [assump.implies(soft2)]) # each assumption variable implies a candidate return model, soft2, assump
[docs] def replace_cons_with_assump(cpm_cons, assump_map): """ Replace soft constraints with assumption variables in a Boolean CPMpy expression. """ if is_any_list(cpm_cons): return [replace_cons_with_assump(c, assump_map) for c in cpm_cons] if cpm_cons in assump_map: return assump_map[cpm_cons] elif hasattr(cpm_cons, "args"): cpm_cons = copy.copy(cpm_cons) cpm_cons.update_args(replace_cons_with_assump(cpm_cons.args, assump_map)) return cpm_cons elif isinstance(cpm_cons, NegBoolView): return ~replace_cons_with_assump(cpm_cons._bv, assump_map) return cpm_cons
[docs] class OCUSException(Exception): pass