Source code for cpmpy.tools.xcsp3

#!/usr/bin/env python
#-*- coding:utf-8 -*-
##
## __init__.py
##
"""
    Set of utilities for working with XCSP3-formatted CP models.


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

    .. autosummary::
        :nosignatures:

        read_xcsp3

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

    .. autosummary::
        :nosignatures:

        _parse_xcsp3
        _load_xcsp3

    ==================
    List of submodules
    ==================

    .. autosummary::
        :nosignatures:

        parser_callbacks
        analyze
        benchmark
        xcsp3_cpmpy
        dataset
        globals
"""
from io import StringIO
import lzma
import os
import cpmpy as cp

# Special case for optional cpmpy dependencies
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from pycsp3.parser.xparser import CallbackerXCSP3, ParserXCSP3

from .dataset import XCSP3Dataset # for easier importing

def _parse_xcsp3(path: os.PathLike) -> "ParserXCSP3":
    """
    Parses an XCSP3 instance file (.xml) and returns a `ParserXCSP3` instance.
    
    Arguments:
        path: location of the XCSP3 instance to read (expects a .xml file).
    
    Returns:
        A parser object.
    """
    try:
        from pycsp3.parser.xparser import ParserXCSP3
    except ImportError as e:
        raise ImportError("The 'pycsp3' package is required to parse XCSP3 files. "
                          "Please install it with `pip install pycsp3`.") from e
    
    parser = ParserXCSP3(path)
    return parser

def _load_xcsp3(parser: "ParserXCSP3") -> cp.Model:
    """
    Takes in a `ParserXCSP3` instance and loads its captured model as a CPMpy model.

    Arguments:
        parser (ParserXCSP3): A parser object to load from.

    Returns:
        The XCSP3 instance loaded as a CPMpy model.
    """
    from .parser_callbacks import CallbacksCPMPy
    from pycsp3.parser.xparser import CallbackerXCSP3
    callbacks = CallbacksCPMPy()
    callbacks.force_exit = True
    callbacker = CallbackerXCSP3(parser, callbacks)
    callbacker.load_instance()
    model = callbacks.cpm_model
   
    return model


[docs] def read_xcsp3(path: os.PathLike) -> cp.Model: """ Reads in an XCSP3 instance (.xml or .xml.lzma) and returns its matching CPMpy model. Arguments: path: location of the XCSP3 instance to read (expects a .xml or .xml.lzma file). Returns: The XCSP3 instance loaded as a CPMpy model. """ # Decompress on the fly if still in .lzma format if str(path).endswith(".lzma"): path = decompress_lzma(path) # Parse and create CPMpy model parser = _parse_xcsp3(path) model = _load_xcsp3(parser) return model
[docs] def decompress_lzma(path: os.PathLike) -> StringIO: """ Decompresses a .lzma file. Arguments: path: Location of .lzma file Returns: Memory-mapped decompressed file """ # Decompress the XZ file with lzma.open(path, 'rt', encoding='utf-8') as f: return StringIO(f.read()) # read to memory-mapped file