From 06c10f7ebf5df868d7e9c2e2d417e5c0396e24ca Mon Sep 17 00:00:00 2001 From: Roland Kaminski Date: Thu, 15 Feb 2024 22:03:16 +0100 Subject: [PATCH] add python doc for 5.7 --- clingo.md | 1 + clingo/python-api/5.7/clingo/application.html | 1184 +++ clingo/python-api/5.7/clingo/ast.html | 6458 +++++++++++++++++ clingo/python-api/5.7/clingo/backend.html | 3427 +++++++++ .../python-api/5.7/clingo/configuration.html | 585 ++ clingo/python-api/5.7/clingo/control.html | 3055 ++++++++ clingo/python-api/5.7/clingo/core.html | 430 ++ clingo/python-api/5.7/clingo/index.html | 340 + clingo/python-api/5.7/clingo/propagator.html | 3549 +++++++++ clingo/python-api/5.7/clingo/script.html | 705 ++ clingo/python-api/5.7/clingo/solving.html | 2143 ++++++ clingo/python-api/5.7/clingo/statistics.html | 989 +++ clingo/python-api/5.7/clingo/symbol.html | 1028 +++ .../python-api/5.7/clingo/symbolic_atoms.html | 704 ++ clingo/python-api/5.7/clingo/theory.html | 1400 ++++ .../python-api/5.7/clingo/theory_atoms.html | 1029 +++ clingo/python-api/5.7/clingo/util.html | 358 + clingo/python-api/5.7/clingox/ast.html | 3401 +++++++++ clingo/python-api/5.7/clingox/backend.html | 1101 +++ clingo/python-api/5.7/clingox/index.html | 111 + clingo/python-api/5.7/clingox/pprint.html | 640 ++ clingo/python-api/5.7/clingox/program.html | 2890 ++++++++ clingo/python-api/5.7/clingox/reify.html | 1967 +++++ clingo/python-api/5.7/clingox/solving.html | 198 + .../python-api/5.7/clingox/testing/ast.html | 293 + .../python-api/5.7/clingox/testing/index.html | 78 + clingo/python-api/5.7/clingox/theory.html | 825 +++ clingo/python-api/5.7/index.html | 58 + .../python-api/5.7/index_files/github.min.css | 1 + .../5.7/index_files/highlight.min.js | 44 + .../5.7/index_files/sanitize.min.css | 2 + .../5.7/index_files/typography.min.css | 2 + clingo/python-api/current | 2 +- 33 files changed, 38997 insertions(+), 1 deletion(-) create mode 100644 clingo/python-api/5.7/clingo/application.html create mode 100644 clingo/python-api/5.7/clingo/ast.html create mode 100644 clingo/python-api/5.7/clingo/backend.html create mode 100644 clingo/python-api/5.7/clingo/configuration.html create mode 100644 clingo/python-api/5.7/clingo/control.html create mode 100644 clingo/python-api/5.7/clingo/core.html create mode 100644 clingo/python-api/5.7/clingo/index.html create mode 100644 clingo/python-api/5.7/clingo/propagator.html create mode 100644 clingo/python-api/5.7/clingo/script.html create mode 100644 clingo/python-api/5.7/clingo/solving.html create mode 100644 clingo/python-api/5.7/clingo/statistics.html create mode 100644 clingo/python-api/5.7/clingo/symbol.html create mode 100644 clingo/python-api/5.7/clingo/symbolic_atoms.html create mode 100644 clingo/python-api/5.7/clingo/theory.html create mode 100644 clingo/python-api/5.7/clingo/theory_atoms.html create mode 100644 clingo/python-api/5.7/clingo/util.html create mode 100644 clingo/python-api/5.7/clingox/ast.html create mode 100644 clingo/python-api/5.7/clingox/backend.html create mode 100644 clingo/python-api/5.7/clingox/index.html create mode 100644 clingo/python-api/5.7/clingox/pprint.html create mode 100644 clingo/python-api/5.7/clingox/program.html create mode 100644 clingo/python-api/5.7/clingox/reify.html create mode 100644 clingo/python-api/5.7/clingox/solving.html create mode 100644 clingo/python-api/5.7/clingox/testing/ast.html create mode 100644 clingo/python-api/5.7/clingox/testing/index.html create mode 100644 clingo/python-api/5.7/clingox/theory.html create mode 100644 clingo/python-api/5.7/index.html create mode 100644 clingo/python-api/5.7/index_files/github.min.css create mode 100644 clingo/python-api/5.7/index_files/highlight.min.js create mode 100644 clingo/python-api/5.7/index_files/sanitize.min.css create mode 100644 clingo/python-api/5.7/index_files/typography.min.css diff --git a/clingo.md b/clingo.md index 475a89b..7e3fd29 100644 --- a/clingo.md +++ b/clingo.md @@ -31,6 +31,7 @@ The language did not change in version 5 but there were many API changes. - [Potassco guide on Sourceforge][guide-sf] for series 4 and earlier - [Formal language specification][ag] - [Python API Reference](/clingo/python-api/current/) (versions + [5.7](/clingo/python-api/5.7/), [5.6](/clingo/python-api/5.6/), [5.5](/clingo/python-api/5.5/), [5.4](/clingo/python-api/5.4/), diff --git a/clingo/python-api/5.7/clingo/application.html b/clingo/python-api/5.7/clingo/application.html new file mode 100644 index 0000000..770cbcd --- /dev/null +++ b/clingo/python-api/5.7/clingo/application.html @@ -0,0 +1,1184 @@ + + + + + + +clingo.application API documentation + + + + + + + + + + + +
+
+
+

Module clingo.application

+
+
+

Functions and classes to implement applications based on clingo.

+

Examples

+

The following example reproduces the default clingo application:

+
import sys
+from clingo.application import Application, clingo_main
+
+class ClingoApp(Application):
+    def __init__(self, name):
+        self.program_name = name
+
+    def main(self, ctl, files):
+        for f in files:
+            ctl.load(f)
+        if not files:
+            ctl.load("-")
+        ctl.ground([("base", [])])
+        ctl.solve()
+
+clingo_main(ClingoApp(sys.argv[0]), sys.argv[1:])
+
+
+ +Expand source code + +
"""
+Functions and classes to implement applications based on clingo.
+
+Examples
+--------
+The following example reproduces the default clingo application:
+
+    import sys
+    from clingo.application import Application, clingo_main
+
+    class ClingoApp(Application):
+        def __init__(self, name):
+            self.program_name = name
+
+        def main(self, ctl, files):
+            for f in files:
+                ctl.load(f)
+            if not files:
+                ctl.load("-")
+            ctl.ground([("base", [])])
+            ctl.solve()
+
+    clingo_main(ClingoApp(sys.argv[0]), sys.argv[1:])
+"""
+
+from typing import Any, Callable, List, Optional, Sequence
+from abc import ABCMeta, abstractmethod
+import sys
+
+from ._internal import (
+    _cb_error_print,
+    _cb_error_panic,
+    _ffi,
+    _handle_error,
+    _lib,
+    _overwritten,
+    _to_str,
+)
+from .core import MessageCode
+from .solving import Model
+from .control import Control
+
+__all__ = ["Application", "ApplicationOptions", "Flag", "clingo_main"]
+
+
+class Flag:
+    """
+    Helper object to parse command-line flags.
+
+    Parameters
+    ----------
+    value
+        The initial value of the flag.
+    """
+
+    def __init__(self, value: bool = False):
+        self._flag = _ffi.new("bool*", value)
+
+    def __bool__(self):
+        return self.flag
+
+    @property
+    def flag(self) -> bool:
+        """
+        The value of the flag.
+        """
+        return self._flag[0]
+
+    @flag.setter
+    def flag(self, value: bool):
+        self._flag[0] = value
+
+
+class ApplicationOptions(metaclass=ABCMeta):
+    """
+    Object to add custom options to a clingo based application.
+    """
+
+    def __init__(self, rep, mem):
+        self._rep = rep
+        self._mem = mem
+
+    def add(
+        self,
+        group: str,
+        option: str,
+        description: str,
+        parser: Callable[[str], bool],
+        multi: bool = False,
+        argument: Optional[str] = None,
+    ) -> None:
+        """
+        Add an option that is processed with a custom parser.
+
+        Parameters
+        ----------
+        group
+            Options are grouped into sections as given by this string.
+        option
+            Parameter option specifies the name(s) of the option. For example,
+            `"ping,p"` adds the short option `-p` and its long form `--ping`. It is
+            also possible to associate an option with a help level by adding `",@l"` to
+            the option specification. Options with a level greater than zero are only
+            shown if the argument to help is greater or equal to `l`.
+        description
+            The description of the option shown in the help output.
+        parser
+            An option parser is a function that takes a string as input and returns
+            true or false depending on whether the option was parsed successively.
+        multi
+            Whether the option can appear multiple times on the command-line.
+        argument
+            Optional string to change the value name in the generated help.
+
+        Notes
+        -----
+        The parser callback has to take care of storing the semantic value of
+        the option somewhere.
+        """
+        # pylint: disable=protected-access
+        c_data = _ffi.new_handle(parser)
+        self._mem.append(c_data)
+
+        _handle_error(
+            _lib.clingo_options_add(
+                self._rep,
+                group.encode(),
+                option.encode(),
+                description.encode(),
+                _lib.pyclingo_application_options_parse,
+                c_data,
+                multi,
+                argument.encode() if argument is not None else _ffi.NULL,
+            )
+        )
+
+    def add_flag(self, group: str, option: str, description: str, target: Flag) -> None:
+        """
+        Add an option that is a simple flag.
+
+        This function is similar to `ApplicationOptions.add` but simpler because
+        it only supports flags, which do not have values. Note that the target
+        parameter must be of type Flag, which is set to true if the flag is passed on
+        the command line.
+
+        Parameters
+        ----------
+        group
+            Options are grouped into sections as given by this string.
+        option
+            Same as for `ApplicationOptions.add`.
+        description
+            The description of the option shown in the help output.
+        target
+            The object that receives the value.
+        """
+        # pylint: disable=protected-access
+        self._mem.append(target)
+        _handle_error(
+            _lib.clingo_options_add_flag(
+                self._rep,
+                group.encode(),
+                option.encode(),
+                description.encode(),
+                target._flag,
+            )
+        )
+
+
+@_ffi.def_extern(onerror=_cb_error_panic, name="pyclingo_application_options_parse")
+def _pyclingo_application_options_parse(value, data):
+    return _ffi.from_handle(data)(_to_str(value))
+
+
+class Application(metaclass=ABCMeta):
+    """
+    Interface that has to be implemented to customize clingo.
+    """
+
+    program_name: str
+    """
+    Program name defaulting to `'clingo'` used in the help output.
+    """
+    version: str
+    """
+    Version string defaulting to clingo's version.
+    """
+    message_limit: int
+    """
+    Maximum number of messages defaulting to `20` passed to the logger.
+    """
+
+    @abstractmethod
+    def main(self, control: Control, files: Sequence[str]) -> None:
+        """
+        Function to replace clingo's default main function.
+
+        This function must be implemented.
+
+        Parameters
+        ----------
+        control
+            The main control object.
+        files
+            The files passed to clingo_main.
+        """
+
+    def register_options(self, options: ApplicationOptions) -> None:
+        """
+        Function to register custom options.
+
+        Parameters
+        ----------
+        options
+            Object to register additional options
+        """
+
+    def validate_options(self) -> bool:
+        """
+        Function to validate custom options.
+
+        Returns
+        -------
+        This function should return false if option validation fails.
+        """
+
+    def print_model(self, model: Model, printer: Callable[[], None]) -> None:
+        """
+        Function to print additional information when the text output is used.
+
+        To avoid entangled output, `sys.stdout.flush` is automatically called
+        after this function.
+
+        Parameters
+        ----------
+        model
+            The current model
+        printer
+            The default printer as used in clingo.
+        """
+
+    def logger(self, code: MessageCode, message: str) -> None:
+        """
+        Function to intercept messages normally printed to standard error.
+
+        By default, messages are printed to standard error.
+
+        Parameters
+        ----------
+        code
+            The message code.
+        message
+            The message string.
+
+        Notes
+        -----
+        This function should not raise exceptions.
+        """
+
+
+def clingo_main(
+    application: Application, arguments: Optional[Sequence[str]] = None
+) -> int:
+    """
+    Runs the given application using clingo's default output and signal handling.
+
+    The application can overwrite clingo's default behaviour by registering
+    additional options and overriding its default main function.
+
+    Parameters
+    ----------
+    application
+        The application object.
+    arguments
+        The command line arguments excluding the program name.
+
+        If omitted, then `sys.argv[1:]` is used.
+
+    Returns
+    -------
+    The exit code of the application.
+
+    Notes
+    -----
+    The main function of the `Application` interface has to be implemented. All
+    other members are optional.
+    """
+    if arguments is None:
+        arguments = sys.argv[1:]
+
+    # pylint: disable=dangerous-default-value,protected-access,line-too-long
+    c_application = _ffi.new(
+        "clingo_application_t*",
+        (
+            _lib.pyclingo_application_program_name
+            if _overwritten(Application, application, "program_name")
+            else _ffi.NULL,
+            _lib.pyclingo_application_version
+            if _overwritten(Application, application, "version")
+            else _ffi.NULL,
+            _lib.pyclingo_application_message_limit
+            if _overwritten(Application, application, "message_limit")
+            else _ffi.NULL,
+            _lib.pyclingo_application_main
+            if _overwritten(Application, application, "main")
+            else _ffi.NULL,
+            _lib.pyclingo_application_logger
+            if _overwritten(Application, application, "logger")
+            else _ffi.NULL,
+            _lib.pyclingo_application_print_model
+            if _overwritten(Application, application, "print_model")
+            else _ffi.NULL,
+            _lib.pyclingo_application_register_options
+            if _overwritten(Application, application, "register_options")
+            else _ffi.NULL,
+            _lib.pyclingo_application_validate_options
+            if _overwritten(Application, application, "validate_options")
+            else _ffi.NULL,
+        ),
+    )
+
+    mem: List[Any] = []
+    c_data = _ffi.new_handle((application, mem))
+
+    return _lib.clingo_main(
+        c_application,
+        [_ffi.new("char[]", arg.encode()) for arg in arguments],
+        len(arguments),
+        c_data,
+    )
+
+
+@_ffi.def_extern(onerror=_cb_error_panic, name="pyclingo_application_program_name")
+def _pyclingo_application_program_name(data):
+    app, mem = _ffi.from_handle(data)
+    mem.append(_ffi.new("char[]", app.program_name.encode()))
+    return mem[-1]
+
+
+@_ffi.def_extern(onerror=_cb_error_panic, name="pyclingo_application_version")
+def _pyclingo_application_version(data):
+    app, mem = _ffi.from_handle(data)
+    mem.append(_ffi.new("char[]", app.version.encode()))
+    return mem[-1]
+
+
+@_ffi.def_extern(onerror=_cb_error_panic, name="pyclingo_application_message_limit")
+def _pyclingo_application_message_limit(data):
+    app = _ffi.from_handle(data)[0]
+    return app.message_limit
+
+
+@_ffi.def_extern(onerror=_cb_error_panic, name="pyclingo_application_logger")
+def _pyclingo_application_logger(code, message, data):
+    app = _ffi.from_handle(data)[0]
+    return app.logger(MessageCode(code), _to_str(message))
+
+
+@_ffi.def_extern(onerror=_cb_error_print, name="pyclingo_application_main")
+def _pyclingo_application_main(control, files, size, data):
+    app = _ffi.from_handle(data)[0]
+    app.main(Control(control), [_to_str(files[i]) for i in range(size)])
+    return True
+
+
+@_ffi.def_extern(onerror=_cb_error_print, name="pyclingo_application_print_model")
+def _pyclingo_application_print_model(model, printer, printer_data, data):
+    def py_printer():
+        _handle_error(printer(printer_data))
+
+    app = _ffi.from_handle(data)[0]
+    app.print_model(Model(model), py_printer)
+    sys.stdout.flush()
+    return True
+
+
+@_ffi.def_extern(onerror=_cb_error_panic, name="pyclingo_application_register_options")
+def _pyclingo_application_register_options(options, data):
+    app, mem = _ffi.from_handle(data)
+    app.register_options(ApplicationOptions(options, mem))
+    return True
+
+
+@_ffi.def_extern(onerror=_cb_error_panic, name="pyclingo_application_validate_options")
+def _pyclingo_application_validate_options(data):
+    app = _ffi.from_handle(data)[0]
+    return app.validate_options()
+
+
+
+
+
+
+
+

Functions

+
+
+def clingo_main(application: Application, arguments: Optional[Sequence[str]] = None) ‑> int +
+
+

Runs the given application using clingo's default output and signal handling.

+

The application can overwrite clingo's default behaviour by registering +additional options and overriding its default main function.

+

Parameters

+
+
application
+
The application object.
+
arguments
+
+

The command line arguments excluding the program name.

+

If omitted, then sys.argv[1:] is used.

+
+
+

Returns

+

The exit code of the application.

+

Notes

+

The main function of the Application interface has to be implemented. All +other members are optional.

+
+ +Expand source code + +
def clingo_main(
+    application: Application, arguments: Optional[Sequence[str]] = None
+) -> int:
+    """
+    Runs the given application using clingo's default output and signal handling.
+
+    The application can overwrite clingo's default behaviour by registering
+    additional options and overriding its default main function.
+
+    Parameters
+    ----------
+    application
+        The application object.
+    arguments
+        The command line arguments excluding the program name.
+
+        If omitted, then `sys.argv[1:]` is used.
+
+    Returns
+    -------
+    The exit code of the application.
+
+    Notes
+    -----
+    The main function of the `Application` interface has to be implemented. All
+    other members are optional.
+    """
+    if arguments is None:
+        arguments = sys.argv[1:]
+
+    # pylint: disable=dangerous-default-value,protected-access,line-too-long
+    c_application = _ffi.new(
+        "clingo_application_t*",
+        (
+            _lib.pyclingo_application_program_name
+            if _overwritten(Application, application, "program_name")
+            else _ffi.NULL,
+            _lib.pyclingo_application_version
+            if _overwritten(Application, application, "version")
+            else _ffi.NULL,
+            _lib.pyclingo_application_message_limit
+            if _overwritten(Application, application, "message_limit")
+            else _ffi.NULL,
+            _lib.pyclingo_application_main
+            if _overwritten(Application, application, "main")
+            else _ffi.NULL,
+            _lib.pyclingo_application_logger
+            if _overwritten(Application, application, "logger")
+            else _ffi.NULL,
+            _lib.pyclingo_application_print_model
+            if _overwritten(Application, application, "print_model")
+            else _ffi.NULL,
+            _lib.pyclingo_application_register_options
+            if _overwritten(Application, application, "register_options")
+            else _ffi.NULL,
+            _lib.pyclingo_application_validate_options
+            if _overwritten(Application, application, "validate_options")
+            else _ffi.NULL,
+        ),
+    )
+
+    mem: List[Any] = []
+    c_data = _ffi.new_handle((application, mem))
+
+    return _lib.clingo_main(
+        c_application,
+        [_ffi.new("char[]", arg.encode()) for arg in arguments],
+        len(arguments),
+        c_data,
+    )
+
+
+
+
+
+

Classes

+
+
+class Application +
+
+

Interface that has to be implemented to customize clingo.

+
+ +Expand source code + +
class Application(metaclass=ABCMeta):
+    """
+    Interface that has to be implemented to customize clingo.
+    """
+
+    program_name: str
+    """
+    Program name defaulting to `'clingo'` used in the help output.
+    """
+    version: str
+    """
+    Version string defaulting to clingo's version.
+    """
+    message_limit: int
+    """
+    Maximum number of messages defaulting to `20` passed to the logger.
+    """
+
+    @abstractmethod
+    def main(self, control: Control, files: Sequence[str]) -> None:
+        """
+        Function to replace clingo's default main function.
+
+        This function must be implemented.
+
+        Parameters
+        ----------
+        control
+            The main control object.
+        files
+            The files passed to clingo_main.
+        """
+
+    def register_options(self, options: ApplicationOptions) -> None:
+        """
+        Function to register custom options.
+
+        Parameters
+        ----------
+        options
+            Object to register additional options
+        """
+
+    def validate_options(self) -> bool:
+        """
+        Function to validate custom options.
+
+        Returns
+        -------
+        This function should return false if option validation fails.
+        """
+
+    def print_model(self, model: Model, printer: Callable[[], None]) -> None:
+        """
+        Function to print additional information when the text output is used.
+
+        To avoid entangled output, `sys.stdout.flush` is automatically called
+        after this function.
+
+        Parameters
+        ----------
+        model
+            The current model
+        printer
+            The default printer as used in clingo.
+        """
+
+    def logger(self, code: MessageCode, message: str) -> None:
+        """
+        Function to intercept messages normally printed to standard error.
+
+        By default, messages are printed to standard error.
+
+        Parameters
+        ----------
+        code
+            The message code.
+        message
+            The message string.
+
+        Notes
+        -----
+        This function should not raise exceptions.
+        """
+
+

Class variables

+
+
var message_limit : int
+
+

Maximum number of messages defaulting to 20 passed to the logger.

+
+
var program_name : str
+
+

Program name defaulting to 'clingo' used in the help output.

+
+
var version : str
+
+

Version string defaulting to clingo's version.

+
+
+

Methods

+
+
+def logger(self, code: MessageCode, message: str) ‑> None +
+
+

Function to intercept messages normally printed to standard error.

+

By default, messages are printed to standard error.

+

Parameters

+
+
code
+
The message code.
+
message
+
The message string.
+
+

Notes

+

This function should not raise exceptions.

+
+ +Expand source code + +
def logger(self, code: MessageCode, message: str) -> None:
+    """
+    Function to intercept messages normally printed to standard error.
+
+    By default, messages are printed to standard error.
+
+    Parameters
+    ----------
+    code
+        The message code.
+    message
+        The message string.
+
+    Notes
+    -----
+    This function should not raise exceptions.
+    """
+
+
+
+def main(self, control: Control, files: Sequence[str]) ‑> None +
+
+

Function to replace clingo's default main function.

+

This function must be implemented.

+

Parameters

+
+
control
+
The main control object.
+
files
+
The files passed to clingo_main.
+
+
+ +Expand source code + +
@abstractmethod
+def main(self, control: Control, files: Sequence[str]) -> None:
+    """
+    Function to replace clingo's default main function.
+
+    This function must be implemented.
+
+    Parameters
+    ----------
+    control
+        The main control object.
+    files
+        The files passed to clingo_main.
+    """
+
+
+
+def print_model(self, model: Model, printer: Callable[[], None]) ‑> None +
+
+

Function to print additional information when the text output is used.

+

To avoid entangled output, sys.stdout.flush is automatically called +after this function.

+

Parameters

+
+
model
+
The current model
+
printer
+
The default printer as used in clingo.
+
+
+ +Expand source code + +
def print_model(self, model: Model, printer: Callable[[], None]) -> None:
+    """
+    Function to print additional information when the text output is used.
+
+    To avoid entangled output, `sys.stdout.flush` is automatically called
+    after this function.
+
+    Parameters
+    ----------
+    model
+        The current model
+    printer
+        The default printer as used in clingo.
+    """
+
+
+
+def register_options(self, options: ApplicationOptions) ‑> None +
+
+

Function to register custom options.

+

Parameters

+
+
options
+
Object to register additional options
+
+
+ +Expand source code + +
def register_options(self, options: ApplicationOptions) -> None:
+    """
+    Function to register custom options.
+
+    Parameters
+    ----------
+    options
+        Object to register additional options
+    """
+
+
+
+def validate_options(self) ‑> bool +
+
+

Function to validate custom options.

+

Returns

+

This function should return false if option validation fails.

+
+ +Expand source code + +
def validate_options(self) -> bool:
+    """
+    Function to validate custom options.
+
+    Returns
+    -------
+    This function should return false if option validation fails.
+    """
+
+
+
+
+
+class ApplicationOptions +(rep, mem) +
+
+

Object to add custom options to a clingo based application.

+
+ +Expand source code + +
class ApplicationOptions(metaclass=ABCMeta):
+    """
+    Object to add custom options to a clingo based application.
+    """
+
+    def __init__(self, rep, mem):
+        self._rep = rep
+        self._mem = mem
+
+    def add(
+        self,
+        group: str,
+        option: str,
+        description: str,
+        parser: Callable[[str], bool],
+        multi: bool = False,
+        argument: Optional[str] = None,
+    ) -> None:
+        """
+        Add an option that is processed with a custom parser.
+
+        Parameters
+        ----------
+        group
+            Options are grouped into sections as given by this string.
+        option
+            Parameter option specifies the name(s) of the option. For example,
+            `"ping,p"` adds the short option `-p` and its long form `--ping`. It is
+            also possible to associate an option with a help level by adding `",@l"` to
+            the option specification. Options with a level greater than zero are only
+            shown if the argument to help is greater or equal to `l`.
+        description
+            The description of the option shown in the help output.
+        parser
+            An option parser is a function that takes a string as input and returns
+            true or false depending on whether the option was parsed successively.
+        multi
+            Whether the option can appear multiple times on the command-line.
+        argument
+            Optional string to change the value name in the generated help.
+
+        Notes
+        -----
+        The parser callback has to take care of storing the semantic value of
+        the option somewhere.
+        """
+        # pylint: disable=protected-access
+        c_data = _ffi.new_handle(parser)
+        self._mem.append(c_data)
+
+        _handle_error(
+            _lib.clingo_options_add(
+                self._rep,
+                group.encode(),
+                option.encode(),
+                description.encode(),
+                _lib.pyclingo_application_options_parse,
+                c_data,
+                multi,
+                argument.encode() if argument is not None else _ffi.NULL,
+            )
+        )
+
+    def add_flag(self, group: str, option: str, description: str, target: Flag) -> None:
+        """
+        Add an option that is a simple flag.
+
+        This function is similar to `ApplicationOptions.add` but simpler because
+        it only supports flags, which do not have values. Note that the target
+        parameter must be of type Flag, which is set to true if the flag is passed on
+        the command line.
+
+        Parameters
+        ----------
+        group
+            Options are grouped into sections as given by this string.
+        option
+            Same as for `ApplicationOptions.add`.
+        description
+            The description of the option shown in the help output.
+        target
+            The object that receives the value.
+        """
+        # pylint: disable=protected-access
+        self._mem.append(target)
+        _handle_error(
+            _lib.clingo_options_add_flag(
+                self._rep,
+                group.encode(),
+                option.encode(),
+                description.encode(),
+                target._flag,
+            )
+        )
+
+

Methods

+
+
+def add(self, group: str, option: str, description: str, parser: Callable[[str], bool], multi: bool = False, argument: Optional[str] = None) ‑> None +
+
+

Add an option that is processed with a custom parser.

+

Parameters

+
+
group
+
Options are grouped into sections as given by this string.
+
option
+
Parameter option specifies the name(s) of the option. For example, +"ping,p" adds the short option -p and its long form --ping. It is +also possible to associate an option with a help level by adding ",@l" to +the option specification. Options with a level greater than zero are only +shown if the argument to help is greater or equal to l.
+
description
+
The description of the option shown in the help output.
+
parser
+
An option parser is a function that takes a string as input and returns +true or false depending on whether the option was parsed successively.
+
multi
+
Whether the option can appear multiple times on the command-line.
+
argument
+
Optional string to change the value name in the generated help.
+
+

Notes

+

The parser callback has to take care of storing the semantic value of +the option somewhere.

+
+ +Expand source code + +
def add(
+    self,
+    group: str,
+    option: str,
+    description: str,
+    parser: Callable[[str], bool],
+    multi: bool = False,
+    argument: Optional[str] = None,
+) -> None:
+    """
+    Add an option that is processed with a custom parser.
+
+    Parameters
+    ----------
+    group
+        Options are grouped into sections as given by this string.
+    option
+        Parameter option specifies the name(s) of the option. For example,
+        `"ping,p"` adds the short option `-p` and its long form `--ping`. It is
+        also possible to associate an option with a help level by adding `",@l"` to
+        the option specification. Options with a level greater than zero are only
+        shown if the argument to help is greater or equal to `l`.
+    description
+        The description of the option shown in the help output.
+    parser
+        An option parser is a function that takes a string as input and returns
+        true or false depending on whether the option was parsed successively.
+    multi
+        Whether the option can appear multiple times on the command-line.
+    argument
+        Optional string to change the value name in the generated help.
+
+    Notes
+    -----
+    The parser callback has to take care of storing the semantic value of
+    the option somewhere.
+    """
+    # pylint: disable=protected-access
+    c_data = _ffi.new_handle(parser)
+    self._mem.append(c_data)
+
+    _handle_error(
+        _lib.clingo_options_add(
+            self._rep,
+            group.encode(),
+            option.encode(),
+            description.encode(),
+            _lib.pyclingo_application_options_parse,
+            c_data,
+            multi,
+            argument.encode() if argument is not None else _ffi.NULL,
+        )
+    )
+
+
+
+def add_flag(self, group: str, option: str, description: str, target: Flag) ‑> None +
+
+

Add an option that is a simple flag.

+

This function is similar to ApplicationOptions.add() but simpler because +it only supports flags, which do not have values. Note that the target +parameter must be of type Flag, which is set to true if the flag is passed on +the command line.

+

Parameters

+
+
group
+
Options are grouped into sections as given by this string.
+
option
+
Same as for ApplicationOptions.add().
+
description
+
The description of the option shown in the help output.
+
target
+
The object that receives the value.
+
+
+ +Expand source code + +
def add_flag(self, group: str, option: str, description: str, target: Flag) -> None:
+    """
+    Add an option that is a simple flag.
+
+    This function is similar to `ApplicationOptions.add` but simpler because
+    it only supports flags, which do not have values. Note that the target
+    parameter must be of type Flag, which is set to true if the flag is passed on
+    the command line.
+
+    Parameters
+    ----------
+    group
+        Options are grouped into sections as given by this string.
+    option
+        Same as for `ApplicationOptions.add`.
+    description
+        The description of the option shown in the help output.
+    target
+        The object that receives the value.
+    """
+    # pylint: disable=protected-access
+    self._mem.append(target)
+    _handle_error(
+        _lib.clingo_options_add_flag(
+            self._rep,
+            group.encode(),
+            option.encode(),
+            description.encode(),
+            target._flag,
+        )
+    )
+
+
+
+
+
+class Flag +(value: bool = False) +
+
+

Helper object to parse command-line flags.

+

Parameters

+
+
value
+
The initial value of the flag.
+
+
+ +Expand source code + +
class Flag:
+    """
+    Helper object to parse command-line flags.
+
+    Parameters
+    ----------
+    value
+        The initial value of the flag.
+    """
+
+    def __init__(self, value: bool = False):
+        self._flag = _ffi.new("bool*", value)
+
+    def __bool__(self):
+        return self.flag
+
+    @property
+    def flag(self) -> bool:
+        """
+        The value of the flag.
+        """
+        return self._flag[0]
+
+    @flag.setter
+    def flag(self, value: bool):
+        self._flag[0] = value
+
+

Instance variables

+
+
var flag : bool
+
+

The value of the flag.

+
+ +Expand source code + +
@property
+def flag(self) -> bool:
+    """
+    The value of the flag.
+    """
+    return self._flag[0]
+
+
+
+
+
+
+
+ +
+ + + \ No newline at end of file diff --git a/clingo/python-api/5.7/clingo/ast.html b/clingo/python-api/5.7/clingo/ast.html new file mode 100644 index 0000000..4465757 --- /dev/null +++ b/clingo/python-api/5.7/clingo/ast.html @@ -0,0 +1,6458 @@ + + + + + + +clingo.ast API documentation + + + + + + + + + + + +
+
+
+

Module clingo.ast

+
+
+

Module to work with clingo's non-ground program representation.

+

Grammar

+

The grammar below defines valid ASTs. For each upper case identifier there is a +matching function in the module. Arguments follow in parenthesis: each having a +type given on the right-hand side of the colon. The symbols ?, *, and + +are used to denote optional arguments (None encodes abscence), list +arguments, and non-empty list arguments.

+
# Terms
+
+term = SymbolicTerm
+        ( location : Location
+        , symbol   : clingo.Symbol
+        )
+     | Variable
+        ( location : Location
+        , name     : str
+        )
+     | UnaryOperation
+        ( location      : Location
+        , operator_type : UnaryOperator
+        , argument      : term
+        )
+     | BinaryOperation
+        ( location      : Location
+        , operator_type : BinaryOperator
+        , left          : term
+        , right         : term
+        )
+     | Interval
+        ( location : Location
+        , left     : term
+        , right    : term
+        )
+     | Function
+        ( location  : Location
+        , name      : str
+        , arguments : term*
+        , external  : bool
+        )
+     | Pool
+        ( location  : Location
+        , arguments : term*
+        )
+
+theory_term = SymbolicTerm
+               ( location : Location
+               , symbol   : clingo.Symbol
+               )
+            | Variable
+               ( location : Location
+               , name     : str
+               )
+            | TheorySequence
+               ( location : Location
+               , sequence_type : TheorySequenceType
+               , terms         : theory_term*
+               )
+            | TheoryFunction
+               ( location  : Location
+               , name      : str
+               , arguments : theory_term*
+               )
+            | TheoryUnparsedTerm
+               ( location : Location
+               , elements : TheoryUnparsedTermElement
+                             ( operators : str*
+                             , term      : theory_term
+                             )+
+               )
+
+# Literals
+
+symbolic_atom = SymbolicAtom
+                 ( symbol : term
+                 )
+
+guard = Guard
+         ( comparison : ComparisonOperator
+         , term       : term
+         )
+
+literal = Literal
+           ( location : Location
+           , sign     : Sign
+           , atom     : Comparison
+                         ( term   : term
+                         , guards : guard+
+                         )
+                      | BooleanConstant
+                         ( value : bool
+                         )
+                      | symbolic_atom
+           )
+
+# Head and Body Literals
+
+conditional_literal = ConditionalLiteral
+                       ( location  : Location
+                       , literal   : Literal
+                       , condition : Literal*
+                       )
+
+aggregate = Aggregate
+             ( location    : Location
+             , left_guard  : guard?
+             , elements    : conditional_literal*
+             , right_guard : guard?
+             )
+
+theory_atom = TheoryAtom
+               ( location : Location
+               , term     : term
+               , elements : TheoryAtomElement
+                             ( terms     : theory_term*
+                             , condition : literal*
+                             )*
+               , guard    : TheoryGuard
+                             ( operator_name : str
+                             , term          : theory_term
+                             )?
+               )
+
+body_atom = aggregate
+          | BodyAggregate
+             ( location    : Location
+             , left_guard  : guard?
+             , function    : AggregateFunction
+             , elements    : BodyAggregateElement
+                              ( terms     : term*
+                              , condition : literal*
+                              )*
+             , right_guard : guard?
+             )
+          | theory_atom
+
+body_literal = literal
+             | conditional_literal
+             | Literal
+                ( location : Location
+                , sign     : Sign
+                , atom     : body_atom
+                )
+
+head = literal
+     | aggregate
+     | HeadAggregate
+        ( location    : Location
+        , left_guard  : guard?
+        , function    : AggregateFunction
+        , elements    : HeadAggregateElement
+                         ( terms     : term*
+                         , condition : conditional_literal
+                         )*
+        , right_guard : guard?
+        )
+     | Disjunction
+        ( location : Location
+        , elements : conditional_literal*
+        )
+     | theory_atom
+
+# Statements
+
+statement = Rule
+             ( location : Location
+             , head     : head
+             , body     : body_literal*
+             )
+          | Definition
+             ( location   : Location
+             , name       : str
+             , value      : term
+             , is_default : bool
+             )
+          | ShowSignature
+             ( location   : Location
+             , name       : str
+             , arity      : int
+             , sign       : bool
+             )
+          | Defined
+             ( location   : Location
+             , name       : str
+             , arity      : int
+             , sign       : bool
+             )
+          | ShowTerm
+             ( location : Location
+             , term     : term
+             , body     : body_literal*
+             )
+          | Minimize
+             ( location : Location
+             , weight   : term
+             , priority : term
+             , terms    : term*
+             , body     : body_literal*
+             )
+          | Script
+             ( location : Location
+             , name     : str
+             , code     : str
+             )
+          | Program
+             ( location   : Location
+             , name       : str
+             , parameters : Id
+                             ( location : Location
+                             , id       : str
+                             )*
+             )
+          | External
+             ( location : Location
+             , atom     : symbolic_atom
+             , body     : body_literal*
+             , type     : term
+             )
+          | Edge
+             ( location : Location
+             , u        : term
+             , v        : term
+             , body     : body_literal*
+             )
+          | Heuristic
+             ( location : Location
+             , atom     : symbolic_atom
+             , body     : body_literal*
+             , bias     : term
+             , priority : term
+             , modifier : term
+             )
+          | ProjectAtom
+             ( location : Location
+             , atom     : symbolic_atom
+             , body     : body_literal*
+             )
+          | ProjectSignature
+             ( location : Location
+             , name     : str
+             , arity    : int
+             , sign     : bool
+             )
+          | TheoryDefinition
+             ( location : Location
+             , name     : str
+             , terms    : TheoryTermDefinition
+                           ( location  : Location
+                           , name      : str
+                           , operators : TheoryOperatorDefinition
+                                          ( location      : Location
+                                          , name          : str
+                                          , priority      : int
+                                          , operator_type : TheoryOperatorType
+                                          )*
+                           )*
+             , atoms    : TheoryAtomDefinition
+                           ( location  : Location
+                           , atom_type : TheoryAtomType
+                           , name      : str
+                           , arity     : int
+                           , term      : str
+                           , guard     : TheoryGuardDefinition
+                                          ( operators : str*
+                                          , term      : str
+                                          )?
+                           )*
+             )
+          | Comment
+             ( location     : Location
+             , value        : str
+             , comment_type : CommentType
+             )
+
+

Examples

+

The following example parses a program from a string and passes the resulting +AST to the builder:

+
>>> from clingo import Control, ast
+>>> from clingo.ast import Location, ProgramBuilder, Position, parse_string
+>>>
+>>> ctl = Control()
+>>>
+>>> with ProgramBuilder(ctl) as bld:
+...     # parse from string
+...     parse_string('a.', bld.add)
+...     # build rule manually
+...     pos = Position('<string>', 1, 1)
+...     loc = Location(pos, pos)
+...     fun = ast.Function(loc, 'b', [], False)
+...     atm = ast.SymbolicAtom(fun)
+...     lit = ast.Literal(loc, ast.Sign.NoSign, atm)
+...     bld.add(ast.Rule(loc, lit, []))
+...
+>>> ctl.ground([('base', [])])
+>>> print(ctl.solve(on_model=print))
+a b
+SAT
+
+

The next example shows how to transform ASTs using the Transformer class:

+
>>> from clingo.ast import Transformer, Variable, parse_string
+>>>
+>>> class VariableRenamer(Transformer):
+...     def visit_Variable(self, node):
+...         return node.update(name='_' + node.name)
+...
+>>> vrt = VariableRenamer()
+>>> parse_string('p(X) :- q(X).', lambda stm: print(str(vrt(stm))))
+#program base.
+p(_X) :- q(_X).
+
+
+ +Expand source code + +
"""
+Module to work with clingo's non-ground program representation.
+
+Grammar
+-------
+The grammar below defines valid ASTs. For each upper case identifier there is a
+matching function in the module. Arguments follow in parenthesis: each having a
+type given on the right-hand side of the colon. The symbols `?`, `*`, and `+`
+are used to denote optional arguments (`None` encodes abscence), list
+arguments, and non-empty list arguments.
+
+```
+# Terms
+
+term = SymbolicTerm
+        ( location : Location
+        , symbol   : clingo.Symbol
+        )
+     | Variable
+        ( location : Location
+        , name     : str
+        )
+     | UnaryOperation
+        ( location      : Location
+        , operator_type : UnaryOperator
+        , argument      : term
+        )
+     | BinaryOperation
+        ( location      : Location
+        , operator_type : BinaryOperator
+        , left          : term
+        , right         : term
+        )
+     | Interval
+        ( location : Location
+        , left     : term
+        , right    : term
+        )
+     | Function
+        ( location  : Location
+        , name      : str
+        , arguments : term*
+        , external  : bool
+        )
+     | Pool
+        ( location  : Location
+        , arguments : term*
+        )
+
+theory_term = SymbolicTerm
+               ( location : Location
+               , symbol   : clingo.Symbol
+               )
+            | Variable
+               ( location : Location
+               , name     : str
+               )
+            | TheorySequence
+               ( location : Location
+               , sequence_type : TheorySequenceType
+               , terms         : theory_term*
+               )
+            | TheoryFunction
+               ( location  : Location
+               , name      : str
+               , arguments : theory_term*
+               )
+            | TheoryUnparsedTerm
+               ( location : Location
+               , elements : TheoryUnparsedTermElement
+                             ( operators : str*
+                             , term      : theory_term
+                             )+
+               )
+
+# Literals
+
+symbolic_atom = SymbolicAtom
+                 ( symbol : term
+                 )
+
+guard = Guard
+         ( comparison : ComparisonOperator
+         , term       : term
+         )
+
+literal = Literal
+           ( location : Location
+           , sign     : Sign
+           , atom     : Comparison
+                         ( term   : term
+                         , guards : guard+
+                         )
+                      | BooleanConstant
+                         ( value : bool
+                         )
+                      | symbolic_atom
+           )
+
+# Head and Body Literals
+
+conditional_literal = ConditionalLiteral
+                       ( location  : Location
+                       , literal   : Literal
+                       , condition : Literal*
+                       )
+
+aggregate = Aggregate
+             ( location    : Location
+             , left_guard  : guard?
+             , elements    : conditional_literal*
+             , right_guard : guard?
+             )
+
+theory_atom = TheoryAtom
+               ( location : Location
+               , term     : term
+               , elements : TheoryAtomElement
+                             ( terms     : theory_term*
+                             , condition : literal*
+                             )*
+               , guard    : TheoryGuard
+                             ( operator_name : str
+                             , term          : theory_term
+                             )?
+               )
+
+body_atom = aggregate
+          | BodyAggregate
+             ( location    : Location
+             , left_guard  : guard?
+             , function    : AggregateFunction
+             , elements    : BodyAggregateElement
+                              ( terms     : term*
+                              , condition : literal*
+                              )*
+             , right_guard : guard?
+             )
+          | theory_atom
+
+body_literal = literal
+             | conditional_literal
+             | Literal
+                ( location : Location
+                , sign     : Sign
+                , atom     : body_atom
+                )
+
+head = literal
+     | aggregate
+     | HeadAggregate
+        ( location    : Location
+        , left_guard  : guard?
+        , function    : AggregateFunction
+        , elements    : HeadAggregateElement
+                         ( terms     : term*
+                         , condition : conditional_literal
+                         )*
+        , right_guard : guard?
+        )
+     | Disjunction
+        ( location : Location
+        , elements : conditional_literal*
+        )
+     | theory_atom
+
+# Statements
+
+statement = Rule
+             ( location : Location
+             , head     : head
+             , body     : body_literal*
+             )
+          | Definition
+             ( location   : Location
+             , name       : str
+             , value      : term
+             , is_default : bool
+             )
+          | ShowSignature
+             ( location   : Location
+             , name       : str
+             , arity      : int
+             , sign       : bool
+             )
+          | Defined
+             ( location   : Location
+             , name       : str
+             , arity      : int
+             , sign       : bool
+             )
+          | ShowTerm
+             ( location : Location
+             , term     : term
+             , body     : body_literal*
+             )
+          | Minimize
+             ( location : Location
+             , weight   : term
+             , priority : term
+             , terms    : term*
+             , body     : body_literal*
+             )
+          | Script
+             ( location : Location
+             , name     : str
+             , code     : str
+             )
+          | Program
+             ( location   : Location
+             , name       : str
+             , parameters : Id
+                             ( location : Location
+                             , id       : str
+                             )*
+             )
+          | External
+             ( location : Location
+             , atom     : symbolic_atom
+             , body     : body_literal*
+             , type     : term
+             )
+          | Edge
+             ( location : Location
+             , u        : term
+             , v        : term
+             , body     : body_literal*
+             )
+          | Heuristic
+             ( location : Location
+             , atom     : symbolic_atom
+             , body     : body_literal*
+             , bias     : term
+             , priority : term
+             , modifier : term
+             )
+          | ProjectAtom
+             ( location : Location
+             , atom     : symbolic_atom
+             , body     : body_literal*
+             )
+          | ProjectSignature
+             ( location : Location
+             , name     : str
+             , arity    : int
+             , sign     : bool
+             )
+          | TheoryDefinition
+             ( location : Location
+             , name     : str
+             , terms    : TheoryTermDefinition
+                           ( location  : Location
+                           , name      : str
+                           , operators : TheoryOperatorDefinition
+                                          ( location      : Location
+                                          , name          : str
+                                          , priority      : int
+                                          , operator_type : TheoryOperatorType
+                                          )*
+                           )*
+             , atoms    : TheoryAtomDefinition
+                           ( location  : Location
+                           , atom_type : TheoryAtomType
+                           , name      : str
+                           , arity     : int
+                           , term      : str
+                           , guard     : TheoryGuardDefinition
+                                          ( operators : str*
+                                          , term      : str
+                                          )?
+                           )*
+             )
+          | Comment
+             ( location     : Location
+             , value        : str
+             , comment_type : CommentType
+             )
+```
+
+Examples
+--------
+The following example parses a program from a string and passes the resulting
+`AST` to the builder:
+
+    >>> from clingo import Control, ast
+    >>> from clingo.ast import Location, ProgramBuilder, Position, parse_string
+    >>>
+    >>> ctl = Control()
+    >>>
+    >>> with ProgramBuilder(ctl) as bld:
+    ...     # parse from string
+    ...     parse_string('a.', bld.add)
+    ...     # build rule manually
+    ...     pos = Position('<string>', 1, 1)
+    ...     loc = Location(pos, pos)
+    ...     fun = ast.Function(loc, 'b', [], False)
+    ...     atm = ast.SymbolicAtom(fun)
+    ...     lit = ast.Literal(loc, ast.Sign.NoSign, atm)
+    ...     bld.add(ast.Rule(loc, lit, []))
+    ...
+    >>> ctl.ground([('base', [])])
+    >>> print(ctl.solve(on_model=print))
+    a b
+    SAT
+
+The next example shows how to transform ASTs using the `Transformer` class:
+
+    >>> from clingo.ast import Transformer, Variable, parse_string
+    >>>
+    >>> class VariableRenamer(Transformer):
+    ...     def visit_Variable(self, node):
+    ...         return node.update(name='_' + node.name)
+    ...
+    >>> vrt = VariableRenamer()
+    >>> parse_string('p(X) :- q(X).', lambda stm: print(str(vrt(stm))))
+    #program base.
+    p(_X) :- q(_X).
+"""
+
+from enum import IntEnum
+from typing import (
+    Any,
+    Callable,
+    ContextManager,
+    Dict,
+    List,
+    MutableSequence,
+    NamedTuple,
+    Optional,
+    Sequence,
+    Tuple,
+    Union,
+)
+from collections import abc
+from functools import total_ordering
+
+from ._internal import (
+    _CBData,
+    _Error,
+    _cb_error_handler,
+    _c_call,
+    _ffi,
+    _handle_error,
+    _lib,
+    _str,
+    _to_str,
+)
+from .util import Slice, SlicedMutableSequence
+from .core import Logger, OrderedEnum
+from .control import Control
+from .symbol import Symbol
+
+__all__ = [
+    "AST",
+    "ASTSequence",
+    "ASTType",
+    "ASTValue",
+    "Aggregate",
+    "AggregateFunction",
+    "Guard",
+    "BinaryOperation",
+    "BinaryOperator",
+    "BodyAggregate",
+    "BodyAggregateElement",
+    "BooleanConstant",
+    "Comment",
+    "CommentType",
+    "Comparison",
+    "ComparisonOperator",
+    "ConditionalLiteral",
+    "Defined",
+    "Definition",
+    "Disjunction",
+    "Edge",
+    "External",
+    "Function",
+    "HeadAggregate",
+    "HeadAggregateElement",
+    "Heuristic",
+    "Id",
+    "Interval",
+    "Literal",
+    "Location",
+    "Minimize",
+    "Pool",
+    "Position",
+    "Program",
+    "ProgramBuilder",
+    "ProjectAtom",
+    "ProjectSignature",
+    "Rule",
+    "Script",
+    "ShowSignature",
+    "ShowTerm",
+    "Sign",
+    "StrSequence",
+    "SymbolicAtom",
+    "SymbolicTerm",
+    "TheoryAtom",
+    "TheoryAtomDefinition",
+    "TheoryAtomElement",
+    "TheoryAtomType",
+    "TheoryDefinition",
+    "TheoryFunction",
+    "TheoryGuard",
+    "TheoryGuardDefinition",
+    "TheoryOperatorDefinition",
+    "TheoryOperatorType",
+    "TheorySequence",
+    "TheorySequenceType",
+    "TheoryTermDefinition",
+    "TheoryUnparsedTerm",
+    "TheoryUnparsedTermElement",
+    "Transformer",
+    "UnaryOperation",
+    "UnaryOperator",
+    "Variable",
+    "parse_files",
+    "parse_string",
+]
+
+# pylint: disable=protected-access,invalid-name,too-many-lines,too-many-ancestors
+
+
+class ASTType(OrderedEnum):
+    """
+    Enumeration of ast node types.
+    """
+
+    Id = _lib.clingo_ast_type_id
+    Variable = _lib.clingo_ast_type_variable
+    SymbolicTerm = _lib.clingo_ast_type_symbolic_term
+    UnaryOperation = _lib.clingo_ast_type_unary_operation
+    BinaryOperation = _lib.clingo_ast_type_binary_operation
+    Interval = _lib.clingo_ast_type_interval
+    Function = _lib.clingo_ast_type_function
+    Pool = _lib.clingo_ast_type_pool
+    BooleanConstant = _lib.clingo_ast_type_boolean_constant
+    SymbolicAtom = _lib.clingo_ast_type_symbolic_atom
+    Comparison = _lib.clingo_ast_type_comparison
+    Guard = _lib.clingo_ast_type_guard
+    ConditionalLiteral = _lib.clingo_ast_type_conditional_literal
+    Aggregate = _lib.clingo_ast_type_aggregate
+    BodyAggregateElement = _lib.clingo_ast_type_body_aggregate_element
+    BodyAggregate = _lib.clingo_ast_type_body_aggregate
+    HeadAggregateElement = _lib.clingo_ast_type_head_aggregate_element
+    HeadAggregate = _lib.clingo_ast_type_head_aggregate
+    Disjunction = _lib.clingo_ast_type_disjunction
+    TheorySequence = _lib.clingo_ast_type_theory_sequence
+    TheoryFunction = _lib.clingo_ast_type_theory_function
+    TheoryUnparsedTermElement = _lib.clingo_ast_type_theory_unparsed_term_element
+    TheoryUnparsedTerm = _lib.clingo_ast_type_theory_unparsed_term
+    TheoryGuard = _lib.clingo_ast_type_theory_guard
+    TheoryAtomElement = _lib.clingo_ast_type_theory_atom_element
+    TheoryAtom = _lib.clingo_ast_type_theory_atom
+    Literal = _lib.clingo_ast_type_literal
+    TheoryOperatorDefinition = _lib.clingo_ast_type_theory_operator_definition
+    TheoryTermDefinition = _lib.clingo_ast_type_theory_term_definition
+    TheoryGuardDefinition = _lib.clingo_ast_type_theory_guard_definition
+    TheoryAtomDefinition = _lib.clingo_ast_type_theory_atom_definition
+    Rule = _lib.clingo_ast_type_rule
+    Definition = _lib.clingo_ast_type_definition
+    ShowSignature = _lib.clingo_ast_type_show_signature
+    ShowTerm = _lib.clingo_ast_type_show_term
+    Minimize = _lib.clingo_ast_type_minimize
+    Script = _lib.clingo_ast_type_script
+    Program = _lib.clingo_ast_type_program
+    External = _lib.clingo_ast_type_external
+    Edge = _lib.clingo_ast_type_edge
+    Heuristic = _lib.clingo_ast_type_heuristic
+    ProjectAtom = _lib.clingo_ast_type_project_atom
+    ProjectSignature = _lib.clingo_ast_type_project_signature
+    Defined = _lib.clingo_ast_type_defined
+    TheoryDefinition = _lib.clingo_ast_type_theory_definition
+    Comment = _lib.clingo_ast_type_comment
+
+
+class AggregateFunction(IntEnum):
+    """
+    Enumeration of aggegate functions.
+    """
+
+    Count = _lib.clingo_ast_aggregate_function_count
+    """
+    The `#count` function.
+    """
+    Max = _lib.clingo_ast_aggregate_function_max
+    """
+    The `#max` function.
+    """
+    Min = _lib.clingo_ast_aggregate_function_min
+    """
+    The `#min` function.
+    """
+    Sum = _lib.clingo_ast_aggregate_function_sum
+    """
+    The `#sum` function.
+    """
+    SumPlus = _lib.clingo_ast_aggregate_function_sump
+    """
+    The `#sum+` function.
+    """
+
+
+class BinaryOperator(IntEnum):
+    """
+    Enumeration of binary operators.
+    """
+
+    And = _lib.clingo_ast_binary_operator_and
+    """
+    For bitwise and.
+    """
+    Division = _lib.clingo_ast_binary_operator_division
+    """
+    For arithmetic division.
+    """
+    Minus = _lib.clingo_ast_binary_operator_minus
+    """
+    For arithmetic subtraction.
+    """
+    Modulo = _lib.clingo_ast_binary_operator_modulo
+    """
+    For arithmetic modulo.
+    """
+    Multiplication = _lib.clingo_ast_binary_operator_multiplication
+    """
+    For arithmetic multipilcation.
+    """
+    Or = _lib.clingo_ast_binary_operator_or
+    """
+    For bitwise or.
+    """
+    Plus = _lib.clingo_ast_binary_operator_plus
+    """
+    For arithmetic addition.
+    """
+    Power = _lib.clingo_ast_binary_operator_power
+    """
+    For arithmetic exponentiation.
+    """
+    XOr = _lib.clingo_ast_binary_operator_xor
+    """
+    For bitwise exclusive or.
+    """
+
+
+class CommentType(OrderedEnum):
+    """
+    Enumeration of comment types.
+    """
+
+    Line = _lib.clingo_comment_type_line
+    """
+    Line comments starting with `%` ending at a newline.
+    """
+    Block = _lib.clingo_comment_type_block
+    """
+    Block comments enclosed in `%*` and  `*%`.
+    """
+
+
+class ComparisonOperator(IntEnum):
+    """
+    Enumeration of comparison operators.
+    """
+
+    Equal = _lib.clingo_ast_comparison_operator_equal
+    """
+    The `=` operator
+    """
+    GreaterEqual = _lib.clingo_ast_comparison_operator_greater_equal
+    """
+    The `>=` operator.
+    """
+    GreaterThan = _lib.clingo_ast_comparison_operator_greater_than
+    """
+    The `>` operator.
+    """
+    LessEqual = _lib.clingo_ast_comparison_operator_less_equal
+    """
+    The `<=` operator.
+    """
+    LessThan = _lib.clingo_ast_comparison_operator_less_than
+    """
+    The `<` operator.
+    """
+    NotEqual = _lib.clingo_ast_comparison_operator_not_equal
+    """
+    The `!=` operator.
+    """
+
+
+class Sign(IntEnum):
+    """
+    Enumeration of signs for literals.
+    """
+
+    DoubleNegation = _lib.clingo_ast_sign_double_negation
+    """
+    For double negated literals (with prefix `not not`)
+    """
+    Negation = _lib.clingo_ast_sign_negation
+    """
+    For negative literals (with prefix `not`).
+    """
+    NoSign = _lib.clingo_ast_sign_no_sign
+    """
+    For positive literals.
+    """
+
+
+class TheoryAtomType(IntEnum):
+    """
+    Enumeration of theory atom types.
+    """
+
+    Any = _lib.clingo_ast_theory_atom_definition_type_any
+    """
+    For atoms that can occur anywhere in a rule.
+    """
+    Body = _lib.clingo_ast_theory_atom_definition_type_body
+    """
+    For atoms that can only occur in rule bodies.
+    """
+    Directive = _lib.clingo_ast_theory_atom_definition_type_directive
+    """
+    For atoms that can only occur in facts.
+    """
+    Head = _lib.clingo_ast_theory_atom_definition_type_head
+    """
+    For atoms that can only occur in rule heads.
+    """
+
+
+class TheoryOperatorType(IntEnum):
+    """
+    Enumeration of operator types.
+    """
+
+    BinaryLeft = _lib.clingo_ast_theory_operator_type_binary_left
+    """
+    For binary left associative operators.
+    """
+    BinaryRight = _lib.clingo_ast_theory_operator_type_binary_right
+    """
+    For binary right associative operator.
+    """
+    Unary = _lib.clingo_ast_theory_operator_type_unary
+    """
+    For unary operators.
+    """
+
+
+class TheorySequenceType(IntEnum):
+    """
+    Enumeration of theory term sequence types.
+    """
+
+    List = _lib.clingo_ast_theory_sequence_type_list
+    """
+    For sequences enclosed in brackets.
+    """
+    Set = _lib.clingo_ast_theory_sequence_type_set
+    """
+    For sequences enclosed in braces.
+    """
+    Tuple = _lib.clingo_ast_theory_sequence_type_tuple
+    """
+    For sequences enclosed in parenthesis.
+    """
+
+
+class UnaryOperator(IntEnum):
+    """
+    Enumeration of signs for literals.
+    """
+
+    Absolute = _lib.clingo_ast_unary_operator_absolute
+    """
+    For taking the absolute value.
+    """
+    Minus = _lib.clingo_ast_unary_operator_minus
+    """
+    For unary minus and classical negation.
+    """
+    Negation = _lib.clingo_ast_unary_operator_negation
+    """
+    For bitwise negation.
+    """
+
+
+class ASTSequence(abc.MutableSequence):
+    """
+    A sequence holding `AST` nodes.
+
+    Sequences implement Python's rich comparison operators and are ordered
+    structurally ignoring the location. They can also be used as dictionary
+    keys.
+    """
+
+    def __init__(self, rep, attribute):
+        self._rep = rep
+        self._attribute = attribute
+        _lib.clingo_ast_acquire(self._rep)
+
+    def __eq__(self, other):
+        return tuple(self) == tuple(other)
+
+    def __lt__(self, other):
+        return tuple(self) < tuple(other)
+
+    def __hash__(self):
+        return hash(tuple(self))
+
+    def __del__(self):
+        _lib.clingo_ast_release(self._rep)
+
+    def __len__(self) -> int:
+        return _c_call(
+            "size_t",
+            _lib.clingo_ast_attribute_size_ast_array,
+            self._rep,
+            self._attribute,
+        )
+
+    def __getitem__(self, index):
+        if isinstance(index, slice):
+            return SlicedMutableSequence(self, Slice(index))
+        size = len(self)
+        if index < 0:
+            index += size
+        if index < 0 or index >= size:
+            raise IndexError("invalid index")
+        return AST(
+            _c_call(
+                "clingo_ast_t*",
+                _lib.clingo_ast_attribute_get_ast_at,
+                self._rep,
+                self._attribute,
+                index,
+            )
+        )
+
+    def __iter__(self):
+        for index in range(len(self)):
+            yield AST(
+                _c_call(
+                    "clingo_ast_t*",
+                    _lib.clingo_ast_attribute_get_ast_at,
+                    self._rep,
+                    self._attribute,
+                    index,
+                )
+            )
+
+    def __setitem__(self, index, ast):
+        if isinstance(index, slice):
+            raise TypeError("slicing not implemented")
+        _handle_error(
+            _lib.clingo_ast_attribute_set_ast_at(
+                self._rep, self._attribute, index, ast._rep
+            )
+        )
+
+    def __delitem__(self, index):
+        if isinstance(index, slice):
+            raise TypeError("slicing not implemented")
+        size = len(self)
+        if index < 0:
+            index += size
+        if index < 0 or index >= size:
+            raise IndexError("invalid index")
+        _handle_error(
+            _lib.clingo_ast_attribute_delete_ast_at(self._rep, self._attribute, index)
+        )
+
+    def insert(self, index, value):
+        _handle_error(
+            _lib.clingo_ast_attribute_insert_ast_at(
+                self._rep, self._attribute, index, value._rep
+            )
+        )
+
+    def clear(self):
+        """
+        Remove all elements from the sequence.
+        """
+        for i in range(len(self), 0, -1):
+            del self[i - 1]
+
+    def __str__(self):
+        return str(list(self))
+
+    def __repr__(self):
+        return repr(list(self))
+
+
+class StrSequence(abc.MutableSequence):
+    """
+    A sequence holding strings.
+    """
+
+    def __init__(self, rep, attribute):
+        self._attribute = attribute
+        self._rep = rep
+        _lib.clingo_ast_acquire(self._rep)
+
+    def __del__(self):
+        _lib.clingo_ast_release(self._rep)
+
+    def __len__(self) -> int:
+        return _c_call(
+            "size_t",
+            _lib.clingo_ast_attribute_size_string_array,
+            self._rep,
+            self._attribute,
+        )
+
+    def __getitem__(self, index):
+        if isinstance(index, slice):
+            return SlicedMutableSequence(self, Slice(index))
+        size = len(self)
+        if index < 0:
+            index += size
+        if index < 0 or index >= size:
+            raise IndexError("invalid index")
+        return _to_str(
+            _c_call(
+                "char*",
+                _lib.clingo_ast_attribute_get_string_at,
+                self._rep,
+                self._attribute,
+                index,
+            )
+        )
+
+    def __iter__(self):
+        for index in range(len(self)):
+            yield _to_str(
+                _c_call(
+                    "char*",
+                    _lib.clingo_ast_attribute_get_string_at,
+                    self._rep,
+                    self._attribute,
+                    index,
+                )
+            )
+
+    def __setitem__(self, index, value):
+        if isinstance(index, slice):
+            raise TypeError("slicing not implemented")
+        _handle_error(
+            _lib.clingo_str_attribute_set_string_at(
+                self._rep, self._attribute, index, value.encode()
+            )
+        )
+
+    def __delitem__(self, index):
+        if isinstance(index, slice):
+            raise TypeError("slicing not implemented")
+        size = len(self)
+        if index < 0:
+            index += size
+        if index < 0 or index >= size:
+            raise IndexError("invalid index")
+        _handle_error(
+            _lib.clingo_ast_attribute_delete_string_at(
+                self._rep, self._attribute, index
+            )
+        )
+
+    def insert(self, index, value):
+        _handle_error(
+            _lib.clingo_ast_attribute_insert_string_at(
+                self._rep, self._attribute, index, value.encode()
+            )
+        )
+
+    def clear(self):
+        """
+        Remove all elements from the sequence.
+        """
+        for i in range(len(self), 0, -1):
+            del self[i - 1]
+
+    def __str__(self):
+        return str(list(self))
+
+    def __repr__(self):
+        return repr(list(self))
+
+
+class Position(NamedTuple):
+    """
+    Class to point to a position in a text file.
+    """
+
+    filename: str
+    """
+    The file name.
+    """
+    line: int
+    """
+    The line number in the file.
+    """
+    column: int
+    """
+    The column number in the line.
+    """
+
+
+class Location(NamedTuple):
+    """
+    Class to point to a range in a text file.
+    """
+
+    begin: Position
+    """
+    The beginning of the range.
+    """
+    end: Position
+    """
+    The end of the range.
+    """
+
+
+def _c_location(loc: Location):
+    mema = _ffi.new("char[]", loc.begin.filename.encode())
+    memb = _ffi.new("char[]", loc.end.filename.encode())
+    return (
+        _ffi.new(
+            "clingo_location_t*",
+            (
+                mema,
+                memb,
+                loc.begin.line,
+                loc.end.line,
+                loc.begin.column,
+                loc.end.column,
+            ),
+        ),
+        mema,
+        memb,
+    )
+
+
+def _py_location(rep):
+    return Location(
+        Position(_to_str(rep.begin_file), rep.begin_line, rep.begin_column),
+        Position(_to_str(rep.end_file), rep.end_line, rep.end_column),
+    )
+
+
+_attribute_names = {
+    _to_str(_lib.g_clingo_ast_attribute_names.names[i]): i
+    for i in range(_lib.g_clingo_ast_attribute_names.size)
+}
+
+ASTValue = Union[str, int, Symbol, Location, None, "AST", StrSequence, ASTSequence]
+ASTUpdate = Union[
+    str, int, Symbol, Location, None, "AST", Sequence[str], Sequence["AST"]
+]
+
+
+@total_ordering
+class AST:
+    """
+    Represents a node in the abstract syntax tree.
+
+    The attributes of an `AST` are tied to its type. They correspond to the
+    grammar in the description of the `clingo.ast` module. `AST` nodes can be
+    constructed using one of the functions provided in this module.
+
+    Furthermore, AST nodes implement Python's rich comparison operators and are
+    ordered structurally ignoring the location. They can also be used as
+    dictionary keys. Their string representation corresponds to their gringo
+    representation. In fact, the string representation of any AST obtained from
+    `parse_files` and `parse_string` can be parsed again. Note that it is
+    possible to construct ASTs that are not parsable, though.
+    """
+
+    def __init__(self, rep):
+        super().__setattr__("_rep", rep)
+
+    def __eq__(self, other):
+        if not isinstance(other, AST):
+            return NotImplemented
+        return _lib.clingo_ast_equal(self._rep, other._rep)
+
+    def __lt__(self, other):
+        if not isinstance(other, AST):
+            return NotImplemented
+        return _lib.clingo_ast_less_than(self._rep, other._rep)
+
+    def __hash__(self):
+        return _lib.clingo_ast_hash(self._rep)
+
+    def __del__(self):
+        _lib.clingo_ast_release(self._rep)
+
+    def __getattr__(self, name):
+        attr_id = _attribute_names.get(name)
+        if attr_id is None or not _c_call(
+            "bool", _lib.clingo_ast_has_attribute, self._rep, attr_id
+        ):
+            raise AttributeError(f"no attribute: {name}")
+        attr_type = _c_call(
+            "clingo_ast_attribute_type_t",
+            _lib.clingo_ast_attribute_type,
+            self._rep,
+            attr_id,
+        )
+        if attr_type == _lib.clingo_ast_attribute_type_string:
+            return _to_str(
+                _c_call(
+                    "char*", _lib.clingo_ast_attribute_get_string, self._rep, attr_id
+                )
+            )
+        if attr_type == _lib.clingo_ast_attribute_type_number:
+            return _c_call(
+                "int", _lib.clingo_ast_attribute_get_number, self._rep, attr_id
+            )
+        if attr_type == _lib.clingo_ast_attribute_type_symbol:
+            return Symbol(
+                _c_call(
+                    "clingo_symbol_t",
+                    _lib.clingo_ast_attribute_get_symbol,
+                    self._rep,
+                    attr_id,
+                )
+            )
+        if attr_type == _lib.clingo_ast_attribute_type_location:
+            return _py_location(
+                _c_call(
+                    "clingo_location_t",
+                    _lib.clingo_ast_attribute_get_location,
+                    self._rep,
+                    attr_id,
+                )
+            )
+        if attr_type == _lib.clingo_ast_attribute_type_optional_ast:
+            rep = _c_call(
+                "clingo_ast_t*",
+                _lib.clingo_ast_attribute_get_optional_ast,
+                self._rep,
+                attr_id,
+            )
+            return AST(rep) if rep != _ffi.NULL else None
+        if attr_type == _lib.clingo_ast_attribute_type_ast:
+            return AST(
+                _c_call(
+                    "clingo_ast_t*",
+                    _lib.clingo_ast_attribute_get_ast,
+                    self._rep,
+                    attr_id,
+                )
+            )
+        if attr_type == _lib.clingo_ast_attribute_type_string_array:
+            return StrSequence(self._rep, attr_id)
+        assert attr_type == _lib.clingo_ast_attribute_type_ast_array
+        return ASTSequence(self._rep, attr_id)
+
+    def __setattr__(self, name, value):
+        attr_id = getattr(_lib, f"clingo_ast_attribute_{name}")
+        if not _c_call("bool", _lib.clingo_ast_has_attribute, self._rep, attr_id):
+            raise AttributeError(f"no attribute: {name}")
+        attr_type = _c_call(
+            "clingo_ast_attribute_type_t",
+            _lib.clingo_ast_attribute_type,
+            self._rep,
+            attr_id,
+        )
+        if attr_type == _lib.clingo_ast_attribute_type_string:
+            _handle_error(
+                _lib.clingo_ast_attribute_set_string(self._rep, attr_id, value.encode())
+            )
+        elif attr_type == _lib.clingo_ast_attribute_type_number:
+            _handle_error(
+                _lib.clingo_ast_attribute_set_number(self._rep, attr_id, value)
+            )
+        elif attr_type == _lib.clingo_ast_attribute_type_symbol:
+            _handle_error(
+                _lib.clingo_ast_attribute_set_symbol(self._rep, attr_id, value._rep)
+            )
+        elif attr_type == _lib.clingo_ast_attribute_type_location:
+            c_loc = _c_location(value)
+            _handle_error(
+                _lib.clingo_ast_attribute_set_location(self._rep, attr_id, c_loc[0])
+            )
+        elif attr_type == _lib.clingo_ast_attribute_type_optional_ast:
+            _handle_error(
+                _lib.clingo_ast_attribute_set_optional_ast(
+                    self._rep, attr_id, _ffi.NULL if value is None else value._rep
+                )
+            )
+        elif attr_type == _lib.clingo_ast_attribute_type_ast:
+            _handle_error(
+                _lib.clingo_ast_attribute_set_ast(self._rep, attr_id, value._rep)
+            )
+        elif attr_type == _lib.clingo_ast_attribute_type_string_array:
+            if isinstance(value, StrSequence):
+                if attr_id == value._attribute and self._rep == value._rep:
+                    value = list(value)
+            elif not isinstance(value, list):
+                value = list(value)
+            str_seq = StrSequence(self._rep, attr_id)
+            str_seq.clear()
+            str_seq.extend(value)
+        else:
+            assert attr_type == _lib.clingo_ast_attribute_type_ast_array
+            if isinstance(value, ASTSequence):
+                if attr_id == value._attribute and self._rep == value._rep:
+                    value = list(value)
+            elif not isinstance(value, list):
+                value = list(value)
+            ast_seq = ASTSequence(self._rep, attr_id)
+            ast_seq.clear()
+            ast_seq.extend(value)
+
+    def __str__(self):
+        return _str(
+            _lib.clingo_ast_to_string_size, _lib.clingo_ast_to_string, self._rep
+        )
+
+    def __repr__(self):
+        name = str(self.ast_type).replace("ASTType", "ast")
+        args = ", ".join(repr(x) for x in self.values())
+        return f"{name}({args})"
+
+    def __copy__(self) -> "AST":
+        """
+        Return a shallow copy of the ast.
+        """
+        return AST(_c_call("clingo_ast_t*", _lib.clingo_ast_copy, self._rep))
+
+    def __deepcopy__(self, memo) -> "AST":
+        """
+        Return a deep copy of the ast.
+        """
+        return AST(_c_call("clingo_ast_t*", _lib.clingo_ast_deep_copy, self._rep))
+
+    def update(self, **kwargs: ASTUpdate) -> "AST":
+        """
+        Return a copy of the AST also updating the given attributes.
+
+        Note that this function returns a reference to self if no arguments are
+        given.
+        """
+        if not kwargs:
+            return self
+
+        args = []
+        for key in self.keys():
+            if key in kwargs:
+                args.append(kwargs[key])
+            else:
+                args.append(getattr(self, key))
+
+        cons = globals()[str(self.ast_type).replace("ASTType.", "")]
+        return cons(*args)
+
+    def items(self) -> List[Tuple[str, ASTValue]]:
+        """
+        The list of items of the AST node.
+        """
+        return [(name, getattr(self, name)) for name in self.keys()]
+
+    def keys(self) -> List[str]:
+        """
+        The list of keys of the AST node.
+        """
+        cons = _lib.g_clingo_ast_constructors.constructors[self.ast_type.value]
+        names = _lib.g_clingo_ast_attribute_names.names
+        return [_to_str(names[cons.arguments[j].attribute]) for j in range(cons.size)]
+
+    def values(self) -> List[ASTValue]:
+        """
+        The list of values of the AST node.
+        """
+        return [(getattr(self, name)) for name in self.keys()]
+
+    @property
+    def ast_type(self) -> ASTType:
+        """
+        The type of the node.
+        """
+        return ASTType(
+            _c_call("clingo_ast_type_t", _lib.clingo_ast_get_type, self._rep)
+        )
+
+    @property
+    def child_keys(self) -> List[str]:
+        """
+        List of attribute names containing ASTs.
+        """
+        cons = _lib.g_clingo_ast_constructors.constructors[self.ast_type.value]
+        names = _lib.g_clingo_ast_attribute_names.names
+        return [
+            _to_str(names[cons.arguments[j].attribute])
+            for j in range(cons.size)
+            if cons.arguments[j].type
+            in (
+                _lib.clingo_ast_attribute_type_ast,
+                _lib.clingo_ast_attribute_type_optional_ast,
+                _lib.clingo_ast_attribute_type_ast_array,
+            )
+        ]
+
+    def unpool(self, other: bool = True, condition: bool = True) -> List["AST"]:
+        """
+        Unpool the AST returning a list of ASTs without pool terms.
+
+        Parameters
+        ----------
+        other
+            Remove all pools except those in conditions of conditional
+            literals.
+        condition
+            Only remove pools from conditions of conditional literals.
+        """
+        unpool_type = 0
+        if other:
+            unpool_type |= _lib.clingo_ast_unpool_type_other
+        if condition:
+            unpool_type |= _lib.clingo_ast_unpool_type_condition
+
+        ret: List[AST] = []
+        error = _Error()
+        cb_data = _CBData(ret.append, error)
+        c_cb_data = _ffi.new_handle(cb_data)
+        _handle_error(
+            _lib.clingo_ast_unpool(
+                self._rep, unpool_type, _lib.pyclingo_ast_callback, c_cb_data
+            )
+        )
+        return ret
+
+
+@_ffi.def_extern(onerror=_cb_error_handler("data"), name="pyclingo_ast_callback")
+def _pyclingo_ast_callback(ast, data):
+    """
+    Low-level ast callback.
+    """
+    callback = _ffi.from_handle(data).data
+    _lib.clingo_ast_acquire(ast)
+    callback(AST(ast))
+
+    return True
+
+
+def parse_files(
+    files: Sequence[str],
+    callback: Callable[[AST], None],
+    control: Optional[Control] = None,
+    logger: Optional[Logger] = None,
+    message_limit: int = 20,
+) -> None:
+    """
+    Parse the programs in the given files and return an abstract syntax tree for
+    each statement via a callback.
+
+    The function follows clingo's handling of files on the command line. Filename
+    `"-"` is treated as stdin and if an empty list is given, then the parser will
+    read from stdin.
+
+    The optional control object can be added to enable parsing of files in
+    ASPIF format. The ground statements will be added to the control object.
+
+    Parameters
+    ----------
+    files
+        List of file names.
+    callback
+        Callable taking an ast as argument.
+    control
+        Control object to add ground rules to.
+    logger
+        Function to intercept messages normally printed to standard error.
+    message_limit
+        The maximum number of messages passed to the logger.
+
+    See Also
+    --------
+    ProgramBuilder
+    """
+    c_control = control._rep if control is not None else _ffi.NULL
+
+    if logger is not None:
+        c_logger_data = _ffi.new_handle(logger)
+        c_logger = _lib.pyclingo_logger_callback
+    else:
+        c_logger_data = _ffi.NULL
+        c_logger = _ffi.NULL
+
+    error = _Error()
+    cb_data = _CBData(callback, error)
+    c_cb_data = _ffi.new_handle(cb_data)
+
+    _handle_error(
+        _lib.clingo_ast_parse_files(
+            [_ffi.new("char[]", f.encode()) for f in files],
+            len(files),
+            _lib.pyclingo_ast_callback,
+            c_cb_data,
+            c_control,
+            c_logger,
+            c_logger_data,
+            message_limit,
+        ),
+        cb_data,
+    )
+
+
+def parse_string(
+    program: str,
+    callback: Callable[[AST], None],
+    control: Optional[Control] = None,
+    logger: Optional[Logger] = None,
+    message_limit: int = 20,
+) -> None:
+    """
+    Parse the given program and return an abstract syntax tree for each
+    statement via a callback.
+
+    The optional control object can be added to enable parsing of files in
+    ASPIF format. The ground statements will be added to the control object.
+
+    Parameters
+    ----------
+    program
+        String representation of the program.
+    callback
+        Callable taking an ast as argument.
+    control
+        Control object to add ground rules to.
+    logger
+        Function to intercept messages normally printed to standard error.
+    message_limit
+        The maximum number of messages passed to the logger.
+
+    See Also
+    --------
+    ProgramBuilder
+    """
+    c_control = control._rep if control is not None else _ffi.NULL
+
+    if logger is not None:
+        c_logger_data = _ffi.new_handle(logger)
+        c_logger = _lib.pyclingo_logger_callback
+    else:
+        c_logger_data = _ffi.NULL
+        c_logger = _ffi.NULL
+
+    error = _Error()
+    cb_data = _CBData(callback, error)
+    c_cb_data = _ffi.new_handle(cb_data)
+
+    _handle_error(
+        _lib.clingo_ast_parse_string(
+            program.encode(),
+            _lib.pyclingo_ast_callback,
+            c_cb_data,
+            c_control,
+            c_logger,
+            c_logger_data,
+            message_limit,
+        ),
+        cb_data,
+    )
+
+
+class ProgramBuilder(ContextManager["ProgramBuilder"]):
+    """
+    Object to build non-ground programs.
+
+    Parameters
+    ----------
+    control
+        The `clingo.control.Control` object to attach the builder to.
+
+    See Also
+    --------
+    parse_string, parse_files
+
+    Notes
+    -----
+    This class is a context manager and must be used with Python's `with`
+    statement.
+    """
+
+    def __init__(self, control: Control):
+        self._rep = _c_call(
+            "clingo_program_builder_t*", _lib.clingo_program_builder_init, control._rep
+        )
+
+    def __enter__(self):
+        _handle_error(_lib.clingo_program_builder_begin(self._rep))
+        return self
+
+    def __exit__(self, exc_type, exc_val, exc_tb):
+        _handle_error(_lib.clingo_program_builder_end(self._rep))
+        return False
+
+    def add(self, statement: AST) -> None:
+        """
+        Adds a statement in form of an `AST` node to the program.
+
+        Parameters
+        ----------
+        statement
+            The statement to add.
+        """
+        _handle_error(_lib.clingo_program_builder_add(self._rep, statement._rep))
+
+
+class Transformer:
+    """
+    Utility class to transform ASTs.
+
+    Classes should inherit from this class and implement functions with name
+    `visit_<ast_type>` where `<ast_type>` is the type of the ASTs to visit and
+    modify. Such a function should return an updated AST or the same AST if no
+    change is necessary. The transformer will take care to copy all parent ASTs
+    involving a modified child. Note that the class works like a visitor if
+    only self references are returned from such functions.
+
+    Any extra arguments passed to the visit method are passed on to child ASTs.
+    """
+
+    def visit(self, ast: AST, *args: Any, **kwargs: Any) -> AST:
+        """
+        Dispatch to a visit method in a base class or visit and transform the
+        children of the given AST if it is missing.
+        """
+        attr = "visit_" + str(ast.ast_type).replace("ASTType.", "")
+        if hasattr(self, attr):
+            return getattr(self, attr)(ast, *args, **kwargs)
+        return ast.update(**self.visit_children(ast, *args, **kwargs))
+
+    def visit_children(
+        self, ast: AST, *args: Any, **kwargs: Any
+    ) -> Dict[str, ASTUpdate]:
+        """
+        Visit and transform the children of the given AST.
+
+        Returns
+        -------
+        The functions returns a dictionary that can be passed to `AST.update`.
+        It contains the attributes and values that have been transformed.
+        """
+        update: Dict[str, ASTUpdate] = dict()
+        for key in ast.child_keys:
+            old = getattr(ast, key)
+            new = self._dispatch(old, *args, **kwargs)
+            if new is not old:
+                update[key] = new
+        return update
+
+    def visit_sequence(
+        self, sequence: ASTSequence, *args: Any, **kwargs: Any
+    ) -> MutableSequence[AST]:
+        """
+        Transform a sequence of ASTs returning the same sequnce if there are no
+        changes or a list of ASTs otherwise.
+        """
+        ret: MutableSequence[AST]
+        ret, lst = sequence, []
+        for old in sequence:
+            lst.append(self(old, *args, **kwargs))
+            if lst[-1] is not old:
+                ret = lst
+        return ret
+
+    def _dispatch(
+        self, ast: Union[None, AST, ASTSequence], *args: Any, **kwargs: Any
+    ) -> Union[None, AST, MutableSequence[AST]]:
+        """
+        Visit and transform an (optional) AST or a sequence of ASTs.
+        """
+        if ast is None:
+            return ast
+
+        if isinstance(ast, AST):
+            return self.visit(ast, *args, **kwargs)  # type: ignore
+
+        if isinstance(ast, abc.Sequence):
+            return self.visit_sequence(ast, *args, **kwargs)
+
+        raise TypeError("unexpected type")
+
+    def __call__(self, ast: AST, *args: Any, **kwargs: Any) -> AST:
+        """
+        Alternative way to call `Transformer.visit`.
+        """
+        return self.visit(ast, *args, **kwargs)
+
+
+def Id(location: Location, name: str) -> AST:
+    """
+    Construct an AST node of type `ASTType.Id`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_id,
+            p_ast,
+            c_location[0],
+            _ffi.new("char const[]", name.encode()),
+        )
+    )
+    return AST(p_ast[0])
+
+
+def Variable(location: Location, name: str) -> AST:
+    """
+    Construct an AST node of type `ASTType.Variable`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_variable,
+            p_ast,
+            c_location[0],
+            _ffi.new("char const[]", name.encode()),
+        )
+    )
+    return AST(p_ast[0])
+
+
+def SymbolicTerm(location: Location, symbol: Symbol) -> AST:
+    """
+    Construct an AST node of type `ASTType.SymbolicTerm`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_symbolic_term,
+            p_ast,
+            c_location[0],
+            _ffi.cast("clingo_symbol_t", symbol._rep),
+        )
+    )
+    return AST(p_ast[0])
+
+
+def UnaryOperation(location: Location, operator_type: int, argument: AST) -> AST:
+    """
+    Construct an AST node of type `ASTType.UnaryOperation`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_unary_operation,
+            p_ast,
+            c_location[0],
+            _ffi.cast("int", operator_type),
+            argument._rep,
+        )
+    )
+    return AST(p_ast[0])
+
+
+def BinaryOperation(
+    location: Location, operator_type: int, left: AST, right: AST
+) -> AST:
+    """
+    Construct an AST node of type `ASTType.BinaryOperation`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_binary_operation,
+            p_ast,
+            c_location[0],
+            _ffi.cast("int", operator_type),
+            left._rep,
+            right._rep,
+        )
+    )
+    return AST(p_ast[0])
+
+
+def Interval(location: Location, left: AST, right: AST) -> AST:
+    """
+    Construct an AST node of type `ASTType.Interval`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_interval, p_ast, c_location[0], left._rep, right._rep
+        )
+    )
+    return AST(p_ast[0])
+
+
+def Function(
+    location: Location, name: str, arguments: Sequence[AST], external: int
+) -> AST:
+    """
+    Construct an AST node of type `ASTType.Function`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_function,
+            p_ast,
+            c_location[0],
+            _ffi.new("char const[]", name.encode()),
+            _ffi.new("clingo_ast_t*[]", [x._rep for x in arguments]),
+            _ffi.cast("size_t", len(arguments)),
+            _ffi.cast("int", external),
+        )
+    )
+    return AST(p_ast[0])
+
+
+def Pool(location: Location, arguments: Sequence[AST]) -> AST:
+    """
+    Construct an AST node of type `ASTType.Pool`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_pool,
+            p_ast,
+            c_location[0],
+            _ffi.new("clingo_ast_t*[]", [x._rep for x in arguments]),
+            _ffi.cast("size_t", len(arguments)),
+        )
+    )
+    return AST(p_ast[0])
+
+
+def BooleanConstant(value: int) -> AST:
+    """
+    Construct an AST node of type `ASTType.BooleanConstant`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_boolean_constant, p_ast, _ffi.cast("int", value)
+        )
+    )
+    return AST(p_ast[0])
+
+
+def SymbolicAtom(symbol: AST) -> AST:
+    """
+    Construct an AST node of type `ASTType.SymbolicAtom`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    _handle_error(
+        _lib.clingo_ast_build(_lib.clingo_ast_type_symbolic_atom, p_ast, symbol._rep)
+    )
+    return AST(p_ast[0])
+
+
+def Comparison(term: AST, guards: Sequence[AST]) -> AST:
+    """
+    Construct an AST node of type `ASTType.Comparison`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_comparison,
+            p_ast,
+            term._rep,
+            _ffi.new("clingo_ast_t*[]", [x._rep for x in guards]),
+            _ffi.cast("size_t", len(guards)),
+        )
+    )
+    return AST(p_ast[0])
+
+
+def Guard(comparison: int, term: AST) -> AST:
+    """
+    Construct an AST node of type `ASTType.Guard`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_guard, p_ast, _ffi.cast("int", comparison), term._rep
+        )
+    )
+    return AST(p_ast[0])
+
+
+def ConditionalLiteral(
+    location: Location, literal: AST, condition: Sequence[AST]
+) -> AST:
+    """
+    Construct an AST node of type `ASTType.ConditionalLiteral`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_conditional_literal,
+            p_ast,
+            c_location[0],
+            literal._rep,
+            _ffi.new("clingo_ast_t*[]", [x._rep for x in condition]),
+            _ffi.cast("size_t", len(condition)),
+        )
+    )
+    return AST(p_ast[0])
+
+
+def Aggregate(
+    location: Location,
+    left_guard: Optional[AST],
+    elements: Sequence[AST],
+    right_guard: Optional[AST],
+) -> AST:
+    """
+    Construct an AST node of type `ASTType.Aggregate`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_aggregate,
+            p_ast,
+            c_location[0],
+            _ffi.NULL if left_guard is None else left_guard._rep,
+            _ffi.new("clingo_ast_t*[]", [x._rep for x in elements]),
+            _ffi.cast("size_t", len(elements)),
+            _ffi.NULL if right_guard is None else right_guard._rep,
+        )
+    )
+    return AST(p_ast[0])
+
+
+def BodyAggregateElement(terms: Sequence[AST], condition: Sequence[AST]) -> AST:
+    """
+    Construct an AST node of type `ASTType.BodyAggregateElement`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_body_aggregate_element,
+            p_ast,
+            _ffi.new("clingo_ast_t*[]", [x._rep for x in terms]),
+            _ffi.cast("size_t", len(terms)),
+            _ffi.new("clingo_ast_t*[]", [x._rep for x in condition]),
+            _ffi.cast("size_t", len(condition)),
+        )
+    )
+    return AST(p_ast[0])
+
+
+def BodyAggregate(
+    location: Location,
+    left_guard: Optional[AST],
+    function: int,
+    elements: Sequence[AST],
+    right_guard: Optional[AST],
+) -> AST:
+    """
+    Construct an AST node of type `ASTType.BodyAggregate`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_body_aggregate,
+            p_ast,
+            c_location[0],
+            _ffi.NULL if left_guard is None else left_guard._rep,
+            _ffi.cast("int", function),
+            _ffi.new("clingo_ast_t*[]", [x._rep for x in elements]),
+            _ffi.cast("size_t", len(elements)),
+            _ffi.NULL if right_guard is None else right_guard._rep,
+        )
+    )
+    return AST(p_ast[0])
+
+
+def HeadAggregateElement(terms: Sequence[AST], condition: AST) -> AST:
+    """
+    Construct an AST node of type `ASTType.HeadAggregateElement`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_head_aggregate_element,
+            p_ast,
+            _ffi.new("clingo_ast_t*[]", [x._rep for x in terms]),
+            _ffi.cast("size_t", len(terms)),
+            condition._rep,
+        )
+    )
+    return AST(p_ast[0])
+
+
+def HeadAggregate(
+    location: Location,
+    left_guard: Optional[AST],
+    function: int,
+    elements: Sequence[AST],
+    right_guard: Optional[AST],
+) -> AST:
+    """
+    Construct an AST node of type `ASTType.HeadAggregate`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_head_aggregate,
+            p_ast,
+            c_location[0],
+            _ffi.NULL if left_guard is None else left_guard._rep,
+            _ffi.cast("int", function),
+            _ffi.new("clingo_ast_t*[]", [x._rep for x in elements]),
+            _ffi.cast("size_t", len(elements)),
+            _ffi.NULL if right_guard is None else right_guard._rep,
+        )
+    )
+    return AST(p_ast[0])
+
+
+def Disjunction(location: Location, elements: Sequence[AST]) -> AST:
+    """
+    Construct an AST node of type `ASTType.Disjunction`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_disjunction,
+            p_ast,
+            c_location[0],
+            _ffi.new("clingo_ast_t*[]", [x._rep for x in elements]),
+            _ffi.cast("size_t", len(elements)),
+        )
+    )
+    return AST(p_ast[0])
+
+
+def TheorySequence(location: Location, sequence_type: int, terms: Sequence[AST]) -> AST:
+    """
+    Construct an AST node of type `ASTType.TheorySequence`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_theory_sequence,
+            p_ast,
+            c_location[0],
+            _ffi.cast("int", sequence_type),
+            _ffi.new("clingo_ast_t*[]", [x._rep for x in terms]),
+            _ffi.cast("size_t", len(terms)),
+        )
+    )
+    return AST(p_ast[0])
+
+
+def TheoryFunction(location: Location, name: str, arguments: Sequence[AST]) -> AST:
+    """
+    Construct an AST node of type `ASTType.TheoryFunction`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_theory_function,
+            p_ast,
+            c_location[0],
+            _ffi.new("char const[]", name.encode()),
+            _ffi.new("clingo_ast_t*[]", [x._rep for x in arguments]),
+            _ffi.cast("size_t", len(arguments)),
+        )
+    )
+    return AST(p_ast[0])
+
+
+def TheoryUnparsedTermElement(operators: Sequence[str], term: AST) -> AST:
+    """
+    Construct an AST node of type `ASTType.TheoryUnparsedTermElement`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_operators = [_ffi.new("char[]", x.encode()) for x in operators]
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_theory_unparsed_term_element,
+            p_ast,
+            _ffi.new("char*[]", c_operators),
+            _ffi.cast("size_t", len(operators)),
+            term._rep,
+        )
+    )
+    return AST(p_ast[0])
+
+
+def TheoryUnparsedTerm(location: Location, elements: Sequence[AST]) -> AST:
+    """
+    Construct an AST node of type `ASTType.TheoryUnparsedTerm`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_theory_unparsed_term,
+            p_ast,
+            c_location[0],
+            _ffi.new("clingo_ast_t*[]", [x._rep for x in elements]),
+            _ffi.cast("size_t", len(elements)),
+        )
+    )
+    return AST(p_ast[0])
+
+
+def TheoryGuard(operator_name: str, term: AST) -> AST:
+    """
+    Construct an AST node of type `ASTType.TheoryGuard`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_theory_guard,
+            p_ast,
+            _ffi.new("char const[]", operator_name.encode()),
+            term._rep,
+        )
+    )
+    return AST(p_ast[0])
+
+
+def TheoryAtomElement(terms: Sequence[AST], condition: Sequence[AST]) -> AST:
+    """
+    Construct an AST node of type `ASTType.TheoryAtomElement`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_theory_atom_element,
+            p_ast,
+            _ffi.new("clingo_ast_t*[]", [x._rep for x in terms]),
+            _ffi.cast("size_t", len(terms)),
+            _ffi.new("clingo_ast_t*[]", [x._rep for x in condition]),
+            _ffi.cast("size_t", len(condition)),
+        )
+    )
+    return AST(p_ast[0])
+
+
+def TheoryAtom(
+    location: Location, term: AST, elements: Sequence[AST], guard: Optional[AST]
+) -> AST:
+    """
+    Construct an AST node of type `ASTType.TheoryAtom`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_theory_atom,
+            p_ast,
+            c_location[0],
+            term._rep,
+            _ffi.new("clingo_ast_t*[]", [x._rep for x in elements]),
+            _ffi.cast("size_t", len(elements)),
+            _ffi.NULL if guard is None else guard._rep,
+        )
+    )
+    return AST(p_ast[0])
+
+
+def Literal(location: Location, sign: int, atom: AST) -> AST:
+    """
+    Construct an AST node of type `ASTType.Literal`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_literal,
+            p_ast,
+            c_location[0],
+            _ffi.cast("int", sign),
+            atom._rep,
+        )
+    )
+    return AST(p_ast[0])
+
+
+def TheoryOperatorDefinition(
+    location: Location, name: str, priority: int, operator_type: int
+) -> AST:
+    """
+    Construct an AST node of type `ASTType.TheoryOperatorDefinition`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_theory_operator_definition,
+            p_ast,
+            c_location[0],
+            _ffi.new("char const[]", name.encode()),
+            _ffi.cast("int", priority),
+            _ffi.cast("int", operator_type),
+        )
+    )
+    return AST(p_ast[0])
+
+
+def TheoryTermDefinition(
+    location: Location, name: str, operators: Sequence[AST]
+) -> AST:
+    """
+    Construct an AST node of type `ASTType.TheoryTermDefinition`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_theory_term_definition,
+            p_ast,
+            c_location[0],
+            _ffi.new("char const[]", name.encode()),
+            _ffi.new("clingo_ast_t*[]", [x._rep for x in operators]),
+            _ffi.cast("size_t", len(operators)),
+        )
+    )
+    return AST(p_ast[0])
+
+
+def TheoryGuardDefinition(operators: Sequence[str], term: str) -> AST:
+    """
+    Construct an AST node of type `ASTType.TheoryGuardDefinition`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_operators = [_ffi.new("char[]", x.encode()) for x in operators]
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_theory_guard_definition,
+            p_ast,
+            _ffi.new("char*[]", c_operators),
+            _ffi.cast("size_t", len(operators)),
+            _ffi.new("char const[]", term.encode()),
+        )
+    )
+    return AST(p_ast[0])
+
+
+def TheoryAtomDefinition(
+    location: Location,
+    atom_type: int,
+    name: str,
+    arity: int,
+    term: str,
+    guard: Optional[AST],
+) -> AST:
+    """
+    Construct an AST node of type `ASTType.TheoryAtomDefinition`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_theory_atom_definition,
+            p_ast,
+            c_location[0],
+            _ffi.cast("int", atom_type),
+            _ffi.new("char const[]", name.encode()),
+            _ffi.cast("int", arity),
+            _ffi.new("char const[]", term.encode()),
+            _ffi.NULL if guard is None else guard._rep,
+        )
+    )
+    return AST(p_ast[0])
+
+
+def Rule(location: Location, head: AST, body: Sequence[AST]) -> AST:
+    """
+    Construct an AST node of type `ASTType.Rule`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_rule,
+            p_ast,
+            c_location[0],
+            head._rep,
+            _ffi.new("clingo_ast_t*[]", [x._rep for x in body]),
+            _ffi.cast("size_t", len(body)),
+        )
+    )
+    return AST(p_ast[0])
+
+
+def Definition(location: Location, name: str, value: AST, is_default: int) -> AST:
+    """
+    Construct an AST node of type `ASTType.Definition`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_definition,
+            p_ast,
+            c_location[0],
+            _ffi.new("char const[]", name.encode()),
+            value._rep,
+            _ffi.cast("int", is_default),
+        )
+    )
+    return AST(p_ast[0])
+
+
+def ShowSignature(location: Location, name: str, arity: int, positive: int) -> AST:
+    """
+    Construct an AST node of type `ASTType.ShowSignature`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_show_signature,
+            p_ast,
+            c_location[0],
+            _ffi.new("char const[]", name.encode()),
+            _ffi.cast("int", arity),
+            _ffi.cast("int", positive),
+        )
+    )
+    return AST(p_ast[0])
+
+
+def ShowTerm(location: Location, term: AST, body: Sequence[AST]) -> AST:
+    """
+    Construct an AST node of type `ASTType.ShowTerm`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_show_term,
+            p_ast,
+            c_location[0],
+            term._rep,
+            _ffi.new("clingo_ast_t*[]", [x._rep for x in body]),
+            _ffi.cast("size_t", len(body)),
+        )
+    )
+    return AST(p_ast[0])
+
+
+def Minimize(
+    location: Location,
+    weight: AST,
+    priority: AST,
+    terms: Sequence[AST],
+    body: Sequence[AST],
+) -> AST:
+    """
+    Construct an AST node of type `ASTType.Minimize`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_minimize,
+            p_ast,
+            c_location[0],
+            weight._rep,
+            priority._rep,
+            _ffi.new("clingo_ast_t*[]", [x._rep for x in terms]),
+            _ffi.cast("size_t", len(terms)),
+            _ffi.new("clingo_ast_t*[]", [x._rep for x in body]),
+            _ffi.cast("size_t", len(body)),
+        )
+    )
+    return AST(p_ast[0])
+
+
+def Script(location: Location, name: str, code: str) -> AST:
+    """
+    Construct an AST node of type `ASTType.Script`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_script,
+            p_ast,
+            c_location[0],
+            _ffi.new("char const[]", name.encode()),
+            _ffi.new("char const[]", code.encode()),
+        )
+    )
+    return AST(p_ast[0])
+
+
+def Program(location: Location, name: str, parameters: Sequence[AST]) -> AST:
+    """
+    Construct an AST node of type `ASTType.Program`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_program,
+            p_ast,
+            c_location[0],
+            _ffi.new("char const[]", name.encode()),
+            _ffi.new("clingo_ast_t*[]", [x._rep for x in parameters]),
+            _ffi.cast("size_t", len(parameters)),
+        )
+    )
+    return AST(p_ast[0])
+
+
+def External(
+    location: Location, atom: AST, body: Sequence[AST], external_type: AST
+) -> AST:
+    """
+    Construct an AST node of type `ASTType.External`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_external,
+            p_ast,
+            c_location[0],
+            atom._rep,
+            _ffi.new("clingo_ast_t*[]", [x._rep for x in body]),
+            _ffi.cast("size_t", len(body)),
+            external_type._rep,
+        )
+    )
+    return AST(p_ast[0])
+
+
+def Edge(location: Location, node_u: AST, node_v: AST, body: Sequence[AST]) -> AST:
+    """
+    Construct an AST node of type `ASTType.Edge`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_edge,
+            p_ast,
+            c_location[0],
+            node_u._rep,
+            node_v._rep,
+            _ffi.new("clingo_ast_t*[]", [x._rep for x in body]),
+            _ffi.cast("size_t", len(body)),
+        )
+    )
+    return AST(p_ast[0])
+
+
+def Heuristic(
+    location: Location,
+    atom: AST,
+    body: Sequence[AST],
+    bias: AST,
+    priority: AST,
+    modifier: AST,
+) -> AST:
+    """
+    Construct an AST node of type `ASTType.Heuristic`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_heuristic,
+            p_ast,
+            c_location[0],
+            atom._rep,
+            _ffi.new("clingo_ast_t*[]", [x._rep for x in body]),
+            _ffi.cast("size_t", len(body)),
+            bias._rep,
+            priority._rep,
+            modifier._rep,
+        )
+    )
+    return AST(p_ast[0])
+
+
+def ProjectAtom(location: Location, atom: AST, body: Sequence[AST]) -> AST:
+    """
+    Construct an AST node of type `ASTType.ProjectAtom`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_project_atom,
+            p_ast,
+            c_location[0],
+            atom._rep,
+            _ffi.new("clingo_ast_t*[]", [x._rep for x in body]),
+            _ffi.cast("size_t", len(body)),
+        )
+    )
+    return AST(p_ast[0])
+
+
+def ProjectSignature(location: Location, name: str, arity: int, positive: int) -> AST:
+    """
+    Construct an AST node of type `ASTType.ProjectSignature`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_project_signature,
+            p_ast,
+            c_location[0],
+            _ffi.new("char const[]", name.encode()),
+            _ffi.cast("int", arity),
+            _ffi.cast("int", positive),
+        )
+    )
+    return AST(p_ast[0])
+
+
+def Defined(location: Location, name: str, arity: int, positive: int) -> AST:
+    """
+    Construct an AST node of type `ASTType.Defined`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_defined,
+            p_ast,
+            c_location[0],
+            _ffi.new("char const[]", name.encode()),
+            _ffi.cast("int", arity),
+            _ffi.cast("int", positive),
+        )
+    )
+    return AST(p_ast[0])
+
+
+def TheoryDefinition(
+    location: Location, name: str, terms: Sequence[AST], atoms: Sequence[AST]
+) -> AST:
+    """
+    Construct an AST node of type `ASTType.TheoryDefinition`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_theory_definition,
+            p_ast,
+            c_location[0],
+            _ffi.new("char const[]", name.encode()),
+            _ffi.new("clingo_ast_t*[]", [x._rep for x in terms]),
+            _ffi.cast("size_t", len(terms)),
+            _ffi.new("clingo_ast_t*[]", [x._rep for x in atoms]),
+            _ffi.cast("size_t", len(atoms)),
+        )
+    )
+    return AST(p_ast[0])
+
+
+def Comment(location: Location, value: str, comment_type: int) -> AST:
+    """
+    Construct an AST node of type `ASTType.Comment`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_comment,
+            p_ast,
+            c_location[0],
+            _ffi.new("char const[]", value.encode()),
+            _ffi.cast("int", comment_type),
+        )
+    )
+    return AST(p_ast[0])
+
+
+
+
+
+
+
+

Functions

+
+
+def Aggregate(location: Location, left_guard: Optional[AST], elements: Sequence[AST], right_guard: Optional[AST]) ‑> AST +
+
+

Construct an AST node of type ASTType.Aggregate.

+
+ +Expand source code + +
def Aggregate(
+    location: Location,
+    left_guard: Optional[AST],
+    elements: Sequence[AST],
+    right_guard: Optional[AST],
+) -> AST:
+    """
+    Construct an AST node of type `ASTType.Aggregate`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_aggregate,
+            p_ast,
+            c_location[0],
+            _ffi.NULL if left_guard is None else left_guard._rep,
+            _ffi.new("clingo_ast_t*[]", [x._rep for x in elements]),
+            _ffi.cast("size_t", len(elements)),
+            _ffi.NULL if right_guard is None else right_guard._rep,
+        )
+    )
+    return AST(p_ast[0])
+
+
+
+def BinaryOperation(location: Location, operator_type: int, left: AST, right: AST) ‑> AST +
+
+

Construct an AST node of type ASTType.BinaryOperation.

+
+ +Expand source code + +
def BinaryOperation(
+    location: Location, operator_type: int, left: AST, right: AST
+) -> AST:
+    """
+    Construct an AST node of type `ASTType.BinaryOperation`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_binary_operation,
+            p_ast,
+            c_location[0],
+            _ffi.cast("int", operator_type),
+            left._rep,
+            right._rep,
+        )
+    )
+    return AST(p_ast[0])
+
+
+
+def BodyAggregate(location: Location, left_guard: Optional[AST], function: int, elements: Sequence[AST], right_guard: Optional[AST]) ‑> AST +
+
+

Construct an AST node of type ASTType.BodyAggregate.

+
+ +Expand source code + +
def BodyAggregate(
+    location: Location,
+    left_guard: Optional[AST],
+    function: int,
+    elements: Sequence[AST],
+    right_guard: Optional[AST],
+) -> AST:
+    """
+    Construct an AST node of type `ASTType.BodyAggregate`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_body_aggregate,
+            p_ast,
+            c_location[0],
+            _ffi.NULL if left_guard is None else left_guard._rep,
+            _ffi.cast("int", function),
+            _ffi.new("clingo_ast_t*[]", [x._rep for x in elements]),
+            _ffi.cast("size_t", len(elements)),
+            _ffi.NULL if right_guard is None else right_guard._rep,
+        )
+    )
+    return AST(p_ast[0])
+
+
+
+def BodyAggregateElement(terms: Sequence[AST], condition: Sequence[AST]) ‑> AST +
+
+

Construct an AST node of type ASTType.BodyAggregateElement.

+
+ +Expand source code + +
def BodyAggregateElement(terms: Sequence[AST], condition: Sequence[AST]) -> AST:
+    """
+    Construct an AST node of type `ASTType.BodyAggregateElement`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_body_aggregate_element,
+            p_ast,
+            _ffi.new("clingo_ast_t*[]", [x._rep for x in terms]),
+            _ffi.cast("size_t", len(terms)),
+            _ffi.new("clingo_ast_t*[]", [x._rep for x in condition]),
+            _ffi.cast("size_t", len(condition)),
+        )
+    )
+    return AST(p_ast[0])
+
+
+
+def BooleanConstant(value: int) ‑> AST +
+
+

Construct an AST node of type ASTType.BooleanConstant.

+
+ +Expand source code + +
def BooleanConstant(value: int) -> AST:
+    """
+    Construct an AST node of type `ASTType.BooleanConstant`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_boolean_constant, p_ast, _ffi.cast("int", value)
+        )
+    )
+    return AST(p_ast[0])
+
+
+
+def Comment(location: Location, value: str, comment_type: int) ‑> AST +
+
+

Construct an AST node of type ASTType.Comment.

+
+ +Expand source code + +
def Comment(location: Location, value: str, comment_type: int) -> AST:
+    """
+    Construct an AST node of type `ASTType.Comment`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_comment,
+            p_ast,
+            c_location[0],
+            _ffi.new("char const[]", value.encode()),
+            _ffi.cast("int", comment_type),
+        )
+    )
+    return AST(p_ast[0])
+
+
+
+def Comparison(term: AST, guards: Sequence[AST]) ‑> AST +
+
+

Construct an AST node of type ASTType.Comparison.

+
+ +Expand source code + +
def Comparison(term: AST, guards: Sequence[AST]) -> AST:
+    """
+    Construct an AST node of type `ASTType.Comparison`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_comparison,
+            p_ast,
+            term._rep,
+            _ffi.new("clingo_ast_t*[]", [x._rep for x in guards]),
+            _ffi.cast("size_t", len(guards)),
+        )
+    )
+    return AST(p_ast[0])
+
+
+
+def ConditionalLiteral(location: Location, literal: AST, condition: Sequence[AST]) ‑> AST +
+
+

Construct an AST node of type ASTType.ConditionalLiteral.

+
+ +Expand source code + +
def ConditionalLiteral(
+    location: Location, literal: AST, condition: Sequence[AST]
+) -> AST:
+    """
+    Construct an AST node of type `ASTType.ConditionalLiteral`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_conditional_literal,
+            p_ast,
+            c_location[0],
+            literal._rep,
+            _ffi.new("clingo_ast_t*[]", [x._rep for x in condition]),
+            _ffi.cast("size_t", len(condition)),
+        )
+    )
+    return AST(p_ast[0])
+
+
+
+def Defined(location: Location, name: str, arity: int, positive: int) ‑> AST +
+
+

Construct an AST node of type ASTType.Defined.

+
+ +Expand source code + +
def Defined(location: Location, name: str, arity: int, positive: int) -> AST:
+    """
+    Construct an AST node of type `ASTType.Defined`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_defined,
+            p_ast,
+            c_location[0],
+            _ffi.new("char const[]", name.encode()),
+            _ffi.cast("int", arity),
+            _ffi.cast("int", positive),
+        )
+    )
+    return AST(p_ast[0])
+
+
+
+def Definition(location: Location, name: str, value: AST, is_default: int) ‑> AST +
+
+

Construct an AST node of type ASTType.Definition.

+
+ +Expand source code + +
def Definition(location: Location, name: str, value: AST, is_default: int) -> AST:
+    """
+    Construct an AST node of type `ASTType.Definition`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_definition,
+            p_ast,
+            c_location[0],
+            _ffi.new("char const[]", name.encode()),
+            value._rep,
+            _ffi.cast("int", is_default),
+        )
+    )
+    return AST(p_ast[0])
+
+
+
+def Disjunction(location: Location, elements: Sequence[AST]) ‑> AST +
+
+

Construct an AST node of type ASTType.Disjunction.

+
+ +Expand source code + +
def Disjunction(location: Location, elements: Sequence[AST]) -> AST:
+    """
+    Construct an AST node of type `ASTType.Disjunction`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_disjunction,
+            p_ast,
+            c_location[0],
+            _ffi.new("clingo_ast_t*[]", [x._rep for x in elements]),
+            _ffi.cast("size_t", len(elements)),
+        )
+    )
+    return AST(p_ast[0])
+
+
+
+def Edge(location: Location, node_u: AST, node_v: AST, body: Sequence[AST]) ‑> AST +
+
+

Construct an AST node of type ASTType.Edge.

+
+ +Expand source code + +
def Edge(location: Location, node_u: AST, node_v: AST, body: Sequence[AST]) -> AST:
+    """
+    Construct an AST node of type `ASTType.Edge`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_edge,
+            p_ast,
+            c_location[0],
+            node_u._rep,
+            node_v._rep,
+            _ffi.new("clingo_ast_t*[]", [x._rep for x in body]),
+            _ffi.cast("size_t", len(body)),
+        )
+    )
+    return AST(p_ast[0])
+
+
+
+def External(location: Location, atom: AST, body: Sequence[AST], external_type: AST) ‑> AST +
+
+

Construct an AST node of type ASTType.External.

+
+ +Expand source code + +
def External(
+    location: Location, atom: AST, body: Sequence[AST], external_type: AST
+) -> AST:
+    """
+    Construct an AST node of type `ASTType.External`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_external,
+            p_ast,
+            c_location[0],
+            atom._rep,
+            _ffi.new("clingo_ast_t*[]", [x._rep for x in body]),
+            _ffi.cast("size_t", len(body)),
+            external_type._rep,
+        )
+    )
+    return AST(p_ast[0])
+
+
+
+def Function(location: Location, name: str, arguments: Sequence[AST], external: int) ‑> AST +
+
+

Construct an AST node of type ASTType.Function.

+
+ +Expand source code + +
def Function(
+    location: Location, name: str, arguments: Sequence[AST], external: int
+) -> AST:
+    """
+    Construct an AST node of type `ASTType.Function`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_function,
+            p_ast,
+            c_location[0],
+            _ffi.new("char const[]", name.encode()),
+            _ffi.new("clingo_ast_t*[]", [x._rep for x in arguments]),
+            _ffi.cast("size_t", len(arguments)),
+            _ffi.cast("int", external),
+        )
+    )
+    return AST(p_ast[0])
+
+
+
+def Guard(comparison: int, term: AST) ‑> AST +
+
+

Construct an AST node of type ASTType.Guard.

+
+ +Expand source code + +
def Guard(comparison: int, term: AST) -> AST:
+    """
+    Construct an AST node of type `ASTType.Guard`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_guard, p_ast, _ffi.cast("int", comparison), term._rep
+        )
+    )
+    return AST(p_ast[0])
+
+
+
+def HeadAggregate(location: Location, left_guard: Optional[AST], function: int, elements: Sequence[AST], right_guard: Optional[AST]) ‑> AST +
+
+

Construct an AST node of type ASTType.HeadAggregate.

+
+ +Expand source code + +
def HeadAggregate(
+    location: Location,
+    left_guard: Optional[AST],
+    function: int,
+    elements: Sequence[AST],
+    right_guard: Optional[AST],
+) -> AST:
+    """
+    Construct an AST node of type `ASTType.HeadAggregate`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_head_aggregate,
+            p_ast,
+            c_location[0],
+            _ffi.NULL if left_guard is None else left_guard._rep,
+            _ffi.cast("int", function),
+            _ffi.new("clingo_ast_t*[]", [x._rep for x in elements]),
+            _ffi.cast("size_t", len(elements)),
+            _ffi.NULL if right_guard is None else right_guard._rep,
+        )
+    )
+    return AST(p_ast[0])
+
+
+
+def HeadAggregateElement(terms: Sequence[AST], condition: AST) ‑> AST +
+
+

Construct an AST node of type ASTType.HeadAggregateElement.

+
+ +Expand source code + +
def HeadAggregateElement(terms: Sequence[AST], condition: AST) -> AST:
+    """
+    Construct an AST node of type `ASTType.HeadAggregateElement`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_head_aggregate_element,
+            p_ast,
+            _ffi.new("clingo_ast_t*[]", [x._rep for x in terms]),
+            _ffi.cast("size_t", len(terms)),
+            condition._rep,
+        )
+    )
+    return AST(p_ast[0])
+
+
+
+def Heuristic(location: Location, atom: AST, body: Sequence[AST], bias: AST, priority: AST, modifier: AST) ‑> AST +
+
+

Construct an AST node of type ASTType.Heuristic.

+
+ +Expand source code + +
def Heuristic(
+    location: Location,
+    atom: AST,
+    body: Sequence[AST],
+    bias: AST,
+    priority: AST,
+    modifier: AST,
+) -> AST:
+    """
+    Construct an AST node of type `ASTType.Heuristic`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_heuristic,
+            p_ast,
+            c_location[0],
+            atom._rep,
+            _ffi.new("clingo_ast_t*[]", [x._rep for x in body]),
+            _ffi.cast("size_t", len(body)),
+            bias._rep,
+            priority._rep,
+            modifier._rep,
+        )
+    )
+    return AST(p_ast[0])
+
+
+
+def Id(location: Location, name: str) ‑> AST +
+
+

Construct an AST node of type ASTType.Id.

+
+ +Expand source code + +
def Id(location: Location, name: str) -> AST:
+    """
+    Construct an AST node of type `ASTType.Id`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_id,
+            p_ast,
+            c_location[0],
+            _ffi.new("char const[]", name.encode()),
+        )
+    )
+    return AST(p_ast[0])
+
+
+
+def Interval(location: Location, left: AST, right: AST) ‑> AST +
+
+

Construct an AST node of type ASTType.Interval.

+
+ +Expand source code + +
def Interval(location: Location, left: AST, right: AST) -> AST:
+    """
+    Construct an AST node of type `ASTType.Interval`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_interval, p_ast, c_location[0], left._rep, right._rep
+        )
+    )
+    return AST(p_ast[0])
+
+
+
+def Literal(location: Location, sign: int, atom: AST) ‑> AST +
+
+

Construct an AST node of type ASTType.Literal.

+
+ +Expand source code + +
def Literal(location: Location, sign: int, atom: AST) -> AST:
+    """
+    Construct an AST node of type `ASTType.Literal`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_literal,
+            p_ast,
+            c_location[0],
+            _ffi.cast("int", sign),
+            atom._rep,
+        )
+    )
+    return AST(p_ast[0])
+
+
+
+def Minimize(location: Location, weight: AST, priority: AST, terms: Sequence[AST], body: Sequence[AST]) ‑> AST +
+
+

Construct an AST node of type ASTType.Minimize.

+
+ +Expand source code + +
def Minimize(
+    location: Location,
+    weight: AST,
+    priority: AST,
+    terms: Sequence[AST],
+    body: Sequence[AST],
+) -> AST:
+    """
+    Construct an AST node of type `ASTType.Minimize`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_minimize,
+            p_ast,
+            c_location[0],
+            weight._rep,
+            priority._rep,
+            _ffi.new("clingo_ast_t*[]", [x._rep for x in terms]),
+            _ffi.cast("size_t", len(terms)),
+            _ffi.new("clingo_ast_t*[]", [x._rep for x in body]),
+            _ffi.cast("size_t", len(body)),
+        )
+    )
+    return AST(p_ast[0])
+
+
+
+def Pool(location: Location, arguments: Sequence[AST]) ‑> AST +
+
+

Construct an AST node of type ASTType.Pool.

+
+ +Expand source code + +
def Pool(location: Location, arguments: Sequence[AST]) -> AST:
+    """
+    Construct an AST node of type `ASTType.Pool`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_pool,
+            p_ast,
+            c_location[0],
+            _ffi.new("clingo_ast_t*[]", [x._rep for x in arguments]),
+            _ffi.cast("size_t", len(arguments)),
+        )
+    )
+    return AST(p_ast[0])
+
+
+
+def Program(location: Location, name: str, parameters: Sequence[AST]) ‑> AST +
+
+

Construct an AST node of type ASTType.Program.

+
+ +Expand source code + +
def Program(location: Location, name: str, parameters: Sequence[AST]) -> AST:
+    """
+    Construct an AST node of type `ASTType.Program`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_program,
+            p_ast,
+            c_location[0],
+            _ffi.new("char const[]", name.encode()),
+            _ffi.new("clingo_ast_t*[]", [x._rep for x in parameters]),
+            _ffi.cast("size_t", len(parameters)),
+        )
+    )
+    return AST(p_ast[0])
+
+
+
+def ProjectAtom(location: Location, atom: AST, body: Sequence[AST]) ‑> AST +
+
+

Construct an AST node of type ASTType.ProjectAtom.

+
+ +Expand source code + +
def ProjectAtom(location: Location, atom: AST, body: Sequence[AST]) -> AST:
+    """
+    Construct an AST node of type `ASTType.ProjectAtom`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_project_atom,
+            p_ast,
+            c_location[0],
+            atom._rep,
+            _ffi.new("clingo_ast_t*[]", [x._rep for x in body]),
+            _ffi.cast("size_t", len(body)),
+        )
+    )
+    return AST(p_ast[0])
+
+
+
+def ProjectSignature(location: Location, name: str, arity: int, positive: int) ‑> AST +
+
+

Construct an AST node of type ASTType.ProjectSignature.

+
+ +Expand source code + +
def ProjectSignature(location: Location, name: str, arity: int, positive: int) -> AST:
+    """
+    Construct an AST node of type `ASTType.ProjectSignature`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_project_signature,
+            p_ast,
+            c_location[0],
+            _ffi.new("char const[]", name.encode()),
+            _ffi.cast("int", arity),
+            _ffi.cast("int", positive),
+        )
+    )
+    return AST(p_ast[0])
+
+
+
+def Rule(location: Location, head: AST, body: Sequence[AST]) ‑> AST +
+
+

Construct an AST node of type ASTType.Rule.

+
+ +Expand source code + +
def Rule(location: Location, head: AST, body: Sequence[AST]) -> AST:
+    """
+    Construct an AST node of type `ASTType.Rule`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_rule,
+            p_ast,
+            c_location[0],
+            head._rep,
+            _ffi.new("clingo_ast_t*[]", [x._rep for x in body]),
+            _ffi.cast("size_t", len(body)),
+        )
+    )
+    return AST(p_ast[0])
+
+
+
+def Script(location: Location, name: str, code: str) ‑> AST +
+
+

Construct an AST node of type ASTType.Script.

+
+ +Expand source code + +
def Script(location: Location, name: str, code: str) -> AST:
+    """
+    Construct an AST node of type `ASTType.Script`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_script,
+            p_ast,
+            c_location[0],
+            _ffi.new("char const[]", name.encode()),
+            _ffi.new("char const[]", code.encode()),
+        )
+    )
+    return AST(p_ast[0])
+
+
+
+def ShowSignature(location: Location, name: str, arity: int, positive: int) ‑> AST +
+
+

Construct an AST node of type ASTType.ShowSignature.

+
+ +Expand source code + +
def ShowSignature(location: Location, name: str, arity: int, positive: int) -> AST:
+    """
+    Construct an AST node of type `ASTType.ShowSignature`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_show_signature,
+            p_ast,
+            c_location[0],
+            _ffi.new("char const[]", name.encode()),
+            _ffi.cast("int", arity),
+            _ffi.cast("int", positive),
+        )
+    )
+    return AST(p_ast[0])
+
+
+
+def ShowTerm(location: Location, term: AST, body: Sequence[AST]) ‑> AST +
+
+

Construct an AST node of type ASTType.ShowTerm.

+
+ +Expand source code + +
def ShowTerm(location: Location, term: AST, body: Sequence[AST]) -> AST:
+    """
+    Construct an AST node of type `ASTType.ShowTerm`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_show_term,
+            p_ast,
+            c_location[0],
+            term._rep,
+            _ffi.new("clingo_ast_t*[]", [x._rep for x in body]),
+            _ffi.cast("size_t", len(body)),
+        )
+    )
+    return AST(p_ast[0])
+
+
+
+def SymbolicAtom(symbol: AST) ‑> AST +
+
+

Construct an AST node of type ASTType.SymbolicAtom.

+
+ +Expand source code + +
def SymbolicAtom(symbol: AST) -> AST:
+    """
+    Construct an AST node of type `ASTType.SymbolicAtom`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    _handle_error(
+        _lib.clingo_ast_build(_lib.clingo_ast_type_symbolic_atom, p_ast, symbol._rep)
+    )
+    return AST(p_ast[0])
+
+
+
+def SymbolicTerm(location: Location, symbol: Symbol) ‑> AST +
+
+

Construct an AST node of type ASTType.SymbolicTerm.

+
+ +Expand source code + +
def SymbolicTerm(location: Location, symbol: Symbol) -> AST:
+    """
+    Construct an AST node of type `ASTType.SymbolicTerm`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_symbolic_term,
+            p_ast,
+            c_location[0],
+            _ffi.cast("clingo_symbol_t", symbol._rep),
+        )
+    )
+    return AST(p_ast[0])
+
+
+
+def TheoryAtom(location: Location, term: AST, elements: Sequence[AST], guard: Optional[AST]) ‑> AST +
+
+

Construct an AST node of type ASTType.TheoryAtom.

+
+ +Expand source code + +
def TheoryAtom(
+    location: Location, term: AST, elements: Sequence[AST], guard: Optional[AST]
+) -> AST:
+    """
+    Construct an AST node of type `ASTType.TheoryAtom`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_theory_atom,
+            p_ast,
+            c_location[0],
+            term._rep,
+            _ffi.new("clingo_ast_t*[]", [x._rep for x in elements]),
+            _ffi.cast("size_t", len(elements)),
+            _ffi.NULL if guard is None else guard._rep,
+        )
+    )
+    return AST(p_ast[0])
+
+
+
+def TheoryAtomDefinition(location: Location, atom_type: int, name: str, arity: int, term: str, guard: Optional[AST]) ‑> AST +
+
+

Construct an AST node of type ASTType.TheoryAtomDefinition.

+
+ +Expand source code + +
def TheoryAtomDefinition(
+    location: Location,
+    atom_type: int,
+    name: str,
+    arity: int,
+    term: str,
+    guard: Optional[AST],
+) -> AST:
+    """
+    Construct an AST node of type `ASTType.TheoryAtomDefinition`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_theory_atom_definition,
+            p_ast,
+            c_location[0],
+            _ffi.cast("int", atom_type),
+            _ffi.new("char const[]", name.encode()),
+            _ffi.cast("int", arity),
+            _ffi.new("char const[]", term.encode()),
+            _ffi.NULL if guard is None else guard._rep,
+        )
+    )
+    return AST(p_ast[0])
+
+
+
+def TheoryAtomElement(terms: Sequence[AST], condition: Sequence[AST]) ‑> AST +
+
+

Construct an AST node of type ASTType.TheoryAtomElement.

+
+ +Expand source code + +
def TheoryAtomElement(terms: Sequence[AST], condition: Sequence[AST]) -> AST:
+    """
+    Construct an AST node of type `ASTType.TheoryAtomElement`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_theory_atom_element,
+            p_ast,
+            _ffi.new("clingo_ast_t*[]", [x._rep for x in terms]),
+            _ffi.cast("size_t", len(terms)),
+            _ffi.new("clingo_ast_t*[]", [x._rep for x in condition]),
+            _ffi.cast("size_t", len(condition)),
+        )
+    )
+    return AST(p_ast[0])
+
+
+
+def TheoryDefinition(location: Location, name: str, terms: Sequence[AST], atoms: Sequence[AST]) ‑> AST +
+
+

Construct an AST node of type ASTType.TheoryDefinition.

+
+ +Expand source code + +
def TheoryDefinition(
+    location: Location, name: str, terms: Sequence[AST], atoms: Sequence[AST]
+) -> AST:
+    """
+    Construct an AST node of type `ASTType.TheoryDefinition`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_theory_definition,
+            p_ast,
+            c_location[0],
+            _ffi.new("char const[]", name.encode()),
+            _ffi.new("clingo_ast_t*[]", [x._rep for x in terms]),
+            _ffi.cast("size_t", len(terms)),
+            _ffi.new("clingo_ast_t*[]", [x._rep for x in atoms]),
+            _ffi.cast("size_t", len(atoms)),
+        )
+    )
+    return AST(p_ast[0])
+
+
+
+def TheoryFunction(location: Location, name: str, arguments: Sequence[AST]) ‑> AST +
+
+

Construct an AST node of type ASTType.TheoryFunction.

+
+ +Expand source code + +
def TheoryFunction(location: Location, name: str, arguments: Sequence[AST]) -> AST:
+    """
+    Construct an AST node of type `ASTType.TheoryFunction`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_theory_function,
+            p_ast,
+            c_location[0],
+            _ffi.new("char const[]", name.encode()),
+            _ffi.new("clingo_ast_t*[]", [x._rep for x in arguments]),
+            _ffi.cast("size_t", len(arguments)),
+        )
+    )
+    return AST(p_ast[0])
+
+
+
+def TheoryGuard(operator_name: str, term: AST) ‑> AST +
+
+

Construct an AST node of type ASTType.TheoryGuard.

+
+ +Expand source code + +
def TheoryGuard(operator_name: str, term: AST) -> AST:
+    """
+    Construct an AST node of type `ASTType.TheoryGuard`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_theory_guard,
+            p_ast,
+            _ffi.new("char const[]", operator_name.encode()),
+            term._rep,
+        )
+    )
+    return AST(p_ast[0])
+
+
+
+def TheoryGuardDefinition(operators: Sequence[str], term: str) ‑> AST +
+
+

Construct an AST node of type ASTType.TheoryGuardDefinition.

+
+ +Expand source code + +
def TheoryGuardDefinition(operators: Sequence[str], term: str) -> AST:
+    """
+    Construct an AST node of type `ASTType.TheoryGuardDefinition`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_operators = [_ffi.new("char[]", x.encode()) for x in operators]
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_theory_guard_definition,
+            p_ast,
+            _ffi.new("char*[]", c_operators),
+            _ffi.cast("size_t", len(operators)),
+            _ffi.new("char const[]", term.encode()),
+        )
+    )
+    return AST(p_ast[0])
+
+
+
+def TheoryOperatorDefinition(location: Location, name: str, priority: int, operator_type: int) ‑> AST +
+
+

Construct an AST node of type ASTType.TheoryOperatorDefinition.

+
+ +Expand source code + +
def TheoryOperatorDefinition(
+    location: Location, name: str, priority: int, operator_type: int
+) -> AST:
+    """
+    Construct an AST node of type `ASTType.TheoryOperatorDefinition`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_theory_operator_definition,
+            p_ast,
+            c_location[0],
+            _ffi.new("char const[]", name.encode()),
+            _ffi.cast("int", priority),
+            _ffi.cast("int", operator_type),
+        )
+    )
+    return AST(p_ast[0])
+
+
+
+def TheorySequence(location: Location, sequence_type: int, terms: Sequence[AST]) ‑> AST +
+
+

Construct an AST node of type ASTType.TheorySequence.

+
+ +Expand source code + +
def TheorySequence(location: Location, sequence_type: int, terms: Sequence[AST]) -> AST:
+    """
+    Construct an AST node of type `ASTType.TheorySequence`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_theory_sequence,
+            p_ast,
+            c_location[0],
+            _ffi.cast("int", sequence_type),
+            _ffi.new("clingo_ast_t*[]", [x._rep for x in terms]),
+            _ffi.cast("size_t", len(terms)),
+        )
+    )
+    return AST(p_ast[0])
+
+
+
+def TheoryTermDefinition(location: Location, name: str, operators: Sequence[AST]) ‑> AST +
+
+

Construct an AST node of type ASTType.TheoryTermDefinition.

+
+ +Expand source code + +
def TheoryTermDefinition(
+    location: Location, name: str, operators: Sequence[AST]
+) -> AST:
+    """
+    Construct an AST node of type `ASTType.TheoryTermDefinition`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_theory_term_definition,
+            p_ast,
+            c_location[0],
+            _ffi.new("char const[]", name.encode()),
+            _ffi.new("clingo_ast_t*[]", [x._rep for x in operators]),
+            _ffi.cast("size_t", len(operators)),
+        )
+    )
+    return AST(p_ast[0])
+
+
+
+def TheoryUnparsedTerm(location: Location, elements: Sequence[AST]) ‑> AST +
+
+

Construct an AST node of type ASTType.TheoryUnparsedTerm.

+
+ +Expand source code + +
def TheoryUnparsedTerm(location: Location, elements: Sequence[AST]) -> AST:
+    """
+    Construct an AST node of type `ASTType.TheoryUnparsedTerm`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_theory_unparsed_term,
+            p_ast,
+            c_location[0],
+            _ffi.new("clingo_ast_t*[]", [x._rep for x in elements]),
+            _ffi.cast("size_t", len(elements)),
+        )
+    )
+    return AST(p_ast[0])
+
+
+
+def TheoryUnparsedTermElement(operators: Sequence[str], term: AST) ‑> AST +
+
+

Construct an AST node of type ASTType.TheoryUnparsedTermElement.

+
+ +Expand source code + +
def TheoryUnparsedTermElement(operators: Sequence[str], term: AST) -> AST:
+    """
+    Construct an AST node of type `ASTType.TheoryUnparsedTermElement`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_operators = [_ffi.new("char[]", x.encode()) for x in operators]
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_theory_unparsed_term_element,
+            p_ast,
+            _ffi.new("char*[]", c_operators),
+            _ffi.cast("size_t", len(operators)),
+            term._rep,
+        )
+    )
+    return AST(p_ast[0])
+
+
+
+def UnaryOperation(location: Location, operator_type: int, argument: AST) ‑> AST +
+
+

Construct an AST node of type ASTType.UnaryOperation.

+
+ +Expand source code + +
def UnaryOperation(location: Location, operator_type: int, argument: AST) -> AST:
+    """
+    Construct an AST node of type `ASTType.UnaryOperation`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_unary_operation,
+            p_ast,
+            c_location[0],
+            _ffi.cast("int", operator_type),
+            argument._rep,
+        )
+    )
+    return AST(p_ast[0])
+
+
+
+def Variable(location: Location, name: str) ‑> AST +
+
+

Construct an AST node of type ASTType.Variable.

+
+ +Expand source code + +
def Variable(location: Location, name: str) -> AST:
+    """
+    Construct an AST node of type `ASTType.Variable`.
+    """
+    p_ast = _ffi.new("clingo_ast_t**")
+    c_location = _c_location(location)
+    _handle_error(
+        _lib.clingo_ast_build(
+            _lib.clingo_ast_type_variable,
+            p_ast,
+            c_location[0],
+            _ffi.new("char const[]", name.encode()),
+        )
+    )
+    return AST(p_ast[0])
+
+
+
+def parse_files(files: Sequence[str], callback: Callable[[AST], None], control: Optional[Control] = None, logger: Optional[Callable[[MessageCode, str], None]] = None, message_limit: int = 20) ‑> None +
+
+

Parse the programs in the given files and return an abstract syntax tree for +each statement via a callback.

+

The function follows clingo's handling of files on the command line. Filename +"-" is treated as stdin and if an empty list is given, then the parser will +read from stdin.

+

The optional control object can be added to enable parsing of files in +ASPIF format. The ground statements will be added to the control object.

+

Parameters

+
+
files
+
List of file names.
+
callback
+
Callable taking an ast as argument.
+
control
+
Control object to add ground rules to.
+
logger
+
Function to intercept messages normally printed to standard error.
+
message_limit
+
The maximum number of messages passed to the logger.
+
+

See Also

+

ProgramBuilder

+
+ +Expand source code + +
def parse_files(
+    files: Sequence[str],
+    callback: Callable[[AST], None],
+    control: Optional[Control] = None,
+    logger: Optional[Logger] = None,
+    message_limit: int = 20,
+) -> None:
+    """
+    Parse the programs in the given files and return an abstract syntax tree for
+    each statement via a callback.
+
+    The function follows clingo's handling of files on the command line. Filename
+    `"-"` is treated as stdin and if an empty list is given, then the parser will
+    read from stdin.
+
+    The optional control object can be added to enable parsing of files in
+    ASPIF format. The ground statements will be added to the control object.
+
+    Parameters
+    ----------
+    files
+        List of file names.
+    callback
+        Callable taking an ast as argument.
+    control
+        Control object to add ground rules to.
+    logger
+        Function to intercept messages normally printed to standard error.
+    message_limit
+        The maximum number of messages passed to the logger.
+
+    See Also
+    --------
+    ProgramBuilder
+    """
+    c_control = control._rep if control is not None else _ffi.NULL
+
+    if logger is not None:
+        c_logger_data = _ffi.new_handle(logger)
+        c_logger = _lib.pyclingo_logger_callback
+    else:
+        c_logger_data = _ffi.NULL
+        c_logger = _ffi.NULL
+
+    error = _Error()
+    cb_data = _CBData(callback, error)
+    c_cb_data = _ffi.new_handle(cb_data)
+
+    _handle_error(
+        _lib.clingo_ast_parse_files(
+            [_ffi.new("char[]", f.encode()) for f in files],
+            len(files),
+            _lib.pyclingo_ast_callback,
+            c_cb_data,
+            c_control,
+            c_logger,
+            c_logger_data,
+            message_limit,
+        ),
+        cb_data,
+    )
+
+
+
+def parse_string(program: str, callback: Callable[[AST], None], control: Optional[Control] = None, logger: Optional[Callable[[MessageCode, str], None]] = None, message_limit: int = 20) ‑> None +
+
+

Parse the given program and return an abstract syntax tree for each +statement via a callback.

+

The optional control object can be added to enable parsing of files in +ASPIF format. The ground statements will be added to the control object.

+

Parameters

+
+
program
+
String representation of the program.
+
callback
+
Callable taking an ast as argument.
+
control
+
Control object to add ground rules to.
+
logger
+
Function to intercept messages normally printed to standard error.
+
message_limit
+
The maximum number of messages passed to the logger.
+
+

See Also

+

ProgramBuilder

+
+ +Expand source code + +
def parse_string(
+    program: str,
+    callback: Callable[[AST], None],
+    control: Optional[Control] = None,
+    logger: Optional[Logger] = None,
+    message_limit: int = 20,
+) -> None:
+    """
+    Parse the given program and return an abstract syntax tree for each
+    statement via a callback.
+
+    The optional control object can be added to enable parsing of files in
+    ASPIF format. The ground statements will be added to the control object.
+
+    Parameters
+    ----------
+    program
+        String representation of the program.
+    callback
+        Callable taking an ast as argument.
+    control
+        Control object to add ground rules to.
+    logger
+        Function to intercept messages normally printed to standard error.
+    message_limit
+        The maximum number of messages passed to the logger.
+
+    See Also
+    --------
+    ProgramBuilder
+    """
+    c_control = control._rep if control is not None else _ffi.NULL
+
+    if logger is not None:
+        c_logger_data = _ffi.new_handle(logger)
+        c_logger = _lib.pyclingo_logger_callback
+    else:
+        c_logger_data = _ffi.NULL
+        c_logger = _ffi.NULL
+
+    error = _Error()
+    cb_data = _CBData(callback, error)
+    c_cb_data = _ffi.new_handle(cb_data)
+
+    _handle_error(
+        _lib.clingo_ast_parse_string(
+            program.encode(),
+            _lib.pyclingo_ast_callback,
+            c_cb_data,
+            c_control,
+            c_logger,
+            c_logger_data,
+            message_limit,
+        ),
+        cb_data,
+    )
+
+
+
+
+
+

Classes

+
+
+class AST +(rep) +
+
+

Represents a node in the abstract syntax tree.

+

The attributes of an AST are tied to its type. They correspond to the +grammar in the description of the clingo.ast module. AST nodes can be +constructed using one of the functions provided in this module.

+

Furthermore, AST nodes implement Python's rich comparison operators and are +ordered structurally ignoring the location. They can also be used as +dictionary keys. Their string representation corresponds to their gringo +representation. In fact, the string representation of any AST obtained from +parse_files() and parse_string() can be parsed again. Note that it is +possible to construct ASTs that are not parsable, though.

+
+ +Expand source code + +
@total_ordering
+class AST:
+    """
+    Represents a node in the abstract syntax tree.
+
+    The attributes of an `AST` are tied to its type. They correspond to the
+    grammar in the description of the `clingo.ast` module. `AST` nodes can be
+    constructed using one of the functions provided in this module.
+
+    Furthermore, AST nodes implement Python's rich comparison operators and are
+    ordered structurally ignoring the location. They can also be used as
+    dictionary keys. Their string representation corresponds to their gringo
+    representation. In fact, the string representation of any AST obtained from
+    `parse_files` and `parse_string` can be parsed again. Note that it is
+    possible to construct ASTs that are not parsable, though.
+    """
+
+    def __init__(self, rep):
+        super().__setattr__("_rep", rep)
+
+    def __eq__(self, other):
+        if not isinstance(other, AST):
+            return NotImplemented
+        return _lib.clingo_ast_equal(self._rep, other._rep)
+
+    def __lt__(self, other):
+        if not isinstance(other, AST):
+            return NotImplemented
+        return _lib.clingo_ast_less_than(self._rep, other._rep)
+
+    def __hash__(self):
+        return _lib.clingo_ast_hash(self._rep)
+
+    def __del__(self):
+        _lib.clingo_ast_release(self._rep)
+
+    def __getattr__(self, name):
+        attr_id = _attribute_names.get(name)
+        if attr_id is None or not _c_call(
+            "bool", _lib.clingo_ast_has_attribute, self._rep, attr_id
+        ):
+            raise AttributeError(f"no attribute: {name}")
+        attr_type = _c_call(
+            "clingo_ast_attribute_type_t",
+            _lib.clingo_ast_attribute_type,
+            self._rep,
+            attr_id,
+        )
+        if attr_type == _lib.clingo_ast_attribute_type_string:
+            return _to_str(
+                _c_call(
+                    "char*", _lib.clingo_ast_attribute_get_string, self._rep, attr_id
+                )
+            )
+        if attr_type == _lib.clingo_ast_attribute_type_number:
+            return _c_call(
+                "int", _lib.clingo_ast_attribute_get_number, self._rep, attr_id
+            )
+        if attr_type == _lib.clingo_ast_attribute_type_symbol:
+            return Symbol(
+                _c_call(
+                    "clingo_symbol_t",
+                    _lib.clingo_ast_attribute_get_symbol,
+                    self._rep,
+                    attr_id,
+                )
+            )
+        if attr_type == _lib.clingo_ast_attribute_type_location:
+            return _py_location(
+                _c_call(
+                    "clingo_location_t",
+                    _lib.clingo_ast_attribute_get_location,
+                    self._rep,
+                    attr_id,
+                )
+            )
+        if attr_type == _lib.clingo_ast_attribute_type_optional_ast:
+            rep = _c_call(
+                "clingo_ast_t*",
+                _lib.clingo_ast_attribute_get_optional_ast,
+                self._rep,
+                attr_id,
+            )
+            return AST(rep) if rep != _ffi.NULL else None
+        if attr_type == _lib.clingo_ast_attribute_type_ast:
+            return AST(
+                _c_call(
+                    "clingo_ast_t*",
+                    _lib.clingo_ast_attribute_get_ast,
+                    self._rep,
+                    attr_id,
+                )
+            )
+        if attr_type == _lib.clingo_ast_attribute_type_string_array:
+            return StrSequence(self._rep, attr_id)
+        assert attr_type == _lib.clingo_ast_attribute_type_ast_array
+        return ASTSequence(self._rep, attr_id)
+
+    def __setattr__(self, name, value):
+        attr_id = getattr(_lib, f"clingo_ast_attribute_{name}")
+        if not _c_call("bool", _lib.clingo_ast_has_attribute, self._rep, attr_id):
+            raise AttributeError(f"no attribute: {name}")
+        attr_type = _c_call(
+            "clingo_ast_attribute_type_t",
+            _lib.clingo_ast_attribute_type,
+            self._rep,
+            attr_id,
+        )
+        if attr_type == _lib.clingo_ast_attribute_type_string:
+            _handle_error(
+                _lib.clingo_ast_attribute_set_string(self._rep, attr_id, value.encode())
+            )
+        elif attr_type == _lib.clingo_ast_attribute_type_number:
+            _handle_error(
+                _lib.clingo_ast_attribute_set_number(self._rep, attr_id, value)
+            )
+        elif attr_type == _lib.clingo_ast_attribute_type_symbol:
+            _handle_error(
+                _lib.clingo_ast_attribute_set_symbol(self._rep, attr_id, value._rep)
+            )
+        elif attr_type == _lib.clingo_ast_attribute_type_location:
+            c_loc = _c_location(value)
+            _handle_error(
+                _lib.clingo_ast_attribute_set_location(self._rep, attr_id, c_loc[0])
+            )
+        elif attr_type == _lib.clingo_ast_attribute_type_optional_ast:
+            _handle_error(
+                _lib.clingo_ast_attribute_set_optional_ast(
+                    self._rep, attr_id, _ffi.NULL if value is None else value._rep
+                )
+            )
+        elif attr_type == _lib.clingo_ast_attribute_type_ast:
+            _handle_error(
+                _lib.clingo_ast_attribute_set_ast(self._rep, attr_id, value._rep)
+            )
+        elif attr_type == _lib.clingo_ast_attribute_type_string_array:
+            if isinstance(value, StrSequence):
+                if attr_id == value._attribute and self._rep == value._rep:
+                    value = list(value)
+            elif not isinstance(value, list):
+                value = list(value)
+            str_seq = StrSequence(self._rep, attr_id)
+            str_seq.clear()
+            str_seq.extend(value)
+        else:
+            assert attr_type == _lib.clingo_ast_attribute_type_ast_array
+            if isinstance(value, ASTSequence):
+                if attr_id == value._attribute and self._rep == value._rep:
+                    value = list(value)
+            elif not isinstance(value, list):
+                value = list(value)
+            ast_seq = ASTSequence(self._rep, attr_id)
+            ast_seq.clear()
+            ast_seq.extend(value)
+
+    def __str__(self):
+        return _str(
+            _lib.clingo_ast_to_string_size, _lib.clingo_ast_to_string, self._rep
+        )
+
+    def __repr__(self):
+        name = str(self.ast_type).replace("ASTType", "ast")
+        args = ", ".join(repr(x) for x in self.values())
+        return f"{name}({args})"
+
+    def __copy__(self) -> "AST":
+        """
+        Return a shallow copy of the ast.
+        """
+        return AST(_c_call("clingo_ast_t*", _lib.clingo_ast_copy, self._rep))
+
+    def __deepcopy__(self, memo) -> "AST":
+        """
+        Return a deep copy of the ast.
+        """
+        return AST(_c_call("clingo_ast_t*", _lib.clingo_ast_deep_copy, self._rep))
+
+    def update(self, **kwargs: ASTUpdate) -> "AST":
+        """
+        Return a copy of the AST also updating the given attributes.
+
+        Note that this function returns a reference to self if no arguments are
+        given.
+        """
+        if not kwargs:
+            return self
+
+        args = []
+        for key in self.keys():
+            if key in kwargs:
+                args.append(kwargs[key])
+            else:
+                args.append(getattr(self, key))
+
+        cons = globals()[str(self.ast_type).replace("ASTType.", "")]
+        return cons(*args)
+
+    def items(self) -> List[Tuple[str, ASTValue]]:
+        """
+        The list of items of the AST node.
+        """
+        return [(name, getattr(self, name)) for name in self.keys()]
+
+    def keys(self) -> List[str]:
+        """
+        The list of keys of the AST node.
+        """
+        cons = _lib.g_clingo_ast_constructors.constructors[self.ast_type.value]
+        names = _lib.g_clingo_ast_attribute_names.names
+        return [_to_str(names[cons.arguments[j].attribute]) for j in range(cons.size)]
+
+    def values(self) -> List[ASTValue]:
+        """
+        The list of values of the AST node.
+        """
+        return [(getattr(self, name)) for name in self.keys()]
+
+    @property
+    def ast_type(self) -> ASTType:
+        """
+        The type of the node.
+        """
+        return ASTType(
+            _c_call("clingo_ast_type_t", _lib.clingo_ast_get_type, self._rep)
+        )
+
+    @property
+    def child_keys(self) -> List[str]:
+        """
+        List of attribute names containing ASTs.
+        """
+        cons = _lib.g_clingo_ast_constructors.constructors[self.ast_type.value]
+        names = _lib.g_clingo_ast_attribute_names.names
+        return [
+            _to_str(names[cons.arguments[j].attribute])
+            for j in range(cons.size)
+            if cons.arguments[j].type
+            in (
+                _lib.clingo_ast_attribute_type_ast,
+                _lib.clingo_ast_attribute_type_optional_ast,
+                _lib.clingo_ast_attribute_type_ast_array,
+            )
+        ]
+
+    def unpool(self, other: bool = True, condition: bool = True) -> List["AST"]:
+        """
+        Unpool the AST returning a list of ASTs without pool terms.
+
+        Parameters
+        ----------
+        other
+            Remove all pools except those in conditions of conditional
+            literals.
+        condition
+            Only remove pools from conditions of conditional literals.
+        """
+        unpool_type = 0
+        if other:
+            unpool_type |= _lib.clingo_ast_unpool_type_other
+        if condition:
+            unpool_type |= _lib.clingo_ast_unpool_type_condition
+
+        ret: List[AST] = []
+        error = _Error()
+        cb_data = _CBData(ret.append, error)
+        c_cb_data = _ffi.new_handle(cb_data)
+        _handle_error(
+            _lib.clingo_ast_unpool(
+                self._rep, unpool_type, _lib.pyclingo_ast_callback, c_cb_data
+            )
+        )
+        return ret
+
+

Instance variables

+
+
var ast_typeASTType
+
+

The type of the node.

+
+ +Expand source code + +
@property
+def ast_type(self) -> ASTType:
+    """
+    The type of the node.
+    """
+    return ASTType(
+        _c_call("clingo_ast_type_t", _lib.clingo_ast_get_type, self._rep)
+    )
+
+
+
var child_keys : List[str]
+
+

List of attribute names containing ASTs.

+
+ +Expand source code + +
@property
+def child_keys(self) -> List[str]:
+    """
+    List of attribute names containing ASTs.
+    """
+    cons = _lib.g_clingo_ast_constructors.constructors[self.ast_type.value]
+    names = _lib.g_clingo_ast_attribute_names.names
+    return [
+        _to_str(names[cons.arguments[j].attribute])
+        for j in range(cons.size)
+        if cons.arguments[j].type
+        in (
+            _lib.clingo_ast_attribute_type_ast,
+            _lib.clingo_ast_attribute_type_optional_ast,
+            _lib.clingo_ast_attribute_type_ast_array,
+        )
+    ]
+
+
+
+

Methods

+
+
+def items(self) ‑> List[Tuple[str, Union[str, int, SymbolLocation, ForwardRef(None), ASTStrSequenceASTSequence]]] +
+
+

The list of items of the AST node.

+
+ +Expand source code + +
def items(self) -> List[Tuple[str, ASTValue]]:
+    """
+    The list of items of the AST node.
+    """
+    return [(name, getattr(self, name)) for name in self.keys()]
+
+
+
+def keys(self) ‑> List[str] +
+
+

The list of keys of the AST node.

+
+ +Expand source code + +
def keys(self) -> List[str]:
+    """
+    The list of keys of the AST node.
+    """
+    cons = _lib.g_clingo_ast_constructors.constructors[self.ast_type.value]
+    names = _lib.g_clingo_ast_attribute_names.names
+    return [_to_str(names[cons.arguments[j].attribute]) for j in range(cons.size)]
+
+
+
+def unpool(self, other: bool = True, condition: bool = True) ‑> List[AST] +
+
+

Unpool the AST returning a list of ASTs without pool terms.

+

Parameters

+
+
other
+
Remove all pools except those in conditions of conditional +literals.
+
condition
+
Only remove pools from conditions of conditional literals.
+
+
+ +Expand source code + +
def unpool(self, other: bool = True, condition: bool = True) -> List["AST"]:
+    """
+    Unpool the AST returning a list of ASTs without pool terms.
+
+    Parameters
+    ----------
+    other
+        Remove all pools except those in conditions of conditional
+        literals.
+    condition
+        Only remove pools from conditions of conditional literals.
+    """
+    unpool_type = 0
+    if other:
+        unpool_type |= _lib.clingo_ast_unpool_type_other
+    if condition:
+        unpool_type |= _lib.clingo_ast_unpool_type_condition
+
+    ret: List[AST] = []
+    error = _Error()
+    cb_data = _CBData(ret.append, error)
+    c_cb_data = _ffi.new_handle(cb_data)
+    _handle_error(
+        _lib.clingo_ast_unpool(
+            self._rep, unpool_type, _lib.pyclingo_ast_callback, c_cb_data
+        )
+    )
+    return ret
+
+
+
+def update(self, **kwargs: Union[str, int, SymbolLocation, ForwardRef(None), ForwardRef('AST'), Sequence[str], Sequence[ForwardRef('AST')]]) ‑> AST +
+
+

Return a copy of the AST also updating the given attributes.

+

Note that this function returns a reference to self if no arguments are +given.

+
+ +Expand source code + +
def update(self, **kwargs: ASTUpdate) -> "AST":
+    """
+    Return a copy of the AST also updating the given attributes.
+
+    Note that this function returns a reference to self if no arguments are
+    given.
+    """
+    if not kwargs:
+        return self
+
+    args = []
+    for key in self.keys():
+        if key in kwargs:
+            args.append(kwargs[key])
+        else:
+            args.append(getattr(self, key))
+
+    cons = globals()[str(self.ast_type).replace("ASTType.", "")]
+    return cons(*args)
+
+
+
+def values(self) ‑> List[Union[str, int, SymbolLocation, ForwardRef(None), ASTStrSequenceASTSequence]] +
+
+

The list of values of the AST node.

+
+ +Expand source code + +
def values(self) -> List[ASTValue]:
+    """
+    The list of values of the AST node.
+    """
+    return [(getattr(self, name)) for name in self.keys()]
+
+
+
+
+
+class ASTSequence +(rep, attribute) +
+
+

A sequence holding AST nodes.

+

Sequences implement Python's rich comparison operators and are ordered +structurally ignoring the location. They can also be used as dictionary +keys.

+
+ +Expand source code + +
class ASTSequence(abc.MutableSequence):
+    """
+    A sequence holding `AST` nodes.
+
+    Sequences implement Python's rich comparison operators and are ordered
+    structurally ignoring the location. They can also be used as dictionary
+    keys.
+    """
+
+    def __init__(self, rep, attribute):
+        self._rep = rep
+        self._attribute = attribute
+        _lib.clingo_ast_acquire(self._rep)
+
+    def __eq__(self, other):
+        return tuple(self) == tuple(other)
+
+    def __lt__(self, other):
+        return tuple(self) < tuple(other)
+
+    def __hash__(self):
+        return hash(tuple(self))
+
+    def __del__(self):
+        _lib.clingo_ast_release(self._rep)
+
+    def __len__(self) -> int:
+        return _c_call(
+            "size_t",
+            _lib.clingo_ast_attribute_size_ast_array,
+            self._rep,
+            self._attribute,
+        )
+
+    def __getitem__(self, index):
+        if isinstance(index, slice):
+            return SlicedMutableSequence(self, Slice(index))
+        size = len(self)
+        if index < 0:
+            index += size
+        if index < 0 or index >= size:
+            raise IndexError("invalid index")
+        return AST(
+            _c_call(
+                "clingo_ast_t*",
+                _lib.clingo_ast_attribute_get_ast_at,
+                self._rep,
+                self._attribute,
+                index,
+            )
+        )
+
+    def __iter__(self):
+        for index in range(len(self)):
+            yield AST(
+                _c_call(
+                    "clingo_ast_t*",
+                    _lib.clingo_ast_attribute_get_ast_at,
+                    self._rep,
+                    self._attribute,
+                    index,
+                )
+            )
+
+    def __setitem__(self, index, ast):
+        if isinstance(index, slice):
+            raise TypeError("slicing not implemented")
+        _handle_error(
+            _lib.clingo_ast_attribute_set_ast_at(
+                self._rep, self._attribute, index, ast._rep
+            )
+        )
+
+    def __delitem__(self, index):
+        if isinstance(index, slice):
+            raise TypeError("slicing not implemented")
+        size = len(self)
+        if index < 0:
+            index += size
+        if index < 0 or index >= size:
+            raise IndexError("invalid index")
+        _handle_error(
+            _lib.clingo_ast_attribute_delete_ast_at(self._rep, self._attribute, index)
+        )
+
+    def insert(self, index, value):
+        _handle_error(
+            _lib.clingo_ast_attribute_insert_ast_at(
+                self._rep, self._attribute, index, value._rep
+            )
+        )
+
+    def clear(self):
+        """
+        Remove all elements from the sequence.
+        """
+        for i in range(len(self), 0, -1):
+            del self[i - 1]
+
+    def __str__(self):
+        return str(list(self))
+
+    def __repr__(self):
+        return repr(list(self))
+
+

Ancestors

+
    +
  • collections.abc.MutableSequence
  • +
  • collections.abc.Sequence
  • +
  • collections.abc.Reversible
  • +
  • collections.abc.Collection
  • +
  • collections.abc.Sized
  • +
  • collections.abc.Iterable
  • +
  • collections.abc.Container
  • +
+

Methods

+
+
+def clear(self) +
+
+

Remove all elements from the sequence.

+
+ +Expand source code + +
def clear(self):
+    """
+    Remove all elements from the sequence.
+    """
+    for i in range(len(self), 0, -1):
+        del self[i - 1]
+
+
+
+def insert(self, index, value) +
+
+

S.insert(index, value) – insert value before index

+
+ +Expand source code + +
def insert(self, index, value):
+    _handle_error(
+        _lib.clingo_ast_attribute_insert_ast_at(
+            self._rep, self._attribute, index, value._rep
+        )
+    )
+
+
+
+
+
+class ASTType +(value, names=None, *, module=None, qualname=None, type=None, start=1) +
+
+

Enumeration of ast node types.

+
+ +Expand source code + +
class ASTType(OrderedEnum):
+    """
+    Enumeration of ast node types.
+    """
+
+    Id = _lib.clingo_ast_type_id
+    Variable = _lib.clingo_ast_type_variable
+    SymbolicTerm = _lib.clingo_ast_type_symbolic_term
+    UnaryOperation = _lib.clingo_ast_type_unary_operation
+    BinaryOperation = _lib.clingo_ast_type_binary_operation
+    Interval = _lib.clingo_ast_type_interval
+    Function = _lib.clingo_ast_type_function
+    Pool = _lib.clingo_ast_type_pool
+    BooleanConstant = _lib.clingo_ast_type_boolean_constant
+    SymbolicAtom = _lib.clingo_ast_type_symbolic_atom
+    Comparison = _lib.clingo_ast_type_comparison
+    Guard = _lib.clingo_ast_type_guard
+    ConditionalLiteral = _lib.clingo_ast_type_conditional_literal
+    Aggregate = _lib.clingo_ast_type_aggregate
+    BodyAggregateElement = _lib.clingo_ast_type_body_aggregate_element
+    BodyAggregate = _lib.clingo_ast_type_body_aggregate
+    HeadAggregateElement = _lib.clingo_ast_type_head_aggregate_element
+    HeadAggregate = _lib.clingo_ast_type_head_aggregate
+    Disjunction = _lib.clingo_ast_type_disjunction
+    TheorySequence = _lib.clingo_ast_type_theory_sequence
+    TheoryFunction = _lib.clingo_ast_type_theory_function
+    TheoryUnparsedTermElement = _lib.clingo_ast_type_theory_unparsed_term_element
+    TheoryUnparsedTerm = _lib.clingo_ast_type_theory_unparsed_term
+    TheoryGuard = _lib.clingo_ast_type_theory_guard
+    TheoryAtomElement = _lib.clingo_ast_type_theory_atom_element
+    TheoryAtom = _lib.clingo_ast_type_theory_atom
+    Literal = _lib.clingo_ast_type_literal
+    TheoryOperatorDefinition = _lib.clingo_ast_type_theory_operator_definition
+    TheoryTermDefinition = _lib.clingo_ast_type_theory_term_definition
+    TheoryGuardDefinition = _lib.clingo_ast_type_theory_guard_definition
+    TheoryAtomDefinition = _lib.clingo_ast_type_theory_atom_definition
+    Rule = _lib.clingo_ast_type_rule
+    Definition = _lib.clingo_ast_type_definition
+    ShowSignature = _lib.clingo_ast_type_show_signature
+    ShowTerm = _lib.clingo_ast_type_show_term
+    Minimize = _lib.clingo_ast_type_minimize
+    Script = _lib.clingo_ast_type_script
+    Program = _lib.clingo_ast_type_program
+    External = _lib.clingo_ast_type_external
+    Edge = _lib.clingo_ast_type_edge
+    Heuristic = _lib.clingo_ast_type_heuristic
+    ProjectAtom = _lib.clingo_ast_type_project_atom
+    ProjectSignature = _lib.clingo_ast_type_project_signature
+    Defined = _lib.clingo_ast_type_defined
+    TheoryDefinition = _lib.clingo_ast_type_theory_definition
+    Comment = _lib.clingo_ast_type_comment
+
+

Ancestors

+ +

Class variables

+
+
var Aggregate
+
+
+
+
var BinaryOperation
+
+
+
+
var BodyAggregate
+
+
+
+
var BodyAggregateElement
+
+
+
+
var BooleanConstant
+
+
+
+
var Comment
+
+
+
+
var Comparison
+
+
+
+
var ConditionalLiteral
+
+
+
+
var Defined
+
+
+
+
var Definition
+
+
+
+
var Disjunction
+
+
+
+
var Edge
+
+
+
+
var External
+
+
+
+
var Function
+
+
+
+
var Guard
+
+
+
+
var HeadAggregate
+
+
+
+
var HeadAggregateElement
+
+
+
+
var Heuristic
+
+
+
+
var Id
+
+
+
+
var Interval
+
+
+
+
var Literal
+
+
+
+
var Minimize
+
+
+
+
var Pool
+
+
+
+
var Program
+
+
+
+
var ProjectAtom
+
+
+
+
var ProjectSignature
+
+
+
+
var Rule
+
+
+
+
var Script
+
+
+
+
var ShowSignature
+
+
+
+
var ShowTerm
+
+
+
+
var SymbolicAtom
+
+
+
+
var SymbolicTerm
+
+
+
+
var TheoryAtom
+
+
+
+
var TheoryAtomDefinition
+
+
+
+
var TheoryAtomElement
+
+
+
+
var TheoryDefinition
+
+
+
+
var TheoryFunction
+
+
+
+
var TheoryGuard
+
+
+
+
var TheoryGuardDefinition
+
+
+
+
var TheoryOperatorDefinition
+
+
+
+
var TheorySequence
+
+
+
+
var TheoryTermDefinition
+
+
+
+
var TheoryUnparsedTerm
+
+
+
+
var TheoryUnparsedTermElement
+
+
+
+
var UnaryOperation
+
+
+
+
var Variable
+
+
+
+
+
+
+class AggregateFunction +(value, names=None, *, module=None, qualname=None, type=None, start=1) +
+
+

Enumeration of aggegate functions.

+
+ +Expand source code + +
class AggregateFunction(IntEnum):
+    """
+    Enumeration of aggegate functions.
+    """
+
+    Count = _lib.clingo_ast_aggregate_function_count
+    """
+    The `#count` function.
+    """
+    Max = _lib.clingo_ast_aggregate_function_max
+    """
+    The `#max` function.
+    """
+    Min = _lib.clingo_ast_aggregate_function_min
+    """
+    The `#min` function.
+    """
+    Sum = _lib.clingo_ast_aggregate_function_sum
+    """
+    The `#sum` function.
+    """
+    SumPlus = _lib.clingo_ast_aggregate_function_sump
+    """
+    The `#sum+` function.
+    """
+
+

Ancestors

+
    +
  • enum.IntEnum
  • +
  • builtins.int
  • +
  • enum.Enum
  • +
+

Class variables

+
+
var Count
+
+

The #count function.

+
+
var Max
+
+

The #max function.

+
+
var Min
+
+

The #min function.

+
+
var Sum
+
+

The #sum function.

+
+
var SumPlus
+
+

The #sum+ function.

+
+
+
+
+class BinaryOperator +(value, names=None, *, module=None, qualname=None, type=None, start=1) +
+
+

Enumeration of binary operators.

+
+ +Expand source code + +
class BinaryOperator(IntEnum):
+    """
+    Enumeration of binary operators.
+    """
+
+    And = _lib.clingo_ast_binary_operator_and
+    """
+    For bitwise and.
+    """
+    Division = _lib.clingo_ast_binary_operator_division
+    """
+    For arithmetic division.
+    """
+    Minus = _lib.clingo_ast_binary_operator_minus
+    """
+    For arithmetic subtraction.
+    """
+    Modulo = _lib.clingo_ast_binary_operator_modulo
+    """
+    For arithmetic modulo.
+    """
+    Multiplication = _lib.clingo_ast_binary_operator_multiplication
+    """
+    For arithmetic multipilcation.
+    """
+    Or = _lib.clingo_ast_binary_operator_or
+    """
+    For bitwise or.
+    """
+    Plus = _lib.clingo_ast_binary_operator_plus
+    """
+    For arithmetic addition.
+    """
+    Power = _lib.clingo_ast_binary_operator_power
+    """
+    For arithmetic exponentiation.
+    """
+    XOr = _lib.clingo_ast_binary_operator_xor
+    """
+    For bitwise exclusive or.
+    """
+
+

Ancestors

+
    +
  • enum.IntEnum
  • +
  • builtins.int
  • +
  • enum.Enum
  • +
+

Class variables

+
+
var And
+
+

For bitwise and.

+
+
var Division
+
+

For arithmetic division.

+
+
var Minus
+
+

For arithmetic subtraction.

+
+
var Modulo
+
+

For arithmetic modulo.

+
+
var Multiplication
+
+

For arithmetic multipilcation.

+
+
var Or
+
+

For bitwise or.

+
+
var Plus
+
+

For arithmetic addition.

+
+
var Power
+
+

For arithmetic exponentiation.

+
+
var XOr
+
+

For bitwise exclusive or.

+
+
+
+
+class CommentType +(value, names=None, *, module=None, qualname=None, type=None, start=1) +
+
+

Enumeration of comment types.

+
+ +Expand source code + +
class CommentType(OrderedEnum):
+    """
+    Enumeration of comment types.
+    """
+
+    Line = _lib.clingo_comment_type_line
+    """
+    Line comments starting with `%` ending at a newline.
+    """
+    Block = _lib.clingo_comment_type_block
+    """
+    Block comments enclosed in `%*` and  `*%`.
+    """
+
+

Ancestors

+ +

Class variables

+
+
var Block
+
+

Block comments enclosed in %* and +*%.

+
+
var Line
+
+

Line comments starting with % ending at a newline.

+
+
+
+
+class ComparisonOperator +(value, names=None, *, module=None, qualname=None, type=None, start=1) +
+
+

Enumeration of comparison operators.

+
+ +Expand source code + +
class ComparisonOperator(IntEnum):
+    """
+    Enumeration of comparison operators.
+    """
+
+    Equal = _lib.clingo_ast_comparison_operator_equal
+    """
+    The `=` operator
+    """
+    GreaterEqual = _lib.clingo_ast_comparison_operator_greater_equal
+    """
+    The `>=` operator.
+    """
+    GreaterThan = _lib.clingo_ast_comparison_operator_greater_than
+    """
+    The `>` operator.
+    """
+    LessEqual = _lib.clingo_ast_comparison_operator_less_equal
+    """
+    The `<=` operator.
+    """
+    LessThan = _lib.clingo_ast_comparison_operator_less_than
+    """
+    The `<` operator.
+    """
+    NotEqual = _lib.clingo_ast_comparison_operator_not_equal
+    """
+    The `!=` operator.
+    """
+
+

Ancestors

+
    +
  • enum.IntEnum
  • +
  • builtins.int
  • +
  • enum.Enum
  • +
+

Class variables

+
+
var Equal
+
+

The = operator

+
+
var GreaterEqual
+
+

The >= operator.

+
+
var GreaterThan
+
+

The > operator.

+
+
var LessEqual
+
+

The <= operator.

+
+
var LessThan
+
+

The < operator.

+
+
var NotEqual
+
+

The != operator.

+
+
+
+
+class Location +(begin: Position, end: Position) +
+
+

Class to point to a range in a text file.

+
+ +Expand source code + +
class Location(NamedTuple):
+    """
+    Class to point to a range in a text file.
+    """
+
+    begin: Position
+    """
+    The beginning of the range.
+    """
+    end: Position
+    """
+    The end of the range.
+    """
+
+

Ancestors

+
    +
  • builtins.tuple
  • +
+

Instance variables

+
+
var beginPosition
+
+

The beginning of the range.

+
+
var endPosition
+
+

The end of the range.

+
+
+
+
+class Position +(filename: str, line: int, column: int) +
+
+

Class to point to a position in a text file.

+
+ +Expand source code + +
class Position(NamedTuple):
+    """
+    Class to point to a position in a text file.
+    """
+
+    filename: str
+    """
+    The file name.
+    """
+    line: int
+    """
+    The line number in the file.
+    """
+    column: int
+    """
+    The column number in the line.
+    """
+
+

Ancestors

+
    +
  • builtins.tuple
  • +
+

Instance variables

+
+
var column : int
+
+

The column number in the line.

+
+
var filename : str
+
+

The file name.

+
+
var line : int
+
+

The line number in the file.

+
+
+
+
+class ProgramBuilder +(control: Control) +
+
+

Object to build non-ground programs.

+

Parameters

+
+
control
+
The Control object to attach the builder to.
+
+

See Also

+

parse_string(), parse_files()

+

Notes

+

This class is a context manager and must be used with Python's with +statement.

+
+ +Expand source code + +
class ProgramBuilder(ContextManager["ProgramBuilder"]):
+    """
+    Object to build non-ground programs.
+
+    Parameters
+    ----------
+    control
+        The `clingo.control.Control` object to attach the builder to.
+
+    See Also
+    --------
+    parse_string, parse_files
+
+    Notes
+    -----
+    This class is a context manager and must be used with Python's `with`
+    statement.
+    """
+
+    def __init__(self, control: Control):
+        self._rep = _c_call(
+            "clingo_program_builder_t*", _lib.clingo_program_builder_init, control._rep
+        )
+
+    def __enter__(self):
+        _handle_error(_lib.clingo_program_builder_begin(self._rep))
+        return self
+
+    def __exit__(self, exc_type, exc_val, exc_tb):
+        _handle_error(_lib.clingo_program_builder_end(self._rep))
+        return False
+
+    def add(self, statement: AST) -> None:
+        """
+        Adds a statement in form of an `AST` node to the program.
+
+        Parameters
+        ----------
+        statement
+            The statement to add.
+        """
+        _handle_error(_lib.clingo_program_builder_add(self._rep, statement._rep))
+
+

Ancestors

+
    +
  • contextlib.AbstractContextManager
  • +
  • abc.ABC
  • +
  • typing.Generic
  • +
+

Methods

+
+
+def add(self, statement: AST) ‑> None +
+
+

Adds a statement in form of an AST node to the program.

+

Parameters

+
+
statement
+
The statement to add.
+
+
+ +Expand source code + +
def add(self, statement: AST) -> None:
+    """
+    Adds a statement in form of an `AST` node to the program.
+
+    Parameters
+    ----------
+    statement
+        The statement to add.
+    """
+    _handle_error(_lib.clingo_program_builder_add(self._rep, statement._rep))
+
+
+
+
+
+class Sign +(value, names=None, *, module=None, qualname=None, type=None, start=1) +
+
+

Enumeration of signs for literals.

+
+ +Expand source code + +
class Sign(IntEnum):
+    """
+    Enumeration of signs for literals.
+    """
+
+    DoubleNegation = _lib.clingo_ast_sign_double_negation
+    """
+    For double negated literals (with prefix `not not`)
+    """
+    Negation = _lib.clingo_ast_sign_negation
+    """
+    For negative literals (with prefix `not`).
+    """
+    NoSign = _lib.clingo_ast_sign_no_sign
+    """
+    For positive literals.
+    """
+
+

Ancestors

+
    +
  • enum.IntEnum
  • +
  • builtins.int
  • +
  • enum.Enum
  • +
+

Class variables

+
+
var DoubleNegation
+
+

For double negated literals (with prefix not not)

+
+
var Negation
+
+

For negative literals (with prefix not).

+
+
var NoSign
+
+

For positive literals.

+
+
+
+
+class StrSequence +(rep, attribute) +
+
+

A sequence holding strings.

+
+ +Expand source code + +
class StrSequence(abc.MutableSequence):
+    """
+    A sequence holding strings.
+    """
+
+    def __init__(self, rep, attribute):
+        self._attribute = attribute
+        self._rep = rep
+        _lib.clingo_ast_acquire(self._rep)
+
+    def __del__(self):
+        _lib.clingo_ast_release(self._rep)
+
+    def __len__(self) -> int:
+        return _c_call(
+            "size_t",
+            _lib.clingo_ast_attribute_size_string_array,
+            self._rep,
+            self._attribute,
+        )
+
+    def __getitem__(self, index):
+        if isinstance(index, slice):
+            return SlicedMutableSequence(self, Slice(index))
+        size = len(self)
+        if index < 0:
+            index += size
+        if index < 0 or index >= size:
+            raise IndexError("invalid index")
+        return _to_str(
+            _c_call(
+                "char*",
+                _lib.clingo_ast_attribute_get_string_at,
+                self._rep,
+                self._attribute,
+                index,
+            )
+        )
+
+    def __iter__(self):
+        for index in range(len(self)):
+            yield _to_str(
+                _c_call(
+                    "char*",
+                    _lib.clingo_ast_attribute_get_string_at,
+                    self._rep,
+                    self._attribute,
+                    index,
+                )
+            )
+
+    def __setitem__(self, index, value):
+        if isinstance(index, slice):
+            raise TypeError("slicing not implemented")
+        _handle_error(
+            _lib.clingo_str_attribute_set_string_at(
+                self._rep, self._attribute, index, value.encode()
+            )
+        )
+
+    def __delitem__(self, index):
+        if isinstance(index, slice):
+            raise TypeError("slicing not implemented")
+        size = len(self)
+        if index < 0:
+            index += size
+        if index < 0 or index >= size:
+            raise IndexError("invalid index")
+        _handle_error(
+            _lib.clingo_ast_attribute_delete_string_at(
+                self._rep, self._attribute, index
+            )
+        )
+
+    def insert(self, index, value):
+        _handle_error(
+            _lib.clingo_ast_attribute_insert_string_at(
+                self._rep, self._attribute, index, value.encode()
+            )
+        )
+
+    def clear(self):
+        """
+        Remove all elements from the sequence.
+        """
+        for i in range(len(self), 0, -1):
+            del self[i - 1]
+
+    def __str__(self):
+        return str(list(self))
+
+    def __repr__(self):
+        return repr(list(self))
+
+

Ancestors

+
    +
  • collections.abc.MutableSequence
  • +
  • collections.abc.Sequence
  • +
  • collections.abc.Reversible
  • +
  • collections.abc.Collection
  • +
  • collections.abc.Sized
  • +
  • collections.abc.Iterable
  • +
  • collections.abc.Container
  • +
+

Methods

+
+
+def clear(self) +
+
+

Remove all elements from the sequence.

+
+ +Expand source code + +
def clear(self):
+    """
+    Remove all elements from the sequence.
+    """
+    for i in range(len(self), 0, -1):
+        del self[i - 1]
+
+
+
+def insert(self, index, value) +
+
+

S.insert(index, value) – insert value before index

+
+ +Expand source code + +
def insert(self, index, value):
+    _handle_error(
+        _lib.clingo_ast_attribute_insert_string_at(
+            self._rep, self._attribute, index, value.encode()
+        )
+    )
+
+
+
+
+
+class TheoryAtomType +(value, names=None, *, module=None, qualname=None, type=None, start=1) +
+
+

Enumeration of theory atom types.

+
+ +Expand source code + +
class TheoryAtomType(IntEnum):
+    """
+    Enumeration of theory atom types.
+    """
+
+    Any = _lib.clingo_ast_theory_atom_definition_type_any
+    """
+    For atoms that can occur anywhere in a rule.
+    """
+    Body = _lib.clingo_ast_theory_atom_definition_type_body
+    """
+    For atoms that can only occur in rule bodies.
+    """
+    Directive = _lib.clingo_ast_theory_atom_definition_type_directive
+    """
+    For atoms that can only occur in facts.
+    """
+    Head = _lib.clingo_ast_theory_atom_definition_type_head
+    """
+    For atoms that can only occur in rule heads.
+    """
+
+

Ancestors

+
    +
  • enum.IntEnum
  • +
  • builtins.int
  • +
  • enum.Enum
  • +
+

Class variables

+
+
var Any
+
+

For atoms that can occur anywhere in a rule.

+
+
var Body
+
+

For atoms that can only occur in rule bodies.

+
+
var Directive
+
+

For atoms that can only occur in facts.

+
+
var Head
+
+

For atoms that can only occur in rule heads.

+
+
+
+
+class TheoryOperatorType +(value, names=None, *, module=None, qualname=None, type=None, start=1) +
+
+

Enumeration of operator types.

+
+ +Expand source code + +
class TheoryOperatorType(IntEnum):
+    """
+    Enumeration of operator types.
+    """
+
+    BinaryLeft = _lib.clingo_ast_theory_operator_type_binary_left
+    """
+    For binary left associative operators.
+    """
+    BinaryRight = _lib.clingo_ast_theory_operator_type_binary_right
+    """
+    For binary right associative operator.
+    """
+    Unary = _lib.clingo_ast_theory_operator_type_unary
+    """
+    For unary operators.
+    """
+
+

Ancestors

+
    +
  • enum.IntEnum
  • +
  • builtins.int
  • +
  • enum.Enum
  • +
+

Class variables

+
+
var BinaryLeft
+
+

For binary left associative operators.

+
+
var BinaryRight
+
+

For binary right associative operator.

+
+
var Unary
+
+

For unary operators.

+
+
+
+
+class TheorySequenceType +(value, names=None, *, module=None, qualname=None, type=None, start=1) +
+
+

Enumeration of theory term sequence types.

+
+ +Expand source code + +
class TheorySequenceType(IntEnum):
+    """
+    Enumeration of theory term sequence types.
+    """
+
+    List = _lib.clingo_ast_theory_sequence_type_list
+    """
+    For sequences enclosed in brackets.
+    """
+    Set = _lib.clingo_ast_theory_sequence_type_set
+    """
+    For sequences enclosed in braces.
+    """
+    Tuple = _lib.clingo_ast_theory_sequence_type_tuple
+    """
+    For sequences enclosed in parenthesis.
+    """
+
+

Ancestors

+
    +
  • enum.IntEnum
  • +
  • builtins.int
  • +
  • enum.Enum
  • +
+

Class variables

+
+
var List
+
+

For sequences enclosed in brackets.

+
+
var Set
+
+

For sequences enclosed in braces.

+
+
var Tuple
+
+

For sequences enclosed in parenthesis.

+
+
+
+
+class Transformer +
+
+

Utility class to transform ASTs.

+

Classes should inherit from this class and implement functions with name +visit_<ast_type> where <ast_type> is the type of the ASTs to visit and +modify. Such a function should return an updated AST or the same AST if no +change is necessary. The transformer will take care to copy all parent ASTs +involving a modified child. Note that the class works like a visitor if +only self references are returned from such functions.

+

Any extra arguments passed to the visit method are passed on to child ASTs.

+
+ +Expand source code + +
class Transformer:
+    """
+    Utility class to transform ASTs.
+
+    Classes should inherit from this class and implement functions with name
+    `visit_<ast_type>` where `<ast_type>` is the type of the ASTs to visit and
+    modify. Such a function should return an updated AST or the same AST if no
+    change is necessary. The transformer will take care to copy all parent ASTs
+    involving a modified child. Note that the class works like a visitor if
+    only self references are returned from such functions.
+
+    Any extra arguments passed to the visit method are passed on to child ASTs.
+    """
+
+    def visit(self, ast: AST, *args: Any, **kwargs: Any) -> AST:
+        """
+        Dispatch to a visit method in a base class or visit and transform the
+        children of the given AST if it is missing.
+        """
+        attr = "visit_" + str(ast.ast_type).replace("ASTType.", "")
+        if hasattr(self, attr):
+            return getattr(self, attr)(ast, *args, **kwargs)
+        return ast.update(**self.visit_children(ast, *args, **kwargs))
+
+    def visit_children(
+        self, ast: AST, *args: Any, **kwargs: Any
+    ) -> Dict[str, ASTUpdate]:
+        """
+        Visit and transform the children of the given AST.
+
+        Returns
+        -------
+        The functions returns a dictionary that can be passed to `AST.update`.
+        It contains the attributes and values that have been transformed.
+        """
+        update: Dict[str, ASTUpdate] = dict()
+        for key in ast.child_keys:
+            old = getattr(ast, key)
+            new = self._dispatch(old, *args, **kwargs)
+            if new is not old:
+                update[key] = new
+        return update
+
+    def visit_sequence(
+        self, sequence: ASTSequence, *args: Any, **kwargs: Any
+    ) -> MutableSequence[AST]:
+        """
+        Transform a sequence of ASTs returning the same sequnce if there are no
+        changes or a list of ASTs otherwise.
+        """
+        ret: MutableSequence[AST]
+        ret, lst = sequence, []
+        for old in sequence:
+            lst.append(self(old, *args, **kwargs))
+            if lst[-1] is not old:
+                ret = lst
+        return ret
+
+    def _dispatch(
+        self, ast: Union[None, AST, ASTSequence], *args: Any, **kwargs: Any
+    ) -> Union[None, AST, MutableSequence[AST]]:
+        """
+        Visit and transform an (optional) AST or a sequence of ASTs.
+        """
+        if ast is None:
+            return ast
+
+        if isinstance(ast, AST):
+            return self.visit(ast, *args, **kwargs)  # type: ignore
+
+        if isinstance(ast, abc.Sequence):
+            return self.visit_sequence(ast, *args, **kwargs)
+
+        raise TypeError("unexpected type")
+
+    def __call__(self, ast: AST, *args: Any, **kwargs: Any) -> AST:
+        """
+        Alternative way to call `Transformer.visit`.
+        """
+        return self.visit(ast, *args, **kwargs)
+
+

Subclasses

+ +

Methods

+
+
+def visit(self, ast: AST, *args: Any, **kwargs: Any) ‑> AST +
+
+

Dispatch to a visit method in a base class or visit and transform the +children of the given AST if it is missing.

+
+ +Expand source code + +
def visit(self, ast: AST, *args: Any, **kwargs: Any) -> AST:
+    """
+    Dispatch to a visit method in a base class or visit and transform the
+    children of the given AST if it is missing.
+    """
+    attr = "visit_" + str(ast.ast_type).replace("ASTType.", "")
+    if hasattr(self, attr):
+        return getattr(self, attr)(ast, *args, **kwargs)
+    return ast.update(**self.visit_children(ast, *args, **kwargs))
+
+
+
+def visit_children(self, ast: AST, *args: Any, **kwargs: Any) ‑> Dict[str, Union[str, int, SymbolLocation, ForwardRef(None), AST, Sequence[str], Sequence[AST]]] +
+
+

Visit and transform the children of the given AST.

+

Returns

+

The functions returns a dictionary that can be passed to AST.update(). +It contains the attributes and values that have been transformed.

+
+ +Expand source code + +
def visit_children(
+    self, ast: AST, *args: Any, **kwargs: Any
+) -> Dict[str, ASTUpdate]:
+    """
+    Visit and transform the children of the given AST.
+
+    Returns
+    -------
+    The functions returns a dictionary that can be passed to `AST.update`.
+    It contains the attributes and values that have been transformed.
+    """
+    update: Dict[str, ASTUpdate] = dict()
+    for key in ast.child_keys:
+        old = getattr(ast, key)
+        new = self._dispatch(old, *args, **kwargs)
+        if new is not old:
+            update[key] = new
+    return update
+
+
+
+def visit_sequence(self, sequence: ASTSequence, *args: Any, **kwargs: Any) ‑> MutableSequence[AST] +
+
+

Transform a sequence of ASTs returning the same sequnce if there are no +changes or a list of ASTs otherwise.

+
+ +Expand source code + +
def visit_sequence(
+    self, sequence: ASTSequence, *args: Any, **kwargs: Any
+) -> MutableSequence[AST]:
+    """
+    Transform a sequence of ASTs returning the same sequnce if there are no
+    changes or a list of ASTs otherwise.
+    """
+    ret: MutableSequence[AST]
+    ret, lst = sequence, []
+    for old in sequence:
+        lst.append(self(old, *args, **kwargs))
+        if lst[-1] is not old:
+            ret = lst
+    return ret
+
+
+
+
+
+class UnaryOperator +(value, names=None, *, module=None, qualname=None, type=None, start=1) +
+
+

Enumeration of signs for literals.

+
+ +Expand source code + +
class UnaryOperator(IntEnum):
+    """
+    Enumeration of signs for literals.
+    """
+
+    Absolute = _lib.clingo_ast_unary_operator_absolute
+    """
+    For taking the absolute value.
+    """
+    Minus = _lib.clingo_ast_unary_operator_minus
+    """
+    For unary minus and classical negation.
+    """
+    Negation = _lib.clingo_ast_unary_operator_negation
+    """
+    For bitwise negation.
+    """
+
+

Ancestors

+
    +
  • enum.IntEnum
  • +
  • builtins.int
  • +
  • enum.Enum
  • +
+

Class variables

+
+
var Absolute
+
+

For taking the absolute value.

+
+
var Minus
+
+

For unary minus and classical negation.

+
+
var Negation
+
+

For bitwise negation.

+
+
+
+
+
+
+ +
+ + + \ No newline at end of file diff --git a/clingo/python-api/5.7/clingo/backend.html b/clingo/python-api/5.7/clingo/backend.html new file mode 100644 index 0000000..61c2f13 --- /dev/null +++ b/clingo/python-api/5.7/clingo/backend.html @@ -0,0 +1,3427 @@ + + + + + + +clingo.backend API documentation + + + + + + + + + + + +
+
+
+

Module clingo.backend

+
+
+

Functions and classes to observe or add ground statements.

+

Examples

+

The following example shows how to add a fact to a program via the backend and +observe the corresponding rule passed to the backend:

+
>>> from clingo.symbol import Function
+>>> from clingo.control import Control
+>>>
+>>> class Observer:
+...     def rule(self, choice, head, body):
+...         print("rule:", choice, head, body)
+...
+>>> ctl = Control()
+>>> ctl.register_observer(Observer())
+>>>
+>>> sym_a = Function("a")
+>>> with ctl.backend() as backend:
+...     atm_a = backend.add_atom(sym_a)
+...     backend.add_rule([atm_a])
+...
+rule: False [1] []
+>>> ctl.symbolic_atoms[sym_a].is_fact
+True
+>>>
+>>> print(ctl.solve(on_model=print))
+a
+SAT
+
+
+ +Expand source code + +
"""
+Functions and classes to observe or add ground statements.
+
+Examples
+--------
+The following example shows how to add a fact to a program via the backend and
+observe the corresponding rule passed to the backend:
+
+    >>> from clingo.symbol import Function
+    >>> from clingo.control import Control
+    >>>
+    >>> class Observer:
+    ...     def rule(self, choice, head, body):
+    ...         print("rule:", choice, head, body)
+    ...
+    >>> ctl = Control()
+    >>> ctl.register_observer(Observer())
+    >>>
+    >>> sym_a = Function("a")
+    >>> with ctl.backend() as backend:
+    ...     atm_a = backend.add_atom(sym_a)
+    ...     backend.add_rule([atm_a])
+    ...
+    rule: False [1] []
+    >>> ctl.symbolic_atoms[sym_a].is_fact
+    True
+    >>>
+    >>> print(ctl.solve(on_model=print))
+    a
+    SAT
+"""
+
+from typing import ContextManager, Sequence, Optional, Tuple
+from abc import ABCMeta
+
+from ._internal import _c_call, _cb_error_handler, _ffi, _handle_error, _lib, _to_str
+from .core import OrderedEnum, TruthValue
+from .symbol import Symbol
+
+__all__ = ["Backend", "HeuristicType", "Observer", "TheorySequenceType"]
+
+
+class TheorySequenceType(OrderedEnum):
+    """
+    Enumeration of the different heuristic types.
+    """
+
+    Tuple = _lib.clingo_theory_sequence_type_tuple
+    """
+    Type for tuples.
+    """
+    List = _lib.clingo_theory_sequence_type_list
+    """
+    Type for lists.
+    """
+    Set = _lib.clingo_theory_sequence_type_set
+    """
+    Type fo sets.
+    """
+
+
+class HeuristicType(OrderedEnum):
+    """
+    Enumeration of the different heuristic types.
+    """
+
+    Factor = _lib.clingo_heuristic_type_factor
+    """
+    Heuristic modification to set the decaying factor of an atom.
+    """
+    False_ = _lib.clingo_heuristic_type_false
+    """
+    Heuristic modification to make an atom false.
+    """
+    Init = _lib.clingo_heuristic_type_init
+    """
+    Heuristic modification to set the inital score of an atom.
+    """
+    Level = _lib.clingo_heuristic_type_level
+    """
+    Heuristic modification to set the level of an atom.
+    """
+    Sign = _lib.clingo_heuristic_type_sign
+    """
+    Heuristic modification to set the sign of an atom.
+    """
+    True_ = _lib.clingo_heuristic_type_true
+    """
+    Heuristic modification to make an atom true.
+    """
+
+
+class Observer(metaclass=ABCMeta):
+    """
+    Interface that has to be implemented to inspect rules produced during
+    grounding.
+
+    See Also
+    --------
+    clingo.control.Control.register_observer
+
+    Notes
+    -----
+    Not all functions the `Observer` interface have to be implemented and can
+    be omitted if not needed.
+    """
+
+    def init_program(self, incremental: bool) -> None:
+        """
+        Called once in the beginning.
+
+        Parameters
+        ----------
+        incremental
+            Whether the program is incremental. If the incremental flag is
+            true, there can be multiple calls to `clingo.control.Control.solve`.
+        """
+
+    def begin_step(self) -> None:
+        """
+        Marks the beginning of a block of directives passed to the solver.
+        """
+
+    def rule(self, choice: bool, head: Sequence[int], body: Sequence[int]) -> None:
+        """
+        Observe rules passed to the solver.
+
+        Parameters
+        ----------
+        choice
+            Determines if the head is a choice or a disjunction.
+        head
+            List of program atoms forming the rule head.
+        body
+            List of program literals forming the rule body.
+        """
+
+    def weight_rule(
+        self,
+        choice: bool,
+        head: Sequence[int],
+        lower_bound: int,
+        body: Sequence[Tuple[int, int]],
+    ) -> None:
+        """
+        Observe rules with one weight constraint in the body passed to the
+        solver.
+
+        Parameters
+        ----------
+        choice
+            Determines if the head is a choice or a disjunction.
+        head
+            List of program atoms forming the head of the rule.
+        lower_bound
+            The lower bound of the weight constraint in the rule body.
+        body
+            List of weighted literals (pairs of literal and weight) forming the
+            elements of the weight constraint.
+        """
+
+    def minimize(self, priority: int, literals: Sequence[Tuple[int, int]]) -> None:
+        """
+        Observe minimize directives (or weak constraints) passed to the
+        solver.
+
+        Parameters
+        ----------
+        priority
+            The priority of the directive.
+        literals
+            List of weighted literals whose sum to minimize (pairs of literal
+            and weight).
+        """
+
+    def project(self, atoms: Sequence[int]) -> None:
+        """
+        Observe projection directives passed to the solver.
+
+        Parameters
+        ----------
+        atoms
+            The program atoms to project on.
+        """
+
+    def output_atom(self, symbol: Symbol, atom: int) -> None:
+        """
+        Observe shown atoms passed to the solver.  Facts do not have an
+        associated program atom. The value of the atom is set to zero.
+
+        Parameters
+        ----------
+        symbol
+            The symbolic representation of the atom.
+        atom
+            The associated program atom (`0` for facts).
+        """
+
+    def output_term(self, symbol: Symbol, condition: Sequence[int]) -> None:
+        """
+        Observe shown terms passed to the solver.
+
+        Parameters
+        ----------
+        symbol
+            The symbolic representation of the term.
+        condition
+            List of program literals forming the condition when to show the
+            term.
+        """
+
+    def external(self, atom: int, value: TruthValue) -> None:
+        """
+        Observe external statements passed to the solver.
+
+        Parameters
+        ----------
+        atom
+            The external atom in form of a program literal.
+        value
+            The truth value of the external statement.
+        """
+
+    def assume(self, literals: Sequence[int]) -> None:
+        """
+        Observe assumption directives passed to the solver.
+
+        Parameters
+        ----------
+        literals
+            The program literals to assume (positive literals are true and
+            negative literals false for the next solve call).
+        """
+
+    def heuristic(
+        self,
+        atom: int,
+        type_: HeuristicType,
+        bias: int,
+        priority: int,
+        condition: Sequence[int],
+    ) -> None:
+        """
+        Observe heuristic directives passed to the solver.
+
+        Parameters
+        ----------
+        atom
+            The program atom heuristically modified.
+        type_
+            The type of the modification.
+        bias
+            A signed integer.
+        priority
+            An unsigned integer.
+        condition
+            List of program literals.
+        """
+
+    def acyc_edge(self, node_u: int, node_v: int, condition: Sequence[int]) -> None:
+        """
+        Observe edge directives passed to the solver.
+
+        Parameters
+        ----------
+        node_u
+            The start vertex of the edge (in form of an integer).
+        node_v
+            Тhe end vertex of the edge (in form of an integer).
+        condition
+            The list of program literals forming th condition under which to
+            add the edge.
+        """
+
+    def theory_term_number(self, term_id: int, number: int) -> None:
+        """
+        Observe numeric theory terms.
+
+        Parameters
+        ----------
+        term_id
+            The id of the term.
+        number
+            The value of the term.
+        """
+
+    def theory_term_string(self, term_id: int, name: str) -> None:
+        """
+        Observe string theory terms.
+
+        Parameters
+        ----------
+        term_id
+            The id of the term.
+        name
+            The string value of the term.
+        """
+
+    def theory_term_compound(
+        self, term_id: int, name_id_or_type: int, arguments: Sequence[int]
+    ) -> None:
+        """
+        Observe compound theory terms.
+
+        Parameters
+        ----------
+        term_id
+            The id of the term.
+        name_id_or_type
+            The name id or type of the term where the value `-1` stands for
+            tuples, `-2` for sets, `-3` for lists, or otherwise for the id of
+            the name (in form of a string term).
+        arguments
+            The arguments of the term in form of a list of term ids.
+        """
+
+    def theory_element(
+        self, element_id: int, terms: Sequence[int], condition: Sequence[int]
+    ) -> None:
+        """
+        Observe theory elements.
+
+        Parameters
+        ----------
+        element_id
+            The id of the element.
+        terms
+            The term tuple of the element in form of a list of term ids.
+        condition
+            The list of program literals forming the condition.
+        """
+
+    def theory_atom(
+        self, atom_id_or_zero: int, term_id: int, elements: Sequence[int]
+    ) -> None:
+        """
+        Observe theory atoms without guard.
+
+        Parameters
+        ----------
+        atom_id_or_zero
+            The id of the atom or zero for directives.
+        term_id
+            The term associated with the atom.
+        elements
+            The elements of the atom in form of a list of element ids.
+        """
+
+    def theory_atom_with_guard(
+        self,
+        atom_id_or_zero: int,
+        term_id: int,
+        elements: Sequence[int],
+        operator_id: int,
+        right_hand_side_id: int,
+    ) -> None:
+        """
+        Observe theory atoms with guard.
+
+        Parameters
+        ----------
+        atom_id_or_zero
+            The id of the atom or zero for directives.
+        term_id : int
+            The term associated with the atom.
+        elements
+            The elements of the atom in form of a list of element ids.
+        operator_id
+            The id of the operator (a string term).
+        right_hand_side_id
+            The id of the term on the right hand side of the atom.
+        """
+
+    def end_step(self) -> None:
+        """
+        Marks the end of a block of directives passed to the solver.
+
+        This function is called right before solving starts.
+        """
+
+
+@_ffi.def_extern(
+    onerror=_cb_error_handler("data"), name="pyclingo_observer_init_program"
+)
+def _pyclingo_observer_init_program(incremental, data):
+    observer: Observer = _ffi.from_handle(data).data
+    observer.init_program(incremental)
+    return True
+
+
+@_ffi.def_extern(onerror=_cb_error_handler("data"), name="pyclingo_observer_begin_step")
+def _pyclingo_observer_begin_step(data):
+    observer: Observer = _ffi.from_handle(data).data
+    observer.begin_step()
+    return True
+
+
+@_ffi.def_extern(onerror=_cb_error_handler("data"), name="pyclingo_observer_end_step")
+def _pyclingo_observer_end_step(data):
+    observer: Observer = _ffi.from_handle(data).data
+    observer.end_step()
+    return True
+
+
+@_ffi.def_extern(onerror=_cb_error_handler("data"), name="pyclingo_observer_rule")
+def _pyclingo_observer_rule(choice, head, head_size, body, body_size, data):
+    observer: Observer = _ffi.from_handle(data).data
+    observer.rule(
+        choice, [head[i] for i in range(head_size)], [body[i] for i in range(body_size)]
+    )
+    return True
+
+
+@_ffi.def_extern(
+    onerror=_cb_error_handler("data"), name="pyclingo_observer_weight_rule"
+)
+def _pyclingo_observer_weight_rule(
+    choice, head, head_size, lower_bound, body, body_size, data
+):
+    observer: Observer = _ffi.from_handle(data).data
+    observer.weight_rule(
+        choice,
+        [head[i] for i in range(head_size)],
+        lower_bound,
+        [(body[i].literal, body[i].weight) for i in range(body_size)],
+    )
+    return True
+
+
+@_ffi.def_extern(onerror=_cb_error_handler("data"), name="pyclingo_observer_minimize")
+def _pyclingo_observer_minimize(priority, literals, size, data):
+    observer: Observer = _ffi.from_handle(data).data
+    observer.minimize(
+        priority, [(literals[i].literal, literals[i].weight) for i in range(size)]
+    )
+    return True
+
+
+@_ffi.def_extern(onerror=_cb_error_handler("data"), name="pyclingo_observer_project")
+def _pyclingo_observer_project(atoms, size, data):
+    observer: Observer = _ffi.from_handle(data).data
+    observer.project([atoms[i] for i in range(size)])
+    return True
+
+
+@_ffi.def_extern(
+    onerror=_cb_error_handler("data"), name="pyclingo_observer_output_atom"
+)
+def _pyclingo_observer_output_atom(symbol, atom, data):
+    observer: Observer = _ffi.from_handle(data).data
+    observer.output_atom(Symbol(symbol), atom)
+    return True
+
+
+@_ffi.def_extern(
+    onerror=_cb_error_handler("data"), name="pyclingo_observer_output_term"
+)
+def _pyclingo_observer_output_term(symbol, condition, size, data):
+    observer: Observer = _ffi.from_handle(data).data
+    observer.output_term(Symbol(symbol), [condition[i] for i in range(size)])
+    return True
+
+
+@_ffi.def_extern(onerror=_cb_error_handler("data"), name="pyclingo_observer_external")
+def _pyclingo_observer_external(atom, type_, data):
+    observer: Observer = _ffi.from_handle(data).data
+    observer.external(atom, TruthValue(type_))
+    return True
+
+
+@_ffi.def_extern(onerror=_cb_error_handler("data"), name="pyclingo_observer_assume")
+def _pyclingo_observer_assume(literals, size, data):
+    observer: Observer = _ffi.from_handle(data).data
+    observer.assume([literals[i] for i in range(size)])
+    return True
+
+
+@_ffi.def_extern(onerror=_cb_error_handler("data"), name="pyclingo_observer_heuristic")
+def _pyclingo_observer_heuristic(atom, type_, bias, priority, condition, size, data):
+    observer: Observer = _ffi.from_handle(data).data
+    observer.heuristic(
+        atom, HeuristicType(type_), bias, priority, [condition[i] for i in range(size)]
+    )
+    return True
+
+
+@_ffi.def_extern(onerror=_cb_error_handler("data"), name="pyclingo_observer_acyc_edge")
+def _pyclingo_observer_acyc_edge(node_u, node_v, condition, size, data):
+    observer: Observer = _ffi.from_handle(data).data
+    observer.acyc_edge(node_u, node_v, [condition[i] for i in range(size)])
+    return True
+
+
+@_ffi.def_extern(
+    onerror=_cb_error_handler("data"), name="pyclingo_observer_theory_term_number"
+)
+def _pyclingo_observer_theory_term_number(term_id, number, data):
+    observer: Observer = _ffi.from_handle(data).data
+    observer.theory_term_number(term_id, number)
+    return True
+
+
+@_ffi.def_extern(
+    onerror=_cb_error_handler("data"), name="pyclingo_observer_theory_term_string"
+)
+def _pyclingo_observer_theory_term_string(term_id, name, data):
+    observer: Observer = _ffi.from_handle(data).data
+    observer.theory_term_string(term_id, _to_str(name))
+    return True
+
+
+@_ffi.def_extern(
+    onerror=_cb_error_handler("data"), name="pyclingo_observer_theory_term_compound"
+)
+def _pyclingo_observer_theory_term_compound(
+    term_id, name_id_or_type, arguments, size, data
+):
+    observer: Observer = _ffi.from_handle(data).data
+    observer.theory_term_compound(
+        term_id, name_id_or_type, [arguments[i] for i in range(size)]
+    )
+    return True
+
+
+@_ffi.def_extern(
+    onerror=_cb_error_handler("data"), name="pyclingo_observer_theory_element"
+)
+def _pyclingo_observer_theory_element(
+    element_id, terms, terms_size, condition, condition_size, data
+):
+    observer: Observer = _ffi.from_handle(data).data
+    observer.theory_element(
+        element_id,
+        [terms[i] for i in range(terms_size)],
+        [condition[i] for i in range(condition_size)],
+    )
+    return True
+
+
+@_ffi.def_extern(
+    onerror=_cb_error_handler("data"), name="pyclingo_observer_theory_atom"
+)
+def _pyclingo_observer_theory_atom(atom_id_or_zero, term_id, elements, size, data):
+    observer: Observer = _ffi.from_handle(data).data
+    observer.theory_atom(atom_id_or_zero, term_id, [elements[i] for i in range(size)])
+    return True
+
+
+@_ffi.def_extern(
+    onerror=_cb_error_handler("data"), name="pyclingo_observer_theory_atom_with_guard"
+)
+def _pyclingo_observer_theory_atom_with_guard(
+    atom_id_or_zero, term_id, elements, size, operator_id, right_hand_side_id, data
+):
+    observer: Observer = _ffi.from_handle(data).data
+    observer.theory_atom_with_guard(
+        atom_id_or_zero,
+        term_id,
+        [elements[i] for i in range(size)],
+        operator_id,
+        right_hand_side_id,
+    )
+    return True
+
+
+class Backend(ContextManager["Backend"]):
+    """
+    Backend object providing a low level interface to extend a logic program.
+
+    This class allows for adding statements in ASPIF format.
+
+    See Also
+    --------
+    clingo.control.Control.backend
+
+    Notes
+    -----
+    The `Backend` is a context manager and must be used with Python's `with`
+    statement.
+    """
+
+    def __init__(self, rep, error):
+        self._rep = rep
+        self._error = error
+
+    def __enter__(self):
+        self._error.clear()
+        _handle_error(_lib.clingo_backend_begin(self._rep), handler=self._error)
+        return self
+
+    def __exit__(self, exc_type, exc_val, exc_tb):
+        self._error.clear()
+        _handle_error(_lib.clingo_backend_end(self._rep), handler=self._error)
+        return False
+
+    def add_acyc_edge(self, node_u: int, node_v: int, condition: Sequence[int]) -> None:
+        """
+        Add an edge directive to the program.
+
+        Parameters
+        ----------
+        node_u
+            The start node represented as an unsigned integer.
+        node_v
+            The end node represented as an unsigned integer.
+        condition
+            List of program literals.
+        """
+        _handle_error(
+            _lib.clingo_backend_acyc_edge(
+                self._rep, node_u, node_v, condition, len(condition)
+            )
+        )
+
+    def add_assume(self, literals: Sequence[int]) -> None:
+        """
+        Add assumptions to the program.
+
+        Parameters
+        ----------
+        literals
+            The list of literals to assume true.
+        """
+        _handle_error(_lib.clingo_backend_assume(self._rep, literals, len(literals)))
+
+    def add_atom(self, symbol: Optional[Symbol] = None) -> int:
+        """
+        Return a fresh program atom or the atom associated with the given symbol.
+
+        If the given symbol does not exist in the atom base, it is added first. Such
+        atoms will be used in subequents calls to ground for instantiation.
+
+        Parameters
+        ----------
+        symbol
+            The symbol associated with the atom.
+        Returns
+        -------
+        The program atom representing the atom.
+        """
+        # pylint: disable=protected-access
+        if symbol is None:
+            p_sym = _ffi.NULL
+        else:
+            p_sym = _ffi.new("clingo_symbol_t*", symbol._rep)
+
+        self._error.clear()
+        return _c_call(
+            "clingo_atom_t",
+            _lib.clingo_backend_add_atom,
+            self._rep,
+            p_sym,
+            handler=self._error,
+        )
+
+    def add_external(self, atom: int, value: TruthValue = TruthValue.False_) -> None:
+        """
+        Mark a program atom as external optionally fixing its truth value.
+
+        Parameters
+        ----------
+        atom
+            The program atom to mark as external.
+        value
+            Optional truth value.
+
+        Notes
+        -----
+        Can also be used to release an external atom using `TruthValue.Release`.
+        """
+        _handle_error(_lib.clingo_backend_external(self._rep, atom, value.value))
+
+    def add_heuristic(
+        self,
+        atom: int,
+        type_: HeuristicType,
+        bias: int,
+        priority: int,
+        condition: Sequence[int],
+    ) -> None:
+        """
+        Add a heuristic directive to the program.
+
+        Parameters
+        ----------
+        atom
+            Program atom to heuristically modify.
+        type_
+            The type of modification.
+        bias
+            A signed integer.
+        priority
+            An unsigned integer.
+        condition
+            List of program literals.
+        """
+        _handle_error(
+            _lib.clingo_backend_heuristic(
+                self._rep, atom, type_.value, bias, priority, condition, len(condition)
+            )
+        )
+
+    def add_minimize(self, priority: int, literals: Sequence[Tuple[int, int]]) -> None:
+        """
+        Add a minimize constraint to the program.
+
+        Parameters
+        ----------
+        priority
+            Integer for the priority.
+        literals
+            List of pairs of program literals and weights.
+        """
+        _handle_error(
+            _lib.clingo_backend_minimize(self._rep, priority, literals, len(literals))
+        )
+
+    def add_project(self, atoms: Sequence[int]) -> None:
+        """
+        Add a project statement to the program.
+
+        Parameters
+        ----------
+        atoms
+            List of program atoms to project on.
+        """
+        _handle_error(_lib.clingo_backend_project(self._rep, atoms, len(atoms)))
+
+    def add_rule(
+        self, head: Sequence[int], body: Sequence[int] = [], choice: bool = False
+    ) -> None:
+        """
+        Add a disjuntive or choice rule to the program.
+
+        Parameters
+        ----------
+        head
+            The program atoms forming the rule head.
+        body
+            The program literals forming the rule body.
+        choice
+            Whether to add a disjunctive or choice rule.
+
+        Notes
+        -----
+        Integrity constraints and normal rules can be added by using an empty or
+        singleton head list, respectively.
+        """
+        # pylint: disable=dangerous-default-value
+        _handle_error(
+            _lib.clingo_backend_rule(
+                self._rep, choice, head, len(head), body, len(body)
+            )
+        )
+
+    def add_weight_rule(
+        self,
+        head: Sequence[int],
+        lower: int,
+        body: Sequence[Tuple[int, int]],
+        choice: bool = False,
+    ) -> None:
+        """
+        Add a disjuntive or choice rule with one weight constraint with a lower bound
+        in the body to the program.
+
+        Parameters
+        ----------
+        head
+            The program atoms forming the rule head.
+        lower
+            The lower bound.
+        body
+            The pairs of program literals and weights forming the elements of the
+            weight constraint.
+        choice
+            Whether to add a disjunctive or choice rule.
+        """
+        _handle_error(
+            _lib.clingo_backend_weight_rule(
+                self._rep, choice, head, len(head), lower, body, len(body)
+            )
+        )
+
+    def add_theory_term_number(self, number: int) -> int:
+        """
+        Add a numeric theory term.
+
+        Parameters
+        ----------
+        number
+            The value of the term.
+
+        Returns
+        -------
+        The id of the added term.
+        """
+        return _c_call(
+            "clingo_id_t",
+            _lib.clingo_backend_theory_term_number,
+            self._rep,
+            number,
+            handler=self._error,
+        )
+
+    def add_theory_term_string(self, string: str) -> int:
+        """
+        Add a theory term representing a string.
+
+        Parameters
+        ----------
+        string
+            The value of the term.
+
+        Returns
+        -------
+        The id of the added term.
+        """
+        return _c_call(
+            "clingo_id_t",
+            _lib.clingo_backend_theory_term_string,
+            self._rep,
+            string.encode(),
+            handler=self._error,
+        )
+
+    def add_theory_term_function(self, name: str, arguments: Sequence[int]) -> int:
+        """
+        Add a theory term representing a function.
+
+        Parameters
+        ----------
+        name
+            The name of the function.
+        arguments
+            Sequence of term ids for the function arguments.
+
+        Returns
+        -------
+        The id of the added term.
+        """
+        return _c_call(
+            "clingo_id_t",
+            _lib.clingo_backend_theory_term_function,
+            self._rep,
+            name.encode(),
+            arguments,
+            len(arguments),
+            handler=self._error,
+        )
+
+    def add_theory_term_sequence(
+        self, sequence_type: TheorySequenceType, arguments: Sequence[int]
+    ) -> int:
+        """
+        Add a theory term representing a sequence of theory terms.
+
+        Parameters
+        ----------
+        sequence_type
+            The type of the sequence
+        arguments
+            Sequence of term ids for the function arguments.
+
+        Returns
+        -------
+        The id of the added term.
+        """
+        return _c_call(
+            "clingo_id_t",
+            _lib.clingo_backend_theory_term_sequence,
+            self._rep,
+            sequence_type.value,
+            arguments,
+            len(arguments),
+            handler=self._error,
+        )
+
+    def add_theory_term_symbol(self, symbol: Symbol) -> int:
+        """
+        Create a theory term from a symbol.
+
+        Parameters
+        ----------
+        symbol
+            The symbol to convert.
+
+        Returns
+        -------
+        The id of the added term.
+        """
+        return _c_call(
+            "clingo_id_t",
+            _lib.clingo_backend_theory_term_symbol,
+            self._rep,
+            symbol._rep,
+            handler=self._error,
+        )
+
+    def add_theory_element(self, terms: Sequence[int], condition: Sequence[int]) -> int:
+        """
+        Create a theory atom element.
+
+        Parameters
+        ----------
+        terms
+            A sequence of term ids.
+        condition
+            A sequence of program literals.
+
+        Returns
+        -------
+        The id of the added element.
+        """
+        return _c_call(
+            "clingo_id_t",
+            _lib.clingo_backend_theory_element,
+            self._rep,
+            terms,
+            len(terms),
+            condition,
+            len(condition),
+            handler=self._error,
+        )
+
+    def add_theory_atom(
+        self,
+        term_id: int,
+        elements: Sequence[int],
+        atom_id_or_zero: Optional[int] = None,
+    ) -> int:
+        """
+        Add a theory atom without a guard.
+
+        If no atom_id is given, a fresh atom id is assigned.
+
+        In case an atom id is given and an equivalent theory atom already
+        exists, the given atom id is ignored.
+
+        To declare a defined theory atom, a rule defining the program atom
+        should be added. Otherwise, the theory atom is considered an external
+        body occurrence.
+
+        Parameters
+        ----------
+        term_id
+            The id of the term associated with the theory atom.
+        elements
+            A sequence of ids of theory atom elements.
+        atom_id_or_zero
+            An optional program atom or zero for theory directives.
+        """
+        if atom_id_or_zero is None:
+            atom_id_or_zero = 0xffffffff
+        return _c_call(
+            "clingo_atom_t",
+            _lib.clingo_backend_theory_atom,
+            self._rep,
+            atom_id_or_zero,
+            term_id,
+            elements,
+            len(elements),
+            handler=self._error,
+        )
+
+    def add_theory_atom_with_guard(
+        self,
+        term_id: int,
+        elements: Sequence[int],
+        operator: str,
+        right_hand_side_id: int,
+        atom_id_or_zero: Optional[int] = None,
+    ) -> int:
+        """
+        Add a theory atom with a guard.
+
+        Parameters
+        ----------
+        term_id
+            The id of the term associated with the theory atom.
+        elements
+            A sequence of ids of theory atom elements.
+        operator
+            String representing a theory operator.
+        right_hand_side_id
+            Term id for the term on the right hand side.
+        atom_id_or_zero
+            A optional program atom or zero for theory directives.
+
+        See Also
+        --------
+        Backend.add_theory_atom
+        """
+        if atom_id_or_zero is None:
+            atom_id_or_zero = 0xffffffff
+        return _c_call(
+            "clingo_atom_t",
+            _lib.clingo_backend_theory_atom_with_guard,
+            self._rep,
+            atom_id_or_zero,
+            term_id,
+            elements,
+            len(elements),
+            operator.encode(),
+            right_hand_side_id,
+            handler=self._error,
+        )
+
+
+
+
+
+
+
+
+
+

Classes

+
+
+class Backend +(rep, error) +
+
+

Backend object providing a low level interface to extend a logic program.

+

This class allows for adding statements in ASPIF format.

+

See Also

+

Control.backend()

+

Notes

+

The Backend is a context manager and must be used with Python's with +statement.

+
+ +Expand source code + +
class Backend(ContextManager["Backend"]):
+    """
+    Backend object providing a low level interface to extend a logic program.
+
+    This class allows for adding statements in ASPIF format.
+
+    See Also
+    --------
+    clingo.control.Control.backend
+
+    Notes
+    -----
+    The `Backend` is a context manager and must be used with Python's `with`
+    statement.
+    """
+
+    def __init__(self, rep, error):
+        self._rep = rep
+        self._error = error
+
+    def __enter__(self):
+        self._error.clear()
+        _handle_error(_lib.clingo_backend_begin(self._rep), handler=self._error)
+        return self
+
+    def __exit__(self, exc_type, exc_val, exc_tb):
+        self._error.clear()
+        _handle_error(_lib.clingo_backend_end(self._rep), handler=self._error)
+        return False
+
+    def add_acyc_edge(self, node_u: int, node_v: int, condition: Sequence[int]) -> None:
+        """
+        Add an edge directive to the program.
+
+        Parameters
+        ----------
+        node_u
+            The start node represented as an unsigned integer.
+        node_v
+            The end node represented as an unsigned integer.
+        condition
+            List of program literals.
+        """
+        _handle_error(
+            _lib.clingo_backend_acyc_edge(
+                self._rep, node_u, node_v, condition, len(condition)
+            )
+        )
+
+    def add_assume(self, literals: Sequence[int]) -> None:
+        """
+        Add assumptions to the program.
+
+        Parameters
+        ----------
+        literals
+            The list of literals to assume true.
+        """
+        _handle_error(_lib.clingo_backend_assume(self._rep, literals, len(literals)))
+
+    def add_atom(self, symbol: Optional[Symbol] = None) -> int:
+        """
+        Return a fresh program atom or the atom associated with the given symbol.
+
+        If the given symbol does not exist in the atom base, it is added first. Such
+        atoms will be used in subequents calls to ground for instantiation.
+
+        Parameters
+        ----------
+        symbol
+            The symbol associated with the atom.
+        Returns
+        -------
+        The program atom representing the atom.
+        """
+        # pylint: disable=protected-access
+        if symbol is None:
+            p_sym = _ffi.NULL
+        else:
+            p_sym = _ffi.new("clingo_symbol_t*", symbol._rep)
+
+        self._error.clear()
+        return _c_call(
+            "clingo_atom_t",
+            _lib.clingo_backend_add_atom,
+            self._rep,
+            p_sym,
+            handler=self._error,
+        )
+
+    def add_external(self, atom: int, value: TruthValue = TruthValue.False_) -> None:
+        """
+        Mark a program atom as external optionally fixing its truth value.
+
+        Parameters
+        ----------
+        atom
+            The program atom to mark as external.
+        value
+            Optional truth value.
+
+        Notes
+        -----
+        Can also be used to release an external atom using `TruthValue.Release`.
+        """
+        _handle_error(_lib.clingo_backend_external(self._rep, atom, value.value))
+
+    def add_heuristic(
+        self,
+        atom: int,
+        type_: HeuristicType,
+        bias: int,
+        priority: int,
+        condition: Sequence[int],
+    ) -> None:
+        """
+        Add a heuristic directive to the program.
+
+        Parameters
+        ----------
+        atom
+            Program atom to heuristically modify.
+        type_
+            The type of modification.
+        bias
+            A signed integer.
+        priority
+            An unsigned integer.
+        condition
+            List of program literals.
+        """
+        _handle_error(
+            _lib.clingo_backend_heuristic(
+                self._rep, atom, type_.value, bias, priority, condition, len(condition)
+            )
+        )
+
+    def add_minimize(self, priority: int, literals: Sequence[Tuple[int, int]]) -> None:
+        """
+        Add a minimize constraint to the program.
+
+        Parameters
+        ----------
+        priority
+            Integer for the priority.
+        literals
+            List of pairs of program literals and weights.
+        """
+        _handle_error(
+            _lib.clingo_backend_minimize(self._rep, priority, literals, len(literals))
+        )
+
+    def add_project(self, atoms: Sequence[int]) -> None:
+        """
+        Add a project statement to the program.
+
+        Parameters
+        ----------
+        atoms
+            List of program atoms to project on.
+        """
+        _handle_error(_lib.clingo_backend_project(self._rep, atoms, len(atoms)))
+
+    def add_rule(
+        self, head: Sequence[int], body: Sequence[int] = [], choice: bool = False
+    ) -> None:
+        """
+        Add a disjuntive or choice rule to the program.
+
+        Parameters
+        ----------
+        head
+            The program atoms forming the rule head.
+        body
+            The program literals forming the rule body.
+        choice
+            Whether to add a disjunctive or choice rule.
+
+        Notes
+        -----
+        Integrity constraints and normal rules can be added by using an empty or
+        singleton head list, respectively.
+        """
+        # pylint: disable=dangerous-default-value
+        _handle_error(
+            _lib.clingo_backend_rule(
+                self._rep, choice, head, len(head), body, len(body)
+            )
+        )
+
+    def add_weight_rule(
+        self,
+        head: Sequence[int],
+        lower: int,
+        body: Sequence[Tuple[int, int]],
+        choice: bool = False,
+    ) -> None:
+        """
+        Add a disjuntive or choice rule with one weight constraint with a lower bound
+        in the body to the program.
+
+        Parameters
+        ----------
+        head
+            The program atoms forming the rule head.
+        lower
+            The lower bound.
+        body
+            The pairs of program literals and weights forming the elements of the
+            weight constraint.
+        choice
+            Whether to add a disjunctive or choice rule.
+        """
+        _handle_error(
+            _lib.clingo_backend_weight_rule(
+                self._rep, choice, head, len(head), lower, body, len(body)
+            )
+        )
+
+    def add_theory_term_number(self, number: int) -> int:
+        """
+        Add a numeric theory term.
+
+        Parameters
+        ----------
+        number
+            The value of the term.
+
+        Returns
+        -------
+        The id of the added term.
+        """
+        return _c_call(
+            "clingo_id_t",
+            _lib.clingo_backend_theory_term_number,
+            self._rep,
+            number,
+            handler=self._error,
+        )
+
+    def add_theory_term_string(self, string: str) -> int:
+        """
+        Add a theory term representing a string.
+
+        Parameters
+        ----------
+        string
+            The value of the term.
+
+        Returns
+        -------
+        The id of the added term.
+        """
+        return _c_call(
+            "clingo_id_t",
+            _lib.clingo_backend_theory_term_string,
+            self._rep,
+            string.encode(),
+            handler=self._error,
+        )
+
+    def add_theory_term_function(self, name: str, arguments: Sequence[int]) -> int:
+        """
+        Add a theory term representing a function.
+
+        Parameters
+        ----------
+        name
+            The name of the function.
+        arguments
+            Sequence of term ids for the function arguments.
+
+        Returns
+        -------
+        The id of the added term.
+        """
+        return _c_call(
+            "clingo_id_t",
+            _lib.clingo_backend_theory_term_function,
+            self._rep,
+            name.encode(),
+            arguments,
+            len(arguments),
+            handler=self._error,
+        )
+
+    def add_theory_term_sequence(
+        self, sequence_type: TheorySequenceType, arguments: Sequence[int]
+    ) -> int:
+        """
+        Add a theory term representing a sequence of theory terms.
+
+        Parameters
+        ----------
+        sequence_type
+            The type of the sequence
+        arguments
+            Sequence of term ids for the function arguments.
+
+        Returns
+        -------
+        The id of the added term.
+        """
+        return _c_call(
+            "clingo_id_t",
+            _lib.clingo_backend_theory_term_sequence,
+            self._rep,
+            sequence_type.value,
+            arguments,
+            len(arguments),
+            handler=self._error,
+        )
+
+    def add_theory_term_symbol(self, symbol: Symbol) -> int:
+        """
+        Create a theory term from a symbol.
+
+        Parameters
+        ----------
+        symbol
+            The symbol to convert.
+
+        Returns
+        -------
+        The id of the added term.
+        """
+        return _c_call(
+            "clingo_id_t",
+            _lib.clingo_backend_theory_term_symbol,
+            self._rep,
+            symbol._rep,
+            handler=self._error,
+        )
+
+    def add_theory_element(self, terms: Sequence[int], condition: Sequence[int]) -> int:
+        """
+        Create a theory atom element.
+
+        Parameters
+        ----------
+        terms
+            A sequence of term ids.
+        condition
+            A sequence of program literals.
+
+        Returns
+        -------
+        The id of the added element.
+        """
+        return _c_call(
+            "clingo_id_t",
+            _lib.clingo_backend_theory_element,
+            self._rep,
+            terms,
+            len(terms),
+            condition,
+            len(condition),
+            handler=self._error,
+        )
+
+    def add_theory_atom(
+        self,
+        term_id: int,
+        elements: Sequence[int],
+        atom_id_or_zero: Optional[int] = None,
+    ) -> int:
+        """
+        Add a theory atom without a guard.
+
+        If no atom_id is given, a fresh atom id is assigned.
+
+        In case an atom id is given and an equivalent theory atom already
+        exists, the given atom id is ignored.
+
+        To declare a defined theory atom, a rule defining the program atom
+        should be added. Otherwise, the theory atom is considered an external
+        body occurrence.
+
+        Parameters
+        ----------
+        term_id
+            The id of the term associated with the theory atom.
+        elements
+            A sequence of ids of theory atom elements.
+        atom_id_or_zero
+            An optional program atom or zero for theory directives.
+        """
+        if atom_id_or_zero is None:
+            atom_id_or_zero = 0xffffffff
+        return _c_call(
+            "clingo_atom_t",
+            _lib.clingo_backend_theory_atom,
+            self._rep,
+            atom_id_or_zero,
+            term_id,
+            elements,
+            len(elements),
+            handler=self._error,
+        )
+
+    def add_theory_atom_with_guard(
+        self,
+        term_id: int,
+        elements: Sequence[int],
+        operator: str,
+        right_hand_side_id: int,
+        atom_id_or_zero: Optional[int] = None,
+    ) -> int:
+        """
+        Add a theory atom with a guard.
+
+        Parameters
+        ----------
+        term_id
+            The id of the term associated with the theory atom.
+        elements
+            A sequence of ids of theory atom elements.
+        operator
+            String representing a theory operator.
+        right_hand_side_id
+            Term id for the term on the right hand side.
+        atom_id_or_zero
+            A optional program atom or zero for theory directives.
+
+        See Also
+        --------
+        Backend.add_theory_atom
+        """
+        if atom_id_or_zero is None:
+            atom_id_or_zero = 0xffffffff
+        return _c_call(
+            "clingo_atom_t",
+            _lib.clingo_backend_theory_atom_with_guard,
+            self._rep,
+            atom_id_or_zero,
+            term_id,
+            elements,
+            len(elements),
+            operator.encode(),
+            right_hand_side_id,
+            handler=self._error,
+        )
+
+

Ancestors

+
    +
  • contextlib.AbstractContextManager
  • +
  • abc.ABC
  • +
  • typing.Generic
  • +
+

Methods

+
+
+def add_acyc_edge(self, node_u: int, node_v: int, condition: Sequence[int]) ‑> None +
+
+

Add an edge directive to the program.

+

Parameters

+
+
node_u
+
The start node represented as an unsigned integer.
+
node_v
+
The end node represented as an unsigned integer.
+
condition
+
List of program literals.
+
+
+ +Expand source code + +
def add_acyc_edge(self, node_u: int, node_v: int, condition: Sequence[int]) -> None:
+    """
+    Add an edge directive to the program.
+
+    Parameters
+    ----------
+    node_u
+        The start node represented as an unsigned integer.
+    node_v
+        The end node represented as an unsigned integer.
+    condition
+        List of program literals.
+    """
+    _handle_error(
+        _lib.clingo_backend_acyc_edge(
+            self._rep, node_u, node_v, condition, len(condition)
+        )
+    )
+
+
+
+def add_assume(self, literals: Sequence[int]) ‑> None +
+
+

Add assumptions to the program.

+

Parameters

+
+
literals
+
The list of literals to assume true.
+
+
+ +Expand source code + +
def add_assume(self, literals: Sequence[int]) -> None:
+    """
+    Add assumptions to the program.
+
+    Parameters
+    ----------
+    literals
+        The list of literals to assume true.
+    """
+    _handle_error(_lib.clingo_backend_assume(self._rep, literals, len(literals)))
+
+
+
+def add_atom(self, symbol: Optional[Symbol] = None) ‑> int +
+
+

Return a fresh program atom or the atom associated with the given symbol.

+

If the given symbol does not exist in the atom base, it is added first. Such +atoms will be used in subequents calls to ground for instantiation.

+

Parameters

+
+
symbol
+
The symbol associated with the atom.
+
+

Returns

+

The program atom representing the atom.

+
+ +Expand source code + +
def add_atom(self, symbol: Optional[Symbol] = None) -> int:
+    """
+    Return a fresh program atom or the atom associated with the given symbol.
+
+    If the given symbol does not exist in the atom base, it is added first. Such
+    atoms will be used in subequents calls to ground for instantiation.
+
+    Parameters
+    ----------
+    symbol
+        The symbol associated with the atom.
+    Returns
+    -------
+    The program atom representing the atom.
+    """
+    # pylint: disable=protected-access
+    if symbol is None:
+        p_sym = _ffi.NULL
+    else:
+        p_sym = _ffi.new("clingo_symbol_t*", symbol._rep)
+
+    self._error.clear()
+    return _c_call(
+        "clingo_atom_t",
+        _lib.clingo_backend_add_atom,
+        self._rep,
+        p_sym,
+        handler=self._error,
+    )
+
+
+
+def add_external(self, atom: int, value: TruthValue = TruthValue.False_) ‑> None +
+
+

Mark a program atom as external optionally fixing its truth value.

+

Parameters

+
+
atom
+
The program atom to mark as external.
+
value
+
Optional truth value.
+
+

Notes

+

Can also be used to release an external atom using TruthValue.Release.

+
+ +Expand source code + +
def add_external(self, atom: int, value: TruthValue = TruthValue.False_) -> None:
+    """
+    Mark a program atom as external optionally fixing its truth value.
+
+    Parameters
+    ----------
+    atom
+        The program atom to mark as external.
+    value
+        Optional truth value.
+
+    Notes
+    -----
+    Can also be used to release an external atom using `TruthValue.Release`.
+    """
+    _handle_error(_lib.clingo_backend_external(self._rep, atom, value.value))
+
+
+
+def add_heuristic(self, atom: int, type_: HeuristicType, bias: int, priority: int, condition: Sequence[int]) ‑> None +
+
+

Add a heuristic directive to the program.

+

Parameters

+
+
atom
+
Program atom to heuristically modify.
+
type_
+
The type of modification.
+
bias
+
A signed integer.
+
priority
+
An unsigned integer.
+
condition
+
List of program literals.
+
+
+ +Expand source code + +
def add_heuristic(
+    self,
+    atom: int,
+    type_: HeuristicType,
+    bias: int,
+    priority: int,
+    condition: Sequence[int],
+) -> None:
+    """
+    Add a heuristic directive to the program.
+
+    Parameters
+    ----------
+    atom
+        Program atom to heuristically modify.
+    type_
+        The type of modification.
+    bias
+        A signed integer.
+    priority
+        An unsigned integer.
+    condition
+        List of program literals.
+    """
+    _handle_error(
+        _lib.clingo_backend_heuristic(
+            self._rep, atom, type_.value, bias, priority, condition, len(condition)
+        )
+    )
+
+
+
+def add_minimize(self, priority: int, literals: Sequence[Tuple[int, int]]) ‑> None +
+
+

Add a minimize constraint to the program.

+

Parameters

+
+
priority
+
Integer for the priority.
+
literals
+
List of pairs of program literals and weights.
+
+
+ +Expand source code + +
def add_minimize(self, priority: int, literals: Sequence[Tuple[int, int]]) -> None:
+    """
+    Add a minimize constraint to the program.
+
+    Parameters
+    ----------
+    priority
+        Integer for the priority.
+    literals
+        List of pairs of program literals and weights.
+    """
+    _handle_error(
+        _lib.clingo_backend_minimize(self._rep, priority, literals, len(literals))
+    )
+
+
+
+def add_project(self, atoms: Sequence[int]) ‑> None +
+
+

Add a project statement to the program.

+

Parameters

+
+
atoms
+
List of program atoms to project on.
+
+
+ +Expand source code + +
def add_project(self, atoms: Sequence[int]) -> None:
+    """
+    Add a project statement to the program.
+
+    Parameters
+    ----------
+    atoms
+        List of program atoms to project on.
+    """
+    _handle_error(_lib.clingo_backend_project(self._rep, atoms, len(atoms)))
+
+
+
+def add_rule(self, head: Sequence[int], body: Sequence[int] = [], choice: bool = False) ‑> None +
+
+

Add a disjuntive or choice rule to the program.

+

Parameters

+
+
head
+
The program atoms forming the rule head.
+
body
+
The program literals forming the rule body.
+
choice
+
Whether to add a disjunctive or choice rule.
+
+

Notes

+

Integrity constraints and normal rules can be added by using an empty or +singleton head list, respectively.

+
+ +Expand source code + +
def add_rule(
+    self, head: Sequence[int], body: Sequence[int] = [], choice: bool = False
+) -> None:
+    """
+    Add a disjuntive or choice rule to the program.
+
+    Parameters
+    ----------
+    head
+        The program atoms forming the rule head.
+    body
+        The program literals forming the rule body.
+    choice
+        Whether to add a disjunctive or choice rule.
+
+    Notes
+    -----
+    Integrity constraints and normal rules can be added by using an empty or
+    singleton head list, respectively.
+    """
+    # pylint: disable=dangerous-default-value
+    _handle_error(
+        _lib.clingo_backend_rule(
+            self._rep, choice, head, len(head), body, len(body)
+        )
+    )
+
+
+
+def add_theory_atom(self, term_id: int, elements: Sequence[int], atom_id_or_zero: Optional[int] = None) ‑> int +
+
+

Add a theory atom without a guard.

+

If no atom_id is given, a fresh atom id is assigned.

+

In case an atom id is given and an equivalent theory atom already +exists, the given atom id is ignored.

+

To declare a defined theory atom, a rule defining the program atom +should be added. Otherwise, the theory atom is considered an external +body occurrence.

+

Parameters

+
+
term_id
+
The id of the term associated with the theory atom.
+
elements
+
A sequence of ids of theory atom elements.
+
atom_id_or_zero
+
An optional program atom or zero for theory directives.
+
+
+ +Expand source code + +
def add_theory_atom(
+    self,
+    term_id: int,
+    elements: Sequence[int],
+    atom_id_or_zero: Optional[int] = None,
+) -> int:
+    """
+    Add a theory atom without a guard.
+
+    If no atom_id is given, a fresh atom id is assigned.
+
+    In case an atom id is given and an equivalent theory atom already
+    exists, the given atom id is ignored.
+
+    To declare a defined theory atom, a rule defining the program atom
+    should be added. Otherwise, the theory atom is considered an external
+    body occurrence.
+
+    Parameters
+    ----------
+    term_id
+        The id of the term associated with the theory atom.
+    elements
+        A sequence of ids of theory atom elements.
+    atom_id_or_zero
+        An optional program atom or zero for theory directives.
+    """
+    if atom_id_or_zero is None:
+        atom_id_or_zero = 0xffffffff
+    return _c_call(
+        "clingo_atom_t",
+        _lib.clingo_backend_theory_atom,
+        self._rep,
+        atom_id_or_zero,
+        term_id,
+        elements,
+        len(elements),
+        handler=self._error,
+    )
+
+
+
+def add_theory_atom_with_guard(self, term_id: int, elements: Sequence[int], operator: str, right_hand_side_id: int, atom_id_or_zero: Optional[int] = None) ‑> int +
+
+

Add a theory atom with a guard.

+

Parameters

+
+
term_id
+
The id of the term associated with the theory atom.
+
elements
+
A sequence of ids of theory atom elements.
+
operator
+
String representing a theory operator.
+
right_hand_side_id
+
Term id for the term on the right hand side.
+
atom_id_or_zero
+
A optional program atom or zero for theory directives.
+
+

See Also

+

Backend.add_theory_atom()

+
+ +Expand source code + +
def add_theory_atom_with_guard(
+    self,
+    term_id: int,
+    elements: Sequence[int],
+    operator: str,
+    right_hand_side_id: int,
+    atom_id_or_zero: Optional[int] = None,
+) -> int:
+    """
+    Add a theory atom with a guard.
+
+    Parameters
+    ----------
+    term_id
+        The id of the term associated with the theory atom.
+    elements
+        A sequence of ids of theory atom elements.
+    operator
+        String representing a theory operator.
+    right_hand_side_id
+        Term id for the term on the right hand side.
+    atom_id_or_zero
+        A optional program atom or zero for theory directives.
+
+    See Also
+    --------
+    Backend.add_theory_atom
+    """
+    if atom_id_or_zero is None:
+        atom_id_or_zero = 0xffffffff
+    return _c_call(
+        "clingo_atom_t",
+        _lib.clingo_backend_theory_atom_with_guard,
+        self._rep,
+        atom_id_or_zero,
+        term_id,
+        elements,
+        len(elements),
+        operator.encode(),
+        right_hand_side_id,
+        handler=self._error,
+    )
+
+
+
+def add_theory_element(self, terms: Sequence[int], condition: Sequence[int]) ‑> int +
+
+

Create a theory atom element.

+

Parameters

+
+
terms
+
A sequence of term ids.
+
condition
+
A sequence of program literals.
+
+

Returns

+

The id of the added element.

+
+ +Expand source code + +
def add_theory_element(self, terms: Sequence[int], condition: Sequence[int]) -> int:
+    """
+    Create a theory atom element.
+
+    Parameters
+    ----------
+    terms
+        A sequence of term ids.
+    condition
+        A sequence of program literals.
+
+    Returns
+    -------
+    The id of the added element.
+    """
+    return _c_call(
+        "clingo_id_t",
+        _lib.clingo_backend_theory_element,
+        self._rep,
+        terms,
+        len(terms),
+        condition,
+        len(condition),
+        handler=self._error,
+    )
+
+
+
+def add_theory_term_function(self, name: str, arguments: Sequence[int]) ‑> int +
+
+

Add a theory term representing a function.

+

Parameters

+
+
name
+
The name of the function.
+
arguments
+
Sequence of term ids for the function arguments.
+
+

Returns

+

The id of the added term.

+
+ +Expand source code + +
def add_theory_term_function(self, name: str, arguments: Sequence[int]) -> int:
+    """
+    Add a theory term representing a function.
+
+    Parameters
+    ----------
+    name
+        The name of the function.
+    arguments
+        Sequence of term ids for the function arguments.
+
+    Returns
+    -------
+    The id of the added term.
+    """
+    return _c_call(
+        "clingo_id_t",
+        _lib.clingo_backend_theory_term_function,
+        self._rep,
+        name.encode(),
+        arguments,
+        len(arguments),
+        handler=self._error,
+    )
+
+
+
+def add_theory_term_number(self, number: int) ‑> int +
+
+

Add a numeric theory term.

+

Parameters

+
+
number
+
The value of the term.
+
+

Returns

+

The id of the added term.

+
+ +Expand source code + +
def add_theory_term_number(self, number: int) -> int:
+    """
+    Add a numeric theory term.
+
+    Parameters
+    ----------
+    number
+        The value of the term.
+
+    Returns
+    -------
+    The id of the added term.
+    """
+    return _c_call(
+        "clingo_id_t",
+        _lib.clingo_backend_theory_term_number,
+        self._rep,
+        number,
+        handler=self._error,
+    )
+
+
+
+def add_theory_term_sequence(self, sequence_type: TheorySequenceType, arguments: Sequence[int]) ‑> int +
+
+

Add a theory term representing a sequence of theory terms.

+

Parameters

+
+
sequence_type
+
The type of the sequence
+
arguments
+
Sequence of term ids for the function arguments.
+
+

Returns

+

The id of the added term.

+
+ +Expand source code + +
def add_theory_term_sequence(
+    self, sequence_type: TheorySequenceType, arguments: Sequence[int]
+) -> int:
+    """
+    Add a theory term representing a sequence of theory terms.
+
+    Parameters
+    ----------
+    sequence_type
+        The type of the sequence
+    arguments
+        Sequence of term ids for the function arguments.
+
+    Returns
+    -------
+    The id of the added term.
+    """
+    return _c_call(
+        "clingo_id_t",
+        _lib.clingo_backend_theory_term_sequence,
+        self._rep,
+        sequence_type.value,
+        arguments,
+        len(arguments),
+        handler=self._error,
+    )
+
+
+
+def add_theory_term_string(self, string: str) ‑> int +
+
+

Add a theory term representing a string.

+

Parameters

+
+
string
+
The value of the term.
+
+

Returns

+

The id of the added term.

+
+ +Expand source code + +
def add_theory_term_string(self, string: str) -> int:
+    """
+    Add a theory term representing a string.
+
+    Parameters
+    ----------
+    string
+        The value of the term.
+
+    Returns
+    -------
+    The id of the added term.
+    """
+    return _c_call(
+        "clingo_id_t",
+        _lib.clingo_backend_theory_term_string,
+        self._rep,
+        string.encode(),
+        handler=self._error,
+    )
+
+
+
+def add_theory_term_symbol(self, symbol: Symbol) ‑> int +
+
+

Create a theory term from a symbol.

+

Parameters

+
+
symbol
+
The symbol to convert.
+
+

Returns

+

The id of the added term.

+
+ +Expand source code + +
def add_theory_term_symbol(self, symbol: Symbol) -> int:
+    """
+    Create a theory term from a symbol.
+
+    Parameters
+    ----------
+    symbol
+        The symbol to convert.
+
+    Returns
+    -------
+    The id of the added term.
+    """
+    return _c_call(
+        "clingo_id_t",
+        _lib.clingo_backend_theory_term_symbol,
+        self._rep,
+        symbol._rep,
+        handler=self._error,
+    )
+
+
+
+def add_weight_rule(self, head: Sequence[int], lower: int, body: Sequence[Tuple[int, int]], choice: bool = False) ‑> None +
+
+

Add a disjuntive or choice rule with one weight constraint with a lower bound +in the body to the program.

+

Parameters

+
+
head
+
The program atoms forming the rule head.
+
lower
+
The lower bound.
+
body
+
The pairs of program literals and weights forming the elements of the +weight constraint.
+
choice
+
Whether to add a disjunctive or choice rule.
+
+
+ +Expand source code + +
def add_weight_rule(
+    self,
+    head: Sequence[int],
+    lower: int,
+    body: Sequence[Tuple[int, int]],
+    choice: bool = False,
+) -> None:
+    """
+    Add a disjuntive or choice rule with one weight constraint with a lower bound
+    in the body to the program.
+
+    Parameters
+    ----------
+    head
+        The program atoms forming the rule head.
+    lower
+        The lower bound.
+    body
+        The pairs of program literals and weights forming the elements of the
+        weight constraint.
+    choice
+        Whether to add a disjunctive or choice rule.
+    """
+    _handle_error(
+        _lib.clingo_backend_weight_rule(
+            self._rep, choice, head, len(head), lower, body, len(body)
+        )
+    )
+
+
+
+
+
+class HeuristicType +(value, names=None, *, module=None, qualname=None, type=None, start=1) +
+
+

Enumeration of the different heuristic types.

+
+ +Expand source code + +
class HeuristicType(OrderedEnum):
+    """
+    Enumeration of the different heuristic types.
+    """
+
+    Factor = _lib.clingo_heuristic_type_factor
+    """
+    Heuristic modification to set the decaying factor of an atom.
+    """
+    False_ = _lib.clingo_heuristic_type_false
+    """
+    Heuristic modification to make an atom false.
+    """
+    Init = _lib.clingo_heuristic_type_init
+    """
+    Heuristic modification to set the inital score of an atom.
+    """
+    Level = _lib.clingo_heuristic_type_level
+    """
+    Heuristic modification to set the level of an atom.
+    """
+    Sign = _lib.clingo_heuristic_type_sign
+    """
+    Heuristic modification to set the sign of an atom.
+    """
+    True_ = _lib.clingo_heuristic_type_true
+    """
+    Heuristic modification to make an atom true.
+    """
+
+

Ancestors

+ +

Class variables

+
+
var Factor
+
+

Heuristic modification to set the decaying factor of an atom.

+
+
var False_
+
+

Heuristic modification to make an atom false.

+
+
var Init
+
+

Heuristic modification to set the inital score of an atom.

+
+
var Level
+
+

Heuristic modification to set the level of an atom.

+
+
var Sign
+
+

Heuristic modification to set the sign of an atom.

+
+
var True_
+
+

Heuristic modification to make an atom true.

+
+
+
+
+class Observer +
+
+

Interface that has to be implemented to inspect rules produced during +grounding.

+

See Also

+

Control.register_observer()

+

Notes

+

Not all functions the Observer interface have to be implemented and can +be omitted if not needed.

+
+ +Expand source code + +
class Observer(metaclass=ABCMeta):
+    """
+    Interface that has to be implemented to inspect rules produced during
+    grounding.
+
+    See Also
+    --------
+    clingo.control.Control.register_observer
+
+    Notes
+    -----
+    Not all functions the `Observer` interface have to be implemented and can
+    be omitted if not needed.
+    """
+
+    def init_program(self, incremental: bool) -> None:
+        """
+        Called once in the beginning.
+
+        Parameters
+        ----------
+        incremental
+            Whether the program is incremental. If the incremental flag is
+            true, there can be multiple calls to `clingo.control.Control.solve`.
+        """
+
+    def begin_step(self) -> None:
+        """
+        Marks the beginning of a block of directives passed to the solver.
+        """
+
+    def rule(self, choice: bool, head: Sequence[int], body: Sequence[int]) -> None:
+        """
+        Observe rules passed to the solver.
+
+        Parameters
+        ----------
+        choice
+            Determines if the head is a choice or a disjunction.
+        head
+            List of program atoms forming the rule head.
+        body
+            List of program literals forming the rule body.
+        """
+
+    def weight_rule(
+        self,
+        choice: bool,
+        head: Sequence[int],
+        lower_bound: int,
+        body: Sequence[Tuple[int, int]],
+    ) -> None:
+        """
+        Observe rules with one weight constraint in the body passed to the
+        solver.
+
+        Parameters
+        ----------
+        choice
+            Determines if the head is a choice or a disjunction.
+        head
+            List of program atoms forming the head of the rule.
+        lower_bound
+            The lower bound of the weight constraint in the rule body.
+        body
+            List of weighted literals (pairs of literal and weight) forming the
+            elements of the weight constraint.
+        """
+
+    def minimize(self, priority: int, literals: Sequence[Tuple[int, int]]) -> None:
+        """
+        Observe minimize directives (or weak constraints) passed to the
+        solver.
+
+        Parameters
+        ----------
+        priority
+            The priority of the directive.
+        literals
+            List of weighted literals whose sum to minimize (pairs of literal
+            and weight).
+        """
+
+    def project(self, atoms: Sequence[int]) -> None:
+        """
+        Observe projection directives passed to the solver.
+
+        Parameters
+        ----------
+        atoms
+            The program atoms to project on.
+        """
+
+    def output_atom(self, symbol: Symbol, atom: int) -> None:
+        """
+        Observe shown atoms passed to the solver.  Facts do not have an
+        associated program atom. The value of the atom is set to zero.
+
+        Parameters
+        ----------
+        symbol
+            The symbolic representation of the atom.
+        atom
+            The associated program atom (`0` for facts).
+        """
+
+    def output_term(self, symbol: Symbol, condition: Sequence[int]) -> None:
+        """
+        Observe shown terms passed to the solver.
+
+        Parameters
+        ----------
+        symbol
+            The symbolic representation of the term.
+        condition
+            List of program literals forming the condition when to show the
+            term.
+        """
+
+    def external(self, atom: int, value: TruthValue) -> None:
+        """
+        Observe external statements passed to the solver.
+
+        Parameters
+        ----------
+        atom
+            The external atom in form of a program literal.
+        value
+            The truth value of the external statement.
+        """
+
+    def assume(self, literals: Sequence[int]) -> None:
+        """
+        Observe assumption directives passed to the solver.
+
+        Parameters
+        ----------
+        literals
+            The program literals to assume (positive literals are true and
+            negative literals false for the next solve call).
+        """
+
+    def heuristic(
+        self,
+        atom: int,
+        type_: HeuristicType,
+        bias: int,
+        priority: int,
+        condition: Sequence[int],
+    ) -> None:
+        """
+        Observe heuristic directives passed to the solver.
+
+        Parameters
+        ----------
+        atom
+            The program atom heuristically modified.
+        type_
+            The type of the modification.
+        bias
+            A signed integer.
+        priority
+            An unsigned integer.
+        condition
+            List of program literals.
+        """
+
+    def acyc_edge(self, node_u: int, node_v: int, condition: Sequence[int]) -> None:
+        """
+        Observe edge directives passed to the solver.
+
+        Parameters
+        ----------
+        node_u
+            The start vertex of the edge (in form of an integer).
+        node_v
+            Тhe end vertex of the edge (in form of an integer).
+        condition
+            The list of program literals forming th condition under which to
+            add the edge.
+        """
+
+    def theory_term_number(self, term_id: int, number: int) -> None:
+        """
+        Observe numeric theory terms.
+
+        Parameters
+        ----------
+        term_id
+            The id of the term.
+        number
+            The value of the term.
+        """
+
+    def theory_term_string(self, term_id: int, name: str) -> None:
+        """
+        Observe string theory terms.
+
+        Parameters
+        ----------
+        term_id
+            The id of the term.
+        name
+            The string value of the term.
+        """
+
+    def theory_term_compound(
+        self, term_id: int, name_id_or_type: int, arguments: Sequence[int]
+    ) -> None:
+        """
+        Observe compound theory terms.
+
+        Parameters
+        ----------
+        term_id
+            The id of the term.
+        name_id_or_type
+            The name id or type of the term where the value `-1` stands for
+            tuples, `-2` for sets, `-3` for lists, or otherwise for the id of
+            the name (in form of a string term).
+        arguments
+            The arguments of the term in form of a list of term ids.
+        """
+
+    def theory_element(
+        self, element_id: int, terms: Sequence[int], condition: Sequence[int]
+    ) -> None:
+        """
+        Observe theory elements.
+
+        Parameters
+        ----------
+        element_id
+            The id of the element.
+        terms
+            The term tuple of the element in form of a list of term ids.
+        condition
+            The list of program literals forming the condition.
+        """
+
+    def theory_atom(
+        self, atom_id_or_zero: int, term_id: int, elements: Sequence[int]
+    ) -> None:
+        """
+        Observe theory atoms without guard.
+
+        Parameters
+        ----------
+        atom_id_or_zero
+            The id of the atom or zero for directives.
+        term_id
+            The term associated with the atom.
+        elements
+            The elements of the atom in form of a list of element ids.
+        """
+
+    def theory_atom_with_guard(
+        self,
+        atom_id_or_zero: int,
+        term_id: int,
+        elements: Sequence[int],
+        operator_id: int,
+        right_hand_side_id: int,
+    ) -> None:
+        """
+        Observe theory atoms with guard.
+
+        Parameters
+        ----------
+        atom_id_or_zero
+            The id of the atom or zero for directives.
+        term_id : int
+            The term associated with the atom.
+        elements
+            The elements of the atom in form of a list of element ids.
+        operator_id
+            The id of the operator (a string term).
+        right_hand_side_id
+            The id of the term on the right hand side of the atom.
+        """
+
+    def end_step(self) -> None:
+        """
+        Marks the end of a block of directives passed to the solver.
+
+        This function is called right before solving starts.
+        """
+
+

Subclasses

+ +

Methods

+
+
+def acyc_edge(self, node_u: int, node_v: int, condition: Sequence[int]) ‑> None +
+
+

Observe edge directives passed to the solver.

+

Parameters

+
+
node_u
+
The start vertex of the edge (in form of an integer).
+
node_v
+
Тhe end vertex of the edge (in form of an integer).
+
condition
+
The list of program literals forming th condition under which to +add the edge.
+
+
+ +Expand source code + +
def acyc_edge(self, node_u: int, node_v: int, condition: Sequence[int]) -> None:
+    """
+    Observe edge directives passed to the solver.
+
+    Parameters
+    ----------
+    node_u
+        The start vertex of the edge (in form of an integer).
+    node_v
+        Тhe end vertex of the edge (in form of an integer).
+    condition
+        The list of program literals forming th condition under which to
+        add the edge.
+    """
+
+
+
+def assume(self, literals: Sequence[int]) ‑> None +
+
+

Observe assumption directives passed to the solver.

+

Parameters

+
+
literals
+
The program literals to assume (positive literals are true and +negative literals false for the next solve call).
+
+
+ +Expand source code + +
def assume(self, literals: Sequence[int]) -> None:
+    """
+    Observe assumption directives passed to the solver.
+
+    Parameters
+    ----------
+    literals
+        The program literals to assume (positive literals are true and
+        negative literals false for the next solve call).
+    """
+
+
+
+def begin_step(self) ‑> None +
+
+

Marks the beginning of a block of directives passed to the solver.

+
+ +Expand source code + +
def begin_step(self) -> None:
+    """
+    Marks the beginning of a block of directives passed to the solver.
+    """
+
+
+
+def end_step(self) ‑> None +
+
+

Marks the end of a block of directives passed to the solver.

+

This function is called right before solving starts.

+
+ +Expand source code + +
def end_step(self) -> None:
+    """
+    Marks the end of a block of directives passed to the solver.
+
+    This function is called right before solving starts.
+    """
+
+
+
+def external(self, atom: int, value: TruthValue) ‑> None +
+
+

Observe external statements passed to the solver.

+

Parameters

+
+
atom
+
The external atom in form of a program literal.
+
value
+
The truth value of the external statement.
+
+
+ +Expand source code + +
def external(self, atom: int, value: TruthValue) -> None:
+    """
+    Observe external statements passed to the solver.
+
+    Parameters
+    ----------
+    atom
+        The external atom in form of a program literal.
+    value
+        The truth value of the external statement.
+    """
+
+
+
+def heuristic(self, atom: int, type_: HeuristicType, bias: int, priority: int, condition: Sequence[int]) ‑> None +
+
+

Observe heuristic directives passed to the solver.

+

Parameters

+
+
atom
+
The program atom heuristically modified.
+
type_
+
The type of the modification.
+
bias
+
A signed integer.
+
priority
+
An unsigned integer.
+
condition
+
List of program literals.
+
+
+ +Expand source code + +
def heuristic(
+    self,
+    atom: int,
+    type_: HeuristicType,
+    bias: int,
+    priority: int,
+    condition: Sequence[int],
+) -> None:
+    """
+    Observe heuristic directives passed to the solver.
+
+    Parameters
+    ----------
+    atom
+        The program atom heuristically modified.
+    type_
+        The type of the modification.
+    bias
+        A signed integer.
+    priority
+        An unsigned integer.
+    condition
+        List of program literals.
+    """
+
+
+
+def init_program(self, incremental: bool) ‑> None +
+
+

Called once in the beginning.

+

Parameters

+
+
incremental
+
Whether the program is incremental. If the incremental flag is +true, there can be multiple calls to Control.solve().
+
+
+ +Expand source code + +
def init_program(self, incremental: bool) -> None:
+    """
+    Called once in the beginning.
+
+    Parameters
+    ----------
+    incremental
+        Whether the program is incremental. If the incremental flag is
+        true, there can be multiple calls to `clingo.control.Control.solve`.
+    """
+
+
+
+def minimize(self, priority: int, literals: Sequence[Tuple[int, int]]) ‑> None +
+
+

Observe minimize directives (or weak constraints) passed to the +solver.

+

Parameters

+
+
priority
+
The priority of the directive.
+
literals
+
List of weighted literals whose sum to minimize (pairs of literal +and weight).
+
+
+ +Expand source code + +
def minimize(self, priority: int, literals: Sequence[Tuple[int, int]]) -> None:
+    """
+    Observe minimize directives (or weak constraints) passed to the
+    solver.
+
+    Parameters
+    ----------
+    priority
+        The priority of the directive.
+    literals
+        List of weighted literals whose sum to minimize (pairs of literal
+        and weight).
+    """
+
+
+
+def output_atom(self, symbol: Symbol, atom: int) ‑> None +
+
+

Observe shown atoms passed to the solver. +Facts do not have an +associated program atom. The value of the atom is set to zero.

+

Parameters

+
+
symbol
+
The symbolic representation of the atom.
+
atom
+
The associated program atom (0 for facts).
+
+
+ +Expand source code + +
def output_atom(self, symbol: Symbol, atom: int) -> None:
+    """
+    Observe shown atoms passed to the solver.  Facts do not have an
+    associated program atom. The value of the atom is set to zero.
+
+    Parameters
+    ----------
+    symbol
+        The symbolic representation of the atom.
+    atom
+        The associated program atom (`0` for facts).
+    """
+
+
+
+def output_term(self, symbol: Symbol, condition: Sequence[int]) ‑> None +
+
+

Observe shown terms passed to the solver.

+

Parameters

+
+
symbol
+
The symbolic representation of the term.
+
condition
+
List of program literals forming the condition when to show the +term.
+
+
+ +Expand source code + +
def output_term(self, symbol: Symbol, condition: Sequence[int]) -> None:
+    """
+    Observe shown terms passed to the solver.
+
+    Parameters
+    ----------
+    symbol
+        The symbolic representation of the term.
+    condition
+        List of program literals forming the condition when to show the
+        term.
+    """
+
+
+
+def project(self, atoms: Sequence[int]) ‑> None +
+
+

Observe projection directives passed to the solver.

+

Parameters

+
+
atoms
+
The program atoms to project on.
+
+
+ +Expand source code + +
def project(self, atoms: Sequence[int]) -> None:
+    """
+    Observe projection directives passed to the solver.
+
+    Parameters
+    ----------
+    atoms
+        The program atoms to project on.
+    """
+
+
+
+def rule(self, choice: bool, head: Sequence[int], body: Sequence[int]) ‑> None +
+
+

Observe rules passed to the solver.

+

Parameters

+
+
choice
+
Determines if the head is a choice or a disjunction.
+
head
+
List of program atoms forming the rule head.
+
body
+
List of program literals forming the rule body.
+
+
+ +Expand source code + +
def rule(self, choice: bool, head: Sequence[int], body: Sequence[int]) -> None:
+    """
+    Observe rules passed to the solver.
+
+    Parameters
+    ----------
+    choice
+        Determines if the head is a choice or a disjunction.
+    head
+        List of program atoms forming the rule head.
+    body
+        List of program literals forming the rule body.
+    """
+
+
+
+def theory_atom(self, atom_id_or_zero: int, term_id: int, elements: Sequence[int]) ‑> None +
+
+

Observe theory atoms without guard.

+

Parameters

+
+
atom_id_or_zero
+
The id of the atom or zero for directives.
+
term_id
+
The term associated with the atom.
+
elements
+
The elements of the atom in form of a list of element ids.
+
+
+ +Expand source code + +
def theory_atom(
+    self, atom_id_or_zero: int, term_id: int, elements: Sequence[int]
+) -> None:
+    """
+    Observe theory atoms without guard.
+
+    Parameters
+    ----------
+    atom_id_or_zero
+        The id of the atom or zero for directives.
+    term_id
+        The term associated with the atom.
+    elements
+        The elements of the atom in form of a list of element ids.
+    """
+
+
+
+def theory_atom_with_guard(self, atom_id_or_zero: int, term_id: int, elements: Sequence[int], operator_id: int, right_hand_side_id: int) ‑> None +
+
+

Observe theory atoms with guard.

+

Parameters

+
+
atom_id_or_zero
+
The id of the atom or zero for directives.
+
term_id : int
+
The term associated with the atom.
+
elements
+
The elements of the atom in form of a list of element ids.
+
operator_id
+
The id of the operator (a string term).
+
right_hand_side_id
+
The id of the term on the right hand side of the atom.
+
+
+ +Expand source code + +
def theory_atom_with_guard(
+    self,
+    atom_id_or_zero: int,
+    term_id: int,
+    elements: Sequence[int],
+    operator_id: int,
+    right_hand_side_id: int,
+) -> None:
+    """
+    Observe theory atoms with guard.
+
+    Parameters
+    ----------
+    atom_id_or_zero
+        The id of the atom or zero for directives.
+    term_id : int
+        The term associated with the atom.
+    elements
+        The elements of the atom in form of a list of element ids.
+    operator_id
+        The id of the operator (a string term).
+    right_hand_side_id
+        The id of the term on the right hand side of the atom.
+    """
+
+
+
+def theory_element(self, element_id: int, terms: Sequence[int], condition: Sequence[int]) ‑> None +
+
+

Observe theory elements.

+

Parameters

+
+
element_id
+
The id of the element.
+
terms
+
The term tuple of the element in form of a list of term ids.
+
condition
+
The list of program literals forming the condition.
+
+
+ +Expand source code + +
def theory_element(
+    self, element_id: int, terms: Sequence[int], condition: Sequence[int]
+) -> None:
+    """
+    Observe theory elements.
+
+    Parameters
+    ----------
+    element_id
+        The id of the element.
+    terms
+        The term tuple of the element in form of a list of term ids.
+    condition
+        The list of program literals forming the condition.
+    """
+
+
+
+def theory_term_compound(self, term_id: int, name_id_or_type: int, arguments: Sequence[int]) ‑> None +
+
+

Observe compound theory terms.

+

Parameters

+
+
term_id
+
The id of the term.
+
name_id_or_type
+
The name id or type of the term where the value -1 stands for +tuples, -2 for sets, -3 for lists, or otherwise for the id of +the name (in form of a string term).
+
arguments
+
The arguments of the term in form of a list of term ids.
+
+
+ +Expand source code + +
def theory_term_compound(
+    self, term_id: int, name_id_or_type: int, arguments: Sequence[int]
+) -> None:
+    """
+    Observe compound theory terms.
+
+    Parameters
+    ----------
+    term_id
+        The id of the term.
+    name_id_or_type
+        The name id or type of the term where the value `-1` stands for
+        tuples, `-2` for sets, `-3` for lists, or otherwise for the id of
+        the name (in form of a string term).
+    arguments
+        The arguments of the term in form of a list of term ids.
+    """
+
+
+
+def theory_term_number(self, term_id: int, number: int) ‑> None +
+
+

Observe numeric theory terms.

+

Parameters

+
+
term_id
+
The id of the term.
+
number
+
The value of the term.
+
+
+ +Expand source code + +
def theory_term_number(self, term_id: int, number: int) -> None:
+    """
+    Observe numeric theory terms.
+
+    Parameters
+    ----------
+    term_id
+        The id of the term.
+    number
+        The value of the term.
+    """
+
+
+
+def theory_term_string(self, term_id: int, name: str) ‑> None +
+
+

Observe string theory terms.

+

Parameters

+
+
term_id
+
The id of the term.
+
name
+
The string value of the term.
+
+
+ +Expand source code + +
def theory_term_string(self, term_id: int, name: str) -> None:
+    """
+    Observe string theory terms.
+
+    Parameters
+    ----------
+    term_id
+        The id of the term.
+    name
+        The string value of the term.
+    """
+
+
+
+def weight_rule(self, choice: bool, head: Sequence[int], lower_bound: int, body: Sequence[Tuple[int, int]]) ‑> None +
+
+

Observe rules with one weight constraint in the body passed to the +solver.

+

Parameters

+
+
choice
+
Determines if the head is a choice or a disjunction.
+
head
+
List of program atoms forming the head of the rule.
+
lower_bound
+
The lower bound of the weight constraint in the rule body.
+
body
+
List of weighted literals (pairs of literal and weight) forming the +elements of the weight constraint.
+
+
+ +Expand source code + +
def weight_rule(
+    self,
+    choice: bool,
+    head: Sequence[int],
+    lower_bound: int,
+    body: Sequence[Tuple[int, int]],
+) -> None:
+    """
+    Observe rules with one weight constraint in the body passed to the
+    solver.
+
+    Parameters
+    ----------
+    choice
+        Determines if the head is a choice or a disjunction.
+    head
+        List of program atoms forming the head of the rule.
+    lower_bound
+        The lower bound of the weight constraint in the rule body.
+    body
+        List of weighted literals (pairs of literal and weight) forming the
+        elements of the weight constraint.
+    """
+
+
+
+
+
+class TheorySequenceType +(value, names=None, *, module=None, qualname=None, type=None, start=1) +
+
+

Enumeration of the different heuristic types.

+
+ +Expand source code + +
class TheorySequenceType(OrderedEnum):
+    """
+    Enumeration of the different heuristic types.
+    """
+
+    Tuple = _lib.clingo_theory_sequence_type_tuple
+    """
+    Type for tuples.
+    """
+    List = _lib.clingo_theory_sequence_type_list
+    """
+    Type for lists.
+    """
+    Set = _lib.clingo_theory_sequence_type_set
+    """
+    Type fo sets.
+    """
+
+

Ancestors

+ +

Class variables

+
+
var List
+
+

Type for lists.

+
+
var Set
+
+

Type fo sets.

+
+
var Tuple
+
+

Type for tuples.

+
+
+
+
+
+
+ +
+ + + \ No newline at end of file diff --git a/clingo/python-api/5.7/clingo/configuration.html b/clingo/python-api/5.7/clingo/configuration.html new file mode 100644 index 0000000..fb385b5 --- /dev/null +++ b/clingo/python-api/5.7/clingo/configuration.html @@ -0,0 +1,585 @@ + + + + + + +clingo.configuration API documentation + + + + + + + + + + + +
+
+
+

Module clingo.configuration

+
+
+

Functions and classes related to configuration.

+

Examples

+

The following example shows how to modify the configuration to enumerate all +models:

+
>>> from clingo.control import Control
+>>>
+>>> ctl = Control()
+>>> ctl.configuration.keys
+['tester', 'solve', 'asp', 'solver', 'configuration', 'share',
+ 'learn_explicit', 'sat_prepro', 'stats', 'parse_ext', 'parse_maxsat']
+>>> ctl.configuration.solve.keys
+['solve_limit', 'parallel_mode', 'global_restarts', 'distribute',
+ 'integrate', 'enum_mode', 'project', 'models', 'opt_mode']
+>>> ctl.configuration.solve.description("models")
+'Compute at most %A models (0 for all)\n'
+>>> ctl.configuration.solve.models = 0
+>>> ctl.add("base", [], "1 {a; b}.")
+>>> ctl.ground([("base", [])])
+>>> print(ctl.solve(on_model=print))
+b
+a
+a b
+SAT
+
+
+ +Expand source code + +
"""
+Functions and classes related to configuration.
+
+Examples
+--------
+The following example shows how to modify the configuration to enumerate all
+models:
+
+```python
+>>> from clingo.control import Control
+>>>
+>>> ctl = Control()
+>>> ctl.configuration.keys
+['tester', 'solve', 'asp', 'solver', 'configuration', 'share',
+ 'learn_explicit', 'sat_prepro', 'stats', 'parse_ext', 'parse_maxsat']
+>>> ctl.configuration.solve.keys
+['solve_limit', 'parallel_mode', 'global_restarts', 'distribute',
+ 'integrate', 'enum_mode', 'project', 'models', 'opt_mode']
+>>> ctl.configuration.solve.description("models")
+'Compute at most %A models (0 for all)\\n'
+>>> ctl.configuration.solve.models = 0
+>>> ctl.add("base", [], "1 {a; b}.")
+>>> ctl.ground([("base", [])])
+>>> print(ctl.solve(on_model=print))
+b
+a
+a b
+SAT
+```
+"""
+
+from typing import List, Optional, Union
+
+from ._internal import _c_call, _ffi, _handle_error, _lib, _to_str
+
+__all__ = ["Configuration"]
+
+
+class Configuration:
+    """
+    Allows for changing the configuration of the underlying solver.
+
+    Options are organized hierarchically. To change and inspect an option use:
+
+        config.group.subgroup.option = "value"
+        value = config.group.subgroup.option
+
+    There are also arrays of option groups that can be accessed using integer
+    indices:
+
+        config.group.subgroup[0].option = "value1"
+        config.group.subgroup[1].option = "value2"
+
+    To list the subgroups of an option group, use the `Configuration.keys`
+    member. Array option groups, like solver, can be iterated. Furthermore,
+    there are meta options having key `configuration`. Assigning a meta option
+    sets a number of related options.  To get further information about an
+    option or option group, use `Configuration.description`.
+
+    Notes
+    -----
+    The value of an option is always a string and any value assigned to an
+    option is automatically converted into a string.
+
+    See Also
+    --------
+    clingo.control.Control.configuration
+    """
+
+    def __init__(self, rep, key):
+        # Note: we have to bypass __setattr__ to avoid infinite recursion
+        super().__setattr__("_rep", rep)
+        super().__setattr__("_key", key)
+
+    @property
+    def _type(self) -> int:
+        return _c_call(
+            "clingo_configuration_type_bitset_t",
+            _lib.clingo_configuration_type,
+            self._rep,
+            self._key,
+        )
+
+    @property
+    def is_array(self) -> bool:
+        """
+        This property is true if the configuration option is an array.
+        """
+        return bool(self._type & _lib.clingo_configuration_type_array)
+
+    def _get_subkey(self, name: str) -> Optional[int]:
+        if self._type & _lib.clingo_configuration_type_map:
+            if _c_call(
+                "bool",
+                _lib.clingo_configuration_map_has_subkey,
+                self._rep,
+                self._key,
+                name.encode(),
+            ):
+                return _c_call(
+                    "clingo_id_t",
+                    _lib.clingo_configuration_map_at,
+                    self._rep,
+                    self._key,
+                    name.encode(),
+                )
+        return None
+
+    def __len__(self):
+        if self._type & _lib.clingo_configuration_type_array:
+            return _c_call(
+                "size_t", _lib.clingo_configuration_array_size, self._rep, self._key
+            )
+        return 0
+
+    def __getitem__(self, idx: int) -> "Configuration":
+        if idx < 0 or idx >= len(self):
+            raise IndexError("invalid index")
+
+        key = _c_call(
+            "clingo_id_t", _lib.clingo_configuration_array_at, self._rep, self._key, idx
+        )
+        return Configuration(self._rep, key)
+
+    def __getattr__(self, name: str) -> Union[None, str, "Configuration"]:
+        key = self._get_subkey(name)
+        if key is None:
+            raise AttributeError(f"no attribute: {name}")
+
+        type_ = _c_call(
+            "clingo_configuration_type_bitset_t",
+            _lib.clingo_configuration_type,
+            self._rep,
+            key,
+        )
+
+        if type_ & _lib.clingo_configuration_type_value:
+            if not _c_call(
+                "bool", _lib.clingo_configuration_value_is_assigned, self._rep, key
+            ):
+                return None
+
+            size = _c_call(
+                "size_t", _lib.clingo_configuration_value_get_size, self._rep, key
+            )
+
+            c_val = _ffi.new("char[]", size)
+            _handle_error(
+                _lib.clingo_configuration_value_get(self._rep, key, c_val, size)
+            )
+            return _to_str(c_val)
+
+        return Configuration(self._rep, key)
+
+    def __setattr__(self, name: str, val) -> None:
+        key = self._get_subkey(name)
+        if key is None:
+            super().__setattr__(name, val)
+        else:
+            _handle_error(
+                _lib.clingo_configuration_value_set(self._rep, key, str(val).encode())
+            )
+
+    def description(self, name: str) -> str:
+        """
+        Get a description for an option or option group.
+
+        Parameters
+        ----------
+        name
+            The name of the option.
+        """
+        key = self._get_subkey(name)
+        if key is None:
+            raise RuntimeError(f"unknown option {name}")
+        return _to_str(
+            _c_call("char*", _lib.clingo_configuration_description, self._rep, key)
+        )
+
+    @property
+    def keys(self) -> Optional[List[str]]:
+        """
+        The list of names of sub-option groups or options.
+
+        The list is `None` if the current object is not an option group.
+        """
+        ret = None
+        if self._type & _lib.clingo_configuration_type_map:
+            ret = []
+            for i in range(
+                _c_call(
+                    "size_t", _lib.clingo_configuration_map_size, self._rep, self._key
+                )
+            ):
+                name = _c_call(
+                    "char*",
+                    _lib.clingo_configuration_map_subkey_name,
+                    self._rep,
+                    self._key,
+                    i,
+                )
+                ret.append(_to_str(name))
+        return ret
+
+
+
+
+
+
+
+
+
+

Classes

+
+
+class Configuration +(rep, key) +
+
+

Allows for changing the configuration of the underlying solver.

+

Options are organized hierarchically. To change and inspect an option use:

+
config.group.subgroup.option = "value"
+value = config.group.subgroup.option
+
+

There are also arrays of option groups that can be accessed using integer +indices:

+
config.group.subgroup[0].option = "value1"
+config.group.subgroup[1].option = "value2"
+
+

To list the subgroups of an option group, use the Configuration.keys +member. Array option groups, like solver, can be iterated. Furthermore, +there are meta options having key configuration. Assigning a meta option +sets a number of related options. +To get further information about an +option or option group, use Configuration.description().

+

Notes

+

The value of an option is always a string and any value assigned to an +option is automatically converted into a string.

+

See Also

+

Control.configuration

+
+ +Expand source code + +
class Configuration:
+    """
+    Allows for changing the configuration of the underlying solver.
+
+    Options are organized hierarchically. To change and inspect an option use:
+
+        config.group.subgroup.option = "value"
+        value = config.group.subgroup.option
+
+    There are also arrays of option groups that can be accessed using integer
+    indices:
+
+        config.group.subgroup[0].option = "value1"
+        config.group.subgroup[1].option = "value2"
+
+    To list the subgroups of an option group, use the `Configuration.keys`
+    member. Array option groups, like solver, can be iterated. Furthermore,
+    there are meta options having key `configuration`. Assigning a meta option
+    sets a number of related options.  To get further information about an
+    option or option group, use `Configuration.description`.
+
+    Notes
+    -----
+    The value of an option is always a string and any value assigned to an
+    option is automatically converted into a string.
+
+    See Also
+    --------
+    clingo.control.Control.configuration
+    """
+
+    def __init__(self, rep, key):
+        # Note: we have to bypass __setattr__ to avoid infinite recursion
+        super().__setattr__("_rep", rep)
+        super().__setattr__("_key", key)
+
+    @property
+    def _type(self) -> int:
+        return _c_call(
+            "clingo_configuration_type_bitset_t",
+            _lib.clingo_configuration_type,
+            self._rep,
+            self._key,
+        )
+
+    @property
+    def is_array(self) -> bool:
+        """
+        This property is true if the configuration option is an array.
+        """
+        return bool(self._type & _lib.clingo_configuration_type_array)
+
+    def _get_subkey(self, name: str) -> Optional[int]:
+        if self._type & _lib.clingo_configuration_type_map:
+            if _c_call(
+                "bool",
+                _lib.clingo_configuration_map_has_subkey,
+                self._rep,
+                self._key,
+                name.encode(),
+            ):
+                return _c_call(
+                    "clingo_id_t",
+                    _lib.clingo_configuration_map_at,
+                    self._rep,
+                    self._key,
+                    name.encode(),
+                )
+        return None
+
+    def __len__(self):
+        if self._type & _lib.clingo_configuration_type_array:
+            return _c_call(
+                "size_t", _lib.clingo_configuration_array_size, self._rep, self._key
+            )
+        return 0
+
+    def __getitem__(self, idx: int) -> "Configuration":
+        if idx < 0 or idx >= len(self):
+            raise IndexError("invalid index")
+
+        key = _c_call(
+            "clingo_id_t", _lib.clingo_configuration_array_at, self._rep, self._key, idx
+        )
+        return Configuration(self._rep, key)
+
+    def __getattr__(self, name: str) -> Union[None, str, "Configuration"]:
+        key = self._get_subkey(name)
+        if key is None:
+            raise AttributeError(f"no attribute: {name}")
+
+        type_ = _c_call(
+            "clingo_configuration_type_bitset_t",
+            _lib.clingo_configuration_type,
+            self._rep,
+            key,
+        )
+
+        if type_ & _lib.clingo_configuration_type_value:
+            if not _c_call(
+                "bool", _lib.clingo_configuration_value_is_assigned, self._rep, key
+            ):
+                return None
+
+            size = _c_call(
+                "size_t", _lib.clingo_configuration_value_get_size, self._rep, key
+            )
+
+            c_val = _ffi.new("char[]", size)
+            _handle_error(
+                _lib.clingo_configuration_value_get(self._rep, key, c_val, size)
+            )
+            return _to_str(c_val)
+
+        return Configuration(self._rep, key)
+
+    def __setattr__(self, name: str, val) -> None:
+        key = self._get_subkey(name)
+        if key is None:
+            super().__setattr__(name, val)
+        else:
+            _handle_error(
+                _lib.clingo_configuration_value_set(self._rep, key, str(val).encode())
+            )
+
+    def description(self, name: str) -> str:
+        """
+        Get a description for an option or option group.
+
+        Parameters
+        ----------
+        name
+            The name of the option.
+        """
+        key = self._get_subkey(name)
+        if key is None:
+            raise RuntimeError(f"unknown option {name}")
+        return _to_str(
+            _c_call("char*", _lib.clingo_configuration_description, self._rep, key)
+        )
+
+    @property
+    def keys(self) -> Optional[List[str]]:
+        """
+        The list of names of sub-option groups or options.
+
+        The list is `None` if the current object is not an option group.
+        """
+        ret = None
+        if self._type & _lib.clingo_configuration_type_map:
+            ret = []
+            for i in range(
+                _c_call(
+                    "size_t", _lib.clingo_configuration_map_size, self._rep, self._key
+                )
+            ):
+                name = _c_call(
+                    "char*",
+                    _lib.clingo_configuration_map_subkey_name,
+                    self._rep,
+                    self._key,
+                    i,
+                )
+                ret.append(_to_str(name))
+        return ret
+
+

Instance variables

+
+
var is_array : bool
+
+

This property is true if the configuration option is an array.

+
+ +Expand source code + +
@property
+def is_array(self) -> bool:
+    """
+    This property is true if the configuration option is an array.
+    """
+    return bool(self._type & _lib.clingo_configuration_type_array)
+
+
+
var keys : Optional[List[str]]
+
+

The list of names of sub-option groups or options.

+

The list is None if the current object is not an option group.

+
+ +Expand source code + +
@property
+def keys(self) -> Optional[List[str]]:
+    """
+    The list of names of sub-option groups or options.
+
+    The list is `None` if the current object is not an option group.
+    """
+    ret = None
+    if self._type & _lib.clingo_configuration_type_map:
+        ret = []
+        for i in range(
+            _c_call(
+                "size_t", _lib.clingo_configuration_map_size, self._rep, self._key
+            )
+        ):
+            name = _c_call(
+                "char*",
+                _lib.clingo_configuration_map_subkey_name,
+                self._rep,
+                self._key,
+                i,
+            )
+            ret.append(_to_str(name))
+    return ret
+
+
+
+

Methods

+
+
+def description(self, name: str) ‑> str +
+
+

Get a description for an option or option group.

+

Parameters

+
+
name
+
The name of the option.
+
+
+ +Expand source code + +
def description(self, name: str) -> str:
+    """
+    Get a description for an option or option group.
+
+    Parameters
+    ----------
+    name
+        The name of the option.
+    """
+    key = self._get_subkey(name)
+    if key is None:
+        raise RuntimeError(f"unknown option {name}")
+    return _to_str(
+        _c_call("char*", _lib.clingo_configuration_description, self._rep, key)
+    )
+
+
+
+
+
+
+
+ +
+ + + \ No newline at end of file diff --git a/clingo/python-api/5.7/clingo/control.html b/clingo/python-api/5.7/clingo/control.html new file mode 100644 index 0000000..3709db7 --- /dev/null +++ b/clingo/python-api/5.7/clingo/control.html @@ -0,0 +1,3055 @@ + + + + + + +clingo.control API documentation + + + + + + + + + + + +
+
+
+

Module clingo.control

+
+
+

This module contains the Control class responsible for +controling grounding and solving.

+

Examples

+

The following example shows the basic ground solve process:

+
>>> from clingo.symbol import Number
+>>> from clingo.control import Control
+>>>
+>>> ctl = Control()
+>>> ctl.add("q.")
+>>>
+>>> ctl.ground()
+>>> print(ctl.solve(on_model=print))
+q
+SAT
+
+

The following example shows basic (multishot) grounding and solving:

+
>>> from clingo.symbol import Number
+>>> from clingo.control import Control
+>>>
+>>> ctl = Control()
+>>> ctl.add("a", [], "q.")
+>>> ctl.add("b", ["t"], "q(t).")
+>>>
+>>> ctl.ground([("a", [])])
+>>> print(ctl.solve(on_model=print))
+q
+SAT
+>>> ctl.ground([("b", [Number(1)]), ("p", [Number(2)])])
+>>> print(ctl.solve(on_model=print))
+q q(1) q(2)
+SAT
+>>> ctl.ground([("b", [Number(3)])])
+>>> print(ctl.solve(on_model=print))
+q q(1) q(2) q(3)
+SAT
+
+
+ +Expand source code + +
"""
+This module contains the `clingo.control.Control` class responsible for
+controling grounding and solving.
+
+Examples
+--------
+The following example shows the basic ground solve process:
+
+    >>> from clingo.symbol import Number
+    >>> from clingo.control import Control
+    >>>
+    >>> ctl = Control()
+    >>> ctl.add("q.")
+    >>>
+    >>> ctl.ground()
+    >>> print(ctl.solve(on_model=print))
+    q
+    SAT
+
+The following example shows basic (multishot) grounding and solving:
+
+    >>> from clingo.symbol import Number
+    >>> from clingo.control import Control
+    >>>
+    >>> ctl = Control()
+    >>> ctl.add("a", [], "q.")
+    >>> ctl.add("b", ["t"], "q(t).")
+    >>>
+    >>> ctl.ground([("a", [])])
+    >>> print(ctl.solve(on_model=print))
+    q
+    SAT
+    >>> ctl.ground([("b", [Number(1)]), ("p", [Number(2)])])
+    >>> print(ctl.solve(on_model=print))
+    q q(1) q(2)
+    SAT
+    >>> ctl.ground([("b", [Number(3)])])
+    >>> print(ctl.solve(on_model=print))
+    q q(1) q(2) q(3)
+    SAT
+"""
+
+import sys
+from collections import abc
+from typing import (
+    Any,
+    Callable,
+    Iterator,
+    Optional,
+    Sequence,
+    Tuple,
+    Union,
+    cast,
+    overload,
+)
+if sys.version_info >= (3, 8):
+    from typing import Literal
+
+from ._internal import (
+    _CBData,
+    _Error,
+    _cb_error_handler,
+    _c_call,
+    _ffi,
+    _handle_error,
+    _lib,
+    _overwritten,
+)
+from .core import Logger
+from .symbol import Symbol
+from .symbolic_atoms import SymbolicAtoms
+from .theory_atoms import TheoryAtom
+from .solving import Model, SolveHandle, SolveResult
+from .propagator import Propagator
+from .backend import Backend, Observer
+from .configuration import Configuration
+from .statistics import StatisticsMap, _mutable_statistics, _statistics
+
+__all__ = ["Control"]
+
+
+class _SolveEventHandler:
+    # pylint: disable=missing-function-docstring
+    def __init__(self, on_model, on_unsat, on_statistics, on_finish):
+        self._on_model = on_model
+        self._on_unsat = on_unsat
+        self._on_statistics = on_statistics
+        self._on_finish = on_finish
+
+    def on_model(self, m):
+        ret = None
+        if self._on_model is not None:
+            ret = self._on_model(Model(m))
+        return bool(ret or ret is None)
+
+    def on_unsat(self, lower):
+        if self._on_unsat is not None:
+            self._on_unsat(lower)
+
+    def on_finish(self, res):
+        if self._on_finish is not None:
+            self._on_finish(SolveResult(res))
+
+    def on_statistics(self, step, accu):
+        if self._on_statistics is not None:
+            self._on_statistics(_mutable_statistics(step), _mutable_statistics(accu))
+
+
+@_ffi.def_extern(
+    onerror=_cb_error_handler("data"), name="pyclingo_solve_event_callback"
+)
+def _pyclingo_solve_event_callback(type_, event, data, goon):
+    """
+    Low-level solve event handler.
+    """
+    handler = _ffi.from_handle(data).data
+    if type_ == _lib.clingo_solve_event_type_finish:
+        handler.on_finish(_ffi.cast("clingo_solve_result_bitset_t*", event)[0])
+
+    if type_ == _lib.clingo_solve_event_type_model:
+        goon[0] = handler.on_model(_ffi.cast("clingo_model_t*", event))
+
+    if type_ == _lib.clingo_solve_event_type_unsat:
+        c_args = _ffi.cast("void**", event)
+        c_lower = _ffi.cast("int64_t*", c_args[0])
+        size = int(_ffi.cast("size_t", c_args[1]))
+        handler.on_unsat([c_lower[i] for i in range(size)])
+
+    if type_ == _lib.clingo_solve_event_type_statistics:
+        p_stats = _ffi.cast("clingo_statistics_t**", event)
+        handler.on_statistics(p_stats[0], p_stats[1])
+
+    return True
+
+
+@_ffi.def_extern(onerror=_cb_error_handler("data"), name="pyclingo_ground_callback")
+def _pyclingo_ground_callback(
+    location,
+    name,
+    arguments,
+    arguments_size,
+    data,
+    symbol_callback,
+    symbol_callback_data,
+):
+    """
+    Low-level ground callback.
+    """
+    # Note: location could be attached to error message
+    # pylint: disable=protected-access,unused-argument
+    context = _ffi.from_handle(data).data
+    py_name = _ffi.string(name).decode()
+    fun = getattr(sys.modules["__main__"] if context is None else context, py_name)
+
+    args = []
+    for i in range(arguments_size):
+        args.append(Symbol(arguments[i]))
+
+    ret = fun(*args)
+    symbols = list(ret) if isinstance(ret, abc.Iterable) else [ret]
+
+    c_symbols = _ffi.new("clingo_symbol_t[]", len(symbols))
+    for i, sym in enumerate(symbols):
+        c_symbols[i] = sym._rep
+    _handle_error(symbol_callback(c_symbols, len(symbols), symbol_callback_data))
+
+    return True
+
+
+class Control:
+    """
+    Control object for the grounding/solving process.
+
+    Parameters
+    ----------
+    arguments
+        Arguments to the grounder and solver.
+    logger
+        Function to intercept messages normally printed to standard error.
+    message_limit
+        The maximum number of messages passed to the logger.
+
+    Notes
+    -----
+    Note that only gringo options (without `--text`) and clasp's search options
+    are supported. Furthermore, you must not call any functions of a `Control`
+    object while a solve call is active.
+    """
+
+    def __init__(
+        self,
+        arguments: Sequence[str] = [],
+        logger: Optional[Logger] = None,
+        message_limit: int = 20,
+    ):
+        # pylint: disable=protected-access,dangerous-default-value
+        self._free = False
+        self._mem = []
+        if isinstance(arguments, abc.Sequence):
+            if logger is not None:
+                c_handle = _ffi.new_handle(logger)
+                c_cb = _lib.pyclingo_logger_callback
+                self._mem.append(c_handle)
+            else:
+                c_handle = _ffi.NULL
+                c_cb = _ffi.NULL
+            c_mem = []
+            c_args = _ffi.new("char*[]", len(arguments))
+            for i, arg in enumerate(arguments):
+                c_mem.append(_ffi.new("char[]", arg.encode()))
+                c_args[i] = c_mem[-1]
+            self._rep = _c_call(
+                "clingo_control_t *",
+                _lib.clingo_control_new,
+                c_args,
+                len(arguments),
+                c_cb,
+                c_handle,
+                message_limit,
+            )
+            self._free = True
+        else:
+            self._rep = arguments
+
+        self._handler = None
+        self._statistics = None
+        self._statistics_call = -1.0
+        self._error = _Error()
+
+    def __del__(self):
+        if self._free:
+            _lib.clingo_control_free(self._rep)
+
+    @overload
+    def add(self, name: str, parameters: Sequence[str], program: str) -> None:
+        """
+        Extend the logic program with the given non-ground logic program in string form.
+
+        Parameters
+        ----------
+        name
+            The name of program block to add.
+        parameters
+            The parameters of the program block to add.
+        program
+            The non-ground program in string form.
+
+        See Also
+        --------
+        Control.ground
+        """
+
+    @overload
+    def add(self, program: str) -> None:
+        """
+        Extend the logic program with the given non-ground logic program in string form.
+
+        Parameters
+        ----------
+        name
+            The name of program block to add.
+
+        Notes
+        -----
+        This function is equivalent to calling `add("base", [], program)`.
+        """
+
+    def add(self, *args, **kwargs) -> None:
+        """
+        Extend the logic program with the given non-ground logic program in string form.
+
+        This function provides two overloads:
+
+        ```python
+        def add(self, name: str, parameters: Sequence[str], program: str) -> None:
+            ...
+
+        def add(self, program: str) -> None:
+            return self.add("base", [], program)
+        ```
+
+        Parameters
+        ----------
+        name
+            The name of program block to add.
+        parameters
+            The parameters of the program block to add.
+        program
+            The non-ground program in string form.
+
+        See Also
+        --------
+        Control.ground
+        """
+        n = len(args) + len(kwargs)
+        if n == 1:
+            self._add1(*args, **kwargs)
+        else:
+            self._add2(*args, **kwargs)
+
+    def _add1(self, program: str) -> None:
+        self._add2("base", [], program)
+
+    def _add2(self, name: str, parameters: Sequence[str], program: str) -> None:
+        c_mem = []
+        c_params = _ffi.new("char*[]", len(parameters))
+        for i, param in enumerate(parameters):
+            c_mem.append(_ffi.new("char[]", param.encode()))
+            c_params[i] = c_mem[-1]
+        _handle_error(
+            _lib.clingo_control_add(
+                self._rep, name.encode(), c_params, len(parameters), program.encode()
+            )
+        )
+
+    def _program_atom(self, lit: Union[Symbol, int]) -> int:
+        if isinstance(lit, int):
+            return lit
+        satom = self.symbolic_atoms[lit]
+        return 0 if satom is None else satom.literal
+
+    def assign_external(
+        self, external: Union[Symbol, int], truth: Optional[bool]
+    ) -> None:
+        """
+        Assign a truth value to an external atom.
+
+        Parameters
+        ----------
+        external
+            A symbol or program literal representing the external atom.
+        truth
+            A Boolean fixes the external to the respective truth value; and
+            None leaves its truth value open.
+
+        See Also
+        --------
+        Control.release_external, clingo.solving.SolveControl.symbolic_atoms,
+        clingo.symbolic_atoms.SymbolicAtom.is_external
+
+        Notes
+        -----
+        The truth value of an external atom can be changed before each solve
+        call. An atom is treated as external if it has been declared using an
+        `#external` directive, and has not been released by calling
+        `Control.release_external` or defined in a logic program with some
+        rule. If the given atom is not external, then the function has no
+        effect.
+
+        For convenience, the truth assigned to atoms over negative program
+        literals is inverted.
+        """
+
+        if truth is None:
+            val = _lib.clingo_external_type_free
+        elif truth:
+            val = _lib.clingo_external_type_true
+        else:
+            val = _lib.clingo_external_type_false
+        _handle_error(
+            _lib.clingo_control_assign_external(
+                self._rep, self._program_atom(external), val
+            )
+        )
+
+    def backend(self) -> Backend:
+        """
+        Returns a `Backend` object providing a low level interface to extend a
+        logic program.
+
+        See Also
+        --------
+        clingo.backend
+        """
+        return Backend(
+            _c_call("clingo_backend_t*", _lib.clingo_control_backend, self._rep),
+            self._error,
+        )
+
+    def cleanup(self) -> None:
+        """
+        Cleanup the domain used for grounding by incorporating information from
+        the solver.
+
+        This function cleans up the domain used for grounding.  This is done by
+        first simplifying the current program representation (falsifying
+        released external atoms).  Afterwards, the top-level implications are
+        used to either remove atoms from the domain or mark them as facts.
+
+        See Also
+        --------
+        Control.enable_cleanup
+
+        Notes
+        -----
+        Any atoms falsified are completely removed from the logic program.
+        Hence, a definition for such an atom in a successive step introduces a
+        fresh atom.
+
+        With the current implementation, the function only has an effect if
+        called after solving and before any function is called that starts a
+        new step.
+
+        Typically, it is not necessary to call this function manually because
+        automatic cleanups are enabled by default.
+        """
+        _handle_error(_lib.clingo_control_cleanup(self._rep))
+
+    def get_const(self, name: str) -> Optional[Symbol]:
+        """
+        Return the symbol for a constant definition of form:
+
+            #const name = symbol.
+
+        Parameters
+        ----------
+        name
+            The name of the constant to retrieve.
+
+        Returns
+        -------
+        The function returns `None` if no matching constant definition exists.
+        """
+        if not _c_call("bool", _lib.clingo_control_has_const, self._rep, name.encode()):
+            return None
+
+        return Symbol(
+            _c_call(
+                "clingo_symbol_t",
+                _lib.clingo_control_get_const,
+                self._rep,
+                name.encode(),
+            )
+        )
+
+    def ground(
+        self,
+        parts: Sequence[Tuple[str, Sequence[Symbol]]] = (("base", ()),),
+        context: Any = None,
+    ) -> None:
+        """
+        Ground the given list of program parts specified by tuples of names and
+        arguments.
+
+        Parameters
+        ----------
+        parts
+            List of tuples of program names and program arguments to ground.
+        context
+            A context object whose methods are called during grounding using
+            the `@`-syntax (if omitted, those from the main module are used).
+
+        Notes
+        -----
+        Note that parts of a logic program without an explicit `#program`
+        specification are by default put into a program called `base` without
+        arguments.
+        """
+        # pylint: disable=protected-access,dangerous-default-value
+        self._error.clear()
+        data = _CBData(context, self._error)
+        c_data = _ffi.new_handle(data) if context else _ffi.NULL
+        c_cb = _lib.pyclingo_ground_callback if context else _ffi.NULL
+
+        c_mem = []
+        c_parts = _ffi.new("clingo_part_t[]", len(parts))
+        for part, c_part in zip(parts, c_parts):
+            c_mem.append(_ffi.new("char[]", part[0].encode()))
+            c_part.name = c_mem[-1]
+            c_mem.append(_ffi.new("clingo_symbol_t[]", len(part[1])))
+            c_part.params = c_mem[-1]
+            for i, sym in enumerate(part[1]):
+                c_part.params[i] = sym._rep
+            c_part.size = len(part[1])
+
+        _handle_error(
+            _lib.clingo_control_ground(self._rep, c_parts, len(parts), c_cb, c_data),
+            data,
+        )
+
+    def interrupt(self) -> None:
+        """
+        Interrupt the active solve call.
+
+        Notes
+        -----
+        This function is thread-safe and can be called from a signal handler. If no
+        search is active, the subsequent call to `Control.solve` is interrupted. The
+        result of the `Control.solve` method can be used to query if the search was
+        interrupted.
+        """
+        _lib.clingo_control_interrupt(self._rep)
+
+    def load(self, path: str) -> None:
+        """
+        Extend the logic program with a (non-ground) logic program in a file.
+
+        Parameters
+        ----------
+        path
+            The path of the file to load.
+        """
+        _handle_error(_lib.clingo_control_load(self._rep, path.encode()))
+
+    def register_observer(self, observer: Observer, replace: bool = False) -> None:
+        """
+        Registers the given observer to inspect the produced grounding.
+
+        Parameters
+        ----------
+        observer
+            The observer to register. See below for a description of the requirede
+            interface.
+        replace
+            If set to true, the output is just passed to the observer and nolonger to
+            the underlying solver (or any previously registered observers).
+
+        See Also
+        --------
+        clingo.backend
+        """
+        # pylint: disable=protected-access,line-too-long
+        c_observer = _ffi.new(
+            "clingo_ground_program_observer_t*",
+            (
+                _lib.pyclingo_observer_init_program
+                if _overwritten(Observer, observer, "init_program")
+                else _ffi.NULL,
+                _lib.pyclingo_observer_begin_step
+                if _overwritten(Observer, observer, "begin_step")
+                else _ffi.NULL,
+                _lib.pyclingo_observer_end_step
+                if _overwritten(Observer, observer, "end_step")
+                else _ffi.NULL,
+                _lib.pyclingo_observer_rule
+                if _overwritten(Observer, observer, "rule")
+                else _ffi.NULL,
+                _lib.pyclingo_observer_weight_rule
+                if _overwritten(Observer, observer, "weight_rule")
+                else _ffi.NULL,
+                _lib.pyclingo_observer_minimize
+                if _overwritten(Observer, observer, "minimize")
+                else _ffi.NULL,
+                _lib.pyclingo_observer_project
+                if _overwritten(Observer, observer, "project")
+                else _ffi.NULL,
+                _lib.pyclingo_observer_output_atom
+                if _overwritten(Observer, observer, "output_atom")
+                else _ffi.NULL,
+                _lib.pyclingo_observer_output_term
+                if _overwritten(Observer, observer, "output_term")
+                else _ffi.NULL,
+                _lib.pyclingo_observer_external
+                if _overwritten(Observer, observer, "external")
+                else _ffi.NULL,
+                _lib.pyclingo_observer_assume
+                if _overwritten(Observer, observer, "assume")
+                else _ffi.NULL,
+                _lib.pyclingo_observer_heuristic
+                if _overwritten(Observer, observer, "heuristic")
+                else _ffi.NULL,
+                _lib.pyclingo_observer_acyc_edge
+                if _overwritten(Observer, observer, "acyc_edge")
+                else _ffi.NULL,
+                _lib.pyclingo_observer_theory_term_number
+                if _overwritten(Observer, observer, "theory_term_number")
+                else _ffi.NULL,
+                _lib.pyclingo_observer_theory_term_string
+                if _overwritten(Observer, observer, "theory_term_string")
+                else _ffi.NULL,
+                _lib.pyclingo_observer_theory_term_compound
+                if _overwritten(Observer, observer, "theory_term_compound")
+                else _ffi.NULL,
+                _lib.pyclingo_observer_theory_element
+                if _overwritten(Observer, observer, "theory_element")
+                else _ffi.NULL,
+                _lib.pyclingo_observer_theory_atom
+                if _overwritten(Observer, observer, "theory_atom")
+                else _ffi.NULL,
+                _lib.pyclingo_observer_theory_atom_with_guard
+                if _overwritten(Observer, observer, "theory_atom_with_guard")
+                else _ffi.NULL,
+            ),
+        )
+        c_data = _ffi.new_handle(_CBData(observer, self._error))
+        self._mem.append(c_data)
+        _handle_error(
+            _lib.clingo_control_register_observer(
+                self._rep, c_observer, replace, c_data
+            )
+        )
+
+    def register_propagator(self, propagator: Propagator) -> None:
+        """
+        Registers the given propagator with all solvers.
+
+        Parameters
+        ----------
+        propagator
+            The propagator to register.
+
+        See Also
+        --------
+        clingo.propagator
+        """
+        # pylint: disable=protected-access
+        c_propagator = _ffi.new(
+            "clingo_propagator_t*",
+            (
+                _lib.pyclingo_propagator_init
+                if _overwritten(Propagator, propagator, "init")
+                else _ffi.NULL,
+                _lib.pyclingo_propagator_propagate
+                if _overwritten(Propagator, propagator, "propagate")
+                else _ffi.NULL,
+                _lib.pyclingo_propagator_undo
+                if _overwritten(Propagator, propagator, "undo")
+                else _ffi.NULL,
+                _lib.pyclingo_propagator_check
+                if _overwritten(Propagator, propagator, "check")
+                else _ffi.NULL,
+                _lib.pyclingo_propagator_decide
+                if _overwritten(Propagator, propagator, "decide")
+                else _ffi.NULL,
+            ),
+        )
+        c_data = _ffi.new_handle(_CBData(propagator, self._error))
+        self._mem.append(c_data)
+        _handle_error(
+            _lib.clingo_control_register_propagator(
+                self._rep, c_propagator, c_data, False
+            )
+        )
+
+    def release_external(self, external: Union[Symbol, int]) -> None:
+        """
+        Release an external atom represented by the given symbol or program
+        literal.
+
+        This function causes the corresponding atom to become permanently false
+        if there is no definition for the atom in the program. Otherwise, the
+        function has no effect.
+
+        Parameters
+        ----------
+        external
+            The symbolic atom or program atom to release.
+
+        Notes
+        -----
+        If the program literal is negative, the corresponding atom is released.
+
+        Examples
+        --------
+        The following example shows the effect of assigning and releasing and external
+        atom.
+
+            >>> from clingo.symbol import Function
+            >>> from clingo.control import Control
+            >>>
+            >>> ctl = Control()
+            >>> ctl.add("base", [], "a. #external b.")
+            >>> ctl.ground([("base", [])])
+            >>> ctl.assign_external(Function("b"), True)
+            >>> print(ctl.solve(on_model=print))
+            b a
+            SAT
+            >>> ctl.release_external(Function("b"))
+            >>> print(ctl.solve(on_model=print))
+            a
+            SAT
+        """
+        _handle_error(
+            _lib.clingo_control_release_external(
+                self._rep, self._program_atom(external)
+            )
+        )
+
+    # this assumes that overloads are matched in the order they appear
+    # unfortunately, PEP0484 does not specify any kind of semantics just giving examples
+    if sys.version_info >= (3, 8):
+        @overload
+        def solve(
+            self,
+            assumptions: Sequence[Union[Tuple[Symbol, bool], int]] = (),
+            on_model: Optional[Callable[[Model], Optional[bool]]] = None,
+            on_unsat: Optional[Callable[[Sequence[int]], None]] = None,
+            on_statistics: Optional[Callable[[StatisticsMap, StatisticsMap], None]] = None,
+            on_finish: Optional[Callable[[SolveResult], None]] = None,
+            on_core: Optional[Callable[[Sequence[int]], None]] = None,
+            *,
+            yield_: Literal[False] = False,
+            async_: Literal[False] = False,
+        ) -> SolveResult: ...
+        @overload
+        def solve(
+            self,
+            assumptions: Sequence[Union[Tuple[Symbol, bool], int]] = (),
+            on_model: Optional[Callable[[Model], Optional[bool]]] = None,
+            on_unsat: Optional[Callable[[Sequence[int]], None]] = None,
+            on_statistics: Optional[Callable[[StatisticsMap, StatisticsMap], None]] = None,
+            on_finish: Optional[Callable[[SolveResult], None]] = None,
+            on_core: Optional[Callable[[Sequence[int]], None]] = None,
+            *,
+            yield_: Literal[True],
+            async_: bool = False,
+        ) -> SolveHandle: ...
+        @overload
+        def solve(
+            self,
+            assumptions: Sequence[Union[Tuple[Symbol, bool], int]] = (),
+            on_model: Optional[Callable[[Model], Optional[bool]]] = None,
+            on_unsat: Optional[Callable[[Sequence[int]], None]] = None,
+            on_statistics: Optional[Callable[[StatisticsMap, StatisticsMap], None]] = None,
+            on_finish: Optional[Callable[[SolveResult], None]] = None,
+            on_core: Optional[Callable[[Sequence[int]], None]] = None,
+            *,
+            yield_: bool = False,
+            async_: Literal[True],
+        ) -> SolveHandle: ...
+    else:
+        @overload
+        def solve(
+            self,
+            assumptions: Sequence[Union[Tuple[Symbol, bool], int]] = (),
+            on_model: Optional[Callable[[Model], Optional[bool]]] = None,
+            on_unsat: Optional[Callable[[Sequence[int]], None]] = None,
+            on_statistics: Optional[Callable[[StatisticsMap, StatisticsMap], None]] = None,
+            on_finish: Optional[Callable[[SolveResult], None]] = None,
+            on_core: Optional[Callable[[Sequence[int]], None]] = None,
+        ) -> SolveResult: ...
+
+    @overload
+    def solve(
+        self,
+        assumptions: Sequence[Union[Tuple[Symbol, bool], int]] = (),
+        on_model: Optional[Callable[[Model], Optional[bool]]] = None,
+        on_unsat: Optional[Callable[[Sequence[int]], None]] = None,
+        on_statistics: Optional[Callable[[StatisticsMap, StatisticsMap], None]] = None,
+        on_finish: Optional[Callable[[SolveResult], None]] = None,
+        on_core: Optional[Callable[[Sequence[int]], None]] = None,
+        yield_: bool = False,
+        async_: bool = False,
+    ) -> Union[SolveHandle, SolveResult]: ...
+
+    def solve(
+        self,
+        assumptions: Sequence[Union[Tuple[Symbol, bool], int]] = (),
+        on_model: Optional[Callable[[Model], Optional[bool]]] = None,
+        on_unsat: Optional[Callable[[Sequence[int]], None]] = None,
+        on_statistics: Optional[Callable[[StatisticsMap, StatisticsMap], None]] = None,
+        on_finish: Optional[Callable[[SolveResult], None]] = None,
+        on_core: Optional[Callable[[Sequence[int]], None]] = None,
+        yield_: bool = False,
+        async_: bool = False,
+    ) -> Union[SolveHandle, SolveResult]:
+        """
+        Starts a search.
+
+        Parameters
+        ----------
+        assumptions
+            List of (atom, boolean) tuples or program literals (see
+            `clingo.symbolic_atoms.SymbolicAtom.literal`) that serve as
+            assumptions for the solve call, e.g., solving under assumptions
+            `[(Function("a"), True)]` only admits answer sets that contain atom `a`.
+        on_model
+            Optional callback for intercepting models.
+            A `clingo.solving.Model` object is passed to the callback. The
+            search can be interruped from the model callback by returning
+            False.
+        on_unsat
+            Optional callback to intercept lower bounds during optimization.
+        on_statistics
+            Optional callback to update statistics.
+            The step and accumulated statistics are passed as arguments.
+        on_finish
+            Optional callback called once search has finished.
+            A `clingo.solving.SolveResult` also indicating whether the solve
+            call has been intrrupted is passed to the callback.
+        on_core
+            Optional callback called with the assumptions that made a problem
+            unsatisfiable.
+        yield_
+            The resulting `clingo.solving.SolveHandle` is iterable yielding
+            `clingo.solving.Model` objects.
+        async_
+            The solve call and the method `clingo.solving.SolveHandle.resume`
+            of the returned handle are non-blocking.
+
+        Returns
+        -------
+        The return value depends on the parameters. If either `yield_` or
+        `async_` is true, then a handle is returned. Otherwise, a
+        `clingo.solving.SolveResult` is returned.
+
+        See Also
+        --------
+        clingo.solving
+
+        Notes
+        -----
+        If neither `yield_` nor `async_` is set, the function returns a
+        `clingo.solving.SolveResult` right away.
+
+        In gringo or in clingo with lparse or text output enabled, this
+        function just grounds and returns a `clingo.solving.SolveResult` where
+        `clingo.solving.SolveResult.unknown` is true.
+
+        If this function is used in embedded Python code, you might want to start
+        clingo using the `--outf=3` option to disable all output from clingo.
+
+        Asynchronous solving is only available in clingo with thread support
+        enabled. Furthermore, the on_model and on_finish callbacks are called
+        from another thread. To ensure that the methods can be called, make
+        sure to not use any functions that block Python's GIL indefinitely.
+
+        This function as well as blocking functions on the
+        `clingo.solving.SolveHandle` release the GIL but are not thread-safe.
+        """
+        # pylint: disable=protected-access,dangerous-default-value
+        self._error.clear()
+        handler = _SolveEventHandler(on_model, on_unsat, on_statistics, on_finish)
+        data = _CBData(handler, self._error)
+        self._handler = _ffi.new_handle(data)
+
+        p_ass = _ffi.NULL
+        if assumptions:
+            atoms = None
+            p_ass = _ffi.new("clingo_literal_t[]", len(assumptions))
+            for i, lit in enumerate(assumptions):
+                if isinstance(lit, int):
+                    p_ass[i] = lit
+                else:
+                    if atoms is None:
+                        atoms = self.symbolic_atoms
+                    atom = self.symbolic_atoms[lit[0]]
+                    slit = -1 if atom is None else atom.literal
+                    p_ass[i] = slit if lit[1] else -slit
+
+        mode = 0
+        if yield_:
+            mode |= _lib.clingo_solve_mode_yield
+        if async_:
+            mode |= _lib.clingo_solve_mode_async
+
+        handle = SolveHandle(
+            _c_call(
+                "clingo_solve_handle_t*",
+                _lib.clingo_control_solve,
+                self._rep,
+                mode,
+                p_ass,
+                len(assumptions),
+                _lib.pyclingo_solve_event_callback,
+                self._handler,
+                handler=data,
+            ),
+            data,
+        )
+
+        if not yield_ and not async_:
+            with handle:
+                ret = handle.get()
+                if on_core is not None and ret.unsatisfiable:
+                    on_core(handle.core())
+                return ret
+        return handle
+
+    @property
+    def configuration(self) -> Configuration:
+        """
+        Object to change the configuration.
+        """
+        conf = _c_call(
+            "clingo_configuration_t*", _lib.clingo_control_configuration, self._rep
+        )
+        key = _c_call("clingo_id_t", _lib.clingo_configuration_root, conf)
+        return Configuration(conf, key)
+
+    @property
+    def enable_cleanup(self) -> bool:
+        """
+        Whether to enable automatic calls to `Control.cleanup`.
+        """
+        return _lib.clingo_control_get_enable_cleanup(self._rep)
+
+    @enable_cleanup.setter
+    def enable_cleanup(self, value: bool) -> None:
+        _handle_error(_lib.clingo_control_set_enable_cleanup(self._rep, value))
+
+    @property
+    def enable_enumeration_assumption(self) -> bool:
+        """
+        Whether do discard or keep learnt information from enumeration modes.
+
+        If the enumeration assumption is enabled, then all information learnt from
+        clasp's various enumeration modes is removed after a solve call. This includes
+        enumeration of cautious or brave consequences, enumeration of answer sets with
+        or without projection, or finding optimal models; as well as clauses added with
+        `clingo.solving.SolveControl.add_clause`.
+
+        Notes
+        -----
+        Initially the enumeration assumption is enabled.
+
+        In general, the enumeration assumption should be enabled whenever there are
+        multiple calls to solve. Otherwise, the behavior of the solver will be
+        unpredictable because there are no guarantees which information exactly is
+        kept. There might be small speed benefits when disabling the enumeration
+        assumption for single shot solving.
+        """
+        return _lib.clingo_control_get_enable_enumeration_assumption(self._rep)
+
+    @enable_enumeration_assumption.setter
+    def enable_enumeration_assumption(self, value: bool) -> None:
+        _handle_error(
+            _lib.clingo_control_set_enable_enumeration_assumption(self._rep, value)
+        )
+
+    @property
+    def is_conflicting(self) -> bool:
+        """
+        Whether the internal program representation is conflicting.
+
+        If this (read-only) property is true, solve calls return immediately with an
+        unsatisfiable solve result.
+
+        Notes
+        -----
+        Conflicts first have to be detected, e.g., initial unit propagation results in
+        an empty clause, or later if an empty clause is resolved during solving. Hence,
+        the property might be false even if the problem is unsatisfiable.
+        """
+        return _lib.clingo_control_is_conflicting(self._rep)
+
+    @property
+    def statistics(self) -> dict:
+        """
+        A `dict` containing solve statistics of the last solve call.
+
+        See Also
+        --------
+        clingo.statistics
+
+        Notes
+        -----
+        The statistics correspond to the `--stats` output of clingo. The detail of the
+        statistics depends on what level is requested on the command line. Furthermore,
+        there are some functions like `Control.release_external` that start a new
+        solving step resetting the current step statistics. It is best to access the
+        statistics right after solving.
+
+        This property is only available in clingo.
+        """
+        stats = _c_call(
+            "clingo_statistics_t*", _lib.clingo_control_statistics, self._rep
+        )
+
+        p_key = _ffi.new("uint64_t*")
+        key_root = _c_call(p_key, _lib.clingo_statistics_root, stats)
+
+        key_summary = _c_call(
+            p_key, _lib.clingo_statistics_map_at, stats, key_root, "summary".encode()
+        )
+        key_call = _c_call(
+            p_key, _lib.clingo_statistics_map_at, stats, key_summary, "call".encode()
+        )
+        call = _c_call("double", _lib.clingo_statistics_value_get, stats, key_call)
+        if self._statistics is not None and call != self._statistics_call:
+            self._statistics = None
+
+        if self._statistics is None:
+            self._statistics_call = call
+            self._statistics = _statistics(stats, key_root)
+
+        return cast(dict, self._statistics)
+
+    @property
+    def symbolic_atoms(self) -> SymbolicAtoms:
+        """
+        An object to inspect the symbolic atoms.
+
+        See Also
+        --------
+        clingo.symbolic_atoms
+        """
+        return SymbolicAtoms(
+            _c_call(
+                "clingo_symbolic_atoms_t*",
+                _lib.clingo_control_symbolic_atoms,
+                self._rep,
+            )
+        )
+
+    @property
+    def theory_atoms(self) -> Iterator[TheoryAtom]:
+        """
+        An iterator over the theory atoms in a program.
+
+        See Also
+        --------
+        clingo.theory_atoms
+        """
+        atoms = _c_call(
+            "clingo_theory_atoms_t*", _lib.clingo_control_theory_atoms, self._rep
+        )
+        size = _c_call("size_t", _lib.clingo_theory_atoms_size, atoms)
+
+        for idx in range(size):
+            yield TheoryAtom(atoms, idx)
+
+
+
+
+
+
+
+
+
+

Classes

+
+
+class Control +(arguments: Sequence[str] = [], logger: Optional[Callable[[MessageCode, str], None]] = None, message_limit: int = 20) +
+
+

Control object for the grounding/solving process.

+

Parameters

+
+
arguments
+
Arguments to the grounder and solver.
+
logger
+
Function to intercept messages normally printed to standard error.
+
message_limit
+
The maximum number of messages passed to the logger.
+
+

Notes

+

Note that only gringo options (without --text) and clasp's search options +are supported. Furthermore, you must not call any functions of a Control +object while a solve call is active.

+
+ +Expand source code + +
class Control:
+    """
+    Control object for the grounding/solving process.
+
+    Parameters
+    ----------
+    arguments
+        Arguments to the grounder and solver.
+    logger
+        Function to intercept messages normally printed to standard error.
+    message_limit
+        The maximum number of messages passed to the logger.
+
+    Notes
+    -----
+    Note that only gringo options (without `--text`) and clasp's search options
+    are supported. Furthermore, you must not call any functions of a `Control`
+    object while a solve call is active.
+    """
+
+    def __init__(
+        self,
+        arguments: Sequence[str] = [],
+        logger: Optional[Logger] = None,
+        message_limit: int = 20,
+    ):
+        # pylint: disable=protected-access,dangerous-default-value
+        self._free = False
+        self._mem = []
+        if isinstance(arguments, abc.Sequence):
+            if logger is not None:
+                c_handle = _ffi.new_handle(logger)
+                c_cb = _lib.pyclingo_logger_callback
+                self._mem.append(c_handle)
+            else:
+                c_handle = _ffi.NULL
+                c_cb = _ffi.NULL
+            c_mem = []
+            c_args = _ffi.new("char*[]", len(arguments))
+            for i, arg in enumerate(arguments):
+                c_mem.append(_ffi.new("char[]", arg.encode()))
+                c_args[i] = c_mem[-1]
+            self._rep = _c_call(
+                "clingo_control_t *",
+                _lib.clingo_control_new,
+                c_args,
+                len(arguments),
+                c_cb,
+                c_handle,
+                message_limit,
+            )
+            self._free = True
+        else:
+            self._rep = arguments
+
+        self._handler = None
+        self._statistics = None
+        self._statistics_call = -1.0
+        self._error = _Error()
+
+    def __del__(self):
+        if self._free:
+            _lib.clingo_control_free(self._rep)
+
+    @overload
+    def add(self, name: str, parameters: Sequence[str], program: str) -> None:
+        """
+        Extend the logic program with the given non-ground logic program in string form.
+
+        Parameters
+        ----------
+        name
+            The name of program block to add.
+        parameters
+            The parameters of the program block to add.
+        program
+            The non-ground program in string form.
+
+        See Also
+        --------
+        Control.ground
+        """
+
+    @overload
+    def add(self, program: str) -> None:
+        """
+        Extend the logic program with the given non-ground logic program in string form.
+
+        Parameters
+        ----------
+        name
+            The name of program block to add.
+
+        Notes
+        -----
+        This function is equivalent to calling `add("base", [], program)`.
+        """
+
+    def add(self, *args, **kwargs) -> None:
+        """
+        Extend the logic program with the given non-ground logic program in string form.
+
+        This function provides two overloads:
+
+        ```python
+        def add(self, name: str, parameters: Sequence[str], program: str) -> None:
+            ...
+
+        def add(self, program: str) -> None:
+            return self.add("base", [], program)
+        ```
+
+        Parameters
+        ----------
+        name
+            The name of program block to add.
+        parameters
+            The parameters of the program block to add.
+        program
+            The non-ground program in string form.
+
+        See Also
+        --------
+        Control.ground
+        """
+        n = len(args) + len(kwargs)
+        if n == 1:
+            self._add1(*args, **kwargs)
+        else:
+            self._add2(*args, **kwargs)
+
+    def _add1(self, program: str) -> None:
+        self._add2("base", [], program)
+
+    def _add2(self, name: str, parameters: Sequence[str], program: str) -> None:
+        c_mem = []
+        c_params = _ffi.new("char*[]", len(parameters))
+        for i, param in enumerate(parameters):
+            c_mem.append(_ffi.new("char[]", param.encode()))
+            c_params[i] = c_mem[-1]
+        _handle_error(
+            _lib.clingo_control_add(
+                self._rep, name.encode(), c_params, len(parameters), program.encode()
+            )
+        )
+
+    def _program_atom(self, lit: Union[Symbol, int]) -> int:
+        if isinstance(lit, int):
+            return lit
+        satom = self.symbolic_atoms[lit]
+        return 0 if satom is None else satom.literal
+
+    def assign_external(
+        self, external: Union[Symbol, int], truth: Optional[bool]
+    ) -> None:
+        """
+        Assign a truth value to an external atom.
+
+        Parameters
+        ----------
+        external
+            A symbol or program literal representing the external atom.
+        truth
+            A Boolean fixes the external to the respective truth value; and
+            None leaves its truth value open.
+
+        See Also
+        --------
+        Control.release_external, clingo.solving.SolveControl.symbolic_atoms,
+        clingo.symbolic_atoms.SymbolicAtom.is_external
+
+        Notes
+        -----
+        The truth value of an external atom can be changed before each solve
+        call. An atom is treated as external if it has been declared using an
+        `#external` directive, and has not been released by calling
+        `Control.release_external` or defined in a logic program with some
+        rule. If the given atom is not external, then the function has no
+        effect.
+
+        For convenience, the truth assigned to atoms over negative program
+        literals is inverted.
+        """
+
+        if truth is None:
+            val = _lib.clingo_external_type_free
+        elif truth:
+            val = _lib.clingo_external_type_true
+        else:
+            val = _lib.clingo_external_type_false
+        _handle_error(
+            _lib.clingo_control_assign_external(
+                self._rep, self._program_atom(external), val
+            )
+        )
+
+    def backend(self) -> Backend:
+        """
+        Returns a `Backend` object providing a low level interface to extend a
+        logic program.
+
+        See Also
+        --------
+        clingo.backend
+        """
+        return Backend(
+            _c_call("clingo_backend_t*", _lib.clingo_control_backend, self._rep),
+            self._error,
+        )
+
+    def cleanup(self) -> None:
+        """
+        Cleanup the domain used for grounding by incorporating information from
+        the solver.
+
+        This function cleans up the domain used for grounding.  This is done by
+        first simplifying the current program representation (falsifying
+        released external atoms).  Afterwards, the top-level implications are
+        used to either remove atoms from the domain or mark them as facts.
+
+        See Also
+        --------
+        Control.enable_cleanup
+
+        Notes
+        -----
+        Any atoms falsified are completely removed from the logic program.
+        Hence, a definition for such an atom in a successive step introduces a
+        fresh atom.
+
+        With the current implementation, the function only has an effect if
+        called after solving and before any function is called that starts a
+        new step.
+
+        Typically, it is not necessary to call this function manually because
+        automatic cleanups are enabled by default.
+        """
+        _handle_error(_lib.clingo_control_cleanup(self._rep))
+
+    def get_const(self, name: str) -> Optional[Symbol]:
+        """
+        Return the symbol for a constant definition of form:
+
+            #const name = symbol.
+
+        Parameters
+        ----------
+        name
+            The name of the constant to retrieve.
+
+        Returns
+        -------
+        The function returns `None` if no matching constant definition exists.
+        """
+        if not _c_call("bool", _lib.clingo_control_has_const, self._rep, name.encode()):
+            return None
+
+        return Symbol(
+            _c_call(
+                "clingo_symbol_t",
+                _lib.clingo_control_get_const,
+                self._rep,
+                name.encode(),
+            )
+        )
+
+    def ground(
+        self,
+        parts: Sequence[Tuple[str, Sequence[Symbol]]] = (("base", ()),),
+        context: Any = None,
+    ) -> None:
+        """
+        Ground the given list of program parts specified by tuples of names and
+        arguments.
+
+        Parameters
+        ----------
+        parts
+            List of tuples of program names and program arguments to ground.
+        context
+            A context object whose methods are called during grounding using
+            the `@`-syntax (if omitted, those from the main module are used).
+
+        Notes
+        -----
+        Note that parts of a logic program without an explicit `#program`
+        specification are by default put into a program called `base` without
+        arguments.
+        """
+        # pylint: disable=protected-access,dangerous-default-value
+        self._error.clear()
+        data = _CBData(context, self._error)
+        c_data = _ffi.new_handle(data) if context else _ffi.NULL
+        c_cb = _lib.pyclingo_ground_callback if context else _ffi.NULL
+
+        c_mem = []
+        c_parts = _ffi.new("clingo_part_t[]", len(parts))
+        for part, c_part in zip(parts, c_parts):
+            c_mem.append(_ffi.new("char[]", part[0].encode()))
+            c_part.name = c_mem[-1]
+            c_mem.append(_ffi.new("clingo_symbol_t[]", len(part[1])))
+            c_part.params = c_mem[-1]
+            for i, sym in enumerate(part[1]):
+                c_part.params[i] = sym._rep
+            c_part.size = len(part[1])
+
+        _handle_error(
+            _lib.clingo_control_ground(self._rep, c_parts, len(parts), c_cb, c_data),
+            data,
+        )
+
+    def interrupt(self) -> None:
+        """
+        Interrupt the active solve call.
+
+        Notes
+        -----
+        This function is thread-safe and can be called from a signal handler. If no
+        search is active, the subsequent call to `Control.solve` is interrupted. The
+        result of the `Control.solve` method can be used to query if the search was
+        interrupted.
+        """
+        _lib.clingo_control_interrupt(self._rep)
+
+    def load(self, path: str) -> None:
+        """
+        Extend the logic program with a (non-ground) logic program in a file.
+
+        Parameters
+        ----------
+        path
+            The path of the file to load.
+        """
+        _handle_error(_lib.clingo_control_load(self._rep, path.encode()))
+
+    def register_observer(self, observer: Observer, replace: bool = False) -> None:
+        """
+        Registers the given observer to inspect the produced grounding.
+
+        Parameters
+        ----------
+        observer
+            The observer to register. See below for a description of the requirede
+            interface.
+        replace
+            If set to true, the output is just passed to the observer and nolonger to
+            the underlying solver (or any previously registered observers).
+
+        See Also
+        --------
+        clingo.backend
+        """
+        # pylint: disable=protected-access,line-too-long
+        c_observer = _ffi.new(
+            "clingo_ground_program_observer_t*",
+            (
+                _lib.pyclingo_observer_init_program
+                if _overwritten(Observer, observer, "init_program")
+                else _ffi.NULL,
+                _lib.pyclingo_observer_begin_step
+                if _overwritten(Observer, observer, "begin_step")
+                else _ffi.NULL,
+                _lib.pyclingo_observer_end_step
+                if _overwritten(Observer, observer, "end_step")
+                else _ffi.NULL,
+                _lib.pyclingo_observer_rule
+                if _overwritten(Observer, observer, "rule")
+                else _ffi.NULL,
+                _lib.pyclingo_observer_weight_rule
+                if _overwritten(Observer, observer, "weight_rule")
+                else _ffi.NULL,
+                _lib.pyclingo_observer_minimize
+                if _overwritten(Observer, observer, "minimize")
+                else _ffi.NULL,
+                _lib.pyclingo_observer_project
+                if _overwritten(Observer, observer, "project")
+                else _ffi.NULL,
+                _lib.pyclingo_observer_output_atom
+                if _overwritten(Observer, observer, "output_atom")
+                else _ffi.NULL,
+                _lib.pyclingo_observer_output_term
+                if _overwritten(Observer, observer, "output_term")
+                else _ffi.NULL,
+                _lib.pyclingo_observer_external
+                if _overwritten(Observer, observer, "external")
+                else _ffi.NULL,
+                _lib.pyclingo_observer_assume
+                if _overwritten(Observer, observer, "assume")
+                else _ffi.NULL,
+                _lib.pyclingo_observer_heuristic
+                if _overwritten(Observer, observer, "heuristic")
+                else _ffi.NULL,
+                _lib.pyclingo_observer_acyc_edge
+                if _overwritten(Observer, observer, "acyc_edge")
+                else _ffi.NULL,
+                _lib.pyclingo_observer_theory_term_number
+                if _overwritten(Observer, observer, "theory_term_number")
+                else _ffi.NULL,
+                _lib.pyclingo_observer_theory_term_string
+                if _overwritten(Observer, observer, "theory_term_string")
+                else _ffi.NULL,
+                _lib.pyclingo_observer_theory_term_compound
+                if _overwritten(Observer, observer, "theory_term_compound")
+                else _ffi.NULL,
+                _lib.pyclingo_observer_theory_element
+                if _overwritten(Observer, observer, "theory_element")
+                else _ffi.NULL,
+                _lib.pyclingo_observer_theory_atom
+                if _overwritten(Observer, observer, "theory_atom")
+                else _ffi.NULL,
+                _lib.pyclingo_observer_theory_atom_with_guard
+                if _overwritten(Observer, observer, "theory_atom_with_guard")
+                else _ffi.NULL,
+            ),
+        )
+        c_data = _ffi.new_handle(_CBData(observer, self._error))
+        self._mem.append(c_data)
+        _handle_error(
+            _lib.clingo_control_register_observer(
+                self._rep, c_observer, replace, c_data
+            )
+        )
+
+    def register_propagator(self, propagator: Propagator) -> None:
+        """
+        Registers the given propagator with all solvers.
+
+        Parameters
+        ----------
+        propagator
+            The propagator to register.
+
+        See Also
+        --------
+        clingo.propagator
+        """
+        # pylint: disable=protected-access
+        c_propagator = _ffi.new(
+            "clingo_propagator_t*",
+            (
+                _lib.pyclingo_propagator_init
+                if _overwritten(Propagator, propagator, "init")
+                else _ffi.NULL,
+                _lib.pyclingo_propagator_propagate
+                if _overwritten(Propagator, propagator, "propagate")
+                else _ffi.NULL,
+                _lib.pyclingo_propagator_undo
+                if _overwritten(Propagator, propagator, "undo")
+                else _ffi.NULL,
+                _lib.pyclingo_propagator_check
+                if _overwritten(Propagator, propagator, "check")
+                else _ffi.NULL,
+                _lib.pyclingo_propagator_decide
+                if _overwritten(Propagator, propagator, "decide")
+                else _ffi.NULL,
+            ),
+        )
+        c_data = _ffi.new_handle(_CBData(propagator, self._error))
+        self._mem.append(c_data)
+        _handle_error(
+            _lib.clingo_control_register_propagator(
+                self._rep, c_propagator, c_data, False
+            )
+        )
+
+    def release_external(self, external: Union[Symbol, int]) -> None:
+        """
+        Release an external atom represented by the given symbol or program
+        literal.
+
+        This function causes the corresponding atom to become permanently false
+        if there is no definition for the atom in the program. Otherwise, the
+        function has no effect.
+
+        Parameters
+        ----------
+        external
+            The symbolic atom or program atom to release.
+
+        Notes
+        -----
+        If the program literal is negative, the corresponding atom is released.
+
+        Examples
+        --------
+        The following example shows the effect of assigning and releasing and external
+        atom.
+
+            >>> from clingo.symbol import Function
+            >>> from clingo.control import Control
+            >>>
+            >>> ctl = Control()
+            >>> ctl.add("base", [], "a. #external b.")
+            >>> ctl.ground([("base", [])])
+            >>> ctl.assign_external(Function("b"), True)
+            >>> print(ctl.solve(on_model=print))
+            b a
+            SAT
+            >>> ctl.release_external(Function("b"))
+            >>> print(ctl.solve(on_model=print))
+            a
+            SAT
+        """
+        _handle_error(
+            _lib.clingo_control_release_external(
+                self._rep, self._program_atom(external)
+            )
+        )
+
+    # this assumes that overloads are matched in the order they appear
+    # unfortunately, PEP0484 does not specify any kind of semantics just giving examples
+    if sys.version_info >= (3, 8):
+        @overload
+        def solve(
+            self,
+            assumptions: Sequence[Union[Tuple[Symbol, bool], int]] = (),
+            on_model: Optional[Callable[[Model], Optional[bool]]] = None,
+            on_unsat: Optional[Callable[[Sequence[int]], None]] = None,
+            on_statistics: Optional[Callable[[StatisticsMap, StatisticsMap], None]] = None,
+            on_finish: Optional[Callable[[SolveResult], None]] = None,
+            on_core: Optional[Callable[[Sequence[int]], None]] = None,
+            *,
+            yield_: Literal[False] = False,
+            async_: Literal[False] = False,
+        ) -> SolveResult: ...
+        @overload
+        def solve(
+            self,
+            assumptions: Sequence[Union[Tuple[Symbol, bool], int]] = (),
+            on_model: Optional[Callable[[Model], Optional[bool]]] = None,
+            on_unsat: Optional[Callable[[Sequence[int]], None]] = None,
+            on_statistics: Optional[Callable[[StatisticsMap, StatisticsMap], None]] = None,
+            on_finish: Optional[Callable[[SolveResult], None]] = None,
+            on_core: Optional[Callable[[Sequence[int]], None]] = None,
+            *,
+            yield_: Literal[True],
+            async_: bool = False,
+        ) -> SolveHandle: ...
+        @overload
+        def solve(
+            self,
+            assumptions: Sequence[Union[Tuple[Symbol, bool], int]] = (),
+            on_model: Optional[Callable[[Model], Optional[bool]]] = None,
+            on_unsat: Optional[Callable[[Sequence[int]], None]] = None,
+            on_statistics: Optional[Callable[[StatisticsMap, StatisticsMap], None]] = None,
+            on_finish: Optional[Callable[[SolveResult], None]] = None,
+            on_core: Optional[Callable[[Sequence[int]], None]] = None,
+            *,
+            yield_: bool = False,
+            async_: Literal[True],
+        ) -> SolveHandle: ...
+    else:
+        @overload
+        def solve(
+            self,
+            assumptions: Sequence[Union[Tuple[Symbol, bool], int]] = (),
+            on_model: Optional[Callable[[Model], Optional[bool]]] = None,
+            on_unsat: Optional[Callable[[Sequence[int]], None]] = None,
+            on_statistics: Optional[Callable[[StatisticsMap, StatisticsMap], None]] = None,
+            on_finish: Optional[Callable[[SolveResult], None]] = None,
+            on_core: Optional[Callable[[Sequence[int]], None]] = None,
+        ) -> SolveResult: ...
+
+    @overload
+    def solve(
+        self,
+        assumptions: Sequence[Union[Tuple[Symbol, bool], int]] = (),
+        on_model: Optional[Callable[[Model], Optional[bool]]] = None,
+        on_unsat: Optional[Callable[[Sequence[int]], None]] = None,
+        on_statistics: Optional[Callable[[StatisticsMap, StatisticsMap], None]] = None,
+        on_finish: Optional[Callable[[SolveResult], None]] = None,
+        on_core: Optional[Callable[[Sequence[int]], None]] = None,
+        yield_: bool = False,
+        async_: bool = False,
+    ) -> Union[SolveHandle, SolveResult]: ...
+
+    def solve(
+        self,
+        assumptions: Sequence[Union[Tuple[Symbol, bool], int]] = (),
+        on_model: Optional[Callable[[Model], Optional[bool]]] = None,
+        on_unsat: Optional[Callable[[Sequence[int]], None]] = None,
+        on_statistics: Optional[Callable[[StatisticsMap, StatisticsMap], None]] = None,
+        on_finish: Optional[Callable[[SolveResult], None]] = None,
+        on_core: Optional[Callable[[Sequence[int]], None]] = None,
+        yield_: bool = False,
+        async_: bool = False,
+    ) -> Union[SolveHandle, SolveResult]:
+        """
+        Starts a search.
+
+        Parameters
+        ----------
+        assumptions
+            List of (atom, boolean) tuples or program literals (see
+            `clingo.symbolic_atoms.SymbolicAtom.literal`) that serve as
+            assumptions for the solve call, e.g., solving under assumptions
+            `[(Function("a"), True)]` only admits answer sets that contain atom `a`.
+        on_model
+            Optional callback for intercepting models.
+            A `clingo.solving.Model` object is passed to the callback. The
+            search can be interruped from the model callback by returning
+            False.
+        on_unsat
+            Optional callback to intercept lower bounds during optimization.
+        on_statistics
+            Optional callback to update statistics.
+            The step and accumulated statistics are passed as arguments.
+        on_finish
+            Optional callback called once search has finished.
+            A `clingo.solving.SolveResult` also indicating whether the solve
+            call has been intrrupted is passed to the callback.
+        on_core
+            Optional callback called with the assumptions that made a problem
+            unsatisfiable.
+        yield_
+            The resulting `clingo.solving.SolveHandle` is iterable yielding
+            `clingo.solving.Model` objects.
+        async_
+            The solve call and the method `clingo.solving.SolveHandle.resume`
+            of the returned handle are non-blocking.
+
+        Returns
+        -------
+        The return value depends on the parameters. If either `yield_` or
+        `async_` is true, then a handle is returned. Otherwise, a
+        `clingo.solving.SolveResult` is returned.
+
+        See Also
+        --------
+        clingo.solving
+
+        Notes
+        -----
+        If neither `yield_` nor `async_` is set, the function returns a
+        `clingo.solving.SolveResult` right away.
+
+        In gringo or in clingo with lparse or text output enabled, this
+        function just grounds and returns a `clingo.solving.SolveResult` where
+        `clingo.solving.SolveResult.unknown` is true.
+
+        If this function is used in embedded Python code, you might want to start
+        clingo using the `--outf=3` option to disable all output from clingo.
+
+        Asynchronous solving is only available in clingo with thread support
+        enabled. Furthermore, the on_model and on_finish callbacks are called
+        from another thread. To ensure that the methods can be called, make
+        sure to not use any functions that block Python's GIL indefinitely.
+
+        This function as well as blocking functions on the
+        `clingo.solving.SolveHandle` release the GIL but are not thread-safe.
+        """
+        # pylint: disable=protected-access,dangerous-default-value
+        self._error.clear()
+        handler = _SolveEventHandler(on_model, on_unsat, on_statistics, on_finish)
+        data = _CBData(handler, self._error)
+        self._handler = _ffi.new_handle(data)
+
+        p_ass = _ffi.NULL
+        if assumptions:
+            atoms = None
+            p_ass = _ffi.new("clingo_literal_t[]", len(assumptions))
+            for i, lit in enumerate(assumptions):
+                if isinstance(lit, int):
+                    p_ass[i] = lit
+                else:
+                    if atoms is None:
+                        atoms = self.symbolic_atoms
+                    atom = self.symbolic_atoms[lit[0]]
+                    slit = -1 if atom is None else atom.literal
+                    p_ass[i] = slit if lit[1] else -slit
+
+        mode = 0
+        if yield_:
+            mode |= _lib.clingo_solve_mode_yield
+        if async_:
+            mode |= _lib.clingo_solve_mode_async
+
+        handle = SolveHandle(
+            _c_call(
+                "clingo_solve_handle_t*",
+                _lib.clingo_control_solve,
+                self._rep,
+                mode,
+                p_ass,
+                len(assumptions),
+                _lib.pyclingo_solve_event_callback,
+                self._handler,
+                handler=data,
+            ),
+            data,
+        )
+
+        if not yield_ and not async_:
+            with handle:
+                ret = handle.get()
+                if on_core is not None and ret.unsatisfiable:
+                    on_core(handle.core())
+                return ret
+        return handle
+
+    @property
+    def configuration(self) -> Configuration:
+        """
+        Object to change the configuration.
+        """
+        conf = _c_call(
+            "clingo_configuration_t*", _lib.clingo_control_configuration, self._rep
+        )
+        key = _c_call("clingo_id_t", _lib.clingo_configuration_root, conf)
+        return Configuration(conf, key)
+
+    @property
+    def enable_cleanup(self) -> bool:
+        """
+        Whether to enable automatic calls to `Control.cleanup`.
+        """
+        return _lib.clingo_control_get_enable_cleanup(self._rep)
+
+    @enable_cleanup.setter
+    def enable_cleanup(self, value: bool) -> None:
+        _handle_error(_lib.clingo_control_set_enable_cleanup(self._rep, value))
+
+    @property
+    def enable_enumeration_assumption(self) -> bool:
+        """
+        Whether do discard or keep learnt information from enumeration modes.
+
+        If the enumeration assumption is enabled, then all information learnt from
+        clasp's various enumeration modes is removed after a solve call. This includes
+        enumeration of cautious or brave consequences, enumeration of answer sets with
+        or without projection, or finding optimal models; as well as clauses added with
+        `clingo.solving.SolveControl.add_clause`.
+
+        Notes
+        -----
+        Initially the enumeration assumption is enabled.
+
+        In general, the enumeration assumption should be enabled whenever there are
+        multiple calls to solve. Otherwise, the behavior of the solver will be
+        unpredictable because there are no guarantees which information exactly is
+        kept. There might be small speed benefits when disabling the enumeration
+        assumption for single shot solving.
+        """
+        return _lib.clingo_control_get_enable_enumeration_assumption(self._rep)
+
+    @enable_enumeration_assumption.setter
+    def enable_enumeration_assumption(self, value: bool) -> None:
+        _handle_error(
+            _lib.clingo_control_set_enable_enumeration_assumption(self._rep, value)
+        )
+
+    @property
+    def is_conflicting(self) -> bool:
+        """
+        Whether the internal program representation is conflicting.
+
+        If this (read-only) property is true, solve calls return immediately with an
+        unsatisfiable solve result.
+
+        Notes
+        -----
+        Conflicts first have to be detected, e.g., initial unit propagation results in
+        an empty clause, or later if an empty clause is resolved during solving. Hence,
+        the property might be false even if the problem is unsatisfiable.
+        """
+        return _lib.clingo_control_is_conflicting(self._rep)
+
+    @property
+    def statistics(self) -> dict:
+        """
+        A `dict` containing solve statistics of the last solve call.
+
+        See Also
+        --------
+        clingo.statistics
+
+        Notes
+        -----
+        The statistics correspond to the `--stats` output of clingo. The detail of the
+        statistics depends on what level is requested on the command line. Furthermore,
+        there are some functions like `Control.release_external` that start a new
+        solving step resetting the current step statistics. It is best to access the
+        statistics right after solving.
+
+        This property is only available in clingo.
+        """
+        stats = _c_call(
+            "clingo_statistics_t*", _lib.clingo_control_statistics, self._rep
+        )
+
+        p_key = _ffi.new("uint64_t*")
+        key_root = _c_call(p_key, _lib.clingo_statistics_root, stats)
+
+        key_summary = _c_call(
+            p_key, _lib.clingo_statistics_map_at, stats, key_root, "summary".encode()
+        )
+        key_call = _c_call(
+            p_key, _lib.clingo_statistics_map_at, stats, key_summary, "call".encode()
+        )
+        call = _c_call("double", _lib.clingo_statistics_value_get, stats, key_call)
+        if self._statistics is not None and call != self._statistics_call:
+            self._statistics = None
+
+        if self._statistics is None:
+            self._statistics_call = call
+            self._statistics = _statistics(stats, key_root)
+
+        return cast(dict, self._statistics)
+
+    @property
+    def symbolic_atoms(self) -> SymbolicAtoms:
+        """
+        An object to inspect the symbolic atoms.
+
+        See Also
+        --------
+        clingo.symbolic_atoms
+        """
+        return SymbolicAtoms(
+            _c_call(
+                "clingo_symbolic_atoms_t*",
+                _lib.clingo_control_symbolic_atoms,
+                self._rep,
+            )
+        )
+
+    @property
+    def theory_atoms(self) -> Iterator[TheoryAtom]:
+        """
+        An iterator over the theory atoms in a program.
+
+        See Also
+        --------
+        clingo.theory_atoms
+        """
+        atoms = _c_call(
+            "clingo_theory_atoms_t*", _lib.clingo_control_theory_atoms, self._rep
+        )
+        size = _c_call("size_t", _lib.clingo_theory_atoms_size, atoms)
+
+        for idx in range(size):
+            yield TheoryAtom(atoms, idx)
+
+

Instance variables

+
+
var configurationConfiguration
+
+

Object to change the configuration.

+
+ +Expand source code + +
@property
+def configuration(self) -> Configuration:
+    """
+    Object to change the configuration.
+    """
+    conf = _c_call(
+        "clingo_configuration_t*", _lib.clingo_control_configuration, self._rep
+    )
+    key = _c_call("clingo_id_t", _lib.clingo_configuration_root, conf)
+    return Configuration(conf, key)
+
+
+
var enable_cleanup : bool
+
+

Whether to enable automatic calls to Control.cleanup().

+
+ +Expand source code + +
@property
+def enable_cleanup(self) -> bool:
+    """
+    Whether to enable automatic calls to `Control.cleanup`.
+    """
+    return _lib.clingo_control_get_enable_cleanup(self._rep)
+
+
+
var enable_enumeration_assumption : bool
+
+

Whether do discard or keep learnt information from enumeration modes.

+

If the enumeration assumption is enabled, then all information learnt from +clasp's various enumeration modes is removed after a solve call. This includes +enumeration of cautious or brave consequences, enumeration of answer sets with +or without projection, or finding optimal models; as well as clauses added with +SolveControl.add_clause().

+

Notes

+

Initially the enumeration assumption is enabled.

+

In general, the enumeration assumption should be enabled whenever there are +multiple calls to solve. Otherwise, the behavior of the solver will be +unpredictable because there are no guarantees which information exactly is +kept. There might be small speed benefits when disabling the enumeration +assumption for single shot solving.

+
+ +Expand source code + +
@property
+def enable_enumeration_assumption(self) -> bool:
+    """
+    Whether do discard or keep learnt information from enumeration modes.
+
+    If the enumeration assumption is enabled, then all information learnt from
+    clasp's various enumeration modes is removed after a solve call. This includes
+    enumeration of cautious or brave consequences, enumeration of answer sets with
+    or without projection, or finding optimal models; as well as clauses added with
+    `clingo.solving.SolveControl.add_clause`.
+
+    Notes
+    -----
+    Initially the enumeration assumption is enabled.
+
+    In general, the enumeration assumption should be enabled whenever there are
+    multiple calls to solve. Otherwise, the behavior of the solver will be
+    unpredictable because there are no guarantees which information exactly is
+    kept. There might be small speed benefits when disabling the enumeration
+    assumption for single shot solving.
+    """
+    return _lib.clingo_control_get_enable_enumeration_assumption(self._rep)
+
+
+
var is_conflicting : bool
+
+

Whether the internal program representation is conflicting.

+

If this (read-only) property is true, solve calls return immediately with an +unsatisfiable solve result.

+

Notes

+

Conflicts first have to be detected, e.g., initial unit propagation results in +an empty clause, or later if an empty clause is resolved during solving. Hence, +the property might be false even if the problem is unsatisfiable.

+
+ +Expand source code + +
@property
+def is_conflicting(self) -> bool:
+    """
+    Whether the internal program representation is conflicting.
+
+    If this (read-only) property is true, solve calls return immediately with an
+    unsatisfiable solve result.
+
+    Notes
+    -----
+    Conflicts first have to be detected, e.g., initial unit propagation results in
+    an empty clause, or later if an empty clause is resolved during solving. Hence,
+    the property might be false even if the problem is unsatisfiable.
+    """
+    return _lib.clingo_control_is_conflicting(self._rep)
+
+
+
var statistics : dict
+
+

A dict containing solve statistics of the last solve call.

+

See Also

+

clingo.statistics

+

Notes

+

The statistics correspond to the --stats output of clingo. The detail of the +statistics depends on what level is requested on the command line. Furthermore, +there are some functions like Control.release_external() that start a new +solving step resetting the current step statistics. It is best to access the +statistics right after solving.

+

This property is only available in clingo.

+
+ +Expand source code + +
@property
+def statistics(self) -> dict:
+    """
+    A `dict` containing solve statistics of the last solve call.
+
+    See Also
+    --------
+    clingo.statistics
+
+    Notes
+    -----
+    The statistics correspond to the `--stats` output of clingo. The detail of the
+    statistics depends on what level is requested on the command line. Furthermore,
+    there are some functions like `Control.release_external` that start a new
+    solving step resetting the current step statistics. It is best to access the
+    statistics right after solving.
+
+    This property is only available in clingo.
+    """
+    stats = _c_call(
+        "clingo_statistics_t*", _lib.clingo_control_statistics, self._rep
+    )
+
+    p_key = _ffi.new("uint64_t*")
+    key_root = _c_call(p_key, _lib.clingo_statistics_root, stats)
+
+    key_summary = _c_call(
+        p_key, _lib.clingo_statistics_map_at, stats, key_root, "summary".encode()
+    )
+    key_call = _c_call(
+        p_key, _lib.clingo_statistics_map_at, stats, key_summary, "call".encode()
+    )
+    call = _c_call("double", _lib.clingo_statistics_value_get, stats, key_call)
+    if self._statistics is not None and call != self._statistics_call:
+        self._statistics = None
+
+    if self._statistics is None:
+        self._statistics_call = call
+        self._statistics = _statistics(stats, key_root)
+
+    return cast(dict, self._statistics)
+
+
+
var symbolic_atomsSymbolicAtoms
+
+

An object to inspect the symbolic atoms.

+

See Also

+

clingo.symbolic_atoms

+
+ +Expand source code + +
@property
+def symbolic_atoms(self) -> SymbolicAtoms:
+    """
+    An object to inspect the symbolic atoms.
+
+    See Also
+    --------
+    clingo.symbolic_atoms
+    """
+    return SymbolicAtoms(
+        _c_call(
+            "clingo_symbolic_atoms_t*",
+            _lib.clingo_control_symbolic_atoms,
+            self._rep,
+        )
+    )
+
+
+
var theory_atoms : Iterator[TheoryAtom]
+
+

An iterator over the theory atoms in a program.

+

See Also

+

clingo.theory_atoms

+
+ +Expand source code + +
@property
+def theory_atoms(self) -> Iterator[TheoryAtom]:
+    """
+    An iterator over the theory atoms in a program.
+
+    See Also
+    --------
+    clingo.theory_atoms
+    """
+    atoms = _c_call(
+        "clingo_theory_atoms_t*", _lib.clingo_control_theory_atoms, self._rep
+    )
+    size = _c_call("size_t", _lib.clingo_theory_atoms_size, atoms)
+
+    for idx in range(size):
+        yield TheoryAtom(atoms, idx)
+
+
+
+

Methods

+
+
+def add(self, *args, **kwargs) ‑> None +
+
+

Extend the logic program with the given non-ground logic program in string form.

+

This function provides two overloads:

+
def add(self, name: str, parameters: Sequence[str], program: str) -> None:
+    ...
+
+def add(self, program: str) -> None:
+    return self.add("base", [], program)
+
+

Parameters

+
+
name
+
The name of program block to add.
+
parameters
+
The parameters of the program block to add.
+
program
+
The non-ground program in string form.
+
+

See Also

+

Control.ground()

+
+ +Expand source code + +
def add(self, *args, **kwargs) -> None:
+    """
+    Extend the logic program with the given non-ground logic program in string form.
+
+    This function provides two overloads:
+
+    ```python
+    def add(self, name: str, parameters: Sequence[str], program: str) -> None:
+        ...
+
+    def add(self, program: str) -> None:
+        return self.add("base", [], program)
+    ```
+
+    Parameters
+    ----------
+    name
+        The name of program block to add.
+    parameters
+        The parameters of the program block to add.
+    program
+        The non-ground program in string form.
+
+    See Also
+    --------
+    Control.ground
+    """
+    n = len(args) + len(kwargs)
+    if n == 1:
+        self._add1(*args, **kwargs)
+    else:
+        self._add2(*args, **kwargs)
+
+
+
+def assign_external(self, external: Union[Symbol, int], truth: Optional[bool]) ‑> None +
+
+

Assign a truth value to an external atom.

+

Parameters

+
+
external
+
A symbol or program literal representing the external atom.
+
truth
+
A Boolean fixes the external to the respective truth value; and +None leaves its truth value open.
+
+

See Also

+

Control.release_external(), SolveControl.symbolic_atoms, +SymbolicAtom.is_external

+

Notes

+

The truth value of an external atom can be changed before each solve +call. An atom is treated as external if it has been declared using an +#external directive, and has not been released by calling +Control.release_external() or defined in a logic program with some +rule. If the given atom is not external, then the function has no +effect.

+

For convenience, the truth assigned to atoms over negative program +literals is inverted.

+
+ +Expand source code + +
def assign_external(
+    self, external: Union[Symbol, int], truth: Optional[bool]
+) -> None:
+    """
+    Assign a truth value to an external atom.
+
+    Parameters
+    ----------
+    external
+        A symbol or program literal representing the external atom.
+    truth
+        A Boolean fixes the external to the respective truth value; and
+        None leaves its truth value open.
+
+    See Also
+    --------
+    Control.release_external, clingo.solving.SolveControl.symbolic_atoms,
+    clingo.symbolic_atoms.SymbolicAtom.is_external
+
+    Notes
+    -----
+    The truth value of an external atom can be changed before each solve
+    call. An atom is treated as external if it has been declared using an
+    `#external` directive, and has not been released by calling
+    `Control.release_external` or defined in a logic program with some
+    rule. If the given atom is not external, then the function has no
+    effect.
+
+    For convenience, the truth assigned to atoms over negative program
+    literals is inverted.
+    """
+
+    if truth is None:
+        val = _lib.clingo_external_type_free
+    elif truth:
+        val = _lib.clingo_external_type_true
+    else:
+        val = _lib.clingo_external_type_false
+    _handle_error(
+        _lib.clingo_control_assign_external(
+            self._rep, self._program_atom(external), val
+        )
+    )
+
+
+
+def backend(self) ‑> Backend +
+
+

Returns a Backend object providing a low level interface to extend a +logic program.

+

See Also

+

clingo.backend

+
+ +Expand source code + +
def backend(self) -> Backend:
+    """
+    Returns a `Backend` object providing a low level interface to extend a
+    logic program.
+
+    See Also
+    --------
+    clingo.backend
+    """
+    return Backend(
+        _c_call("clingo_backend_t*", _lib.clingo_control_backend, self._rep),
+        self._error,
+    )
+
+
+
+def cleanup(self) ‑> None +
+
+

Cleanup the domain used for grounding by incorporating information from +the solver.

+

This function cleans up the domain used for grounding. +This is done by +first simplifying the current program representation (falsifying +released external atoms). +Afterwards, the top-level implications are +used to either remove atoms from the domain or mark them as facts.

+

See Also

+

Control.enable_cleanup

+

Notes

+

Any atoms falsified are completely removed from the logic program. +Hence, a definition for such an atom in a successive step introduces a +fresh atom.

+

With the current implementation, the function only has an effect if +called after solving and before any function is called that starts a +new step.

+

Typically, it is not necessary to call this function manually because +automatic cleanups are enabled by default.

+
+ +Expand source code + +
def cleanup(self) -> None:
+    """
+    Cleanup the domain used for grounding by incorporating information from
+    the solver.
+
+    This function cleans up the domain used for grounding.  This is done by
+    first simplifying the current program representation (falsifying
+    released external atoms).  Afterwards, the top-level implications are
+    used to either remove atoms from the domain or mark them as facts.
+
+    See Also
+    --------
+    Control.enable_cleanup
+
+    Notes
+    -----
+    Any atoms falsified are completely removed from the logic program.
+    Hence, a definition for such an atom in a successive step introduces a
+    fresh atom.
+
+    With the current implementation, the function only has an effect if
+    called after solving and before any function is called that starts a
+    new step.
+
+    Typically, it is not necessary to call this function manually because
+    automatic cleanups are enabled by default.
+    """
+    _handle_error(_lib.clingo_control_cleanup(self._rep))
+
+
+
+def get_const(self, name: str) ‑> Optional[Symbol] +
+
+

Return the symbol for a constant definition of form:

+
#const name = symbol.
+
+

Parameters

+
+
name
+
The name of the constant to retrieve.
+
+

Returns

+

The function returns None if no matching constant definition exists.

+
+ +Expand source code + +
def get_const(self, name: str) -> Optional[Symbol]:
+    """
+    Return the symbol for a constant definition of form:
+
+        #const name = symbol.
+
+    Parameters
+    ----------
+    name
+        The name of the constant to retrieve.
+
+    Returns
+    -------
+    The function returns `None` if no matching constant definition exists.
+    """
+    if not _c_call("bool", _lib.clingo_control_has_const, self._rep, name.encode()):
+        return None
+
+    return Symbol(
+        _c_call(
+            "clingo_symbol_t",
+            _lib.clingo_control_get_const,
+            self._rep,
+            name.encode(),
+        )
+    )
+
+
+
+def ground(self, parts: Sequence[Tuple[str, Sequence[Symbol]]] = (('base', ()),), context: Any = None) ‑> None +
+
+

Ground the given list of program parts specified by tuples of names and +arguments.

+

Parameters

+
+
parts
+
List of tuples of program names and program arguments to ground.
+
context
+
A context object whose methods are called during grounding using +the @-syntax (if omitted, those from the main module are used).
+
+

Notes

+

Note that parts of a logic program without an explicit #program +specification are by default put into a program called base without +arguments.

+
+ +Expand source code + +
def ground(
+    self,
+    parts: Sequence[Tuple[str, Sequence[Symbol]]] = (("base", ()),),
+    context: Any = None,
+) -> None:
+    """
+    Ground the given list of program parts specified by tuples of names and
+    arguments.
+
+    Parameters
+    ----------
+    parts
+        List of tuples of program names and program arguments to ground.
+    context
+        A context object whose methods are called during grounding using
+        the `@`-syntax (if omitted, those from the main module are used).
+
+    Notes
+    -----
+    Note that parts of a logic program without an explicit `#program`
+    specification are by default put into a program called `base` without
+    arguments.
+    """
+    # pylint: disable=protected-access,dangerous-default-value
+    self._error.clear()
+    data = _CBData(context, self._error)
+    c_data = _ffi.new_handle(data) if context else _ffi.NULL
+    c_cb = _lib.pyclingo_ground_callback if context else _ffi.NULL
+
+    c_mem = []
+    c_parts = _ffi.new("clingo_part_t[]", len(parts))
+    for part, c_part in zip(parts, c_parts):
+        c_mem.append(_ffi.new("char[]", part[0].encode()))
+        c_part.name = c_mem[-1]
+        c_mem.append(_ffi.new("clingo_symbol_t[]", len(part[1])))
+        c_part.params = c_mem[-1]
+        for i, sym in enumerate(part[1]):
+            c_part.params[i] = sym._rep
+        c_part.size = len(part[1])
+
+    _handle_error(
+        _lib.clingo_control_ground(self._rep, c_parts, len(parts), c_cb, c_data),
+        data,
+    )
+
+
+
+def interrupt(self) ‑> None +
+
+

Interrupt the active solve call.

+

Notes

+

This function is thread-safe and can be called from a signal handler. If no +search is active, the subsequent call to Control.solve() is interrupted. The +result of the Control.solve() method can be used to query if the search was +interrupted.

+
+ +Expand source code + +
def interrupt(self) -> None:
+    """
+    Interrupt the active solve call.
+
+    Notes
+    -----
+    This function is thread-safe and can be called from a signal handler. If no
+    search is active, the subsequent call to `Control.solve` is interrupted. The
+    result of the `Control.solve` method can be used to query if the search was
+    interrupted.
+    """
+    _lib.clingo_control_interrupt(self._rep)
+
+
+
+def load(self, path: str) ‑> None +
+
+

Extend the logic program with a (non-ground) logic program in a file.

+

Parameters

+
+
path
+
The path of the file to load.
+
+
+ +Expand source code + +
def load(self, path: str) -> None:
+    """
+    Extend the logic program with a (non-ground) logic program in a file.
+
+    Parameters
+    ----------
+    path
+        The path of the file to load.
+    """
+    _handle_error(_lib.clingo_control_load(self._rep, path.encode()))
+
+
+
+def register_observer(self, observer: Observer, replace: bool = False) ‑> None +
+
+

Registers the given observer to inspect the produced grounding.

+

Parameters

+
+
observer
+
The observer to register. See below for a description of the requirede +interface.
+
replace
+
If set to true, the output is just passed to the observer and nolonger to +the underlying solver (or any previously registered observers).
+
+

See Also

+

clingo.backend

+
+ +Expand source code + +
def register_observer(self, observer: Observer, replace: bool = False) -> None:
+    """
+    Registers the given observer to inspect the produced grounding.
+
+    Parameters
+    ----------
+    observer
+        The observer to register. See below for a description of the requirede
+        interface.
+    replace
+        If set to true, the output is just passed to the observer and nolonger to
+        the underlying solver (or any previously registered observers).
+
+    See Also
+    --------
+    clingo.backend
+    """
+    # pylint: disable=protected-access,line-too-long
+    c_observer = _ffi.new(
+        "clingo_ground_program_observer_t*",
+        (
+            _lib.pyclingo_observer_init_program
+            if _overwritten(Observer, observer, "init_program")
+            else _ffi.NULL,
+            _lib.pyclingo_observer_begin_step
+            if _overwritten(Observer, observer, "begin_step")
+            else _ffi.NULL,
+            _lib.pyclingo_observer_end_step
+            if _overwritten(Observer, observer, "end_step")
+            else _ffi.NULL,
+            _lib.pyclingo_observer_rule
+            if _overwritten(Observer, observer, "rule")
+            else _ffi.NULL,
+            _lib.pyclingo_observer_weight_rule
+            if _overwritten(Observer, observer, "weight_rule")
+            else _ffi.NULL,
+            _lib.pyclingo_observer_minimize
+            if _overwritten(Observer, observer, "minimize")
+            else _ffi.NULL,
+            _lib.pyclingo_observer_project
+            if _overwritten(Observer, observer, "project")
+            else _ffi.NULL,
+            _lib.pyclingo_observer_output_atom
+            if _overwritten(Observer, observer, "output_atom")
+            else _ffi.NULL,
+            _lib.pyclingo_observer_output_term
+            if _overwritten(Observer, observer, "output_term")
+            else _ffi.NULL,
+            _lib.pyclingo_observer_external
+            if _overwritten(Observer, observer, "external")
+            else _ffi.NULL,
+            _lib.pyclingo_observer_assume
+            if _overwritten(Observer, observer, "assume")
+            else _ffi.NULL,
+            _lib.pyclingo_observer_heuristic
+            if _overwritten(Observer, observer, "heuristic")
+            else _ffi.NULL,
+            _lib.pyclingo_observer_acyc_edge
+            if _overwritten(Observer, observer, "acyc_edge")
+            else _ffi.NULL,
+            _lib.pyclingo_observer_theory_term_number
+            if _overwritten(Observer, observer, "theory_term_number")
+            else _ffi.NULL,
+            _lib.pyclingo_observer_theory_term_string
+            if _overwritten(Observer, observer, "theory_term_string")
+            else _ffi.NULL,
+            _lib.pyclingo_observer_theory_term_compound
+            if _overwritten(Observer, observer, "theory_term_compound")
+            else _ffi.NULL,
+            _lib.pyclingo_observer_theory_element
+            if _overwritten(Observer, observer, "theory_element")
+            else _ffi.NULL,
+            _lib.pyclingo_observer_theory_atom
+            if _overwritten(Observer, observer, "theory_atom")
+            else _ffi.NULL,
+            _lib.pyclingo_observer_theory_atom_with_guard
+            if _overwritten(Observer, observer, "theory_atom_with_guard")
+            else _ffi.NULL,
+        ),
+    )
+    c_data = _ffi.new_handle(_CBData(observer, self._error))
+    self._mem.append(c_data)
+    _handle_error(
+        _lib.clingo_control_register_observer(
+            self._rep, c_observer, replace, c_data
+        )
+    )
+
+
+
+def register_propagator(self, propagator: Propagator) ‑> None +
+
+

Registers the given propagator with all solvers.

+

Parameters

+
+
propagator
+
The propagator to register.
+
+

See Also

+

clingo.propagator

+
+ +Expand source code + +
def register_propagator(self, propagator: Propagator) -> None:
+    """
+    Registers the given propagator with all solvers.
+
+    Parameters
+    ----------
+    propagator
+        The propagator to register.
+
+    See Also
+    --------
+    clingo.propagator
+    """
+    # pylint: disable=protected-access
+    c_propagator = _ffi.new(
+        "clingo_propagator_t*",
+        (
+            _lib.pyclingo_propagator_init
+            if _overwritten(Propagator, propagator, "init")
+            else _ffi.NULL,
+            _lib.pyclingo_propagator_propagate
+            if _overwritten(Propagator, propagator, "propagate")
+            else _ffi.NULL,
+            _lib.pyclingo_propagator_undo
+            if _overwritten(Propagator, propagator, "undo")
+            else _ffi.NULL,
+            _lib.pyclingo_propagator_check
+            if _overwritten(Propagator, propagator, "check")
+            else _ffi.NULL,
+            _lib.pyclingo_propagator_decide
+            if _overwritten(Propagator, propagator, "decide")
+            else _ffi.NULL,
+        ),
+    )
+    c_data = _ffi.new_handle(_CBData(propagator, self._error))
+    self._mem.append(c_data)
+    _handle_error(
+        _lib.clingo_control_register_propagator(
+            self._rep, c_propagator, c_data, False
+        )
+    )
+
+
+
+def release_external(self, external: Union[Symbol, int]) ‑> None +
+
+

Release an external atom represented by the given symbol or program +literal.

+

This function causes the corresponding atom to become permanently false +if there is no definition for the atom in the program. Otherwise, the +function has no effect.

+

Parameters

+
+
external
+
The symbolic atom or program atom to release.
+
+

Notes

+

If the program literal is negative, the corresponding atom is released.

+

Examples

+

The following example shows the effect of assigning and releasing and external +atom.

+
>>> from clingo.symbol import Function
+>>> from clingo.control import Control
+>>>
+>>> ctl = Control()
+>>> ctl.add("base", [], "a. #external b.")
+>>> ctl.ground([("base", [])])
+>>> ctl.assign_external(Function("b"), True)
+>>> print(ctl.solve(on_model=print))
+b a
+SAT
+>>> ctl.release_external(Function("b"))
+>>> print(ctl.solve(on_model=print))
+a
+SAT
+
+
+ +Expand source code + +
def release_external(self, external: Union[Symbol, int]) -> None:
+    """
+    Release an external atom represented by the given symbol or program
+    literal.
+
+    This function causes the corresponding atom to become permanently false
+    if there is no definition for the atom in the program. Otherwise, the
+    function has no effect.
+
+    Parameters
+    ----------
+    external
+        The symbolic atom or program atom to release.
+
+    Notes
+    -----
+    If the program literal is negative, the corresponding atom is released.
+
+    Examples
+    --------
+    The following example shows the effect of assigning and releasing and external
+    atom.
+
+        >>> from clingo.symbol import Function
+        >>> from clingo.control import Control
+        >>>
+        >>> ctl = Control()
+        >>> ctl.add("base", [], "a. #external b.")
+        >>> ctl.ground([("base", [])])
+        >>> ctl.assign_external(Function("b"), True)
+        >>> print(ctl.solve(on_model=print))
+        b a
+        SAT
+        >>> ctl.release_external(Function("b"))
+        >>> print(ctl.solve(on_model=print))
+        a
+        SAT
+    """
+    _handle_error(
+        _lib.clingo_control_release_external(
+            self._rep, self._program_atom(external)
+        )
+    )
+
+
+
+def solve(self, assumptions: Sequence[Union[Tuple[Symbol, bool], int]] = (), on_model: Optional[Callable[[Model], Optional[bool]]] = None, on_unsat: Optional[Callable[[Sequence[int]], None]] = None, on_statistics: Optional[Callable[[StatisticsMapStatisticsMap], None]] = None, on_finish: Optional[Callable[[SolveResult], None]] = None, on_core: Optional[Callable[[Sequence[int]], None]] = None, yield_: bool = False, async_: bool = False) ‑> Union[SolveHandleSolveResult] +
+
+

Starts a search.

+

Parameters

+
+
assumptions
+
List of (atom, boolean) tuples or program literals (see +SymbolicAtom.literal) that serve as +assumptions for the solve call, e.g., solving under assumptions +[(Function("a"), True)] only admits answer sets that contain atom a.
+
on_model
+
Optional callback for intercepting models. +A Model object is passed to the callback. The +search can be interruped from the model callback by returning +False.
+
on_unsat
+
Optional callback to intercept lower bounds during optimization.
+
on_statistics
+
Optional callback to update statistics. +The step and accumulated statistics are passed as arguments.
+
on_finish
+
Optional callback called once search has finished. +A SolveResult also indicating whether the solve +call has been intrrupted is passed to the callback.
+
on_core
+
Optional callback called with the assumptions that made a problem +unsatisfiable.
+
yield_
+
The resulting SolveHandle is iterable yielding +Model objects.
+
async_
+
The solve call and the method SolveHandle.resume() +of the returned handle are non-blocking.
+
+

Returns

+

The return value depends on the parameters. If either yield_ or +async_ is true, then a handle is returned. Otherwise, a +SolveResult is returned.

+

See Also

+

clingo.solving

+

Notes

+

If neither yield_ nor async_ is set, the function returns a +SolveResult right away.

+

In gringo or in clingo with lparse or text output enabled, this +function just grounds and returns a SolveResult where +SolveResult.unknown is true.

+

If this function is used in embedded Python code, you might want to start +clingo using the --outf=3 option to disable all output from clingo.

+

Asynchronous solving is only available in clingo with thread support +enabled. Furthermore, the on_model and on_finish callbacks are called +from another thread. To ensure that the methods can be called, make +sure to not use any functions that block Python's GIL indefinitely.

+

This function as well as blocking functions on the +SolveHandle release the GIL but are not thread-safe.

+
+ +Expand source code + +
def solve(
+    self,
+    assumptions: Sequence[Union[Tuple[Symbol, bool], int]] = (),
+    on_model: Optional[Callable[[Model], Optional[bool]]] = None,
+    on_unsat: Optional[Callable[[Sequence[int]], None]] = None,
+    on_statistics: Optional[Callable[[StatisticsMap, StatisticsMap], None]] = None,
+    on_finish: Optional[Callable[[SolveResult], None]] = None,
+    on_core: Optional[Callable[[Sequence[int]], None]] = None,
+    yield_: bool = False,
+    async_: bool = False,
+) -> Union[SolveHandle, SolveResult]:
+    """
+    Starts a search.
+
+    Parameters
+    ----------
+    assumptions
+        List of (atom, boolean) tuples or program literals (see
+        `clingo.symbolic_atoms.SymbolicAtom.literal`) that serve as
+        assumptions for the solve call, e.g., solving under assumptions
+        `[(Function("a"), True)]` only admits answer sets that contain atom `a`.
+    on_model
+        Optional callback for intercepting models.
+        A `clingo.solving.Model` object is passed to the callback. The
+        search can be interruped from the model callback by returning
+        False.
+    on_unsat
+        Optional callback to intercept lower bounds during optimization.
+    on_statistics
+        Optional callback to update statistics.
+        The step and accumulated statistics are passed as arguments.
+    on_finish
+        Optional callback called once search has finished.
+        A `clingo.solving.SolveResult` also indicating whether the solve
+        call has been intrrupted is passed to the callback.
+    on_core
+        Optional callback called with the assumptions that made a problem
+        unsatisfiable.
+    yield_
+        The resulting `clingo.solving.SolveHandle` is iterable yielding
+        `clingo.solving.Model` objects.
+    async_
+        The solve call and the method `clingo.solving.SolveHandle.resume`
+        of the returned handle are non-blocking.
+
+    Returns
+    -------
+    The return value depends on the parameters. If either `yield_` or
+    `async_` is true, then a handle is returned. Otherwise, a
+    `clingo.solving.SolveResult` is returned.
+
+    See Also
+    --------
+    clingo.solving
+
+    Notes
+    -----
+    If neither `yield_` nor `async_` is set, the function returns a
+    `clingo.solving.SolveResult` right away.
+
+    In gringo or in clingo with lparse or text output enabled, this
+    function just grounds and returns a `clingo.solving.SolveResult` where
+    `clingo.solving.SolveResult.unknown` is true.
+
+    If this function is used in embedded Python code, you might want to start
+    clingo using the `--outf=3` option to disable all output from clingo.
+
+    Asynchronous solving is only available in clingo with thread support
+    enabled. Furthermore, the on_model and on_finish callbacks are called
+    from another thread. To ensure that the methods can be called, make
+    sure to not use any functions that block Python's GIL indefinitely.
+
+    This function as well as blocking functions on the
+    `clingo.solving.SolveHandle` release the GIL but are not thread-safe.
+    """
+    # pylint: disable=protected-access,dangerous-default-value
+    self._error.clear()
+    handler = _SolveEventHandler(on_model, on_unsat, on_statistics, on_finish)
+    data = _CBData(handler, self._error)
+    self._handler = _ffi.new_handle(data)
+
+    p_ass = _ffi.NULL
+    if assumptions:
+        atoms = None
+        p_ass = _ffi.new("clingo_literal_t[]", len(assumptions))
+        for i, lit in enumerate(assumptions):
+            if isinstance(lit, int):
+                p_ass[i] = lit
+            else:
+                if atoms is None:
+                    atoms = self.symbolic_atoms
+                atom = self.symbolic_atoms[lit[0]]
+                slit = -1 if atom is None else atom.literal
+                p_ass[i] = slit if lit[1] else -slit
+
+    mode = 0
+    if yield_:
+        mode |= _lib.clingo_solve_mode_yield
+    if async_:
+        mode |= _lib.clingo_solve_mode_async
+
+    handle = SolveHandle(
+        _c_call(
+            "clingo_solve_handle_t*",
+            _lib.clingo_control_solve,
+            self._rep,
+            mode,
+            p_ass,
+            len(assumptions),
+            _lib.pyclingo_solve_event_callback,
+            self._handler,
+            handler=data,
+        ),
+        data,
+    )
+
+    if not yield_ and not async_:
+        with handle:
+            ret = handle.get()
+            if on_core is not None and ret.unsatisfiable:
+                on_core(handle.core())
+            return ret
+    return handle
+
+
+
+
+
+
+
+ +
+ + + \ No newline at end of file diff --git a/clingo/python-api/5.7/clingo/core.html b/clingo/python-api/5.7/clingo/core.html new file mode 100644 index 0000000..b3cbc26 --- /dev/null +++ b/clingo/python-api/5.7/clingo/core.html @@ -0,0 +1,430 @@ + + + + + + +clingo.core API documentation + + + + + + + + + + + +
+
+
+

Module clingo.core

+
+
+

Core functionality used throught the clingo package.

+
+ +Expand source code + +
"""
+Core functionality used throught the clingo package.
+"""
+
+from typing import Callable, Tuple
+from enum import Enum
+
+from ._internal import _cb_error_panic, _ffi, _lib, _to_str
+
+__all__ = ["Logger", "MessageCode", "OrderedEnum", "TruthValue", "version"]
+
+
+class OrderedEnum(Enum):
+    """
+    Enumeration of orderable elements.
+    """
+
+    def __ge__(self, other):
+        if self.__class__ is other.__class__:
+            return self.value >= other.value
+        return NotImplemented
+
+    def __gt__(self, other):
+        if self.__class__ is other.__class__:
+            return self.value > other.value
+        return NotImplemented
+
+    def __le__(self, other):
+        if self.__class__ is other.__class__:
+            return self.value <= other.value
+        return NotImplemented
+
+    def __lt__(self, other):
+        if self.__class__ is other.__class__:
+            return self.value < other.value
+        return NotImplemented
+
+
+def version() -> Tuple[int, int, int]:
+    """
+    Clingo's version as a tuple `(major, minor, revision)`.
+    """
+    p_major = _ffi.new("int*")
+    p_minor = _ffi.new("int*")
+    p_revision = _ffi.new("int*")
+    _lib.clingo_version(p_major, p_minor, p_revision)
+    return p_major[0], p_minor[0], p_revision[0]
+
+
+class MessageCode(OrderedEnum):
+    """
+    Enumeration of messages codes.
+    """
+
+    AtomUndefined = _lib.clingo_warning_atom_undefined
+    """
+    Informs about an undefined atom in program.
+    """
+    FileIncluded = _lib.clingo_warning_file_included
+    """
+    Indicates that the same file was included multiple times.
+    """
+    GlobalVariable = _lib.clingo_warning_global_variable
+    """
+    Informs about a global variable in a tuple of an aggregate element.
+    """
+    OperationUndefined = _lib.clingo_warning_operation_undefined
+    """
+    Inform about an undefined arithmetic operation or unsupported weight of an
+    aggregate.
+    """
+    Other = _lib.clingo_warning_other
+    """
+    Reports other kinds of messages.
+    """
+    RuntimeError = _lib.clingo_warning_runtime_error
+    """
+    To report multiple errors; a corresponding runtime error is raised later.
+    """
+    VariableUnbounded = _lib.clingo_warning_variable_unbounded
+    """
+    Informs about a CSP variable with an unbounded domain.
+    """
+
+
+Logger = Callable[[MessageCode, str], None]
+
+
+@_ffi.def_extern(onerror=_cb_error_panic, name="pyclingo_logger_callback")
+def _pyclingo_logger_callback(code, message, data):
+    """
+    Low-level logger callback.
+    """
+    handler = _ffi.from_handle(data)
+    handler(MessageCode(code), _to_str(message))
+
+
+class TruthValue(OrderedEnum):
+    """
+    Enumeration of the different truth values.
+    """
+
+    False_ = _lib.clingo_external_type_false
+    """
+    Represents truth value true.
+    """
+    Free = _lib.clingo_external_type_free
+    """
+    Represents absence of a truth value.
+    """
+    True_ = _lib.clingo_external_type_true
+    """
+    Represents truth value true.
+    """
+    Release = _lib.clingo_external_type_release
+    """
+    Indicates that an atom is to be released.
+    """
+
+
+
+
+
+
+
+

Functions

+
+
+def version() ‑> Tuple[int, int, int] +
+
+

Clingo's version as a tuple (major, minor, revision).

+
+ +Expand source code + +
def version() -> Tuple[int, int, int]:
+    """
+    Clingo's version as a tuple `(major, minor, revision)`.
+    """
+    p_major = _ffi.new("int*")
+    p_minor = _ffi.new("int*")
+    p_revision = _ffi.new("int*")
+    _lib.clingo_version(p_major, p_minor, p_revision)
+    return p_major[0], p_minor[0], p_revision[0]
+
+
+
+
+
+

Classes

+
+
+class MessageCode +(value, names=None, *, module=None, qualname=None, type=None, start=1) +
+
+

Enumeration of messages codes.

+
+ +Expand source code + +
class MessageCode(OrderedEnum):
+    """
+    Enumeration of messages codes.
+    """
+
+    AtomUndefined = _lib.clingo_warning_atom_undefined
+    """
+    Informs about an undefined atom in program.
+    """
+    FileIncluded = _lib.clingo_warning_file_included
+    """
+    Indicates that the same file was included multiple times.
+    """
+    GlobalVariable = _lib.clingo_warning_global_variable
+    """
+    Informs about a global variable in a tuple of an aggregate element.
+    """
+    OperationUndefined = _lib.clingo_warning_operation_undefined
+    """
+    Inform about an undefined arithmetic operation or unsupported weight of an
+    aggregate.
+    """
+    Other = _lib.clingo_warning_other
+    """
+    Reports other kinds of messages.
+    """
+    RuntimeError = _lib.clingo_warning_runtime_error
+    """
+    To report multiple errors; a corresponding runtime error is raised later.
+    """
+    VariableUnbounded = _lib.clingo_warning_variable_unbounded
+    """
+    Informs about a CSP variable with an unbounded domain.
+    """
+
+

Ancestors

+ +

Class variables

+
+
var AtomUndefined
+
+

Informs about an undefined atom in program.

+
+
var FileIncluded
+
+

Indicates that the same file was included multiple times.

+
+
var GlobalVariable
+
+

Informs about a global variable in a tuple of an aggregate element.

+
+
var OperationUndefined
+
+

Inform about an undefined arithmetic operation or unsupported weight of an +aggregate.

+
+
var Other
+
+

Reports other kinds of messages.

+
+
var RuntimeError
+
+

To report multiple errors; a corresponding runtime error is raised later.

+
+
var VariableUnbounded
+
+

Informs about a CSP variable with an unbounded domain.

+
+
+
+
+class OrderedEnum +(value, names=None, *, module=None, qualname=None, type=None, start=1) +
+
+

Enumeration of orderable elements.

+
+ +Expand source code + +
class OrderedEnum(Enum):
+    """
+    Enumeration of orderable elements.
+    """
+
+    def __ge__(self, other):
+        if self.__class__ is other.__class__:
+            return self.value >= other.value
+        return NotImplemented
+
+    def __gt__(self, other):
+        if self.__class__ is other.__class__:
+            return self.value > other.value
+        return NotImplemented
+
+    def __le__(self, other):
+        if self.__class__ is other.__class__:
+            return self.value <= other.value
+        return NotImplemented
+
+    def __lt__(self, other):
+        if self.__class__ is other.__class__:
+            return self.value < other.value
+        return NotImplemented
+
+

Ancestors

+
    +
  • enum.Enum
  • +
+

Subclasses

+ +
+
+class TruthValue +(value, names=None, *, module=None, qualname=None, type=None, start=1) +
+
+

Enumeration of the different truth values.

+
+ +Expand source code + +
class TruthValue(OrderedEnum):
+    """
+    Enumeration of the different truth values.
+    """
+
+    False_ = _lib.clingo_external_type_false
+    """
+    Represents truth value true.
+    """
+    Free = _lib.clingo_external_type_free
+    """
+    Represents absence of a truth value.
+    """
+    True_ = _lib.clingo_external_type_true
+    """
+    Represents truth value true.
+    """
+    Release = _lib.clingo_external_type_release
+    """
+    Indicates that an atom is to be released.
+    """
+
+

Ancestors

+ +

Class variables

+
+
var False_
+
+

Represents truth value true.

+
+
var Free
+
+

Represents absence of a truth value.

+
+
var Release
+
+

Indicates that an atom is to be released.

+
+
var True_
+
+

Represents truth value true.

+
+
+
+
+
+
+ +
+ + + \ No newline at end of file diff --git a/clingo/python-api/5.7/clingo/index.html b/clingo/python-api/5.7/clingo/index.html new file mode 100644 index 0000000..c9027a2 --- /dev/null +++ b/clingo/python-api/5.7/clingo/index.html @@ -0,0 +1,340 @@ + + + + + + +clingo API documentation + + + + + + + + + + + +
+
+
+

Package clingo

+
+
+

Module providing functions and classes to control the grounding and solving +process.

+

Next follow some concepts used throughout the modules of the clingo package.

+

Terms

+

Terms without variables and interpreted functions are called symbols in the +following. They are wrapped in the Symbol class.

+

Symbolic Atoms And Literals

+

Symbolic atoms without variables and interpreted functions, which appear in +ground logic programs, are captured using the Symbol class. +They must be of type SymbolType.Function. Furthermore, some +functions accept symbolic literals, which are represented as pairs of symbols +and Booleans. The Boolean stands for the sign of the literal (True for +positive and False for negative).

+

Program Literals

+

When passing a ground logic program to a solver, clingo does not use a human +readable textual representation but the aspif format. The literals in this +format are called program literals. They are non-zero integers associated +with symbolic atoms, theory atoms, and also without any association if they are +used to translate complex language constructs not directly representable in +aspif format. The sign of a program literal is used to represent default +negation. Symbolic atoms can be mapped to program literals using the +clingo.symbolic_atoms module and theory atoms using the clingo.theory_atoms +module. Note that symbolic and theory atoms can share the same program +literals. Finally, the clingo.backend module can also be used to introduce +fresh symbolic atoms and program literals.

+

Solver Literals

+

Before solving, programs in aspif format are translated to an internal solver +representation, where program literals are again mapped to non-zero integers, +so called solver literals. The PropagateInit.solver_literal() +function can be used to map program literals to solver literals. Note that +different program literals can share the same solver literal.

+

Embedded Python Code

+

If the clingo application is build with Python support, clingo will also be +able to execute Python code embedded in logic programs. Functions defined in a +Python script block are callable during the instantiation process using +@-syntax. The default grounding/solving process can be customized if a main +function is provided.

+

Examples

+

The first example shows how to use the clingo module from Python.

+
>>> from clingo.symbol import Number
+>>> from clingo.control import Control
+>>>
+>>> class Context:
+...     def inc(self, x):
+...         return Number(x.number + 1)
+...     def seq(self, x, y):
+...         return [x, y]
+...
+>>> def on_model(m):
+...     print (m)
+...
+>>> ctl = Control()
+>>> ctl.add("base", [], """\
+... p(@inc(10)).
+... q(@seq(1,2)).
+... """)
+>>> ctl.ground([("base", [])], context=Context())
+>>> print(ctl.solve(on_model=on_model))
+p(11) q(1) q(2)
+SAT
+
+

The second example shows how to use Python code from clingo.

+
#script (python)
+
+from clingo.symbol import Number
+
+class Context:
+    def inc(self, x):
+        return Number(x.number + 1)
+
+    def seq(self, x, y):
+        return [x, y]
+
+def main(prg):
+    prg.ground([("base", [])], context=Context())
+    prg.solve()
+
+#end.
+
+p(@inc(10)).
+q(@seq(1,2)).
+
+
+ +Expand source code + +
'''
+Module providing functions and classes to control the grounding and solving
+process.
+
+Next follow some concepts used throughout the modules of the clingo package.
+
+Terms
+-----
+Terms without variables and interpreted functions are called symbols in the
+following. They are wrapped in the `clingo.symbol.Symbol` class.
+
+Symbolic Atoms and Literals
+---------------------------
+*Symbolic atoms* without variables and interpreted functions, which appear in
+ground logic programs, are captured using the `clingo.symbol.Symbol` class.
+They must be of type `clingo.symbol.SymbolType.Function`. Furthermore, some
+functions accept *symbolic literals*, which are represented as pairs of symbols
+and Booleans. The Boolean stands for the sign of the literal (`True` for
+positive and `False` for negative).
+
+Program Literals
+----------------
+When passing a ground logic program to a solver, clingo does not use a human
+readable textual representation but the aspif format. The literals in this
+format are called *program literals*. They are non-zero integers associated
+with symbolic atoms, theory atoms, and also without any association if they are
+used to translate complex language constructs not directly representable in
+aspif format. The sign of a program literal is used to represent default
+negation. Symbolic atoms can be mapped to program literals using the
+`clingo.symbolic_atoms` module and theory atoms using the `clingo.theory_atoms`
+module. Note that symbolic and theory atoms can share the same program
+literals. Finally, the `clingo.backend` module can also be used to introduce
+fresh symbolic atoms and program literals.
+
+Solver Literals
+---------------
+Before solving, programs in aspif format are translated to an internal solver
+representation, where program literals are again mapped to non-zero integers,
+so called *solver literals*. The `clingo.propagator.PropagateInit.solver_literal`
+function can be used to map program literals to solver literals. Note that
+different program literals can share the same solver literal.
+
+Embedded Python Code
+--------------------
+If the clingo application is build with Python support, clingo will also be
+able to execute Python code embedded in logic programs. Functions defined in a
+Python script block are callable during the instantiation process using
+`@`-syntax. The default grounding/solving process can be customized if a main
+function is provided.
+
+## Examples
+
+The first example shows how to use the clingo module from Python.
+
+    >>> from clingo.symbol import Number
+    >>> from clingo.control import Control
+    >>>
+    >>> class Context:
+    ...     def inc(self, x):
+    ...         return Number(x.number + 1)
+    ...     def seq(self, x, y):
+    ...         return [x, y]
+    ...
+    >>> def on_model(m):
+    ...     print (m)
+    ...
+    >>> ctl = Control()
+    >>> ctl.add("base", [], """\\
+    ... p(@inc(10)).
+    ... q(@seq(1,2)).
+    ... """)
+    >>> ctl.ground([("base", [])], context=Context())
+    >>> print(ctl.solve(on_model=on_model))
+    p(11) q(1) q(2)
+    SAT
+
+The second example shows how to use Python code from clingo.
+
+    #script (python)
+
+    from clingo.symbol import Number
+
+    class Context:
+        def inc(self, x):
+            return Number(x.number + 1)
+
+        def seq(self, x, y):
+            return [x, y]
+
+    def main(prg):
+        prg.ground([("base", [])], context=Context())
+        prg.solve()
+
+    #end.
+
+    p(@inc(10)).
+    q(@seq(1,2)).
+'''
+
+from .core import *
+from .symbol import *
+from .symbolic_atoms import *
+from .theory_atoms import *
+from .solving import *
+from .propagator import *
+from .backend import *
+from .configuration import *
+from .statistics import *
+from .control import *
+from .application import *
+
+__version__ = ".".join(map(str, version()))
+
+
+
+

Sub-modules

+
+
clingo.application
+
+

Functions and classes to implement applications based on clingo …

+
+
clingo.ast
+
+

Module to work with clingo's non-ground program representation …

+
+
clingo.backend
+
+

Functions and classes to observe or add ground statements …

+
+
clingo.configuration
+
+

Functions and classes related to configuration …

+
+
clingo.control
+
+

This module contains the Control class responsible for +controling grounding and solving …

+
+
clingo.core
+
+

Core functionality used throught the clingo package.

+
+
clingo.propagator
+
+

Functions and classes to implement custom propagators …

+
+
clingo.script
+
+

This module contains functions to add custom scripts, which can be embedded +into logic programs …

+
+
clingo.solving
+
+

Functions and classes related to solving …

+
+
clingo.statistics
+
+

Functions and classes related to statistics …

+
+
clingo.symbol
+
+

Functions and classes for symbol manipulation …

+
+
clingo.symbolic_atoms
+
+

Functions and classes to work with symbolic atoms …

+
+
clingo.theory
+
+

This module defines the Theory class for using a [CFFI] based module with +clingo's Python package …

+
+
clingo.theory_atoms
+
+

Functions and classes to work with theory atoms …

+
+
clingo.util
+
+

Utility functions and classes.

+
+
+
+
+
+
+
+
+
+
+ +
+ + + \ No newline at end of file diff --git a/clingo/python-api/5.7/clingo/propagator.html b/clingo/python-api/5.7/clingo/propagator.html new file mode 100644 index 0000000..4bc5f8a --- /dev/null +++ b/clingo/python-api/5.7/clingo/propagator.html @@ -0,0 +1,3549 @@ + + + + + + +clingo.propagator API documentation + + + + + + + + + + + +
+
+
+

Module clingo.propagator

+
+
+

Functions and classes to implement custom propagators.

+
>>> from clingo.symbol import Function
+>>> from clingo.propagator import Propagator
+>>> from clingo.control import Control
+>>>
+>>> class AIFFB(Propagator):
+...     # add watches for atoms `a` and `b`
+...     def init(self, init):
+...         # get program literals for atoms `a` and `b`
+...         plit_a = init.symbolic_atoms[Function("a")].literal
+...         plit_b = init.symbolic_atoms[Function("b")].literal
+...         # get solver literals for program literals `a` and `b`
+...         self.slit_a = init.solver_literal(plit_a)
+...         self.slit_b = init.solver_literal(plit_b)
+...         # add watches for solver literals `a` and `b`
+...         init.add_watch(self.slit_a)
+...         init.add_watch(self.slit_b)
+...     # propagate solver literals `a` and `b`
+...     def propagate(self, ctl, changes):
+...         # if `a` is true imply `b`
+...         if self.slit_a in changes:
+...             ctl.add_clause([-self.slit_a, self.slit_b])
+...         # if `b` is true imply `a`
+...         if self.slit_b in changes:
+...             ctl.add_clause([-self.slit_b, self.slit_a])
+...
+>>> ctl = Control(["0"])
+>>> ctl.register_propagator(AIFFB())
+>>> ctl.add("base", [], "1 { a; b }.")
+>>> ctl.ground([("base", [])])
+>>> print(ctl.solve(on_model=print))
+a b
+SAT
+
+
+ +Expand source code + +
"""
+Functions and classes to implement custom propagators.
+
+```python
+>>> from clingo.symbol import Function
+>>> from clingo.propagator import Propagator
+>>> from clingo.control import Control
+>>>
+>>> class AIFFB(Propagator):
+...     # add watches for atoms `a` and `b`
+...     def init(self, init):
+...         # get program literals for atoms `a` and `b`
+...         plit_a = init.symbolic_atoms[Function("a")].literal
+...         plit_b = init.symbolic_atoms[Function("b")].literal
+...         # get solver literals for program literals `a` and `b`
+...         self.slit_a = init.solver_literal(plit_a)
+...         self.slit_b = init.solver_literal(plit_b)
+...         # add watches for solver literals `a` and `b`
+...         init.add_watch(self.slit_a)
+...         init.add_watch(self.slit_b)
+...     # propagate solver literals `a` and `b`
+...     def propagate(self, ctl, changes):
+...         # if `a` is true imply `b`
+...         if self.slit_a in changes:
+...             ctl.add_clause([-self.slit_a, self.slit_b])
+...         # if `b` is true imply `a`
+...         if self.slit_b in changes:
+...             ctl.add_clause([-self.slit_b, self.slit_a])
+...
+>>> ctl = Control(["0"])
+>>> ctl.register_propagator(AIFFB())
+>>> ctl.add("base", [], "1 { a; b }.")
+>>> ctl.ground([("base", [])])
+>>> print(ctl.solve(on_model=print))
+a b
+SAT
+```
+"""
+
+from typing import Iterable, Iterator, Optional, Sequence, Tuple
+from abc import ABCMeta
+
+from ._internal import _cb_error_handler, _c_call, _ffi, _handle_error, _lib
+from .core import OrderedEnum
+from .util import Slice, SlicedSequence
+from .symbolic_atoms import SymbolicAtoms
+from .theory_atoms import TheoryAtom
+
+__all__ = [
+    "Assignment",
+    "PropagateControl",
+    "PropagateInit",
+    "Propagator",
+    "PropagatorCheckMode",
+    "PropagatorUndoMode",
+    "Trail",
+]
+
+
+class Trail(Sequence[int]):
+    """
+    Class to access literals assigned by the solver in chronological order.
+
+    Literals in the trail are ordered by decision levels, where the first
+    literal with a larger level than the previous literals is a decision; the
+    following literals with same level are implied by this decision literal.
+    Each decision level up to and including the current decision level has a
+    valid offset in the trail.
+    """
+
+    def __init__(self, rep):
+        self._rep = rep
+
+    def __len__(self):
+        return _c_call("uint32_t", _lib.clingo_assignment_trail_size, self._rep)
+
+    def __getitem__(self, slc):
+        if isinstance(slc, slice):
+            return SlicedSequence(self, Slice(slc))
+        if slc < 0:
+            slc += len(self)
+        if slc < 0 or slc >= len(self):
+            raise IndexError("invalid index")
+        return _c_call(
+            "clingo_literal_t", _lib.clingo_assignment_trail_at, self._rep, slc
+        )
+
+    def __iter__(self):
+        for i in range(len(self)):
+            yield _c_call(
+                "clingo_literal_t", _lib.clingo_assignment_trail_at, self._rep, i
+            )
+
+    def begin(self, level: int) -> int:
+        """
+        Returns the offset of the decision literal with the given decision
+        level in the trail.
+
+        Parameters
+        ----------
+        level
+            The decision level.
+        """
+        return _c_call("uint32_t", _lib.clingo_assignment_trail_begin, self._rep, level)
+
+    def end(self, level: int) -> int:
+        """
+        Returns the offset following the last literal with the given decision
+        literal in the trail.
+
+        Parameters
+        ----------
+        level
+            The decision level.
+        """
+        return _c_call("uint32_t", _lib.clingo_assignment_trail_end, self._rep, level)
+
+
+class Assignment(Sequence[int]):
+    """
+    Class to inspect the (parital) assignment of an associated solver.
+
+    Assigns truth values to solver literals.  Each solver literal is either
+    true, false, or undefined, represented by the Python constants `True`,
+    `False`, or `None`, respectively.
+
+    This class implements `Sequence[int]` to access the (positive)
+    literals in the assignment.
+    """
+
+    def __init__(self, rep):
+        self._rep = rep
+
+    def __len__(self):
+        return _lib.clingo_assignment_size(self._rep)
+
+    def __getitem__(self, slc):
+        if isinstance(slc, slice):
+            return SlicedSequence(self, Slice(slc))
+        if slc < 0:
+            slc += len(self)
+        if slc < 0 or slc >= len(self):
+            raise IndexError("invalid index")
+        return _c_call("clingo_literal_t", _lib.clingo_assignment_at, self._rep, slc)
+
+    def __iter__(self):
+        for i in range(len(self)):
+            yield _c_call("clingo_literal_t", _lib.clingo_assignment_at, self._rep, i)
+
+    def decision(self, level: int) -> int:
+        """
+        Return the decision literal of the given level.
+
+        Parameters
+        ----------
+        level
+            The decision level.
+        """
+        return _c_call(
+            "clingo_literal_t", _lib.clingo_assignment_decision, self._rep, level
+        )
+
+    def has_literal(self, literal: int) -> bool:
+        """
+        Determine if the given literal is valid in this solver.
+
+        Parameters
+        ----------
+        literal
+            The solver literal.
+        """
+        return _lib.clingo_assignment_has_literal(self._rep, literal)
+
+    def is_false(self, literal: int) -> bool:
+        """
+        Determine if the literal is false.
+
+        Parameters
+        ----------
+        literal
+            The solver literal.
+        """
+        return _c_call("bool", _lib.clingo_assignment_is_false, self._rep, literal)
+
+    def is_fixed(self, literal: int) -> bool:
+        """
+        Determine if the literal is assigned on the top level.
+
+        Parameters
+        ----------
+        literal
+            The solver literal.
+        """
+        return _c_call("bool", _lib.clingo_assignment_is_fixed, self._rep, literal)
+
+    def is_true(self, literal: int) -> bool:
+        """
+        Determine if the literal is true.
+
+        Parameters
+        ----------
+        literal
+            The solver literal.
+        """
+        return _c_call("bool", _lib.clingo_assignment_is_true, self._rep, literal)
+
+    def is_free(self, literal: int) -> bool:
+        """
+        Determine if the literal is free.
+
+        Parameters
+        ----------
+        literal
+            The solver literal.
+        """
+        value = _c_call(
+            "clingo_truth_value_t",
+            _lib.clingo_assignment_truth_value,
+            self._rep,
+            literal,
+        )
+        return value == _lib.clingo_truth_value_free
+
+    def level(self, literal: int) -> int:
+        """
+        The decision level of the given literal.
+
+        Parameters
+        ----------
+        literal
+            The solver literal.
+
+        Notes
+        -----
+        Note that the returned value is only meaningful if the literal is
+        assigned - i.e., `value(lit) is not None`.
+        """
+        return _c_call("uint32_t", _lib.clingo_assignment_level, self._rep, literal)
+
+    def value(self, literal) -> Optional[bool]:
+        """
+        Get the truth value of the given literal or `None` if it has none.
+
+        Parameters
+        ----------
+        literal
+            The solver literal.
+        """
+        value = _c_call(
+            "clingo_truth_value_t",
+            _lib.clingo_assignment_truth_value,
+            self._rep,
+            literal,
+        )
+        if value == _lib.clingo_truth_value_true:
+            return True
+        if value == _lib.clingo_truth_value_false:
+            return False
+        assert value == _lib.clingo_truth_value_free
+        return None
+
+    @property
+    def decision_level(self) -> int:
+        """
+        The current decision level.
+        """
+        return _lib.clingo_assignment_decision_level(self._rep)
+
+    @property
+    def has_conflict(self) -> bool:
+        """
+        True if the assignment is conflicting.
+        """
+        return _lib.clingo_assignment_has_conflict(self._rep)
+
+    @property
+    def is_total(self) -> bool:
+        """
+        Whether the assignment is total.
+        """
+        return _lib.clingo_assignment_is_total(self._rep)
+
+    @property
+    def root_level(self) -> int:
+        """
+        The current root level.
+        """
+        return _lib.clingo_assignment_root_level(self._rep)
+
+    @property
+    def trail(self) -> Trail:
+        """
+        The trail of assigned literals.
+        """
+        return Trail(self._rep)
+
+
+class PropagatorCheckMode(OrderedEnum):
+    """
+    Enumeration of supported check modes for propagators.
+
+    Note that total checks are subject to the lock when a model is found. This
+    means that information from previously found models can be used to discard
+    assignments in check calls.
+    """
+
+    Both = _lib.clingo_propagator_check_mode_both
+    """
+    Call `Propagator.check` on propagation fixpoints and total assignments.
+    """
+    Fixpoint = _lib.clingo_propagator_check_mode_fixpoint
+    """
+    Call `Propagator.check` on propagation fixpoints.
+    """
+    Off = _lib.clingo_propagator_check_mode_none
+    """
+    Do not call `Propagator.check` at all.
+    """
+    Total = _lib.clingo_propagator_check_mode_total
+    """
+    Call `Propagator.check` on total assignments.
+    """
+
+
+class PropagatorUndoMode(OrderedEnum):
+    """
+    Enumeration of supported check modes for propagators.
+
+    Note that total checks are subject to the lock when a model is found. This
+    means that information from previously found models can be used to discard
+    assignments in check calls.
+    """
+
+    Default = _lib.clingo_propagator_undo_mode_default
+    """
+    Call `Propagator.undo` for decision levels with non-emty changes.
+    """
+    Always = _lib.clingo_propagator_undo_mode_always
+    """
+    Also call `Propagator.undo` when check has been called.
+    """
+
+
+class PropagateInit:
+    """
+    Object that is used to initialize a propagator before each solving step.
+    """
+
+    def __init__(self, rep):
+        self._rep = rep
+
+    def add_clause(self, clause: Sequence[int]) -> bool:
+        """
+        Statically adds the given clause to the problem.
+
+        Parameters
+        ----------
+        clause
+            The clause over solver literals to add.
+
+        Returns
+        -------
+        Returns false if the program becomes unsatisfiable.
+
+        Notes
+        -----
+        If this function returns false, initialization should be stopped and no
+        further functions of the `PropagateInit` and related objects should be
+        called.
+        """
+        return _c_call(
+            "bool",
+            _lib.clingo_propagate_init_add_clause,
+            self._rep,
+            clause,
+            len(clause),
+        )
+
+    def add_literal(self, freeze: bool = True) -> int:
+        """
+        Statically adds a literal to the solver.
+
+        To be able to use the variable in clauses during propagation or add
+        watches to it, it has to be frozen. Otherwise, it might be removed
+        during preprocessing.
+
+        Parameters
+        ----------
+        freeze
+            Whether to freeze the variable.
+
+        Returns
+        -------
+        Returns the added literal.
+
+        Notes
+        -----
+        If literals are added to the solver, subsequent calls to `add_clause` and
+        `propagate` are expensive. It is best to add literals in batches.
+        """
+        return _c_call(
+            "clingo_literal_t",
+            _lib.clingo_propagate_init_add_literal,
+            self._rep,
+            freeze,
+        )
+
+    def add_minimize(self, literal: int, weight: int, priority: int = 0) -> None:
+        """
+        Extends the solver's minimize constraint with the given weighted
+        literal.
+
+        Parameters
+        ----------
+        literal
+            The literal to add.
+        weight
+            The weight of the literal.
+        priority
+            The priority of the literal.
+        """
+        _handle_error(
+            _lib.clingo_propagate_init_add_minimize(
+                self._rep, literal, weight, priority
+            )
+        )
+
+    def add_watch(self, literal: int, thread_id: Optional[int] = None) -> None:
+        """
+        Add a watch for the solver literal in the given phase.
+
+        Parameters
+        ----------
+        literal
+            The solver literal to watch.
+        thread_id
+            The id of the thread to watch the literal. If the is `None` then
+            all active threads will watch the literal.
+        """
+        if thread_id is None:
+            _handle_error(_lib.clingo_propagate_init_add_watch(self._rep, literal))
+        else:
+            _handle_error(
+                _lib.clingo_propagate_init_add_watch_to_thread(
+                    self._rep, literal, thread_id
+                )
+            )
+
+    def remove_watch(self, literal: int, thread_id: Optional[int] = None) -> None:
+        """
+        Remove the watch for the solver literal in the given phase.
+
+        Parameters
+        ----------
+        literal
+            The solver literal to remove the watch from.
+        thread_id
+            The id of the thread from which to remove the watch. If the is `None`, then
+            the watch is removed from all active threads.
+        """
+        if thread_id is None:
+            _handle_error(_lib.clingo_propagate_init_remove_watch(self._rep, literal))
+        else:
+            _handle_error(
+                _lib.clingo_propagate_init_remove_watch_from_thread(
+                    self._rep, literal, thread_id
+                )
+            )
+
+    def freeze_literal(self, literal: int) -> None:
+        """
+        Freeze the given solver literal.
+
+        Any solver literal that is not frozen is subject to simplification and
+        might be removed in a preprocessing step after propagator
+        initialization. A propagator should freeze all literals over which it
+        might add clauses during propagation. Note that any watched literal is
+        automatically frozen and that it does not matter which phase of the
+        literal is frozen.
+
+        Parameters
+        ----------
+        literal
+            The solver literal to freeze.
+        """
+        _handle_error(_lib.clingo_propagate_init_freeze_literal(self._rep, literal))
+
+    def add_weight_constraint(
+        self,
+        literal: int,
+        literals: Sequence[Tuple[int, int]],
+        bound: int,
+        type_: int = 0,
+        compare_equal: bool = False,
+    ) -> bool:
+        """
+        Statically adds a constraint of form
+
+            literal <=> { l=w | (l, w) in literals } >= bound
+
+        to the solver.
+
+        - If `type_ < 0`, then `<=>` is a left implication.
+        - If `type_ > 0`, then `<=>` is a right implication.
+        - Otherwise, `<=>` is an equivalence.
+
+        Parameters
+        ----------
+        literal
+            The literal associated with the constraint.
+        literals
+            The weighted literals of the constraint.
+        bound
+            The bound of the constraint.
+        type_
+            Add a weight constraint of the given type_.
+        compare_equal
+            A Boolean indicating whether to compare equal or less than equal.
+
+        Returns
+        -------
+        Returns false if the program became unsatisfiable.
+
+        Notes
+        -----
+        If this function returns false, initialization should be stopped and no further
+        functions of the `PropagateInit` and related objects should be called.
+        """
+        return _c_call(
+            "bool",
+            _lib.clingo_propagate_init_add_weight_constraint,
+            self._rep,
+            literal,
+            literals,
+            len(literals),
+            bound,
+            type_,
+            compare_equal,
+        )
+
+    def propagate(self) -> bool:
+        """
+        Propagates consequences of the underlying problem excluding registered
+        propagators.
+
+        Returns
+        -------
+        Returns false if the program becomes unsatisfiable.
+
+        Notes
+        -----
+        This function has no effect if SAT-preprocessing is enabled.
+
+        If this function returns false, initialization should be stopped and no
+        further functions of the `PropagateInit` and related objects should be
+        called.
+        """
+        return _c_call("bool", _lib.clingo_propagate_init_propagate, self._rep)
+
+    def solver_literal(self, literal: int) -> int:
+        """
+        Maps the given program literal or condition id to its solver literal.
+
+        Parameters
+        ----------
+        literal
+            A program literal or condition id.
+
+        Returns
+        -------
+        A solver literal.
+        """
+        return _c_call(
+            "clingo_literal_t",
+            _lib.clingo_propagate_init_solver_literal,
+            self._rep,
+            literal,
+        )
+
+    @property
+    def assignment(self) -> Assignment:
+        """
+        `Assignment` object capturing the top level assignment.
+        """
+        return Assignment(_lib.clingo_propagate_init_assignment(self._rep))
+
+    @property
+    def check_mode(self) -> PropagatorCheckMode:
+        """
+        `PropagatorCheckMode` controlling when to call `Propagator.check`.
+        """
+        return PropagatorCheckMode(_lib.clingo_propagate_init_get_check_mode(self._rep))
+
+    @check_mode.setter
+    def check_mode(self, mode: PropagatorCheckMode) -> None:
+        _lib.clingo_propagate_init_set_check_mode(self._rep, mode.value)
+
+    @property
+    def undo_mode(self) -> PropagatorUndoMode:
+        """
+        `PropagatorUndoMode` controlling when to call `Propagator.undo`.
+        """
+        return PropagatorUndoMode(_lib.clingo_propagate_init_get_undo_mode(self._rep))
+
+    @undo_mode.setter
+    def undo_mode(self, mode: PropagatorUndoMode) -> None:
+        _lib.clingo_propagate_init_set_undo_mode(self._rep, mode.value)
+
+    @property
+    def number_of_threads(self) -> int:
+        """
+        The number of solver threads used in the corresponding solve call.
+        """
+        return _lib.clingo_propagate_init_number_of_threads(self._rep)
+
+    @property
+    def symbolic_atoms(self) -> SymbolicAtoms:
+        """
+        The symbolic atoms captured by a `SymbolicAtoms` object.
+        """
+        atoms = _c_call(
+            "clingo_symbolic_atoms_t*",
+            _lib.clingo_propagate_init_symbolic_atoms,
+            self._rep,
+        )
+        return SymbolicAtoms(atoms)
+
+    @property
+    def theory_atoms(self) -> Iterator[TheoryAtom]:
+        """
+        An iterator over all theory atoms.
+        """
+        atoms = _c_call(
+            "clingo_theory_atoms_t*", _lib.clingo_propagate_init_theory_atoms, self._rep
+        )
+        size = _c_call("size_t", _lib.clingo_theory_atoms_size, atoms)
+
+        for idx in range(size):
+            yield TheoryAtom(atoms, idx)
+
+
+class PropagateControl:
+    """
+    This object can be used to add clauses and to propagate them.
+    """
+
+    def __init__(self, rep):
+        self._rep = rep
+
+    def add_clause(
+        self, clause: Sequence[int], tag: bool = False, lock: bool = False
+    ) -> bool:
+        """
+        Add the given clause to the solver.
+
+        Parameters
+        ----------
+        clause
+            List of solver literals forming the clause.
+        tag
+            If true, the clause applies only in the current solving step.
+        lock
+            If true, exclude clause from the solver's regular clause deletion
+            policy.
+
+        Returns
+        -------
+        This method returns false if the current propagation must be stopped.
+        """
+        type_ = 0
+        if tag:
+            type_ |= _lib.clingo_clause_type_volatile
+        if lock:
+            type_ |= _lib.clingo_clause_type_static
+        return _c_call(
+            "bool",
+            _lib.clingo_propagate_control_add_clause,
+            self._rep,
+            clause,
+            len(clause),
+            type_,
+        )
+
+    def add_literal(self) -> int:
+        """
+        Adds a new positive volatile literal to the underlying solver thread.
+
+        The literal is only valid within the current solving step and solver
+        thread. All volatile literals and clauses involving a volatile literal
+        are deleted after the current search.
+
+        Returns
+        -------
+        The added solver literal.
+        """
+        return _c_call(
+            "clingo_literal_t", _lib.clingo_propagate_control_add_literal, self._rep
+        )
+
+    def add_nogood(
+        self, clause: Iterable[int], tag: bool = False, lock: bool = False
+    ) -> bool:
+        """
+        Equivalent to `self.add_clause([-lit for lit in clause], tag, lock)`.
+        """
+        return self.add_clause([-lit for lit in clause], tag, lock)
+
+    def add_watch(self, literal: int) -> None:
+        """
+        Add a watch for the solver literal in the given phase.
+
+        Parameters
+        ----------
+        literal
+            The target solver literal.
+
+        Notes
+        -----
+        Unlike `PropagateInit.add_watch` this does not add a watch to all
+        solver threads but just the current one.
+        """
+        _handle_error(_lib.clingo_propagate_control_add_watch(self._rep, literal))
+
+    def has_watch(self, literal: int) -> bool:
+        """
+        Check whether a literal is watched in the current solver thread.
+
+        Parameters
+        ----------
+        literal
+            The target solver literal.
+
+        Returns
+        -------
+        Whether the literal is watched.
+        """
+        return _lib.clingo_propagate_control_has_watch(self._rep, literal)
+
+    def propagate(self) -> bool:
+        """
+        Propagate literals implied by added clauses.
+
+        Returns
+        -------
+        This method returns false if the current propagation must be stopped.
+        """
+        return _c_call("bool", _lib.clingo_propagate_control_propagate, self._rep)
+
+    def remove_watch(self, literal: int) -> None:
+        """
+        Removes the watch (if any) for the given solver literal.
+
+        Parameters
+        ----------
+        literal
+            The target solver literal.
+        """
+        _lib.clingo_propagate_control_remove_watch(self._rep, literal)
+
+    @property
+    def assignment(self) -> Assignment:
+        """
+        `Assignment` object capturing the partial assignment of the current solver thread.
+        """
+        return Assignment(_lib.clingo_propagate_control_assignment(self._rep))
+
+    @property
+    def thread_id(self) -> int:
+        """
+        The numeric id of the current solver thread.
+        """
+        return _lib.clingo_propagate_control_thread_id(self._rep)
+
+
+class Propagator(metaclass=ABCMeta):
+    """
+    Propagator interface for custom constraints.
+
+    See Also
+    --------
+    clingo.control.Control.register_propagator
+
+    Notes
+    -----
+    Not all functions of the `Propagator` interface have to be implemented and
+    can be omitted if not needed.
+    """
+
+    def init(self, init: PropagateInit) -> None:
+        """
+        This function is called once before each solving step.
+
+        It is used to map relevant program literals to solver literals, add
+        watches for solver literals, and initialize the data structures used
+        during propagation.
+
+        Parameters
+        ----------
+        init
+            Object to initialize the propagator.
+
+        Notes
+        -----
+        This is the last point to access theory atoms.  Once the search has
+        started, they are no longer accessible.
+        """
+
+    def propagate(self, control: PropagateControl, changes: Sequence[int]) -> None:
+        """
+        Can be used to propagate solver literals given a partial assignment.
+
+        Parameters
+        ----------
+        control
+            Object to control propagation.
+        changes
+            List of watched solver literals assigned to true.
+
+        Notes
+        -----
+        Called during propagation with a non-empty list of watched solver
+        literals that have been assigned to true since the last call to either
+        propagate, undo, (or the start of the search) - the change set. Only
+        watched solver literals are contained in the change set. Each literal
+        in the change set is true w.r.t. the current Assignment.
+        `PropagateControl.add_clause` can be used to add clauses. If a clause
+        is unit resulting, it can be propagated using
+        `PropagateControl.propagate`. If either of the two methods returns
+        False, the propagate function must return immediately.
+
+            c = ...
+            if not control.add_clause(c) or not control.propagate(c):
+                return
+
+        Note that this function can be called from different solving threads.
+        Each thread has its own assignment and id, which can be obtained using
+        `PropagateControl.thread_id`.
+        """
+
+    def undo(
+        self, thread_id: int, assignment: Assignment, changes: Sequence[int]
+    ) -> None:
+        """
+        Called whenever a solver with the given id undos assignments to watched
+        solver literals.
+
+        Parameters
+        ----------
+        thread_id
+            The solver thread id.
+        assignment
+            Object for inspecting the partial assignment of the solver.
+        changes
+            The list of watched solver literals whose assignment is undone.
+
+        Notes
+        -----
+        This function is meant to update assignment dependent state in a
+        propagator but not to modify the current state of the solver.
+        Furthermore, errors raised in the function lead to program termination.
+        """
+
+    def check(self, control: PropagateControl) -> None:
+        """
+        This function is similar to propagate but is called without a change
+        set on propagation fixpoints.
+
+        When exactly this function is called, can be configured using the @ref
+        PropagateInit.check_mode property.
+
+        Parameters
+        ----------
+        control
+            Object to control propagation.
+
+        Notes
+        -----
+        This function is called even if no watches have been added.
+        """
+
+    def decide(self, thread_id: int, assignment: Assignment, fallback: int) -> int:
+        """
+        This function allows a propagator to implement domain-specific
+        heuristics.
+
+        It is called whenever propagation reaches a fixed point.
+
+        Parameters
+        ----------
+        thread_id
+            The solver thread id.
+        assignment
+            Object for inspecting the partial assignment of the solver.
+        fallback
+            The literal choosen by the solver's heuristic.
+
+        Returns
+        -------
+        Тhe next solver literal to make true.
+
+        Notes
+        -----
+        This function should return a free solver literal that is to be
+        assigned true. In case multiple propagators are registered, this
+        function can return 0 to let a propagator registered later make a
+        decision. If all propagators return 0, then the fallback literal is
+        used.
+        """
+        # pylint: disable=unused-argument
+        return fallback
+
+
+@_ffi.def_extern(onerror=_cb_error_handler("data"), name="pyclingo_propagator_init")
+def _pyclingo_propagator_init(init, data):
+    propagator = _ffi.from_handle(data).data
+    propagator.init(PropagateInit(init))
+    return True
+
+
+@_ffi.def_extern(
+    onerror=_cb_error_handler("data"), name="pyclingo_propagator_propagate"
+)
+def _pyclingo_propagator_propagate(control, changes, size, data):
+    propagator = _ffi.from_handle(data).data
+    py_changes = [changes[i] for i in range(size)]
+    propagator.propagate(PropagateControl(control), py_changes)
+    return True
+
+
+@_ffi.def_extern(onerror=_cb_error_handler("data"), name="pyclingo_propagator_undo")
+def _pyclingo_propagator_undo(control, changes, size, data):
+    propagator = _ffi.from_handle(data).data
+    py_changes = [changes[i] for i in range(size)]
+    ctl = PropagateControl(control)
+    propagator.undo(ctl.thread_id, ctl.assignment, py_changes)
+
+
+@_ffi.def_extern(onerror=_cb_error_handler("data"), name="pyclingo_propagator_check")
+def _pyclingo_propagator_check(control, data):
+    propagator = _ffi.from_handle(data).data
+    propagator.check(PropagateControl(control))
+    return True
+
+
+@_ffi.def_extern(onerror=_cb_error_handler("data"), name="pyclingo_propagator_decide")
+def _pyclingo_propagator_decide(thread_id, assignment, fallback, data, decision):
+    propagator = _ffi.from_handle(data).data
+    decision[0] = propagator.decide(thread_id, Assignment(assignment), fallback)
+    return True
+
+
+
+
+
+
+
+
+
+

Classes

+
+
+class Assignment +(rep) +
+
+

Class to inspect the (parital) assignment of an associated solver.

+

Assigns truth values to solver literals. +Each solver literal is either +true, false, or undefined, represented by the Python constants True, +False, or None, respectively.

+

This class implements Sequence[int] to access the (positive) +literals in the assignment.

+
+ +Expand source code + +
class Assignment(Sequence[int]):
+    """
+    Class to inspect the (parital) assignment of an associated solver.
+
+    Assigns truth values to solver literals.  Each solver literal is either
+    true, false, or undefined, represented by the Python constants `True`,
+    `False`, or `None`, respectively.
+
+    This class implements `Sequence[int]` to access the (positive)
+    literals in the assignment.
+    """
+
+    def __init__(self, rep):
+        self._rep = rep
+
+    def __len__(self):
+        return _lib.clingo_assignment_size(self._rep)
+
+    def __getitem__(self, slc):
+        if isinstance(slc, slice):
+            return SlicedSequence(self, Slice(slc))
+        if slc < 0:
+            slc += len(self)
+        if slc < 0 or slc >= len(self):
+            raise IndexError("invalid index")
+        return _c_call("clingo_literal_t", _lib.clingo_assignment_at, self._rep, slc)
+
+    def __iter__(self):
+        for i in range(len(self)):
+            yield _c_call("clingo_literal_t", _lib.clingo_assignment_at, self._rep, i)
+
+    def decision(self, level: int) -> int:
+        """
+        Return the decision literal of the given level.
+
+        Parameters
+        ----------
+        level
+            The decision level.
+        """
+        return _c_call(
+            "clingo_literal_t", _lib.clingo_assignment_decision, self._rep, level
+        )
+
+    def has_literal(self, literal: int) -> bool:
+        """
+        Determine if the given literal is valid in this solver.
+
+        Parameters
+        ----------
+        literal
+            The solver literal.
+        """
+        return _lib.clingo_assignment_has_literal(self._rep, literal)
+
+    def is_false(self, literal: int) -> bool:
+        """
+        Determine if the literal is false.
+
+        Parameters
+        ----------
+        literal
+            The solver literal.
+        """
+        return _c_call("bool", _lib.clingo_assignment_is_false, self._rep, literal)
+
+    def is_fixed(self, literal: int) -> bool:
+        """
+        Determine if the literal is assigned on the top level.
+
+        Parameters
+        ----------
+        literal
+            The solver literal.
+        """
+        return _c_call("bool", _lib.clingo_assignment_is_fixed, self._rep, literal)
+
+    def is_true(self, literal: int) -> bool:
+        """
+        Determine if the literal is true.
+
+        Parameters
+        ----------
+        literal
+            The solver literal.
+        """
+        return _c_call("bool", _lib.clingo_assignment_is_true, self._rep, literal)
+
+    def is_free(self, literal: int) -> bool:
+        """
+        Determine if the literal is free.
+
+        Parameters
+        ----------
+        literal
+            The solver literal.
+        """
+        value = _c_call(
+            "clingo_truth_value_t",
+            _lib.clingo_assignment_truth_value,
+            self._rep,
+            literal,
+        )
+        return value == _lib.clingo_truth_value_free
+
+    def level(self, literal: int) -> int:
+        """
+        The decision level of the given literal.
+
+        Parameters
+        ----------
+        literal
+            The solver literal.
+
+        Notes
+        -----
+        Note that the returned value is only meaningful if the literal is
+        assigned - i.e., `value(lit) is not None`.
+        """
+        return _c_call("uint32_t", _lib.clingo_assignment_level, self._rep, literal)
+
+    def value(self, literal) -> Optional[bool]:
+        """
+        Get the truth value of the given literal or `None` if it has none.
+
+        Parameters
+        ----------
+        literal
+            The solver literal.
+        """
+        value = _c_call(
+            "clingo_truth_value_t",
+            _lib.clingo_assignment_truth_value,
+            self._rep,
+            literal,
+        )
+        if value == _lib.clingo_truth_value_true:
+            return True
+        if value == _lib.clingo_truth_value_false:
+            return False
+        assert value == _lib.clingo_truth_value_free
+        return None
+
+    @property
+    def decision_level(self) -> int:
+        """
+        The current decision level.
+        """
+        return _lib.clingo_assignment_decision_level(self._rep)
+
+    @property
+    def has_conflict(self) -> bool:
+        """
+        True if the assignment is conflicting.
+        """
+        return _lib.clingo_assignment_has_conflict(self._rep)
+
+    @property
+    def is_total(self) -> bool:
+        """
+        Whether the assignment is total.
+        """
+        return _lib.clingo_assignment_is_total(self._rep)
+
+    @property
+    def root_level(self) -> int:
+        """
+        The current root level.
+        """
+        return _lib.clingo_assignment_root_level(self._rep)
+
+    @property
+    def trail(self) -> Trail:
+        """
+        The trail of assigned literals.
+        """
+        return Trail(self._rep)
+
+

Ancestors

+
    +
  • collections.abc.Sequence
  • +
  • collections.abc.Reversible
  • +
  • collections.abc.Collection
  • +
  • collections.abc.Sized
  • +
  • collections.abc.Iterable
  • +
  • collections.abc.Container
  • +
  • typing.Generic
  • +
+

Instance variables

+
+
var decision_level : int
+
+

The current decision level.

+
+ +Expand source code + +
@property
+def decision_level(self) -> int:
+    """
+    The current decision level.
+    """
+    return _lib.clingo_assignment_decision_level(self._rep)
+
+
+
var has_conflict : bool
+
+

True if the assignment is conflicting.

+
+ +Expand source code + +
@property
+def has_conflict(self) -> bool:
+    """
+    True if the assignment is conflicting.
+    """
+    return _lib.clingo_assignment_has_conflict(self._rep)
+
+
+
var is_total : bool
+
+

Whether the assignment is total.

+
+ +Expand source code + +
@property
+def is_total(self) -> bool:
+    """
+    Whether the assignment is total.
+    """
+    return _lib.clingo_assignment_is_total(self._rep)
+
+
+
var root_level : int
+
+

The current root level.

+
+ +Expand source code + +
@property
+def root_level(self) -> int:
+    """
+    The current root level.
+    """
+    return _lib.clingo_assignment_root_level(self._rep)
+
+
+
var trailTrail
+
+

The trail of assigned literals.

+
+ +Expand source code + +
@property
+def trail(self) -> Trail:
+    """
+    The trail of assigned literals.
+    """
+    return Trail(self._rep)
+
+
+
+

Methods

+
+
+def decision(self, level: int) ‑> int +
+
+

Return the decision literal of the given level.

+

Parameters

+
+
level
+
The decision level.
+
+
+ +Expand source code + +
def decision(self, level: int) -> int:
+    """
+    Return the decision literal of the given level.
+
+    Parameters
+    ----------
+    level
+        The decision level.
+    """
+    return _c_call(
+        "clingo_literal_t", _lib.clingo_assignment_decision, self._rep, level
+    )
+
+
+
+def has_literal(self, literal: int) ‑> bool +
+
+

Determine if the given literal is valid in this solver.

+

Parameters

+
+
literal
+
The solver literal.
+
+
+ +Expand source code + +
def has_literal(self, literal: int) -> bool:
+    """
+    Determine if the given literal is valid in this solver.
+
+    Parameters
+    ----------
+    literal
+        The solver literal.
+    """
+    return _lib.clingo_assignment_has_literal(self._rep, literal)
+
+
+
+def is_false(self, literal: int) ‑> bool +
+
+

Determine if the literal is false.

+

Parameters

+
+
literal
+
The solver literal.
+
+
+ +Expand source code + +
def is_false(self, literal: int) -> bool:
+    """
+    Determine if the literal is false.
+
+    Parameters
+    ----------
+    literal
+        The solver literal.
+    """
+    return _c_call("bool", _lib.clingo_assignment_is_false, self._rep, literal)
+
+
+
+def is_fixed(self, literal: int) ‑> bool +
+
+

Determine if the literal is assigned on the top level.

+

Parameters

+
+
literal
+
The solver literal.
+
+
+ +Expand source code + +
def is_fixed(self, literal: int) -> bool:
+    """
+    Determine if the literal is assigned on the top level.
+
+    Parameters
+    ----------
+    literal
+        The solver literal.
+    """
+    return _c_call("bool", _lib.clingo_assignment_is_fixed, self._rep, literal)
+
+
+
+def is_free(self, literal: int) ‑> bool +
+
+

Determine if the literal is free.

+

Parameters

+
+
literal
+
The solver literal.
+
+
+ +Expand source code + +
def is_free(self, literal: int) -> bool:
+    """
+    Determine if the literal is free.
+
+    Parameters
+    ----------
+    literal
+        The solver literal.
+    """
+    value = _c_call(
+        "clingo_truth_value_t",
+        _lib.clingo_assignment_truth_value,
+        self._rep,
+        literal,
+    )
+    return value == _lib.clingo_truth_value_free
+
+
+
+def is_true(self, literal: int) ‑> bool +
+
+

Determine if the literal is true.

+

Parameters

+
+
literal
+
The solver literal.
+
+
+ +Expand source code + +
def is_true(self, literal: int) -> bool:
+    """
+    Determine if the literal is true.
+
+    Parameters
+    ----------
+    literal
+        The solver literal.
+    """
+    return _c_call("bool", _lib.clingo_assignment_is_true, self._rep, literal)
+
+
+
+def level(self, literal: int) ‑> int +
+
+

The decision level of the given literal.

+

Parameters

+
+
literal
+
The solver literal.
+
+

Notes

+

Note that the returned value is only meaningful if the literal is +assigned - i.e., value(lit) is not None.

+
+ +Expand source code + +
def level(self, literal: int) -> int:
+    """
+    The decision level of the given literal.
+
+    Parameters
+    ----------
+    literal
+        The solver literal.
+
+    Notes
+    -----
+    Note that the returned value is only meaningful if the literal is
+    assigned - i.e., `value(lit) is not None`.
+    """
+    return _c_call("uint32_t", _lib.clingo_assignment_level, self._rep, literal)
+
+
+
+def value(self, literal) ‑> Optional[bool] +
+
+

Get the truth value of the given literal or None if it has none.

+

Parameters

+
+
literal
+
The solver literal.
+
+
+ +Expand source code + +
def value(self, literal) -> Optional[bool]:
+    """
+    Get the truth value of the given literal or `None` if it has none.
+
+    Parameters
+    ----------
+    literal
+        The solver literal.
+    """
+    value = _c_call(
+        "clingo_truth_value_t",
+        _lib.clingo_assignment_truth_value,
+        self._rep,
+        literal,
+    )
+    if value == _lib.clingo_truth_value_true:
+        return True
+    if value == _lib.clingo_truth_value_false:
+        return False
+    assert value == _lib.clingo_truth_value_free
+    return None
+
+
+
+
+
+class PropagateControl +(rep) +
+
+

This object can be used to add clauses and to propagate them.

+
+ +Expand source code + +
class PropagateControl:
+    """
+    This object can be used to add clauses and to propagate them.
+    """
+
+    def __init__(self, rep):
+        self._rep = rep
+
+    def add_clause(
+        self, clause: Sequence[int], tag: bool = False, lock: bool = False
+    ) -> bool:
+        """
+        Add the given clause to the solver.
+
+        Parameters
+        ----------
+        clause
+            List of solver literals forming the clause.
+        tag
+            If true, the clause applies only in the current solving step.
+        lock
+            If true, exclude clause from the solver's regular clause deletion
+            policy.
+
+        Returns
+        -------
+        This method returns false if the current propagation must be stopped.
+        """
+        type_ = 0
+        if tag:
+            type_ |= _lib.clingo_clause_type_volatile
+        if lock:
+            type_ |= _lib.clingo_clause_type_static
+        return _c_call(
+            "bool",
+            _lib.clingo_propagate_control_add_clause,
+            self._rep,
+            clause,
+            len(clause),
+            type_,
+        )
+
+    def add_literal(self) -> int:
+        """
+        Adds a new positive volatile literal to the underlying solver thread.
+
+        The literal is only valid within the current solving step and solver
+        thread. All volatile literals and clauses involving a volatile literal
+        are deleted after the current search.
+
+        Returns
+        -------
+        The added solver literal.
+        """
+        return _c_call(
+            "clingo_literal_t", _lib.clingo_propagate_control_add_literal, self._rep
+        )
+
+    def add_nogood(
+        self, clause: Iterable[int], tag: bool = False, lock: bool = False
+    ) -> bool:
+        """
+        Equivalent to `self.add_clause([-lit for lit in clause], tag, lock)`.
+        """
+        return self.add_clause([-lit for lit in clause], tag, lock)
+
+    def add_watch(self, literal: int) -> None:
+        """
+        Add a watch for the solver literal in the given phase.
+
+        Parameters
+        ----------
+        literal
+            The target solver literal.
+
+        Notes
+        -----
+        Unlike `PropagateInit.add_watch` this does not add a watch to all
+        solver threads but just the current one.
+        """
+        _handle_error(_lib.clingo_propagate_control_add_watch(self._rep, literal))
+
+    def has_watch(self, literal: int) -> bool:
+        """
+        Check whether a literal is watched in the current solver thread.
+
+        Parameters
+        ----------
+        literal
+            The target solver literal.
+
+        Returns
+        -------
+        Whether the literal is watched.
+        """
+        return _lib.clingo_propagate_control_has_watch(self._rep, literal)
+
+    def propagate(self) -> bool:
+        """
+        Propagate literals implied by added clauses.
+
+        Returns
+        -------
+        This method returns false if the current propagation must be stopped.
+        """
+        return _c_call("bool", _lib.clingo_propagate_control_propagate, self._rep)
+
+    def remove_watch(self, literal: int) -> None:
+        """
+        Removes the watch (if any) for the given solver literal.
+
+        Parameters
+        ----------
+        literal
+            The target solver literal.
+        """
+        _lib.clingo_propagate_control_remove_watch(self._rep, literal)
+
+    @property
+    def assignment(self) -> Assignment:
+        """
+        `Assignment` object capturing the partial assignment of the current solver thread.
+        """
+        return Assignment(_lib.clingo_propagate_control_assignment(self._rep))
+
+    @property
+    def thread_id(self) -> int:
+        """
+        The numeric id of the current solver thread.
+        """
+        return _lib.clingo_propagate_control_thread_id(self._rep)
+
+

Instance variables

+
+
var assignmentAssignment
+
+

Assignment object capturing the partial assignment of the current solver thread.

+
+ +Expand source code + +
@property
+def assignment(self) -> Assignment:
+    """
+    `Assignment` object capturing the partial assignment of the current solver thread.
+    """
+    return Assignment(_lib.clingo_propagate_control_assignment(self._rep))
+
+
+
var thread_id : int
+
+

The numeric id of the current solver thread.

+
+ +Expand source code + +
@property
+def thread_id(self) -> int:
+    """
+    The numeric id of the current solver thread.
+    """
+    return _lib.clingo_propagate_control_thread_id(self._rep)
+
+
+
+

Methods

+
+
+def add_clause(self, clause: Sequence[int], tag: bool = False, lock: bool = False) ‑> bool +
+
+

Add the given clause to the solver.

+

Parameters

+
+
clause
+
List of solver literals forming the clause.
+
tag
+
If true, the clause applies only in the current solving step.
+
lock
+
If true, exclude clause from the solver's regular clause deletion +policy.
+
+

Returns

+

This method returns false if the current propagation must be stopped.

+
+ +Expand source code + +
def add_clause(
+    self, clause: Sequence[int], tag: bool = False, lock: bool = False
+) -> bool:
+    """
+    Add the given clause to the solver.
+
+    Parameters
+    ----------
+    clause
+        List of solver literals forming the clause.
+    tag
+        If true, the clause applies only in the current solving step.
+    lock
+        If true, exclude clause from the solver's regular clause deletion
+        policy.
+
+    Returns
+    -------
+    This method returns false if the current propagation must be stopped.
+    """
+    type_ = 0
+    if tag:
+        type_ |= _lib.clingo_clause_type_volatile
+    if lock:
+        type_ |= _lib.clingo_clause_type_static
+    return _c_call(
+        "bool",
+        _lib.clingo_propagate_control_add_clause,
+        self._rep,
+        clause,
+        len(clause),
+        type_,
+    )
+
+
+
+def add_literal(self) ‑> int +
+
+

Adds a new positive volatile literal to the underlying solver thread.

+

The literal is only valid within the current solving step and solver +thread. All volatile literals and clauses involving a volatile literal +are deleted after the current search.

+

Returns

+

The added solver literal.

+
+ +Expand source code + +
def add_literal(self) -> int:
+    """
+    Adds a new positive volatile literal to the underlying solver thread.
+
+    The literal is only valid within the current solving step and solver
+    thread. All volatile literals and clauses involving a volatile literal
+    are deleted after the current search.
+
+    Returns
+    -------
+    The added solver literal.
+    """
+    return _c_call(
+        "clingo_literal_t", _lib.clingo_propagate_control_add_literal, self._rep
+    )
+
+
+
+def add_nogood(self, clause: Iterable[int], tag: bool = False, lock: bool = False) ‑> bool +
+
+

Equivalent to self.add_clause([-lit for lit in clause], tag, lock).

+
+ +Expand source code + +
def add_nogood(
+    self, clause: Iterable[int], tag: bool = False, lock: bool = False
+) -> bool:
+    """
+    Equivalent to `self.add_clause([-lit for lit in clause], tag, lock)`.
+    """
+    return self.add_clause([-lit for lit in clause], tag, lock)
+
+
+
+def add_watch(self, literal: int) ‑> None +
+
+

Add a watch for the solver literal in the given phase.

+

Parameters

+
+
literal
+
The target solver literal.
+
+

Notes

+

Unlike PropagateInit.add_watch() this does not add a watch to all +solver threads but just the current one.

+
+ +Expand source code + +
def add_watch(self, literal: int) -> None:
+    """
+    Add a watch for the solver literal in the given phase.
+
+    Parameters
+    ----------
+    literal
+        The target solver literal.
+
+    Notes
+    -----
+    Unlike `PropagateInit.add_watch` this does not add a watch to all
+    solver threads but just the current one.
+    """
+    _handle_error(_lib.clingo_propagate_control_add_watch(self._rep, literal))
+
+
+
+def has_watch(self, literal: int) ‑> bool +
+
+

Check whether a literal is watched in the current solver thread.

+

Parameters

+
+
literal
+
The target solver literal.
+
+

Returns

+

Whether the literal is watched.

+
+ +Expand source code + +
def has_watch(self, literal: int) -> bool:
+    """
+    Check whether a literal is watched in the current solver thread.
+
+    Parameters
+    ----------
+    literal
+        The target solver literal.
+
+    Returns
+    -------
+    Whether the literal is watched.
+    """
+    return _lib.clingo_propagate_control_has_watch(self._rep, literal)
+
+
+
+def propagate(self) ‑> bool +
+
+

Propagate literals implied by added clauses.

+

Returns

+

This method returns false if the current propagation must be stopped.

+
+ +Expand source code + +
def propagate(self) -> bool:
+    """
+    Propagate literals implied by added clauses.
+
+    Returns
+    -------
+    This method returns false if the current propagation must be stopped.
+    """
+    return _c_call("bool", _lib.clingo_propagate_control_propagate, self._rep)
+
+
+
+def remove_watch(self, literal: int) ‑> None +
+
+

Removes the watch (if any) for the given solver literal.

+

Parameters

+
+
literal
+
The target solver literal.
+
+
+ +Expand source code + +
def remove_watch(self, literal: int) -> None:
+    """
+    Removes the watch (if any) for the given solver literal.
+
+    Parameters
+    ----------
+    literal
+        The target solver literal.
+    """
+    _lib.clingo_propagate_control_remove_watch(self._rep, literal)
+
+
+
+
+
+class PropagateInit +(rep) +
+
+

Object that is used to initialize a propagator before each solving step.

+
+ +Expand source code + +
class PropagateInit:
+    """
+    Object that is used to initialize a propagator before each solving step.
+    """
+
+    def __init__(self, rep):
+        self._rep = rep
+
+    def add_clause(self, clause: Sequence[int]) -> bool:
+        """
+        Statically adds the given clause to the problem.
+
+        Parameters
+        ----------
+        clause
+            The clause over solver literals to add.
+
+        Returns
+        -------
+        Returns false if the program becomes unsatisfiable.
+
+        Notes
+        -----
+        If this function returns false, initialization should be stopped and no
+        further functions of the `PropagateInit` and related objects should be
+        called.
+        """
+        return _c_call(
+            "bool",
+            _lib.clingo_propagate_init_add_clause,
+            self._rep,
+            clause,
+            len(clause),
+        )
+
+    def add_literal(self, freeze: bool = True) -> int:
+        """
+        Statically adds a literal to the solver.
+
+        To be able to use the variable in clauses during propagation or add
+        watches to it, it has to be frozen. Otherwise, it might be removed
+        during preprocessing.
+
+        Parameters
+        ----------
+        freeze
+            Whether to freeze the variable.
+
+        Returns
+        -------
+        Returns the added literal.
+
+        Notes
+        -----
+        If literals are added to the solver, subsequent calls to `add_clause` and
+        `propagate` are expensive. It is best to add literals in batches.
+        """
+        return _c_call(
+            "clingo_literal_t",
+            _lib.clingo_propagate_init_add_literal,
+            self._rep,
+            freeze,
+        )
+
+    def add_minimize(self, literal: int, weight: int, priority: int = 0) -> None:
+        """
+        Extends the solver's minimize constraint with the given weighted
+        literal.
+
+        Parameters
+        ----------
+        literal
+            The literal to add.
+        weight
+            The weight of the literal.
+        priority
+            The priority of the literal.
+        """
+        _handle_error(
+            _lib.clingo_propagate_init_add_minimize(
+                self._rep, literal, weight, priority
+            )
+        )
+
+    def add_watch(self, literal: int, thread_id: Optional[int] = None) -> None:
+        """
+        Add a watch for the solver literal in the given phase.
+
+        Parameters
+        ----------
+        literal
+            The solver literal to watch.
+        thread_id
+            The id of the thread to watch the literal. If the is `None` then
+            all active threads will watch the literal.
+        """
+        if thread_id is None:
+            _handle_error(_lib.clingo_propagate_init_add_watch(self._rep, literal))
+        else:
+            _handle_error(
+                _lib.clingo_propagate_init_add_watch_to_thread(
+                    self._rep, literal, thread_id
+                )
+            )
+
+    def remove_watch(self, literal: int, thread_id: Optional[int] = None) -> None:
+        """
+        Remove the watch for the solver literal in the given phase.
+
+        Parameters
+        ----------
+        literal
+            The solver literal to remove the watch from.
+        thread_id
+            The id of the thread from which to remove the watch. If the is `None`, then
+            the watch is removed from all active threads.
+        """
+        if thread_id is None:
+            _handle_error(_lib.clingo_propagate_init_remove_watch(self._rep, literal))
+        else:
+            _handle_error(
+                _lib.clingo_propagate_init_remove_watch_from_thread(
+                    self._rep, literal, thread_id
+                )
+            )
+
+    def freeze_literal(self, literal: int) -> None:
+        """
+        Freeze the given solver literal.
+
+        Any solver literal that is not frozen is subject to simplification and
+        might be removed in a preprocessing step after propagator
+        initialization. A propagator should freeze all literals over which it
+        might add clauses during propagation. Note that any watched literal is
+        automatically frozen and that it does not matter which phase of the
+        literal is frozen.
+
+        Parameters
+        ----------
+        literal
+            The solver literal to freeze.
+        """
+        _handle_error(_lib.clingo_propagate_init_freeze_literal(self._rep, literal))
+
+    def add_weight_constraint(
+        self,
+        literal: int,
+        literals: Sequence[Tuple[int, int]],
+        bound: int,
+        type_: int = 0,
+        compare_equal: bool = False,
+    ) -> bool:
+        """
+        Statically adds a constraint of form
+
+            literal <=> { l=w | (l, w) in literals } >= bound
+
+        to the solver.
+
+        - If `type_ < 0`, then `<=>` is a left implication.
+        - If `type_ > 0`, then `<=>` is a right implication.
+        - Otherwise, `<=>` is an equivalence.
+
+        Parameters
+        ----------
+        literal
+            The literal associated with the constraint.
+        literals
+            The weighted literals of the constraint.
+        bound
+            The bound of the constraint.
+        type_
+            Add a weight constraint of the given type_.
+        compare_equal
+            A Boolean indicating whether to compare equal or less than equal.
+
+        Returns
+        -------
+        Returns false if the program became unsatisfiable.
+
+        Notes
+        -----
+        If this function returns false, initialization should be stopped and no further
+        functions of the `PropagateInit` and related objects should be called.
+        """
+        return _c_call(
+            "bool",
+            _lib.clingo_propagate_init_add_weight_constraint,
+            self._rep,
+            literal,
+            literals,
+            len(literals),
+            bound,
+            type_,
+            compare_equal,
+        )
+
+    def propagate(self) -> bool:
+        """
+        Propagates consequences of the underlying problem excluding registered
+        propagators.
+
+        Returns
+        -------
+        Returns false if the program becomes unsatisfiable.
+
+        Notes
+        -----
+        This function has no effect if SAT-preprocessing is enabled.
+
+        If this function returns false, initialization should be stopped and no
+        further functions of the `PropagateInit` and related objects should be
+        called.
+        """
+        return _c_call("bool", _lib.clingo_propagate_init_propagate, self._rep)
+
+    def solver_literal(self, literal: int) -> int:
+        """
+        Maps the given program literal or condition id to its solver literal.
+
+        Parameters
+        ----------
+        literal
+            A program literal or condition id.
+
+        Returns
+        -------
+        A solver literal.
+        """
+        return _c_call(
+            "clingo_literal_t",
+            _lib.clingo_propagate_init_solver_literal,
+            self._rep,
+            literal,
+        )
+
+    @property
+    def assignment(self) -> Assignment:
+        """
+        `Assignment` object capturing the top level assignment.
+        """
+        return Assignment(_lib.clingo_propagate_init_assignment(self._rep))
+
+    @property
+    def check_mode(self) -> PropagatorCheckMode:
+        """
+        `PropagatorCheckMode` controlling when to call `Propagator.check`.
+        """
+        return PropagatorCheckMode(_lib.clingo_propagate_init_get_check_mode(self._rep))
+
+    @check_mode.setter
+    def check_mode(self, mode: PropagatorCheckMode) -> None:
+        _lib.clingo_propagate_init_set_check_mode(self._rep, mode.value)
+
+    @property
+    def undo_mode(self) -> PropagatorUndoMode:
+        """
+        `PropagatorUndoMode` controlling when to call `Propagator.undo`.
+        """
+        return PropagatorUndoMode(_lib.clingo_propagate_init_get_undo_mode(self._rep))
+
+    @undo_mode.setter
+    def undo_mode(self, mode: PropagatorUndoMode) -> None:
+        _lib.clingo_propagate_init_set_undo_mode(self._rep, mode.value)
+
+    @property
+    def number_of_threads(self) -> int:
+        """
+        The number of solver threads used in the corresponding solve call.
+        """
+        return _lib.clingo_propagate_init_number_of_threads(self._rep)
+
+    @property
+    def symbolic_atoms(self) -> SymbolicAtoms:
+        """
+        The symbolic atoms captured by a `SymbolicAtoms` object.
+        """
+        atoms = _c_call(
+            "clingo_symbolic_atoms_t*",
+            _lib.clingo_propagate_init_symbolic_atoms,
+            self._rep,
+        )
+        return SymbolicAtoms(atoms)
+
+    @property
+    def theory_atoms(self) -> Iterator[TheoryAtom]:
+        """
+        An iterator over all theory atoms.
+        """
+        atoms = _c_call(
+            "clingo_theory_atoms_t*", _lib.clingo_propagate_init_theory_atoms, self._rep
+        )
+        size = _c_call("size_t", _lib.clingo_theory_atoms_size, atoms)
+
+        for idx in range(size):
+            yield TheoryAtom(atoms, idx)
+
+

Instance variables

+
+
var assignmentAssignment
+
+

Assignment object capturing the top level assignment.

+
+ +Expand source code + +
@property
+def assignment(self) -> Assignment:
+    """
+    `Assignment` object capturing the top level assignment.
+    """
+    return Assignment(_lib.clingo_propagate_init_assignment(self._rep))
+
+
+
var check_modePropagatorCheckMode
+
+

PropagatorCheckMode controlling when to call Propagator.check().

+
+ +Expand source code + +
@property
+def check_mode(self) -> PropagatorCheckMode:
+    """
+    `PropagatorCheckMode` controlling when to call `Propagator.check`.
+    """
+    return PropagatorCheckMode(_lib.clingo_propagate_init_get_check_mode(self._rep))
+
+
+
var number_of_threads : int
+
+

The number of solver threads used in the corresponding solve call.

+
+ +Expand source code + +
@property
+def number_of_threads(self) -> int:
+    """
+    The number of solver threads used in the corresponding solve call.
+    """
+    return _lib.clingo_propagate_init_number_of_threads(self._rep)
+
+
+
var symbolic_atomsSymbolicAtoms
+
+

The symbolic atoms captured by a SymbolicAtoms object.

+
+ +Expand source code + +
@property
+def symbolic_atoms(self) -> SymbolicAtoms:
+    """
+    The symbolic atoms captured by a `SymbolicAtoms` object.
+    """
+    atoms = _c_call(
+        "clingo_symbolic_atoms_t*",
+        _lib.clingo_propagate_init_symbolic_atoms,
+        self._rep,
+    )
+    return SymbolicAtoms(atoms)
+
+
+
var theory_atoms : Iterator[TheoryAtom]
+
+

An iterator over all theory atoms.

+
+ +Expand source code + +
@property
+def theory_atoms(self) -> Iterator[TheoryAtom]:
+    """
+    An iterator over all theory atoms.
+    """
+    atoms = _c_call(
+        "clingo_theory_atoms_t*", _lib.clingo_propagate_init_theory_atoms, self._rep
+    )
+    size = _c_call("size_t", _lib.clingo_theory_atoms_size, atoms)
+
+    for idx in range(size):
+        yield TheoryAtom(atoms, idx)
+
+
+
var undo_modePropagatorUndoMode
+
+

PropagatorUndoMode controlling when to call Propagator.undo().

+
+ +Expand source code + +
@property
+def undo_mode(self) -> PropagatorUndoMode:
+    """
+    `PropagatorUndoMode` controlling when to call `Propagator.undo`.
+    """
+    return PropagatorUndoMode(_lib.clingo_propagate_init_get_undo_mode(self._rep))
+
+
+
+

Methods

+
+
+def add_clause(self, clause: Sequence[int]) ‑> bool +
+
+

Statically adds the given clause to the problem.

+

Parameters

+
+
clause
+
The clause over solver literals to add.
+
+

Returns

+

Returns false if the program becomes unsatisfiable.

+

Notes

+

If this function returns false, initialization should be stopped and no +further functions of the PropagateInit and related objects should be +called.

+
+ +Expand source code + +
def add_clause(self, clause: Sequence[int]) -> bool:
+    """
+    Statically adds the given clause to the problem.
+
+    Parameters
+    ----------
+    clause
+        The clause over solver literals to add.
+
+    Returns
+    -------
+    Returns false if the program becomes unsatisfiable.
+
+    Notes
+    -----
+    If this function returns false, initialization should be stopped and no
+    further functions of the `PropagateInit` and related objects should be
+    called.
+    """
+    return _c_call(
+        "bool",
+        _lib.clingo_propagate_init_add_clause,
+        self._rep,
+        clause,
+        len(clause),
+    )
+
+
+
+def add_literal(self, freeze: bool = True) ‑> int +
+
+

Statically adds a literal to the solver.

+

To be able to use the variable in clauses during propagation or add +watches to it, it has to be frozen. Otherwise, it might be removed +during preprocessing.

+

Parameters

+
+
freeze
+
Whether to freeze the variable.
+
+

Returns

+

Returns the added literal.

+

Notes

+

If literals are added to the solver, subsequent calls to add_clause and +propagate are expensive. It is best to add literals in batches.

+
+ +Expand source code + +
def add_literal(self, freeze: bool = True) -> int:
+    """
+    Statically adds a literal to the solver.
+
+    To be able to use the variable in clauses during propagation or add
+    watches to it, it has to be frozen. Otherwise, it might be removed
+    during preprocessing.
+
+    Parameters
+    ----------
+    freeze
+        Whether to freeze the variable.
+
+    Returns
+    -------
+    Returns the added literal.
+
+    Notes
+    -----
+    If literals are added to the solver, subsequent calls to `add_clause` and
+    `propagate` are expensive. It is best to add literals in batches.
+    """
+    return _c_call(
+        "clingo_literal_t",
+        _lib.clingo_propagate_init_add_literal,
+        self._rep,
+        freeze,
+    )
+
+
+
+def add_minimize(self, literal: int, weight: int, priority: int = 0) ‑> None +
+
+

Extends the solver's minimize constraint with the given weighted +literal.

+

Parameters

+
+
literal
+
The literal to add.
+
weight
+
The weight of the literal.
+
priority
+
The priority of the literal.
+
+
+ +Expand source code + +
def add_minimize(self, literal: int, weight: int, priority: int = 0) -> None:
+    """
+    Extends the solver's minimize constraint with the given weighted
+    literal.
+
+    Parameters
+    ----------
+    literal
+        The literal to add.
+    weight
+        The weight of the literal.
+    priority
+        The priority of the literal.
+    """
+    _handle_error(
+        _lib.clingo_propagate_init_add_minimize(
+            self._rep, literal, weight, priority
+        )
+    )
+
+
+
+def add_watch(self, literal: int, thread_id: Optional[int] = None) ‑> None +
+
+

Add a watch for the solver literal in the given phase.

+

Parameters

+
+
literal
+
The solver literal to watch.
+
thread_id
+
The id of the thread to watch the literal. If the is None then +all active threads will watch the literal.
+
+
+ +Expand source code + +
def add_watch(self, literal: int, thread_id: Optional[int] = None) -> None:
+    """
+    Add a watch for the solver literal in the given phase.
+
+    Parameters
+    ----------
+    literal
+        The solver literal to watch.
+    thread_id
+        The id of the thread to watch the literal. If the is `None` then
+        all active threads will watch the literal.
+    """
+    if thread_id is None:
+        _handle_error(_lib.clingo_propagate_init_add_watch(self._rep, literal))
+    else:
+        _handle_error(
+            _lib.clingo_propagate_init_add_watch_to_thread(
+                self._rep, literal, thread_id
+            )
+        )
+
+
+
+def add_weight_constraint(self, literal: int, literals: Sequence[Tuple[int, int]], bound: int, type_: int = 0, compare_equal: bool = False) ‑> bool +
+
+

Statically adds a constraint of form

+
literal <=> { l=w | (l, w) in literals } >= bound
+
+

to the solver.

+
    +
  • If type_ < 0, then <=> is a left implication.
  • +
  • If type_ > 0, then <=> is a right implication.
  • +
  • Otherwise, <=> is an equivalence.
  • +
+

Parameters

+
+
literal
+
The literal associated with the constraint.
+
literals
+
The weighted literals of the constraint.
+
bound
+
The bound of the constraint.
+
type_
+
Add a weight constraint of the given type_.
+
compare_equal
+
A Boolean indicating whether to compare equal or less than equal.
+
+

Returns

+

Returns false if the program became unsatisfiable.

+

Notes

+

If this function returns false, initialization should be stopped and no further +functions of the PropagateInit and related objects should be called.

+
+ +Expand source code + +
def add_weight_constraint(
+    self,
+    literal: int,
+    literals: Sequence[Tuple[int, int]],
+    bound: int,
+    type_: int = 0,
+    compare_equal: bool = False,
+) -> bool:
+    """
+    Statically adds a constraint of form
+
+        literal <=> { l=w | (l, w) in literals } >= bound
+
+    to the solver.
+
+    - If `type_ < 0`, then `<=>` is a left implication.
+    - If `type_ > 0`, then `<=>` is a right implication.
+    - Otherwise, `<=>` is an equivalence.
+
+    Parameters
+    ----------
+    literal
+        The literal associated with the constraint.
+    literals
+        The weighted literals of the constraint.
+    bound
+        The bound of the constraint.
+    type_
+        Add a weight constraint of the given type_.
+    compare_equal
+        A Boolean indicating whether to compare equal or less than equal.
+
+    Returns
+    -------
+    Returns false if the program became unsatisfiable.
+
+    Notes
+    -----
+    If this function returns false, initialization should be stopped and no further
+    functions of the `PropagateInit` and related objects should be called.
+    """
+    return _c_call(
+        "bool",
+        _lib.clingo_propagate_init_add_weight_constraint,
+        self._rep,
+        literal,
+        literals,
+        len(literals),
+        bound,
+        type_,
+        compare_equal,
+    )
+
+
+
+def freeze_literal(self, literal: int) ‑> None +
+
+

Freeze the given solver literal.

+

Any solver literal that is not frozen is subject to simplification and +might be removed in a preprocessing step after propagator +initialization. A propagator should freeze all literals over which it +might add clauses during propagation. Note that any watched literal is +automatically frozen and that it does not matter which phase of the +literal is frozen.

+

Parameters

+
+
literal
+
The solver literal to freeze.
+
+
+ +Expand source code + +
def freeze_literal(self, literal: int) -> None:
+    """
+    Freeze the given solver literal.
+
+    Any solver literal that is not frozen is subject to simplification and
+    might be removed in a preprocessing step after propagator
+    initialization. A propagator should freeze all literals over which it
+    might add clauses during propagation. Note that any watched literal is
+    automatically frozen and that it does not matter which phase of the
+    literal is frozen.
+
+    Parameters
+    ----------
+    literal
+        The solver literal to freeze.
+    """
+    _handle_error(_lib.clingo_propagate_init_freeze_literal(self._rep, literal))
+
+
+
+def propagate(self) ‑> bool +
+
+

Propagates consequences of the underlying problem excluding registered +propagators.

+

Returns

+

Returns false if the program becomes unsatisfiable.

+

Notes

+

This function has no effect if SAT-preprocessing is enabled.

+

If this function returns false, initialization should be stopped and no +further functions of the PropagateInit and related objects should be +called.

+
+ +Expand source code + +
def propagate(self) -> bool:
+    """
+    Propagates consequences of the underlying problem excluding registered
+    propagators.
+
+    Returns
+    -------
+    Returns false if the program becomes unsatisfiable.
+
+    Notes
+    -----
+    This function has no effect if SAT-preprocessing is enabled.
+
+    If this function returns false, initialization should be stopped and no
+    further functions of the `PropagateInit` and related objects should be
+    called.
+    """
+    return _c_call("bool", _lib.clingo_propagate_init_propagate, self._rep)
+
+
+
+def remove_watch(self, literal: int, thread_id: Optional[int] = None) ‑> None +
+
+

Remove the watch for the solver literal in the given phase.

+

Parameters

+
+
literal
+
The solver literal to remove the watch from.
+
thread_id
+
The id of the thread from which to remove the watch. If the is None, then +the watch is removed from all active threads.
+
+
+ +Expand source code + +
def remove_watch(self, literal: int, thread_id: Optional[int] = None) -> None:
+    """
+    Remove the watch for the solver literal in the given phase.
+
+    Parameters
+    ----------
+    literal
+        The solver literal to remove the watch from.
+    thread_id
+        The id of the thread from which to remove the watch. If the is `None`, then
+        the watch is removed from all active threads.
+    """
+    if thread_id is None:
+        _handle_error(_lib.clingo_propagate_init_remove_watch(self._rep, literal))
+    else:
+        _handle_error(
+            _lib.clingo_propagate_init_remove_watch_from_thread(
+                self._rep, literal, thread_id
+            )
+        )
+
+
+
+def solver_literal(self, literal: int) ‑> int +
+
+

Maps the given program literal or condition id to its solver literal.

+

Parameters

+
+
literal
+
A program literal or condition id.
+
+

Returns

+

A solver literal.

+
+ +Expand source code + +
def solver_literal(self, literal: int) -> int:
+    """
+    Maps the given program literal or condition id to its solver literal.
+
+    Parameters
+    ----------
+    literal
+        A program literal or condition id.
+
+    Returns
+    -------
+    A solver literal.
+    """
+    return _c_call(
+        "clingo_literal_t",
+        _lib.clingo_propagate_init_solver_literal,
+        self._rep,
+        literal,
+    )
+
+
+
+
+
+class Propagator +
+
+

Propagator interface for custom constraints.

+

See Also

+

Control.register_propagator()

+

Notes

+

Not all functions of the Propagator interface have to be implemented and +can be omitted if not needed.

+
+ +Expand source code + +
class Propagator(metaclass=ABCMeta):
+    """
+    Propagator interface for custom constraints.
+
+    See Also
+    --------
+    clingo.control.Control.register_propagator
+
+    Notes
+    -----
+    Not all functions of the `Propagator` interface have to be implemented and
+    can be omitted if not needed.
+    """
+
+    def init(self, init: PropagateInit) -> None:
+        """
+        This function is called once before each solving step.
+
+        It is used to map relevant program literals to solver literals, add
+        watches for solver literals, and initialize the data structures used
+        during propagation.
+
+        Parameters
+        ----------
+        init
+            Object to initialize the propagator.
+
+        Notes
+        -----
+        This is the last point to access theory atoms.  Once the search has
+        started, they are no longer accessible.
+        """
+
+    def propagate(self, control: PropagateControl, changes: Sequence[int]) -> None:
+        """
+        Can be used to propagate solver literals given a partial assignment.
+
+        Parameters
+        ----------
+        control
+            Object to control propagation.
+        changes
+            List of watched solver literals assigned to true.
+
+        Notes
+        -----
+        Called during propagation with a non-empty list of watched solver
+        literals that have been assigned to true since the last call to either
+        propagate, undo, (or the start of the search) - the change set. Only
+        watched solver literals are contained in the change set. Each literal
+        in the change set is true w.r.t. the current Assignment.
+        `PropagateControl.add_clause` can be used to add clauses. If a clause
+        is unit resulting, it can be propagated using
+        `PropagateControl.propagate`. If either of the two methods returns
+        False, the propagate function must return immediately.
+
+            c = ...
+            if not control.add_clause(c) or not control.propagate(c):
+                return
+
+        Note that this function can be called from different solving threads.
+        Each thread has its own assignment and id, which can be obtained using
+        `PropagateControl.thread_id`.
+        """
+
+    def undo(
+        self, thread_id: int, assignment: Assignment, changes: Sequence[int]
+    ) -> None:
+        """
+        Called whenever a solver with the given id undos assignments to watched
+        solver literals.
+
+        Parameters
+        ----------
+        thread_id
+            The solver thread id.
+        assignment
+            Object for inspecting the partial assignment of the solver.
+        changes
+            The list of watched solver literals whose assignment is undone.
+
+        Notes
+        -----
+        This function is meant to update assignment dependent state in a
+        propagator but not to modify the current state of the solver.
+        Furthermore, errors raised in the function lead to program termination.
+        """
+
+    def check(self, control: PropagateControl) -> None:
+        """
+        This function is similar to propagate but is called without a change
+        set on propagation fixpoints.
+
+        When exactly this function is called, can be configured using the @ref
+        PropagateInit.check_mode property.
+
+        Parameters
+        ----------
+        control
+            Object to control propagation.
+
+        Notes
+        -----
+        This function is called even if no watches have been added.
+        """
+
+    def decide(self, thread_id: int, assignment: Assignment, fallback: int) -> int:
+        """
+        This function allows a propagator to implement domain-specific
+        heuristics.
+
+        It is called whenever propagation reaches a fixed point.
+
+        Parameters
+        ----------
+        thread_id
+            The solver thread id.
+        assignment
+            Object for inspecting the partial assignment of the solver.
+        fallback
+            The literal choosen by the solver's heuristic.
+
+        Returns
+        -------
+        Тhe next solver literal to make true.
+
+        Notes
+        -----
+        This function should return a free solver literal that is to be
+        assigned true. In case multiple propagators are registered, this
+        function can return 0 to let a propagator registered later make a
+        decision. If all propagators return 0, then the fallback literal is
+        used.
+        """
+        # pylint: disable=unused-argument
+        return fallback
+
+

Methods

+
+
+def check(self, control: PropagateControl) ‑> None +
+
+

This function is similar to propagate but is called without a change +set on propagation fixpoints.

+

When exactly this function is called, can be configured using the @ref +PropagateInit.check_mode property.

+

Parameters

+
+
control
+
Object to control propagation.
+
+

Notes

+

This function is called even if no watches have been added.

+
+ +Expand source code + +
def check(self, control: PropagateControl) -> None:
+    """
+    This function is similar to propagate but is called without a change
+    set on propagation fixpoints.
+
+    When exactly this function is called, can be configured using the @ref
+    PropagateInit.check_mode property.
+
+    Parameters
+    ----------
+    control
+        Object to control propagation.
+
+    Notes
+    -----
+    This function is called even if no watches have been added.
+    """
+
+
+
+def decide(self, thread_id: int, assignment: Assignment, fallback: int) ‑> int +
+
+

This function allows a propagator to implement domain-specific +heuristics.

+

It is called whenever propagation reaches a fixed point.

+

Parameters

+
+
thread_id
+
The solver thread id.
+
assignment
+
Object for inspecting the partial assignment of the solver.
+
fallback
+
The literal choosen by the solver's heuristic.
+
+

Returns

+

Тhe next solver literal to make true.

+

Notes

+

This function should return a free solver literal that is to be +assigned true. In case multiple propagators are registered, this +function can return 0 to let a propagator registered later make a +decision. If all propagators return 0, then the fallback literal is +used.

+
+ +Expand source code + +
def decide(self, thread_id: int, assignment: Assignment, fallback: int) -> int:
+    """
+    This function allows a propagator to implement domain-specific
+    heuristics.
+
+    It is called whenever propagation reaches a fixed point.
+
+    Parameters
+    ----------
+    thread_id
+        The solver thread id.
+    assignment
+        Object for inspecting the partial assignment of the solver.
+    fallback
+        The literal choosen by the solver's heuristic.
+
+    Returns
+    -------
+    Тhe next solver literal to make true.
+
+    Notes
+    -----
+    This function should return a free solver literal that is to be
+    assigned true. In case multiple propagators are registered, this
+    function can return 0 to let a propagator registered later make a
+    decision. If all propagators return 0, then the fallback literal is
+    used.
+    """
+    # pylint: disable=unused-argument
+    return fallback
+
+
+
+def init(self, init: PropagateInit) ‑> None +
+
+

This function is called once before each solving step.

+

It is used to map relevant program literals to solver literals, add +watches for solver literals, and initialize the data structures used +during propagation.

+

Parameters

+
+
init
+
Object to initialize the propagator.
+
+

Notes

+

This is the last point to access theory atoms. +Once the search has +started, they are no longer accessible.

+
+ +Expand source code + +
def init(self, init: PropagateInit) -> None:
+    """
+    This function is called once before each solving step.
+
+    It is used to map relevant program literals to solver literals, add
+    watches for solver literals, and initialize the data structures used
+    during propagation.
+
+    Parameters
+    ----------
+    init
+        Object to initialize the propagator.
+
+    Notes
+    -----
+    This is the last point to access theory atoms.  Once the search has
+    started, they are no longer accessible.
+    """
+
+
+
+def propagate(self, control: PropagateControl, changes: Sequence[int]) ‑> None +
+
+

Can be used to propagate solver literals given a partial assignment.

+

Parameters

+
+
control
+
Object to control propagation.
+
changes
+
List of watched solver literals assigned to true.
+
+

Notes

+

Called during propagation with a non-empty list of watched solver +literals that have been assigned to true since the last call to either +propagate, undo, (or the start of the search) - the change set. Only +watched solver literals are contained in the change set. Each literal +in the change set is true w.r.t. the current Assignment. +PropagateControl.add_clause() can be used to add clauses. If a clause +is unit resulting, it can be propagated using +PropagateControl.propagate(). If either of the two methods returns +False, the propagate function must return immediately.

+
c = ...
+if not control.add_clause(c) or not control.propagate(c):
+    return
+
+

Note that this function can be called from different solving threads. +Each thread has its own assignment and id, which can be obtained using +PropagateControl.thread_id.

+
+ +Expand source code + +
def propagate(self, control: PropagateControl, changes: Sequence[int]) -> None:
+    """
+    Can be used to propagate solver literals given a partial assignment.
+
+    Parameters
+    ----------
+    control
+        Object to control propagation.
+    changes
+        List of watched solver literals assigned to true.
+
+    Notes
+    -----
+    Called during propagation with a non-empty list of watched solver
+    literals that have been assigned to true since the last call to either
+    propagate, undo, (or the start of the search) - the change set. Only
+    watched solver literals are contained in the change set. Each literal
+    in the change set is true w.r.t. the current Assignment.
+    `PropagateControl.add_clause` can be used to add clauses. If a clause
+    is unit resulting, it can be propagated using
+    `PropagateControl.propagate`. If either of the two methods returns
+    False, the propagate function must return immediately.
+
+        c = ...
+        if not control.add_clause(c) or not control.propagate(c):
+            return
+
+    Note that this function can be called from different solving threads.
+    Each thread has its own assignment and id, which can be obtained using
+    `PropagateControl.thread_id`.
+    """
+
+
+
+def undo(self, thread_id: int, assignment: Assignment, changes: Sequence[int]) ‑> None +
+
+

Called whenever a solver with the given id undos assignments to watched +solver literals.

+

Parameters

+
+
thread_id
+
The solver thread id.
+
assignment
+
Object for inspecting the partial assignment of the solver.
+
changes
+
The list of watched solver literals whose assignment is undone.
+
+

Notes

+

This function is meant to update assignment dependent state in a +propagator but not to modify the current state of the solver. +Furthermore, errors raised in the function lead to program termination.

+
+ +Expand source code + +
def undo(
+    self, thread_id: int, assignment: Assignment, changes: Sequence[int]
+) -> None:
+    """
+    Called whenever a solver with the given id undos assignments to watched
+    solver literals.
+
+    Parameters
+    ----------
+    thread_id
+        The solver thread id.
+    assignment
+        Object for inspecting the partial assignment of the solver.
+    changes
+        The list of watched solver literals whose assignment is undone.
+
+    Notes
+    -----
+    This function is meant to update assignment dependent state in a
+    propagator but not to modify the current state of the solver.
+    Furthermore, errors raised in the function lead to program termination.
+    """
+
+
+
+
+
+class PropagatorCheckMode +(value, names=None, *, module=None, qualname=None, type=None, start=1) +
+
+

Enumeration of supported check modes for propagators.

+

Note that total checks are subject to the lock when a model is found. This +means that information from previously found models can be used to discard +assignments in check calls.

+
+ +Expand source code + +
class PropagatorCheckMode(OrderedEnum):
+    """
+    Enumeration of supported check modes for propagators.
+
+    Note that total checks are subject to the lock when a model is found. This
+    means that information from previously found models can be used to discard
+    assignments in check calls.
+    """
+
+    Both = _lib.clingo_propagator_check_mode_both
+    """
+    Call `Propagator.check` on propagation fixpoints and total assignments.
+    """
+    Fixpoint = _lib.clingo_propagator_check_mode_fixpoint
+    """
+    Call `Propagator.check` on propagation fixpoints.
+    """
+    Off = _lib.clingo_propagator_check_mode_none
+    """
+    Do not call `Propagator.check` at all.
+    """
+    Total = _lib.clingo_propagator_check_mode_total
+    """
+    Call `Propagator.check` on total assignments.
+    """
+
+

Ancestors

+ +

Class variables

+
+
var Both
+
+

Call Propagator.check() on propagation fixpoints and total assignments.

+
+
var Fixpoint
+
+

Call Propagator.check() on propagation fixpoints.

+
+
var Off
+
+

Do not call Propagator.check() at all.

+
+
var Total
+
+

Call Propagator.check() on total assignments.

+
+
+
+
+class PropagatorUndoMode +(value, names=None, *, module=None, qualname=None, type=None, start=1) +
+
+

Enumeration of supported check modes for propagators.

+

Note that total checks are subject to the lock when a model is found. This +means that information from previously found models can be used to discard +assignments in check calls.

+
+ +Expand source code + +
class PropagatorUndoMode(OrderedEnum):
+    """
+    Enumeration of supported check modes for propagators.
+
+    Note that total checks are subject to the lock when a model is found. This
+    means that information from previously found models can be used to discard
+    assignments in check calls.
+    """
+
+    Default = _lib.clingo_propagator_undo_mode_default
+    """
+    Call `Propagator.undo` for decision levels with non-emty changes.
+    """
+    Always = _lib.clingo_propagator_undo_mode_always
+    """
+    Also call `Propagator.undo` when check has been called.
+    """
+
+

Ancestors

+ +

Class variables

+
+
var Always
+
+

Also call Propagator.undo() when check has been called.

+
+
var Default
+
+

Call Propagator.undo() for decision levels with non-emty changes.

+
+
+
+
+class Trail +(rep) +
+
+

Class to access literals assigned by the solver in chronological order.

+

Literals in the trail are ordered by decision levels, where the first +literal with a larger level than the previous literals is a decision; the +following literals with same level are implied by this decision literal. +Each decision level up to and including the current decision level has a +valid offset in the trail.

+
+ +Expand source code + +
class Trail(Sequence[int]):
+    """
+    Class to access literals assigned by the solver in chronological order.
+
+    Literals in the trail are ordered by decision levels, where the first
+    literal with a larger level than the previous literals is a decision; the
+    following literals with same level are implied by this decision literal.
+    Each decision level up to and including the current decision level has a
+    valid offset in the trail.
+    """
+
+    def __init__(self, rep):
+        self._rep = rep
+
+    def __len__(self):
+        return _c_call("uint32_t", _lib.clingo_assignment_trail_size, self._rep)
+
+    def __getitem__(self, slc):
+        if isinstance(slc, slice):
+            return SlicedSequence(self, Slice(slc))
+        if slc < 0:
+            slc += len(self)
+        if slc < 0 or slc >= len(self):
+            raise IndexError("invalid index")
+        return _c_call(
+            "clingo_literal_t", _lib.clingo_assignment_trail_at, self._rep, slc
+        )
+
+    def __iter__(self):
+        for i in range(len(self)):
+            yield _c_call(
+                "clingo_literal_t", _lib.clingo_assignment_trail_at, self._rep, i
+            )
+
+    def begin(self, level: int) -> int:
+        """
+        Returns the offset of the decision literal with the given decision
+        level in the trail.
+
+        Parameters
+        ----------
+        level
+            The decision level.
+        """
+        return _c_call("uint32_t", _lib.clingo_assignment_trail_begin, self._rep, level)
+
+    def end(self, level: int) -> int:
+        """
+        Returns the offset following the last literal with the given decision
+        literal in the trail.
+
+        Parameters
+        ----------
+        level
+            The decision level.
+        """
+        return _c_call("uint32_t", _lib.clingo_assignment_trail_end, self._rep, level)
+
+

Ancestors

+
    +
  • collections.abc.Sequence
  • +
  • collections.abc.Reversible
  • +
  • collections.abc.Collection
  • +
  • collections.abc.Sized
  • +
  • collections.abc.Iterable
  • +
  • collections.abc.Container
  • +
  • typing.Generic
  • +
+

Methods

+
+
+def begin(self, level: int) ‑> int +
+
+

Returns the offset of the decision literal with the given decision +level in the trail.

+

Parameters

+
+
level
+
The decision level.
+
+
+ +Expand source code + +
def begin(self, level: int) -> int:
+    """
+    Returns the offset of the decision literal with the given decision
+    level in the trail.
+
+    Parameters
+    ----------
+    level
+        The decision level.
+    """
+    return _c_call("uint32_t", _lib.clingo_assignment_trail_begin, self._rep, level)
+
+
+
+def end(self, level: int) ‑> int +
+
+

Returns the offset following the last literal with the given decision +literal in the trail.

+

Parameters

+
+
level
+
The decision level.
+
+
+ +Expand source code + +
def end(self, level: int) -> int:
+    """
+    Returns the offset following the last literal with the given decision
+    literal in the trail.
+
+    Parameters
+    ----------
+    level
+        The decision level.
+    """
+    return _c_call("uint32_t", _lib.clingo_assignment_trail_end, self._rep, level)
+
+
+
+
+
+
+
+ +
+ + + \ No newline at end of file diff --git a/clingo/python-api/5.7/clingo/script.html b/clingo/python-api/5.7/clingo/script.html new file mode 100644 index 0000000..2472117 --- /dev/null +++ b/clingo/python-api/5.7/clingo/script.html @@ -0,0 +1,705 @@ + + + + + + +clingo.script API documentation + + + + + + + + + + + +
+
+
+

Module clingo.script

+
+
+

This module contains functions to add custom scripts, which can be embedded +into logic programs.

+

Examples

+

The following example shows how to add a script that works the same way as +clingo's embedded Python script:

+
>>> from clingo.script import Script, register_script
+>>> from clingo.control import Control
+>>>
+>>> import __main__
+>>>
+>>> class MyPythonScript(Script):
+...     def execute(self, location, code):
+...         exec(code, __main__.__dict__, __main__.__dict__)
+...     def call(self, location, name, arguments):
+...         return getattr(__main__, name)(*arguments)
+...     def callable(self, name):
+...         return name in __main__.__dict__ and callable(__main__.__dict__[name])
+...
+>>> register_script('mypython', MyPythonScript())
+>>>
+>>> ctl = Control()
+>>> ctl.add('base', [], """
+... #script(mypython)
+... from clingo.symbol import Number
+... def func(a):
+...     return Number(a.number + 1)
+... #end.
+... a(@func(1)).
+... """)
+>>>
+>>> ctl.ground([('base',[])])
+>>> ctl.solve(on_model=print)
+a(2)
+
+
+ +Expand source code + +
'''
+This module contains functions to add custom scripts, which can be embedded
+into logic programs.
+
+Examples
+--------
+The following example shows how to add a script that works the same way as
+clingo's embedded Python script:
+```python
+>>> from clingo.script import Script, register_script
+>>> from clingo.control import Control
+>>>
+>>> import __main__
+>>>
+>>> class MyPythonScript(Script):
+...     def execute(self, location, code):
+...         exec(code, __main__.__dict__, __main__.__dict__)
+...     def call(self, location, name, arguments):
+...         return getattr(__main__, name)(*arguments)
+...     def callable(self, name):
+...         return name in __main__.__dict__ and callable(__main__.__dict__[name])
+...
+>>> register_script('mypython', MyPythonScript())
+>>>
+>>> ctl = Control()
+>>> ctl.add('base', [], """
+... #script(mypython)
+... from clingo.symbol import Number
+... def func(a):
+...     return Number(a.number + 1)
+... #end.
+... a(@func(1)).
+... """)
+>>>
+>>> ctl.ground([('base',[])])
+>>> ctl.solve(on_model=print)
+a(2)
+```
+'''
+
+from platform import python_version
+from abc import ABCMeta, abstractmethod
+from typing import Any, List, Iterable, Tuple, Union
+from collections.abc import Iterable as IterableABC
+from traceback import format_exception
+from clingo._internal import _c_call, _ffi, _handle_error, _lib
+from clingo.control import Control
+from clingo.symbol import Symbol
+from clingo.ast import Location, _py_location
+
+try:
+    import __main__  # type: ignore
+except ImportError:
+    # Note: pypy does not create a main module if embedded
+    import sys
+    import types
+
+    sys.modules["__main__"] = types.ModuleType("__main__", "the main module")
+    import __main__  # type: ignore
+
+__all__ = ["Script", "enable_python", "register_script"]
+
+
+def _cb_error_top_level(exception, exc_value, traceback):
+    msg = "".join(format_exception(exception, exc_value, traceback))
+    _lib.clingo_set_error(_lib.clingo_error_runtime, msg.encode())
+    return False
+
+
+class Script(metaclass=ABCMeta):
+    """
+    This interface can be implemented to embed custom scripting languages into
+    logic programs.
+    """
+
+    @abstractmethod
+    def execute(self, location: Location, code: str) -> None:
+        """
+        Execute the given source code.
+
+        Parameters
+        ----------
+        location
+            The location of the code.
+        code
+            The code to execute.
+        """
+
+    @abstractmethod
+    def call(
+        self, location: Location, name: str, arguments: Iterable[Symbol]
+    ) -> Union[Iterable[Symbol], Symbol]:
+        """
+        Call the function with the given name and arguments.
+
+        Parameters
+        ----------
+        location
+            From where in the logic program the function was called.
+        name
+            The name of the function.
+        arguments
+            The arguments to the function.
+
+        Returns
+        -------
+        The resulting pool of symbols.
+        """
+
+    @abstractmethod
+    def callable(self, name: str) -> bool:
+        """
+        Check there is a function with the given name.
+
+        Parameters
+        ----------
+        name
+            The name of the function.
+
+        Returns
+        -------
+        Whether the function is callable.
+        """
+
+    def main(self, control: Control) -> None:
+        """
+        Run the main function.
+
+        This function exisits primarily for internal purposes and does not need
+        to be implemented.
+
+        Parameters
+        ----------
+        control
+            Control object to pass to the main function.
+        """
+
+
+class _PythonScript(Script):
+    def execute(self, location, code):
+        exec(code, __main__.__dict__, __main__.__dict__)  # pylint: disable=exec-used
+
+    def call(self, location, name, arguments):
+        fun = getattr(__main__, name)
+        return fun(*arguments)
+
+    def callable(self, name):
+        return name in __main__.__dict__ and callable(__main__.__dict__[name])
+
+    def main(self, control):
+        __main__.main(control)  # pylint: disable=c-extension-no-member
+
+
+_PYTHON_SCRIPT = _PythonScript()
+_GLOBAL_SCRIPTS: List[Tuple[Script, Any]] = []
+
+
+@_ffi.def_extern(onerror=_cb_error_top_level, name="pyclingo_script_execute")
+def _pyclingo_script_execute(location, code, data):
+    script: Script = _ffi.from_handle(data)
+    script.execute(_py_location(location), _ffi.string(code).decode())
+    return True
+
+
+@_ffi.def_extern(onerror=_cb_error_top_level, name="pyclingo_script_call")
+def _pyclingo_script_call(
+    location, name, arguments, size, symbol_callback, symbol_callback_data, data
+):
+    script: Script = _ffi.from_handle(data)
+    symbol_callback = _ffi.cast("clingo_symbol_callback_t", symbol_callback)
+    arguments = _ffi.cast("clingo_symbol_t*", arguments)
+    py_name = _ffi.string(name).decode()
+    py_args = [Symbol(arguments[i]) for i in range(size)]
+
+    ret = script.call(_py_location(location), py_name, py_args)
+    symbols = list(ret) if isinstance(ret, IterableABC) else [ret]
+
+    c_symbols = _ffi.new("clingo_symbol_t[]", len(symbols))
+    for i, sym in enumerate(symbols):
+        c_symbols[i] = sym._rep  # pylint: disable=protected-access
+    _handle_error(symbol_callback(c_symbols, len(symbols), symbol_callback_data))
+    return True
+
+
+@_ffi.def_extern(onerror=_cb_error_top_level, name="pyclingo_script_callable")
+def _pyclingo_script_callable(name, ret, data):
+    script: Script = _ffi.from_handle(data)
+    py_name = _ffi.string(name).decode()
+    ret[0] = script.callable(py_name)
+    return True
+
+
+@_ffi.def_extern(onerror=_cb_error_top_level, name="pyclingo_script_main")
+def _pyclingo_script_main(ctl, data):
+    script: Script = _ffi.from_handle(data)
+    script.main(Control(_ffi.cast("clingo_control_t*", ctl)))
+    return True
+
+
+@_ffi.def_extern(onerror=_cb_error_top_level, name="pyclingo_execute")
+def _pyclingo_execute(location, code, data):
+    assert data == _ffi.NULL
+    return _pyclingo_script_execute(
+        _ffi.cast("clingo_location_t*", location), code, _ffi.new_handle(_PYTHON_SCRIPT)
+    )
+
+
+@_ffi.def_extern(onerror=_cb_error_top_level, name="pyclingo_call")
+def _pyclingo_call(
+    location, name, arguments, size, symbol_callback, symbol_callback_data, data
+):
+    assert data == _ffi.NULL
+    return _pyclingo_script_call(
+        _ffi.cast("clingo_location_t*", location),
+        name,
+        arguments,
+        size,
+        symbol_callback,
+        symbol_callback_data,
+        _ffi.new_handle(_PYTHON_SCRIPT),
+    )
+
+
+@_ffi.def_extern(onerror=_cb_error_top_level, name="pyclingo_callable")
+def _pyclingo_callable(name, ret, data):
+    assert data == _ffi.NULL
+    return _pyclingo_script_callable(name, ret, _ffi.new_handle(_PYTHON_SCRIPT))
+
+
+@_ffi.def_extern(onerror=_cb_error_top_level, name="pyclingo_main")
+def _pyclingo_main(ctl, data):
+    assert data == _ffi.NULL
+    return _pyclingo_script_main(
+        _ffi.cast("clingo_control_t*", ctl), _ffi.new_handle(_PYTHON_SCRIPT)
+    )
+
+
+def register_script(name: str, script: Script, version: str = "1.0.0") -> None:
+    """
+    Registers a script language which can then be embedded into a logic
+    program.
+
+    Parameters
+    ----------
+    name
+        The name of the script. This name can then be used in the script
+        statement in a logic program.
+    script
+        The class to register.
+    version
+        The version of the script.
+    """
+    c_version = _c_call("char const*", _lib.clingo_add_string, version.encode())
+    c_script = _ffi.new("clingo_script_t*")
+    c_script[0].execute = _ffi.cast("void*", _lib.pyclingo_script_execute)
+    c_script[0].call = _ffi.cast("void*", _lib.pyclingo_script_call)
+    c_script[0].callable = _ffi.cast("void*", _lib.pyclingo_script_callable)
+    c_script[0].main = _ffi.cast("void*", _lib.pyclingo_script_main)
+    c_script[0].free = _ffi.NULL
+    c_script[0].version = c_version
+    data = _ffi.new_handle(script)
+    _GLOBAL_SCRIPTS.append((script, data))
+    _handle_error(_lib.clingo_register_script(name.encode(), c_script, data))
+
+
+def enable_python() -> None:
+    """
+    This function can be called to enable evaluation of Python scripts in logic
+    programs.
+
+    By default evaluation is only enabled in the clingo executable but not in
+    the Python module.
+    """
+    c_version = _c_call(
+        "char const*", _lib.clingo_add_string, python_version().encode()
+    )
+    c_script = _ffi.new("clingo_script_t*")
+    c_script[0].execute = _ffi.cast("void*", _lib.pyclingo_execute)
+    c_script[0].call = _ffi.cast("void*", _lib.pyclingo_call)
+    c_script[0].callable = _ffi.cast("void*", _lib.pyclingo_callable)
+    c_script[0].main = _ffi.cast("void*", _lib.pyclingo_main)
+    c_script[0].free = _ffi.NULL
+    c_script[0].version = c_version
+    _handle_error(_lib.clingo_register_script("python".encode(), c_script, _ffi.NULL))
+
+
+
+
+
+
+
+

Functions

+
+
+def enable_python() ‑> None +
+
+

This function can be called to enable evaluation of Python scripts in logic +programs.

+

By default evaluation is only enabled in the clingo executable but not in +the Python module.

+
+ +Expand source code + +
def enable_python() -> None:
+    """
+    This function can be called to enable evaluation of Python scripts in logic
+    programs.
+
+    By default evaluation is only enabled in the clingo executable but not in
+    the Python module.
+    """
+    c_version = _c_call(
+        "char const*", _lib.clingo_add_string, python_version().encode()
+    )
+    c_script = _ffi.new("clingo_script_t*")
+    c_script[0].execute = _ffi.cast("void*", _lib.pyclingo_execute)
+    c_script[0].call = _ffi.cast("void*", _lib.pyclingo_call)
+    c_script[0].callable = _ffi.cast("void*", _lib.pyclingo_callable)
+    c_script[0].main = _ffi.cast("void*", _lib.pyclingo_main)
+    c_script[0].free = _ffi.NULL
+    c_script[0].version = c_version
+    _handle_error(_lib.clingo_register_script("python".encode(), c_script, _ffi.NULL))
+
+
+
+def register_script(name: str, script: Script, version: str = '1.0.0') ‑> None +
+
+

Registers a script language which can then be embedded into a logic +program.

+

Parameters

+
+
name
+
The name of the script. This name can then be used in the script +statement in a logic program.
+
script
+
The class to register.
+
version
+
The version of the script.
+
+
+ +Expand source code + +
def register_script(name: str, script: Script, version: str = "1.0.0") -> None:
+    """
+    Registers a script language which can then be embedded into a logic
+    program.
+
+    Parameters
+    ----------
+    name
+        The name of the script. This name can then be used in the script
+        statement in a logic program.
+    script
+        The class to register.
+    version
+        The version of the script.
+    """
+    c_version = _c_call("char const*", _lib.clingo_add_string, version.encode())
+    c_script = _ffi.new("clingo_script_t*")
+    c_script[0].execute = _ffi.cast("void*", _lib.pyclingo_script_execute)
+    c_script[0].call = _ffi.cast("void*", _lib.pyclingo_script_call)
+    c_script[0].callable = _ffi.cast("void*", _lib.pyclingo_script_callable)
+    c_script[0].main = _ffi.cast("void*", _lib.pyclingo_script_main)
+    c_script[0].free = _ffi.NULL
+    c_script[0].version = c_version
+    data = _ffi.new_handle(script)
+    _GLOBAL_SCRIPTS.append((script, data))
+    _handle_error(_lib.clingo_register_script(name.encode(), c_script, data))
+
+
+
+
+
+

Classes

+
+
+class Script +
+
+

This interface can be implemented to embed custom scripting languages into +logic programs.

+
+ +Expand source code + +
class Script(metaclass=ABCMeta):
+    """
+    This interface can be implemented to embed custom scripting languages into
+    logic programs.
+    """
+
+    @abstractmethod
+    def execute(self, location: Location, code: str) -> None:
+        """
+        Execute the given source code.
+
+        Parameters
+        ----------
+        location
+            The location of the code.
+        code
+            The code to execute.
+        """
+
+    @abstractmethod
+    def call(
+        self, location: Location, name: str, arguments: Iterable[Symbol]
+    ) -> Union[Iterable[Symbol], Symbol]:
+        """
+        Call the function with the given name and arguments.
+
+        Parameters
+        ----------
+        location
+            From where in the logic program the function was called.
+        name
+            The name of the function.
+        arguments
+            The arguments to the function.
+
+        Returns
+        -------
+        The resulting pool of symbols.
+        """
+
+    @abstractmethod
+    def callable(self, name: str) -> bool:
+        """
+        Check there is a function with the given name.
+
+        Parameters
+        ----------
+        name
+            The name of the function.
+
+        Returns
+        -------
+        Whether the function is callable.
+        """
+
+    def main(self, control: Control) -> None:
+        """
+        Run the main function.
+
+        This function exisits primarily for internal purposes and does not need
+        to be implemented.
+
+        Parameters
+        ----------
+        control
+            Control object to pass to the main function.
+        """
+
+

Subclasses

+
    +
  • clingo.script._PythonScript
  • +
+

Methods

+
+
+def call(self, location: Location, name: str, arguments: Iterable[Symbol]) ‑> Union[Iterable[Symbol], Symbol] +
+
+

Call the function with the given name and arguments.

+

Parameters

+
+
location
+
From where in the logic program the function was called.
+
name
+
The name of the function.
+
arguments
+
The arguments to the function.
+
+

Returns

+

The resulting pool of symbols.

+
+ +Expand source code + +
@abstractmethod
+def call(
+    self, location: Location, name: str, arguments: Iterable[Symbol]
+) -> Union[Iterable[Symbol], Symbol]:
+    """
+    Call the function with the given name and arguments.
+
+    Parameters
+    ----------
+    location
+        From where in the logic program the function was called.
+    name
+        The name of the function.
+    arguments
+        The arguments to the function.
+
+    Returns
+    -------
+    The resulting pool of symbols.
+    """
+
+
+
+def callable(self, name: str) ‑> bool +
+
+

Check there is a function with the given name.

+

Parameters

+
+
name
+
The name of the function.
+
+

Returns

+

Whether the function is callable.

+
+ +Expand source code + +
@abstractmethod
+def callable(self, name: str) -> bool:
+    """
+    Check there is a function with the given name.
+
+    Parameters
+    ----------
+    name
+        The name of the function.
+
+    Returns
+    -------
+    Whether the function is callable.
+    """
+
+
+
+def execute(self, location: Location, code: str) ‑> None +
+
+

Execute the given source code.

+

Parameters

+
+
location
+
The location of the code.
+
code
+
The code to execute.
+
+
+ +Expand source code + +
@abstractmethod
+def execute(self, location: Location, code: str) -> None:
+    """
+    Execute the given source code.
+
+    Parameters
+    ----------
+    location
+        The location of the code.
+    code
+        The code to execute.
+    """
+
+
+
+def main(self, control: Control) ‑> None +
+
+

Run the main function.

+

This function exisits primarily for internal purposes and does not need +to be implemented.

+

Parameters

+
+
control
+
Control object to pass to the main function.
+
+
+ +Expand source code + +
def main(self, control: Control) -> None:
+    """
+    Run the main function.
+
+    This function exisits primarily for internal purposes and does not need
+    to be implemented.
+
+    Parameters
+    ----------
+    control
+        Control object to pass to the main function.
+    """
+
+
+
+
+
+
+
+ +
+ + + \ No newline at end of file diff --git a/clingo/python-api/5.7/clingo/solving.html b/clingo/python-api/5.7/clingo/solving.html new file mode 100644 index 0000000..685d03b --- /dev/null +++ b/clingo/python-api/5.7/clingo/solving.html @@ -0,0 +1,2143 @@ + + + + + + +clingo.solving API documentation + + + + + + + + + + + +
+
+
+

Module clingo.solving

+
+
+

Functions and classes related to solving.

+

Examples

+

The following example shows how to intercept models with a callback:

+
>>> from clingo import Control
+>>>
+>>> ctl = Control(["0"])
+>>> ctl.add("base", [], "1 { a; b } 1.")
+>>> ctl.ground([("base", [])])
+>>> print(ctl.solve(on_model=print))
+Answer: a
+Answer: b
+SAT
+
+

The following example shows how to yield models:

+
>>> from clingo import Control
+>>>
+>>> ctl = Control(["0"])
+>>> ctl.add("base", [], "1 { a; b } 1.")
+>>> ctl.ground([("base", [])])
+>>> with ctl.solve(yield_=True) as hnd:
+...     for m in hnd:
+...         print(m)
+...     print(hnd.get())
+...
+Answer: a
+Answer: b
+SAT
+
+

The following example shows how to solve asynchronously:

+
>>> from clingo import Control
+>>>
+>>> ctl = Control(["0"])
+>>> ctl.add("base", [], "1 { a; b } 1.")
+>>> ctl.ground([("base", [])])
+>>> with ctl.solve(on_model=print, async_=True) as hnd:
+...     # some computation here
+...     hnd.wait()
+...     print(hnd.get())
+...
+Answer: a
+Answer: b
+SAT
+
+

This example shows how to solve both iteratively and asynchronously:

+
>>> from clingo import Control
+>>>
+>>> ctl = Control(["0"])
+>>> ctl.add("base", [], "1 { a; b } 1.")
+>>> ctl.ground([("base", [])])
+>>> with ctl.solve(yield_=True, async_=True) as hnd:
+...     while True:
+...         hnd.resume()
+...         # some computation here
+...         _ = hnd.wait()
+...         m = hnd.model()
+...         if m is None:
+...             print(hnd.get())
+...             break
+...         print(m)
+b
+a
+a b
+None
+
+
+ +Expand source code + +
"""
+Functions and classes related to solving.
+
+Examples
+--------
+
+The following example shows how to intercept models with a callback:
+
+    >>> from clingo import Control
+    >>>
+    >>> ctl = Control(["0"])
+    >>> ctl.add("base", [], "1 { a; b } 1.")
+    >>> ctl.ground([("base", [])])
+    >>> print(ctl.solve(on_model=print))
+    Answer: a
+    Answer: b
+    SAT
+
+The following example shows how to yield models:
+
+    >>> from clingo import Control
+    >>>
+    >>> ctl = Control(["0"])
+    >>> ctl.add("base", [], "1 { a; b } 1.")
+    >>> ctl.ground([("base", [])])
+    >>> with ctl.solve(yield_=True) as hnd:
+    ...     for m in hnd:
+    ...         print(m)
+    ...     print(hnd.get())
+    ...
+    Answer: a
+    Answer: b
+    SAT
+
+The following example shows how to solve asynchronously:
+
+    >>> from clingo import Control
+    >>>
+    >>> ctl = Control(["0"])
+    >>> ctl.add("base", [], "1 { a; b } 1.")
+    >>> ctl.ground([("base", [])])
+    >>> with ctl.solve(on_model=print, async_=True) as hnd:
+    ...     # some computation here
+    ...     hnd.wait()
+    ...     print(hnd.get())
+    ...
+    Answer: a
+    Answer: b
+    SAT
+
+This example shows how to solve both iteratively and asynchronously:
+
+    >>> from clingo import Control
+    >>>
+    >>> ctl = Control(["0"])
+    >>> ctl.add("base", [], "1 { a; b } 1.")
+    >>> ctl.ground([("base", [])])
+    >>> with ctl.solve(yield_=True, async_=True) as hnd:
+    ...     while True:
+    ...         hnd.resume()
+    ...         # some computation here
+    ...         _ = hnd.wait()
+    ...         m = hnd.model()
+    ...         if m is None:
+    ...             print(hnd.get())
+    ...             break
+    ...         print(m)
+    b
+    a
+    a b
+    None
+"""
+
+from typing import ContextManager, Iterator, List, Optional, Sequence, Tuple, Union
+
+from ._internal import _c_call, _c_call2, _ffi, _handle_error, _lib
+from .util import Slice, SlicedSequence
+from .core import OrderedEnum
+from .symbol import Symbol
+from .symbolic_atoms import SymbolicAtoms
+
+__all__ = ["Model", "ModelType", "SolveControl", "SolveHandle", "SolveResult"]
+
+
+class SolveResult:
+    """
+    Captures the result of a solve call.
+    """
+
+    def __init__(self, rep):
+        self._rep = rep
+
+    @property
+    def exhausted(self) -> bool:
+        """
+        Determine if the search space was exhausted.
+        """
+        return (_lib.clingo_solve_result_exhausted & self._rep) != 0
+
+    @property
+    def interrupted(self) -> bool:
+        """
+        Determine if the search was interrupted.
+        """
+        return (_lib.clingo_solve_result_interrupted & self._rep) != 0
+
+    @property
+    def satisfiable(self) -> Optional[bool]:
+        """
+        `True` if the problem is satisfiable, `False` if the problem is
+        unsatisfiable, or `None` if the satisfiablity is not known.
+        """
+        if (_lib.clingo_solve_result_satisfiable & self._rep) != 0:
+            return True
+        if (_lib.clingo_solve_result_unsatisfiable & self._rep) != 0:
+            return False
+        return None
+
+    @property
+    def unknown(self) -> bool:
+        """
+        Determine if the satisfiablity is not known.
+
+        This is equivalent to satisfiable is None.
+        """
+        return self.satisfiable is None
+
+    @property
+    def unsatisfiable(self) -> Optional[bool]:
+        """
+        `True` if the problem is unsatisfiable, `False` if the problem is
+        satisfiable, or `None` if the satisfiablity is not known.
+        """
+        if (_lib.clingo_solve_result_unsatisfiable & self._rep) != 0:
+            return True
+        if (_lib.clingo_solve_result_satisfiable & self._rep) != 0:
+            return False
+        return None
+
+    def __str__(self):
+        if self.satisfiable:
+            return "SAT"
+        if self.unsatisfiable:
+            return "UNSAT"
+        return "UNKNOWN"
+
+    def __repr__(self):
+        return f"SolveResult({self._rep})"
+
+
+class SolveControl:
+    """
+    Object that allows for controlling a running search.
+    """
+
+    def __init__(self, rep):
+        self._rep = rep
+
+    def add_clause(self, literals: Sequence[Union[Tuple[Symbol, bool], int]]) -> None:
+        """
+        Add a clause that applies to the current solving step during the search.
+
+        Parameters
+        ----------
+        literals
+            List of literals either represented as pairs of symbolic atoms and
+            Booleans or as program literals.
+
+        Notes
+        -----
+        This function can only be called in a model callback or while iterating
+        when using a `SolveHandle`.
+        """
+        atoms = self.symbolic_atoms
+        p_lits = _ffi.new("clingo_literal_t[]", len(literals))
+        for i, lit in enumerate(literals):
+            if isinstance(lit, int):
+                p_lits[i] = lit
+            else:
+                atom = atoms[lit[0]]
+                if atom is not None:
+                    slit = atom.literal
+                else:
+                    slit = -1
+                p_lits[i] = slit if lit[1] else -slit
+
+        _handle_error(
+            _lib.clingo_solve_control_add_clause(self._rep, p_lits, len(literals))
+        )
+
+    def _invert(
+        self, lit: Union[Tuple[Symbol, bool], int]
+    ) -> Union[Tuple[Symbol, bool], int]:
+        if isinstance(lit, int):
+            return -lit
+        return lit[0], not lit[1]
+
+    def add_nogood(self, literals: Sequence[Union[Tuple[Symbol, bool], int]]) -> None:
+        """
+        Equivalent to `SolveControl.add_clause` with the literals inverted.
+        """
+        self.add_clause([self._invert(lit) for lit in literals])
+
+    @property
+    def symbolic_atoms(self) -> SymbolicAtoms:
+        """
+        `clingo.symbolic_atoms.SymbolicAtoms` object to inspect the symbolic atoms.
+        """
+        atoms = _c_call(
+            "clingo_symbolic_atoms_t*",
+            _lib.clingo_solve_control_symbolic_atoms,
+            self._rep,
+        )
+        return SymbolicAtoms(atoms)
+
+
+class ModelType(OrderedEnum):
+    """
+    Enumeration of the different types of models.
+    """
+
+    BraveConsequences = _lib.clingo_model_type_brave_consequences
+    """
+    The model stores the set of brave consequences.
+    """
+    CautiousConsequences = _lib.clingo_model_type_cautious_consequences
+    """
+    The model stores the set of cautious consequences.
+    """
+    StableModel = _lib.clingo_model_type_stable_model
+    """
+    The model captures a stable model.
+    """
+
+
+class _SymbolSequence(Sequence[Symbol]):
+    """
+    Helper class to efficiently store sequences of symbols.
+    """
+
+    def __init__(self, p_symbols):
+        self._p_symbols = p_symbols
+
+    def __len__(self):
+        return len(self._p_symbols)
+
+    def __getitem__(self, slc):
+        if isinstance(slc, slice):
+            return SlicedSequence(self, Slice(slc))
+        if slc < 0:
+            slc += len(self)
+        if slc < 0 or slc >= len(self):
+            raise IndexError("invalid index")
+        return Symbol(self._p_symbols[slc])
+
+    def __iter__(self):
+        for i in range(len(self)):
+            yield Symbol(self._p_symbols[i])
+
+    def __str__(self):
+        return f'[{", ".join(str(sym) for sym in self)}]'
+
+    def __repr__(self):
+        return f'[{", ".join(repr(sym) for sym in self)}]'
+
+
+class Model:
+    """
+    Provides access to a model during a solve call and provides a
+    `SolveContext` object to influence the running search.
+
+    Notes
+    -----
+    The string representation of a model object is similar to the output of
+    models by clingo using the default output.
+
+    `Model` objects cannot be constructed from Python. Instead they are obained
+    during solving (see `Control.solve`). Furthermore, the lifetime of a model
+    object is limited to the scope of the callback it was passed to or until
+    the search for the next model is started. They must not be stored for later
+    use.
+    """
+
+    def __init__(self, rep):
+        self._rep = rep
+
+    def contains(self, atom: Symbol) -> bool:
+        """
+        Efficiently check if an atom is contained in the model.
+
+        Parameters
+        ----------
+        atom
+            The atom to lookup.
+
+        Returns
+        -------
+        Whether the given atom is contained in the model.
+
+        Notes
+        -----
+        The atom must be represented using a function symbol.
+        """
+        # pylint: disable=protected-access
+        return _c_call("bool", _lib.clingo_model_contains, self._rep, atom._rep)
+
+    def extend(self, symbols: Sequence[Symbol]) -> None:
+        """
+        Extend a model with the given symbols.
+
+        Parameters
+        ----------
+        symbols
+            The symbols to add to the model.
+
+        Notes
+        -----
+        This only has an effect if there is an underlying clingo application,
+        which will print the added symbols.
+        """
+        # pylint: disable=protected-access
+        c_symbols = _ffi.new("clingo_symbol_t[]", len(symbols))
+        for i, sym in enumerate(symbols):
+            c_symbols[i] = sym._rep
+        _handle_error(_lib.clingo_model_extend(self._rep, c_symbols, len(symbols)))
+
+    def is_true(self, literal: int) -> bool:
+        """
+        Check if the given program literal is true.
+
+        Parameters
+        ----------
+        literal
+            The given program literal.
+
+        Returns
+        -------
+        Whether the given program literal is true.
+        """
+        return _c_call("bool", _lib.clingo_model_is_true, self._rep, literal)
+
+    def is_consequence(self, literal: int) -> Optional[bool]:
+        """
+        Check if the given program literal is a consequence.
+
+        The function returns `True`, `False`, or `None` if the literal is a
+        consequence, not a consequence, or it is not yet known whether it is a
+        consequence, respectively.
+
+        While enumerating cautious or brave consequences, there is partial
+        information about which literals are consequences. The current state of
+        a literal can be requested using this function. If this function is
+        used during normal model enumeration, the function just returns whether
+        a literal is true of false in the current model.
+
+        Parameters
+        ----------
+        literal
+            The given program literal.
+
+        Returns
+        -------
+        Whether the given program literal is a consequence.
+        """
+        res = _c_call(
+            "clingo_consequence_t", _lib.clingo_model_is_consequence, self._rep, literal
+        )
+        if res == _lib.clingo_consequence_true:
+            return True
+        if res == _lib.clingo_consequence_false:
+            return False
+        return None
+
+    def symbols(
+        self,
+        atoms: bool = False,
+        terms: bool = False,
+        shown: bool = False,
+        theory: bool = False,
+        complement: bool = False,
+    ) -> Sequence[Symbol]:
+        """
+        Return the list of atoms, terms, or CSP assignments in the model.
+
+        Parameters
+        ----------
+        atoms
+            Select all atoms in the model (independent of `#show` statements).
+        terms
+            Select all terms displayed with `#show` statements in the model.
+        shown
+            Select all atoms and terms as outputted by clingo.
+        theory
+            Select atoms added with `Model.extend`.
+        complement
+            Return the complement of the answer set w.r.t. to the atoms known
+            to the grounder.
+
+        Returns
+        -------
+        The selected symbols.
+
+        Notes
+        -----
+        Atoms are represented using functions (`Symbol` objects), and CSP
+        assignments are represented using functions with name `"$"` where the
+        first argument is the name of the CSP variable and the second its
+        value.
+        """
+        show = 0
+        if atoms:
+            show |= _lib.clingo_show_type_atoms
+        if terms:
+            show |= _lib.clingo_show_type_terms
+        if shown:
+            show |= _lib.clingo_show_type_shown
+        if theory:
+            show |= _lib.clingo_show_type_theory
+        if complement:
+            show |= _lib.clingo_show_type_complement
+
+        size = _c_call("size_t", _lib.clingo_model_symbols_size, self._rep, show)
+
+        p_symbols = _ffi.new("clingo_symbol_t[]", size)
+        _handle_error(_lib.clingo_model_symbols(self._rep, show, p_symbols, size))
+
+        return _SymbolSequence(p_symbols)
+
+    def __str__(self):
+        return " ".join(map(str, self.symbols(shown=True)))
+
+    def __repr__(self):
+        return f"Model({self._rep!r})"
+
+    @property
+    def context(self) -> SolveControl:
+        """
+        Object that allows for controlling the running search.
+        """
+        ctl = _c_call("clingo_solve_control_t*", _lib.clingo_model_context, self._rep)
+        return SolveControl(ctl)
+
+    @property
+    def cost(self) -> List[int]:
+        """
+        Return the list of integer cost values of the model.
+
+        The return values correspond to clasp's cost output.
+        """
+        size = _c_call("size_t", _lib.clingo_model_cost_size, self._rep)
+
+        p_costs = _ffi.new("int64_t[]", size)
+        _handle_error(_lib.clingo_model_cost(self._rep, p_costs, size))
+
+        return list(p_costs)
+
+    @property
+    def priority(self) -> List[int]:
+        """
+        Return the priorities of the model's cost values.
+        """
+        size = _c_call("size_t", _lib.clingo_model_cost_size, self._rep)
+
+        p_priorities = _ffi.new("clingo_weight_t[]", size)
+        _handle_error(_lib.clingo_model_priority(self._rep, p_priorities, size))
+
+        return list(p_priorities)
+
+    @property
+    def number(self) -> int:
+        """
+        The running number of the model.
+        """
+        return _c_call("uint64_t", _lib.clingo_model_number, self._rep)
+
+    @property
+    def optimality_proven(self) -> bool:
+        """
+        Whether the optimality of the model has been proven.
+        """
+        return _c_call("bool", _lib.clingo_model_optimality_proven, self._rep)
+
+    @property
+    def thread_id(self) -> int:
+        """
+        The id of the thread which found the model.
+        """
+        return _c_call("clingo_id_t", _lib.clingo_model_thread_id, self._rep)
+
+    @property
+    def type(self) -> ModelType:
+        """
+        The type of the model.
+        """
+        return ModelType(
+            _c_call("clingo_model_type_t", _lib.clingo_model_type, self._rep)
+        )
+
+
+class SolveHandle(ContextManager["SolveHandle"]):
+    """
+    Handle for solve calls.
+
+    They can be used to control solving, like, retrieving models or cancelling
+    a search.
+
+    See Also
+    --------
+    Control.solve
+
+    Notes
+    -----
+    A `SolveHandle` is a context manager and must be used with Python's `with`
+    statement.
+
+    Blocking functions in this object release the GIL. They are not thread-safe
+    though.
+    """
+
+    def __init__(self, rep, handler):
+        self._rep = rep
+        self._handler = handler
+
+    def __iter__(self) -> Iterator[Model]:
+        while True:
+            self.resume()
+            m = self.model()
+            if m is None:
+                break
+            yield m
+
+    def __enter__(self):
+        return self
+
+    def __exit__(self, exc_type, exc_val, exc_tb):
+        _handle_error(_lib.clingo_solve_handle_close(self._rep), self._handler)
+        return False
+
+    def cancel(self) -> None:
+        """
+        Cancel the running search.
+
+        See Also
+        --------
+        clingo.control.Control.interrupt
+        """
+        _handle_error(_lib.clingo_solve_handle_cancel(self._rep), self._handler)
+
+    def core(self) -> List[int]:
+        """
+        The subset of assumptions that made the problem unsatisfiable.
+        """
+        core, size = _c_call2(
+            "clingo_literal_t*",
+            "size_t",
+            _lib.clingo_solve_handle_core,
+            self._rep,
+            handler=self._handler,
+        )
+        return [core[i] for i in range(size)]
+
+    def get(self) -> SolveResult:
+        """
+        Get the result of a solve call.
+
+        If the search is not completed yet, the function blocks until the
+        result is ready.
+        """
+        res = _c_call(
+            "clingo_solve_result_bitset_t",
+            _lib.clingo_solve_handle_get,
+            self._rep,
+            handler=self._handler,
+        )
+        return SolveResult(res)
+
+    def model(self) -> Optional[Model]:
+        """
+        Get the current model if there is any.
+        """
+        p_model = _ffi.new("clingo_model_t**")
+        _handle_error(_lib.clingo_solve_handle_model(self._rep, p_model), self._handler)
+        if p_model[0] == _ffi.NULL:
+            return None
+        return Model(p_model[0])
+
+    def resume(self) -> None:
+        """
+        Discards the last model and starts searching for the next one.
+
+        Notes
+        -----
+        If the search has been started asynchronously, this function starts the
+        search in the background.
+        """
+        _handle_error(_lib.clingo_solve_handle_resume(self._rep), self._handler)
+
+    def wait(self, timeout: Optional[float] = None) -> bool:
+        """
+        Wait for solve call to finish or the next result with an optional timeout.
+
+        If a timeout is given, the behavior of the function changes depending
+        on the sign of the timeout. If a postive timeout is given, the function
+        blocks for the given amount time or until a result is ready. If the
+        timeout is negative, the function will block until a result is ready,
+        which also corresponds to the behavior of the function if no timeout is
+        given. A timeout of zero can be used to poll if a result is ready.
+
+        Parameters
+        ----------
+        timeout
+            If a timeout is given, the function blocks for at most timeout seconds.
+
+        Returns
+        -------
+        Indicates whether the solve call has finished or the next result is ready.
+        """
+        p_res = _ffi.new("bool*")
+        _lib.clingo_solve_handle_wait(
+            self._rep, -1 if timeout is None else timeout, p_res
+        )
+        return p_res[0]
+
+
+
+
+
+
+
+
+
+

Classes

+
+
+class Model +(rep) +
+
+

Provides access to a model during a solve call and provides a +SolveContext object to influence the running search.

+

Notes

+

The string representation of a model object is similar to the output of +models by clingo using the default output.

+

Model objects cannot be constructed from Python. Instead they are obained +during solving (see Control.solve). Furthermore, the lifetime of a model +object is limited to the scope of the callback it was passed to or until +the search for the next model is started. They must not be stored for later +use.

+
+ +Expand source code + +
class Model:
+    """
+    Provides access to a model during a solve call and provides a
+    `SolveContext` object to influence the running search.
+
+    Notes
+    -----
+    The string representation of a model object is similar to the output of
+    models by clingo using the default output.
+
+    `Model` objects cannot be constructed from Python. Instead they are obained
+    during solving (see `Control.solve`). Furthermore, the lifetime of a model
+    object is limited to the scope of the callback it was passed to or until
+    the search for the next model is started. They must not be stored for later
+    use.
+    """
+
+    def __init__(self, rep):
+        self._rep = rep
+
+    def contains(self, atom: Symbol) -> bool:
+        """
+        Efficiently check if an atom is contained in the model.
+
+        Parameters
+        ----------
+        atom
+            The atom to lookup.
+
+        Returns
+        -------
+        Whether the given atom is contained in the model.
+
+        Notes
+        -----
+        The atom must be represented using a function symbol.
+        """
+        # pylint: disable=protected-access
+        return _c_call("bool", _lib.clingo_model_contains, self._rep, atom._rep)
+
+    def extend(self, symbols: Sequence[Symbol]) -> None:
+        """
+        Extend a model with the given symbols.
+
+        Parameters
+        ----------
+        symbols
+            The symbols to add to the model.
+
+        Notes
+        -----
+        This only has an effect if there is an underlying clingo application,
+        which will print the added symbols.
+        """
+        # pylint: disable=protected-access
+        c_symbols = _ffi.new("clingo_symbol_t[]", len(symbols))
+        for i, sym in enumerate(symbols):
+            c_symbols[i] = sym._rep
+        _handle_error(_lib.clingo_model_extend(self._rep, c_symbols, len(symbols)))
+
+    def is_true(self, literal: int) -> bool:
+        """
+        Check if the given program literal is true.
+
+        Parameters
+        ----------
+        literal
+            The given program literal.
+
+        Returns
+        -------
+        Whether the given program literal is true.
+        """
+        return _c_call("bool", _lib.clingo_model_is_true, self._rep, literal)
+
+    def is_consequence(self, literal: int) -> Optional[bool]:
+        """
+        Check if the given program literal is a consequence.
+
+        The function returns `True`, `False`, or `None` if the literal is a
+        consequence, not a consequence, or it is not yet known whether it is a
+        consequence, respectively.
+
+        While enumerating cautious or brave consequences, there is partial
+        information about which literals are consequences. The current state of
+        a literal can be requested using this function. If this function is
+        used during normal model enumeration, the function just returns whether
+        a literal is true of false in the current model.
+
+        Parameters
+        ----------
+        literal
+            The given program literal.
+
+        Returns
+        -------
+        Whether the given program literal is a consequence.
+        """
+        res = _c_call(
+            "clingo_consequence_t", _lib.clingo_model_is_consequence, self._rep, literal
+        )
+        if res == _lib.clingo_consequence_true:
+            return True
+        if res == _lib.clingo_consequence_false:
+            return False
+        return None
+
+    def symbols(
+        self,
+        atoms: bool = False,
+        terms: bool = False,
+        shown: bool = False,
+        theory: bool = False,
+        complement: bool = False,
+    ) -> Sequence[Symbol]:
+        """
+        Return the list of atoms, terms, or CSP assignments in the model.
+
+        Parameters
+        ----------
+        atoms
+            Select all atoms in the model (independent of `#show` statements).
+        terms
+            Select all terms displayed with `#show` statements in the model.
+        shown
+            Select all atoms and terms as outputted by clingo.
+        theory
+            Select atoms added with `Model.extend`.
+        complement
+            Return the complement of the answer set w.r.t. to the atoms known
+            to the grounder.
+
+        Returns
+        -------
+        The selected symbols.
+
+        Notes
+        -----
+        Atoms are represented using functions (`Symbol` objects), and CSP
+        assignments are represented using functions with name `"$"` where the
+        first argument is the name of the CSP variable and the second its
+        value.
+        """
+        show = 0
+        if atoms:
+            show |= _lib.clingo_show_type_atoms
+        if terms:
+            show |= _lib.clingo_show_type_terms
+        if shown:
+            show |= _lib.clingo_show_type_shown
+        if theory:
+            show |= _lib.clingo_show_type_theory
+        if complement:
+            show |= _lib.clingo_show_type_complement
+
+        size = _c_call("size_t", _lib.clingo_model_symbols_size, self._rep, show)
+
+        p_symbols = _ffi.new("clingo_symbol_t[]", size)
+        _handle_error(_lib.clingo_model_symbols(self._rep, show, p_symbols, size))
+
+        return _SymbolSequence(p_symbols)
+
+    def __str__(self):
+        return " ".join(map(str, self.symbols(shown=True)))
+
+    def __repr__(self):
+        return f"Model({self._rep!r})"
+
+    @property
+    def context(self) -> SolveControl:
+        """
+        Object that allows for controlling the running search.
+        """
+        ctl = _c_call("clingo_solve_control_t*", _lib.clingo_model_context, self._rep)
+        return SolveControl(ctl)
+
+    @property
+    def cost(self) -> List[int]:
+        """
+        Return the list of integer cost values of the model.
+
+        The return values correspond to clasp's cost output.
+        """
+        size = _c_call("size_t", _lib.clingo_model_cost_size, self._rep)
+
+        p_costs = _ffi.new("int64_t[]", size)
+        _handle_error(_lib.clingo_model_cost(self._rep, p_costs, size))
+
+        return list(p_costs)
+
+    @property
+    def priority(self) -> List[int]:
+        """
+        Return the priorities of the model's cost values.
+        """
+        size = _c_call("size_t", _lib.clingo_model_cost_size, self._rep)
+
+        p_priorities = _ffi.new("clingo_weight_t[]", size)
+        _handle_error(_lib.clingo_model_priority(self._rep, p_priorities, size))
+
+        return list(p_priorities)
+
+    @property
+    def number(self) -> int:
+        """
+        The running number of the model.
+        """
+        return _c_call("uint64_t", _lib.clingo_model_number, self._rep)
+
+    @property
+    def optimality_proven(self) -> bool:
+        """
+        Whether the optimality of the model has been proven.
+        """
+        return _c_call("bool", _lib.clingo_model_optimality_proven, self._rep)
+
+    @property
+    def thread_id(self) -> int:
+        """
+        The id of the thread which found the model.
+        """
+        return _c_call("clingo_id_t", _lib.clingo_model_thread_id, self._rep)
+
+    @property
+    def type(self) -> ModelType:
+        """
+        The type of the model.
+        """
+        return ModelType(
+            _c_call("clingo_model_type_t", _lib.clingo_model_type, self._rep)
+        )
+
+

Instance variables

+
+
var contextSolveControl
+
+

Object that allows for controlling the running search.

+
+ +Expand source code + +
@property
+def context(self) -> SolveControl:
+    """
+    Object that allows for controlling the running search.
+    """
+    ctl = _c_call("clingo_solve_control_t*", _lib.clingo_model_context, self._rep)
+    return SolveControl(ctl)
+
+
+
var cost : List[int]
+
+

Return the list of integer cost values of the model.

+

The return values correspond to clasp's cost output.

+
+ +Expand source code + +
@property
+def cost(self) -> List[int]:
+    """
+    Return the list of integer cost values of the model.
+
+    The return values correspond to clasp's cost output.
+    """
+    size = _c_call("size_t", _lib.clingo_model_cost_size, self._rep)
+
+    p_costs = _ffi.new("int64_t[]", size)
+    _handle_error(_lib.clingo_model_cost(self._rep, p_costs, size))
+
+    return list(p_costs)
+
+
+
var number : int
+
+

The running number of the model.

+
+ +Expand source code + +
@property
+def number(self) -> int:
+    """
+    The running number of the model.
+    """
+    return _c_call("uint64_t", _lib.clingo_model_number, self._rep)
+
+
+
var optimality_proven : bool
+
+

Whether the optimality of the model has been proven.

+
+ +Expand source code + +
@property
+def optimality_proven(self) -> bool:
+    """
+    Whether the optimality of the model has been proven.
+    """
+    return _c_call("bool", _lib.clingo_model_optimality_proven, self._rep)
+
+
+
var priority : List[int]
+
+

Return the priorities of the model's cost values.

+
+ +Expand source code + +
@property
+def priority(self) -> List[int]:
+    """
+    Return the priorities of the model's cost values.
+    """
+    size = _c_call("size_t", _lib.clingo_model_cost_size, self._rep)
+
+    p_priorities = _ffi.new("clingo_weight_t[]", size)
+    _handle_error(_lib.clingo_model_priority(self._rep, p_priorities, size))
+
+    return list(p_priorities)
+
+
+
var thread_id : int
+
+

The id of the thread which found the model.

+
+ +Expand source code + +
@property
+def thread_id(self) -> int:
+    """
+    The id of the thread which found the model.
+    """
+    return _c_call("clingo_id_t", _lib.clingo_model_thread_id, self._rep)
+
+
+
var typeModelType
+
+

The type of the model.

+
+ +Expand source code + +
@property
+def type(self) -> ModelType:
+    """
+    The type of the model.
+    """
+    return ModelType(
+        _c_call("clingo_model_type_t", _lib.clingo_model_type, self._rep)
+    )
+
+
+
+

Methods

+
+
+def contains(self, atom: Symbol) ‑> bool +
+
+

Efficiently check if an atom is contained in the model.

+

Parameters

+
+
atom
+
The atom to lookup.
+
+

Returns

+

Whether the given atom is contained in the model.

+

Notes

+

The atom must be represented using a function symbol.

+
+ +Expand source code + +
def contains(self, atom: Symbol) -> bool:
+    """
+    Efficiently check if an atom is contained in the model.
+
+    Parameters
+    ----------
+    atom
+        The atom to lookup.
+
+    Returns
+    -------
+    Whether the given atom is contained in the model.
+
+    Notes
+    -----
+    The atom must be represented using a function symbol.
+    """
+    # pylint: disable=protected-access
+    return _c_call("bool", _lib.clingo_model_contains, self._rep, atom._rep)
+
+
+
+def extend(self, symbols: Sequence[Symbol]) ‑> None +
+
+

Extend a model with the given symbols.

+

Parameters

+
+
symbols
+
The symbols to add to the model.
+
+

Notes

+

This only has an effect if there is an underlying clingo application, +which will print the added symbols.

+
+ +Expand source code + +
def extend(self, symbols: Sequence[Symbol]) -> None:
+    """
+    Extend a model with the given symbols.
+
+    Parameters
+    ----------
+    symbols
+        The symbols to add to the model.
+
+    Notes
+    -----
+    This only has an effect if there is an underlying clingo application,
+    which will print the added symbols.
+    """
+    # pylint: disable=protected-access
+    c_symbols = _ffi.new("clingo_symbol_t[]", len(symbols))
+    for i, sym in enumerate(symbols):
+        c_symbols[i] = sym._rep
+    _handle_error(_lib.clingo_model_extend(self._rep, c_symbols, len(symbols)))
+
+
+
+def is_consequence(self, literal: int) ‑> Optional[bool] +
+
+

Check if the given program literal is a consequence.

+

The function returns True, False, or None if the literal is a +consequence, not a consequence, or it is not yet known whether it is a +consequence, respectively.

+

While enumerating cautious or brave consequences, there is partial +information about which literals are consequences. The current state of +a literal can be requested using this function. If this function is +used during normal model enumeration, the function just returns whether +a literal is true of false in the current model.

+

Parameters

+
+
literal
+
The given program literal.
+
+

Returns

+

Whether the given program literal is a consequence.

+
+ +Expand source code + +
def is_consequence(self, literal: int) -> Optional[bool]:
+    """
+    Check if the given program literal is a consequence.
+
+    The function returns `True`, `False`, or `None` if the literal is a
+    consequence, not a consequence, or it is not yet known whether it is a
+    consequence, respectively.
+
+    While enumerating cautious or brave consequences, there is partial
+    information about which literals are consequences. The current state of
+    a literal can be requested using this function. If this function is
+    used during normal model enumeration, the function just returns whether
+    a literal is true of false in the current model.
+
+    Parameters
+    ----------
+    literal
+        The given program literal.
+
+    Returns
+    -------
+    Whether the given program literal is a consequence.
+    """
+    res = _c_call(
+        "clingo_consequence_t", _lib.clingo_model_is_consequence, self._rep, literal
+    )
+    if res == _lib.clingo_consequence_true:
+        return True
+    if res == _lib.clingo_consequence_false:
+        return False
+    return None
+
+
+
+def is_true(self, literal: int) ‑> bool +
+
+

Check if the given program literal is true.

+

Parameters

+
+
literal
+
The given program literal.
+
+

Returns

+

Whether the given program literal is true.

+
+ +Expand source code + +
def is_true(self, literal: int) -> bool:
+    """
+    Check if the given program literal is true.
+
+    Parameters
+    ----------
+    literal
+        The given program literal.
+
+    Returns
+    -------
+    Whether the given program literal is true.
+    """
+    return _c_call("bool", _lib.clingo_model_is_true, self._rep, literal)
+
+
+
+def symbols(self, atoms: bool = False, terms: bool = False, shown: bool = False, theory: bool = False, complement: bool = False) ‑> Sequence[Symbol] +
+
+

Return the list of atoms, terms, or CSP assignments in the model.

+

Parameters

+
+
atoms
+
Select all atoms in the model (independent of #show statements).
+
terms
+
Select all terms displayed with #show statements in the model.
+
shown
+
Select all atoms and terms as outputted by clingo.
+
theory
+
Select atoms added with Model.extend().
+
complement
+
Return the complement of the answer set w.r.t. to the atoms known +to the grounder.
+
+

Returns

+

The selected symbols.

+

Notes

+

Atoms are represented using functions (Symbol objects), and CSP +assignments are represented using functions with name "$" where the +first argument is the name of the CSP variable and the second its +value.

+
+ +Expand source code + +
def symbols(
+    self,
+    atoms: bool = False,
+    terms: bool = False,
+    shown: bool = False,
+    theory: bool = False,
+    complement: bool = False,
+) -> Sequence[Symbol]:
+    """
+    Return the list of atoms, terms, or CSP assignments in the model.
+
+    Parameters
+    ----------
+    atoms
+        Select all atoms in the model (independent of `#show` statements).
+    terms
+        Select all terms displayed with `#show` statements in the model.
+    shown
+        Select all atoms and terms as outputted by clingo.
+    theory
+        Select atoms added with `Model.extend`.
+    complement
+        Return the complement of the answer set w.r.t. to the atoms known
+        to the grounder.
+
+    Returns
+    -------
+    The selected symbols.
+
+    Notes
+    -----
+    Atoms are represented using functions (`Symbol` objects), and CSP
+    assignments are represented using functions with name `"$"` where the
+    first argument is the name of the CSP variable and the second its
+    value.
+    """
+    show = 0
+    if atoms:
+        show |= _lib.clingo_show_type_atoms
+    if terms:
+        show |= _lib.clingo_show_type_terms
+    if shown:
+        show |= _lib.clingo_show_type_shown
+    if theory:
+        show |= _lib.clingo_show_type_theory
+    if complement:
+        show |= _lib.clingo_show_type_complement
+
+    size = _c_call("size_t", _lib.clingo_model_symbols_size, self._rep, show)
+
+    p_symbols = _ffi.new("clingo_symbol_t[]", size)
+    _handle_error(_lib.clingo_model_symbols(self._rep, show, p_symbols, size))
+
+    return _SymbolSequence(p_symbols)
+
+
+
+
+
+class ModelType +(value, names=None, *, module=None, qualname=None, type=None, start=1) +
+
+

Enumeration of the different types of models.

+
+ +Expand source code + +
class ModelType(OrderedEnum):
+    """
+    Enumeration of the different types of models.
+    """
+
+    BraveConsequences = _lib.clingo_model_type_brave_consequences
+    """
+    The model stores the set of brave consequences.
+    """
+    CautiousConsequences = _lib.clingo_model_type_cautious_consequences
+    """
+    The model stores the set of cautious consequences.
+    """
+    StableModel = _lib.clingo_model_type_stable_model
+    """
+    The model captures a stable model.
+    """
+
+

Ancestors

+ +

Class variables

+
+
var BraveConsequences
+
+

The model stores the set of brave consequences.

+
+
var CautiousConsequences
+
+

The model stores the set of cautious consequences.

+
+
var StableModel
+
+

The model captures a stable model.

+
+
+
+
+class SolveControl +(rep) +
+
+

Object that allows for controlling a running search.

+
+ +Expand source code + +
class SolveControl:
+    """
+    Object that allows for controlling a running search.
+    """
+
+    def __init__(self, rep):
+        self._rep = rep
+
+    def add_clause(self, literals: Sequence[Union[Tuple[Symbol, bool], int]]) -> None:
+        """
+        Add a clause that applies to the current solving step during the search.
+
+        Parameters
+        ----------
+        literals
+            List of literals either represented as pairs of symbolic atoms and
+            Booleans or as program literals.
+
+        Notes
+        -----
+        This function can only be called in a model callback or while iterating
+        when using a `SolveHandle`.
+        """
+        atoms = self.symbolic_atoms
+        p_lits = _ffi.new("clingo_literal_t[]", len(literals))
+        for i, lit in enumerate(literals):
+            if isinstance(lit, int):
+                p_lits[i] = lit
+            else:
+                atom = atoms[lit[0]]
+                if atom is not None:
+                    slit = atom.literal
+                else:
+                    slit = -1
+                p_lits[i] = slit if lit[1] else -slit
+
+        _handle_error(
+            _lib.clingo_solve_control_add_clause(self._rep, p_lits, len(literals))
+        )
+
+    def _invert(
+        self, lit: Union[Tuple[Symbol, bool], int]
+    ) -> Union[Tuple[Symbol, bool], int]:
+        if isinstance(lit, int):
+            return -lit
+        return lit[0], not lit[1]
+
+    def add_nogood(self, literals: Sequence[Union[Tuple[Symbol, bool], int]]) -> None:
+        """
+        Equivalent to `SolveControl.add_clause` with the literals inverted.
+        """
+        self.add_clause([self._invert(lit) for lit in literals])
+
+    @property
+    def symbolic_atoms(self) -> SymbolicAtoms:
+        """
+        `clingo.symbolic_atoms.SymbolicAtoms` object to inspect the symbolic atoms.
+        """
+        atoms = _c_call(
+            "clingo_symbolic_atoms_t*",
+            _lib.clingo_solve_control_symbolic_atoms,
+            self._rep,
+        )
+        return SymbolicAtoms(atoms)
+
+

Instance variables

+
+
var symbolic_atomsSymbolicAtoms
+
+

SymbolicAtoms object to inspect the symbolic atoms.

+
+ +Expand source code + +
@property
+def symbolic_atoms(self) -> SymbolicAtoms:
+    """
+    `clingo.symbolic_atoms.SymbolicAtoms` object to inspect the symbolic atoms.
+    """
+    atoms = _c_call(
+        "clingo_symbolic_atoms_t*",
+        _lib.clingo_solve_control_symbolic_atoms,
+        self._rep,
+    )
+    return SymbolicAtoms(atoms)
+
+
+
+

Methods

+
+
+def add_clause(self, literals: Sequence[Union[Tuple[Symbol, bool], int]]) ‑> None +
+
+

Add a clause that applies to the current solving step during the search.

+

Parameters

+
+
literals
+
List of literals either represented as pairs of symbolic atoms and +Booleans or as program literals.
+
+

Notes

+

This function can only be called in a model callback or while iterating +when using a SolveHandle.

+
+ +Expand source code + +
def add_clause(self, literals: Sequence[Union[Tuple[Symbol, bool], int]]) -> None:
+    """
+    Add a clause that applies to the current solving step during the search.
+
+    Parameters
+    ----------
+    literals
+        List of literals either represented as pairs of symbolic atoms and
+        Booleans or as program literals.
+
+    Notes
+    -----
+    This function can only be called in a model callback or while iterating
+    when using a `SolveHandle`.
+    """
+    atoms = self.symbolic_atoms
+    p_lits = _ffi.new("clingo_literal_t[]", len(literals))
+    for i, lit in enumerate(literals):
+        if isinstance(lit, int):
+            p_lits[i] = lit
+        else:
+            atom = atoms[lit[0]]
+            if atom is not None:
+                slit = atom.literal
+            else:
+                slit = -1
+            p_lits[i] = slit if lit[1] else -slit
+
+    _handle_error(
+        _lib.clingo_solve_control_add_clause(self._rep, p_lits, len(literals))
+    )
+
+
+
+def add_nogood(self, literals: Sequence[Union[Tuple[Symbol, bool], int]]) ‑> None +
+
+

Equivalent to SolveControl.add_clause() with the literals inverted.

+
+ +Expand source code + +
def add_nogood(self, literals: Sequence[Union[Tuple[Symbol, bool], int]]) -> None:
+    """
+    Equivalent to `SolveControl.add_clause` with the literals inverted.
+    """
+    self.add_clause([self._invert(lit) for lit in literals])
+
+
+
+
+
+class SolveHandle +(rep, handler) +
+
+

Handle for solve calls.

+

They can be used to control solving, like, retrieving models or cancelling +a search.

+

See Also

+

Control.solve

+

Notes

+

A SolveHandle is a context manager and must be used with Python's with +statement.

+

Blocking functions in this object release the GIL. They are not thread-safe +though.

+
+ +Expand source code + +
class SolveHandle(ContextManager["SolveHandle"]):
+    """
+    Handle for solve calls.
+
+    They can be used to control solving, like, retrieving models or cancelling
+    a search.
+
+    See Also
+    --------
+    Control.solve
+
+    Notes
+    -----
+    A `SolveHandle` is a context manager and must be used with Python's `with`
+    statement.
+
+    Blocking functions in this object release the GIL. They are not thread-safe
+    though.
+    """
+
+    def __init__(self, rep, handler):
+        self._rep = rep
+        self._handler = handler
+
+    def __iter__(self) -> Iterator[Model]:
+        while True:
+            self.resume()
+            m = self.model()
+            if m is None:
+                break
+            yield m
+
+    def __enter__(self):
+        return self
+
+    def __exit__(self, exc_type, exc_val, exc_tb):
+        _handle_error(_lib.clingo_solve_handle_close(self._rep), self._handler)
+        return False
+
+    def cancel(self) -> None:
+        """
+        Cancel the running search.
+
+        See Also
+        --------
+        clingo.control.Control.interrupt
+        """
+        _handle_error(_lib.clingo_solve_handle_cancel(self._rep), self._handler)
+
+    def core(self) -> List[int]:
+        """
+        The subset of assumptions that made the problem unsatisfiable.
+        """
+        core, size = _c_call2(
+            "clingo_literal_t*",
+            "size_t",
+            _lib.clingo_solve_handle_core,
+            self._rep,
+            handler=self._handler,
+        )
+        return [core[i] for i in range(size)]
+
+    def get(self) -> SolveResult:
+        """
+        Get the result of a solve call.
+
+        If the search is not completed yet, the function blocks until the
+        result is ready.
+        """
+        res = _c_call(
+            "clingo_solve_result_bitset_t",
+            _lib.clingo_solve_handle_get,
+            self._rep,
+            handler=self._handler,
+        )
+        return SolveResult(res)
+
+    def model(self) -> Optional[Model]:
+        """
+        Get the current model if there is any.
+        """
+        p_model = _ffi.new("clingo_model_t**")
+        _handle_error(_lib.clingo_solve_handle_model(self._rep, p_model), self._handler)
+        if p_model[0] == _ffi.NULL:
+            return None
+        return Model(p_model[0])
+
+    def resume(self) -> None:
+        """
+        Discards the last model and starts searching for the next one.
+
+        Notes
+        -----
+        If the search has been started asynchronously, this function starts the
+        search in the background.
+        """
+        _handle_error(_lib.clingo_solve_handle_resume(self._rep), self._handler)
+
+    def wait(self, timeout: Optional[float] = None) -> bool:
+        """
+        Wait for solve call to finish or the next result with an optional timeout.
+
+        If a timeout is given, the behavior of the function changes depending
+        on the sign of the timeout. If a postive timeout is given, the function
+        blocks for the given amount time or until a result is ready. If the
+        timeout is negative, the function will block until a result is ready,
+        which also corresponds to the behavior of the function if no timeout is
+        given. A timeout of zero can be used to poll if a result is ready.
+
+        Parameters
+        ----------
+        timeout
+            If a timeout is given, the function blocks for at most timeout seconds.
+
+        Returns
+        -------
+        Indicates whether the solve call has finished or the next result is ready.
+        """
+        p_res = _ffi.new("bool*")
+        _lib.clingo_solve_handle_wait(
+            self._rep, -1 if timeout is None else timeout, p_res
+        )
+        return p_res[0]
+
+

Ancestors

+
    +
  • contextlib.AbstractContextManager
  • +
  • abc.ABC
  • +
  • typing.Generic
  • +
+

Methods

+
+
+def cancel(self) ‑> None +
+
+

Cancel the running search.

+

See Also

+

Control.interrupt()

+
+ +Expand source code + +
def cancel(self) -> None:
+    """
+    Cancel the running search.
+
+    See Also
+    --------
+    clingo.control.Control.interrupt
+    """
+    _handle_error(_lib.clingo_solve_handle_cancel(self._rep), self._handler)
+
+
+
+def core(self) ‑> List[int] +
+
+

The subset of assumptions that made the problem unsatisfiable.

+
+ +Expand source code + +
def core(self) -> List[int]:
+    """
+    The subset of assumptions that made the problem unsatisfiable.
+    """
+    core, size = _c_call2(
+        "clingo_literal_t*",
+        "size_t",
+        _lib.clingo_solve_handle_core,
+        self._rep,
+        handler=self._handler,
+    )
+    return [core[i] for i in range(size)]
+
+
+
+def get(self) ‑> SolveResult +
+
+

Get the result of a solve call.

+

If the search is not completed yet, the function blocks until the +result is ready.

+
+ +Expand source code + +
def get(self) -> SolveResult:
+    """
+    Get the result of a solve call.
+
+    If the search is not completed yet, the function blocks until the
+    result is ready.
+    """
+    res = _c_call(
+        "clingo_solve_result_bitset_t",
+        _lib.clingo_solve_handle_get,
+        self._rep,
+        handler=self._handler,
+    )
+    return SolveResult(res)
+
+
+
+def model(self) ‑> Optional[Model] +
+
+

Get the current model if there is any.

+
+ +Expand source code + +
def model(self) -> Optional[Model]:
+    """
+    Get the current model if there is any.
+    """
+    p_model = _ffi.new("clingo_model_t**")
+    _handle_error(_lib.clingo_solve_handle_model(self._rep, p_model), self._handler)
+    if p_model[0] == _ffi.NULL:
+        return None
+    return Model(p_model[0])
+
+
+
+def resume(self) ‑> None +
+
+

Discards the last model and starts searching for the next one.

+

Notes

+

If the search has been started asynchronously, this function starts the +search in the background.

+
+ +Expand source code + +
def resume(self) -> None:
+    """
+    Discards the last model and starts searching for the next one.
+
+    Notes
+    -----
+    If the search has been started asynchronously, this function starts the
+    search in the background.
+    """
+    _handle_error(_lib.clingo_solve_handle_resume(self._rep), self._handler)
+
+
+
+def wait(self, timeout: Optional[float] = None) ‑> bool +
+
+

Wait for solve call to finish or the next result with an optional timeout.

+

If a timeout is given, the behavior of the function changes depending +on the sign of the timeout. If a postive timeout is given, the function +blocks for the given amount time or until a result is ready. If the +timeout is negative, the function will block until a result is ready, +which also corresponds to the behavior of the function if no timeout is +given. A timeout of zero can be used to poll if a result is ready.

+

Parameters

+
+
timeout
+
If a timeout is given, the function blocks for at most timeout seconds.
+
+

Returns

+

Indicates whether the solve call has finished or the next result is ready.

+
+ +Expand source code + +
def wait(self, timeout: Optional[float] = None) -> bool:
+    """
+    Wait for solve call to finish or the next result with an optional timeout.
+
+    If a timeout is given, the behavior of the function changes depending
+    on the sign of the timeout. If a postive timeout is given, the function
+    blocks for the given amount time or until a result is ready. If the
+    timeout is negative, the function will block until a result is ready,
+    which also corresponds to the behavior of the function if no timeout is
+    given. A timeout of zero can be used to poll if a result is ready.
+
+    Parameters
+    ----------
+    timeout
+        If a timeout is given, the function blocks for at most timeout seconds.
+
+    Returns
+    -------
+    Indicates whether the solve call has finished or the next result is ready.
+    """
+    p_res = _ffi.new("bool*")
+    _lib.clingo_solve_handle_wait(
+        self._rep, -1 if timeout is None else timeout, p_res
+    )
+    return p_res[0]
+
+
+
+
+
+class SolveResult +(rep) +
+
+

Captures the result of a solve call.

+
+ +Expand source code + +
class SolveResult:
+    """
+    Captures the result of a solve call.
+    """
+
+    def __init__(self, rep):
+        self._rep = rep
+
+    @property
+    def exhausted(self) -> bool:
+        """
+        Determine if the search space was exhausted.
+        """
+        return (_lib.clingo_solve_result_exhausted & self._rep) != 0
+
+    @property
+    def interrupted(self) -> bool:
+        """
+        Determine if the search was interrupted.
+        """
+        return (_lib.clingo_solve_result_interrupted & self._rep) != 0
+
+    @property
+    def satisfiable(self) -> Optional[bool]:
+        """
+        `True` if the problem is satisfiable, `False` if the problem is
+        unsatisfiable, or `None` if the satisfiablity is not known.
+        """
+        if (_lib.clingo_solve_result_satisfiable & self._rep) != 0:
+            return True
+        if (_lib.clingo_solve_result_unsatisfiable & self._rep) != 0:
+            return False
+        return None
+
+    @property
+    def unknown(self) -> bool:
+        """
+        Determine if the satisfiablity is not known.
+
+        This is equivalent to satisfiable is None.
+        """
+        return self.satisfiable is None
+
+    @property
+    def unsatisfiable(self) -> Optional[bool]:
+        """
+        `True` if the problem is unsatisfiable, `False` if the problem is
+        satisfiable, or `None` if the satisfiablity is not known.
+        """
+        if (_lib.clingo_solve_result_unsatisfiable & self._rep) != 0:
+            return True
+        if (_lib.clingo_solve_result_satisfiable & self._rep) != 0:
+            return False
+        return None
+
+    def __str__(self):
+        if self.satisfiable:
+            return "SAT"
+        if self.unsatisfiable:
+            return "UNSAT"
+        return "UNKNOWN"
+
+    def __repr__(self):
+        return f"SolveResult({self._rep})"
+
+

Instance variables

+
+
var exhausted : bool
+
+

Determine if the search space was exhausted.

+
+ +Expand source code + +
@property
+def exhausted(self) -> bool:
+    """
+    Determine if the search space was exhausted.
+    """
+    return (_lib.clingo_solve_result_exhausted & self._rep) != 0
+
+
+
var interrupted : bool
+
+

Determine if the search was interrupted.

+
+ +Expand source code + +
@property
+def interrupted(self) -> bool:
+    """
+    Determine if the search was interrupted.
+    """
+    return (_lib.clingo_solve_result_interrupted & self._rep) != 0
+
+
+
var satisfiable : Optional[bool]
+
+

True if the problem is satisfiable, False if the problem is +unsatisfiable, or None if the satisfiablity is not known.

+
+ +Expand source code + +
@property
+def satisfiable(self) -> Optional[bool]:
+    """
+    `True` if the problem is satisfiable, `False` if the problem is
+    unsatisfiable, or `None` if the satisfiablity is not known.
+    """
+    if (_lib.clingo_solve_result_satisfiable & self._rep) != 0:
+        return True
+    if (_lib.clingo_solve_result_unsatisfiable & self._rep) != 0:
+        return False
+    return None
+
+
+
var unknown : bool
+
+

Determine if the satisfiablity is not known.

+

This is equivalent to satisfiable is None.

+
+ +Expand source code + +
@property
+def unknown(self) -> bool:
+    """
+    Determine if the satisfiablity is not known.
+
+    This is equivalent to satisfiable is None.
+    """
+    return self.satisfiable is None
+
+
+
var unsatisfiable : Optional[bool]
+
+

True if the problem is unsatisfiable, False if the problem is +satisfiable, or None if the satisfiablity is not known.

+
+ +Expand source code + +
@property
+def unsatisfiable(self) -> Optional[bool]:
+    """
+    `True` if the problem is unsatisfiable, `False` if the problem is
+    satisfiable, or `None` if the satisfiablity is not known.
+    """
+    if (_lib.clingo_solve_result_unsatisfiable & self._rep) != 0:
+        return True
+    if (_lib.clingo_solve_result_satisfiable & self._rep) != 0:
+        return False
+    return None
+
+
+
+
+
+
+
+ +
+ + + \ No newline at end of file diff --git a/clingo/python-api/5.7/clingo/statistics.html b/clingo/python-api/5.7/clingo/statistics.html new file mode 100644 index 0000000..a59e047 --- /dev/null +++ b/clingo/python-api/5.7/clingo/statistics.html @@ -0,0 +1,989 @@ + + + + + + +clingo.statistics API documentation + + + + + + + + + + + +
+
+
+

Module clingo.statistics

+
+
+

Functions and classes related to statistics.

+

Examples

+

The following example shows how to add custom statistics and dump the +statistics in json format:

+
>>> from json import dumps
+>>> from clingo.control import Control
+>>>
+>>> def on_statistics(step, accu):
+...     accu["example"] = 42
+...
+>>> ctl = Control(['--stats'])
+>>> ctl.add("base", [], "{a}.")
+>>> ctl.ground([("base", [])])
+>>> print(ctl.solve(on_statistics=on_statistics))
+SAT
+>>> print(dumps(ctl.statistics['user_accu'], sort_keys=True,
+...             indent=4, separators=(',', ': ')))
+{
+    "example": 42.0
+}
+>>> print(dumps(ctl.statistics['summary']['times'], sort_keys=True,
+...             indent=4, separators=(',', ': ')))
+{
+    "cpu": 0.000785999999999995,
+    "sat": 7.867813110351562e-06,
+    "solve": 2.288818359375e-05,
+    "total": 0.0007848739624023438,
+    "unsat": 0.0
+}
+
+
+ +Expand source code + +
"""
+Functions and classes related to statistics.
+
+Examples
+--------
+The following example shows how to add custom statistics and dump the
+statistics in json format:
+
+    >>> from json import dumps
+    >>> from clingo.control import Control
+    >>>
+    >>> def on_statistics(step, accu):
+    ...     accu["example"] = 42
+    ...
+    >>> ctl = Control(['--stats'])
+    >>> ctl.add("base", [], "{a}.")
+    >>> ctl.ground([("base", [])])
+    >>> print(ctl.solve(on_statistics=on_statistics))
+    SAT
+    >>> print(dumps(ctl.statistics['user_accu'], sort_keys=True,
+    ...             indent=4, separators=(',', ': ')))
+    {
+        "example": 42.0
+    }
+    >>> print(dumps(ctl.statistics['summary']['times'], sort_keys=True,
+    ...             indent=4, separators=(',', ': ')))
+    {
+        "cpu": 0.000785999999999995,
+        "sat": 7.867813110351562e-06,
+        "solve": 2.288818359375e-05,
+        "total": 0.0007848739624023438,
+        "unsat": 0.0
+    }
+"""
+from typing import (
+    Any,
+    ItemsView,
+    Iterable,
+    KeysView,
+    MutableMapping,
+    MutableSequence,
+    Sequence,
+    Tuple,
+    Union,
+    ValuesView,
+    cast,
+)
+from collections import abc
+
+from ._internal import _c_call, _handle_error, _lib, _to_str
+
+__all__ = ["StatisticsArray", "StatisticsMap", "StatisticsValue"]
+
+StatisticsValue = Union["StatisticsArray", "StatisticsMap", float]
+
+
+def _statistics_type(stats, key):
+    return _c_call("clingo_statistics_type_t", _lib.clingo_statistics_type, stats, key)
+
+
+def _statistics(stats, key):
+    """
+    Transform clingo's statistics into python type.
+    """
+    type_ = _statistics_type(stats, key)
+
+    if type_ == _lib.clingo_statistics_type_value:
+        return _c_call("double", _lib.clingo_statistics_value_get, stats, key)
+
+    if type_ == _lib.clingo_statistics_type_array:
+        ret = []
+        for i in range(
+            _c_call("size_t", _lib.clingo_statistics_array_size, stats, key)
+        ):
+            ret.append(
+                _statistics(
+                    stats,
+                    _c_call("uint64_t", _lib.clingo_statistics_array_at, stats, key, i),
+                )
+            )
+        return ret
+
+    assert type_ == _lib.clingo_statistics_type_map
+    ret = {}
+    for i in range(_c_call("size_t", _lib.clingo_statistics_map_size, stats, key)):
+        name = _c_call("char*", _lib.clingo_statistics_map_subkey_name, stats, key, i)
+        subkey = _c_call("uint64_t", _lib.clingo_statistics_map_at, stats, key, name)
+        ret[_to_str(name)] = _statistics(stats, subkey)
+    return ret
+
+
+def _mutable_statistics_value_type(value):
+    if isinstance(value, str):
+        raise TypeError("unexpected string")
+    if isinstance(value, abc.Sequence):
+        return _lib.clingo_statistics_type_array
+    if isinstance(value, abc.Mapping):
+        return _lib.clingo_statistics_type_map
+    return _lib.clingo_statistics_type_value
+
+
+def _mutable_statistics(stats) -> "StatisticsMap":
+    key = _c_call("uint64_t", _lib.clingo_statistics_root, stats)
+    return cast(StatisticsMap, _mutable_statistics_get(stats, key))
+
+
+def _mutable_statistics_get(stats, key) -> StatisticsValue:
+    type_ = _statistics_type(stats, key)
+
+    if type_ == _lib.clingo_statistics_type_array:
+        return StatisticsArray(stats, key)
+
+    if type_ == _lib.clingo_statistics_type_map:
+        return StatisticsMap(stats, key)
+
+    assert type_ == _lib.clingo_statistics_type_value
+    return _c_call("double", _lib.clingo_statistics_value_get, stats, key)
+
+
+def _mutable_statistics_set(stats, key, type_, value, update):
+    if type_ == _lib.clingo_statistics_type_map:
+        StatisticsMap(stats, key).update(value)
+    elif type_ == _lib.clingo_statistics_type_array:
+        StatisticsArray(stats, key).update(value)
+    else:
+        assert type_ == _lib.clingo_statistics_type_value
+        if callable(value):
+            if update:
+                uval = value(
+                    _c_call("double", _lib.clingo_statistics_value_get, stats, key)
+                )
+            else:
+                uval = value(None)
+        else:
+            uval = value
+        _handle_error(_lib.clingo_statistics_value_set(stats, key, uval))
+
+
+class StatisticsArray(MutableSequence[StatisticsValue]):
+    """
+    Class to modify statistics stored in an array.
+
+    Notes
+    -----
+    Only inplace concatenation and no deletion is supported.
+    """
+
+    def __init__(self, rep, key):
+        self._rep = rep
+        self._key = key
+
+    def __len__(self):
+        return _c_call(
+            "size_t", _lib.clingo_statistics_array_size, self._rep, self._key
+        )
+
+    def __getitem__(self, index):
+        if index < 0 or index >= len(self):
+            raise IndexError("invalid index")
+        key = _c_call(
+            "uint64_t", _lib.clingo_statistics_array_at, self._rep, self._key, index
+        )
+        return _mutable_statistics_get(self._rep, key)
+
+    def __setitem__(self, index, value):
+        key = _c_call(
+            "uint64_t", _lib.clingo_statistics_array_at, self._rep, self._key, index
+        )
+        type_ = _statistics_type(self._rep, key)
+        _mutable_statistics_set(self._rep, key, type_, value, True)
+
+    def insert(self, index, value):
+        """
+        This method is not supported.
+        """
+        raise NotImplementedError("insertion is not supported")
+
+    def __delitem__(self, index):
+        raise NotImplementedError("deletion is not supported")
+
+    def __add__(self, other):
+        raise NotImplementedError("only inplace concatenation is supported")
+
+    def __iadd__(self, other):
+        for x in other:
+            self.append(x)
+        return self
+
+    def append(self, value: Any) -> None:
+        """
+        Append a value.
+
+        Parameters
+        ----------
+        value
+            A nested structure composed of floats, sequences, and mappings.
+        """
+        type_ = _mutable_statistics_value_type(value)
+        key = _c_call(
+            "uint64_t", _lib.clingo_statistics_array_push, self._rep, self._key, type_
+        )
+        _mutable_statistics_set(self._rep, key, type_, value, False)
+
+    def extend(self, values: Iterable[Any]) -> None:
+        """
+        Extend the statistics array with the given values.
+
+        Paremeters
+        ----------
+        values
+            A sequence of nested structures composed of floats, sequences, and
+            mappings.
+        """
+        self += values
+
+    def update(self, values: Sequence[Any]) -> None:
+        """
+        Update a statistics array.
+
+        Parameters
+        ----------
+        values
+            A sequence of nested structures composed of floats, callable,
+            sequences, and mappings. A callable can be used to update an
+            existing value, it receives the previous numeric value (or None if
+            absent) as argument and must return an updated numeric value.
+        """
+        n = len(self)
+        for idx, val in enumerate(values):
+            if idx < n:
+                self[idx] = val
+            else:
+                self.append(val)
+
+
+class StatisticsMap(MutableMapping[str, StatisticsValue]):
+    """
+    Object to capture statistics stored in a map.
+
+    This class does not support item deletion.
+    """
+
+    def __init__(self, rep, key):
+        self._rep = rep
+        self._key = key
+
+    def __len__(self):
+        return _c_call("size_t", _lib.clingo_statistics_map_size, self._rep, self._key)
+
+    def __getitem__(self, name: str):
+        if not name in self:
+            raise KeyError("key not found")
+        key = _c_call(
+            "uint64_t",
+            _lib.clingo_statistics_map_at,
+            self._rep,
+            self._key,
+            name.encode(),
+        )
+        return _mutable_statistics_get(self._rep, key)
+
+    def __setitem__(self, name: str, value: Any):
+        has_key = name in self
+        if has_key:
+            key = _c_call(
+                "uint64_t",
+                _lib.clingo_statistics_map_at,
+                self._rep,
+                self._key,
+                name.encode(),
+            )
+            type_ = _statistics_type(self._rep, key)
+        else:
+            type_ = _mutable_statistics_value_type(value)
+            key = _c_call(
+                "uint64_t",
+                _lib.clingo_statistics_map_add_subkey,
+                self._rep,
+                self._key,
+                name.encode(),
+                type_,
+            )
+        _mutable_statistics_set(self._rep, key, type_, value, has_key)
+
+    def __delitem__(self, index):
+        raise NotImplementedError("deletion is not supported")
+
+    def __contains__(self, name):
+        # note: has to be done like this because of python's container model
+        if not isinstance(name, str):
+            return False
+        return _c_call(
+            "bool",
+            _lib.clingo_statistics_map_has_subkey,
+            self._rep,
+            self._key,
+            name.encode(),
+        )
+
+    def __iter__(self):
+        return iter(self.keys())
+
+    def items(self) -> ItemsView[str, StatisticsValue]:
+        """
+        Return the items of the map.
+        """
+        ret = []
+        for i in range(len(self)):
+            name = _c_call(
+                "char*", _lib.clingo_statistics_map_subkey_name, self._rep, self._key, i
+            )
+            key = _c_call(
+                "uint64_t", _lib.clingo_statistics_map_at, self._rep, self._key, name
+            )
+            ret.append((_to_str(name), _mutable_statistics_get(self._rep, key)))
+        # Note: to shut up the type checker; this should work fine in practice
+        return cast(ItemsView[str, StatisticsValue], ret)
+
+    def keys(self) -> KeysView[str]:
+        """
+        Return the keys of the map.
+        """
+        ret = []
+        for i in range(len(self)):
+            ret.append(
+                _to_str(
+                    _c_call(
+                        "char*",
+                        _lib.clingo_statistics_map_subkey_name,
+                        self._rep,
+                        self._key,
+                        i,
+                    )
+                )
+            )
+        # Note: to shut up the type checker; this should work fine in practice
+        return cast(KeysView[str], ret)
+
+    def update(self, values):
+        """
+        Update the map with the given values.
+
+        Parameters
+        ----------
+        values
+            A mapping of nested structures composed of floats, callable,
+            sequences, and mappings. A callable can be used to update an
+            existing value, it receives the previous numeric value (or None if
+            absent) as argument and must return an updated numeric value.
+        """
+        for key, value in values.items():
+            self[key] = value
+
+    def values(self) -> ValuesView[StatisticsValue]:
+        """
+        Return the values of the map.
+        """
+        ret = []
+        for i in range(len(self)):
+            name = _c_call(
+                "char*", _lib.clingo_statistics_map_subkey_name, self._rep, self._key, i
+            )
+            key = _c_call(
+                "uint64_t", _lib.clingo_statistics_map_at, self._rep, self._key, name
+            )
+            ret.append(_mutable_statistics_get(self._rep, key))
+        # Note: to shut up the type checker; this should work fine in practice
+        return cast(ValuesView[StatisticsValue], ret)
+
+
+
+
+
+
+
+
+
+

Classes

+
+
+class StatisticsArray +(rep, key) +
+
+

Class to modify statistics stored in an array.

+

Notes

+

Only inplace concatenation and no deletion is supported.

+
+ +Expand source code + +
class StatisticsArray(MutableSequence[StatisticsValue]):
+    """
+    Class to modify statistics stored in an array.
+
+    Notes
+    -----
+    Only inplace concatenation and no deletion is supported.
+    """
+
+    def __init__(self, rep, key):
+        self._rep = rep
+        self._key = key
+
+    def __len__(self):
+        return _c_call(
+            "size_t", _lib.clingo_statistics_array_size, self._rep, self._key
+        )
+
+    def __getitem__(self, index):
+        if index < 0 or index >= len(self):
+            raise IndexError("invalid index")
+        key = _c_call(
+            "uint64_t", _lib.clingo_statistics_array_at, self._rep, self._key, index
+        )
+        return _mutable_statistics_get(self._rep, key)
+
+    def __setitem__(self, index, value):
+        key = _c_call(
+            "uint64_t", _lib.clingo_statistics_array_at, self._rep, self._key, index
+        )
+        type_ = _statistics_type(self._rep, key)
+        _mutable_statistics_set(self._rep, key, type_, value, True)
+
+    def insert(self, index, value):
+        """
+        This method is not supported.
+        """
+        raise NotImplementedError("insertion is not supported")
+
+    def __delitem__(self, index):
+        raise NotImplementedError("deletion is not supported")
+
+    def __add__(self, other):
+        raise NotImplementedError("only inplace concatenation is supported")
+
+    def __iadd__(self, other):
+        for x in other:
+            self.append(x)
+        return self
+
+    def append(self, value: Any) -> None:
+        """
+        Append a value.
+
+        Parameters
+        ----------
+        value
+            A nested structure composed of floats, sequences, and mappings.
+        """
+        type_ = _mutable_statistics_value_type(value)
+        key = _c_call(
+            "uint64_t", _lib.clingo_statistics_array_push, self._rep, self._key, type_
+        )
+        _mutable_statistics_set(self._rep, key, type_, value, False)
+
+    def extend(self, values: Iterable[Any]) -> None:
+        """
+        Extend the statistics array with the given values.
+
+        Paremeters
+        ----------
+        values
+            A sequence of nested structures composed of floats, sequences, and
+            mappings.
+        """
+        self += values
+
+    def update(self, values: Sequence[Any]) -> None:
+        """
+        Update a statistics array.
+
+        Parameters
+        ----------
+        values
+            A sequence of nested structures composed of floats, callable,
+            sequences, and mappings. A callable can be used to update an
+            existing value, it receives the previous numeric value (or None if
+            absent) as argument and must return an updated numeric value.
+        """
+        n = len(self)
+        for idx, val in enumerate(values):
+            if idx < n:
+                self[idx] = val
+            else:
+                self.append(val)
+
+

Ancestors

+
    +
  • collections.abc.MutableSequence
  • +
  • collections.abc.Sequence
  • +
  • collections.abc.Reversible
  • +
  • collections.abc.Collection
  • +
  • collections.abc.Sized
  • +
  • collections.abc.Iterable
  • +
  • collections.abc.Container
  • +
  • typing.Generic
  • +
+

Methods

+
+
+def append(self, value: Any) ‑> None +
+
+

Append a value.

+

Parameters

+
+
value
+
A nested structure composed of floats, sequences, and mappings.
+
+
+ +Expand source code + +
def append(self, value: Any) -> None:
+    """
+    Append a value.
+
+    Parameters
+    ----------
+    value
+        A nested structure composed of floats, sequences, and mappings.
+    """
+    type_ = _mutable_statistics_value_type(value)
+    key = _c_call(
+        "uint64_t", _lib.clingo_statistics_array_push, self._rep, self._key, type_
+    )
+    _mutable_statistics_set(self._rep, key, type_, value, False)
+
+
+
+def extend(self, values: Iterable[Any]) ‑> None +
+
+

Extend the statistics array with the given values.

+

Paremeters

+

values +A sequence of nested structures composed of floats, sequences, and +mappings.

+
+ +Expand source code + +
def extend(self, values: Iterable[Any]) -> None:
+    """
+    Extend the statistics array with the given values.
+
+    Paremeters
+    ----------
+    values
+        A sequence of nested structures composed of floats, sequences, and
+        mappings.
+    """
+    self += values
+
+
+
+def insert(self, index, value) +
+
+

This method is not supported.

+
+ +Expand source code + +
def insert(self, index, value):
+    """
+    This method is not supported.
+    """
+    raise NotImplementedError("insertion is not supported")
+
+
+
+def update(self, values: Sequence[Any]) ‑> None +
+
+

Update a statistics array.

+

Parameters

+
+
values
+
A sequence of nested structures composed of floats, callable, +sequences, and mappings. A callable can be used to update an +existing value, it receives the previous numeric value (or None if +absent) as argument and must return an updated numeric value.
+
+
+ +Expand source code + +
def update(self, values: Sequence[Any]) -> None:
+    """
+    Update a statistics array.
+
+    Parameters
+    ----------
+    values
+        A sequence of nested structures composed of floats, callable,
+        sequences, and mappings. A callable can be used to update an
+        existing value, it receives the previous numeric value (or None if
+        absent) as argument and must return an updated numeric value.
+    """
+    n = len(self)
+    for idx, val in enumerate(values):
+        if idx < n:
+            self[idx] = val
+        else:
+            self.append(val)
+
+
+
+
+
+class StatisticsMap +(rep, key) +
+
+

Object to capture statistics stored in a map.

+

This class does not support item deletion.

+
+ +Expand source code + +
class StatisticsMap(MutableMapping[str, StatisticsValue]):
+    """
+    Object to capture statistics stored in a map.
+
+    This class does not support item deletion.
+    """
+
+    def __init__(self, rep, key):
+        self._rep = rep
+        self._key = key
+
+    def __len__(self):
+        return _c_call("size_t", _lib.clingo_statistics_map_size, self._rep, self._key)
+
+    def __getitem__(self, name: str):
+        if not name in self:
+            raise KeyError("key not found")
+        key = _c_call(
+            "uint64_t",
+            _lib.clingo_statistics_map_at,
+            self._rep,
+            self._key,
+            name.encode(),
+        )
+        return _mutable_statistics_get(self._rep, key)
+
+    def __setitem__(self, name: str, value: Any):
+        has_key = name in self
+        if has_key:
+            key = _c_call(
+                "uint64_t",
+                _lib.clingo_statistics_map_at,
+                self._rep,
+                self._key,
+                name.encode(),
+            )
+            type_ = _statistics_type(self._rep, key)
+        else:
+            type_ = _mutable_statistics_value_type(value)
+            key = _c_call(
+                "uint64_t",
+                _lib.clingo_statistics_map_add_subkey,
+                self._rep,
+                self._key,
+                name.encode(),
+                type_,
+            )
+        _mutable_statistics_set(self._rep, key, type_, value, has_key)
+
+    def __delitem__(self, index):
+        raise NotImplementedError("deletion is not supported")
+
+    def __contains__(self, name):
+        # note: has to be done like this because of python's container model
+        if not isinstance(name, str):
+            return False
+        return _c_call(
+            "bool",
+            _lib.clingo_statistics_map_has_subkey,
+            self._rep,
+            self._key,
+            name.encode(),
+        )
+
+    def __iter__(self):
+        return iter(self.keys())
+
+    def items(self) -> ItemsView[str, StatisticsValue]:
+        """
+        Return the items of the map.
+        """
+        ret = []
+        for i in range(len(self)):
+            name = _c_call(
+                "char*", _lib.clingo_statistics_map_subkey_name, self._rep, self._key, i
+            )
+            key = _c_call(
+                "uint64_t", _lib.clingo_statistics_map_at, self._rep, self._key, name
+            )
+            ret.append((_to_str(name), _mutable_statistics_get(self._rep, key)))
+        # Note: to shut up the type checker; this should work fine in practice
+        return cast(ItemsView[str, StatisticsValue], ret)
+
+    def keys(self) -> KeysView[str]:
+        """
+        Return the keys of the map.
+        """
+        ret = []
+        for i in range(len(self)):
+            ret.append(
+                _to_str(
+                    _c_call(
+                        "char*",
+                        _lib.clingo_statistics_map_subkey_name,
+                        self._rep,
+                        self._key,
+                        i,
+                    )
+                )
+            )
+        # Note: to shut up the type checker; this should work fine in practice
+        return cast(KeysView[str], ret)
+
+    def update(self, values):
+        """
+        Update the map with the given values.
+
+        Parameters
+        ----------
+        values
+            A mapping of nested structures composed of floats, callable,
+            sequences, and mappings. A callable can be used to update an
+            existing value, it receives the previous numeric value (or None if
+            absent) as argument and must return an updated numeric value.
+        """
+        for key, value in values.items():
+            self[key] = value
+
+    def values(self) -> ValuesView[StatisticsValue]:
+        """
+        Return the values of the map.
+        """
+        ret = []
+        for i in range(len(self)):
+            name = _c_call(
+                "char*", _lib.clingo_statistics_map_subkey_name, self._rep, self._key, i
+            )
+            key = _c_call(
+                "uint64_t", _lib.clingo_statistics_map_at, self._rep, self._key, name
+            )
+            ret.append(_mutable_statistics_get(self._rep, key))
+        # Note: to shut up the type checker; this should work fine in practice
+        return cast(ValuesView[StatisticsValue], ret)
+
+

Ancestors

+
    +
  • collections.abc.MutableMapping
  • +
  • collections.abc.Mapping
  • +
  • collections.abc.Collection
  • +
  • collections.abc.Sized
  • +
  • collections.abc.Iterable
  • +
  • collections.abc.Container
  • +
  • typing.Generic
  • +
+

Methods

+
+
+def items(self) ‑> ItemsView[str, Union[StatisticsArrayStatisticsMap, float]] +
+
+

Return the items of the map.

+
+ +Expand source code + +
def items(self) -> ItemsView[str, StatisticsValue]:
+    """
+    Return the items of the map.
+    """
+    ret = []
+    for i in range(len(self)):
+        name = _c_call(
+            "char*", _lib.clingo_statistics_map_subkey_name, self._rep, self._key, i
+        )
+        key = _c_call(
+            "uint64_t", _lib.clingo_statistics_map_at, self._rep, self._key, name
+        )
+        ret.append((_to_str(name), _mutable_statistics_get(self._rep, key)))
+    # Note: to shut up the type checker; this should work fine in practice
+    return cast(ItemsView[str, StatisticsValue], ret)
+
+
+
+def keys(self) ‑> KeysView[str] +
+
+

Return the keys of the map.

+
+ +Expand source code + +
def keys(self) -> KeysView[str]:
+    """
+    Return the keys of the map.
+    """
+    ret = []
+    for i in range(len(self)):
+        ret.append(
+            _to_str(
+                _c_call(
+                    "char*",
+                    _lib.clingo_statistics_map_subkey_name,
+                    self._rep,
+                    self._key,
+                    i,
+                )
+            )
+        )
+    # Note: to shut up the type checker; this should work fine in practice
+    return cast(KeysView[str], ret)
+
+
+
+def update(self, values) +
+
+

Update the map with the given values.

+

Parameters

+
+
values
+
A mapping of nested structures composed of floats, callable, +sequences, and mappings. A callable can be used to update an +existing value, it receives the previous numeric value (or None if +absent) as argument and must return an updated numeric value.
+
+
+ +Expand source code + +
def update(self, values):
+    """
+    Update the map with the given values.
+
+    Parameters
+    ----------
+    values
+        A mapping of nested structures composed of floats, callable,
+        sequences, and mappings. A callable can be used to update an
+        existing value, it receives the previous numeric value (or None if
+        absent) as argument and must return an updated numeric value.
+    """
+    for key, value in values.items():
+        self[key] = value
+
+
+
+def values(self) ‑> ValuesView[Union[StatisticsArrayStatisticsMap, float]] +
+
+

Return the values of the map.

+
+ +Expand source code + +
def values(self) -> ValuesView[StatisticsValue]:
+    """
+    Return the values of the map.
+    """
+    ret = []
+    for i in range(len(self)):
+        name = _c_call(
+            "char*", _lib.clingo_statistics_map_subkey_name, self._rep, self._key, i
+        )
+        key = _c_call(
+            "uint64_t", _lib.clingo_statistics_map_at, self._rep, self._key, name
+        )
+        ret.append(_mutable_statistics_get(self._rep, key))
+    # Note: to shut up the type checker; this should work fine in practice
+    return cast(ValuesView[StatisticsValue], ret)
+
+
+
+
+
+
+
+ +
+ + + \ No newline at end of file diff --git a/clingo/python-api/5.7/clingo/symbol.html b/clingo/python-api/5.7/clingo/symbol.html new file mode 100644 index 0000000..6b28503 --- /dev/null +++ b/clingo/python-api/5.7/clingo/symbol.html @@ -0,0 +1,1028 @@ + + + + + + +clingo.symbol API documentation + + + + + + + + + + + +
+
+
+

Module clingo.symbol

+
+
+

Functions and classes for symbol manipulation.

+

Examples

+
>>> from clingo.symbol import Function, Number, parse_term
+>>>
+>>> num = Number(42)
+>>> num.number
+42
+>>> fun = Function("f", [num])
+>>> fun.name
+'f'
+>>> [ str(arg) for arg in fun.arguments ]
+['42']
+>>> parse_term(str(fun)) == fun
+True
+>>> clingo.parse_term('p(1+2)')
+p(3)
+
+
+ +Expand source code + +
"""
+Functions and classes for symbol manipulation.
+
+Examples
+--------
+
+    >>> from clingo.symbol import Function, Number, parse_term
+    >>>
+    >>> num = Number(42)
+    >>> num.number
+    42
+    >>> fun = Function("f", [num])
+    >>> fun.name
+    'f'
+    >>> [ str(arg) for arg in fun.arguments ]
+    ['42']
+    >>> parse_term(str(fun)) == fun
+    True
+    >>> clingo.parse_term('p(1+2)')
+    p(3)
+"""
+
+from typing import Callable, List, Optional, Sequence
+
+from functools import total_ordering
+
+from ._internal import _c_call, _c_call2, _ffi, _lib, _str, _to_str
+from .core import MessageCode, OrderedEnum
+
+__all__ = [
+    "Function",
+    "Infimum",
+    "Number",
+    "String",
+    "Supremum",
+    "Symbol",
+    "SymbolType",
+    "Tuple_",
+    "parse_term",
+]
+
+
+class SymbolType(OrderedEnum):
+    """
+    Enumeration of symbols types.
+    """
+
+    Function = _lib.clingo_symbol_type_function
+    """
+    A function symbol, e.g., `c`, `(1,"a")`, or `f(1,"a")`.
+    """
+    Infimum = _lib.clingo_symbol_type_infimum
+    """
+    The `#inf` symbol.
+    """
+    Number = _lib.clingo_symbol_type_number
+    """
+    A numeric symbol, e.g., `1`.
+    """
+    String = _lib.clingo_symbol_type_string
+    """
+    A string symbol, e.g., `"a"`.
+    """
+    Supremum = _lib.clingo_symbol_type_supremum
+    """
+    The `#sup` symbol
+    """
+
+
+@total_ordering
+class Symbol:
+    """
+    Represents a gringo symbol.
+
+    This includes numbers, strings, functions (including constants with
+    `len(arguments) == 0` and tuples with `len(name) == 0`), `#inf` and `#sup`.
+
+    Symbol objects implement Python's rich comparison operators and are ordered
+    like in gringo. They can also be used as keys in dictionaries. Their string
+    representation corresponds to their gringo representation.
+
+    Notes
+    -----
+    Note that this class does not have a constructor. Instead there are the
+    functions `Number`, `String`, `Tuple_`, and `Function` to construct symbol
+    objects or the preconstructed symbols `Infimum` and `Supremum`.
+    """
+
+    __slots__ = ("_rep",)
+
+    def __init__(self, rep):
+        self._rep = rep
+
+    def __str__(self) -> str:
+        return _str(
+            _lib.clingo_symbol_to_string_size, _lib.clingo_symbol_to_string, self._rep
+        )
+
+    def __repr__(self) -> str:
+        if self.type == SymbolType.Infimum:
+            return "Infimum"
+        if self.type == SymbolType.Supremum:
+            return "Supremum"
+        if self.type == SymbolType.Number:
+            return f"Number({self.number!r})"
+        if self.type == SymbolType.String:
+            return f"String({self.string!r})"
+        assert self.type == SymbolType.Function
+        return f"Function({self.name!r}, {self.arguments!r}, {self.positive!r})"
+
+    def __hash__(self) -> int:
+        return _lib.clingo_symbol_hash(self._rep)
+
+    def __eq__(self, other: object) -> bool:
+        if not isinstance(other, Symbol):
+            return NotImplemented
+        return _lib.clingo_symbol_is_equal_to(self._rep, other._rep)
+
+    def __lt__(self, other: object) -> bool:
+        if not isinstance(other, Symbol):
+            return NotImplemented
+        return _lib.clingo_symbol_is_less_than(self._rep, other._rep)
+
+    def match(self, name: str, arity: int, positive: bool = True) -> bool:
+        """
+        Check if this is a function symbol with the given signature.
+
+        Parameters
+        ----------
+        name
+            The name of the function.
+
+        arity
+            The arity of the function.
+
+        positive
+            Whether to match positive or negative signatures.
+
+        Returns
+        -------
+        Whether the function matches.
+        """
+        return (
+            self.type == SymbolType.Function
+            and self.positive == positive
+            and self.name == name
+            and len(self.arguments) == arity
+        )
+
+    @property
+    def arguments(self) -> List["Symbol"]:
+        """
+        The arguments of a function.
+        """
+        args, size = _c_call2(
+            "clingo_symbol_t*", "size_t", _lib.clingo_symbol_arguments, self._rep
+        )
+        return [Symbol(args[i]) for i in range(size)]
+
+    @property
+    def name(self) -> str:
+        """
+        The name of a function.
+        """
+        return _to_str(_c_call("char*", _lib.clingo_symbol_name, self._rep))
+
+    @property
+    def negative(self) -> bool:
+        """
+        The inverted sign of a function.
+        """
+        return _c_call("bool", _lib.clingo_symbol_is_negative, self._rep)
+
+    @property
+    def number(self) -> int:
+        """
+        The value of a number.
+        """
+        return _c_call("int", _lib.clingo_symbol_number, self._rep)
+
+    @property
+    def positive(self) -> bool:
+        """
+        The sign of a function.
+        """
+        return _c_call("bool", _lib.clingo_symbol_is_positive, self._rep)
+
+    @property
+    def string(self) -> str:
+        """
+        The value of a string.
+        """
+        return _to_str(_c_call("char*", _lib.clingo_symbol_string, self._rep))
+
+    @property
+    def type(self) -> SymbolType:
+        """
+        The type of the symbol.
+        """
+        return SymbolType(_lib.clingo_symbol_type(self._rep))
+
+
+def Function(
+    name: str, arguments: Sequence[Symbol] = [], positive: bool = True
+) -> Symbol:
+    """
+    Construct a function symbol.
+
+    This includes constants and tuples. Constants have an empty argument list
+    and tuples have an empty name. Functions can represent classically negated
+    atoms. Argument `positive` has to be set to false to represent such atoms.
+
+    Parameters
+    ----------
+    name
+        The name of the function (empty for tuples).
+    arguments
+        The arguments in form of a list of symbols.
+    positive
+        The sign of the function (tuples must not have signs).
+    """
+    # pylint: disable=protected-access,invalid-name,dangerous-default-value
+    c_args = _ffi.new("clingo_symbol_t[]", len(arguments))
+    for i, arg in enumerate(arguments):
+        c_args[i] = arg._rep
+    sym = _c_call(
+        "clingo_symbol_t",
+        _lib.clingo_symbol_create_function,
+        name.encode(),
+        c_args,
+        len(arguments),
+        positive,
+    )
+    return Symbol(sym)
+
+
+def Number(number: int) -> Symbol:
+    """
+    Construct a numeric symbol given a number.
+
+    Parameters
+    ----------
+    number
+        The given number.
+    """
+    # pylint: disable=invalid-name
+    p_rep = _ffi.new("clingo_symbol_t*")
+    _lib.clingo_symbol_create_number(number, p_rep)
+    return Symbol(p_rep[0])
+
+
+def String(string: str) -> Symbol:
+    """
+    Construct a string symbol given a string.
+
+    Parameters
+    ----------
+    string
+        The given string.
+    """
+    # pylint: disable=invalid-name
+    return Symbol(
+        _c_call("clingo_symbol_t", _lib.clingo_symbol_create_string, string.encode())
+    )
+
+
+def Tuple_(arguments: Sequence[Symbol]) -> Symbol:
+    """
+    A shortcut for `Function("", arguments)`.
+
+    Parameters
+    ----------
+    arguments
+        The arguments in form of a list of symbols.
+
+    See Also
+    --------
+    Function
+    """
+    # pylint: disable=invalid-name
+    return Function("", arguments)
+
+
+_p_infimum = _ffi.new("clingo_symbol_t*")
+_p_supremum = _ffi.new("clingo_symbol_t*")
+_lib.clingo_symbol_create_infimum(_p_infimum)
+_lib.clingo_symbol_create_supremum(_p_supremum)
+
+Infimum: Symbol = Symbol(_p_infimum[0])
+Supremum: Symbol = Symbol(_p_supremum[0])
+
+
+def parse_term(
+    string: str,
+    logger: Optional[Callable[[MessageCode, str], None]] = None,
+    message_limit: int = 20,
+) -> Symbol:
+    """
+    Parse the given string using gringo's term parser for ground terms.
+
+    The function also evaluates arithmetic functions.
+
+    Parameters
+    ----------
+    string
+        The string to be parsed.
+    logger
+        Function to intercept messages normally printed to standard error.
+    message_limit
+        Maximum number of messages passed to the logger.
+    """
+    if logger is not None:
+        # pylint: disable=protected-access
+        c_handle = _ffi.new_handle(logger)
+        c_cb = _lib.pyclingo_logger_callback
+    else:
+        c_handle = _ffi.NULL
+        c_cb = _ffi.NULL
+    return Symbol(
+        _c_call(
+            "clingo_symbol_t",
+            _lib.clingo_parse_term,
+            string.encode(),
+            c_cb,
+            c_handle,
+            message_limit,
+        )
+    )
+
+
+
+
+
+
+
+

Functions

+
+
+def Function(name: str, arguments: Sequence[Symbol] = [], positive: bool = True) ‑> Symbol +
+
+

Construct a function symbol.

+

This includes constants and tuples. Constants have an empty argument list +and tuples have an empty name. Functions can represent classically negated +atoms. Argument positive has to be set to false to represent such atoms.

+

Parameters

+
+
name
+
The name of the function (empty for tuples).
+
arguments
+
The arguments in form of a list of symbols.
+
positive
+
The sign of the function (tuples must not have signs).
+
+
+ +Expand source code + +
def Function(
+    name: str, arguments: Sequence[Symbol] = [], positive: bool = True
+) -> Symbol:
+    """
+    Construct a function symbol.
+
+    This includes constants and tuples. Constants have an empty argument list
+    and tuples have an empty name. Functions can represent classically negated
+    atoms. Argument `positive` has to be set to false to represent such atoms.
+
+    Parameters
+    ----------
+    name
+        The name of the function (empty for tuples).
+    arguments
+        The arguments in form of a list of symbols.
+    positive
+        The sign of the function (tuples must not have signs).
+    """
+    # pylint: disable=protected-access,invalid-name,dangerous-default-value
+    c_args = _ffi.new("clingo_symbol_t[]", len(arguments))
+    for i, arg in enumerate(arguments):
+        c_args[i] = arg._rep
+    sym = _c_call(
+        "clingo_symbol_t",
+        _lib.clingo_symbol_create_function,
+        name.encode(),
+        c_args,
+        len(arguments),
+        positive,
+    )
+    return Symbol(sym)
+
+
+
+def Number(number: int) ‑> Symbol +
+
+

Construct a numeric symbol given a number.

+

Parameters

+
+
number
+
The given number.
+
+
+ +Expand source code + +
def Number(number: int) -> Symbol:
+    """
+    Construct a numeric symbol given a number.
+
+    Parameters
+    ----------
+    number
+        The given number.
+    """
+    # pylint: disable=invalid-name
+    p_rep = _ffi.new("clingo_symbol_t*")
+    _lib.clingo_symbol_create_number(number, p_rep)
+    return Symbol(p_rep[0])
+
+
+
+def String(string: str) ‑> Symbol +
+
+

Construct a string symbol given a string.

+

Parameters

+
+
string
+
The given string.
+
+
+ +Expand source code + +
def String(string: str) -> Symbol:
+    """
+    Construct a string symbol given a string.
+
+    Parameters
+    ----------
+    string
+        The given string.
+    """
+    # pylint: disable=invalid-name
+    return Symbol(
+        _c_call("clingo_symbol_t", _lib.clingo_symbol_create_string, string.encode())
+    )
+
+
+
+def Tuple_(arguments: Sequence[Symbol]) ‑> Symbol +
+
+

A shortcut for Function("", arguments).

+

Parameters

+
+
arguments
+
The arguments in form of a list of symbols.
+
+

See Also

+

Function()

+
+ +Expand source code + +
def Tuple_(arguments: Sequence[Symbol]) -> Symbol:
+    """
+    A shortcut for `Function("", arguments)`.
+
+    Parameters
+    ----------
+    arguments
+        The arguments in form of a list of symbols.
+
+    See Also
+    --------
+    Function
+    """
+    # pylint: disable=invalid-name
+    return Function("", arguments)
+
+
+
+def parse_term(string: str, logger: Optional[Callable[[MessageCode, str], None]] = None, message_limit: int = 20) ‑> Symbol +
+
+

Parse the given string using gringo's term parser for ground terms.

+

The function also evaluates arithmetic functions.

+

Parameters

+
+
string
+
The string to be parsed.
+
logger
+
Function to intercept messages normally printed to standard error.
+
message_limit
+
Maximum number of messages passed to the logger.
+
+
+ +Expand source code + +
def parse_term(
+    string: str,
+    logger: Optional[Callable[[MessageCode, str], None]] = None,
+    message_limit: int = 20,
+) -> Symbol:
+    """
+    Parse the given string using gringo's term parser for ground terms.
+
+    The function also evaluates arithmetic functions.
+
+    Parameters
+    ----------
+    string
+        The string to be parsed.
+    logger
+        Function to intercept messages normally printed to standard error.
+    message_limit
+        Maximum number of messages passed to the logger.
+    """
+    if logger is not None:
+        # pylint: disable=protected-access
+        c_handle = _ffi.new_handle(logger)
+        c_cb = _lib.pyclingo_logger_callback
+    else:
+        c_handle = _ffi.NULL
+        c_cb = _ffi.NULL
+    return Symbol(
+        _c_call(
+            "clingo_symbol_t",
+            _lib.clingo_parse_term,
+            string.encode(),
+            c_cb,
+            c_handle,
+            message_limit,
+        )
+    )
+
+
+
+
+
+

Classes

+
+
+class Symbol +(rep) +
+
+

Represents a gringo symbol.

+

This includes numbers, strings, functions (including constants with +len(arguments) == 0 and tuples with len(name) == 0), #inf and #sup.

+

Symbol objects implement Python's rich comparison operators and are ordered +like in gringo. They can also be used as keys in dictionaries. Their string +representation corresponds to their gringo representation.

+

Notes

+

Note that this class does not have a constructor. Instead there are the +functions Number(), String(), Tuple_(), and Function() to construct symbol +objects or the preconstructed symbols Infimum and Supremum.

+
+ +Expand source code + +
@total_ordering
+class Symbol:
+    """
+    Represents a gringo symbol.
+
+    This includes numbers, strings, functions (including constants with
+    `len(arguments) == 0` and tuples with `len(name) == 0`), `#inf` and `#sup`.
+
+    Symbol objects implement Python's rich comparison operators and are ordered
+    like in gringo. They can also be used as keys in dictionaries. Their string
+    representation corresponds to their gringo representation.
+
+    Notes
+    -----
+    Note that this class does not have a constructor. Instead there are the
+    functions `Number`, `String`, `Tuple_`, and `Function` to construct symbol
+    objects or the preconstructed symbols `Infimum` and `Supremum`.
+    """
+
+    __slots__ = ("_rep",)
+
+    def __init__(self, rep):
+        self._rep = rep
+
+    def __str__(self) -> str:
+        return _str(
+            _lib.clingo_symbol_to_string_size, _lib.clingo_symbol_to_string, self._rep
+        )
+
+    def __repr__(self) -> str:
+        if self.type == SymbolType.Infimum:
+            return "Infimum"
+        if self.type == SymbolType.Supremum:
+            return "Supremum"
+        if self.type == SymbolType.Number:
+            return f"Number({self.number!r})"
+        if self.type == SymbolType.String:
+            return f"String({self.string!r})"
+        assert self.type == SymbolType.Function
+        return f"Function({self.name!r}, {self.arguments!r}, {self.positive!r})"
+
+    def __hash__(self) -> int:
+        return _lib.clingo_symbol_hash(self._rep)
+
+    def __eq__(self, other: object) -> bool:
+        if not isinstance(other, Symbol):
+            return NotImplemented
+        return _lib.clingo_symbol_is_equal_to(self._rep, other._rep)
+
+    def __lt__(self, other: object) -> bool:
+        if not isinstance(other, Symbol):
+            return NotImplemented
+        return _lib.clingo_symbol_is_less_than(self._rep, other._rep)
+
+    def match(self, name: str, arity: int, positive: bool = True) -> bool:
+        """
+        Check if this is a function symbol with the given signature.
+
+        Parameters
+        ----------
+        name
+            The name of the function.
+
+        arity
+            The arity of the function.
+
+        positive
+            Whether to match positive or negative signatures.
+
+        Returns
+        -------
+        Whether the function matches.
+        """
+        return (
+            self.type == SymbolType.Function
+            and self.positive == positive
+            and self.name == name
+            and len(self.arguments) == arity
+        )
+
+    @property
+    def arguments(self) -> List["Symbol"]:
+        """
+        The arguments of a function.
+        """
+        args, size = _c_call2(
+            "clingo_symbol_t*", "size_t", _lib.clingo_symbol_arguments, self._rep
+        )
+        return [Symbol(args[i]) for i in range(size)]
+
+    @property
+    def name(self) -> str:
+        """
+        The name of a function.
+        """
+        return _to_str(_c_call("char*", _lib.clingo_symbol_name, self._rep))
+
+    @property
+    def negative(self) -> bool:
+        """
+        The inverted sign of a function.
+        """
+        return _c_call("bool", _lib.clingo_symbol_is_negative, self._rep)
+
+    @property
+    def number(self) -> int:
+        """
+        The value of a number.
+        """
+        return _c_call("int", _lib.clingo_symbol_number, self._rep)
+
+    @property
+    def positive(self) -> bool:
+        """
+        The sign of a function.
+        """
+        return _c_call("bool", _lib.clingo_symbol_is_positive, self._rep)
+
+    @property
+    def string(self) -> str:
+        """
+        The value of a string.
+        """
+        return _to_str(_c_call("char*", _lib.clingo_symbol_string, self._rep))
+
+    @property
+    def type(self) -> SymbolType:
+        """
+        The type of the symbol.
+        """
+        return SymbolType(_lib.clingo_symbol_type(self._rep))
+
+

Instance variables

+
+
var arguments : List[Symbol]
+
+

The arguments of a function.

+
+ +Expand source code + +
@property
+def arguments(self) -> List["Symbol"]:
+    """
+    The arguments of a function.
+    """
+    args, size = _c_call2(
+        "clingo_symbol_t*", "size_t", _lib.clingo_symbol_arguments, self._rep
+    )
+    return [Symbol(args[i]) for i in range(size)]
+
+
+
var name : str
+
+

The name of a function.

+
+ +Expand source code + +
@property
+def name(self) -> str:
+    """
+    The name of a function.
+    """
+    return _to_str(_c_call("char*", _lib.clingo_symbol_name, self._rep))
+
+
+
var negative : bool
+
+

The inverted sign of a function.

+
+ +Expand source code + +
@property
+def negative(self) -> bool:
+    """
+    The inverted sign of a function.
+    """
+    return _c_call("bool", _lib.clingo_symbol_is_negative, self._rep)
+
+
+
var number : int
+
+

The value of a number.

+
+ +Expand source code + +
@property
+def number(self) -> int:
+    """
+    The value of a number.
+    """
+    return _c_call("int", _lib.clingo_symbol_number, self._rep)
+
+
+
var positive : bool
+
+

The sign of a function.

+
+ +Expand source code + +
@property
+def positive(self) -> bool:
+    """
+    The sign of a function.
+    """
+    return _c_call("bool", _lib.clingo_symbol_is_positive, self._rep)
+
+
+
var string : str
+
+

The value of a string.

+
+ +Expand source code + +
@property
+def string(self) -> str:
+    """
+    The value of a string.
+    """
+    return _to_str(_c_call("char*", _lib.clingo_symbol_string, self._rep))
+
+
+
var typeSymbolType
+
+

The type of the symbol.

+
+ +Expand source code + +
@property
+def type(self) -> SymbolType:
+    """
+    The type of the symbol.
+    """
+    return SymbolType(_lib.clingo_symbol_type(self._rep))
+
+
+
+

Methods

+
+
+def match(self, name: str, arity: int, positive: bool = True) ‑> bool +
+
+

Check if this is a function symbol with the given signature.

+

Parameters

+
+
name
+
The name of the function.
+
arity
+
The arity of the function.
+
positive
+
Whether to match positive or negative signatures.
+
+

Returns

+

Whether the function matches.

+
+ +Expand source code + +
def match(self, name: str, arity: int, positive: bool = True) -> bool:
+    """
+    Check if this is a function symbol with the given signature.
+
+    Parameters
+    ----------
+    name
+        The name of the function.
+
+    arity
+        The arity of the function.
+
+    positive
+        Whether to match positive or negative signatures.
+
+    Returns
+    -------
+    Whether the function matches.
+    """
+    return (
+        self.type == SymbolType.Function
+        and self.positive == positive
+        and self.name == name
+        and len(self.arguments) == arity
+    )
+
+
+
+
+
+class SymbolType +(value, names=None, *, module=None, qualname=None, type=None, start=1) +
+
+

Enumeration of symbols types.

+
+ +Expand source code + +
class SymbolType(OrderedEnum):
+    """
+    Enumeration of symbols types.
+    """
+
+    Function = _lib.clingo_symbol_type_function
+    """
+    A function symbol, e.g., `c`, `(1,"a")`, or `f(1,"a")`.
+    """
+    Infimum = _lib.clingo_symbol_type_infimum
+    """
+    The `#inf` symbol.
+    """
+    Number = _lib.clingo_symbol_type_number
+    """
+    A numeric symbol, e.g., `1`.
+    """
+    String = _lib.clingo_symbol_type_string
+    """
+    A string symbol, e.g., `"a"`.
+    """
+    Supremum = _lib.clingo_symbol_type_supremum
+    """
+    The `#sup` symbol
+    """
+
+

Ancestors

+ +

Class variables

+
+
var Function
+
+

A function symbol, e.g., c, (1,"a"), or f(1,"a").

+
+
var Infimum
+
+

The #inf symbol.

+
+
var Number
+
+

A numeric symbol, e.g., 1.

+
+
var String
+
+

A string symbol, e.g., "a".

+
+
var Supremum
+
+

The #sup symbol

+
+
+
+
+
+
+ +
+ + + \ No newline at end of file diff --git a/clingo/python-api/5.7/clingo/symbolic_atoms.html b/clingo/python-api/5.7/clingo/symbolic_atoms.html new file mode 100644 index 0000000..635e12d --- /dev/null +++ b/clingo/python-api/5.7/clingo/symbolic_atoms.html @@ -0,0 +1,704 @@ + + + + + + +clingo.symbolic_atoms API documentation + + + + + + + + + + + +
+
+
+

Module clingo.symbolic_atoms

+
+
+

Functions and classes to work with symbolic atoms.

+

Examples

+
>>> from clingo.symbol import Function, Number
+>>> from clingo.control import Control
+>>> ctl = Control()
+>>> ctl.add('base', [], """\
+... p(1).
+... { p(3) }.
+... #external p(1..3).
+...
+... q(X) :- p(X).
+... """)
+>>> ctl.ground([("base", [])])
+>>> len(ctl.symbolic_atoms)
+6
+>>> ctl.symbolic_atoms[Function("p", [Number(2)])] is not None
+True
+>>> ctl.symbolic_atoms[Function("p", [Number(4)])] is None
+True
+>>> ctl.symbolic_atoms.signatures
+[('p', 1, True), ('q', 1, True)]
+>>> [(str(x.symbol), x.is_fact, x.is_external)
+...  for x in ctl.symbolic_atoms.by_signature("p", 1)]
+[('p(1)', True, False), ('p(3)', False, False), ('p(2)', False, True)]
+
+
+ +Expand source code + +
'''
+Functions and classes to work with symbolic atoms.
+
+Examples
+--------
+
+    >>> from clingo.symbol import Function, Number
+    >>> from clingo.control import Control
+    >>> ctl = Control()
+    >>> ctl.add('base', [], """\\
+    ... p(1).
+    ... { p(3) }.
+    ... #external p(1..3).
+    ...
+    ... q(X) :- p(X).
+    ... """)
+    >>> ctl.ground([("base", [])])
+    >>> len(ctl.symbolic_atoms)
+    6
+    >>> ctl.symbolic_atoms[Function("p", [Number(2)])] is not None
+    True
+    >>> ctl.symbolic_atoms[Function("p", [Number(4)])] is None
+    True
+    >>> ctl.symbolic_atoms.signatures
+    [('p', 1, True), ('q', 1, True)]
+    >>> [(str(x.symbol), x.is_fact, x.is_external)
+    ...  for x in ctl.symbolic_atoms.by_signature("p", 1)]
+    [('p(1)', True, False), ('p(3)', False, False), ('p(2)', False, True)]
+'''
+
+from typing import Collection, Iterator, List, Optional, Tuple
+
+from ._internal import _c_call, _ffi, _handle_error, _lib, _to_str
+from .symbol import Symbol
+
+__all__ = ["SymbolicAtom", "SymbolicAtoms"]
+
+
+class SymbolicAtom:
+    """
+    Captures a symbolic atom and provides properties to inspect its state.
+    """
+
+    def __init__(self, rep, it):
+        self._rep = rep
+        self._it = it
+
+    def match(self, name: str, arity: int, positive: bool = True) -> bool:
+        """
+        Check if the atom matches the given signature.
+
+        Parameters
+        ----------
+        name
+            The name of the function.
+
+        arity
+            The arity of the function.
+
+        positive
+            Whether to match positive or negative signatures.
+
+        Returns
+        -------
+        Whether the atom matches.
+
+        See Also
+        --------
+        clingo.symbol.Symbol.match
+        """
+        return self.symbol.match(name, arity, positive)
+
+    @property
+    def is_external(self) -> bool:
+        """
+        Whether the atom is an external atom.
+        """
+        return _c_call(
+            "bool", _lib.clingo_symbolic_atoms_is_external, self._rep, self._it
+        )
+
+    @property
+    def is_fact(self) -> bool:
+        """
+        Whether the atom is a fact.
+        """
+        return _c_call("bool", _lib.clingo_symbolic_atoms_is_fact, self._rep, self._it)
+
+    @property
+    def literal(self) -> int:
+        """
+        The program literal associated with the atom.
+        """
+        return _c_call(
+            "clingo_literal_t", _lib.clingo_symbolic_atoms_literal, self._rep, self._it
+        )
+
+    @property
+    def symbol(self) -> Symbol:
+        """
+        The representation of the atom in form of a symbol.
+        """
+        return Symbol(
+            _c_call(
+                "clingo_symbol_t",
+                _lib.clingo_symbolic_atoms_symbol,
+                self._rep,
+                self._it,
+            )
+        )
+
+
+class SymbolicAtoms(Collection[SymbolicAtom]):
+    """
+    This class provides read-only access to the atom base of the grounder.
+    """
+
+    def __init__(self, rep):
+        self._rep = rep
+
+    def _iter(self, p_sig) -> Iterator[SymbolicAtom]:
+        p_it = _ffi.new("clingo_symbolic_atom_iterator_t*")
+        p_valid = _ffi.new("bool*")
+        _handle_error(_lib.clingo_symbolic_atoms_begin(self._rep, p_sig, p_it))
+        while _c_call(p_valid, _lib.clingo_symbolic_atoms_is_valid, self._rep, p_it[0]):
+            yield SymbolicAtom(self._rep, p_it[0])
+            _handle_error(_lib.clingo_symbolic_atoms_next(self._rep, p_it[0], p_it))
+
+    def __iter__(self) -> Iterator[SymbolicAtom]:
+        yield from self._iter(_ffi.NULL)
+
+    def __contains__(self, symbol) -> bool:
+        if not isinstance(symbol, Symbol):
+            return False
+
+        it = _c_call(
+            "clingo_symbolic_atom_iterator_t",
+            _lib.clingo_symbolic_atoms_find,
+            self._rep,
+            symbol._rep,
+        )
+
+        return _c_call("bool", _lib.clingo_symbolic_atoms_is_valid, self._rep, it)
+
+    def __getitem__(self, symbol: Symbol) -> Optional[SymbolicAtom]:
+        it = _c_call(
+            "clingo_symbolic_atom_iterator_t",
+            _lib.clingo_symbolic_atoms_find,
+            self._rep,
+            symbol._rep,
+        )
+
+        if not _c_call("bool", _lib.clingo_symbolic_atoms_is_valid, self._rep, it):
+            return None
+
+        return SymbolicAtom(self._rep, it)
+
+    def __len__(self) -> int:
+        return _c_call("size_t", _lib.clingo_symbolic_atoms_size, self._rep)
+
+    def by_signature(
+        self, name: str, arity: int, positive: bool = True
+    ) -> Iterator[SymbolicAtom]:
+        """
+        Return an iterator over the symbolic atoms with the given signature.
+
+        Arguments
+        ---------
+        name
+            The name of the signature.
+        arity
+            The arity of the signature.
+        positive
+            The sign of the signature.
+        """
+        p_sig = _ffi.new("clingo_signature_t*")
+        _handle_error(
+            _lib.clingo_signature_create(name.encode(), arity, positive, p_sig)
+        )
+        yield from self._iter(p_sig)
+
+    @property
+    def signatures(self) -> List[Tuple[str, int, bool]]:
+        """
+        The list of predicate signatures occurring in the program.
+
+        The Boolean indicates the sign of the signature.
+        """
+        size = _c_call("size_t", _lib.clingo_symbolic_atoms_signatures_size, self._rep)
+
+        p_sigs = _ffi.new("clingo_signature_t[]", size)
+        _handle_error(_lib.clingo_symbolic_atoms_signatures(self._rep, p_sigs, size))
+
+        return [
+            (
+                _to_str(_lib.clingo_signature_name(c_sig)),
+                _lib.clingo_signature_arity(c_sig),
+                _lib.clingo_signature_is_positive(c_sig),
+            )
+            for c_sig in p_sigs
+        ]
+
+
+
+
+
+
+
+
+
+

Classes

+
+
+class SymbolicAtom +(rep, it) +
+
+

Captures a symbolic atom and provides properties to inspect its state.

+
+ +Expand source code + +
class SymbolicAtom:
+    """
+    Captures a symbolic atom and provides properties to inspect its state.
+    """
+
+    def __init__(self, rep, it):
+        self._rep = rep
+        self._it = it
+
+    def match(self, name: str, arity: int, positive: bool = True) -> bool:
+        """
+        Check if the atom matches the given signature.
+
+        Parameters
+        ----------
+        name
+            The name of the function.
+
+        arity
+            The arity of the function.
+
+        positive
+            Whether to match positive or negative signatures.
+
+        Returns
+        -------
+        Whether the atom matches.
+
+        See Also
+        --------
+        clingo.symbol.Symbol.match
+        """
+        return self.symbol.match(name, arity, positive)
+
+    @property
+    def is_external(self) -> bool:
+        """
+        Whether the atom is an external atom.
+        """
+        return _c_call(
+            "bool", _lib.clingo_symbolic_atoms_is_external, self._rep, self._it
+        )
+
+    @property
+    def is_fact(self) -> bool:
+        """
+        Whether the atom is a fact.
+        """
+        return _c_call("bool", _lib.clingo_symbolic_atoms_is_fact, self._rep, self._it)
+
+    @property
+    def literal(self) -> int:
+        """
+        The program literal associated with the atom.
+        """
+        return _c_call(
+            "clingo_literal_t", _lib.clingo_symbolic_atoms_literal, self._rep, self._it
+        )
+
+    @property
+    def symbol(self) -> Symbol:
+        """
+        The representation of the atom in form of a symbol.
+        """
+        return Symbol(
+            _c_call(
+                "clingo_symbol_t",
+                _lib.clingo_symbolic_atoms_symbol,
+                self._rep,
+                self._it,
+            )
+        )
+
+

Instance variables

+
+
var is_external : bool
+
+

Whether the atom is an external atom.

+
+ +Expand source code + +
@property
+def is_external(self) -> bool:
+    """
+    Whether the atom is an external atom.
+    """
+    return _c_call(
+        "bool", _lib.clingo_symbolic_atoms_is_external, self._rep, self._it
+    )
+
+
+
var is_fact : bool
+
+

Whether the atom is a fact.

+
+ +Expand source code + +
@property
+def is_fact(self) -> bool:
+    """
+    Whether the atom is a fact.
+    """
+    return _c_call("bool", _lib.clingo_symbolic_atoms_is_fact, self._rep, self._it)
+
+
+
var literal : int
+
+

The program literal associated with the atom.

+
+ +Expand source code + +
@property
+def literal(self) -> int:
+    """
+    The program literal associated with the atom.
+    """
+    return _c_call(
+        "clingo_literal_t", _lib.clingo_symbolic_atoms_literal, self._rep, self._it
+    )
+
+
+
var symbolSymbol
+
+

The representation of the atom in form of a symbol.

+
+ +Expand source code + +
@property
+def symbol(self) -> Symbol:
+    """
+    The representation of the atom in form of a symbol.
+    """
+    return Symbol(
+        _c_call(
+            "clingo_symbol_t",
+            _lib.clingo_symbolic_atoms_symbol,
+            self._rep,
+            self._it,
+        )
+    )
+
+
+
+

Methods

+
+
+def match(self, name: str, arity: int, positive: bool = True) ‑> bool +
+
+

Check if the atom matches the given signature.

+

Parameters

+
+
name
+
The name of the function.
+
arity
+
The arity of the function.
+
positive
+
Whether to match positive or negative signatures.
+
+

Returns

+

Whether the atom matches.

+

See Also

+

Symbol.match()

+
+ +Expand source code + +
def match(self, name: str, arity: int, positive: bool = True) -> bool:
+    """
+    Check if the atom matches the given signature.
+
+    Parameters
+    ----------
+    name
+        The name of the function.
+
+    arity
+        The arity of the function.
+
+    positive
+        Whether to match positive or negative signatures.
+
+    Returns
+    -------
+    Whether the atom matches.
+
+    See Also
+    --------
+    clingo.symbol.Symbol.match
+    """
+    return self.symbol.match(name, arity, positive)
+
+
+
+
+
+class SymbolicAtoms +(rep) +
+
+

This class provides read-only access to the atom base of the grounder.

+
+ +Expand source code + +
class SymbolicAtoms(Collection[SymbolicAtom]):
+    """
+    This class provides read-only access to the atom base of the grounder.
+    """
+
+    def __init__(self, rep):
+        self._rep = rep
+
+    def _iter(self, p_sig) -> Iterator[SymbolicAtom]:
+        p_it = _ffi.new("clingo_symbolic_atom_iterator_t*")
+        p_valid = _ffi.new("bool*")
+        _handle_error(_lib.clingo_symbolic_atoms_begin(self._rep, p_sig, p_it))
+        while _c_call(p_valid, _lib.clingo_symbolic_atoms_is_valid, self._rep, p_it[0]):
+            yield SymbolicAtom(self._rep, p_it[0])
+            _handle_error(_lib.clingo_symbolic_atoms_next(self._rep, p_it[0], p_it))
+
+    def __iter__(self) -> Iterator[SymbolicAtom]:
+        yield from self._iter(_ffi.NULL)
+
+    def __contains__(self, symbol) -> bool:
+        if not isinstance(symbol, Symbol):
+            return False
+
+        it = _c_call(
+            "clingo_symbolic_atom_iterator_t",
+            _lib.clingo_symbolic_atoms_find,
+            self._rep,
+            symbol._rep,
+        )
+
+        return _c_call("bool", _lib.clingo_symbolic_atoms_is_valid, self._rep, it)
+
+    def __getitem__(self, symbol: Symbol) -> Optional[SymbolicAtom]:
+        it = _c_call(
+            "clingo_symbolic_atom_iterator_t",
+            _lib.clingo_symbolic_atoms_find,
+            self._rep,
+            symbol._rep,
+        )
+
+        if not _c_call("bool", _lib.clingo_symbolic_atoms_is_valid, self._rep, it):
+            return None
+
+        return SymbolicAtom(self._rep, it)
+
+    def __len__(self) -> int:
+        return _c_call("size_t", _lib.clingo_symbolic_atoms_size, self._rep)
+
+    def by_signature(
+        self, name: str, arity: int, positive: bool = True
+    ) -> Iterator[SymbolicAtom]:
+        """
+        Return an iterator over the symbolic atoms with the given signature.
+
+        Arguments
+        ---------
+        name
+            The name of the signature.
+        arity
+            The arity of the signature.
+        positive
+            The sign of the signature.
+        """
+        p_sig = _ffi.new("clingo_signature_t*")
+        _handle_error(
+            _lib.clingo_signature_create(name.encode(), arity, positive, p_sig)
+        )
+        yield from self._iter(p_sig)
+
+    @property
+    def signatures(self) -> List[Tuple[str, int, bool]]:
+        """
+        The list of predicate signatures occurring in the program.
+
+        The Boolean indicates the sign of the signature.
+        """
+        size = _c_call("size_t", _lib.clingo_symbolic_atoms_signatures_size, self._rep)
+
+        p_sigs = _ffi.new("clingo_signature_t[]", size)
+        _handle_error(_lib.clingo_symbolic_atoms_signatures(self._rep, p_sigs, size))
+
+        return [
+            (
+                _to_str(_lib.clingo_signature_name(c_sig)),
+                _lib.clingo_signature_arity(c_sig),
+                _lib.clingo_signature_is_positive(c_sig),
+            )
+            for c_sig in p_sigs
+        ]
+
+

Ancestors

+
    +
  • collections.abc.Collection
  • +
  • collections.abc.Sized
  • +
  • collections.abc.Iterable
  • +
  • collections.abc.Container
  • +
  • typing.Generic
  • +
+

Instance variables

+
+
var signatures : List[Tuple[str, int, bool]]
+
+

The list of predicate signatures occurring in the program.

+

The Boolean indicates the sign of the signature.

+
+ +Expand source code + +
@property
+def signatures(self) -> List[Tuple[str, int, bool]]:
+    """
+    The list of predicate signatures occurring in the program.
+
+    The Boolean indicates the sign of the signature.
+    """
+    size = _c_call("size_t", _lib.clingo_symbolic_atoms_signatures_size, self._rep)
+
+    p_sigs = _ffi.new("clingo_signature_t[]", size)
+    _handle_error(_lib.clingo_symbolic_atoms_signatures(self._rep, p_sigs, size))
+
+    return [
+        (
+            _to_str(_lib.clingo_signature_name(c_sig)),
+            _lib.clingo_signature_arity(c_sig),
+            _lib.clingo_signature_is_positive(c_sig),
+        )
+        for c_sig in p_sigs
+    ]
+
+
+
+

Methods

+
+
+def by_signature(self, name: str, arity: int, positive: bool = True) ‑> Iterator[SymbolicAtom] +
+
+

Return an iterator over the symbolic atoms with the given signature.

+

Arguments

+
+
name
+
The name of the signature.
+
arity
+
The arity of the signature.
+
positive
+
The sign of the signature.
+
+
+ +Expand source code + +
def by_signature(
+    self, name: str, arity: int, positive: bool = True
+) -> Iterator[SymbolicAtom]:
+    """
+    Return an iterator over the symbolic atoms with the given signature.
+
+    Arguments
+    ---------
+    name
+        The name of the signature.
+    arity
+        The arity of the signature.
+    positive
+        The sign of the signature.
+    """
+    p_sig = _ffi.new("clingo_signature_t*")
+    _handle_error(
+        _lib.clingo_signature_create(name.encode(), arity, positive, p_sig)
+    )
+    yield from self._iter(p_sig)
+
+
+
+
+
+
+
+ +
+ + + \ No newline at end of file diff --git a/clingo/python-api/5.7/clingo/theory.html b/clingo/python-api/5.7/clingo/theory.html new file mode 100644 index 0000000..5658472 --- /dev/null +++ b/clingo/python-api/5.7/clingo/theory.html @@ -0,0 +1,1400 @@ + + + + + + +clingo.theory API documentation + + + + + + + + + + + +
+
+
+

Module clingo.theory

+
+
+

This module defines the Theory class for using a CFFI based module with +clingo's Python package.

+

Example

+
>>> from clingo import Control
+>>> from clingo.ast import parse_string, ProgramBuilder
+>>> from clingo.theory import Theory
+>>> from clingcon._clingcon import lib, ffi
+>>>
+>>> prg = '&sum { x } >= 1. &sum { x } <= 3.'
+>>>
+>>> thy = Theory('clingcon', lib, ffi)
+>>> ctl = Control(['0'])
+>>> thy.register(ctl)
+>>> with ProgramBuilder(ctl) as bld:
+...     parse_string(prg, lambda ast: thy.rewrite_ast(ast, bld.add))
+...
+>>> ctl.ground([('base', [])])
+>>> thy.prepare(ctl)
+>>> with ctl.solve(yield_=True, on_model=thy.on_model) as hnd:
+...     for mdl in hnd:
+...         print([f'{key}={val}' for key, val in thy.assignment(mdl.thread_id)])
+...
+['x=1']
+['x=2']
+['x=3']
+
+

Notes

+

The CFFI module must provide the following functions and data structures, where +PREFIX corresponds to the prefix string passed to the Theory constructor:

+
enum PREFIX_value_type {
+    PREFIX_value_type_int = 0,
+    PREFIX_value_type_double = 1,
+    PREFIX_value_type_symbol = 2
+};
+typedef int PREFIX_value_type_t;
+typedef struct PREFIX_value {
+    PREFIX_value_type_t type;
+    union {
+        int int_number;
+        double double_number;
+        clingo_symbol_t symbol;
+    };
+} PREFIX_value_t;
+typedef bool (*PREFIX_ast_callback_t)(clingo_ast_t *ast, void *data);
+
+bool PREFIX_create(PREFIX_theory_t **theory)
+bool PREFIX_destroy(PREFIX_theory_t *theory)
+bool PREFIX_version(PREFIX_theory_t **theory, int *major, int *minor, int *patch);
+bool PREFIX_register(PREFIX_theory_t *theory, clingo_control_t* control)
+bool PREFIX_rewrite_ast(PREFIX_theory_t *theory, clingo_ast_t *ast, PREFIX_ast_callback_t add, void *data);
+bool PREFIX_prepare(PREFIX_theory_t *theory, clingo_control_t* control)
+bool PREFIX_register_options(PREFIX_theory_t *theory, clingo_options_t* options)
+bool PREFIX_validate_options(PREFIX_theory_t *theory)
+bool PREFIX_on_model(PREFIX_theory_t *theory, clingo_model_t* model)
+bool PREFIX_on_statistics(PREFIX_theory_t *theory, clingo_statistics_t* step, clingo_statistics_t* accu)
+bool PREFIX_lookup_symbol(PREFIX_theory_t *theory, clingo_symbol_t symbol, size_t *index)
+clingo_symbol_t PREFIX_get_symbol(PREFIX_theory_t *theory, size_t index)
+void PREFIX_assignment_begin(PREFIX_theory_t *theory, uint32_t thread_id, size_t *index)
+bool PREFIX_assignment_next(PREFIX_theory_t *theory, uint32_t thread_id, size_t *index)
+bool PREFIX_assignment_has_value(PREFIX_theory_t *theory, uint32_t thread_id, size_t index)
+void PREFIX_assignment_get_value(PREFIX_theory_t *theory, uint32_t thread_id, size_t index, PREFIX_value_t *value)
+bool PREFIX_configure(PREFIX_theory_t *theory, char const *key, char const *value)
+
+
+ +Expand source code + +
"""
+This module defines the `Theory` class for using a [CFFI] based module with
+clingo's Python package.
+
+[CFFI]: https://cffi.readthedocs.io/en/latest/
+
+Example
+-------
+
+```python
+>>> from clingo import Control
+>>> from clingo.ast import parse_string, ProgramBuilder
+>>> from clingo.theory import Theory
+>>> from clingcon._clingcon import lib, ffi
+>>>
+>>> prg = '&sum { x } >= 1. &sum { x } <= 3.'
+>>>
+>>> thy = Theory('clingcon', lib, ffi)
+>>> ctl = Control(['0'])
+>>> thy.register(ctl)
+>>> with ProgramBuilder(ctl) as bld:
+...     parse_string(prg, lambda ast: thy.rewrite_ast(ast, bld.add))
+...
+>>> ctl.ground([('base', [])])
+>>> thy.prepare(ctl)
+>>> with ctl.solve(yield_=True, on_model=thy.on_model) as hnd:
+...     for mdl in hnd:
+...         print([f'{key}={val}' for key, val in thy.assignment(mdl.thread_id)])
+...
+['x=1']
+['x=2']
+['x=3']
+```
+
+Notes
+-----
+The CFFI module must provide the following functions and data structures, where
+`PREFIX` corresponds to the prefix string passed to the `Theory` constructor:
+
+```c
+enum PREFIX_value_type {
+    PREFIX_value_type_int = 0,
+    PREFIX_value_type_double = 1,
+    PREFIX_value_type_symbol = 2
+};
+typedef int PREFIX_value_type_t;
+typedef struct PREFIX_value {
+    PREFIX_value_type_t type;
+    union {
+        int int_number;
+        double double_number;
+        clingo_symbol_t symbol;
+    };
+} PREFIX_value_t;
+typedef bool (*PREFIX_ast_callback_t)(clingo_ast_t *ast, void *data);
+
+bool PREFIX_create(PREFIX_theory_t **theory)
+bool PREFIX_destroy(PREFIX_theory_t *theory)
+bool PREFIX_version(PREFIX_theory_t **theory, int *major, int *minor, int *patch);
+bool PREFIX_register(PREFIX_theory_t *theory, clingo_control_t* control)
+bool PREFIX_rewrite_ast(PREFIX_theory_t *theory, clingo_ast_t *ast, PREFIX_ast_callback_t add, void *data);
+bool PREFIX_prepare(PREFIX_theory_t *theory, clingo_control_t* control)
+bool PREFIX_register_options(PREFIX_theory_t *theory, clingo_options_t* options)
+bool PREFIX_validate_options(PREFIX_theory_t *theory)
+bool PREFIX_on_model(PREFIX_theory_t *theory, clingo_model_t* model)
+bool PREFIX_on_statistics(PREFIX_theory_t *theory, clingo_statistics_t* step, clingo_statistics_t* accu)
+bool PREFIX_lookup_symbol(PREFIX_theory_t *theory, clingo_symbol_t symbol, size_t *index)
+clingo_symbol_t PREFIX_get_symbol(PREFIX_theory_t *theory, size_t index)
+void PREFIX_assignment_begin(PREFIX_theory_t *theory, uint32_t thread_id, size_t *index)
+bool PREFIX_assignment_next(PREFIX_theory_t *theory, uint32_t thread_id, size_t *index)
+bool PREFIX_assignment_has_value(PREFIX_theory_t *theory, uint32_t thread_id, size_t index)
+void PREFIX_assignment_get_value(PREFIX_theory_t *theory, uint32_t thread_id, size_t index, PREFIX_value_t *value)
+bool PREFIX_configure(PREFIX_theory_t *theory, char const *key, char const *value)
+```
+"""
+from typing import Any, Callable, Iterator, Optional, Tuple, Union
+
+from ._internal import _ffi, _handle_error, _lib
+from .control import Control
+from .application import ApplicationOptions
+from .solving import Model
+from .statistics import StatisticsMap
+from .symbol import Symbol
+from .ast import AST
+
+__all__ = ["Theory"]
+
+ValueType = Union[int, float, Symbol]
+
+
+class _CBData:  # pylint: disable=too-few-public-methods
+    """
+    The class stores the data object that should be passed to a callback as
+    well as provides the means to set an error while a callback is running.
+    """
+
+    def __init__(self, data):
+        self.data = data
+        self.error = None
+
+
+class Theory:
+    """
+    Interface to call functions from a C-library extending clingo's C/Python
+    library.
+
+    The functions in here are designed to be used with a `Application`
+    object but can also be used with a standalone `Control` object.
+    """
+
+    # pylint: disable=too-many-instance-attributes,line-too-long,protected-access
+
+    def __init__(self, prefix: str, lib: Any, ffi: Any):
+        """
+        Loads a given library.
+
+        Arguments
+        ---------
+        prefix
+            Prefix of functions and data structures in the library.
+        lib
+            [A CFFI lib object](https://cffi.readthedocs.io/en/latest/using.html).
+        ffi
+            [A CFFI ffi object](https://cffi.readthedocs.io/en/latest/ref.html).
+        """
+        self._pre = prefix
+        self._lib = lib
+        self._ffi = ffi
+        self._theory = self.__call1(self.__pre("theory_t*"), "create")
+        self._rewrite = self.__define_rewrite()
+
+    def __pre(self, name, extra=""):
+        return f"{extra}{self._pre}_{name}"
+
+    def __get(self, name, extra=""):
+        return getattr(self._lib, self.__pre(name, extra))
+
+    def __error_handler(self, exception, exc_value, traceback) -> bool:
+        if traceback is not None:
+            cb_data = self._ffi.from_handle(traceback.tb_frame.f_locals["data"])
+            cb_data.error = (exception, exc_value, traceback)
+            _lib.clingo_set_error(_lib.clingo_error_unknown, str(exc_value).encode())
+        else:
+            _lib.clingo_set_error(
+                _lib.clingo_error_runtime, "error in callback".encode()
+            )
+        return False
+
+    def __define_rewrite(self):
+        @self._ffi.def_extern(
+            name=self.__pre("rewrite", "py"), onerror=self.__error_handler
+        )
+        def rewrite(ast, data):
+            add = self._ffi.from_handle(data).data
+            ast = _ffi.cast("clingo_ast_t*", ast)
+            _lib.clingo_ast_acquire(ast)
+            add(AST(ast))
+            return True
+
+        return rewrite
+
+    def __call(self, c_fun, *args):
+        """
+        Helper to simplify calling C functions without error handling.
+        """
+        return self.__get(c_fun)(*args)
+
+    def __call0(self, c_fun, *args):
+        """
+        Helper to simplify calling C functions without a return value.
+        """
+        _handle_error(self.__call(c_fun, *args))
+
+    def __call1(self, c_type, c_fun, *args):
+        """
+        Helper to simplify calling C functions where the last parameter is a
+        reference to the return value.
+        """
+        if isinstance(c_type, str):
+            p_ret = self._ffi.new(f"{c_type}*")
+        else:
+            p_ret = c_type
+        _handle_error(self.__call(c_fun, *args, p_ret))
+        return p_ret[0]
+
+    def __del__(self):
+        if self._theory is not None:
+            self.__call0("destroy", self._theory)
+            self._theory = None
+
+    def version(self) -> Tuple[int, int, int]:
+        """
+        This function returns the version of the theory.
+
+        Returns
+        -------
+        A 3-tuple of integers representing major and minor version as well as
+        the patch level.
+        """
+        p_version = self._ffi.new("int[3]")
+        self.__call("version", p_version, p_version + 1, p_version + 2)
+        return p_version[0], p_version[1], p_version[2]
+
+    def configure(self, key: str, value: str) -> None:
+        """
+        Allows for configuring a theory via key/value pairs similar to
+        command line options.
+
+        This function must be called before the theory is registered.
+
+        Arguments
+        ---------
+        key
+            The name of the option.
+        value
+            The value of the option.
+        """
+        self.__call0("configure", self._theory, key.encode(), value.encode())
+
+    def register(self, control: Control) -> None:
+        """
+        Register the theory with the given control object.
+
+        Arguments
+        ---------
+        control
+            Target to register with.
+        """
+        self.__call0(
+            "register", self._theory, self._ffi.cast("clingo_control_t*", control._rep)
+        )
+
+    def prepare(self, control: Control) -> None:
+        """
+        Prepare the theory.
+
+        Must be called between ground and solve.
+
+        Arguments
+        ---------
+        control
+            The associated control object.
+        """
+        self.__call0(
+            "prepare", self._theory, self._ffi.cast("clingo_control_t*", control._rep)
+        )
+
+    def rewrite_ast(self, stm: AST, add: Callable[[AST], None]) -> None:
+        """
+        Rewrite the given statement and call add on the rewritten version(s).
+
+        Must be called for some theories that have to perform rewritings on the
+        AST.
+
+        Arguments
+        ---------
+        stm
+            Statement to translate.
+        add
+            Callback for adding translated statements.
+        """
+
+        cb_data = _CBData(add)
+        handle = self._ffi.new_handle(cb_data)
+        self.__call0(
+            "rewrite_ast",
+            self._theory,
+            self._ffi.cast("clingo_ast_t*", stm._rep),
+            self.__get("rewrite", "py"),
+            handle,
+        )
+
+    def register_options(self, options: ApplicationOptions) -> None:
+        """
+        Register the theory's options with the given application options
+        object.
+
+        Arguments
+        ---------
+        options
+            Target to register with.
+        """
+        self.__call0(
+            "register_options",
+            self._theory,
+            self._ffi.cast("clingo_options_t*", options._rep),
+        )
+
+    def validate_options(self) -> None:
+        """
+        Validate the options of the theory.
+        """
+        self.__call0("validate_options", self._theory)
+
+    def on_model(self, model: Model) -> None:
+        """
+        Inform the theory that a model has been found.
+
+        Arguments
+        ---------
+        model
+            The current model.
+        """
+        self.__call0(
+            "on_model", self._theory, self._ffi.cast("clingo_model_t*", model._rep)
+        )
+
+    def on_statistics(self, step: StatisticsMap, accu: StatisticsMap) -> None:
+        """
+        Add the theory's statistics to the given maps.
+
+        Arguments
+        ---------
+        step: StatisticsMap
+            Map for per step statistics.
+        accu: StatisticsMap
+            Map for accumulated statistics.
+        """
+        self.__call0(
+            "on_statistics",
+            self._theory,
+            self._ffi.cast("clingo_statistics_t*", step._rep),
+            self._ffi.cast("clingo_statistics_t*", accu._rep),
+        )
+
+    def lookup_symbol(self, symbol: Symbol) -> Optional[int]:
+        """
+        Get the integer index of a symbol assigned by the theory when a
+        model is found.
+
+        Using indices allows for efficent retrieval of values.
+
+        Arguments
+        ---------
+        symbol
+            The symbol to look up.
+
+        Returns
+        -------
+        The index of the value if found.
+        """
+        c_index = self._ffi.new("size_t*")
+        if self.__call("lookup_symbol", self._theory, symbol._rep, c_index):
+            return c_index[0]
+        return None
+
+    def get_symbol(self, index: int) -> Symbol:
+        """
+        Get the symbol associated with an index.
+
+        The index must be valid.
+
+        Arguments
+        ---------
+        index
+            Index to retreive.
+
+        Returns
+        -------
+        The associated symbol.
+        """
+        return Symbol(
+            _ffi.cast("clingo_symbol_t", self.__call("get_symbol", self._theory, index))
+        )
+
+    def has_value(self, thread_id: int, index: int) -> bool:
+        """
+        Check if the given symbol index has a value in the current model.
+
+        Arguments
+        ---------
+        thread_id
+            The index of the solving thread that found the model.
+        index
+            Index to retreive.
+
+        Returns
+        -------
+        Whether the given index has a value.
+        """
+        return self.__call("assignment_has_value", self._theory, thread_id, index)
+
+    def get_value(self, thread_id: int, index: int) -> ValueType:
+        """
+        Get the value of the symbol index in the current model.
+
+        Arguments
+        ---------
+        thread_id
+            The index of the solving thread that found the model.
+        index
+            Index to retreive.
+
+        Returns
+        -------
+        The value of the index in form of an int, float, or Symbol.
+        """
+        c_value = self._ffi.new(self.__pre("value_t*"))
+        self.__call("assignment_get_value", self._theory, thread_id, index, c_value)
+        if c_value.type == 0:
+            return c_value.int_number
+        if c_value.type == 1:
+            return c_value.double_number
+        if c_value.type == 2:
+            return Symbol(c_value.symbol)
+        raise RuntimeError("must not happen")
+
+    def assignment(self, thread_id: int) -> Iterator[Tuple[Symbol, ValueType]]:
+        """
+        Get all values symbol/value pairs assigned by the theory in the
+        current model.
+
+        Arguments
+        ---------
+        thread_id
+            The index of the solving thread that found the model.
+
+        Returns
+        -------
+        An iterator over symbol/value pairs.
+        """
+        c_index = self._ffi.new("size_t*")
+        self.__call("assignment_begin", self._theory, thread_id, c_index)
+        while self.__call("assignment_next", self._theory, thread_id, c_index):
+            yield (self.get_symbol(c_index[0]), self.get_value(thread_id, c_index[0]))
+
+
+
+
+
+
+
+
+
+

Classes

+
+
+class Theory +(prefix: str, lib: Any, ffi: Any) +
+
+

Interface to call functions from a C-library extending clingo's C/Python +library.

+

The functions in here are designed to be used with a Application +object but can also be used with a standalone Control object.

+

Loads a given library.

+

Arguments

+
+
prefix
+
Prefix of functions and data structures in the library.
+
lib
+
A CFFI lib object.
+
ffi
+
A CFFI ffi object.
+
+
+ +Expand source code + +
class Theory:
+    """
+    Interface to call functions from a C-library extending clingo's C/Python
+    library.
+
+    The functions in here are designed to be used with a `Application`
+    object but can also be used with a standalone `Control` object.
+    """
+
+    # pylint: disable=too-many-instance-attributes,line-too-long,protected-access
+
+    def __init__(self, prefix: str, lib: Any, ffi: Any):
+        """
+        Loads a given library.
+
+        Arguments
+        ---------
+        prefix
+            Prefix of functions and data structures in the library.
+        lib
+            [A CFFI lib object](https://cffi.readthedocs.io/en/latest/using.html).
+        ffi
+            [A CFFI ffi object](https://cffi.readthedocs.io/en/latest/ref.html).
+        """
+        self._pre = prefix
+        self._lib = lib
+        self._ffi = ffi
+        self._theory = self.__call1(self.__pre("theory_t*"), "create")
+        self._rewrite = self.__define_rewrite()
+
+    def __pre(self, name, extra=""):
+        return f"{extra}{self._pre}_{name}"
+
+    def __get(self, name, extra=""):
+        return getattr(self._lib, self.__pre(name, extra))
+
+    def __error_handler(self, exception, exc_value, traceback) -> bool:
+        if traceback is not None:
+            cb_data = self._ffi.from_handle(traceback.tb_frame.f_locals["data"])
+            cb_data.error = (exception, exc_value, traceback)
+            _lib.clingo_set_error(_lib.clingo_error_unknown, str(exc_value).encode())
+        else:
+            _lib.clingo_set_error(
+                _lib.clingo_error_runtime, "error in callback".encode()
+            )
+        return False
+
+    def __define_rewrite(self):
+        @self._ffi.def_extern(
+            name=self.__pre("rewrite", "py"), onerror=self.__error_handler
+        )
+        def rewrite(ast, data):
+            add = self._ffi.from_handle(data).data
+            ast = _ffi.cast("clingo_ast_t*", ast)
+            _lib.clingo_ast_acquire(ast)
+            add(AST(ast))
+            return True
+
+        return rewrite
+
+    def __call(self, c_fun, *args):
+        """
+        Helper to simplify calling C functions without error handling.
+        """
+        return self.__get(c_fun)(*args)
+
+    def __call0(self, c_fun, *args):
+        """
+        Helper to simplify calling C functions without a return value.
+        """
+        _handle_error(self.__call(c_fun, *args))
+
+    def __call1(self, c_type, c_fun, *args):
+        """
+        Helper to simplify calling C functions where the last parameter is a
+        reference to the return value.
+        """
+        if isinstance(c_type, str):
+            p_ret = self._ffi.new(f"{c_type}*")
+        else:
+            p_ret = c_type
+        _handle_error(self.__call(c_fun, *args, p_ret))
+        return p_ret[0]
+
+    def __del__(self):
+        if self._theory is not None:
+            self.__call0("destroy", self._theory)
+            self._theory = None
+
+    def version(self) -> Tuple[int, int, int]:
+        """
+        This function returns the version of the theory.
+
+        Returns
+        -------
+        A 3-tuple of integers representing major and minor version as well as
+        the patch level.
+        """
+        p_version = self._ffi.new("int[3]")
+        self.__call("version", p_version, p_version + 1, p_version + 2)
+        return p_version[0], p_version[1], p_version[2]
+
+    def configure(self, key: str, value: str) -> None:
+        """
+        Allows for configuring a theory via key/value pairs similar to
+        command line options.
+
+        This function must be called before the theory is registered.
+
+        Arguments
+        ---------
+        key
+            The name of the option.
+        value
+            The value of the option.
+        """
+        self.__call0("configure", self._theory, key.encode(), value.encode())
+
+    def register(self, control: Control) -> None:
+        """
+        Register the theory with the given control object.
+
+        Arguments
+        ---------
+        control
+            Target to register with.
+        """
+        self.__call0(
+            "register", self._theory, self._ffi.cast("clingo_control_t*", control._rep)
+        )
+
+    def prepare(self, control: Control) -> None:
+        """
+        Prepare the theory.
+
+        Must be called between ground and solve.
+
+        Arguments
+        ---------
+        control
+            The associated control object.
+        """
+        self.__call0(
+            "prepare", self._theory, self._ffi.cast("clingo_control_t*", control._rep)
+        )
+
+    def rewrite_ast(self, stm: AST, add: Callable[[AST], None]) -> None:
+        """
+        Rewrite the given statement and call add on the rewritten version(s).
+
+        Must be called for some theories that have to perform rewritings on the
+        AST.
+
+        Arguments
+        ---------
+        stm
+            Statement to translate.
+        add
+            Callback for adding translated statements.
+        """
+
+        cb_data = _CBData(add)
+        handle = self._ffi.new_handle(cb_data)
+        self.__call0(
+            "rewrite_ast",
+            self._theory,
+            self._ffi.cast("clingo_ast_t*", stm._rep),
+            self.__get("rewrite", "py"),
+            handle,
+        )
+
+    def register_options(self, options: ApplicationOptions) -> None:
+        """
+        Register the theory's options with the given application options
+        object.
+
+        Arguments
+        ---------
+        options
+            Target to register with.
+        """
+        self.__call0(
+            "register_options",
+            self._theory,
+            self._ffi.cast("clingo_options_t*", options._rep),
+        )
+
+    def validate_options(self) -> None:
+        """
+        Validate the options of the theory.
+        """
+        self.__call0("validate_options", self._theory)
+
+    def on_model(self, model: Model) -> None:
+        """
+        Inform the theory that a model has been found.
+
+        Arguments
+        ---------
+        model
+            The current model.
+        """
+        self.__call0(
+            "on_model", self._theory, self._ffi.cast("clingo_model_t*", model._rep)
+        )
+
+    def on_statistics(self, step: StatisticsMap, accu: StatisticsMap) -> None:
+        """
+        Add the theory's statistics to the given maps.
+
+        Arguments
+        ---------
+        step: StatisticsMap
+            Map for per step statistics.
+        accu: StatisticsMap
+            Map for accumulated statistics.
+        """
+        self.__call0(
+            "on_statistics",
+            self._theory,
+            self._ffi.cast("clingo_statistics_t*", step._rep),
+            self._ffi.cast("clingo_statistics_t*", accu._rep),
+        )
+
+    def lookup_symbol(self, symbol: Symbol) -> Optional[int]:
+        """
+        Get the integer index of a symbol assigned by the theory when a
+        model is found.
+
+        Using indices allows for efficent retrieval of values.
+
+        Arguments
+        ---------
+        symbol
+            The symbol to look up.
+
+        Returns
+        -------
+        The index of the value if found.
+        """
+        c_index = self._ffi.new("size_t*")
+        if self.__call("lookup_symbol", self._theory, symbol._rep, c_index):
+            return c_index[0]
+        return None
+
+    def get_symbol(self, index: int) -> Symbol:
+        """
+        Get the symbol associated with an index.
+
+        The index must be valid.
+
+        Arguments
+        ---------
+        index
+            Index to retreive.
+
+        Returns
+        -------
+        The associated symbol.
+        """
+        return Symbol(
+            _ffi.cast("clingo_symbol_t", self.__call("get_symbol", self._theory, index))
+        )
+
+    def has_value(self, thread_id: int, index: int) -> bool:
+        """
+        Check if the given symbol index has a value in the current model.
+
+        Arguments
+        ---------
+        thread_id
+            The index of the solving thread that found the model.
+        index
+            Index to retreive.
+
+        Returns
+        -------
+        Whether the given index has a value.
+        """
+        return self.__call("assignment_has_value", self._theory, thread_id, index)
+
+    def get_value(self, thread_id: int, index: int) -> ValueType:
+        """
+        Get the value of the symbol index in the current model.
+
+        Arguments
+        ---------
+        thread_id
+            The index of the solving thread that found the model.
+        index
+            Index to retreive.
+
+        Returns
+        -------
+        The value of the index in form of an int, float, or Symbol.
+        """
+        c_value = self._ffi.new(self.__pre("value_t*"))
+        self.__call("assignment_get_value", self._theory, thread_id, index, c_value)
+        if c_value.type == 0:
+            return c_value.int_number
+        if c_value.type == 1:
+            return c_value.double_number
+        if c_value.type == 2:
+            return Symbol(c_value.symbol)
+        raise RuntimeError("must not happen")
+
+    def assignment(self, thread_id: int) -> Iterator[Tuple[Symbol, ValueType]]:
+        """
+        Get all values symbol/value pairs assigned by the theory in the
+        current model.
+
+        Arguments
+        ---------
+        thread_id
+            The index of the solving thread that found the model.
+
+        Returns
+        -------
+        An iterator over symbol/value pairs.
+        """
+        c_index = self._ffi.new("size_t*")
+        self.__call("assignment_begin", self._theory, thread_id, c_index)
+        while self.__call("assignment_next", self._theory, thread_id, c_index):
+            yield (self.get_symbol(c_index[0]), self.get_value(thread_id, c_index[0]))
+
+

Methods

+
+
+def assignment(self, thread_id: int) ‑> Iterator[Tuple[Symbol, Union[int, float, Symbol]]] +
+
+

Get all values symbol/value pairs assigned by the theory in the +current model.

+

Arguments

+
+
thread_id
+
The index of the solving thread that found the model.
+
+

Returns

+

An iterator over symbol/value pairs.

+
+ +Expand source code + +
def assignment(self, thread_id: int) -> Iterator[Tuple[Symbol, ValueType]]:
+    """
+    Get all values symbol/value pairs assigned by the theory in the
+    current model.
+
+    Arguments
+    ---------
+    thread_id
+        The index of the solving thread that found the model.
+
+    Returns
+    -------
+    An iterator over symbol/value pairs.
+    """
+    c_index = self._ffi.new("size_t*")
+    self.__call("assignment_begin", self._theory, thread_id, c_index)
+    while self.__call("assignment_next", self._theory, thread_id, c_index):
+        yield (self.get_symbol(c_index[0]), self.get_value(thread_id, c_index[0]))
+
+
+
+def configure(self, key: str, value: str) ‑> None +
+
+

Allows for configuring a theory via key/value pairs similar to +command line options.

+

This function must be called before the theory is registered.

+

Arguments

+
+
key
+
The name of the option.
+
value
+
The value of the option.
+
+
+ +Expand source code + +
def configure(self, key: str, value: str) -> None:
+    """
+    Allows for configuring a theory via key/value pairs similar to
+    command line options.
+
+    This function must be called before the theory is registered.
+
+    Arguments
+    ---------
+    key
+        The name of the option.
+    value
+        The value of the option.
+    """
+    self.__call0("configure", self._theory, key.encode(), value.encode())
+
+
+
+def get_symbol(self, index: int) ‑> Symbol +
+
+

Get the symbol associated with an index.

+

The index must be valid.

+

Arguments

+
+
index
+
Index to retreive.
+
+

Returns

+

The associated symbol.

+
+ +Expand source code + +
def get_symbol(self, index: int) -> Symbol:
+    """
+    Get the symbol associated with an index.
+
+    The index must be valid.
+
+    Arguments
+    ---------
+    index
+        Index to retreive.
+
+    Returns
+    -------
+    The associated symbol.
+    """
+    return Symbol(
+        _ffi.cast("clingo_symbol_t", self.__call("get_symbol", self._theory, index))
+    )
+
+
+
+def get_value(self, thread_id: int, index: int) ‑> Union[int, float, Symbol] +
+
+

Get the value of the symbol index in the current model.

+

Arguments

+
+
thread_id
+
The index of the solving thread that found the model.
+
index
+
Index to retreive.
+
+

Returns

+

The value of the index in form of an int, float, or Symbol.

+
+ +Expand source code + +
def get_value(self, thread_id: int, index: int) -> ValueType:
+    """
+    Get the value of the symbol index in the current model.
+
+    Arguments
+    ---------
+    thread_id
+        The index of the solving thread that found the model.
+    index
+        Index to retreive.
+
+    Returns
+    -------
+    The value of the index in form of an int, float, or Symbol.
+    """
+    c_value = self._ffi.new(self.__pre("value_t*"))
+    self.__call("assignment_get_value", self._theory, thread_id, index, c_value)
+    if c_value.type == 0:
+        return c_value.int_number
+    if c_value.type == 1:
+        return c_value.double_number
+    if c_value.type == 2:
+        return Symbol(c_value.symbol)
+    raise RuntimeError("must not happen")
+
+
+
+def has_value(self, thread_id: int, index: int) ‑> bool +
+
+

Check if the given symbol index has a value in the current model.

+

Arguments

+
+
thread_id
+
The index of the solving thread that found the model.
+
index
+
Index to retreive.
+
+

Returns

+

Whether the given index has a value.

+
+ +Expand source code + +
def has_value(self, thread_id: int, index: int) -> bool:
+    """
+    Check if the given symbol index has a value in the current model.
+
+    Arguments
+    ---------
+    thread_id
+        The index of the solving thread that found the model.
+    index
+        Index to retreive.
+
+    Returns
+    -------
+    Whether the given index has a value.
+    """
+    return self.__call("assignment_has_value", self._theory, thread_id, index)
+
+
+
+def lookup_symbol(self, symbol: Symbol) ‑> Optional[int] +
+
+

Get the integer index of a symbol assigned by the theory when a +model is found.

+

Using indices allows for efficent retrieval of values.

+

Arguments

+
+
symbol
+
The symbol to look up.
+
+

Returns

+

The index of the value if found.

+
+ +Expand source code + +
def lookup_symbol(self, symbol: Symbol) -> Optional[int]:
+    """
+    Get the integer index of a symbol assigned by the theory when a
+    model is found.
+
+    Using indices allows for efficent retrieval of values.
+
+    Arguments
+    ---------
+    symbol
+        The symbol to look up.
+
+    Returns
+    -------
+    The index of the value if found.
+    """
+    c_index = self._ffi.new("size_t*")
+    if self.__call("lookup_symbol", self._theory, symbol._rep, c_index):
+        return c_index[0]
+    return None
+
+
+
+def on_model(self, model: Model) ‑> None +
+
+

Inform the theory that a model has been found.

+

Arguments

+
+
model
+
The current model.
+
+
+ +Expand source code + +
def on_model(self, model: Model) -> None:
+    """
+    Inform the theory that a model has been found.
+
+    Arguments
+    ---------
+    model
+        The current model.
+    """
+    self.__call0(
+        "on_model", self._theory, self._ffi.cast("clingo_model_t*", model._rep)
+    )
+
+
+
+def on_statistics(self, step: StatisticsMap, accu: StatisticsMap) ‑> None +
+
+

Add the theory's statistics to the given maps.

+

Arguments

+
+
step : StatisticsMap
+
Map for per step statistics.
+
accu : StatisticsMap
+
Map for accumulated statistics.
+
+
+ +Expand source code + +
def on_statistics(self, step: StatisticsMap, accu: StatisticsMap) -> None:
+    """
+    Add the theory's statistics to the given maps.
+
+    Arguments
+    ---------
+    step: StatisticsMap
+        Map for per step statistics.
+    accu: StatisticsMap
+        Map for accumulated statistics.
+    """
+    self.__call0(
+        "on_statistics",
+        self._theory,
+        self._ffi.cast("clingo_statistics_t*", step._rep),
+        self._ffi.cast("clingo_statistics_t*", accu._rep),
+    )
+
+
+
+def prepare(self, control: Control) ‑> None +
+
+

Prepare the theory.

+

Must be called between ground and solve.

+

Arguments

+
+
control
+
The associated control object.
+
+
+ +Expand source code + +
def prepare(self, control: Control) -> None:
+    """
+    Prepare the theory.
+
+    Must be called between ground and solve.
+
+    Arguments
+    ---------
+    control
+        The associated control object.
+    """
+    self.__call0(
+        "prepare", self._theory, self._ffi.cast("clingo_control_t*", control._rep)
+    )
+
+
+
+def register(self, control: Control) ‑> None +
+
+

Register the theory with the given control object.

+

Arguments

+
+
control
+
Target to register with.
+
+
+ +Expand source code + +
def register(self, control: Control) -> None:
+    """
+    Register the theory with the given control object.
+
+    Arguments
+    ---------
+    control
+        Target to register with.
+    """
+    self.__call0(
+        "register", self._theory, self._ffi.cast("clingo_control_t*", control._rep)
+    )
+
+
+
+def register_options(self, options: ApplicationOptions) ‑> None +
+
+

Register the theory's options with the given application options +object.

+

Arguments

+
+
options
+
Target to register with.
+
+
+ +Expand source code + +
def register_options(self, options: ApplicationOptions) -> None:
+    """
+    Register the theory's options with the given application options
+    object.
+
+    Arguments
+    ---------
+    options
+        Target to register with.
+    """
+    self.__call0(
+        "register_options",
+        self._theory,
+        self._ffi.cast("clingo_options_t*", options._rep),
+    )
+
+
+
+def rewrite_ast(self, stm: AST, add: Callable[[AST], None]) ‑> None +
+
+

Rewrite the given statement and call add on the rewritten version(s).

+

Must be called for some theories that have to perform rewritings on the +AST.

+

Arguments

+
+
stm
+
Statement to translate.
+
add
+
Callback for adding translated statements.
+
+
+ +Expand source code + +
def rewrite_ast(self, stm: AST, add: Callable[[AST], None]) -> None:
+    """
+    Rewrite the given statement and call add on the rewritten version(s).
+
+    Must be called for some theories that have to perform rewritings on the
+    AST.
+
+    Arguments
+    ---------
+    stm
+        Statement to translate.
+    add
+        Callback for adding translated statements.
+    """
+
+    cb_data = _CBData(add)
+    handle = self._ffi.new_handle(cb_data)
+    self.__call0(
+        "rewrite_ast",
+        self._theory,
+        self._ffi.cast("clingo_ast_t*", stm._rep),
+        self.__get("rewrite", "py"),
+        handle,
+    )
+
+
+
+def validate_options(self) ‑> None +
+
+

Validate the options of the theory.

+
+ +Expand source code + +
def validate_options(self) -> None:
+    """
+    Validate the options of the theory.
+    """
+    self.__call0("validate_options", self._theory)
+
+
+
+def version(self) ‑> Tuple[int, int, int] +
+
+

This function returns the version of the theory.

+

Returns

+
+
A 3-tuple of integers representing major and minor version as well as
+
 
+
+

the patch level.

+
+ +Expand source code + +
def version(self) -> Tuple[int, int, int]:
+    """
+    This function returns the version of the theory.
+
+    Returns
+    -------
+    A 3-tuple of integers representing major and minor version as well as
+    the patch level.
+    """
+    p_version = self._ffi.new("int[3]")
+    self.__call("version", p_version, p_version + 1, p_version + 2)
+    return p_version[0], p_version[1], p_version[2]
+
+
+
+
+
+
+
+ +
+ + + \ No newline at end of file diff --git a/clingo/python-api/5.7/clingo/theory_atoms.html b/clingo/python-api/5.7/clingo/theory_atoms.html new file mode 100644 index 0000000..7675c36 --- /dev/null +++ b/clingo/python-api/5.7/clingo/theory_atoms.html @@ -0,0 +1,1029 @@ + + + + + + +clingo.theory_atoms API documentation + + + + + + + + + + + +
+
+
+

Module clingo.theory_atoms

+
+
+

Functions and classes to work with theory atoms.

+

Examples

+
>>> from clingo.control import Control
+>>>
+>>> ctl = Control()
+>>> ctl.add('base', [], """\
+... #theory example {
+...     t { };
+...     &a/0 : t, head
+... }.
+... {c}.
+... &a { t: c }.
+... """)
+>>> ctl.ground([('base', [])])
+>>> atm = next(ctl.theory_atoms)
+>>> print(atm)
+&a{t: c}
+>>> elm = atm.elements[0]
+>>> print(elm)
+t: c
+
+
+ +Expand source code + +
'''
+Functions and classes to work with theory atoms.
+
+Examples
+--------
+    >>> from clingo.control import Control
+    >>>
+    >>> ctl = Control()
+    >>> ctl.add('base', [], """\\
+    ... #theory example {
+    ...     t { };
+    ...     &a/0 : t, head
+    ... }.
+    ... {c}.
+    ... &a { t: c }.
+    ... """)
+    >>> ctl.ground([('base', [])])
+    >>> atm = next(ctl.theory_atoms)
+    >>> print(atm)
+    &a{t: c}
+    >>> elm = atm.elements[0]
+    >>> print(elm)
+    t: c
+'''
+
+from typing import List, Optional, Tuple
+from functools import total_ordering
+
+from ._internal import _c_call, _c_call2, _lib, _str, _to_str
+from .core import OrderedEnum
+
+__all__ = ["TheoryAtom", "TheoryElement", "TheoryTerm", "TheoryTermType"]
+
+
+class TheoryTermType(OrderedEnum):
+    """
+    Enumeration of theory term types.
+    """
+
+    Function = _lib.clingo_theory_term_type_function
+    """
+    For a function theory terms.
+    """
+    List = _lib.clingo_theory_term_type_list
+    """
+    For list theory terms.
+    """
+    Number = _lib.clingo_theory_term_type_number
+    """
+    For numeric theory terms.
+    """
+    Set = _lib.clingo_theory_term_type_set
+    """
+    For set theory terms.
+    """
+    Symbol = _lib.clingo_theory_term_type_symbol
+    """
+    For symbolic theory terms (symbol here means the term is a string).
+    """
+    Tuple = _lib.clingo_theory_term_type_tuple
+    """
+    For tuple theory terms.
+    """
+
+
+@total_ordering
+class TheoryTerm:
+    """
+    `TheoryTerm` objects represent theory terms.
+
+    Theory terms have a readable string representation, implement Python's rich
+    comparison operators, and can be used as dictionary keys.
+    """
+
+    def __init__(self, rep, idx):
+        self._rep = rep
+        self._idx = idx
+
+    def __hash__(self):
+        return self._idx
+
+    def __eq__(self, other):
+        return self._idx == other._idx
+
+    def __lt__(self, other):
+        return self._idx < other._idx
+
+    def __str__(self):
+        return _str(
+            _lib.clingo_theory_atoms_term_to_string_size,
+            _lib.clingo_theory_atoms_term_to_string,
+            self._rep,
+            self._idx,
+        )
+
+    def __repr__(self):
+        return f"TheoryTerm({self._rep!r})"
+
+    @property
+    def arguments(self) -> List["TheoryTerm"]:
+        """
+        The arguments of the term (for functions, tuples, list, and sets).
+        """
+        args, size = _c_call2(
+            "clingo_id_t*",
+            "size_t",
+            _lib.clingo_theory_atoms_term_arguments,
+            self._rep,
+            self._idx,
+        )
+        return [TheoryTerm(self._rep, args[i]) for i in range(size)]
+
+    @property
+    def name(self) -> str:
+        """
+        The name of the term (for symbols and functions).
+        """
+        return _to_str(
+            _c_call("char*", _lib.clingo_theory_atoms_term_name, self._rep, self._idx)
+        )
+
+    @property
+    def number(self) -> int:
+        """
+        The numeric representation of the term (for numbers).
+        """
+        return _c_call(
+            "int", _lib.clingo_theory_atoms_term_number, self._rep, self._idx
+        )
+
+    @property
+    def type(self) -> TheoryTermType:
+        """
+        The type of the theory term.
+        """
+        type_ = _c_call(
+            "clingo_theory_term_type_t",
+            _lib.clingo_theory_atoms_term_type,
+            self._rep,
+            self._idx,
+        )
+        return TheoryTermType(type_)
+
+
+@total_ordering
+class TheoryElement:
+    """
+    Class to represent theory elements.
+
+    Theory elements have a readable string representation, implement Python's rich
+    comparison operators, and can be used as dictionary keys.
+    """
+
+    def __init__(self, rep, idx):
+        self._rep = rep
+        self._idx = idx
+
+    def __hash__(self):
+        return self._idx
+
+    def __eq__(self, other):
+        return self._idx == other._idx
+
+    def __lt__(self, other):
+        return self._idx < other._idx
+
+    def __str__(self):
+        return _str(
+            _lib.clingo_theory_atoms_element_to_string_size,
+            _lib.clingo_theory_atoms_element_to_string,
+            self._rep,
+            self._idx,
+        )
+
+    def __repr__(self):
+        return f"TheoryElement({self._rep!r})"
+
+    @property
+    def condition(self) -> List[int]:
+        """
+        The condition of the element in form of a list of program literals.
+        """
+        cond, size = _c_call2(
+            "clingo_literal_t*",
+            "size_t",
+            _lib.clingo_theory_atoms_element_condition,
+            self._rep,
+            self._idx,
+        )
+        return [cond[i] for i in range(size)]
+
+    @property
+    def condition_id(self) -> int:
+        """
+        Each condition has an id, which is a temporary program literal. This id
+        can be passed to `clingo.propagator.PropagateInit.solver_literal` to
+        obtain a corresponding solver literal.
+        """
+        return _c_call(
+            "clingo_literal_t",
+            _lib.clingo_theory_atoms_element_condition_id,
+            self._rep,
+            self._idx,
+        )
+
+    @property
+    def terms(self) -> List[TheoryTerm]:
+        """
+        The tuple of the element.
+        """
+        terms, size = _c_call2(
+            "clingo_id_t*",
+            "size_t",
+            _lib.clingo_theory_atoms_element_tuple,
+            self._rep,
+            self._idx,
+        )
+        return [TheoryTerm(self._rep, terms[i]) for i in range(size)]
+
+
+@total_ordering
+class TheoryAtom:
+    """
+    Class to represent theory atoms.
+
+    Theory atoms have a readable string representation, implement Python's rich
+    comparison operators, and can be used as dictionary keys.
+    """
+
+    def __init__(self, rep, idx):
+        self._rep = rep
+        self._idx = idx
+
+    def __hash__(self):
+        return self._idx
+
+    def __eq__(self, other):
+        return self._idx == other._idx
+
+    def __lt__(self, other):
+        return self._idx < other._idx
+
+    def __str__(self):
+        return _str(
+            _lib.clingo_theory_atoms_atom_to_string_size,
+            _lib.clingo_theory_atoms_atom_to_string,
+            self._rep,
+            self._idx,
+        )
+
+    def __repr__(self):
+        return f"TheoryAtom({self._rep!r})"
+
+    @property
+    def elements(self) -> List[TheoryElement]:
+        """
+        The elements of the atom.
+        """
+        elems, size = _c_call2(
+            "clingo_id_t*",
+            "size_t",
+            _lib.clingo_theory_atoms_atom_elements,
+            self._rep,
+            self._idx,
+        )
+        return [TheoryElement(self._rep, elems[i]) for i in range(size)]
+
+    @property
+    def guard(self) -> Optional[Tuple[str, TheoryTerm]]:
+        """
+        The guard of the atom or None if the atom has no guard.
+        """
+        if not _c_call(
+            "bool", _lib.clingo_theory_atoms_atom_has_guard, self._rep, self._idx
+        ):
+            return None
+
+        conn, term = _c_call2(
+            "char*",
+            "clingo_id_t",
+            _lib.clingo_theory_atoms_atom_guard,
+            self._rep,
+            self._idx,
+        )
+
+        return (_to_str(conn), TheoryTerm(self._rep, term))
+
+    @property
+    def literal(self) -> int:
+        """
+        The program literal associated with the atom.
+        """
+        return _c_call(
+            "clingo_literal_t",
+            _lib.clingo_theory_atoms_atom_literal,
+            self._rep,
+            self._idx,
+        )
+
+    @property
+    def term(self) -> TheoryTerm:
+        """
+        The term of the atom.
+        """
+        term = _c_call(
+            "clingo_id_t", _lib.clingo_theory_atoms_atom_term, self._rep, self._idx
+        )
+        return TheoryTerm(self._rep, term)
+
+
+
+
+
+
+
+
+
+

Classes

+
+
+class TheoryAtom +(rep, idx) +
+
+

Class to represent theory atoms.

+

Theory atoms have a readable string representation, implement Python's rich +comparison operators, and can be used as dictionary keys.

+
+ +Expand source code + +
@total_ordering
+class TheoryAtom:
+    """
+    Class to represent theory atoms.
+
+    Theory atoms have a readable string representation, implement Python's rich
+    comparison operators, and can be used as dictionary keys.
+    """
+
+    def __init__(self, rep, idx):
+        self._rep = rep
+        self._idx = idx
+
+    def __hash__(self):
+        return self._idx
+
+    def __eq__(self, other):
+        return self._idx == other._idx
+
+    def __lt__(self, other):
+        return self._idx < other._idx
+
+    def __str__(self):
+        return _str(
+            _lib.clingo_theory_atoms_atom_to_string_size,
+            _lib.clingo_theory_atoms_atom_to_string,
+            self._rep,
+            self._idx,
+        )
+
+    def __repr__(self):
+        return f"TheoryAtom({self._rep!r})"
+
+    @property
+    def elements(self) -> List[TheoryElement]:
+        """
+        The elements of the atom.
+        """
+        elems, size = _c_call2(
+            "clingo_id_t*",
+            "size_t",
+            _lib.clingo_theory_atoms_atom_elements,
+            self._rep,
+            self._idx,
+        )
+        return [TheoryElement(self._rep, elems[i]) for i in range(size)]
+
+    @property
+    def guard(self) -> Optional[Tuple[str, TheoryTerm]]:
+        """
+        The guard of the atom or None if the atom has no guard.
+        """
+        if not _c_call(
+            "bool", _lib.clingo_theory_atoms_atom_has_guard, self._rep, self._idx
+        ):
+            return None
+
+        conn, term = _c_call2(
+            "char*",
+            "clingo_id_t",
+            _lib.clingo_theory_atoms_atom_guard,
+            self._rep,
+            self._idx,
+        )
+
+        return (_to_str(conn), TheoryTerm(self._rep, term))
+
+    @property
+    def literal(self) -> int:
+        """
+        The program literal associated with the atom.
+        """
+        return _c_call(
+            "clingo_literal_t",
+            _lib.clingo_theory_atoms_atom_literal,
+            self._rep,
+            self._idx,
+        )
+
+    @property
+    def term(self) -> TheoryTerm:
+        """
+        The term of the atom.
+        """
+        term = _c_call(
+            "clingo_id_t", _lib.clingo_theory_atoms_atom_term, self._rep, self._idx
+        )
+        return TheoryTerm(self._rep, term)
+
+

Instance variables

+
+
var elements : List[TheoryElement]
+
+

The elements of the atom.

+
+ +Expand source code + +
@property
+def elements(self) -> List[TheoryElement]:
+    """
+    The elements of the atom.
+    """
+    elems, size = _c_call2(
+        "clingo_id_t*",
+        "size_t",
+        _lib.clingo_theory_atoms_atom_elements,
+        self._rep,
+        self._idx,
+    )
+    return [TheoryElement(self._rep, elems[i]) for i in range(size)]
+
+
+
var guard : Optional[Tuple[str, TheoryTerm]]
+
+

The guard of the atom or None if the atom has no guard.

+
+ +Expand source code + +
@property
+def guard(self) -> Optional[Tuple[str, TheoryTerm]]:
+    """
+    The guard of the atom or None if the atom has no guard.
+    """
+    if not _c_call(
+        "bool", _lib.clingo_theory_atoms_atom_has_guard, self._rep, self._idx
+    ):
+        return None
+
+    conn, term = _c_call2(
+        "char*",
+        "clingo_id_t",
+        _lib.clingo_theory_atoms_atom_guard,
+        self._rep,
+        self._idx,
+    )
+
+    return (_to_str(conn), TheoryTerm(self._rep, term))
+
+
+
var literal : int
+
+

The program literal associated with the atom.

+
+ +Expand source code + +
@property
+def literal(self) -> int:
+    """
+    The program literal associated with the atom.
+    """
+    return _c_call(
+        "clingo_literal_t",
+        _lib.clingo_theory_atoms_atom_literal,
+        self._rep,
+        self._idx,
+    )
+
+
+
var termTheoryTerm
+
+

The term of the atom.

+
+ +Expand source code + +
@property
+def term(self) -> TheoryTerm:
+    """
+    The term of the atom.
+    """
+    term = _c_call(
+        "clingo_id_t", _lib.clingo_theory_atoms_atom_term, self._rep, self._idx
+    )
+    return TheoryTerm(self._rep, term)
+
+
+
+
+
+class TheoryElement +(rep, idx) +
+
+

Class to represent theory elements.

+

Theory elements have a readable string representation, implement Python's rich +comparison operators, and can be used as dictionary keys.

+
+ +Expand source code + +
@total_ordering
+class TheoryElement:
+    """
+    Class to represent theory elements.
+
+    Theory elements have a readable string representation, implement Python's rich
+    comparison operators, and can be used as dictionary keys.
+    """
+
+    def __init__(self, rep, idx):
+        self._rep = rep
+        self._idx = idx
+
+    def __hash__(self):
+        return self._idx
+
+    def __eq__(self, other):
+        return self._idx == other._idx
+
+    def __lt__(self, other):
+        return self._idx < other._idx
+
+    def __str__(self):
+        return _str(
+            _lib.clingo_theory_atoms_element_to_string_size,
+            _lib.clingo_theory_atoms_element_to_string,
+            self._rep,
+            self._idx,
+        )
+
+    def __repr__(self):
+        return f"TheoryElement({self._rep!r})"
+
+    @property
+    def condition(self) -> List[int]:
+        """
+        The condition of the element in form of a list of program literals.
+        """
+        cond, size = _c_call2(
+            "clingo_literal_t*",
+            "size_t",
+            _lib.clingo_theory_atoms_element_condition,
+            self._rep,
+            self._idx,
+        )
+        return [cond[i] for i in range(size)]
+
+    @property
+    def condition_id(self) -> int:
+        """
+        Each condition has an id, which is a temporary program literal. This id
+        can be passed to `clingo.propagator.PropagateInit.solver_literal` to
+        obtain a corresponding solver literal.
+        """
+        return _c_call(
+            "clingo_literal_t",
+            _lib.clingo_theory_atoms_element_condition_id,
+            self._rep,
+            self._idx,
+        )
+
+    @property
+    def terms(self) -> List[TheoryTerm]:
+        """
+        The tuple of the element.
+        """
+        terms, size = _c_call2(
+            "clingo_id_t*",
+            "size_t",
+            _lib.clingo_theory_atoms_element_tuple,
+            self._rep,
+            self._idx,
+        )
+        return [TheoryTerm(self._rep, terms[i]) for i in range(size)]
+
+

Instance variables

+
+
var condition : List[int]
+
+

The condition of the element in form of a list of program literals.

+
+ +Expand source code + +
@property
+def condition(self) -> List[int]:
+    """
+    The condition of the element in form of a list of program literals.
+    """
+    cond, size = _c_call2(
+        "clingo_literal_t*",
+        "size_t",
+        _lib.clingo_theory_atoms_element_condition,
+        self._rep,
+        self._idx,
+    )
+    return [cond[i] for i in range(size)]
+
+
+
var condition_id : int
+
+

Each condition has an id, which is a temporary program literal. This id +can be passed to PropagateInit.solver_literal() to +obtain a corresponding solver literal.

+
+ +Expand source code + +
@property
+def condition_id(self) -> int:
+    """
+    Each condition has an id, which is a temporary program literal. This id
+    can be passed to `clingo.propagator.PropagateInit.solver_literal` to
+    obtain a corresponding solver literal.
+    """
+    return _c_call(
+        "clingo_literal_t",
+        _lib.clingo_theory_atoms_element_condition_id,
+        self._rep,
+        self._idx,
+    )
+
+
+
var terms : List[TheoryTerm]
+
+

The tuple of the element.

+
+ +Expand source code + +
@property
+def terms(self) -> List[TheoryTerm]:
+    """
+    The tuple of the element.
+    """
+    terms, size = _c_call2(
+        "clingo_id_t*",
+        "size_t",
+        _lib.clingo_theory_atoms_element_tuple,
+        self._rep,
+        self._idx,
+    )
+    return [TheoryTerm(self._rep, terms[i]) for i in range(size)]
+
+
+
+
+
+class TheoryTerm +(rep, idx) +
+
+

TheoryTerm objects represent theory terms.

+

Theory terms have a readable string representation, implement Python's rich +comparison operators, and can be used as dictionary keys.

+
+ +Expand source code + +
@total_ordering
+class TheoryTerm:
+    """
+    `TheoryTerm` objects represent theory terms.
+
+    Theory terms have a readable string representation, implement Python's rich
+    comparison operators, and can be used as dictionary keys.
+    """
+
+    def __init__(self, rep, idx):
+        self._rep = rep
+        self._idx = idx
+
+    def __hash__(self):
+        return self._idx
+
+    def __eq__(self, other):
+        return self._idx == other._idx
+
+    def __lt__(self, other):
+        return self._idx < other._idx
+
+    def __str__(self):
+        return _str(
+            _lib.clingo_theory_atoms_term_to_string_size,
+            _lib.clingo_theory_atoms_term_to_string,
+            self._rep,
+            self._idx,
+        )
+
+    def __repr__(self):
+        return f"TheoryTerm({self._rep!r})"
+
+    @property
+    def arguments(self) -> List["TheoryTerm"]:
+        """
+        The arguments of the term (for functions, tuples, list, and sets).
+        """
+        args, size = _c_call2(
+            "clingo_id_t*",
+            "size_t",
+            _lib.clingo_theory_atoms_term_arguments,
+            self._rep,
+            self._idx,
+        )
+        return [TheoryTerm(self._rep, args[i]) for i in range(size)]
+
+    @property
+    def name(self) -> str:
+        """
+        The name of the term (for symbols and functions).
+        """
+        return _to_str(
+            _c_call("char*", _lib.clingo_theory_atoms_term_name, self._rep, self._idx)
+        )
+
+    @property
+    def number(self) -> int:
+        """
+        The numeric representation of the term (for numbers).
+        """
+        return _c_call(
+            "int", _lib.clingo_theory_atoms_term_number, self._rep, self._idx
+        )
+
+    @property
+    def type(self) -> TheoryTermType:
+        """
+        The type of the theory term.
+        """
+        type_ = _c_call(
+            "clingo_theory_term_type_t",
+            _lib.clingo_theory_atoms_term_type,
+            self._rep,
+            self._idx,
+        )
+        return TheoryTermType(type_)
+
+

Instance variables

+
+
var arguments : List[TheoryTerm]
+
+

The arguments of the term (for functions, tuples, list, and sets).

+
+ +Expand source code + +
@property
+def arguments(self) -> List["TheoryTerm"]:
+    """
+    The arguments of the term (for functions, tuples, list, and sets).
+    """
+    args, size = _c_call2(
+        "clingo_id_t*",
+        "size_t",
+        _lib.clingo_theory_atoms_term_arguments,
+        self._rep,
+        self._idx,
+    )
+    return [TheoryTerm(self._rep, args[i]) for i in range(size)]
+
+
+
var name : str
+
+

The name of the term (for symbols and functions).

+
+ +Expand source code + +
@property
+def name(self) -> str:
+    """
+    The name of the term (for symbols and functions).
+    """
+    return _to_str(
+        _c_call("char*", _lib.clingo_theory_atoms_term_name, self._rep, self._idx)
+    )
+
+
+
var number : int
+
+

The numeric representation of the term (for numbers).

+
+ +Expand source code + +
@property
+def number(self) -> int:
+    """
+    The numeric representation of the term (for numbers).
+    """
+    return _c_call(
+        "int", _lib.clingo_theory_atoms_term_number, self._rep, self._idx
+    )
+
+
+
var typeTheoryTermType
+
+

The type of the theory term.

+
+ +Expand source code + +
@property
+def type(self) -> TheoryTermType:
+    """
+    The type of the theory term.
+    """
+    type_ = _c_call(
+        "clingo_theory_term_type_t",
+        _lib.clingo_theory_atoms_term_type,
+        self._rep,
+        self._idx,
+    )
+    return TheoryTermType(type_)
+
+
+
+
+
+class TheoryTermType +(value, names=None, *, module=None, qualname=None, type=None, start=1) +
+
+

Enumeration of theory term types.

+
+ +Expand source code + +
class TheoryTermType(OrderedEnum):
+    """
+    Enumeration of theory term types.
+    """
+
+    Function = _lib.clingo_theory_term_type_function
+    """
+    For a function theory terms.
+    """
+    List = _lib.clingo_theory_term_type_list
+    """
+    For list theory terms.
+    """
+    Number = _lib.clingo_theory_term_type_number
+    """
+    For numeric theory terms.
+    """
+    Set = _lib.clingo_theory_term_type_set
+    """
+    For set theory terms.
+    """
+    Symbol = _lib.clingo_theory_term_type_symbol
+    """
+    For symbolic theory terms (symbol here means the term is a string).
+    """
+    Tuple = _lib.clingo_theory_term_type_tuple
+    """
+    For tuple theory terms.
+    """
+
+

Ancestors

+ +

Class variables

+
+
var Function
+
+

For a function theory terms.

+
+
var List
+
+

For list theory terms.

+
+
var Number
+
+

For numeric theory terms.

+
+
var Set
+
+

For set theory terms.

+
+
var Symbol
+
+

For symbolic theory terms (symbol here means the term is a string).

+
+
var Tuple
+
+

For tuple theory terms.

+
+
+
+
+
+
+ +
+ + + \ No newline at end of file diff --git a/clingo/python-api/5.7/clingo/util.html b/clingo/python-api/5.7/clingo/util.html new file mode 100644 index 0000000..373b4f5 --- /dev/null +++ b/clingo/python-api/5.7/clingo/util.html @@ -0,0 +1,358 @@ + + + + + + +clingo.util API documentation + + + + + + + + + + + +
+
+
+

Module clingo.util

+
+
+

Utility functions and classes.

+
+ +Expand source code + +
"""
+Utility functions and classes.
+"""
+
+from typing import Optional, cast
+from collections import abc
+
+# pylint: disable=too-many-ancestors
+
+
+class Slice:
+    """
+    Wrapper for Python's slice that computes index ranges to slice sequences.
+
+    Currently, the range is recomputed each time. It is probably also possible
+    to combine the involved slices into one.
+    """
+
+    def __init__(self, slc: slice, rec: Optional["Slice"] = None):
+        self._slc = slc
+        self._rec = rec
+
+    def rng(self, size):
+        """
+        Return a range providing indices to access a sequence of length size.
+        """
+        return (
+            range(*self._slc.indices(size))
+            if self._rec is None
+            else self._rec.rng(size)[self._slc]
+        )
+
+
+class SlicedSequence(abc.Sequence):
+    """
+    Helper to slice sequences.
+    """
+
+    def __init__(self, seq: abc.Sequence, slc: Slice):
+        self._seq = seq
+        self._slc = slc
+        self._len = -1
+        self._lst = None
+
+    @property
+    def _rng(self):
+        size = len(self._seq)
+        if size != self._len:
+            self._lst = self._slc.rng(size)
+            self._len = size
+        return self._lst
+
+    def __len__(self) -> int:
+        return len(self._rng)
+
+    def __iter__(self):
+        for idx in self._rng:
+            yield self._seq[idx]
+
+    def __getitem__(self, slc):
+        if isinstance(slc, slice):
+            return SlicedSequence(self._seq, Slice(slc, self._slc))
+        return self._seq[self._rng[slc]]
+
+    def __str__(self):
+        return str(list(self))
+
+    def __repr__(self):
+        return repr(list(self))
+
+
+class SlicedMutableSequence(SlicedSequence, abc.MutableSequence):
+    """
+    Helper to slice sequences.
+    """
+
+    def __init__(self, seq: abc.MutableSequence, slc: Slice):
+        super().__init__(seq, slc)
+
+    @property
+    def _mut_seq(self):
+        return cast(abc.MutableSequence, self._seq)
+
+    def __setitem__(self, index, ast):
+        if isinstance(index, slice):
+            raise TypeError("slicing not implemented")
+        self._mut_seq[self._rng[index]] = ast
+
+    def __delitem__(self, index):
+        if isinstance(index, slice):
+            raise TypeError("slicing not implemented")
+        del self._mut_seq[self._rng[index]]
+
+    def insert(self, index, value):
+        self._mut_seq[self._rng[index]] = value
+
+
+
+
+
+
+
+
+
+

Classes

+
+
+class Slice +(slc: slice, rec: Optional[ForwardRef('Slice')] = None) +
+
+

Wrapper for Python's slice that computes index ranges to slice sequences.

+

Currently, the range is recomputed each time. It is probably also possible +to combine the involved slices into one.

+
+ +Expand source code + +
class Slice:
+    """
+    Wrapper for Python's slice that computes index ranges to slice sequences.
+
+    Currently, the range is recomputed each time. It is probably also possible
+    to combine the involved slices into one.
+    """
+
+    def __init__(self, slc: slice, rec: Optional["Slice"] = None):
+        self._slc = slc
+        self._rec = rec
+
+    def rng(self, size):
+        """
+        Return a range providing indices to access a sequence of length size.
+        """
+        return (
+            range(*self._slc.indices(size))
+            if self._rec is None
+            else self._rec.rng(size)[self._slc]
+        )
+
+

Methods

+
+
+def rng(self, size) +
+
+

Return a range providing indices to access a sequence of length size.

+
+ +Expand source code + +
def rng(self, size):
+    """
+    Return a range providing indices to access a sequence of length size.
+    """
+    return (
+        range(*self._slc.indices(size))
+        if self._rec is None
+        else self._rec.rng(size)[self._slc]
+    )
+
+
+
+
+
+class SlicedMutableSequence +(seq: collections.abc.MutableSequence, slc: Slice) +
+
+

Helper to slice sequences.

+
+ +Expand source code + +
class SlicedMutableSequence(SlicedSequence, abc.MutableSequence):
+    """
+    Helper to slice sequences.
+    """
+
+    def __init__(self, seq: abc.MutableSequence, slc: Slice):
+        super().__init__(seq, slc)
+
+    @property
+    def _mut_seq(self):
+        return cast(abc.MutableSequence, self._seq)
+
+    def __setitem__(self, index, ast):
+        if isinstance(index, slice):
+            raise TypeError("slicing not implemented")
+        self._mut_seq[self._rng[index]] = ast
+
+    def __delitem__(self, index):
+        if isinstance(index, slice):
+            raise TypeError("slicing not implemented")
+        del self._mut_seq[self._rng[index]]
+
+    def insert(self, index, value):
+        self._mut_seq[self._rng[index]] = value
+
+

Ancestors

+
    +
  • SlicedSequence
  • +
  • collections.abc.MutableSequence
  • +
  • collections.abc.Sequence
  • +
  • collections.abc.Reversible
  • +
  • collections.abc.Collection
  • +
  • collections.abc.Sized
  • +
  • collections.abc.Iterable
  • +
  • collections.abc.Container
  • +
+

Methods

+
+
+def insert(self, index, value) +
+
+

S.insert(index, value) – insert value before index

+
+ +Expand source code + +
def insert(self, index, value):
+    self._mut_seq[self._rng[index]] = value
+
+
+
+
+
+class SlicedSequence +(seq: collections.abc.Sequence, slc: Slice) +
+
+

Helper to slice sequences.

+
+ +Expand source code + +
class SlicedSequence(abc.Sequence):
+    """
+    Helper to slice sequences.
+    """
+
+    def __init__(self, seq: abc.Sequence, slc: Slice):
+        self._seq = seq
+        self._slc = slc
+        self._len = -1
+        self._lst = None
+
+    @property
+    def _rng(self):
+        size = len(self._seq)
+        if size != self._len:
+            self._lst = self._slc.rng(size)
+            self._len = size
+        return self._lst
+
+    def __len__(self) -> int:
+        return len(self._rng)
+
+    def __iter__(self):
+        for idx in self._rng:
+            yield self._seq[idx]
+
+    def __getitem__(self, slc):
+        if isinstance(slc, slice):
+            return SlicedSequence(self._seq, Slice(slc, self._slc))
+        return self._seq[self._rng[slc]]
+
+    def __str__(self):
+        return str(list(self))
+
+    def __repr__(self):
+        return repr(list(self))
+
+

Ancestors

+
    +
  • collections.abc.Sequence
  • +
  • collections.abc.Reversible
  • +
  • collections.abc.Collection
  • +
  • collections.abc.Sized
  • +
  • collections.abc.Iterable
  • +
  • collections.abc.Container
  • +
+

Subclasses

+ +
+
+
+
+ +
+ + + \ No newline at end of file diff --git a/clingo/python-api/5.7/clingox/ast.html b/clingo/python-api/5.7/clingox/ast.html new file mode 100644 index 0000000..9d32122 --- /dev/null +++ b/clingo/python-api/5.7/clingox/ast.html @@ -0,0 +1,3401 @@ + + + + + + +clingox.ast API documentation + + + + + + + + + + + +
+
+
+

Module clingox.ast

+
+
+

This module provides highlevel functions to work with clingo's AST.

+

Theory Parsing Examples

+

The following examples shows how to construct and use a theory parser:

+
>>> from clingo.ast import TheoryAtomType, parse_string
+>>> from clingox.ast import Arity, Associativity, TheoryParser
+>>>
+>>> terms = {"term":
+...     {("-", Arity.Unary): (3, Associativity.NoAssociativity),
+...      ("**", Arity.Binary): (2, Associativity.Right),
+...      ("*", Arity.Binary): (1, Associativity.Left),
+...      ("+", Arity.Binary): (0, Associativity.Left),
+...      ("-", Arity.Binary): (0, Associativity.Left)}}
+>>> atoms = {("eval", 0): (TheoryAtomType.Head, "term", None)}
+>>> parser = TheoryParser(terms, atoms)
+>>>
+>>> parse_string('&eval{ -1 * 2 + 3 }.', print)
+#program base.
+&eval { (- 1 * 2 + 3) }.
+>>> parse_string('&eval{ -1 * 2 + 3 }.', lambda x: print(parser(x)))
+#program base.
+&eval { +(*(-(1),2),3) }.
+
+

The same parser can also be constructed from a theory:

+
>>> from clingo.ast import parse_string, ASTType
+>>> from clingox.ast import theory_parser_from_definition
+>>>
+>>> theory = """\
+... #theory test {
+...     term {
+...         -  : 3, unary;
+...         ** : 2, binary, right;
+...         *  : 1, binary, left;
+...         +  : 0, binary, left;
+...         -  : 0, binary, left
+...     };
+...     &eval/0 : term, head
+... }.
+... """
+>>>
+>>> parsers = []
+>>> def extract(stm):
+...     if stm.ast_type == ASTType.TheoryDefinition:
+...         parsers.append(theory_parser_from_definition(stm))
+...
+>>> parse_string(theory, extract)
+>>> parse_string('&eval{ -1 * 2 + 3 }.', print)
+#program base.
+&eval { (- 1 * 2 + 3) }.
+>>> parse_string('&eval{ -1 * 2 + 3 }.', lambda x: print(parsers[0](x)))
+#program base.
+&eval { +(*(-(1),2),3) }.
+
+

Ast To Dict Conversion Example

+

Another interesting feature is to convert ASTs to YAML:

+
>>> from json import dumps
+>>> from clingo.ast import parse_string
+>>> from clingox.ast import ast_to_dict
+>>>
+>>> prg = []
+>>> parse_string('a.', lambda x: prg.append(ast_to_dict(x)))
+>>>
+>>> print(dumps(prg, indent=2))
+[
+  {
+    "ast_type": "Program",
+    "location": "<string>:1:1",
+    "name": "base",
+    "parameters": []
+  },
+  {
+    "ast_type": "Rule",
+    "location": "<string>:1:1-3",
+    "head": {
+      "ast_type": "Literal",
+      "location": "<string>:1:1-2",
+      "sign": 0,
+      "atom": {
+        "ast_type": "SymbolicAtom",
+        "symbol": {
+          "ast_type": "Function",
+          "location": "<string>:1:1-2",
+          "name": "a",
+          "arguments": [],
+          "external": 0
+        }
+      }
+    },
+    "body": []
+  }
+]
+
+
+ +Expand source code + +
'''
+This module provides highlevel functions to work with clingo's AST.
+
+Theory Parsing Examples
+-----------------------
+
+The following examples shows how to construct and use a theory parser:
+
+```python-repl
+>>> from clingo.ast import TheoryAtomType, parse_string
+>>> from clingox.ast import Arity, Associativity, TheoryParser
+>>>
+>>> terms = {"term":
+...     {("-", Arity.Unary): (3, Associativity.NoAssociativity),
+...      ("**", Arity.Binary): (2, Associativity.Right),
+...      ("*", Arity.Binary): (1, Associativity.Left),
+...      ("+", Arity.Binary): (0, Associativity.Left),
+...      ("-", Arity.Binary): (0, Associativity.Left)}}
+>>> atoms = {("eval", 0): (TheoryAtomType.Head, "term", None)}
+>>> parser = TheoryParser(terms, atoms)
+>>>
+>>> parse_string('&eval{ -1 * 2 + 3 }.', print)
+#program base.
+&eval { (- 1 * 2 + 3) }.
+>>> parse_string('&eval{ -1 * 2 + 3 }.', lambda x: print(parser(x)))
+#program base.
+&eval { +(*(-(1),2),3) }.
+```
+
+The same parser can also be constructed from a theory:
+
+```python-repl
+>>> from clingo.ast import parse_string, ASTType
+>>> from clingox.ast import theory_parser_from_definition
+>>>
+>>> theory = """\\
+... #theory test {
+...     term {
+...         -  : 3, unary;
+...         ** : 2, binary, right;
+...         *  : 1, binary, left;
+...         +  : 0, binary, left;
+...         -  : 0, binary, left
+...     };
+...     &eval/0 : term, head
+... }.
+... """
+>>>
+>>> parsers = []
+>>> def extract(stm):
+...     if stm.ast_type == ASTType.TheoryDefinition:
+...         parsers.append(theory_parser_from_definition(stm))
+...
+>>> parse_string(theory, extract)
+>>> parse_string('&eval{ -1 * 2 + 3 }.', print)
+#program base.
+&eval { (- 1 * 2 + 3) }.
+>>> parse_string('&eval{ -1 * 2 + 3 }.', lambda x: print(parsers[0](x)))
+#program base.
+&eval { +(*(-(1),2),3) }.
+```
+
+AST to dict Conversion Example
+------------------------------
+
+Another interesting feature is to convert ASTs to YAML:
+
+```python-repl
+>>> from json import dumps
+>>> from clingo.ast import parse_string
+>>> from clingox.ast import ast_to_dict
+>>>
+>>> prg = []
+>>> parse_string('a.', lambda x: prg.append(ast_to_dict(x)))
+>>>
+>>> print(dumps(prg, indent=2))
+[
+  {
+    "ast_type": "Program",
+    "location": "<string>:1:1",
+    "name": "base",
+    "parameters": []
+  },
+  {
+    "ast_type": "Rule",
+    "location": "<string>:1:1-3",
+    "head": {
+      "ast_type": "Literal",
+      "location": "<string>:1:1-2",
+      "sign": 0,
+      "atom": {
+        "ast_type": "SymbolicAtom",
+        "symbol": {
+          "ast_type": "Function",
+          "location": "<string>:1:1-2",
+          "name": "a",
+          "arguments": [],
+          "external": 0
+        }
+      }
+    },
+    "body": []
+  }
+]
+```
+'''
+from copy import copy
+from enum import Enum, auto
+from functools import lru_cache, partial, singledispatch
+from re import fullmatch
+from typing import (
+    Any,
+    Callable,
+    Container,
+    Iterable,
+    List,
+    Mapping,
+    Optional,
+    Sequence,
+    Set,
+    Tuple,
+    Union,
+    cast,
+)
+
+import clingo
+from clingo import ast
+from clingo.ast import (
+    AST,
+    ASTSequence,
+    ASTType,
+    Function,
+    Location,
+    Position,
+    Sign,
+    StrSequence,
+    SymbolicAtom,
+    SymbolicTerm,
+    TheoryAtomType,
+    TheoryFunction,
+    TheoryOperatorType,
+    Transformer,
+    UnaryOperation,
+    parse_string,
+)
+
+from .theory import is_operator
+
+__all__ = [
+    "Arity",
+    "Associativity",
+    "ASTPredicate",
+    "AtomTable",
+    "OperatorTable",
+    "TheoryParser",
+    "TheoryTermParser",
+    "TheoryUnparsedTermParser",
+    "ast_to_dict",
+    "clingo_literal_parser",
+    "clingo_term_parser",
+    "dict_to_ast",
+    "filter_body_literals",
+    "location_to_str",
+    "negate_sign",
+    "parse_theory",
+    "partition_body_literals",
+    "prefix_symbolic_atoms",
+    "reify_symbolic_atoms",
+    "rename_symbolic_atoms",
+    "str_to_location",
+    "theory_parser_from_definition",
+    "theory_term_to_literal",
+    "theory_term_to_term",
+]
+
+
+class Arity(Enum):
+    """
+    Enumeration of operator arities.
+    """
+
+    # pylint:disable=invalid-name
+    Unary = 1
+    Binary = 2
+
+
+class Associativity(Enum):
+    """
+    Enumeration of operator associativities.
+    """
+
+    # pylint: disable=invalid-name
+    Left = auto()
+    Right = auto()
+    NoAssociativity = auto()
+
+
+def _s(m, a: str, b: str):
+    """
+    Select the match group b if not None and group a otherwise.
+    """
+    return m[a] if m[b] is None else m[b]
+
+
+def _quote(s: str) -> str:
+    return s.replace("\\", "\\\\").replace(":", "\\:")
+
+
+def _unquote(s: str) -> str:
+    return s.replace("\\:", ":").replace("\\\\", "\\")
+
+
+def location_to_str(loc: Location) -> str:
+    """
+    This function transfroms a loctation object into a readable string.
+
+    Colons in the location will be quoted ensuring that the resulting is
+    parsable using `str_to_location`.
+
+    Parameters
+    ----------
+    loc
+        The location to transform.
+
+    Returns
+    -------
+    The string representation of the given location.
+    """
+    begin, end = loc.begin, loc.end
+    bf, ef = _quote(begin.filename), _quote(end.filename)
+    ret = f"{bf}:{begin.line}:{begin.column}"
+    dash, eq = True, bf == ef
+    if not eq:
+        ret += f"{'-' if dash else ':'}{ef}"
+        dash = False
+    eq = eq and begin.line == end.line
+    if not eq:
+        ret += f"{'-' if dash else ':'}{end.line}"
+        dash = False
+    eq = eq and begin.column == end.column
+    if not eq:
+        ret += f"{'-' if dash else ':'}{end.column}"
+        dash = False
+    return ret
+
+
+def str_to_location(loc: str) -> Location:
+    """
+    This function parses a location from its string representation.
+
+    Parameters
+    ----------
+    loc
+        The string to parse.
+
+    Returns
+    -------
+    The parsed location.
+
+    See Also
+    --------
+    location_to_str
+    """
+    m = fullmatch(
+        r"(?P<bf>([^\\:]|\\\\|\\:)*):(?P<bl>[0-9]*):(?P<bc>[0-9]+)"
+        r"(-(((?P<ef>([^\\:]|\\\\|\\:)*):)?(?P<el>[0-9]*):)?(?P<ec>[0-9]+))?",
+        loc,
+    )
+    if not m:
+        raise RuntimeError("could not parse location")
+    begin = Position(_unquote(m["bf"]), int(m["bl"]), int(m["bc"]))
+    end = Position(
+        _unquote(_s(m, "bf", "ef")), int(_s(m, "bl", "el")), int(_s(m, "bc", "ec"))
+    )
+    return Location(begin, end)
+
+
+OperatorTable = Mapping[Tuple[str, Arity], Tuple[int, Associativity]]
+AtomTable = Mapping[
+    Tuple[str, int], Tuple[TheoryAtomType, str, Optional[Tuple[List[str], str]]]
+]
+
+
+class TheoryUnparsedTermParser:
+    """
+    Parser for unparsed theory terms in clingo's AST that works like the
+    inbuilt one.
+
+    Note that associativity for unary operators is ignored and binary
+    operators must use either `Associativity.Left` or `Associativity.Right`.
+
+    Parameters
+    ----------
+    table
+        Mapping of operator/arity pairs to priority/associativity pairs.
+    """
+
+    _stack: List[Tuple[str, Arity]]
+    _terms: List[AST]
+    _table: OperatorTable
+
+    def __init__(self, table: OperatorTable):
+        self._stack = []
+        self._terms = []
+        self._table = table
+
+    def _priority_and_associativity(self, operator: str) -> Tuple[int, Associativity]:
+        """
+        Get priority and associativity of the given binary operator.
+        """
+        return self._table[(operator, Arity.Binary)]
+
+    def _priority(self, operator: str, arity: Arity) -> int:
+        """
+        Get priority of the given unary or binary operator.
+        """
+        return self._table[(operator, arity)][0]
+
+    def _check(self, operator: str) -> bool:
+        """
+        Returns true if the stack has to be reduced because of the precedence
+        of the given binary operator is lower than the preceeding operator on
+        the stack.
+        """
+        if not self._stack:
+            return False
+        priority, associativity = self._priority_and_associativity(operator)
+        previous_priority = self._priority(*self._stack[-1])
+        return previous_priority > priority or (
+            previous_priority == priority and associativity == Associativity.Left
+        )
+
+    def _reduce(self) -> None:
+        """
+        Combines the last unary or binary term on the stack.
+        """
+        b = self._terms.pop()
+        operator, arity = self._stack.pop()
+        if arity == Arity.Unary:
+            self._terms.append(TheoryFunction(b.location, operator, [b]))
+        else:
+            a = self._terms.pop()
+            loc = Location(a.location.begin, b.location.end)
+            self._terms.append(TheoryFunction(loc, operator, [a, b]))
+
+    def check_operator(self, operator: str, arity: Arity, location: Location) -> None:
+        """
+        Check if the given operator is in the parse table raising a runtime
+        error if absent.
+
+        Parameters
+        ----------
+        operator
+            The operator name.
+        arity
+            The arity of the operator.
+        location
+            Location of the operator for error reporting.
+        """
+        if (operator, arity) not in self._table:
+            raise RuntimeError(
+                f"cannot parse operator `{operator}`: {location_to_str(location)}"
+            )
+
+    def parse(self, x: AST) -> AST:
+        """
+        Parses the given unparsed term, replacing it by nested theory
+        functions.
+
+        Parameters
+        ----------
+        x
+            The AST to parse.
+
+        Returns
+        -------
+        The rewritten AST.
+        """
+        del self._stack[:]
+        del self._terms[:]
+
+        arity = Arity.Unary
+
+        for element in x.elements:
+            for operator in element.operators:
+                self.check_operator(operator, arity, x.location)
+
+                while arity == Arity.Binary and self._check(operator):
+                    self._reduce()
+
+                self._stack.append((operator, arity))
+                arity = Arity.Unary
+
+            self._terms.append(element.term)
+            arity = Arity.Binary
+
+        while self._stack:
+            self._reduce()
+
+        return self._terms[0]
+
+
+class TheoryTermParser(Transformer):
+    """
+    Parser for theory terms in clingo's AST that works like the inbuilt one.
+
+    This is implemented as a transformer that traverses the AST replacing all
+    terms found.
+
+    Parameters
+    ----------
+    table
+        This must either be a table of operators or a `TheoryUnparsedTermParser`.
+
+    See Also
+    --------
+    TheoryUnparsedTermParser
+    """
+
+    # pylint: disable=invalid-name
+
+    def __init__(self, table: Union[OperatorTable, TheoryUnparsedTermParser]):
+        self._parser = (
+            table
+            if isinstance(table, TheoryUnparsedTermParser)
+            else TheoryUnparsedTermParser(table)
+        )
+
+    def visit_TheoryFunction(self, x) -> AST:
+        """
+        Parse the theory function and check if it agrees with the grammar.
+
+        Parameters
+        ----------
+        x
+            The AST to rewrite.
+
+        Returns
+        -------
+        The rewritten AST.
+        """
+        arity = None
+        if len(x.arguments) == 1:
+            arity = Arity.Unary
+        if len(x.arguments) == 2:
+            arity = Arity.Binary
+        if arity is not None and is_operator(x.name):
+            self._parser.check_operator(x.name, arity, x.location)
+
+        return x.update(**self.visit_children(x))
+
+    def visit_TheoryUnparsedTerm(self, x: AST) -> AST:
+        """
+        Parse the given unparsed term.
+
+        Parameters
+        ----------
+        x
+            The AST to rewrite.
+
+        Returns
+        -------
+        The rewritten AST.
+        """
+        return cast(AST, self(self._parser.parse(x)))
+
+
+_clingo_term_table = {
+    ("-", Arity.Unary): (5, Associativity.NoAssociativity),
+    ("~", Arity.Unary): (5, Associativity.NoAssociativity),
+    ("**", Arity.Binary): (4, Associativity.Right),
+    ("*", Arity.Binary): (3, Associativity.Left),
+    ("/", Arity.Binary): (3, Associativity.Left),
+    ("\\", Arity.Binary): (3, Associativity.Left),
+    ("+", Arity.Binary): (2, Associativity.Left),
+    ("-", Arity.Binary): (2, Associativity.Left),
+    ("&", Arity.Binary): (1, Associativity.Left),
+    ("?", Arity.Binary): (1, Associativity.Left),
+    ("^", Arity.Binary): (1, Associativity.Left),
+    ("..", Arity.Binary): (0, Associativity.Left),
+}
+
+
+@lru_cache(maxsize=None)
+def clingo_term_parser() -> TheoryTermParser:
+    """
+    Return a theory term parser that parses theory terms like clingo terms.
+
+    Note that for technical reasons pools and the absolute function are not
+    supported.
+    """
+    return TheoryTermParser(_clingo_term_table)
+
+
+@lru_cache(maxsize=None)
+def clingo_literal_parser() -> TheoryTermParser:
+    """
+    Return a theory term parser that parses theory literals similar to clingo's
+    parser for symbolic literals.
+
+    Note that for technical reasons pools and the absolute function are not
+    supported.
+    """
+    clingo_literal_table = _clingo_term_table.copy()
+    clingo_literal_table.update(
+        {
+            ("-", Arity.Unary): (0, Associativity.NoAssociativity),
+            ("not", Arity.Unary): (0, Associativity.NoAssociativity),
+        }
+    )
+    return TheoryTermParser(clingo_literal_table)
+
+
+class TheoryParser(Transformer):
+    """
+    This class parses theory atoms in the same way as clingo's internal parser.
+
+    Parameters
+    ----------
+    terms
+        Mapping from term identifiers to `TheoryTermParser`s. If an operator
+        table is given, the `TheoryTermParser` is constructed from this table.
+
+    atoms
+        Mapping from atom name/arity pairs to tuples defining the acceptable
+        structure of the theory atom.
+    """
+
+    # pylint: disable=invalid-name
+    _table: Mapping[
+        Tuple[str, int],
+        Tuple[
+            TheoryAtomType,
+            TheoryTermParser,
+            Optional[Tuple[Set[str], TheoryTermParser]],
+        ],
+    ]
+    _in_body: bool
+    _in_head: bool
+    _is_directive: bool
+
+    def __init__(
+        self,
+        terms: Mapping[str, Union[OperatorTable, TheoryTermParser]],
+        atoms: AtomTable,
+    ):
+        self._reset()
+
+        term_parsers = {}
+        for term_key, parser in terms.items():
+            if isinstance(parser, TheoryTermParser):
+                term_parsers[term_key] = parser
+            else:
+                term_parsers[term_key] = TheoryTermParser(parser)
+
+        self._table = {}
+        for atom_key, (atom_type, term_key, guard) in atoms.items():
+            guard_table = None
+            if guard is not None:
+                guard_table = (set(guard[0]), term_parsers[guard[1]])
+            self._table[atom_key] = (atom_type, term_parsers[term_key], guard_table)
+
+    def _reset(self, in_head=True, in_body=True, is_directive=True):
+        """
+        Set state information about active scope.
+        """
+        self._in_head = in_head
+        self._in_body = in_body
+        self._is_directive = is_directive
+
+    def _visit_body(self, x: AST) -> AST:
+        try:
+            self._reset(False, True, False)
+            old = x.body
+            new = self.visit_sequence(old)
+            return x if new is old else x.update(body=new)
+        finally:
+            self._reset()
+
+    def visit_Rule(self, x: AST) -> AST:
+        """
+        Parse theory atoms in body and head.
+
+        Parameters
+        ----------
+        x
+            The AST to rewrite.
+
+        Returns
+        -------
+        The rewritten AST.
+        """
+        ret = self._visit_body(x)
+        try:
+            self._reset(True, False, not x.body)
+            head = self(x.head)
+            if head is not x.head:
+                if ret is x:
+                    ret = copy(ret)
+                ret.head = head
+        finally:
+            self._reset()
+
+        return ret
+
+    def visit_ShowTerm(self, x: AST) -> AST:
+        """
+        Parse theory atoms in body.
+
+        Parameters
+        ----------
+        x
+            The AST to rewrite.
+
+        Returns
+        -------
+        The rewritten AST.
+        """
+        return self._visit_body(x)
+
+    def visit_Minimize(self, x: AST) -> AST:
+        """
+        Parse theory atoms in body.
+
+        Parameters
+        ----------
+        x
+            The AST to rewrite.
+
+        Returns
+        -------
+        The rewritten AST.
+        """
+        return self._visit_body(x)
+
+    def visit_Edge(self, x: AST) -> AST:
+        """
+        Parse theory atoms in body.
+
+        Parameters
+        ----------
+        x
+            The AST to rewrite.
+
+        Returns
+        -------
+        The rewritten AST.
+        """
+        return self._visit_body(x)
+
+    def visit_Heuristic(self, x: AST) -> AST:
+        """
+        Parse theory atoms in body.
+
+        Parameters
+        ----------
+        x
+            The AST to rewrite.
+
+        Returns
+        -------
+        The rewritten AST.
+        """
+        return self._visit_body(x)
+
+    def visit_ProjectAtom(self, x: AST) -> AST:
+        """
+        Parse theory atoms in body.
+
+        Parameters
+        ----------
+        x
+            The AST to rewrite.
+
+        Returns
+        -------
+        The rewritten AST.
+        """
+        return self._visit_body(x)
+
+    def visit_TheoryAtom(self, x: AST) -> AST:
+        """
+        Parse the given theory atom.
+
+        Parameters
+        ----------
+        x
+            The AST to rewrite.
+
+        Returns
+        -------
+        The rewritten AST.
+        """
+        name = x.term.name
+        arity = len(x.term.arguments)
+        if (name, arity) not in self._table:
+            raise RuntimeError(
+                f"theory atom definiton not found: {location_to_str(x.location)}"
+            )
+
+        type_, element_parser, guard_table = self._table[(name, arity)]
+        if type_ == TheoryAtomType.Head and not self._in_head:
+            raise RuntimeError(
+                f"theory atom only accepted in head: {location_to_str(x.location)}"
+            )
+        if type_ == TheoryAtomType.Body and not self._in_body:
+            raise RuntimeError(
+                f"theory atom only accepted in body: {location_to_str(x.location)}"
+            )
+        if type_ == TheoryAtomType.Directive and not (
+            self._in_head and self._is_directive
+        ):
+            raise RuntimeError(
+                f"theory atom must be a directive: {location_to_str(x.location)}"
+            )
+
+        x = copy(x)
+        x.term = element_parser(x.term)
+        x.elements = element_parser.visit_sequence(x.elements)
+
+        if x.guard is not None:
+            if guard_table is None:
+                raise RuntimeError(
+                    f"unexpected guard in theory atom: {location_to_str(x.location)}"
+                )
+
+            guards, guard_parser = guard_table
+            if x.guard.operator_name not in guards:
+                raise RuntimeError(
+                    f"unexpected guard in theory atom: {location_to_str(x.location)}"
+                )
+
+            x.guard = copy(x.guard)
+            x.guard.term = guard_parser(x.guard.term)
+
+        return x
+
+
+def theory_parser_from_definition(x: AST) -> TheoryParser:
+    """
+    Turn an AST node of type TheoryDefinition into a TheoryParser.
+
+    Parameters
+    ----------
+    x
+        An AST representing a theory definition.
+
+    Returns
+    -------
+    The corresponding `TheoryParser`.
+    """
+    assert x.ast_type == ASTType.TheoryDefinition
+
+    terms = {}
+    atoms = {}
+
+    for term_def in x.terms:
+        term_table = {}
+
+        for op_def in term_def.operators:
+            op_assoc: Associativity
+            if op_def.operator_type == TheoryOperatorType.BinaryLeft:
+                op_type = Arity.Binary
+                op_assoc = Associativity.Left
+            elif op_def.operator_type == TheoryOperatorType.BinaryRight:
+                op_type = Arity.Binary
+                op_assoc = Associativity.Right
+            else:
+                op_type = Arity.Unary
+                op_assoc = Associativity.NoAssociativity
+
+            term_table[(op_def.name, op_type)] = (op_def.priority, op_assoc)
+
+        terms[term_def.name] = term_table
+
+    for atom_def in x.atoms:
+        guard = None
+        if atom_def.guard is not None:
+            guard = (atom_def.guard.operators, atom_def.guard.term)
+
+        atoms[(atom_def.name, atom_def.arity)] = (
+            atom_def.atom_type,
+            atom_def.term,
+            guard,
+        )
+
+    return TheoryParser(terms, atoms)
+
+
+def parse_theory(s: str) -> TheoryParser:
+    """
+    Turn the given theory into a parser.
+    """
+    parser = None
+
+    def extract(stm):
+        nonlocal parser
+        if stm.ast_type == ASTType.TheoryDefinition:
+            if parser is not None:
+                raise ValueError("multiple theory definitions")
+            parser = theory_parser_from_definition(stm)
+        else:
+            assert (
+                stm.ast_type == ASTType.Program
+                and stm.name == "base"
+                and not stm.parameters
+            )
+
+    parse_string(f"{s}.", extract)
+    if parser is None:
+        raise ValueError("no theory definition found")
+    return cast(TheoryParser, parser)
+
+
+class _SymbolicAtomTransformer(Transformer):
+    """
+    Transforms symbolic atoms with the given function.
+    """
+
+    # pylint: disable=invalid-name
+
+    def __init__(self, transformer_function: Callable[[AST], AST]):
+        self._transformer_function = transformer_function
+
+    def visit_SymbolicAtom(self, x: AST) -> AST:
+        """
+        Transform the given symbolic.
+
+        Parameters
+        ----------
+        x
+            The AST to rewrite.
+
+        Returns
+        -------
+        The rewritten AST.
+        """
+        term = x.symbol
+        new_term = self._transformer_function(term)
+        return x if new_term is term else SymbolicAtom(new_term)
+
+
+def rewrite_symbolic_atoms(x: AST, rewrite_function: Callable[[AST], AST]) -> AST:
+    """
+    Rewrite all symbolic atoms in the given AST node with the given function.
+
+    Parameters
+    ----------
+    x
+        The ast in which to rename symbolic atoms.
+    rename_function
+        A function applied to the term representation of the symbolic atom. The
+        function has to return a term compatible with symbolic atoms.
+
+    Returns
+    -------
+    The rewritten AST.
+    """
+    return cast(AST, _SymbolicAtomTransformer(rewrite_function)(x))
+
+
+def rename_symbolic_atoms(x: AST, rename_function: Callable[[str], str]) -> AST:
+    """
+    Rename all symbolic atoms in the given AST node with the given function.
+
+    Parameters
+    ----------
+    x
+        The ast in which to rename symbolic atoms.
+    rename_function
+        A function for renaming symbols.
+
+    Returns
+    -------
+    The rewritten AST.
+    """
+
+    def renamer(term: AST):
+        if term.ast_type == ASTType.UnaryOperation:
+            return UnaryOperation(
+                term.location, term.operator_type, renamer(term.argument)
+            )
+        if term.ast_type == ASTType.SymbolicTerm:
+            sym = term.symbol
+            new_name = rename_function(sym.name)
+            return SymbolicTerm(
+                term.location, clingo.Function(new_name, sym.arguments, sym.positive)
+            )
+        if term.ast_type == ASTType.Function:
+            return Function(
+                term.location, rename_function(term.name), term.arguments, term.external
+            )
+        return term
+
+    return rewrite_symbolic_atoms(x, renamer)
+
+
+def prefix_symbolic_atoms(x: AST, prefix: str) -> AST:
+    """
+    Prefix all symbolic atoms in the given AST with the given string.
+
+    Parameters
+    ----------
+    x
+        The ast in which to prefix symbolic atom names.
+    prefix
+        The prefix to add.
+
+    Returns
+    -------
+    The rewritten AST.
+
+    See Also
+    --------
+    rename_symbolic_atoms
+    """
+    return rename_symbolic_atoms(x, lambda s: prefix + s)
+
+
+def reify_symbolic_atoms(
+    x: AST,
+    name: str,
+    argument_extender: Callable[[AST], Sequence[AST]] = None,
+    reify_strong_negation: bool = False,
+) -> AST:
+    """
+    Reify all symbolic atoms in the given AST node with the given name and
+    function.
+
+    Parameters
+    ----------
+    x
+        The ast in which to rename symbolic atoms.
+    name
+        A string to serve as name of the new symbolic atom.
+    argument_extender
+        A function to provide extra arguments. If not provided, no extra
+        arguments are added. The term passed as argument should be placed in
+        the correct position.
+    reify_strong_negation
+        Boolean indicating how to encode strong negation. If false, `-p(X)` is
+        reified as `-name(p(X))`. If true, then `-p(X)` is reified as
+        `name(-p(X))`. In the latter case, this means that stable models
+        containing both `name(p(a))` and `name(-p(a))` are possible. Clingo
+        style consistency can be restored by adding the constraint
+        `:- name(X), name(-X), X<-X.`
+
+    Returns
+    -------
+    The rewritten AST.
+    """
+
+    def reifier(term: AST):
+        if term.ast_type == ASTType.UnaryOperation and not reify_strong_negation:
+            return UnaryOperation(
+                term.location, term.operator_type, reifier(term.argument)
+            )
+        arguments = argument_extender(term) if argument_extender else [term]
+        return Function(term.location, name, arguments, False)
+
+    return rewrite_symbolic_atoms(x, reifier)
+
+
+@singledispatch
+def _encode(x: Any) -> Any:
+    assert False, f"unknown value to encode: {x}"
+
+
+@_encode.register(str)
+def _encode_str(x: str) -> str:
+    return x
+
+
+@_encode.register(clingo.Symbol)
+def _encode_symbol(x: clingo.Symbol) -> str:
+    return str(x)
+
+
+@_encode.register(int)
+def _encode_int(x: int) -> int:
+    return x
+
+
+@_encode.register(ASTSequence)
+def _encode_ast_seq(x: ASTSequence) -> List[Any]:
+    return [_encode(y) for y in x]
+
+
+@_encode.register(StrSequence)
+def _encode_str_seq(x: StrSequence) -> List[Any]:
+    return [_encode(y) for y in x]
+
+
+@_encode.register(type(None))
+def _encode_none(x: None) -> None:
+    return x
+
+
+@_encode.register(AST)
+def _encode_ast(x: AST) -> Any:
+    return ast_to_dict(x)
+
+
+def ast_to_dict(x: AST) -> dict:
+    """
+    Convert the given ast node into a dictionary representation whose elements
+    only involve the data structures: `dict`, `list`, `int`, and `str`.
+
+    The resulting value can be used with other Python modules like the `yaml`
+    or `pickle` modules.
+
+    Parameters
+    ----------
+    x
+        The ast to transform.
+
+    Returns
+    -------
+    The corresponding Python representation.
+
+    See Also
+    --------
+    dict_to_ast
+    """
+    ret = {"ast_type": str(x.ast_type).replace("ASTType.", "")}
+    for key, val in x.items():
+        if key == "location":
+            assert isinstance(val, Location)
+            enc = location_to_str(val)
+        else:
+            enc = _encode(val)
+        ret[key] = enc
+    return ret
+
+
+@singledispatch
+def _decode(x: Any, key: str) -> Any:
+    raise RuntimeError(f"unknown key/value to decode: {key}: {x}")
+
+
+@_decode.register(str)
+def _decode_str(x: str, key: str) -> Any:
+    if key == "location":
+        return str_to_location(x)
+
+    if key == "symbol":
+        return clingo.parse_term(x)
+
+    assert key in ("name", "id", "code", "elements", "term", "list", "operator_name")
+    return x
+
+
+@_decode.register(int)
+def _decode_int(x: int, key: str) -> Any:
+    # pylint: disable=unused-argument
+    return x
+
+
+@_decode.register(type(None))
+def _decode_none(x: None, key: str) -> Any:
+    # pylint: disable=unused-argument
+    return x
+
+
+@_decode.register(list)
+def _decode_list(x: list, key_: str) -> Any:
+    # pylint: disable=unused-argument
+    return [_decode(y, "list") for y in x]
+
+
+@_decode.register(dict)
+def _decode_dict(x: dict, key_: str) -> Any:
+    # pylint: disable=unused-argument
+    return dict_to_ast(x)
+
+
+def dict_to_ast(x: dict) -> AST:
+    """
+    Convert the Python dict representation of an AST node into an AST node.
+
+    Parameters
+    ----------
+    x
+        The Python representation of the AST.
+
+    Returns
+    -------
+    The corresponding AST.
+
+    See Also
+    --------
+    ast_to_dict
+    """
+    return getattr(ast, x["ast_type"])(
+        **{key: _decode(value, key) for key, value in x.items() if key != "ast_type"}
+    )
+
+
+ASTPredicate = Union[Callable[[AST], bool], bool]
+
+
+def _eval_predicate(predicate: ASTPredicate, arg: AST) -> bool:
+    if callable(predicate):
+        return predicate(arg)
+    return predicate
+
+
+def _body_literal_predicate(
+    lit: AST,
+    symbolic_atom_predicate: ASTPredicate = True,
+    theory_atom_predicate: ASTPredicate = True,
+    aggregate_predicate: ASTPredicate = True,
+    conditional_literal_predicate: ASTPredicate = True,
+    signs: Container[Sign] = (Sign.NoSign, Sign.Negation, Sign.DoubleNegation),
+) -> bool:
+    if lit.ast_type == ASTType.Literal:
+        atom = lit.atom
+        if lit.sign not in signs:
+            return False
+        if atom.ast_type == ASTType.SymbolicAtom:
+            return _eval_predicate(symbolic_atom_predicate, atom.symbol)
+        if atom.ast_type in (ASTType.Aggregate, ASTType.BodyAggregate):
+            return _eval_predicate(aggregate_predicate, atom)
+        if atom.ast_type == ASTType.TheoryAtom:
+            return _eval_predicate(theory_atom_predicate, atom)
+    elif lit.ast_type == ASTType.ConditionalLiteral:
+        return lit.literal.sign in signs and _eval_predicate(
+            conditional_literal_predicate, lit
+        )
+    return True
+
+
+def filter_body_literals(
+    body: Iterable[AST],
+    symbolic_atom_predicate: ASTPredicate = True,
+    theory_atom_predicate: ASTPredicate = True,
+    aggregate_predicate: ASTPredicate = True,
+    conditional_literal_predicate: ASTPredicate = True,
+    signs: Container[Sign] = (Sign.NoSign, Sign.Negation, Sign.DoubleNegation),
+) -> Iterable[AST]:
+    """
+    Filters the given body literals according to the given predicates.
+
+    Parameters
+    ----------
+    body
+        An iterable of `AST`s for body literals.
+    symbolic_atom_predicate
+        Predicate to filter symbolic atoms.
+    theory_atom_predicate
+        Predicate to filter theory atoms.
+    aggregate_predicate
+        Predicate to filter aggregates.
+    conditional_literal_predicate
+        Predicate to filter conditional literals.
+    signs
+        Only include literals with the given signs.
+
+    Returns
+    -------
+    An iterarable of body literals.
+
+    Notes
+    -----
+    An `ASTPredicate` is a callable that takes an `AST` and returns a Boolean.
+    Booleans `True` and `False` are also accepted, meaning that the predicate
+    is always `True` or `False`, respectively.
+    """
+    pred = partial(
+        _body_literal_predicate,
+        symbolic_atom_predicate=symbolic_atom_predicate,
+        theory_atom_predicate=theory_atom_predicate,
+        aggregate_predicate=aggregate_predicate,
+        conditional_literal_predicate=conditional_literal_predicate,
+        signs=signs,
+    )
+    return filter(pred, body)
+
+
+def partition_body_literals(
+    body: Iterable[AST],
+    symbolic_atom_predicate: ASTPredicate = True,
+    theory_atom_predicate: ASTPredicate = True,
+    aggregate_predicate: ASTPredicate = True,
+    conditional_literal_predicate: ASTPredicate = True,
+    signs: Container[Sign] = (Sign.NoSign, Sign.Negation, Sign.DoubleNegation),
+) -> Tuple[List[AST], List[AST]]:
+    """
+    Partition the given body literals according to the given predicates.
+
+    Parameters
+    ----------
+    body
+        An iterable of `AST` that represents a body.
+    symbolic_atom_predicate
+        Predicate to partition symbolic atoms.
+    theory_atom_predicate
+        Predicate to partition theory atoms.
+    aggregate_predicate
+        Predicate to partition aggregates.
+    conditional_literal_predicate
+        Predicate to partition conditional literals.
+    signs
+        Only include literals with the given signs in the first list.
+
+    Returns
+    -------
+    A pair of lists of body literals. The first iterable yields the literals
+    that satisfy the predicate while the second one yields the ones that do
+    not.
+
+    Notes
+    -----
+    An `ASTPredicate` is a callable that takes an `AST` and returns a Boolean.
+    Booleans `True` and `False` are also accepted, meaning that the predicate
+    is always `True` or `False`, respectively.
+    """
+    pred = partial(
+        _body_literal_predicate,
+        symbolic_atom_predicate=symbolic_atom_predicate,
+        theory_atom_predicate=theory_atom_predicate,
+        aggregate_predicate=aggregate_predicate,
+        conditional_literal_predicate=conditional_literal_predicate,
+        signs=signs,
+    )
+    part_a: List[AST] = []
+    part_b: List[AST] = []
+    for lit in body:
+        if pred(lit):
+            part_a.append(lit)
+        else:
+            part_b.append(lit)
+    return part_a, part_b
+
+
+_unary_operator_map = {
+    "-": ast.UnaryOperator.Minus,
+    "~": ast.UnaryOperator.Negation,
+    "|": ast.UnaryOperator.Absolute,
+}
+
+_binary_operator_map = {
+    "+": ast.BinaryOperator.Plus,
+    "-": ast.BinaryOperator.Minus,
+    "*": ast.BinaryOperator.Multiplication,
+    "/": ast.BinaryOperator.Division,
+    "\\": ast.BinaryOperator.Modulo,
+    "**": ast.BinaryOperator.Power,
+    "&": ast.BinaryOperator.And,
+    "?": ast.BinaryOperator.Or,
+    "^": ast.BinaryOperator.XOr,
+}
+
+
+def _theory_term_to_term(x: AST) -> AST:
+    """
+    Convert a given theory term into a plain clingo term.
+    """
+    if x.ast_type in (ASTType.SymbolicTerm, ASTType.Variable):
+        return x
+
+    if x.ast_type == ASTType.TheoryFunction:
+        if len(x.arguments) == 1 and x.name in _unary_operator_map:
+            arg = _theory_term_to_term(x.arguments[0])
+            uop = _unary_operator_map[x.name]
+
+            return ast.UnaryOperation(x.location, uop, arg)
+
+        if len(x.arguments) == 2:
+            lhs = _theory_term_to_term(x.arguments[0])
+            rhs = _theory_term_to_term(x.arguments[1])
+
+            if x.name in _binary_operator_map:
+                bop = _binary_operator_map[x.name]
+                return ast.BinaryOperation(x.location, bop, lhs, rhs)
+
+            if x.name == "..":
+                return ast.Interval(x.location, lhs, rhs)
+
+        if not is_operator(x.name):
+            return ast.Function(
+                x.location,
+                x.name,
+                [_theory_term_to_term(a) for a in x.arguments],
+                False,
+            )
+
+    elif x.ast_type == ASTType.TheorySequence:
+        if x.sequence_type == ast.TheorySequenceType.Tuple:
+            return ast.Function(
+                x.location, "", [_theory_term_to_term(a) for a in x.terms], False
+            )
+
+    raise RuntimeError(f"{location_to_str(x.location)}: invalid term `{x}`")
+
+
+def theory_term_to_term(x: AST, parse: bool = True) -> AST:
+    """
+    Convert the given theory term into a plain clingo term.
+
+    If argument `parse` is set to true, occurences of unparsed theory terms are
+    parsed using `clingo_term_parser()`.
+    """
+    if parse:
+        x = clingo_term_parser()(x)
+    return _theory_term_to_term(x)
+
+
+def _build_atom(
+    location: ast.Location, positive: bool, name: str, arguments: List
+) -> ast.AST:
+    """
+    Helper function to create an atom.
+
+    Arguments:
+    location  -- Location to use.
+    positive  -- Classical sign of the atom.
+    name      -- The name of the atom.
+    arguments -- The arguments of the atom.
+    """
+    ret = ast.Function(location, name, arguments, False)
+    if not positive:
+        ret = ast.UnaryOperation(location, ast.UnaryOperator.Minus, ret)
+    return ast.SymbolicAtom(ret)
+
+
+def negate_sign(sign: ast.Sign) -> ast.Sign:
+    """
+    Negate the given sign.
+    """
+    if sign == ast.Sign.Negation:
+        return ast.Sign.DoubleNegation
+    return ast.Sign.Negation
+
+
+def _theory_term_to_literal(
+    x: AST, positive: bool = True, sign: ast.Sign = ast.Sign.NoSign
+) -> AST:
+    """
+    Convert a given theory term into a symbolic clingo literal.
+    """
+    if x.ast_type == ASTType.TheoryFunction:
+        if x.name == "-":
+            return _theory_term_to_literal(x.arguments[0], not positive, sign)
+
+        if x.name == "not":
+            sign = negate_sign(sign)
+            if not positive:
+                sign = negate_sign(sign)
+            return _theory_term_to_literal(x.arguments[0], True, sign)
+
+        if not is_operator(x.name):
+            atom = _build_atom(
+                x.location,
+                positive,
+                x.name,
+                [theory_term_to_term(a) for a in x.arguments],
+            )
+            return ast.Literal(x.location, sign, atom)
+
+    elif (
+        x.ast_type == ASTType.SymbolicTerm
+        and x.symbol.type == clingo.SymbolType.Function
+        and x.symbol.name
+    ):
+        atom = _build_atom(
+            x.location,
+            (positive == x.symbol.positive),
+            x.symbol.name,
+            [ast.SymbolicTerm(x.location, a) for a in x.symbol.arguments],
+        )
+        return ast.Literal(x.location, sign, atom)
+
+    raise RuntimeError(f"{location_to_str(x.location)}: invalid literal `{x}`")
+
+
+def theory_term_to_literal(x: AST, parse: bool = True) -> AST:
+    """
+    Convert the given theory term into a symbolic clingo literal.
+
+    If argument `parse` is set to true, occurences of unparsed theory terms are
+    parsed using `clingo_literal_parser()`.
+
+    Literals can use an arbitrary number of classical and default negation
+    signs. They are normalized using the following equivalences:
+
+    - `- - lit = lit`
+    - `- not lit = not not lit`
+    - `not not not lit = not lit`
+    """
+    if parse:
+        x = clingo_literal_parser()(x)
+    return _theory_term_to_literal(x, True, ast.Sign.NoSign)
+
+
+
+
+
+
+
+

Functions

+
+
+def ast_to_dict(x: AST) ‑> dict +
+
+

Convert the given ast node into a dictionary representation whose elements +only involve the data structures: dict, list, int, and str.

+

The resulting value can be used with other Python modules like the yaml +or pickle modules.

+

Parameters

+
+
x
+
The ast to transform.
+
+

Returns

+

The corresponding Python representation.

+

See Also

+

dict_to_ast()

+
+ +Expand source code + +
def ast_to_dict(x: AST) -> dict:
+    """
+    Convert the given ast node into a dictionary representation whose elements
+    only involve the data structures: `dict`, `list`, `int`, and `str`.
+
+    The resulting value can be used with other Python modules like the `yaml`
+    or `pickle` modules.
+
+    Parameters
+    ----------
+    x
+        The ast to transform.
+
+    Returns
+    -------
+    The corresponding Python representation.
+
+    See Also
+    --------
+    dict_to_ast
+    """
+    ret = {"ast_type": str(x.ast_type).replace("ASTType.", "")}
+    for key, val in x.items():
+        if key == "location":
+            assert isinstance(val, Location)
+            enc = location_to_str(val)
+        else:
+            enc = _encode(val)
+        ret[key] = enc
+    return ret
+
+
+
+def clingo_literal_parser() ‑> TheoryTermParser +
+
+

Return a theory term parser that parses theory literals similar to clingo's +parser for symbolic literals.

+

Note that for technical reasons pools and the absolute function are not +supported.

+
+ +Expand source code + +
@lru_cache(maxsize=None)
+def clingo_literal_parser() -> TheoryTermParser:
+    """
+    Return a theory term parser that parses theory literals similar to clingo's
+    parser for symbolic literals.
+
+    Note that for technical reasons pools and the absolute function are not
+    supported.
+    """
+    clingo_literal_table = _clingo_term_table.copy()
+    clingo_literal_table.update(
+        {
+            ("-", Arity.Unary): (0, Associativity.NoAssociativity),
+            ("not", Arity.Unary): (0, Associativity.NoAssociativity),
+        }
+    )
+    return TheoryTermParser(clingo_literal_table)
+
+
+
+def clingo_term_parser() ‑> TheoryTermParser +
+
+

Return a theory term parser that parses theory terms like clingo terms.

+

Note that for technical reasons pools and the absolute function are not +supported.

+
+ +Expand source code + +
@lru_cache(maxsize=None)
+def clingo_term_parser() -> TheoryTermParser:
+    """
+    Return a theory term parser that parses theory terms like clingo terms.
+
+    Note that for technical reasons pools and the absolute function are not
+    supported.
+    """
+    return TheoryTermParser(_clingo_term_table)
+
+
+
+def dict_to_ast(x: dict) ‑> AST +
+
+

Convert the Python dict representation of an AST node into an AST node.

+

Parameters

+
+
x
+
The Python representation of the AST.
+
+

Returns

+

The corresponding AST.

+

See Also

+

ast_to_dict()

+
+ +Expand source code + +
def dict_to_ast(x: dict) -> AST:
+    """
+    Convert the Python dict representation of an AST node into an AST node.
+
+    Parameters
+    ----------
+    x
+        The Python representation of the AST.
+
+    Returns
+    -------
+    The corresponding AST.
+
+    See Also
+    --------
+    ast_to_dict
+    """
+    return getattr(ast, x["ast_type"])(
+        **{key: _decode(value, key) for key, value in x.items() if key != "ast_type"}
+    )
+
+
+
+def filter_body_literals(body: Iterable[AST], symbolic_atom_predicate: Union[Callable[[AST], bool], bool] = True, theory_atom_predicate: Union[Callable[[AST], bool], bool] = True, aggregate_predicate: Union[Callable[[AST], bool], bool] = True, conditional_literal_predicate: Union[Callable[[AST], bool], bool] = True, signs: Container[Sign] = (<Sign.NoSign: 0>, <Sign.Negation: 1>, <Sign.DoubleNegation: 2>)) ‑> Iterable[AST] +
+
+

Filters the given body literals according to the given predicates.

+

Parameters

+
+
body
+
An iterable of ASTs for body literals.
+
symbolic_atom_predicate
+
Predicate to filter symbolic atoms.
+
theory_atom_predicate
+
Predicate to filter theory atoms.
+
aggregate_predicate
+
Predicate to filter aggregates.
+
conditional_literal_predicate
+
Predicate to filter conditional literals.
+
signs
+
Only include literals with the given signs.
+
+

Returns

+

An iterarable of body literals.

+

Notes

+

An ASTPredicate is a callable that takes an AST and returns a Boolean. +Booleans True and False are also accepted, meaning that the predicate +is always True or False, respectively.

+
+ +Expand source code + +
def filter_body_literals(
+    body: Iterable[AST],
+    symbolic_atom_predicate: ASTPredicate = True,
+    theory_atom_predicate: ASTPredicate = True,
+    aggregate_predicate: ASTPredicate = True,
+    conditional_literal_predicate: ASTPredicate = True,
+    signs: Container[Sign] = (Sign.NoSign, Sign.Negation, Sign.DoubleNegation),
+) -> Iterable[AST]:
+    """
+    Filters the given body literals according to the given predicates.
+
+    Parameters
+    ----------
+    body
+        An iterable of `AST`s for body literals.
+    symbolic_atom_predicate
+        Predicate to filter symbolic atoms.
+    theory_atom_predicate
+        Predicate to filter theory atoms.
+    aggregate_predicate
+        Predicate to filter aggregates.
+    conditional_literal_predicate
+        Predicate to filter conditional literals.
+    signs
+        Only include literals with the given signs.
+
+    Returns
+    -------
+    An iterarable of body literals.
+
+    Notes
+    -----
+    An `ASTPredicate` is a callable that takes an `AST` and returns a Boolean.
+    Booleans `True` and `False` are also accepted, meaning that the predicate
+    is always `True` or `False`, respectively.
+    """
+    pred = partial(
+        _body_literal_predicate,
+        symbolic_atom_predicate=symbolic_atom_predicate,
+        theory_atom_predicate=theory_atom_predicate,
+        aggregate_predicate=aggregate_predicate,
+        conditional_literal_predicate=conditional_literal_predicate,
+        signs=signs,
+    )
+    return filter(pred, body)
+
+
+
+def location_to_str(loc: Location) ‑> str +
+
+

This function transfroms a loctation object into a readable string.

+

Colons in the location will be quoted ensuring that the resulting is +parsable using str_to_location().

+

Parameters

+
+
loc
+
The location to transform.
+
+

Returns

+

The string representation of the given location.

+
+ +Expand source code + +
def location_to_str(loc: Location) -> str:
+    """
+    This function transfroms a loctation object into a readable string.
+
+    Colons in the location will be quoted ensuring that the resulting is
+    parsable using `str_to_location`.
+
+    Parameters
+    ----------
+    loc
+        The location to transform.
+
+    Returns
+    -------
+    The string representation of the given location.
+    """
+    begin, end = loc.begin, loc.end
+    bf, ef = _quote(begin.filename), _quote(end.filename)
+    ret = f"{bf}:{begin.line}:{begin.column}"
+    dash, eq = True, bf == ef
+    if not eq:
+        ret += f"{'-' if dash else ':'}{ef}"
+        dash = False
+    eq = eq and begin.line == end.line
+    if not eq:
+        ret += f"{'-' if dash else ':'}{end.line}"
+        dash = False
+    eq = eq and begin.column == end.column
+    if not eq:
+        ret += f"{'-' if dash else ':'}{end.column}"
+        dash = False
+    return ret
+
+
+
+def negate_sign(sign: Sign) ‑> Sign +
+
+

Negate the given sign.

+
+ +Expand source code + +
def negate_sign(sign: ast.Sign) -> ast.Sign:
+    """
+    Negate the given sign.
+    """
+    if sign == ast.Sign.Negation:
+        return ast.Sign.DoubleNegation
+    return ast.Sign.Negation
+
+
+
+def parse_theory(s: str) ‑> TheoryParser +
+
+

Turn the given theory into a parser.

+
+ +Expand source code + +
def parse_theory(s: str) -> TheoryParser:
+    """
+    Turn the given theory into a parser.
+    """
+    parser = None
+
+    def extract(stm):
+        nonlocal parser
+        if stm.ast_type == ASTType.TheoryDefinition:
+            if parser is not None:
+                raise ValueError("multiple theory definitions")
+            parser = theory_parser_from_definition(stm)
+        else:
+            assert (
+                stm.ast_type == ASTType.Program
+                and stm.name == "base"
+                and not stm.parameters
+            )
+
+    parse_string(f"{s}.", extract)
+    if parser is None:
+        raise ValueError("no theory definition found")
+    return cast(TheoryParser, parser)
+
+
+
+def partition_body_literals(body: Iterable[AST], symbolic_atom_predicate: Union[Callable[[AST], bool], bool] = True, theory_atom_predicate: Union[Callable[[AST], bool], bool] = True, aggregate_predicate: Union[Callable[[AST], bool], bool] = True, conditional_literal_predicate: Union[Callable[[AST], bool], bool] = True, signs: Container[Sign] = (<Sign.NoSign: 0>, <Sign.Negation: 1>, <Sign.DoubleNegation: 2>)) ‑> Tuple[List[AST], List[AST]] +
+
+

Partition the given body literals according to the given predicates.

+

Parameters

+
+
body
+
An iterable of AST that represents a body.
+
symbolic_atom_predicate
+
Predicate to partition symbolic atoms.
+
theory_atom_predicate
+
Predicate to partition theory atoms.
+
aggregate_predicate
+
Predicate to partition aggregates.
+
conditional_literal_predicate
+
Predicate to partition conditional literals.
+
signs
+
Only include literals with the given signs in the first list.
+
+

Returns

+
+
A pair of lists of body literals. The first iterable yields the literals
+
 
+
that satisfy the predicate while the second one yields the ones that do
+
 
+
+

not.

+

Notes

+

An ASTPredicate is a callable that takes an AST and returns a Boolean. +Booleans True and False are also accepted, meaning that the predicate +is always True or False, respectively.

+
+ +Expand source code + +
def partition_body_literals(
+    body: Iterable[AST],
+    symbolic_atom_predicate: ASTPredicate = True,
+    theory_atom_predicate: ASTPredicate = True,
+    aggregate_predicate: ASTPredicate = True,
+    conditional_literal_predicate: ASTPredicate = True,
+    signs: Container[Sign] = (Sign.NoSign, Sign.Negation, Sign.DoubleNegation),
+) -> Tuple[List[AST], List[AST]]:
+    """
+    Partition the given body literals according to the given predicates.
+
+    Parameters
+    ----------
+    body
+        An iterable of `AST` that represents a body.
+    symbolic_atom_predicate
+        Predicate to partition symbolic atoms.
+    theory_atom_predicate
+        Predicate to partition theory atoms.
+    aggregate_predicate
+        Predicate to partition aggregates.
+    conditional_literal_predicate
+        Predicate to partition conditional literals.
+    signs
+        Only include literals with the given signs in the first list.
+
+    Returns
+    -------
+    A pair of lists of body literals. The first iterable yields the literals
+    that satisfy the predicate while the second one yields the ones that do
+    not.
+
+    Notes
+    -----
+    An `ASTPredicate` is a callable that takes an `AST` and returns a Boolean.
+    Booleans `True` and `False` are also accepted, meaning that the predicate
+    is always `True` or `False`, respectively.
+    """
+    pred = partial(
+        _body_literal_predicate,
+        symbolic_atom_predicate=symbolic_atom_predicate,
+        theory_atom_predicate=theory_atom_predicate,
+        aggregate_predicate=aggregate_predicate,
+        conditional_literal_predicate=conditional_literal_predicate,
+        signs=signs,
+    )
+    part_a: List[AST] = []
+    part_b: List[AST] = []
+    for lit in body:
+        if pred(lit):
+            part_a.append(lit)
+        else:
+            part_b.append(lit)
+    return part_a, part_b
+
+
+
+def prefix_symbolic_atoms(x: AST, prefix: str) ‑> AST +
+
+

Prefix all symbolic atoms in the given AST with the given string.

+

Parameters

+
+
x
+
The ast in which to prefix symbolic atom names.
+
prefix
+
The prefix to add.
+
+

Returns

+

The rewritten AST.

+

See Also

+

rename_symbolic_atoms()

+
+ +Expand source code + +
def prefix_symbolic_atoms(x: AST, prefix: str) -> AST:
+    """
+    Prefix all symbolic atoms in the given AST with the given string.
+
+    Parameters
+    ----------
+    x
+        The ast in which to prefix symbolic atom names.
+    prefix
+        The prefix to add.
+
+    Returns
+    -------
+    The rewritten AST.
+
+    See Also
+    --------
+    rename_symbolic_atoms
+    """
+    return rename_symbolic_atoms(x, lambda s: prefix + s)
+
+
+
+def reify_symbolic_atoms(x: AST, name: str, argument_extender: Callable[[AST], Sequence[AST]] = None, reify_strong_negation: bool = False) ‑> AST +
+
+

Reify all symbolic atoms in the given AST node with the given name and +function.

+

Parameters

+
+
x
+
The ast in which to rename symbolic atoms.
+
name
+
A string to serve as name of the new symbolic atom.
+
argument_extender
+
A function to provide extra arguments. If not provided, no extra +arguments are added. The term passed as argument should be placed in +the correct position.
+
reify_strong_negation
+
Boolean indicating how to encode strong negation. If false, -p(X) is +reified as -name(p(X)). If true, then -p(X) is reified as +name(-p(X)). In the latter case, this means that stable models +containing both name(p(a)) and name(-p(a)) are possible. Clingo +style consistency can be restored by adding the constraint +:- name(X), name(-X), X<-X.
+
+

Returns

+

The rewritten AST.

+
+ +Expand source code + +
def reify_symbolic_atoms(
+    x: AST,
+    name: str,
+    argument_extender: Callable[[AST], Sequence[AST]] = None,
+    reify_strong_negation: bool = False,
+) -> AST:
+    """
+    Reify all symbolic atoms in the given AST node with the given name and
+    function.
+
+    Parameters
+    ----------
+    x
+        The ast in which to rename symbolic atoms.
+    name
+        A string to serve as name of the new symbolic atom.
+    argument_extender
+        A function to provide extra arguments. If not provided, no extra
+        arguments are added. The term passed as argument should be placed in
+        the correct position.
+    reify_strong_negation
+        Boolean indicating how to encode strong negation. If false, `-p(X)` is
+        reified as `-name(p(X))`. If true, then `-p(X)` is reified as
+        `name(-p(X))`. In the latter case, this means that stable models
+        containing both `name(p(a))` and `name(-p(a))` are possible. Clingo
+        style consistency can be restored by adding the constraint
+        `:- name(X), name(-X), X<-X.`
+
+    Returns
+    -------
+    The rewritten AST.
+    """
+
+    def reifier(term: AST):
+        if term.ast_type == ASTType.UnaryOperation and not reify_strong_negation:
+            return UnaryOperation(
+                term.location, term.operator_type, reifier(term.argument)
+            )
+        arguments = argument_extender(term) if argument_extender else [term]
+        return Function(term.location, name, arguments, False)
+
+    return rewrite_symbolic_atoms(x, reifier)
+
+
+
+def rename_symbolic_atoms(x: AST, rename_function: Callable[[str], str]) ‑> AST +
+
+

Rename all symbolic atoms in the given AST node with the given function.

+

Parameters

+
+
x
+
The ast in which to rename symbolic atoms.
+
rename_function
+
A function for renaming symbols.
+
+

Returns

+

The rewritten AST.

+
+ +Expand source code + +
def rename_symbolic_atoms(x: AST, rename_function: Callable[[str], str]) -> AST:
+    """
+    Rename all symbolic atoms in the given AST node with the given function.
+
+    Parameters
+    ----------
+    x
+        The ast in which to rename symbolic atoms.
+    rename_function
+        A function for renaming symbols.
+
+    Returns
+    -------
+    The rewritten AST.
+    """
+
+    def renamer(term: AST):
+        if term.ast_type == ASTType.UnaryOperation:
+            return UnaryOperation(
+                term.location, term.operator_type, renamer(term.argument)
+            )
+        if term.ast_type == ASTType.SymbolicTerm:
+            sym = term.symbol
+            new_name = rename_function(sym.name)
+            return SymbolicTerm(
+                term.location, clingo.Function(new_name, sym.arguments, sym.positive)
+            )
+        if term.ast_type == ASTType.Function:
+            return Function(
+                term.location, rename_function(term.name), term.arguments, term.external
+            )
+        return term
+
+    return rewrite_symbolic_atoms(x, renamer)
+
+
+
+def str_to_location(loc: str) ‑> Location +
+
+

This function parses a location from its string representation.

+

Parameters

+
+
loc
+
The string to parse.
+
+

Returns

+

The parsed location.

+

See Also

+

location_to_str()

+
+ +Expand source code + +
def str_to_location(loc: str) -> Location:
+    """
+    This function parses a location from its string representation.
+
+    Parameters
+    ----------
+    loc
+        The string to parse.
+
+    Returns
+    -------
+    The parsed location.
+
+    See Also
+    --------
+    location_to_str
+    """
+    m = fullmatch(
+        r"(?P<bf>([^\\:]|\\\\|\\:)*):(?P<bl>[0-9]*):(?P<bc>[0-9]+)"
+        r"(-(((?P<ef>([^\\:]|\\\\|\\:)*):)?(?P<el>[0-9]*):)?(?P<ec>[0-9]+))?",
+        loc,
+    )
+    if not m:
+        raise RuntimeError("could not parse location")
+    begin = Position(_unquote(m["bf"]), int(m["bl"]), int(m["bc"]))
+    end = Position(
+        _unquote(_s(m, "bf", "ef")), int(_s(m, "bl", "el")), int(_s(m, "bc", "ec"))
+    )
+    return Location(begin, end)
+
+
+
+def theory_parser_from_definition(x: AST) ‑> TheoryParser +
+
+

Turn an AST node of type TheoryDefinition into a TheoryParser.

+

Parameters

+
+
x
+
An AST representing a theory definition.
+
+

Returns

+

The corresponding TheoryParser.

+
+ +Expand source code + +
def theory_parser_from_definition(x: AST) -> TheoryParser:
+    """
+    Turn an AST node of type TheoryDefinition into a TheoryParser.
+
+    Parameters
+    ----------
+    x
+        An AST representing a theory definition.
+
+    Returns
+    -------
+    The corresponding `TheoryParser`.
+    """
+    assert x.ast_type == ASTType.TheoryDefinition
+
+    terms = {}
+    atoms = {}
+
+    for term_def in x.terms:
+        term_table = {}
+
+        for op_def in term_def.operators:
+            op_assoc: Associativity
+            if op_def.operator_type == TheoryOperatorType.BinaryLeft:
+                op_type = Arity.Binary
+                op_assoc = Associativity.Left
+            elif op_def.operator_type == TheoryOperatorType.BinaryRight:
+                op_type = Arity.Binary
+                op_assoc = Associativity.Right
+            else:
+                op_type = Arity.Unary
+                op_assoc = Associativity.NoAssociativity
+
+            term_table[(op_def.name, op_type)] = (op_def.priority, op_assoc)
+
+        terms[term_def.name] = term_table
+
+    for atom_def in x.atoms:
+        guard = None
+        if atom_def.guard is not None:
+            guard = (atom_def.guard.operators, atom_def.guard.term)
+
+        atoms[(atom_def.name, atom_def.arity)] = (
+            atom_def.atom_type,
+            atom_def.term,
+            guard,
+        )
+
+    return TheoryParser(terms, atoms)
+
+
+
+def theory_term_to_literal(x: AST, parse: bool = True) ‑> AST +
+
+

Convert the given theory term into a symbolic clingo literal.

+

If argument parse is set to true, occurences of unparsed theory terms are +parsed using clingo_literal_parser().

+

Literals can use an arbitrary number of classical and default negation +signs. They are normalized using the following equivalences:

+
    +
  • - - lit = lit
  • +
  • - not lit = not not lit
  • +
  • not not not lit = not lit
  • +
+
+ +Expand source code + +
def theory_term_to_literal(x: AST, parse: bool = True) -> AST:
+    """
+    Convert the given theory term into a symbolic clingo literal.
+
+    If argument `parse` is set to true, occurences of unparsed theory terms are
+    parsed using `clingo_literal_parser()`.
+
+    Literals can use an arbitrary number of classical and default negation
+    signs. They are normalized using the following equivalences:
+
+    - `- - lit = lit`
+    - `- not lit = not not lit`
+    - `not not not lit = not lit`
+    """
+    if parse:
+        x = clingo_literal_parser()(x)
+    return _theory_term_to_literal(x, True, ast.Sign.NoSign)
+
+
+
+def theory_term_to_term(x: AST, parse: bool = True) ‑> AST +
+
+

Convert the given theory term into a plain clingo term.

+

If argument parse is set to true, occurences of unparsed theory terms are +parsed using clingo_term_parser().

+
+ +Expand source code + +
def theory_term_to_term(x: AST, parse: bool = True) -> AST:
+    """
+    Convert the given theory term into a plain clingo term.
+
+    If argument `parse` is set to true, occurences of unparsed theory terms are
+    parsed using `clingo_term_parser()`.
+    """
+    if parse:
+        x = clingo_term_parser()(x)
+    return _theory_term_to_term(x)
+
+
+
+
+
+

Classes

+
+
+class Arity +(value, names=None, *, module=None, qualname=None, type=None, start=1) +
+
+

Enumeration of operator arities.

+
+ +Expand source code + +
class Arity(Enum):
+    """
+    Enumeration of operator arities.
+    """
+
+    # pylint:disable=invalid-name
+    Unary = 1
+    Binary = 2
+
+

Ancestors

+
    +
  • enum.Enum
  • +
+

Class variables

+
+
var Binary
+
+
+
+
var Unary
+
+
+
+
+
+
+class Associativity +(value, names=None, *, module=None, qualname=None, type=None, start=1) +
+
+

Enumeration of operator associativities.

+
+ +Expand source code + +
class Associativity(Enum):
+    """
+    Enumeration of operator associativities.
+    """
+
+    # pylint: disable=invalid-name
+    Left = auto()
+    Right = auto()
+    NoAssociativity = auto()
+
+

Ancestors

+
    +
  • enum.Enum
  • +
+

Class variables

+
+
var Left
+
+
+
+
var NoAssociativity
+
+
+
+
var Right
+
+
+
+
+
+
+class TheoryParser +(terms: Mapping[str, Union[Mapping[Tuple[str, Arity], Tuple[int, Associativity]], TheoryTermParser]], atoms: Mapping[Tuple[str, int], Tuple[TheoryAtomType, str, Optional[Tuple[List[str], str]]]]) +
+
+

This class parses theory atoms in the same way as clingo's internal parser.

+

Parameters

+
+
terms
+
Mapping from term identifiers to TheoryTermParsers. If an operator +table is given, the TheoryTermParser is constructed from this table.
+
atoms
+
Mapping from atom name/arity pairs to tuples defining the acceptable +structure of the theory atom.
+
+
+ +Expand source code + +
class TheoryParser(Transformer):
+    """
+    This class parses theory atoms in the same way as clingo's internal parser.
+
+    Parameters
+    ----------
+    terms
+        Mapping from term identifiers to `TheoryTermParser`s. If an operator
+        table is given, the `TheoryTermParser` is constructed from this table.
+
+    atoms
+        Mapping from atom name/arity pairs to tuples defining the acceptable
+        structure of the theory atom.
+    """
+
+    # pylint: disable=invalid-name
+    _table: Mapping[
+        Tuple[str, int],
+        Tuple[
+            TheoryAtomType,
+            TheoryTermParser,
+            Optional[Tuple[Set[str], TheoryTermParser]],
+        ],
+    ]
+    _in_body: bool
+    _in_head: bool
+    _is_directive: bool
+
+    def __init__(
+        self,
+        terms: Mapping[str, Union[OperatorTable, TheoryTermParser]],
+        atoms: AtomTable,
+    ):
+        self._reset()
+
+        term_parsers = {}
+        for term_key, parser in terms.items():
+            if isinstance(parser, TheoryTermParser):
+                term_parsers[term_key] = parser
+            else:
+                term_parsers[term_key] = TheoryTermParser(parser)
+
+        self._table = {}
+        for atom_key, (atom_type, term_key, guard) in atoms.items():
+            guard_table = None
+            if guard is not None:
+                guard_table = (set(guard[0]), term_parsers[guard[1]])
+            self._table[atom_key] = (atom_type, term_parsers[term_key], guard_table)
+
+    def _reset(self, in_head=True, in_body=True, is_directive=True):
+        """
+        Set state information about active scope.
+        """
+        self._in_head = in_head
+        self._in_body = in_body
+        self._is_directive = is_directive
+
+    def _visit_body(self, x: AST) -> AST:
+        try:
+            self._reset(False, True, False)
+            old = x.body
+            new = self.visit_sequence(old)
+            return x if new is old else x.update(body=new)
+        finally:
+            self._reset()
+
+    def visit_Rule(self, x: AST) -> AST:
+        """
+        Parse theory atoms in body and head.
+
+        Parameters
+        ----------
+        x
+            The AST to rewrite.
+
+        Returns
+        -------
+        The rewritten AST.
+        """
+        ret = self._visit_body(x)
+        try:
+            self._reset(True, False, not x.body)
+            head = self(x.head)
+            if head is not x.head:
+                if ret is x:
+                    ret = copy(ret)
+                ret.head = head
+        finally:
+            self._reset()
+
+        return ret
+
+    def visit_ShowTerm(self, x: AST) -> AST:
+        """
+        Parse theory atoms in body.
+
+        Parameters
+        ----------
+        x
+            The AST to rewrite.
+
+        Returns
+        -------
+        The rewritten AST.
+        """
+        return self._visit_body(x)
+
+    def visit_Minimize(self, x: AST) -> AST:
+        """
+        Parse theory atoms in body.
+
+        Parameters
+        ----------
+        x
+            The AST to rewrite.
+
+        Returns
+        -------
+        The rewritten AST.
+        """
+        return self._visit_body(x)
+
+    def visit_Edge(self, x: AST) -> AST:
+        """
+        Parse theory atoms in body.
+
+        Parameters
+        ----------
+        x
+            The AST to rewrite.
+
+        Returns
+        -------
+        The rewritten AST.
+        """
+        return self._visit_body(x)
+
+    def visit_Heuristic(self, x: AST) -> AST:
+        """
+        Parse theory atoms in body.
+
+        Parameters
+        ----------
+        x
+            The AST to rewrite.
+
+        Returns
+        -------
+        The rewritten AST.
+        """
+        return self._visit_body(x)
+
+    def visit_ProjectAtom(self, x: AST) -> AST:
+        """
+        Parse theory atoms in body.
+
+        Parameters
+        ----------
+        x
+            The AST to rewrite.
+
+        Returns
+        -------
+        The rewritten AST.
+        """
+        return self._visit_body(x)
+
+    def visit_TheoryAtom(self, x: AST) -> AST:
+        """
+        Parse the given theory atom.
+
+        Parameters
+        ----------
+        x
+            The AST to rewrite.
+
+        Returns
+        -------
+        The rewritten AST.
+        """
+        name = x.term.name
+        arity = len(x.term.arguments)
+        if (name, arity) not in self._table:
+            raise RuntimeError(
+                f"theory atom definiton not found: {location_to_str(x.location)}"
+            )
+
+        type_, element_parser, guard_table = self._table[(name, arity)]
+        if type_ == TheoryAtomType.Head and not self._in_head:
+            raise RuntimeError(
+                f"theory atom only accepted in head: {location_to_str(x.location)}"
+            )
+        if type_ == TheoryAtomType.Body and not self._in_body:
+            raise RuntimeError(
+                f"theory atom only accepted in body: {location_to_str(x.location)}"
+            )
+        if type_ == TheoryAtomType.Directive and not (
+            self._in_head and self._is_directive
+        ):
+            raise RuntimeError(
+                f"theory atom must be a directive: {location_to_str(x.location)}"
+            )
+
+        x = copy(x)
+        x.term = element_parser(x.term)
+        x.elements = element_parser.visit_sequence(x.elements)
+
+        if x.guard is not None:
+            if guard_table is None:
+                raise RuntimeError(
+                    f"unexpected guard in theory atom: {location_to_str(x.location)}"
+                )
+
+            guards, guard_parser = guard_table
+            if x.guard.operator_name not in guards:
+                raise RuntimeError(
+                    f"unexpected guard in theory atom: {location_to_str(x.location)}"
+                )
+
+            x.guard = copy(x.guard)
+            x.guard.term = guard_parser(x.guard.term)
+
+        return x
+
+

Ancestors

+ +

Methods

+
+
+def visit_Edge(self, x: AST) ‑> AST +
+
+

Parse theory atoms in body.

+

Parameters

+
+
x
+
The AST to rewrite.
+
+

Returns

+

The rewritten AST.

+
+ +Expand source code + +
def visit_Edge(self, x: AST) -> AST:
+    """
+    Parse theory atoms in body.
+
+    Parameters
+    ----------
+    x
+        The AST to rewrite.
+
+    Returns
+    -------
+    The rewritten AST.
+    """
+    return self._visit_body(x)
+
+
+
+def visit_Heuristic(self, x: AST) ‑> AST +
+
+

Parse theory atoms in body.

+

Parameters

+
+
x
+
The AST to rewrite.
+
+

Returns

+

The rewritten AST.

+
+ +Expand source code + +
def visit_Heuristic(self, x: AST) -> AST:
+    """
+    Parse theory atoms in body.
+
+    Parameters
+    ----------
+    x
+        The AST to rewrite.
+
+    Returns
+    -------
+    The rewritten AST.
+    """
+    return self._visit_body(x)
+
+
+
+def visit_Minimize(self, x: AST) ‑> AST +
+
+

Parse theory atoms in body.

+

Parameters

+
+
x
+
The AST to rewrite.
+
+

Returns

+

The rewritten AST.

+
+ +Expand source code + +
def visit_Minimize(self, x: AST) -> AST:
+    """
+    Parse theory atoms in body.
+
+    Parameters
+    ----------
+    x
+        The AST to rewrite.
+
+    Returns
+    -------
+    The rewritten AST.
+    """
+    return self._visit_body(x)
+
+
+
+def visit_ProjectAtom(self, x: AST) ‑> AST +
+
+

Parse theory atoms in body.

+

Parameters

+
+
x
+
The AST to rewrite.
+
+

Returns

+

The rewritten AST.

+
+ +Expand source code + +
def visit_ProjectAtom(self, x: AST) -> AST:
+    """
+    Parse theory atoms in body.
+
+    Parameters
+    ----------
+    x
+        The AST to rewrite.
+
+    Returns
+    -------
+    The rewritten AST.
+    """
+    return self._visit_body(x)
+
+
+
+def visit_Rule(self, x: AST) ‑> AST +
+
+

Parse theory atoms in body and head.

+

Parameters

+
+
x
+
The AST to rewrite.
+
+

Returns

+

The rewritten AST.

+
+ +Expand source code + +
def visit_Rule(self, x: AST) -> AST:
+    """
+    Parse theory atoms in body and head.
+
+    Parameters
+    ----------
+    x
+        The AST to rewrite.
+
+    Returns
+    -------
+    The rewritten AST.
+    """
+    ret = self._visit_body(x)
+    try:
+        self._reset(True, False, not x.body)
+        head = self(x.head)
+        if head is not x.head:
+            if ret is x:
+                ret = copy(ret)
+            ret.head = head
+    finally:
+        self._reset()
+
+    return ret
+
+
+
+def visit_ShowTerm(self, x: AST) ‑> AST +
+
+

Parse theory atoms in body.

+

Parameters

+
+
x
+
The AST to rewrite.
+
+

Returns

+

The rewritten AST.

+
+ +Expand source code + +
def visit_ShowTerm(self, x: AST) -> AST:
+    """
+    Parse theory atoms in body.
+
+    Parameters
+    ----------
+    x
+        The AST to rewrite.
+
+    Returns
+    -------
+    The rewritten AST.
+    """
+    return self._visit_body(x)
+
+
+
+def visit_TheoryAtom(self, x: AST) ‑> AST +
+
+

Parse the given theory atom.

+

Parameters

+
+
x
+
The AST to rewrite.
+
+

Returns

+

The rewritten AST.

+
+ +Expand source code + +
def visit_TheoryAtom(self, x: AST) -> AST:
+    """
+    Parse the given theory atom.
+
+    Parameters
+    ----------
+    x
+        The AST to rewrite.
+
+    Returns
+    -------
+    The rewritten AST.
+    """
+    name = x.term.name
+    arity = len(x.term.arguments)
+    if (name, arity) not in self._table:
+        raise RuntimeError(
+            f"theory atom definiton not found: {location_to_str(x.location)}"
+        )
+
+    type_, element_parser, guard_table = self._table[(name, arity)]
+    if type_ == TheoryAtomType.Head and not self._in_head:
+        raise RuntimeError(
+            f"theory atom only accepted in head: {location_to_str(x.location)}"
+        )
+    if type_ == TheoryAtomType.Body and not self._in_body:
+        raise RuntimeError(
+            f"theory atom only accepted in body: {location_to_str(x.location)}"
+        )
+    if type_ == TheoryAtomType.Directive and not (
+        self._in_head and self._is_directive
+    ):
+        raise RuntimeError(
+            f"theory atom must be a directive: {location_to_str(x.location)}"
+        )
+
+    x = copy(x)
+    x.term = element_parser(x.term)
+    x.elements = element_parser.visit_sequence(x.elements)
+
+    if x.guard is not None:
+        if guard_table is None:
+            raise RuntimeError(
+                f"unexpected guard in theory atom: {location_to_str(x.location)}"
+            )
+
+        guards, guard_parser = guard_table
+        if x.guard.operator_name not in guards:
+            raise RuntimeError(
+                f"unexpected guard in theory atom: {location_to_str(x.location)}"
+            )
+
+        x.guard = copy(x.guard)
+        x.guard.term = guard_parser(x.guard.term)
+
+    return x
+
+
+
+

Inherited members

+ +
+
+class TheoryTermParser +(table: Union[Mapping[Tuple[str, Arity], Tuple[int, Associativity]], TheoryUnparsedTermParser]) +
+
+

Parser for theory terms in clingo's AST that works like the inbuilt one.

+

This is implemented as a transformer that traverses the AST replacing all +terms found.

+

Parameters

+
+
table
+
This must either be a table of operators or a TheoryUnparsedTermParser.
+
+

See Also

+

TheoryUnparsedTermParser

+
+ +Expand source code + +
class TheoryTermParser(Transformer):
+    """
+    Parser for theory terms in clingo's AST that works like the inbuilt one.
+
+    This is implemented as a transformer that traverses the AST replacing all
+    terms found.
+
+    Parameters
+    ----------
+    table
+        This must either be a table of operators or a `TheoryUnparsedTermParser`.
+
+    See Also
+    --------
+    TheoryUnparsedTermParser
+    """
+
+    # pylint: disable=invalid-name
+
+    def __init__(self, table: Union[OperatorTable, TheoryUnparsedTermParser]):
+        self._parser = (
+            table
+            if isinstance(table, TheoryUnparsedTermParser)
+            else TheoryUnparsedTermParser(table)
+        )
+
+    def visit_TheoryFunction(self, x) -> AST:
+        """
+        Parse the theory function and check if it agrees with the grammar.
+
+        Parameters
+        ----------
+        x
+            The AST to rewrite.
+
+        Returns
+        -------
+        The rewritten AST.
+        """
+        arity = None
+        if len(x.arguments) == 1:
+            arity = Arity.Unary
+        if len(x.arguments) == 2:
+            arity = Arity.Binary
+        if arity is not None and is_operator(x.name):
+            self._parser.check_operator(x.name, arity, x.location)
+
+        return x.update(**self.visit_children(x))
+
+    def visit_TheoryUnparsedTerm(self, x: AST) -> AST:
+        """
+        Parse the given unparsed term.
+
+        Parameters
+        ----------
+        x
+            The AST to rewrite.
+
+        Returns
+        -------
+        The rewritten AST.
+        """
+        return cast(AST, self(self._parser.parse(x)))
+
+

Ancestors

+ +

Methods

+
+
+def visit_TheoryFunction(self, x) ‑> AST +
+
+

Parse the theory function and check if it agrees with the grammar.

+

Parameters

+
+
x
+
The AST to rewrite.
+
+

Returns

+

The rewritten AST.

+
+ +Expand source code + +
def visit_TheoryFunction(self, x) -> AST:
+    """
+    Parse the theory function and check if it agrees with the grammar.
+
+    Parameters
+    ----------
+    x
+        The AST to rewrite.
+
+    Returns
+    -------
+    The rewritten AST.
+    """
+    arity = None
+    if len(x.arguments) == 1:
+        arity = Arity.Unary
+    if len(x.arguments) == 2:
+        arity = Arity.Binary
+    if arity is not None and is_operator(x.name):
+        self._parser.check_operator(x.name, arity, x.location)
+
+    return x.update(**self.visit_children(x))
+
+
+
+def visit_TheoryUnparsedTerm(self, x: AST) ‑> AST +
+
+

Parse the given unparsed term.

+

Parameters

+
+
x
+
The AST to rewrite.
+
+

Returns

+

The rewritten AST.

+
+ +Expand source code + +
def visit_TheoryUnparsedTerm(self, x: AST) -> AST:
+    """
+    Parse the given unparsed term.
+
+    Parameters
+    ----------
+    x
+        The AST to rewrite.
+
+    Returns
+    -------
+    The rewritten AST.
+    """
+    return cast(AST, self(self._parser.parse(x)))
+
+
+
+

Inherited members

+ +
+
+class TheoryUnparsedTermParser +(table: Mapping[Tuple[str, Arity], Tuple[int, Associativity]]) +
+
+

Parser for unparsed theory terms in clingo's AST that works like the +inbuilt one.

+

Note that associativity for unary operators is ignored and binary +operators must use either Associativity.Left or Associativity.Right.

+

Parameters

+
+
table
+
Mapping of operator/arity pairs to priority/associativity pairs.
+
+
+ +Expand source code + +
class TheoryUnparsedTermParser:
+    """
+    Parser for unparsed theory terms in clingo's AST that works like the
+    inbuilt one.
+
+    Note that associativity for unary operators is ignored and binary
+    operators must use either `Associativity.Left` or `Associativity.Right`.
+
+    Parameters
+    ----------
+    table
+        Mapping of operator/arity pairs to priority/associativity pairs.
+    """
+
+    _stack: List[Tuple[str, Arity]]
+    _terms: List[AST]
+    _table: OperatorTable
+
+    def __init__(self, table: OperatorTable):
+        self._stack = []
+        self._terms = []
+        self._table = table
+
+    def _priority_and_associativity(self, operator: str) -> Tuple[int, Associativity]:
+        """
+        Get priority and associativity of the given binary operator.
+        """
+        return self._table[(operator, Arity.Binary)]
+
+    def _priority(self, operator: str, arity: Arity) -> int:
+        """
+        Get priority of the given unary or binary operator.
+        """
+        return self._table[(operator, arity)][0]
+
+    def _check(self, operator: str) -> bool:
+        """
+        Returns true if the stack has to be reduced because of the precedence
+        of the given binary operator is lower than the preceeding operator on
+        the stack.
+        """
+        if not self._stack:
+            return False
+        priority, associativity = self._priority_and_associativity(operator)
+        previous_priority = self._priority(*self._stack[-1])
+        return previous_priority > priority or (
+            previous_priority == priority and associativity == Associativity.Left
+        )
+
+    def _reduce(self) -> None:
+        """
+        Combines the last unary or binary term on the stack.
+        """
+        b = self._terms.pop()
+        operator, arity = self._stack.pop()
+        if arity == Arity.Unary:
+            self._terms.append(TheoryFunction(b.location, operator, [b]))
+        else:
+            a = self._terms.pop()
+            loc = Location(a.location.begin, b.location.end)
+            self._terms.append(TheoryFunction(loc, operator, [a, b]))
+
+    def check_operator(self, operator: str, arity: Arity, location: Location) -> None:
+        """
+        Check if the given operator is in the parse table raising a runtime
+        error if absent.
+
+        Parameters
+        ----------
+        operator
+            The operator name.
+        arity
+            The arity of the operator.
+        location
+            Location of the operator for error reporting.
+        """
+        if (operator, arity) not in self._table:
+            raise RuntimeError(
+                f"cannot parse operator `{operator}`: {location_to_str(location)}"
+            )
+
+    def parse(self, x: AST) -> AST:
+        """
+        Parses the given unparsed term, replacing it by nested theory
+        functions.
+
+        Parameters
+        ----------
+        x
+            The AST to parse.
+
+        Returns
+        -------
+        The rewritten AST.
+        """
+        del self._stack[:]
+        del self._terms[:]
+
+        arity = Arity.Unary
+
+        for element in x.elements:
+            for operator in element.operators:
+                self.check_operator(operator, arity, x.location)
+
+                while arity == Arity.Binary and self._check(operator):
+                    self._reduce()
+
+                self._stack.append((operator, arity))
+                arity = Arity.Unary
+
+            self._terms.append(element.term)
+            arity = Arity.Binary
+
+        while self._stack:
+            self._reduce()
+
+        return self._terms[0]
+
+

Methods

+
+
+def check_operator(self, operator: str, arity: Arity, location: Location) ‑> None +
+
+

Check if the given operator is in the parse table raising a runtime +error if absent.

+

Parameters

+
+
operator
+
The operator name.
+
arity
+
The arity of the operator.
+
location
+
Location of the operator for error reporting.
+
+
+ +Expand source code + +
def check_operator(self, operator: str, arity: Arity, location: Location) -> None:
+    """
+    Check if the given operator is in the parse table raising a runtime
+    error if absent.
+
+    Parameters
+    ----------
+    operator
+        The operator name.
+    arity
+        The arity of the operator.
+    location
+        Location of the operator for error reporting.
+    """
+    if (operator, arity) not in self._table:
+        raise RuntimeError(
+            f"cannot parse operator `{operator}`: {location_to_str(location)}"
+        )
+
+
+
+def parse(self, x: AST) ‑> AST +
+
+

Parses the given unparsed term, replacing it by nested theory +functions.

+

Parameters

+
+
x
+
The AST to parse.
+
+

Returns

+

The rewritten AST.

+
+ +Expand source code + +
def parse(self, x: AST) -> AST:
+    """
+    Parses the given unparsed term, replacing it by nested theory
+    functions.
+
+    Parameters
+    ----------
+    x
+        The AST to parse.
+
+    Returns
+    -------
+    The rewritten AST.
+    """
+    del self._stack[:]
+    del self._terms[:]
+
+    arity = Arity.Unary
+
+    for element in x.elements:
+        for operator in element.operators:
+            self.check_operator(operator, arity, x.location)
+
+            while arity == Arity.Binary and self._check(operator):
+                self._reduce()
+
+            self._stack.append((operator, arity))
+            arity = Arity.Unary
+
+        self._terms.append(element.term)
+        arity = Arity.Binary
+
+    while self._stack:
+        self._reduce()
+
+    return self._terms[0]
+
+
+
+
+
+
+
+ +
+ + + \ No newline at end of file diff --git a/clingo/python-api/5.7/clingox/backend.html b/clingo/python-api/5.7/clingox/backend.html new file mode 100644 index 0000000..3ba8e0f --- /dev/null +++ b/clingo/python-api/5.7/clingox/backend.html @@ -0,0 +1,1101 @@ + + + + + + +clingox.backend API documentation + + + + + + + + + + + +
+
+
+

Module clingox.backend

+
+
+

This module provides a backend wrapper to work with symbols instead of integer +literals.

+

Examples

+

The following example shows how to add the rules

+
a :- b, not c.
+b.
+
+

to a program using the SymbolicBackend:

+
>>> import clingo
+>>> from clingox.backends import SymbolicBackend
+>>> ctl = clingo.Control()
+>>> a = clingo.Function("a")
+>>> b = clingo.Function("b")
+>>> c = clingo.Function("c")
+>>> with SymbolicBackend(ctl.backend()) as symbolic_backend:
+        symbolic_backend.add_rule([a], [b], [c])
+        symbolic_backend.add_rule([b])
+>>> ctl.solve(on_model=lambda m: print("Answer: {}".format(m)))
+Answer: a b
+SAT
+
+

The SymbolicBackend can also be used in combination with the Backend +that it wraps. In this case, it is the Backend that must be used with +Python's with statement:

+
>>> import clingo
+>>> from clingox.backends import SymbolicBackend
+>>> ctl = clingo.Control()
+>>> a = clingo.Function("a")
+>>> b = clingo.Function("b")
+>>> c = clingo.Function("c")
+>>> with ctl.backend() as backend:
+        symbolic_backend = SymbolicBackend(backend)
+        symbolic_backend.add_rule([a], [b], [c])
+        atom_b = backend.add_atom(b)
+        backend.add_rule([atom_b])
+>>> ctl.solve(on_model=lambda m: print("Answer: {}".format(m)))
+Answer: a b
+SAT
+
+
+ +Expand source code + +
"""
+This module provides a backend wrapper to work with symbols instead of integer
+literals.
+
+Examples
+--------
+
+The following example shows how to add the rules
+
+    a :- b, not c.
+    b.
+
+to a program using the `SymbolicBackend`:
+
+    >>> import clingo
+    >>> from clingox.backends import SymbolicBackend
+    >>> ctl = clingo.Control()
+    >>> a = clingo.Function("a")
+    >>> b = clingo.Function("b")
+    >>> c = clingo.Function("c")
+    >>> with SymbolicBackend(ctl.backend()) as symbolic_backend:
+            symbolic_backend.add_rule([a], [b], [c])
+            symbolic_backend.add_rule([b])
+    >>> ctl.solve(on_model=lambda m: print("Answer: {}".format(m)))
+    Answer: a b
+    SAT
+
+The `SymbolicBackend` can also be used in combination with the `Backend`
+that it wraps. In this case, it is the `Backend` that must be used with
+Python's `with` statement:
+
+    >>> import clingo
+    >>> from clingox.backends import SymbolicBackend
+    >>> ctl = clingo.Control()
+    >>> a = clingo.Function("a")
+    >>> b = clingo.Function("b")
+    >>> c = clingo.Function("c")
+    >>> with ctl.backend() as backend:
+            symbolic_backend = SymbolicBackend(backend)
+            symbolic_backend.add_rule([a], [b], [c])
+            atom_b = backend.add_atom(b)
+            backend.add_rule([atom_b])
+    >>> ctl.solve(on_model=lambda m: print("Answer: {}".format(m)))
+    Answer: a b
+    SAT
+"""
+
+from itertools import chain
+from typing import Iterable, Sequence, Tuple
+
+from clingo import Backend, HeuristicType, Symbol, TruthValue
+
+__all__ = ["SymbolicBackend"]
+
+
+def _add_sign(lit: int, sign: bool):
+    """
+    Invert the literal if sign is negative and otherwise leave it untouched.
+    """
+    return lit if sign else -lit
+
+
+class SymbolicBackend:
+    """
+    Backend wrapper providing an interface to extend a logic program. It
+    mirrors the interface of clingo's Backend, but using Symbols rather than
+    integers to represent literals.
+
+    See Also
+    --------
+    clingo.backend.Backend, clingo.control.Control.backend
+
+    Notes
+    --------
+    The `SymbolicBackend` is a context manager and must be used with Python's
+    `with` statement or be attached to an already managed
+    `clingo.backend.Backend` object.
+    """
+
+    backend: Backend
+    """
+    The underlying `clingo.backend.Backend` object.
+    """
+
+    def __init__(self, backend: Backend):
+        self.backend: Backend = backend
+
+    def __enter__(self):
+        """
+        Initialize the backend.
+
+        Returns
+        -------
+        The backend itself.
+
+        Notes
+        -----
+        Must be called before using the backend.
+        """
+        self.backend.__enter__()
+        return self
+
+    def __exit__(self, type_, value, traceback):
+        """
+        Finalize the backend.
+
+        Notes
+        -----
+        Follows Python's __exit__ conventions. Does not suppress exceptions.
+        """
+        return self.backend.__exit__(type_, value, traceback)
+
+    def add_acyc_edge(
+        self,
+        node_u: int,
+        node_v: int,
+        pos_condition: Sequence[Symbol],
+        neg_condition: Sequence[Symbol],
+    ) -> None:
+        """
+        Add an edge directive to the underlying backend.
+
+        Parameters
+        ----------
+        node_u
+            The start node represented as an unsigned integer.
+        node_v
+            The end node represented as an unsigned integer.
+        pos_condition
+            List of atoms forming positive part of the condition.
+        neg_condition
+            List of atoms forming negated part of the condition.
+        """
+        condition = chain(
+            self._add_lits(pos_condition, True), self._add_lits(neg_condition, False)
+        )
+        self.backend.add_acyc_edge(node_u, node_v, list(condition))
+
+    def add_assume(
+        self, pos_atoms: Sequence[Symbol] = (), neg_atoms: Sequence[Symbol] = ()
+    ) -> None:
+        """
+        Add assumptions to the underlying backend.
+
+        Parameters
+        ----------
+        pos_atoms
+            Atoms to assume true.
+        neg_atoms
+            Atoms to assume false.
+        """
+        literals = chain(
+            self._add_lits(pos_atoms, True), self._add_lits(neg_atoms, False)
+        )
+        self.backend.add_assume(list(literals))
+
+    def add_external(self, atom: Symbol, value: TruthValue = TruthValue.False_) -> None:
+        """
+        Mark an atom as external and set its truth value.
+
+        Parameters
+        ----------
+        atom
+            The atom to mark as external.
+        value
+            Optional truth value.
+
+        Notes
+        -----
+        Can also be used to release an external atom using `TruthValue.Release`.
+        """
+        return self.backend.add_external(self.backend.add_atom(atom), value)
+
+    def add_heuristic(
+        self,
+        atom: Symbol,
+        type_: HeuristicType,
+        bias: int,
+        priority: int,
+        pos_condition: Sequence[Symbol],
+        neg_condition: Sequence[Symbol],
+    ) -> None:
+        """
+        Add a heuristic directive to the underlying backend.
+
+        Parameters
+        ----------
+        atom
+            The atom to heuristically modify.
+        type_
+            The type of modification.
+        bias
+            A signed integer.
+        priority
+            An unsigned integer.
+        pos_condition
+            List of program literals forming the positive part of the
+            condition.
+        neg_condition
+            List of program literals forming the negated part of the condition.
+        """
+        condition = chain(
+            self._add_lits(pos_condition, True), self._add_lits(neg_condition, False)
+        )
+        return self.backend.add_heuristic(
+            self.backend.add_atom(atom), type_, bias, priority, list(condition)
+        )
+
+    def add_minimize(
+        self,
+        priority: int,
+        pos_literals: Sequence[Tuple[Symbol, int]],
+        neg_literals: Sequence[Tuple[Symbol, int]],
+    ) -> None:
+        """
+        Add a minimize constraint to the underlying backend.
+
+        Parameters
+        ----------
+        priority
+            Integer for the priority.
+        pos_literals
+            List of pairs of atoms and weights forming the positive
+            part of the condition.
+        neg_literals
+            List of pairs of atoms and weights forming the negated
+            part of the condition.
+        """
+        literals = chain(
+            self._add_wlits(pos_literals, True), self._add_wlits(neg_literals, False)
+        )
+        return self.backend.add_minimize(priority, list(literals))
+
+    def add_project(self, atoms: Sequence[Symbol]) -> None:
+        """
+        Add a project statement to the underlying backend.
+
+        Parameters
+        ----------
+        atoms
+            List of atoms to project on.
+        """
+        return self.backend.add_project(list(self._add_lits(atoms, True)))
+
+    def add_rule(
+        self,
+        head: Sequence[Symbol] = (),
+        pos_body: Sequence[Symbol] = (),
+        neg_body: Sequence[Symbol] = (),
+        choice: bool = False,
+    ) -> None:
+        """
+        Add a disjuntive or choice rule to the underlying backend.
+
+        Parameters
+        ----------
+        head
+            The atoms forming the rule head.
+        pos_body
+            The atoms forming the positive body of the rule
+        neg_body
+            The atoms forming the negated body of the rule
+        choice
+            Whether to add a disjunctive or choice rule.
+
+        Notes
+        -----
+        Integrity constraints and normal rules can be added by using an empty or
+        singleton head list, respectively.
+        """
+        body = chain(self._add_lits(pos_body, True), self._add_lits(neg_body, False))
+        return self.backend.add_rule(
+            list(self._add_lits(head, True)), list(body), choice
+        )
+
+    def add_weight_rule(
+        self,
+        head: Sequence[Symbol],
+        lower: int,
+        pos_body: Sequence[Tuple[Symbol, int]],
+        neg_body: Sequence[Tuple[Symbol, int]],
+        choice: bool = False,
+    ) -> None:
+        """
+        Add a disjunctive or choice rule with one weight constraint with a lower
+        bound in the body to the underlying backend.
+
+        Parameters
+        ----------
+        head
+            The atoms forming the rule head.
+        lower
+            The lower bound.
+        pos_body
+            The pairs of atoms and weights forming the elements of the
+            positive body of the weight constraint.
+        neg_body
+            The pairs of atoms and weights forming the elements of the
+            negative body of the weight constraint.
+        choice
+            Whether to add a disjunctive or choice rule.
+        """
+        body = chain(self._add_wlits(pos_body, True), self._add_wlits(neg_body, False))
+        return self.backend.add_weight_rule(
+            list(self._add_lits(head, True)), lower, list(body), choice
+        )
+
+    def _add_lits(self, atoms: Sequence[Symbol], sign: bool) -> Iterable[int]:
+        """
+        Map the given atoms to program literals with the given sign.
+        """
+        return (_add_sign(self.backend.add_atom(symbol), sign) for symbol in atoms)
+
+    def _add_wlits(
+        self, weighted_symbols: Sequence[Tuple[Symbol, int]], sign: bool
+    ) -> Iterable[Tuple[int, int]]:
+        """
+        Map the given weighted atoms to weighted program literals with the
+        given sign.
+        """
+        return (
+            (_add_sign(self.backend.add_atom(x), sign), w)
+            for (x, w) in weighted_symbols
+        )
+
+
+
+
+
+
+
+
+
+

Classes

+
+
+class SymbolicBackend +(backend: Backend) +
+
+

Backend wrapper providing an interface to extend a logic program. It +mirrors the interface of clingo's Backend, but using Symbols rather than +integers to represent literals.

+

See Also

+

Backend, Control.backend()

+

Notes

+

The SymbolicBackend is a context manager and must be used with Python's +with statement or be attached to an already managed +Backend object.

+
+ +Expand source code + +
class SymbolicBackend:
+    """
+    Backend wrapper providing an interface to extend a logic program. It
+    mirrors the interface of clingo's Backend, but using Symbols rather than
+    integers to represent literals.
+
+    See Also
+    --------
+    clingo.backend.Backend, clingo.control.Control.backend
+
+    Notes
+    --------
+    The `SymbolicBackend` is a context manager and must be used with Python's
+    `with` statement or be attached to an already managed
+    `clingo.backend.Backend` object.
+    """
+
+    backend: Backend
+    """
+    The underlying `clingo.backend.Backend` object.
+    """
+
+    def __init__(self, backend: Backend):
+        self.backend: Backend = backend
+
+    def __enter__(self):
+        """
+        Initialize the backend.
+
+        Returns
+        -------
+        The backend itself.
+
+        Notes
+        -----
+        Must be called before using the backend.
+        """
+        self.backend.__enter__()
+        return self
+
+    def __exit__(self, type_, value, traceback):
+        """
+        Finalize the backend.
+
+        Notes
+        -----
+        Follows Python's __exit__ conventions. Does not suppress exceptions.
+        """
+        return self.backend.__exit__(type_, value, traceback)
+
+    def add_acyc_edge(
+        self,
+        node_u: int,
+        node_v: int,
+        pos_condition: Sequence[Symbol],
+        neg_condition: Sequence[Symbol],
+    ) -> None:
+        """
+        Add an edge directive to the underlying backend.
+
+        Parameters
+        ----------
+        node_u
+            The start node represented as an unsigned integer.
+        node_v
+            The end node represented as an unsigned integer.
+        pos_condition
+            List of atoms forming positive part of the condition.
+        neg_condition
+            List of atoms forming negated part of the condition.
+        """
+        condition = chain(
+            self._add_lits(pos_condition, True), self._add_lits(neg_condition, False)
+        )
+        self.backend.add_acyc_edge(node_u, node_v, list(condition))
+
+    def add_assume(
+        self, pos_atoms: Sequence[Symbol] = (), neg_atoms: Sequence[Symbol] = ()
+    ) -> None:
+        """
+        Add assumptions to the underlying backend.
+
+        Parameters
+        ----------
+        pos_atoms
+            Atoms to assume true.
+        neg_atoms
+            Atoms to assume false.
+        """
+        literals = chain(
+            self._add_lits(pos_atoms, True), self._add_lits(neg_atoms, False)
+        )
+        self.backend.add_assume(list(literals))
+
+    def add_external(self, atom: Symbol, value: TruthValue = TruthValue.False_) -> None:
+        """
+        Mark an atom as external and set its truth value.
+
+        Parameters
+        ----------
+        atom
+            The atom to mark as external.
+        value
+            Optional truth value.
+
+        Notes
+        -----
+        Can also be used to release an external atom using `TruthValue.Release`.
+        """
+        return self.backend.add_external(self.backend.add_atom(atom), value)
+
+    def add_heuristic(
+        self,
+        atom: Symbol,
+        type_: HeuristicType,
+        bias: int,
+        priority: int,
+        pos_condition: Sequence[Symbol],
+        neg_condition: Sequence[Symbol],
+    ) -> None:
+        """
+        Add a heuristic directive to the underlying backend.
+
+        Parameters
+        ----------
+        atom
+            The atom to heuristically modify.
+        type_
+            The type of modification.
+        bias
+            A signed integer.
+        priority
+            An unsigned integer.
+        pos_condition
+            List of program literals forming the positive part of the
+            condition.
+        neg_condition
+            List of program literals forming the negated part of the condition.
+        """
+        condition = chain(
+            self._add_lits(pos_condition, True), self._add_lits(neg_condition, False)
+        )
+        return self.backend.add_heuristic(
+            self.backend.add_atom(atom), type_, bias, priority, list(condition)
+        )
+
+    def add_minimize(
+        self,
+        priority: int,
+        pos_literals: Sequence[Tuple[Symbol, int]],
+        neg_literals: Sequence[Tuple[Symbol, int]],
+    ) -> None:
+        """
+        Add a minimize constraint to the underlying backend.
+
+        Parameters
+        ----------
+        priority
+            Integer for the priority.
+        pos_literals
+            List of pairs of atoms and weights forming the positive
+            part of the condition.
+        neg_literals
+            List of pairs of atoms and weights forming the negated
+            part of the condition.
+        """
+        literals = chain(
+            self._add_wlits(pos_literals, True), self._add_wlits(neg_literals, False)
+        )
+        return self.backend.add_minimize(priority, list(literals))
+
+    def add_project(self, atoms: Sequence[Symbol]) -> None:
+        """
+        Add a project statement to the underlying backend.
+
+        Parameters
+        ----------
+        atoms
+            List of atoms to project on.
+        """
+        return self.backend.add_project(list(self._add_lits(atoms, True)))
+
+    def add_rule(
+        self,
+        head: Sequence[Symbol] = (),
+        pos_body: Sequence[Symbol] = (),
+        neg_body: Sequence[Symbol] = (),
+        choice: bool = False,
+    ) -> None:
+        """
+        Add a disjuntive or choice rule to the underlying backend.
+
+        Parameters
+        ----------
+        head
+            The atoms forming the rule head.
+        pos_body
+            The atoms forming the positive body of the rule
+        neg_body
+            The atoms forming the negated body of the rule
+        choice
+            Whether to add a disjunctive or choice rule.
+
+        Notes
+        -----
+        Integrity constraints and normal rules can be added by using an empty or
+        singleton head list, respectively.
+        """
+        body = chain(self._add_lits(pos_body, True), self._add_lits(neg_body, False))
+        return self.backend.add_rule(
+            list(self._add_lits(head, True)), list(body), choice
+        )
+
+    def add_weight_rule(
+        self,
+        head: Sequence[Symbol],
+        lower: int,
+        pos_body: Sequence[Tuple[Symbol, int]],
+        neg_body: Sequence[Tuple[Symbol, int]],
+        choice: bool = False,
+    ) -> None:
+        """
+        Add a disjunctive or choice rule with one weight constraint with a lower
+        bound in the body to the underlying backend.
+
+        Parameters
+        ----------
+        head
+            The atoms forming the rule head.
+        lower
+            The lower bound.
+        pos_body
+            The pairs of atoms and weights forming the elements of the
+            positive body of the weight constraint.
+        neg_body
+            The pairs of atoms and weights forming the elements of the
+            negative body of the weight constraint.
+        choice
+            Whether to add a disjunctive or choice rule.
+        """
+        body = chain(self._add_wlits(pos_body, True), self._add_wlits(neg_body, False))
+        return self.backend.add_weight_rule(
+            list(self._add_lits(head, True)), lower, list(body), choice
+        )
+
+    def _add_lits(self, atoms: Sequence[Symbol], sign: bool) -> Iterable[int]:
+        """
+        Map the given atoms to program literals with the given sign.
+        """
+        return (_add_sign(self.backend.add_atom(symbol), sign) for symbol in atoms)
+
+    def _add_wlits(
+        self, weighted_symbols: Sequence[Tuple[Symbol, int]], sign: bool
+    ) -> Iterable[Tuple[int, int]]:
+        """
+        Map the given weighted atoms to weighted program literals with the
+        given sign.
+        """
+        return (
+            (_add_sign(self.backend.add_atom(x), sign), w)
+            for (x, w) in weighted_symbols
+        )
+
+

Class variables

+
+
var backendBackend
+
+

The underlying Backend object.

+
+
+

Methods

+
+
+def add_acyc_edge(self, node_u: int, node_v: int, pos_condition: Sequence[Symbol], neg_condition: Sequence[Symbol]) ‑> None +
+
+

Add an edge directive to the underlying backend.

+

Parameters

+
+
node_u
+
The start node represented as an unsigned integer.
+
node_v
+
The end node represented as an unsigned integer.
+
pos_condition
+
List of atoms forming positive part of the condition.
+
neg_condition
+
List of atoms forming negated part of the condition.
+
+
+ +Expand source code + +
def add_acyc_edge(
+    self,
+    node_u: int,
+    node_v: int,
+    pos_condition: Sequence[Symbol],
+    neg_condition: Sequence[Symbol],
+) -> None:
+    """
+    Add an edge directive to the underlying backend.
+
+    Parameters
+    ----------
+    node_u
+        The start node represented as an unsigned integer.
+    node_v
+        The end node represented as an unsigned integer.
+    pos_condition
+        List of atoms forming positive part of the condition.
+    neg_condition
+        List of atoms forming negated part of the condition.
+    """
+    condition = chain(
+        self._add_lits(pos_condition, True), self._add_lits(neg_condition, False)
+    )
+    self.backend.add_acyc_edge(node_u, node_v, list(condition))
+
+
+
+def add_assume(self, pos_atoms: Sequence[Symbol] = (), neg_atoms: Sequence[Symbol] = ()) ‑> None +
+
+

Add assumptions to the underlying backend.

+

Parameters

+
+
pos_atoms
+
Atoms to assume true.
+
neg_atoms
+
Atoms to assume false.
+
+
+ +Expand source code + +
def add_assume(
+    self, pos_atoms: Sequence[Symbol] = (), neg_atoms: Sequence[Symbol] = ()
+) -> None:
+    """
+    Add assumptions to the underlying backend.
+
+    Parameters
+    ----------
+    pos_atoms
+        Atoms to assume true.
+    neg_atoms
+        Atoms to assume false.
+    """
+    literals = chain(
+        self._add_lits(pos_atoms, True), self._add_lits(neg_atoms, False)
+    )
+    self.backend.add_assume(list(literals))
+
+
+
+def add_external(self, atom: Symbol, value: TruthValue = TruthValue.False_) ‑> None +
+
+

Mark an atom as external and set its truth value.

+

Parameters

+
+
atom
+
The atom to mark as external.
+
value
+
Optional truth value.
+
+

Notes

+

Can also be used to release an external atom using TruthValue.Release.

+
+ +Expand source code + +
def add_external(self, atom: Symbol, value: TruthValue = TruthValue.False_) -> None:
+    """
+    Mark an atom as external and set its truth value.
+
+    Parameters
+    ----------
+    atom
+        The atom to mark as external.
+    value
+        Optional truth value.
+
+    Notes
+    -----
+    Can also be used to release an external atom using `TruthValue.Release`.
+    """
+    return self.backend.add_external(self.backend.add_atom(atom), value)
+
+
+
+def add_heuristic(self, atom: Symbol, type_: HeuristicType, bias: int, priority: int, pos_condition: Sequence[Symbol], neg_condition: Sequence[Symbol]) ‑> None +
+
+

Add a heuristic directive to the underlying backend.

+

Parameters

+
+
atom
+
The atom to heuristically modify.
+
type_
+
The type of modification.
+
bias
+
A signed integer.
+
priority
+
An unsigned integer.
+
pos_condition
+
List of program literals forming the positive part of the +condition.
+
neg_condition
+
List of program literals forming the negated part of the condition.
+
+
+ +Expand source code + +
def add_heuristic(
+    self,
+    atom: Symbol,
+    type_: HeuristicType,
+    bias: int,
+    priority: int,
+    pos_condition: Sequence[Symbol],
+    neg_condition: Sequence[Symbol],
+) -> None:
+    """
+    Add a heuristic directive to the underlying backend.
+
+    Parameters
+    ----------
+    atom
+        The atom to heuristically modify.
+    type_
+        The type of modification.
+    bias
+        A signed integer.
+    priority
+        An unsigned integer.
+    pos_condition
+        List of program literals forming the positive part of the
+        condition.
+    neg_condition
+        List of program literals forming the negated part of the condition.
+    """
+    condition = chain(
+        self._add_lits(pos_condition, True), self._add_lits(neg_condition, False)
+    )
+    return self.backend.add_heuristic(
+        self.backend.add_atom(atom), type_, bias, priority, list(condition)
+    )
+
+
+
+def add_minimize(self, priority: int, pos_literals: Sequence[Tuple[Symbol, int]], neg_literals: Sequence[Tuple[Symbol, int]]) ‑> None +
+
+

Add a minimize constraint to the underlying backend.

+

Parameters

+
+
priority
+
Integer for the priority.
+
pos_literals
+
List of pairs of atoms and weights forming the positive +part of the condition.
+
neg_literals
+
List of pairs of atoms and weights forming the negated +part of the condition.
+
+
+ +Expand source code + +
def add_minimize(
+    self,
+    priority: int,
+    pos_literals: Sequence[Tuple[Symbol, int]],
+    neg_literals: Sequence[Tuple[Symbol, int]],
+) -> None:
+    """
+    Add a minimize constraint to the underlying backend.
+
+    Parameters
+    ----------
+    priority
+        Integer for the priority.
+    pos_literals
+        List of pairs of atoms and weights forming the positive
+        part of the condition.
+    neg_literals
+        List of pairs of atoms and weights forming the negated
+        part of the condition.
+    """
+    literals = chain(
+        self._add_wlits(pos_literals, True), self._add_wlits(neg_literals, False)
+    )
+    return self.backend.add_minimize(priority, list(literals))
+
+
+
+def add_project(self, atoms: Sequence[Symbol]) ‑> None +
+
+

Add a project statement to the underlying backend.

+

Parameters

+
+
atoms
+
List of atoms to project on.
+
+
+ +Expand source code + +
def add_project(self, atoms: Sequence[Symbol]) -> None:
+    """
+    Add a project statement to the underlying backend.
+
+    Parameters
+    ----------
+    atoms
+        List of atoms to project on.
+    """
+    return self.backend.add_project(list(self._add_lits(atoms, True)))
+
+
+
+def add_rule(self, head: Sequence[Symbol] = (), pos_body: Sequence[Symbol] = (), neg_body: Sequence[Symbol] = (), choice: bool = False) ‑> None +
+
+

Add a disjuntive or choice rule to the underlying backend.

+

Parameters

+
+
head
+
The atoms forming the rule head.
+
pos_body
+
The atoms forming the positive body of the rule
+
neg_body
+
The atoms forming the negated body of the rule
+
choice
+
Whether to add a disjunctive or choice rule.
+
+

Notes

+

Integrity constraints and normal rules can be added by using an empty or +singleton head list, respectively.

+
+ +Expand source code + +
def add_rule(
+    self,
+    head: Sequence[Symbol] = (),
+    pos_body: Sequence[Symbol] = (),
+    neg_body: Sequence[Symbol] = (),
+    choice: bool = False,
+) -> None:
+    """
+    Add a disjuntive or choice rule to the underlying backend.
+
+    Parameters
+    ----------
+    head
+        The atoms forming the rule head.
+    pos_body
+        The atoms forming the positive body of the rule
+    neg_body
+        The atoms forming the negated body of the rule
+    choice
+        Whether to add a disjunctive or choice rule.
+
+    Notes
+    -----
+    Integrity constraints and normal rules can be added by using an empty or
+    singleton head list, respectively.
+    """
+    body = chain(self._add_lits(pos_body, True), self._add_lits(neg_body, False))
+    return self.backend.add_rule(
+        list(self._add_lits(head, True)), list(body), choice
+    )
+
+
+
+def add_weight_rule(self, head: Sequence[Symbol], lower: int, pos_body: Sequence[Tuple[Symbol, int]], neg_body: Sequence[Tuple[Symbol, int]], choice: bool = False) ‑> None +
+
+

Add a disjunctive or choice rule with one weight constraint with a lower +bound in the body to the underlying backend.

+

Parameters

+
+
head
+
The atoms forming the rule head.
+
lower
+
The lower bound.
+
pos_body
+
The pairs of atoms and weights forming the elements of the +positive body of the weight constraint.
+
neg_body
+
The pairs of atoms and weights forming the elements of the +negative body of the weight constraint.
+
choice
+
Whether to add a disjunctive or choice rule.
+
+
+ +Expand source code + +
def add_weight_rule(
+    self,
+    head: Sequence[Symbol],
+    lower: int,
+    pos_body: Sequence[Tuple[Symbol, int]],
+    neg_body: Sequence[Tuple[Symbol, int]],
+    choice: bool = False,
+) -> None:
+    """
+    Add a disjunctive or choice rule with one weight constraint with a lower
+    bound in the body to the underlying backend.
+
+    Parameters
+    ----------
+    head
+        The atoms forming the rule head.
+    lower
+        The lower bound.
+    pos_body
+        The pairs of atoms and weights forming the elements of the
+        positive body of the weight constraint.
+    neg_body
+        The pairs of atoms and weights forming the elements of the
+        negative body of the weight constraint.
+    choice
+        Whether to add a disjunctive or choice rule.
+    """
+    body = chain(self._add_wlits(pos_body, True), self._add_wlits(neg_body, False))
+    return self.backend.add_weight_rule(
+        list(self._add_lits(head, True)), lower, list(body), choice
+    )
+
+
+
+
+
+
+
+ +
+ + + \ No newline at end of file diff --git a/clingo/python-api/5.7/clingox/index.html b/clingo/python-api/5.7/clingox/index.html new file mode 100644 index 0000000..da3cd49 --- /dev/null +++ b/clingo/python-api/5.7/clingox/index.html @@ -0,0 +1,111 @@ + + + + + + +clingox API documentation + + + + + + + + + + + +
+
+
+

Package clingox

+
+
+

The clingox package provides auxiliary functions that extend the functionality +of the clingo package.

+
+ +Expand source code + +
"""
+The clingox package provides auxiliary functions that extend the functionality
+of the `clingo` package.
+"""
+
+
+
+

Sub-modules

+
+
clingox.ast
+
+

This module provides highlevel functions to work with clingo's AST …

+
+
clingox.backend
+
+

This module provides a backend wrapper to work with symbols instead of integer +literals …

+
+
clingox.pprint
+
+

This module is a replacement for Python`s pprint module for pretty printing +clingo objects.

+
+
clingox.program
+
+

This module provides functions to work with ground programs …

+
+
clingox.reify
+
+

This module provides functions to reify programs …

+
+
clingox.solving
+
+

This module provides functions to approximate the cautious consequences of a +program

+
+
clingox.testing
+
+

The clingox.testing module provides auxiliary functions to create unit test for +the clingo package.

+
+
clingox.theory
+
+

This module provides functions to work with clingo's theories …

+
+
+
+
+
+
+
+
+
+
+ +
+ + + \ No newline at end of file diff --git a/clingo/python-api/5.7/clingox/pprint.html b/clingo/python-api/5.7/clingox/pprint.html new file mode 100644 index 0000000..327b782 --- /dev/null +++ b/clingo/python-api/5.7/clingox/pprint.html @@ -0,0 +1,640 @@ + + + + + + +clingox.pprint API documentation + + + + + + + + + + + +
+
+
+

Module clingox.pprint

+
+
+

This module is a replacement for Python`s pprint module for pretty printing +clingo objects.

+
+ +Expand source code + +
"""
+This module is a replacement for Python`s pprint module for pretty printing
+clingo objects.
+"""
+
+# pylint: disable=protected-access
+
+import pprint as _pp
+from typing import IO, Any, Dict, Optional, Sequence, Tuple
+
+from clingo.ast import AST, ASTSequence, Location, Position
+from clingo.symbol import Symbol, SymbolType
+
+__all__ = [
+    "PrettyPrinter",
+    "isreadable",
+    "isrecursive",
+    "pformat",
+    "pp",
+    "pprint",
+    "saferepr",
+]
+
+
+def pprint(
+    obj: Any,
+    stream: Optional[IO[str]] = None,
+    indent: int = 1,
+    width: int = 80,
+    depth: Optional[int] = None,
+    **kwargs
+):
+    """Pretty-print a Python object to a stream [default is sys.stdout]."""
+    printer = PrettyPrinter(
+        stream=stream, indent=indent, width=width, depth=depth, **kwargs
+    )
+    printer.pprint(obj)
+
+
+def pformat(
+    obj: Any, indent: int = 1, width: int = 80, depth: Optional[int] = None, **kwargs
+) -> str:
+    """Format a Python object into a pretty-printed representation."""
+    return PrettyPrinter(
+        stream=None, indent=indent, width=width, depth=depth, **kwargs
+    ).pformat(obj)
+
+
+def pp(obj: Any, *args, sort_dicts: bool = False, **kwargs):
+    """Pretty-print a Python object."""
+    # pylint: disable=invalid-name
+    pprint(obj, *args, sort_dicts=sort_dicts, **kwargs)  # nocoverage
+
+
+def saferepr(obj: Any) -> str:
+    """Version of repr() which can handle recursive data structures."""
+    if hasattr(PrettyPrinter, "_safe_repr"):
+        return PrettyPrinter()._safe_repr(obj, {}, None, 0)[0]  # type: ignore
+    return _pp.saferepr(obj)  # nocoverage
+
+
+def isreadable(obj: Any) -> bool:
+    """Determine if saferepr(object) is readable by eval()."""
+    if hasattr(PrettyPrinter, "_safe_repr"):
+        return PrettyPrinter()._safe_repr(obj, {}, None, 0)[1]  # type: ignore
+    return _pp.isreadable(obj)  # nocoverage
+
+
+def isrecursive(obj: Any) -> bool:
+    """Determine if object requires a recursive representation."""
+    if hasattr(PrettyPrinter, "_safe_repr"):
+        return PrettyPrinter()._safe_repr(obj, {}, None, 0)[2]  # type: ignore
+    return _pp.isrecursive(obj)  # nocoverage
+
+
+class _DummyLoc:
+    def __repr__(self):
+        return "LOC"
+
+
+class PrettyPrinter(_pp.PrettyPrinter):
+    """
+    A pretty printer extending the standard `PrettyPrinter` class with
+    functions to format `clingo.ast.AST` objects.
+    """
+
+    _hide_location: bool
+
+    def __init__(self, *args, **kwargs):
+        hide_location = kwargs.pop("hide_location", False)
+        super().__init__(*args, **kwargs)
+        self._hide_location = hide_location
+
+    if _pp.PrettyPrinter.__init__.__doc__ is not None:
+        __init__.__doc__ = (
+            _pp.PrettyPrinter.__init__.__doc__
+            + """hide_location
+            Replace locations in `clingo.ast.AST` objects by placeholder LOC.
+        """
+        )
+
+    def _pprint_namedtuple(
+        self,
+        obj: Any,
+        stream: IO[str],
+        indent: int,
+        allowance: int,
+        context: Dict[int, Any],
+        level: int,
+    ):
+        # Note: adjusted _pprint_dataclass from python 3.10
+        cls_name = obj.__class__.__name__
+        indent += len(cls_name) + 1
+        stream.write(cls_name + "(")
+        self._format_kwargs_items(
+            obj._asdict().items(), stream, indent, allowance, context, level
+        )
+        stream.write(")")
+
+    def _format_kwargs_items(
+        self,
+        items: Sequence[Tuple[str, Any]],
+        stream: IO[str],
+        indent: int,
+        allowance: int,
+        context: Dict[int, Any],
+        level: int,
+    ):
+        # Note: copied _pprint_namespace_items from python 3.10
+        write = stream.write
+        delimnl = ",\n" + " " * indent
+        last_index = len(items) - 1
+        for i, (key, ent) in enumerate(items):
+            last = i == last_index
+            write(key)
+            write("=")
+            if id(ent) in context:
+                write("...")  # nocoverage
+            else:
+                self._format(  # type: ignore
+                    ent,
+                    stream,
+                    indent + len(key) + 1,
+                    allowance if last else 1,
+                    context,
+                    level,
+                )
+            if not last:
+                write(delimnl)
+
+    def _format_args_items(
+        self,
+        items: Sequence[Any],
+        stream: IO[str],
+        indent: int,
+        allowance: int,
+        context: Dict[int, Any],
+        level: int,
+    ):
+        write = stream.write
+        delimnl = ",\n" + " " * indent
+        last_index = len(items) - 1
+        for i, ent in enumerate(items):
+            last = i == last_index
+            if id(ent) in context:
+                write("...")  # nocoverage
+            else:
+                self._format(  # type: ignore
+                    ent,
+                    stream,
+                    indent,
+                    allowance if last else 1,
+                    context,
+                    level,
+                )
+            if not last:
+                write(delimnl)
+
+    _dispatch = _pp.PrettyPrinter._dispatch.copy()  # type: ignore
+
+    def _pprint_pos(
+        self,
+        obj: Position,
+        stream: IO[str],
+        indent: int,
+        allowance: int,
+        context: Dict[int, Any],
+        level: int,
+    ):
+        self._pprint_namedtuple(obj, stream, indent, allowance, context, level)
+
+    _dispatch[Position.__repr__] = _pprint_pos
+
+    def _pprint_loc(
+        self,
+        obj: Location,
+        stream: IO[str],
+        indent: int,
+        allowance: int,
+        context: Dict[int, Any],
+        level: int,
+    ):
+        self._pprint_namedtuple(obj, stream, indent, allowance, context, level)
+
+    _dispatch[Location.__repr__] = _pprint_loc
+
+    def _pprint_ast(
+        self,
+        obj: AST,
+        stream: IO[str],
+        indent: int,
+        allowance: int,
+        context: Dict[int, Any],
+        level: int,
+    ):
+        name = str(obj.ast_type).replace("ASTType", "ast")
+        indent += len(name) + 1
+        items = [
+            (key, _DummyLoc() if self._hide_location and key == "location" else val)
+            for key, val in obj.items()
+        ]
+        stream.write(name + "(")
+        self._format_kwargs_items(items, stream, indent, allowance, context, level)
+        stream.write(")")
+
+    _dispatch[AST.__repr__] = _pprint_ast
+    _dispatch[ASTSequence.__repr__] = _pp.PrettyPrinter._pprint_list  # type: ignore
+
+    def _pprint_sym(
+        self,
+        obj: Symbol,
+        stream: IO[str],
+        indent: int,
+        allowance: int,
+        context: Dict[int, Any],
+        level: int,
+    ):
+        if obj.type == SymbolType.Function:
+            indent += 9
+            items = [obj.name, obj.arguments, obj.positive]
+
+            stream.write("Function(")
+            self._format_args_items(items, stream, indent, allowance, context, level)
+            stream.write(")")
+        else:
+            stream.write(repr(obj))
+
+    _dispatch[Symbol.__repr__] = _pprint_sym
+
+
+
+
+
+
+
+

Functions

+
+
+def isreadable(obj: Any) ‑> bool +
+
+

Determine if saferepr(object) is readable by eval().

+
+ +Expand source code + +
def isreadable(obj: Any) -> bool:
+    """Determine if saferepr(object) is readable by eval()."""
+    if hasattr(PrettyPrinter, "_safe_repr"):
+        return PrettyPrinter()._safe_repr(obj, {}, None, 0)[1]  # type: ignore
+    return _pp.isreadable(obj)  # nocoverage
+
+
+
+def isrecursive(obj: Any) ‑> bool +
+
+

Determine if object requires a recursive representation.

+
+ +Expand source code + +
def isrecursive(obj: Any) -> bool:
+    """Determine if object requires a recursive representation."""
+    if hasattr(PrettyPrinter, "_safe_repr"):
+        return PrettyPrinter()._safe_repr(obj, {}, None, 0)[2]  # type: ignore
+    return _pp.isrecursive(obj)  # nocoverage
+
+
+
+def pformat(obj: Any, indent: int = 1, width: int = 80, depth: Optional[int] = None, **kwargs) ‑> str +
+
+

Format a Python object into a pretty-printed representation.

+
+ +Expand source code + +
def pformat(
+    obj: Any, indent: int = 1, width: int = 80, depth: Optional[int] = None, **kwargs
+) -> str:
+    """Format a Python object into a pretty-printed representation."""
+    return PrettyPrinter(
+        stream=None, indent=indent, width=width, depth=depth, **kwargs
+    ).pformat(obj)
+
+
+
+def pp(obj: Any, *args, sort_dicts: bool = False, **kwargs) +
+
+

Pretty-print a Python object.

+
+ +Expand source code + +
def pp(obj: Any, *args, sort_dicts: bool = False, **kwargs):
+    """Pretty-print a Python object."""
+    # pylint: disable=invalid-name
+    pprint(obj, *args, sort_dicts=sort_dicts, **kwargs)  # nocoverage
+
+
+
+def pprint(obj: Any, stream: Optional[IO[str]] = None, indent: int = 1, width: int = 80, depth: Optional[int] = None, **kwargs) +
+
+

Pretty-print a Python object to a stream [default is sys.stdout].

+
+ +Expand source code + +
def pprint(
+    obj: Any,
+    stream: Optional[IO[str]] = None,
+    indent: int = 1,
+    width: int = 80,
+    depth: Optional[int] = None,
+    **kwargs
+):
+    """Pretty-print a Python object to a stream [default is sys.stdout]."""
+    printer = PrettyPrinter(
+        stream=stream, indent=indent, width=width, depth=depth, **kwargs
+    )
+    printer.pprint(obj)
+
+
+
+def saferepr(obj: Any) ‑> str +
+
+

Version of repr() which can handle recursive data structures.

+
+ +Expand source code + +
def saferepr(obj: Any) -> str:
+    """Version of repr() which can handle recursive data structures."""
+    if hasattr(PrettyPrinter, "_safe_repr"):
+        return PrettyPrinter()._safe_repr(obj, {}, None, 0)[0]  # type: ignore
+    return _pp.saferepr(obj)  # nocoverage
+
+
+
+
+
+

Classes

+
+
+class PrettyPrinter +(*args, **kwargs) +
+
+

A pretty printer extending the standard PrettyPrinter class with +functions to format AST objects.

+

Handle pretty printing operations onto a stream using a set of +configured parameters.

+

indent +Number of spaces to indent for each level of nesting.

+

width +Attempted maximum number of columns in the output.

+

depth +The maximum depth to print out nested structures.

+

stream +The desired output stream. +If omitted (or false), the standard +output stream available at construction will be used.

+

compact +If true, several items will be combined in one line.

+

sort_dicts +If true, dict keys are sorted.

+

hide_location +Replace locations in AST objects by placeholder LOC.

+
+ +Expand source code + +
class PrettyPrinter(_pp.PrettyPrinter):
+    """
+    A pretty printer extending the standard `PrettyPrinter` class with
+    functions to format `clingo.ast.AST` objects.
+    """
+
+    _hide_location: bool
+
+    def __init__(self, *args, **kwargs):
+        hide_location = kwargs.pop("hide_location", False)
+        super().__init__(*args, **kwargs)
+        self._hide_location = hide_location
+
+    if _pp.PrettyPrinter.__init__.__doc__ is not None:
+        __init__.__doc__ = (
+            _pp.PrettyPrinter.__init__.__doc__
+            + """hide_location
+            Replace locations in `clingo.ast.AST` objects by placeholder LOC.
+        """
+        )
+
+    def _pprint_namedtuple(
+        self,
+        obj: Any,
+        stream: IO[str],
+        indent: int,
+        allowance: int,
+        context: Dict[int, Any],
+        level: int,
+    ):
+        # Note: adjusted _pprint_dataclass from python 3.10
+        cls_name = obj.__class__.__name__
+        indent += len(cls_name) + 1
+        stream.write(cls_name + "(")
+        self._format_kwargs_items(
+            obj._asdict().items(), stream, indent, allowance, context, level
+        )
+        stream.write(")")
+
+    def _format_kwargs_items(
+        self,
+        items: Sequence[Tuple[str, Any]],
+        stream: IO[str],
+        indent: int,
+        allowance: int,
+        context: Dict[int, Any],
+        level: int,
+    ):
+        # Note: copied _pprint_namespace_items from python 3.10
+        write = stream.write
+        delimnl = ",\n" + " " * indent
+        last_index = len(items) - 1
+        for i, (key, ent) in enumerate(items):
+            last = i == last_index
+            write(key)
+            write("=")
+            if id(ent) in context:
+                write("...")  # nocoverage
+            else:
+                self._format(  # type: ignore
+                    ent,
+                    stream,
+                    indent + len(key) + 1,
+                    allowance if last else 1,
+                    context,
+                    level,
+                )
+            if not last:
+                write(delimnl)
+
+    def _format_args_items(
+        self,
+        items: Sequence[Any],
+        stream: IO[str],
+        indent: int,
+        allowance: int,
+        context: Dict[int, Any],
+        level: int,
+    ):
+        write = stream.write
+        delimnl = ",\n" + " " * indent
+        last_index = len(items) - 1
+        for i, ent in enumerate(items):
+            last = i == last_index
+            if id(ent) in context:
+                write("...")  # nocoverage
+            else:
+                self._format(  # type: ignore
+                    ent,
+                    stream,
+                    indent,
+                    allowance if last else 1,
+                    context,
+                    level,
+                )
+            if not last:
+                write(delimnl)
+
+    _dispatch = _pp.PrettyPrinter._dispatch.copy()  # type: ignore
+
+    def _pprint_pos(
+        self,
+        obj: Position,
+        stream: IO[str],
+        indent: int,
+        allowance: int,
+        context: Dict[int, Any],
+        level: int,
+    ):
+        self._pprint_namedtuple(obj, stream, indent, allowance, context, level)
+
+    _dispatch[Position.__repr__] = _pprint_pos
+
+    def _pprint_loc(
+        self,
+        obj: Location,
+        stream: IO[str],
+        indent: int,
+        allowance: int,
+        context: Dict[int, Any],
+        level: int,
+    ):
+        self._pprint_namedtuple(obj, stream, indent, allowance, context, level)
+
+    _dispatch[Location.__repr__] = _pprint_loc
+
+    def _pprint_ast(
+        self,
+        obj: AST,
+        stream: IO[str],
+        indent: int,
+        allowance: int,
+        context: Dict[int, Any],
+        level: int,
+    ):
+        name = str(obj.ast_type).replace("ASTType", "ast")
+        indent += len(name) + 1
+        items = [
+            (key, _DummyLoc() if self._hide_location and key == "location" else val)
+            for key, val in obj.items()
+        ]
+        stream.write(name + "(")
+        self._format_kwargs_items(items, stream, indent, allowance, context, level)
+        stream.write(")")
+
+    _dispatch[AST.__repr__] = _pprint_ast
+    _dispatch[ASTSequence.__repr__] = _pp.PrettyPrinter._pprint_list  # type: ignore
+
+    def _pprint_sym(
+        self,
+        obj: Symbol,
+        stream: IO[str],
+        indent: int,
+        allowance: int,
+        context: Dict[int, Any],
+        level: int,
+    ):
+        if obj.type == SymbolType.Function:
+            indent += 9
+            items = [obj.name, obj.arguments, obj.positive]
+
+            stream.write("Function(")
+            self._format_args_items(items, stream, indent, allowance, context, level)
+            stream.write(")")
+        else:
+            stream.write(repr(obj))
+
+    _dispatch[Symbol.__repr__] = _pprint_sym
+
+

Ancestors

+
    +
  • pprint.PrettyPrinter
  • +
+
+
+
+
+ +
+ + + \ No newline at end of file diff --git a/clingo/python-api/5.7/clingox/program.html b/clingo/python-api/5.7/clingox/program.html new file mode 100644 index 0000000..270c192 --- /dev/null +++ b/clingo/python-api/5.7/clingox/program.html @@ -0,0 +1,2890 @@ + + + + + + +clingox.program API documentation + + + + + + + + + + + +
+
+
+

Module clingox.program

+
+
+

This module provides functions to work with ground programs.

+

This includes constructing a ground representation using an observer, pretty +printing the ground representation, and adding ground program to control +objects via the backend.

+

Example

+

The following example shows how to:

+ +
>>> from clingo.control import Control
+>>> from clingox.program import Program, ProgramObserver, Remapping
+>>>
+>>> prg = Program()
+>>> ctl_a = Control()
+>>> ctl_a.register_observer(ProgramObserver(prg))
+>>>
+>>> ctl_a.add('base', [], 'a. {b}. c :- b.')
+>>> ctl_a.ground([('base', [])])
+>>> print(prg)
+a.
+__x1.
+c :- b.
+{b}.
+>>>
+>>> ctl_b = Control(['0'])
+>>> with ctl_b.backend() as backend:
+...     mapping = Remapping(backend, prg.output_atoms, prg.facts)
+...     prg.add_to_backend(backend, mapping)
+...
+>>> ctl_b.solve(on_model=print)
+a
+b c a
+
+
+ +Expand source code + +
"""
+This module provides functions to work with ground programs.
+
+This includes constructing a ground representation using an observer, pretty
+printing the ground representation, and adding ground program to control
+objects via the backend.
+
+Example
+-------
+
+The following example shows how to:
+
+- use the `ProgramObserver` to construct a `Program`, and
+- add it to another `clingo.control.Control` object.
+
+```python-repl
+>>> from clingo.control import Control
+>>> from clingox.program import Program, ProgramObserver, Remapping
+>>>
+>>> prg = Program()
+>>> ctl_a = Control()
+>>> ctl_a.register_observer(ProgramObserver(prg))
+>>>
+>>> ctl_a.add('base', [], 'a. {b}. c :- b.')
+>>> ctl_a.ground([('base', [])])
+>>> print(prg)
+a.
+__x1.
+c :- b.
+{b}.
+>>>
+>>> ctl_b = Control(['0'])
+>>> with ctl_b.backend() as backend:
+...     mapping = Remapping(backend, prg.output_atoms, prg.facts)
+...     prg.add_to_backend(backend, mapping)
+...
+>>> ctl_b.solve(on_model=print)
+a
+b c a
+```
+"""
+
+from copy import copy
+from dataclasses import dataclass, field
+from functools import singledispatch
+from itertools import chain
+from typing import (
+    Callable,
+    Iterable,
+    List,
+    Mapping,
+    MutableMapping,
+    MutableSequence,
+    NamedTuple,
+    Optional,
+    Sequence,
+    Tuple,
+    TypeVar,
+)
+
+from clingo import Backend, HeuristicType, Observer, Symbol, TruthValue
+
+__all__ = [
+    "add_to_backend",
+    "pretty_str",
+    "remap",
+    "Edge",
+    "External",
+    "Fact",
+    "Heuristic",
+    "Minimize",
+    "Program",
+    "ProgramObserver",
+    "Project",
+    "Remapping",
+    "Rule",
+    "Show",
+    "WeightRule",
+]
+__pdoc__ = {}
+
+Atom = int
+Literal = int
+Weight = int
+OutputTable = Mapping[Atom, Symbol]
+AtomMap = Callable[[Atom], Atom]
+Statement = TypeVar(
+    "Statement",
+    "Fact",
+    "Show",
+    "Rule",
+    "WeightRule",
+    "Heuristic",
+    "Edge",
+    "Minimize",
+    "External",
+    "Project",
+)
+
+
+@singledispatch
+def pretty_str(stm, output_atoms: OutputTable) -> str:
+    """
+    Pretty print statements.
+
+    Parameters
+    ----------
+    stm
+        The statement to convert to a string.
+    output_atoms
+        A mapping from program atoms to symbols.
+
+    Returns
+    -------
+    The string representation of the statement.
+    """
+    # pylint: disable=unused-argument
+    assert False, "unexpected type"
+
+
+@singledispatch
+def remap(stm, mapping: AtomMap):
+    """
+    Remap literals in the given statement with the provided mapping.
+
+    Parameters
+    ----------
+    stm
+        The statement to remap.
+    mapping
+        The mapping function to remap literals.
+
+    Returns
+    -------
+    The updated statement.
+
+    See Also
+    --------
+    Remapping
+    """
+    # pylint: disable=unused-argument
+    assert False, "unexpected type"
+
+
+@singledispatch
+def add_to_backend(stm, backend: Backend):
+    """
+    Add statements to the backend using the provided mapping to map literals.
+
+    Parameters
+    ----------
+    stm
+        The statement to add to the backend.
+    backend
+        The backend.
+    """
+    # pylint: disable=unused-argument
+    assert False, "unexpected type"
+
+
+def _pretty_str_lit(stm: Literal, output_atoms: OutputTable) -> str:
+    """
+    Pretty print literals and atoms.
+    """
+    atom = abs(stm)
+    if atom in output_atoms:
+        atom_str = str(output_atoms[atom])
+    else:
+        atom_str = f"__x{atom}"
+
+    return f"not {atom_str}" if stm < 0 else atom_str
+
+
+def _pretty_str_rule_head(
+    choice: bool, has_body: bool, head: Sequence[Atom], output_atoms: OutputTable
+) -> str:
+    """
+    Pretty print the head of a rule including the implication symbol if
+    necessary.
+    """
+    ret = ""
+
+    if choice:
+        ret += "{"
+    ret += "; ".join(_pretty_str_lit(lit, output_atoms) for lit in head)
+    if choice:
+        ret += "}"
+
+    if has_body or (not head and not choice):
+        ret += " :- "
+
+    return ret
+
+
+def _pretty_str_truth_value(stm: TruthValue):
+    """
+    Pretty print a truth value.
+    """
+    if stm == TruthValue.False_:
+        return "False"
+    if stm == TruthValue.True_:
+        return "True"
+    return "Free"
+
+
+def _remap_lit(literal: Literal, mapping: AtomMap) -> Atom:
+    return -mapping(-literal) if literal < 0 else mapping(literal)
+
+
+def _remap_seq(literals: Sequence[Literal], mapping: AtomMap):
+    """
+    Apply the mapping to a sequence of literals or atoms.
+    """
+    return [_remap_lit(lit, mapping) for lit in literals]
+
+
+def _remap_wseq(literals: Sequence[Tuple[Literal, Weight]], mapping: AtomMap):
+    """
+    Apply the mapping to a sequence of weighted literals or atoms.
+    """
+    return [(_remap_lit(lit, mapping), weight) for lit, weight in literals]
+
+
+def _remap_stms(stms: MutableSequence[Statement], mapping: AtomMap):
+    """
+    Remap the given statements.
+    """
+    for i, stm in enumerate(stms):
+        stms[i] = remap(stm, mapping)
+
+
+def _add_stms_to_backend(
+    stms: Iterable[Statement], backend: Backend, mapping: Optional[AtomMap]
+):
+    """
+    Remap the given statements returning a list with the result.
+    """
+    for stm in stms:
+        if mapping:
+            add_to_backend(remap(stm, mapping), backend)
+        else:
+            add_to_backend(stm, backend)
+
+
+class Fact(NamedTuple):
+    """
+    Ground representation of a fact.
+    """
+
+    symbol: Symbol
+
+
+@pretty_str.register(Fact)
+def _pretty_str_fact(stm: Fact, output_atoms: OutputTable) -> str:
+    """
+    Pretty print a fact.
+    """
+    # pylint: disable=unused-argument
+    return f"{stm.symbol}."
+
+
+@remap.register(Fact)
+def _remap_fact(stm: Fact, mapping: AtomMap) -> Fact:
+    """
+    Remap a fact statement.
+    """
+    # pylint: disable=unused-argument
+    return stm
+
+
+@add_to_backend.register(Fact)
+def _add_to_backend_fact(stm: Fact, backend: Backend) -> None:
+    """
+    Add a fact to the backend.
+
+    This does nothing to not interfere with the mapping of literals. If facts
+    are to be mapped, then this should be done manually beforehand.
+    """
+    # pylint: disable=unused-argument
+
+
+class Show(NamedTuple):
+    """
+    Ground representation of a show statements.
+    """
+
+    symbol: Symbol
+    condition: Sequence[Literal]
+
+
+@pretty_str.register(Show)
+def _pretty_str_show(stm: Show, output_atoms: OutputTable) -> str:
+    """
+    Pretty print a fact.
+    """
+    body = ", ".join(_pretty_str_lit(lit, output_atoms) for lit in stm.condition)
+    return f'#show {stm.symbol}{": " if body else ""}{body}.'
+
+
+@remap.register(Show)
+def _remap_show(stm: Show, mapping: AtomMap) -> Show:
+    """
+    Remap a show statetment.
+    """
+    return Show(stm.symbol, _remap_seq(stm.condition, mapping))
+
+
+@add_to_backend.register(Show)
+def _add_to_backend_show(stm: Show, backend: Backend) -> None:
+    """
+    Add a show statement to the backend.
+
+    Note that this currently does nothing because backend does not yet support
+    adding to the symbol table.
+    """
+    # pylint: disable=unused-argument
+
+
+class Rule(NamedTuple):
+    """
+    Ground representation of disjunctive and choice rules.
+    """
+
+    choice: bool
+    head: Sequence[Atom]
+    body: Sequence[Literal]
+
+
+@pretty_str.register(Rule)
+def _pretty_str_rule(stm: Rule, output_atoms: OutputTable) -> str:
+    """
+    Pretty print a rule.
+    """
+    head = _pretty_str_rule_head(stm.choice, bool(stm.body), stm.head, output_atoms)
+    body = ", ".join(_pretty_str_lit(lit, output_atoms) for lit in stm.body)
+
+    return f"{head}{body}."
+
+
+@remap.register(Rule)
+def _remap_rule(stm: Rule, mapping: AtomMap) -> Rule:
+    """
+    Remap literals in a rule.
+    """
+    return Rule(
+        stm.choice, _remap_seq(stm.head, mapping), _remap_seq(stm.body, mapping)
+    )
+
+
+@add_to_backend.register(Rule)
+def _add_to_backend_rule(stm: Rule, backend: Backend) -> None:
+    """
+    Add a rule to the backend.
+    """
+    backend.add_rule(stm.head, stm.body, stm.choice)
+
+
+class WeightRule(NamedTuple):
+    """
+    Ground representation of rules with a weight constraint in the body.
+    """
+
+    choice: bool
+    head: Sequence[Atom]
+    lower_bound: Weight
+    body: Sequence[Tuple[Literal, Weight]]
+
+
+@pretty_str.register(WeightRule)
+def _pretty_str_weight_rule(stm: WeightRule, output_atoms: OutputTable) -> str:
+    """
+    Pretty print a rule or weight rule.
+    """
+    head = _pretty_str_rule_head(stm.choice, bool(stm.body), stm.head, output_atoms)
+    body = ", ".join(
+        f"{weight},{i}: {_pretty_str_lit(literal, output_atoms)}"
+        for i, (literal, weight) in enumerate(stm.body)
+    )
+
+    return f"{head}{stm.lower_bound}{{{body}}}."
+
+
+@remap.register(WeightRule)
+def _remap_weight_rule(stm: WeightRule, mapping: AtomMap) -> WeightRule:
+    """
+    Remap literals in a weight rule.
+    """
+    return WeightRule(
+        stm.choice,
+        _remap_seq(stm.head, mapping),
+        stm.lower_bound,
+        _remap_wseq(stm.body, mapping),
+    )
+
+
+@add_to_backend.register(WeightRule)
+def _add_to_backend_weight_rule(stm: WeightRule, backend: Backend) -> None:
+    """
+    Add a weight rule to the backend.
+    """
+    backend.add_weight_rule(stm.head, stm.lower_bound, stm.body, stm.choice)
+
+
+class Project(NamedTuple):
+    """
+    Ground representation of project statements.
+    """
+
+    atom: Atom
+
+
+@pretty_str.register(Project)
+def _pretty_str_project(stm: Project, output_atoms: OutputTable) -> str:
+    """
+    Pretty print a project statement.
+    """
+    return f"#project {_pretty_str_lit(stm.atom, output_atoms)}."
+
+
+@remap.register(Project)
+def _remap_project(stm: Project, mapping: AtomMap):
+    """
+    Remap project statement.
+    """
+    return Project(mapping(stm.atom))
+
+
+@add_to_backend.register(Project)
+def _add_to_backend_project(stm: Project, backend: Backend):
+    """
+    Add a project statement to the backend.
+    """
+    backend.add_project([stm.atom])
+
+
+class External(NamedTuple):
+    """
+    Ground representation of external atoms.
+    """
+
+    atom: Atom
+    value: TruthValue
+
+
+@pretty_str.register(External)
+def _pretty_print_external(stm: External, output_atoms: OutputTable) -> str:
+    """
+    Pretty print an external.
+    """
+    return f"#external {_pretty_str_lit(stm.atom, output_atoms)}. [{_pretty_str_truth_value(stm.value)}]"
+
+
+@remap.register(External)
+def _remap_external(stm: External, mapping: AtomMap) -> External:
+    """
+    Remap the external.
+    """
+    return External(mapping(stm.atom), stm.value)
+
+
+@add_to_backend.register(External)
+def _add_to_backend_external(stm: External, backend: Backend):
+    """
+    Add an external statement to the backend remapping its atom.
+    """
+    backend.add_external(stm.atom, stm.value)
+
+
+class Minimize(NamedTuple):
+    """
+    Ground representation of a minimize statement.
+    """
+
+    priority: Weight
+    literals: Sequence[Tuple[Literal, Weight]]
+
+
+@pretty_str.register(Minimize)
+def _pretty_print_minimize(stm, output_atoms) -> str:
+    """
+    Pretty print a minimize statement.
+    """
+    body = "; ".join(
+        f"{weight}@{stm.priority},{i}: {_pretty_str_lit(literal, output_atoms)}"
+        for i, (literal, weight) in enumerate(stm.literals)
+    )
+    return f"#minimize{{{body}}}."
+
+
+@remap.register(Minimize)
+def _remap_minimize(stm: Minimize, mapping: AtomMap) -> Minimize:
+    """
+    Remap the literals in the minimize statement.
+    """
+    return Minimize(stm.priority, _remap_wseq(stm.literals, mapping))
+
+
+@add_to_backend.register(Minimize)
+def _add_to_backend_minimize(stm: Minimize, backend: Backend):
+    """
+    Add a minimize statement to the backend.
+    """
+    backend.add_minimize(stm.priority, stm.literals)
+
+
+class Heuristic(NamedTuple):
+    """
+    Ground representation of a heuristic statement.
+    """
+
+    atom: Atom
+    type_: HeuristicType
+    bias: Weight
+    priority: Weight
+    condition: Sequence[Literal]
+
+
+def _pretty_str_heuristic_type(type_):
+    return str(type_).replace("HeuristicType.", "")
+
+
+@pretty_str.register(Heuristic)
+def _pretty_str_heuristic(stm: Heuristic, output_atoms: OutputTable) -> str:
+    """
+    Pretty print a heuristic statement.
+    """
+    body = ", ".join(_pretty_str_lit(lit, output_atoms) for lit in stm.condition)
+    head = _pretty_str_lit(stm.atom, output_atoms)
+    type_ = _pretty_str_heuristic_type(stm.type_)
+    return f'#heuristic {head}{": " if body else ""}{body}. [{stm.bias}@{stm.priority}, {type_}]'
+
+
+@remap.register(Heuristic)
+def _remap_heuristic(stm: Heuristic, mapping: AtomMap) -> Heuristic:
+    """
+    Remap the heuristic statement.
+    """
+    return Heuristic(
+        mapping(stm.atom),
+        stm.type_,
+        stm.bias,
+        stm.priority,
+        _remap_seq(stm.condition, mapping),
+    )
+
+
+@add_to_backend.register(Heuristic)
+def _add_to_backend_heuristic(stm: Heuristic, backend: Backend) -> None:
+    """
+    Add a heurisitic statement to the backend.
+    """
+    backend.add_heuristic(stm.atom, stm.type_, stm.bias, stm.priority, stm.condition)
+
+
+class Edge(NamedTuple):
+    """
+    Ground representation of a heuristic statement.
+    """
+
+    u: int
+    v: int
+    condition: Sequence[Literal]
+
+
+@pretty_str.register(Edge)
+def _pretty_str_edge(stm: Edge, output_atoms: OutputTable) -> str:
+    """
+    Pretty print a heuristic statement.
+    """
+    body = ", ".join(_pretty_str_lit(lit, output_atoms) for lit in stm.condition)
+    return f'#edge ({stm.u},{stm.v}){": " if body else ""}{body}.'
+
+
+@remap.register(Edge)
+def _remap_edge(stm: Edge, mapping: AtomMap) -> Edge:
+    """
+    Remap an edge statement.
+    """
+    return Edge(stm.u, stm.v, _remap_seq(stm.condition, mapping))
+
+
+@add_to_backend.register(Edge)
+def _add_to_backend_edge(stm: Edge, backend: Backend) -> None:
+    """
+    Add an edge statement to the backend remapping its literals.
+    """
+    backend.add_acyc_edge(stm.u, stm.v, stm.condition)
+
+
+@dataclass
+class Program:  # pylint: disable=too-many-instance-attributes
+    """
+    Ground program representation.
+
+    Although inefficient, the string representation of this program is parsable
+    by clingo.
+    """
+
+    output_atoms: MutableMapping[Atom, Symbol] = field(default_factory=dict)
+    """
+    A mapping from program atoms to symbols.
+    """
+    shows: List[Show] = field(default_factory=list)
+    """
+    A list of show statements.
+    """
+    facts: List[Fact] = field(default_factory=list)
+    """
+    A list of facts.
+    """
+    rules: List[Rule] = field(default_factory=list)
+    """
+    A list of rules.
+    """
+    weight_rules: List[WeightRule] = field(default_factory=list)
+    """
+    A list of weight rules.
+    """
+    heuristics: List[Heuristic] = field(default_factory=list)
+    """
+    A list of heuristic statements.
+    """
+    edges: List[Edge] = field(default_factory=list)
+    """
+    A list of edge statements.
+    """
+    minimizes: List[Minimize] = field(default_factory=list)
+    """
+    A list of minimize statements.
+    """
+    externals: List[External] = field(default_factory=list)
+    """
+    A list of external statements.
+    """
+    projects: Optional[List[Project]] = None
+    """
+    A list of project statements.
+    """
+    assumptions: List[Literal] = field(default_factory=list)
+    """
+    A list of assumptions in form of program literals.
+    """
+
+    def _pretty_stms(self, arg: Iterable[Statement], sort: bool) -> Iterable[str]:
+        if sort:
+            arg = sorted(arg)
+        return (pretty_str(x, self.output_atoms) for x in arg)
+
+    def _pretty_assumptions(self, sort: bool) -> Iterable[str]:
+        if not self.assumptions:
+            return []
+        arg = sorted(self.assumptions) if sort else self.assumptions
+        assumptions = (_pretty_str_lit(lit, self.output_atoms) for lit in arg)
+        return [f'% assumptions: {", ".join(assumptions)}']
+
+    def _pretty_projects(self, sort: bool) -> Iterable[str]:
+        if self.projects is None:
+            return []
+        # This is to inform that there is an empty projection statement.
+        # It might be worth to allow writing just #project.
+        if not self.projects:
+            return ["#project x: #false."]
+        arg = sorted(self.projects) if sort else self.projects
+        return (pretty_str(project, self.output_atoms) for project in arg)
+
+    def sort(self) -> "Program":
+        """
+        Sort the statements in the program inplace.
+
+        Returns
+        -------
+        A reference to self.
+        """
+        self.shows.sort()
+        self.facts.sort()
+        self.rules.sort()
+        self.weight_rules.sort()
+        self.heuristics.sort()
+        self.edges.sort()
+        self.minimizes.sort()
+        self.externals.sort()
+        if self.projects is not None:
+            self.projects.sort()
+        self.assumptions.sort()
+
+        return self
+
+    def remap(self, mapping: AtomMap) -> "Program":
+        """
+        Remap the literals in the program inplace.
+
+        Parameters
+        ----------
+        mapping
+            A function to remap program atoms.
+
+        Returns
+        -------
+        A reference to self.
+
+        See Also
+        --------
+        remap
+        """
+        _remap_stms(self.shows, mapping)
+        _remap_stms(self.facts, mapping)
+        _remap_stms(self.rules, mapping)
+        _remap_stms(self.weight_rules, mapping)
+        _remap_stms(self.heuristics, mapping)
+        _remap_stms(self.edges, mapping)
+        _remap_stms(self.minimizes, mapping)
+        _remap_stms(self.externals, mapping)
+        if self.projects is not None:
+            _remap_stms(self.projects, mapping)
+        for i, lit in enumerate(self.assumptions):
+            self.assumptions[i] = _remap_lit(lit, mapping)
+        self.output_atoms = {
+            mapping(lit): sym for lit, sym in self.output_atoms.items()
+        }
+
+        return self
+
+    def add_to_backend(
+        self, backend: Backend, mapping: Optional[AtomMap] = None
+    ) -> "Program":
+        """
+        Add the program to the given backend with an optional mapping.
+
+        Note that the output table cannot be added to the backend for technical
+        reasons. This has to be taken care of by the user. See for example the
+        `Remapping` class, which provides functionality for this.
+
+        Parameters
+        ----------
+        backend
+            The backend.
+        mapping
+            A mapping function to remap literals.
+
+        Returns
+        -------
+        A reference to self.
+
+        See Also
+        --------
+        add_to_backend
+        """
+
+        _add_stms_to_backend(self.shows, backend, mapping)
+        _add_stms_to_backend(self.facts, backend, mapping)
+        _add_stms_to_backend(self.rules, backend, mapping)
+        _add_stms_to_backend(self.weight_rules, backend, mapping)
+        _add_stms_to_backend(self.heuristics, backend, mapping)
+        _add_stms_to_backend(self.edges, backend, mapping)
+        _add_stms_to_backend(self.minimizes, backend, mapping)
+        _add_stms_to_backend(self.externals, backend, mapping)
+        if self.projects is not None:
+            if self.projects:
+                _add_stms_to_backend(self.projects, backend, mapping)
+            else:
+                backend.add_project([])
+
+        backend.add_assume(
+            [_remap_lit(lit, mapping) if mapping else lit for lit in self.assumptions]
+        )
+
+        return self
+
+    def pretty_str(self, sort: bool = True) -> str:
+        """
+        Return a readable string represenation of the program.
+
+        Parameters
+        ----------
+        sort
+            Whether to sort the statements in the program befor printing.
+
+        Returns
+        -------
+        The string representation of the program.
+        """
+        return "\n".join(
+            chain(
+                self._pretty_stms(self.shows, sort),
+                self._pretty_stms(self.facts, sort),
+                self._pretty_stms(self.rules, sort),
+                self._pretty_stms(self.weight_rules, sort),
+                self._pretty_stms(self.heuristics, sort),
+                self._pretty_stms(self.edges, sort),
+                self._pretty_stms(self.minimizes, sort),
+                self._pretty_stms(self.externals, sort),
+                self._pretty_projects(sort),
+                self._pretty_assumptions(sort),
+            )
+        )
+
+    def copy(self) -> "Program":
+        """
+        Return a shallow copy of the program copying all mutable state.
+
+        Returns
+        -------
+        A shallow copy of the program.
+        """
+        return copy(self)
+
+    def __str__(self) -> str:
+        """
+        Return a readable string represenation of the program.
+        """
+        return self.pretty_str()
+
+
+class Remapping:
+    """
+    This class maps existing literals to fresh literals as created by the
+    backend.
+
+    Parameters
+    ----------
+    backend
+        The backend used to introduce fresh atoms.
+    output_atoms
+        The output table to initialize the mapping with.
+    facts
+        A list of facts each of which will receive a fresh program atom.
+    """
+
+    _backend: Backend
+    _map: MutableMapping[Atom, Atom]
+
+    def __init__(
+        self, backend: Backend, output_atoms: OutputTable, facts: Iterable[Fact] = None
+    ):
+        self._backend = backend
+        self._map = {}
+        for atom, sym in output_atoms.items():
+            assert atom not in self._map
+            self._map[atom] = self._backend.add_atom(sym)
+        if facts is not None:
+            for fact in facts:
+                backend.add_rule([backend.add_atom(fact.symbol)])
+
+    def __call__(self, atom: Atom) -> Atom:
+        """
+        Map the given program atom to the corresponding atom in the backend.
+
+        If the literal was not mapped during initialization, a new literal is
+        associated with it.
+
+        Parameters
+        ----------
+        atom
+            The atom to remap.
+
+        Returns
+        -------
+        The remapped program atom.
+        """
+        if atom not in self._map:
+            self._map[atom] = self._backend.add_atom()
+
+        return self._map[atom]
+
+
+__pdoc__["Remapping.__call__"] = True
+
+
+class ProgramObserver(Observer):
+    """
+    Program observer to build a ground program representation while grounding.
+
+    This class explicitly ignores theory atoms because they already have a
+    ground representation.
+
+    Parameters
+    ----------
+    program
+        The program to add statements to.
+    """
+
+    _program: Program
+
+    def __init__(self, program: Program):
+        self._program = program
+
+    def begin_step(self) -> None:
+        """
+        Resets the assumptions.
+        """
+        self._program.assumptions.clear()
+
+    def output_atom(self, symbol: Symbol, atom: Atom) -> None:
+        """
+        Add the given atom to the list of facts or output table.
+        """
+        if atom != 0:
+            self._program.output_atoms[atom] = symbol
+        else:
+            self._program.facts.append(Fact(symbol))
+
+    def output_term(self, symbol: Symbol, condition: Sequence[Literal]) -> None:
+        """
+        Add a term to the output table.
+        """
+        self._program.shows.append(Show(symbol, condition))
+
+    def rule(self, choice: bool, head: Sequence[Atom], body: Sequence[Literal]) -> None:
+        """
+        Add a rule to the ground representation.
+
+        Parameters
+        ----------
+        choice
+            Determines if the head is a choice or a disjunction.
+        head
+            List of program atoms forming the rule head.
+        body
+            List of program literals forming the rule body.
+        """
+        self._program.rules.append(Rule(choice, head, body))
+
+    def weight_rule(
+        self,
+        choice: bool,
+        head: Sequence[Atom],
+        lower_bound: Weight,
+        body: Sequence[Tuple[Literal, Weight]],
+    ) -> None:
+        """
+        Add a weight rule to the ground representation.
+
+        Parameters
+        ----------
+        choice
+            Determines if the head is a choice or a disjunction.
+        head
+            List of program atoms forming the head of the rule.
+        lower_bound
+            The lower bound of the weight constraint in the rule body.
+        body
+            List of weighted literals (pairs of literal and weight) forming the
+            elements of the weight constraint.
+        """
+        self._program.weight_rules.append(WeightRule(choice, head, lower_bound, body))
+
+    def project(self, atoms: Sequence[Atom]) -> None:
+        """
+        Add a project statement to the ground representation.
+
+        Parameters
+        ----------
+        atoms
+            The program atoms to project on.
+        """
+        if self._program.projects is None:
+            self._program.projects = []
+        self._program.projects.extend(Project(atom) for atom in atoms)
+
+    def external(self, atom: Atom, value: TruthValue) -> None:
+        """
+        Add an external statement to the ground representation.
+
+        Parameters
+        ----------
+        atom
+            The external atom in form of a program literal.
+        value
+            The truth value of the external statement.
+        """
+        self._program.externals.append(External(atom, value))
+
+    def assume(self, literals: Sequence[Literal]) -> None:
+        """
+        Extend the program with the given assumptions.
+
+        Parameters
+        ----------
+        literals
+            The program literals to assume (positive literals are true and
+            negative literals false for the next solve call).
+        """
+        self._program.assumptions.extend(literals)
+
+    def minimize(
+        self, priority: Weight, literals: Sequence[Tuple[Literal, Weight]]
+    ) -> None:
+        """
+        Add a minimize statement to the ground representation.
+
+        Parameters
+        ----------
+        priority
+            The priority of the directive.
+        literals
+            List of weighted literals whose sum to minimize (pairs of literal
+            and weight).
+        """
+        self._program.minimizes.append(Minimize(priority, literals))
+
+    def acyc_edge(self, node_u: int, node_v: int, condition: Sequence[Literal]) -> None:
+        """
+        Add an edge statement to the gronud representation.
+
+        Parameters
+        ----------
+        node_u
+            The start vertex of the edge (in form of an integer).
+        node_v
+            Тhe end vertex of the edge (in form of an integer).
+        condition
+            The list of program literals forming th condition under which to
+            add the edge.
+        """
+        self._program.edges.append(Edge(node_u, node_v, condition))
+
+    def heuristic(
+        self,
+        atom: Atom,
+        type_: HeuristicType,
+        bias: Weight,
+        priority: Weight,
+        condition: Sequence[Literal],
+    ) -> None:
+        """
+        Add heurisitic statement to the gronud representation.
+
+        Parameters
+        ----------
+        atom
+            The program atom heuristically modified.
+        type_
+            The type of the modification.
+        bias
+            A signed integer.
+        priority
+            An unsigned integer.
+        condition
+            List of program literals.
+        """
+        self._program.heuristics.append(
+            Heuristic(atom, type_, bias, priority, condition)
+        )
+
+
+
+
+
+
+
+

Functions

+
+
+def add_to_backend(stm, backend: Backend) +
+
+

Add statements to the backend using the provided mapping to map literals.

+

Parameters

+
+
stm
+
The statement to add to the backend.
+
backend
+
The backend.
+
+
+ +Expand source code + +
@singledispatch
+def add_to_backend(stm, backend: Backend):
+    """
+    Add statements to the backend using the provided mapping to map literals.
+
+    Parameters
+    ----------
+    stm
+        The statement to add to the backend.
+    backend
+        The backend.
+    """
+    # pylint: disable=unused-argument
+    assert False, "unexpected type"
+
+
+
+def pretty_str(stm, output_atoms: Mapping[int, Symbol]) ‑> str +
+
+

Pretty print statements.

+

Parameters

+
+
stm
+
The statement to convert to a string.
+
output_atoms
+
A mapping from program atoms to symbols.
+
+

Returns

+

The string representation of the statement.

+
+ +Expand source code + +
@singledispatch
+def pretty_str(stm, output_atoms: OutputTable) -> str:
+    """
+    Pretty print statements.
+
+    Parameters
+    ----------
+    stm
+        The statement to convert to a string.
+    output_atoms
+        A mapping from program atoms to symbols.
+
+    Returns
+    -------
+    The string representation of the statement.
+    """
+    # pylint: disable=unused-argument
+    assert False, "unexpected type"
+
+
+
+def remap(stm, mapping: Callable[[int], int]) +
+
+

Remap literals in the given statement with the provided mapping.

+

Parameters

+
+
stm
+
The statement to remap.
+
mapping
+
The mapping function to remap literals.
+
+

Returns

+

The updated statement.

+

See Also

+

Remapping

+
+ +Expand source code + +
@singledispatch
+def remap(stm, mapping: AtomMap):
+    """
+    Remap literals in the given statement with the provided mapping.
+
+    Parameters
+    ----------
+    stm
+        The statement to remap.
+    mapping
+        The mapping function to remap literals.
+
+    Returns
+    -------
+    The updated statement.
+
+    See Also
+    --------
+    Remapping
+    """
+    # pylint: disable=unused-argument
+    assert False, "unexpected type"
+
+
+
+
+
+

Classes

+
+
+class Edge +(u: int, v: int, condition: Sequence[int]) +
+
+

Ground representation of a heuristic statement.

+
+ +Expand source code + +
class Edge(NamedTuple):
+    """
+    Ground representation of a heuristic statement.
+    """
+
+    u: int
+    v: int
+    condition: Sequence[Literal]
+
+

Ancestors

+
    +
  • builtins.tuple
  • +
+

Instance variables

+
+
var condition : Sequence[int]
+
+

Alias for field number 2

+
+
var u : int
+
+

Alias for field number 0

+
+
var v : int
+
+

Alias for field number 1

+
+
+
+
+class External +(atom: int, value: TruthValue) +
+
+

Ground representation of external atoms.

+
+ +Expand source code + +
class External(NamedTuple):
+    """
+    Ground representation of external atoms.
+    """
+
+    atom: Atom
+    value: TruthValue
+
+

Ancestors

+
    +
  • builtins.tuple
  • +
+

Instance variables

+
+
var atom : int
+
+

Alias for field number 0

+
+
var valueTruthValue
+
+

Alias for field number 1

+
+
+
+
+class Fact +(symbol: Symbol) +
+
+

Ground representation of a fact.

+
+ +Expand source code + +
class Fact(NamedTuple):
+    """
+    Ground representation of a fact.
+    """
+
+    symbol: Symbol
+
+

Ancestors

+
    +
  • builtins.tuple
  • +
+

Instance variables

+
+
var symbolSymbol
+
+

Alias for field number 0

+
+
+
+
+class Heuristic +(atom: int, type_: HeuristicType, bias: int, priority: int, condition: Sequence[int]) +
+
+

Ground representation of a heuristic statement.

+
+ +Expand source code + +
class Heuristic(NamedTuple):
+    """
+    Ground representation of a heuristic statement.
+    """
+
+    atom: Atom
+    type_: HeuristicType
+    bias: Weight
+    priority: Weight
+    condition: Sequence[Literal]
+
+

Ancestors

+
    +
  • builtins.tuple
  • +
+

Instance variables

+
+
var atom : int
+
+

Alias for field number 0

+
+
var bias : int
+
+

Alias for field number 2

+
+
var condition : Sequence[int]
+
+

Alias for field number 4

+
+
var priority : int
+
+

Alias for field number 3

+
+
var type_HeuristicType
+
+

Alias for field number 1

+
+
+
+
+class Minimize +(priority: int, literals: Sequence[Tuple[int, int]]) +
+
+

Ground representation of a minimize statement.

+
+ +Expand source code + +
class Minimize(NamedTuple):
+    """
+    Ground representation of a minimize statement.
+    """
+
+    priority: Weight
+    literals: Sequence[Tuple[Literal, Weight]]
+
+

Ancestors

+
    +
  • builtins.tuple
  • +
+

Instance variables

+
+
var literals : Sequence[Tuple[int, int]]
+
+

Alias for field number 1

+
+
var priority : int
+
+

Alias for field number 0

+
+
+
+
+class Program +(output_atoms: MutableMapping[int, Symbol] = <factory>, shows: List[Show] = <factory>, facts: List[Fact] = <factory>, rules: List[Rule] = <factory>, weight_rules: List[WeightRule] = <factory>, heuristics: List[Heuristic] = <factory>, edges: List[Edge] = <factory>, minimizes: List[Minimize] = <factory>, externals: List[External] = <factory>, projects: Optional[List[Project]] = None, assumptions: List[int] = <factory>) +
+
+

Ground program representation.

+

Although inefficient, the string representation of this program is parsable +by clingo.

+
+ +Expand source code + +
@dataclass
+class Program:  # pylint: disable=too-many-instance-attributes
+    """
+    Ground program representation.
+
+    Although inefficient, the string representation of this program is parsable
+    by clingo.
+    """
+
+    output_atoms: MutableMapping[Atom, Symbol] = field(default_factory=dict)
+    """
+    A mapping from program atoms to symbols.
+    """
+    shows: List[Show] = field(default_factory=list)
+    """
+    A list of show statements.
+    """
+    facts: List[Fact] = field(default_factory=list)
+    """
+    A list of facts.
+    """
+    rules: List[Rule] = field(default_factory=list)
+    """
+    A list of rules.
+    """
+    weight_rules: List[WeightRule] = field(default_factory=list)
+    """
+    A list of weight rules.
+    """
+    heuristics: List[Heuristic] = field(default_factory=list)
+    """
+    A list of heuristic statements.
+    """
+    edges: List[Edge] = field(default_factory=list)
+    """
+    A list of edge statements.
+    """
+    minimizes: List[Minimize] = field(default_factory=list)
+    """
+    A list of minimize statements.
+    """
+    externals: List[External] = field(default_factory=list)
+    """
+    A list of external statements.
+    """
+    projects: Optional[List[Project]] = None
+    """
+    A list of project statements.
+    """
+    assumptions: List[Literal] = field(default_factory=list)
+    """
+    A list of assumptions in form of program literals.
+    """
+
+    def _pretty_stms(self, arg: Iterable[Statement], sort: bool) -> Iterable[str]:
+        if sort:
+            arg = sorted(arg)
+        return (pretty_str(x, self.output_atoms) for x in arg)
+
+    def _pretty_assumptions(self, sort: bool) -> Iterable[str]:
+        if not self.assumptions:
+            return []
+        arg = sorted(self.assumptions) if sort else self.assumptions
+        assumptions = (_pretty_str_lit(lit, self.output_atoms) for lit in arg)
+        return [f'% assumptions: {", ".join(assumptions)}']
+
+    def _pretty_projects(self, sort: bool) -> Iterable[str]:
+        if self.projects is None:
+            return []
+        # This is to inform that there is an empty projection statement.
+        # It might be worth to allow writing just #project.
+        if not self.projects:
+            return ["#project x: #false."]
+        arg = sorted(self.projects) if sort else self.projects
+        return (pretty_str(project, self.output_atoms) for project in arg)
+
+    def sort(self) -> "Program":
+        """
+        Sort the statements in the program inplace.
+
+        Returns
+        -------
+        A reference to self.
+        """
+        self.shows.sort()
+        self.facts.sort()
+        self.rules.sort()
+        self.weight_rules.sort()
+        self.heuristics.sort()
+        self.edges.sort()
+        self.minimizes.sort()
+        self.externals.sort()
+        if self.projects is not None:
+            self.projects.sort()
+        self.assumptions.sort()
+
+        return self
+
+    def remap(self, mapping: AtomMap) -> "Program":
+        """
+        Remap the literals in the program inplace.
+
+        Parameters
+        ----------
+        mapping
+            A function to remap program atoms.
+
+        Returns
+        -------
+        A reference to self.
+
+        See Also
+        --------
+        remap
+        """
+        _remap_stms(self.shows, mapping)
+        _remap_stms(self.facts, mapping)
+        _remap_stms(self.rules, mapping)
+        _remap_stms(self.weight_rules, mapping)
+        _remap_stms(self.heuristics, mapping)
+        _remap_stms(self.edges, mapping)
+        _remap_stms(self.minimizes, mapping)
+        _remap_stms(self.externals, mapping)
+        if self.projects is not None:
+            _remap_stms(self.projects, mapping)
+        for i, lit in enumerate(self.assumptions):
+            self.assumptions[i] = _remap_lit(lit, mapping)
+        self.output_atoms = {
+            mapping(lit): sym for lit, sym in self.output_atoms.items()
+        }
+
+        return self
+
+    def add_to_backend(
+        self, backend: Backend, mapping: Optional[AtomMap] = None
+    ) -> "Program":
+        """
+        Add the program to the given backend with an optional mapping.
+
+        Note that the output table cannot be added to the backend for technical
+        reasons. This has to be taken care of by the user. See for example the
+        `Remapping` class, which provides functionality for this.
+
+        Parameters
+        ----------
+        backend
+            The backend.
+        mapping
+            A mapping function to remap literals.
+
+        Returns
+        -------
+        A reference to self.
+
+        See Also
+        --------
+        add_to_backend
+        """
+
+        _add_stms_to_backend(self.shows, backend, mapping)
+        _add_stms_to_backend(self.facts, backend, mapping)
+        _add_stms_to_backend(self.rules, backend, mapping)
+        _add_stms_to_backend(self.weight_rules, backend, mapping)
+        _add_stms_to_backend(self.heuristics, backend, mapping)
+        _add_stms_to_backend(self.edges, backend, mapping)
+        _add_stms_to_backend(self.minimizes, backend, mapping)
+        _add_stms_to_backend(self.externals, backend, mapping)
+        if self.projects is not None:
+            if self.projects:
+                _add_stms_to_backend(self.projects, backend, mapping)
+            else:
+                backend.add_project([])
+
+        backend.add_assume(
+            [_remap_lit(lit, mapping) if mapping else lit for lit in self.assumptions]
+        )
+
+        return self
+
+    def pretty_str(self, sort: bool = True) -> str:
+        """
+        Return a readable string represenation of the program.
+
+        Parameters
+        ----------
+        sort
+            Whether to sort the statements in the program befor printing.
+
+        Returns
+        -------
+        The string representation of the program.
+        """
+        return "\n".join(
+            chain(
+                self._pretty_stms(self.shows, sort),
+                self._pretty_stms(self.facts, sort),
+                self._pretty_stms(self.rules, sort),
+                self._pretty_stms(self.weight_rules, sort),
+                self._pretty_stms(self.heuristics, sort),
+                self._pretty_stms(self.edges, sort),
+                self._pretty_stms(self.minimizes, sort),
+                self._pretty_stms(self.externals, sort),
+                self._pretty_projects(sort),
+                self._pretty_assumptions(sort),
+            )
+        )
+
+    def copy(self) -> "Program":
+        """
+        Return a shallow copy of the program copying all mutable state.
+
+        Returns
+        -------
+        A shallow copy of the program.
+        """
+        return copy(self)
+
+    def __str__(self) -> str:
+        """
+        Return a readable string represenation of the program.
+        """
+        return self.pretty_str()
+
+

Class variables

+
+
var assumptions : List[int]
+
+

A list of assumptions in form of program literals.

+
+
var edges : List[Edge]
+
+

A list of edge statements.

+
+
var externals : List[External]
+
+

A list of external statements.

+
+
var facts : List[Fact]
+
+

A list of facts.

+
+
var heuristics : List[Heuristic]
+
+

A list of heuristic statements.

+
+
var minimizes : List[Minimize]
+
+

A list of minimize statements.

+
+
var output_atoms : MutableMapping[int, Symbol]
+
+

A mapping from program atoms to symbols.

+
+
var projects : Optional[List[Project]]
+
+

A list of project statements.

+
+
var rules : List[Rule]
+
+

A list of rules.

+
+
var shows : List[Show]
+
+

A list of show statements.

+
+
var weight_rules : List[WeightRule]
+
+

A list of weight rules.

+
+
+

Methods

+
+
+def add_to_backend(self, backend: Backend, mapping: Optional[Callable[[int], int]] = None) ‑> Program +
+
+

Add the program to the given backend with an optional mapping.

+

Note that the output table cannot be added to the backend for technical +reasons. This has to be taken care of by the user. See for example the +Remapping class, which provides functionality for this.

+

Parameters

+
+
backend
+
The backend.
+
mapping
+
A mapping function to remap literals.
+
+

Returns

+

A reference to self.

+

See Also

+

add_to_backend()

+
+ +Expand source code + +
def add_to_backend(
+    self, backend: Backend, mapping: Optional[AtomMap] = None
+) -> "Program":
+    """
+    Add the program to the given backend with an optional mapping.
+
+    Note that the output table cannot be added to the backend for technical
+    reasons. This has to be taken care of by the user. See for example the
+    `Remapping` class, which provides functionality for this.
+
+    Parameters
+    ----------
+    backend
+        The backend.
+    mapping
+        A mapping function to remap literals.
+
+    Returns
+    -------
+    A reference to self.
+
+    See Also
+    --------
+    add_to_backend
+    """
+
+    _add_stms_to_backend(self.shows, backend, mapping)
+    _add_stms_to_backend(self.facts, backend, mapping)
+    _add_stms_to_backend(self.rules, backend, mapping)
+    _add_stms_to_backend(self.weight_rules, backend, mapping)
+    _add_stms_to_backend(self.heuristics, backend, mapping)
+    _add_stms_to_backend(self.edges, backend, mapping)
+    _add_stms_to_backend(self.minimizes, backend, mapping)
+    _add_stms_to_backend(self.externals, backend, mapping)
+    if self.projects is not None:
+        if self.projects:
+            _add_stms_to_backend(self.projects, backend, mapping)
+        else:
+            backend.add_project([])
+
+    backend.add_assume(
+        [_remap_lit(lit, mapping) if mapping else lit for lit in self.assumptions]
+    )
+
+    return self
+
+
+
+def copy(self) ‑> Program +
+
+

Return a shallow copy of the program copying all mutable state.

+

Returns

+

A shallow copy of the program.

+
+ +Expand source code + +
def copy(self) -> "Program":
+    """
+    Return a shallow copy of the program copying all mutable state.
+
+    Returns
+    -------
+    A shallow copy of the program.
+    """
+    return copy(self)
+
+
+
+def pretty_str(self, sort: bool = True) ‑> str +
+
+

Return a readable string represenation of the program.

+

Parameters

+
+
sort
+
Whether to sort the statements in the program befor printing.
+
+

Returns

+

The string representation of the program.

+
+ +Expand source code + +
def pretty_str(self, sort: bool = True) -> str:
+    """
+    Return a readable string represenation of the program.
+
+    Parameters
+    ----------
+    sort
+        Whether to sort the statements in the program befor printing.
+
+    Returns
+    -------
+    The string representation of the program.
+    """
+    return "\n".join(
+        chain(
+            self._pretty_stms(self.shows, sort),
+            self._pretty_stms(self.facts, sort),
+            self._pretty_stms(self.rules, sort),
+            self._pretty_stms(self.weight_rules, sort),
+            self._pretty_stms(self.heuristics, sort),
+            self._pretty_stms(self.edges, sort),
+            self._pretty_stms(self.minimizes, sort),
+            self._pretty_stms(self.externals, sort),
+            self._pretty_projects(sort),
+            self._pretty_assumptions(sort),
+        )
+    )
+
+
+
+def remap(self, mapping: Callable[[int], int]) ‑> Program +
+
+

Remap the literals in the program inplace.

+

Parameters

+
+
mapping
+
A function to remap program atoms.
+
+

Returns

+

A reference to self.

+

See Also

+

remap()

+
+ +Expand source code + +
def remap(self, mapping: AtomMap) -> "Program":
+    """
+    Remap the literals in the program inplace.
+
+    Parameters
+    ----------
+    mapping
+        A function to remap program atoms.
+
+    Returns
+    -------
+    A reference to self.
+
+    See Also
+    --------
+    remap
+    """
+    _remap_stms(self.shows, mapping)
+    _remap_stms(self.facts, mapping)
+    _remap_stms(self.rules, mapping)
+    _remap_stms(self.weight_rules, mapping)
+    _remap_stms(self.heuristics, mapping)
+    _remap_stms(self.edges, mapping)
+    _remap_stms(self.minimizes, mapping)
+    _remap_stms(self.externals, mapping)
+    if self.projects is not None:
+        _remap_stms(self.projects, mapping)
+    for i, lit in enumerate(self.assumptions):
+        self.assumptions[i] = _remap_lit(lit, mapping)
+    self.output_atoms = {
+        mapping(lit): sym for lit, sym in self.output_atoms.items()
+    }
+
+    return self
+
+
+
+def sort(self) ‑> Program +
+
+

Sort the statements in the program inplace.

+

Returns

+

A reference to self.

+
+ +Expand source code + +
def sort(self) -> "Program":
+    """
+    Sort the statements in the program inplace.
+
+    Returns
+    -------
+    A reference to self.
+    """
+    self.shows.sort()
+    self.facts.sort()
+    self.rules.sort()
+    self.weight_rules.sort()
+    self.heuristics.sort()
+    self.edges.sort()
+    self.minimizes.sort()
+    self.externals.sort()
+    if self.projects is not None:
+        self.projects.sort()
+    self.assumptions.sort()
+
+    return self
+
+
+
+
+
+class ProgramObserver +(program: Program) +
+
+

Program observer to build a ground program representation while grounding.

+

This class explicitly ignores theory atoms because they already have a +ground representation.

+

Parameters

+
+
program
+
The program to add statements to.
+
+
+ +Expand source code + +
class ProgramObserver(Observer):
+    """
+    Program observer to build a ground program representation while grounding.
+
+    This class explicitly ignores theory atoms because they already have a
+    ground representation.
+
+    Parameters
+    ----------
+    program
+        The program to add statements to.
+    """
+
+    _program: Program
+
+    def __init__(self, program: Program):
+        self._program = program
+
+    def begin_step(self) -> None:
+        """
+        Resets the assumptions.
+        """
+        self._program.assumptions.clear()
+
+    def output_atom(self, symbol: Symbol, atom: Atom) -> None:
+        """
+        Add the given atom to the list of facts or output table.
+        """
+        if atom != 0:
+            self._program.output_atoms[atom] = symbol
+        else:
+            self._program.facts.append(Fact(symbol))
+
+    def output_term(self, symbol: Symbol, condition: Sequence[Literal]) -> None:
+        """
+        Add a term to the output table.
+        """
+        self._program.shows.append(Show(symbol, condition))
+
+    def rule(self, choice: bool, head: Sequence[Atom], body: Sequence[Literal]) -> None:
+        """
+        Add a rule to the ground representation.
+
+        Parameters
+        ----------
+        choice
+            Determines if the head is a choice or a disjunction.
+        head
+            List of program atoms forming the rule head.
+        body
+            List of program literals forming the rule body.
+        """
+        self._program.rules.append(Rule(choice, head, body))
+
+    def weight_rule(
+        self,
+        choice: bool,
+        head: Sequence[Atom],
+        lower_bound: Weight,
+        body: Sequence[Tuple[Literal, Weight]],
+    ) -> None:
+        """
+        Add a weight rule to the ground representation.
+
+        Parameters
+        ----------
+        choice
+            Determines if the head is a choice or a disjunction.
+        head
+            List of program atoms forming the head of the rule.
+        lower_bound
+            The lower bound of the weight constraint in the rule body.
+        body
+            List of weighted literals (pairs of literal and weight) forming the
+            elements of the weight constraint.
+        """
+        self._program.weight_rules.append(WeightRule(choice, head, lower_bound, body))
+
+    def project(self, atoms: Sequence[Atom]) -> None:
+        """
+        Add a project statement to the ground representation.
+
+        Parameters
+        ----------
+        atoms
+            The program atoms to project on.
+        """
+        if self._program.projects is None:
+            self._program.projects = []
+        self._program.projects.extend(Project(atom) for atom in atoms)
+
+    def external(self, atom: Atom, value: TruthValue) -> None:
+        """
+        Add an external statement to the ground representation.
+
+        Parameters
+        ----------
+        atom
+            The external atom in form of a program literal.
+        value
+            The truth value of the external statement.
+        """
+        self._program.externals.append(External(atom, value))
+
+    def assume(self, literals: Sequence[Literal]) -> None:
+        """
+        Extend the program with the given assumptions.
+
+        Parameters
+        ----------
+        literals
+            The program literals to assume (positive literals are true and
+            negative literals false for the next solve call).
+        """
+        self._program.assumptions.extend(literals)
+
+    def minimize(
+        self, priority: Weight, literals: Sequence[Tuple[Literal, Weight]]
+    ) -> None:
+        """
+        Add a minimize statement to the ground representation.
+
+        Parameters
+        ----------
+        priority
+            The priority of the directive.
+        literals
+            List of weighted literals whose sum to minimize (pairs of literal
+            and weight).
+        """
+        self._program.minimizes.append(Minimize(priority, literals))
+
+    def acyc_edge(self, node_u: int, node_v: int, condition: Sequence[Literal]) -> None:
+        """
+        Add an edge statement to the gronud representation.
+
+        Parameters
+        ----------
+        node_u
+            The start vertex of the edge (in form of an integer).
+        node_v
+            Тhe end vertex of the edge (in form of an integer).
+        condition
+            The list of program literals forming th condition under which to
+            add the edge.
+        """
+        self._program.edges.append(Edge(node_u, node_v, condition))
+
+    def heuristic(
+        self,
+        atom: Atom,
+        type_: HeuristicType,
+        bias: Weight,
+        priority: Weight,
+        condition: Sequence[Literal],
+    ) -> None:
+        """
+        Add heurisitic statement to the gronud representation.
+
+        Parameters
+        ----------
+        atom
+            The program atom heuristically modified.
+        type_
+            The type of the modification.
+        bias
+            A signed integer.
+        priority
+            An unsigned integer.
+        condition
+            List of program literals.
+        """
+        self._program.heuristics.append(
+            Heuristic(atom, type_, bias, priority, condition)
+        )
+
+

Ancestors

+ +

Methods

+
+
+def acyc_edge(self, node_u: int, node_v: int, condition: Sequence[int]) ‑> None +
+
+

Add an edge statement to the gronud representation.

+

Parameters

+
+
node_u
+
The start vertex of the edge (in form of an integer).
+
node_v
+
Тhe end vertex of the edge (in form of an integer).
+
condition
+
The list of program literals forming th condition under which to +add the edge.
+
+
+ +Expand source code + +
def acyc_edge(self, node_u: int, node_v: int, condition: Sequence[Literal]) -> None:
+    """
+    Add an edge statement to the gronud representation.
+
+    Parameters
+    ----------
+    node_u
+        The start vertex of the edge (in form of an integer).
+    node_v
+        Тhe end vertex of the edge (in form of an integer).
+    condition
+        The list of program literals forming th condition under which to
+        add the edge.
+    """
+    self._program.edges.append(Edge(node_u, node_v, condition))
+
+
+
+def assume(self, literals: Sequence[int]) ‑> None +
+
+

Extend the program with the given assumptions.

+

Parameters

+
+
literals
+
The program literals to assume (positive literals are true and +negative literals false for the next solve call).
+
+
+ +Expand source code + +
def assume(self, literals: Sequence[Literal]) -> None:
+    """
+    Extend the program with the given assumptions.
+
+    Parameters
+    ----------
+    literals
+        The program literals to assume (positive literals are true and
+        negative literals false for the next solve call).
+    """
+    self._program.assumptions.extend(literals)
+
+
+
+def begin_step(self) ‑> None +
+
+

Resets the assumptions.

+
+ +Expand source code + +
def begin_step(self) -> None:
+    """
+    Resets the assumptions.
+    """
+    self._program.assumptions.clear()
+
+
+
+def external(self, atom: int, value: TruthValue) ‑> None +
+
+

Add an external statement to the ground representation.

+

Parameters

+
+
atom
+
The external atom in form of a program literal.
+
value
+
The truth value of the external statement.
+
+
+ +Expand source code + +
def external(self, atom: Atom, value: TruthValue) -> None:
+    """
+    Add an external statement to the ground representation.
+
+    Parameters
+    ----------
+    atom
+        The external atom in form of a program literal.
+    value
+        The truth value of the external statement.
+    """
+    self._program.externals.append(External(atom, value))
+
+
+
+def heuristic(self, atom: int, type_: HeuristicType, bias: int, priority: int, condition: Sequence[int]) ‑> None +
+
+

Add heurisitic statement to the gronud representation.

+

Parameters

+
+
atom
+
The program atom heuristically modified.
+
type_
+
The type of the modification.
+
bias
+
A signed integer.
+
priority
+
An unsigned integer.
+
condition
+
List of program literals.
+
+
+ +Expand source code + +
def heuristic(
+    self,
+    atom: Atom,
+    type_: HeuristicType,
+    bias: Weight,
+    priority: Weight,
+    condition: Sequence[Literal],
+) -> None:
+    """
+    Add heurisitic statement to the gronud representation.
+
+    Parameters
+    ----------
+    atom
+        The program atom heuristically modified.
+    type_
+        The type of the modification.
+    bias
+        A signed integer.
+    priority
+        An unsigned integer.
+    condition
+        List of program literals.
+    """
+    self._program.heuristics.append(
+        Heuristic(atom, type_, bias, priority, condition)
+    )
+
+
+
+def minimize(self, priority: int, literals: Sequence[Tuple[int, int]]) ‑> None +
+
+

Add a minimize statement to the ground representation.

+

Parameters

+
+
priority
+
The priority of the directive.
+
literals
+
List of weighted literals whose sum to minimize (pairs of literal +and weight).
+
+
+ +Expand source code + +
def minimize(
+    self, priority: Weight, literals: Sequence[Tuple[Literal, Weight]]
+) -> None:
+    """
+    Add a minimize statement to the ground representation.
+
+    Parameters
+    ----------
+    priority
+        The priority of the directive.
+    literals
+        List of weighted literals whose sum to minimize (pairs of literal
+        and weight).
+    """
+    self._program.minimizes.append(Minimize(priority, literals))
+
+
+
+def output_atom(self, symbol: Symbol, atom: int) ‑> None +
+
+

Add the given atom to the list of facts or output table.

+
+ +Expand source code + +
def output_atom(self, symbol: Symbol, atom: Atom) -> None:
+    """
+    Add the given atom to the list of facts or output table.
+    """
+    if atom != 0:
+        self._program.output_atoms[atom] = symbol
+    else:
+        self._program.facts.append(Fact(symbol))
+
+
+
+def output_term(self, symbol: Symbol, condition: Sequence[int]) ‑> None +
+
+

Add a term to the output table.

+
+ +Expand source code + +
def output_term(self, symbol: Symbol, condition: Sequence[Literal]) -> None:
+    """
+    Add a term to the output table.
+    """
+    self._program.shows.append(Show(symbol, condition))
+
+
+
+def project(self, atoms: Sequence[int]) ‑> None +
+
+

Add a project statement to the ground representation.

+

Parameters

+
+
atoms
+
The program atoms to project on.
+
+
+ +Expand source code + +
def project(self, atoms: Sequence[Atom]) -> None:
+    """
+    Add a project statement to the ground representation.
+
+    Parameters
+    ----------
+    atoms
+        The program atoms to project on.
+    """
+    if self._program.projects is None:
+        self._program.projects = []
+    self._program.projects.extend(Project(atom) for atom in atoms)
+
+
+
+def rule(self, choice: bool, head: Sequence[int], body: Sequence[int]) ‑> None +
+
+

Add a rule to the ground representation.

+

Parameters

+
+
choice
+
Determines if the head is a choice or a disjunction.
+
head
+
List of program atoms forming the rule head.
+
body
+
List of program literals forming the rule body.
+
+
+ +Expand source code + +
def rule(self, choice: bool, head: Sequence[Atom], body: Sequence[Literal]) -> None:
+    """
+    Add a rule to the ground representation.
+
+    Parameters
+    ----------
+    choice
+        Determines if the head is a choice or a disjunction.
+    head
+        List of program atoms forming the rule head.
+    body
+        List of program literals forming the rule body.
+    """
+    self._program.rules.append(Rule(choice, head, body))
+
+
+
+def weight_rule(self, choice: bool, head: Sequence[int], lower_bound: int, body: Sequence[Tuple[int, int]]) ‑> None +
+
+

Add a weight rule to the ground representation.

+

Parameters

+
+
choice
+
Determines if the head is a choice or a disjunction.
+
head
+
List of program atoms forming the head of the rule.
+
lower_bound
+
The lower bound of the weight constraint in the rule body.
+
body
+
List of weighted literals (pairs of literal and weight) forming the +elements of the weight constraint.
+
+
+ +Expand source code + +
def weight_rule(
+    self,
+    choice: bool,
+    head: Sequence[Atom],
+    lower_bound: Weight,
+    body: Sequence[Tuple[Literal, Weight]],
+) -> None:
+    """
+    Add a weight rule to the ground representation.
+
+    Parameters
+    ----------
+    choice
+        Determines if the head is a choice or a disjunction.
+    head
+        List of program atoms forming the head of the rule.
+    lower_bound
+        The lower bound of the weight constraint in the rule body.
+    body
+        List of weighted literals (pairs of literal and weight) forming the
+        elements of the weight constraint.
+    """
+    self._program.weight_rules.append(WeightRule(choice, head, lower_bound, body))
+
+
+
+

Inherited members

+ +
+
+class Project +(atom: int) +
+
+

Ground representation of project statements.

+
+ +Expand source code + +
class Project(NamedTuple):
+    """
+    Ground representation of project statements.
+    """
+
+    atom: Atom
+
+

Ancestors

+
    +
  • builtins.tuple
  • +
+

Instance variables

+
+
var atom : int
+
+

Alias for field number 0

+
+
+
+
+class Remapping +(backend: Backend, output_atoms: Mapping[int, Symbol], facts: Iterable[Fact] = None) +
+
+

This class maps existing literals to fresh literals as created by the +backend.

+

Parameters

+
+
backend
+
The backend used to introduce fresh atoms.
+
output_atoms
+
The output table to initialize the mapping with.
+
facts
+
A list of facts each of which will receive a fresh program atom.
+
+
+ +Expand source code + +
class Remapping:
+    """
+    This class maps existing literals to fresh literals as created by the
+    backend.
+
+    Parameters
+    ----------
+    backend
+        The backend used to introduce fresh atoms.
+    output_atoms
+        The output table to initialize the mapping with.
+    facts
+        A list of facts each of which will receive a fresh program atom.
+    """
+
+    _backend: Backend
+    _map: MutableMapping[Atom, Atom]
+
+    def __init__(
+        self, backend: Backend, output_atoms: OutputTable, facts: Iterable[Fact] = None
+    ):
+        self._backend = backend
+        self._map = {}
+        for atom, sym in output_atoms.items():
+            assert atom not in self._map
+            self._map[atom] = self._backend.add_atom(sym)
+        if facts is not None:
+            for fact in facts:
+                backend.add_rule([backend.add_atom(fact.symbol)])
+
+    def __call__(self, atom: Atom) -> Atom:
+        """
+        Map the given program atom to the corresponding atom in the backend.
+
+        If the literal was not mapped during initialization, a new literal is
+        associated with it.
+
+        Parameters
+        ----------
+        atom
+            The atom to remap.
+
+        Returns
+        -------
+        The remapped program atom.
+        """
+        if atom not in self._map:
+            self._map[atom] = self._backend.add_atom()
+
+        return self._map[atom]
+
+

Methods

+
+
+def __call__(self, atom: int) ‑> int +
+
+

Map the given program atom to the corresponding atom in the backend.

+

If the literal was not mapped during initialization, a new literal is +associated with it.

+

Parameters

+
+
atom
+
The atom to remap.
+
+

Returns

+

The remapped program atom.

+
+ +Expand source code + +
def __call__(self, atom: Atom) -> Atom:
+    """
+    Map the given program atom to the corresponding atom in the backend.
+
+    If the literal was not mapped during initialization, a new literal is
+    associated with it.
+
+    Parameters
+    ----------
+    atom
+        The atom to remap.
+
+    Returns
+    -------
+    The remapped program atom.
+    """
+    if atom not in self._map:
+        self._map[atom] = self._backend.add_atom()
+
+    return self._map[atom]
+
+
+
+
+
+class Rule +(choice: bool, head: Sequence[int], body: Sequence[int]) +
+
+

Ground representation of disjunctive and choice rules.

+
+ +Expand source code + +
class Rule(NamedTuple):
+    """
+    Ground representation of disjunctive and choice rules.
+    """
+
+    choice: bool
+    head: Sequence[Atom]
+    body: Sequence[Literal]
+
+

Ancestors

+
    +
  • builtins.tuple
  • +
+

Instance variables

+
+
var body : Sequence[int]
+
+

Alias for field number 2

+
+
var choice : bool
+
+

Alias for field number 0

+
+
var head : Sequence[int]
+
+

Alias for field number 1

+
+
+
+
+class Show +(symbol: Symbol, condition: Sequence[int]) +
+
+

Ground representation of a show statements.

+
+ +Expand source code + +
class Show(NamedTuple):
+    """
+    Ground representation of a show statements.
+    """
+
+    symbol: Symbol
+    condition: Sequence[Literal]
+
+

Ancestors

+
    +
  • builtins.tuple
  • +
+

Instance variables

+
+
var condition : Sequence[int]
+
+

Alias for field number 1

+
+
var symbolSymbol
+
+

Alias for field number 0

+
+
+
+
+class WeightRule +(choice: bool, head: Sequence[int], lower_bound: int, body: Sequence[Tuple[int, int]]) +
+
+

Ground representation of rules with a weight constraint in the body.

+
+ +Expand source code + +
class WeightRule(NamedTuple):
+    """
+    Ground representation of rules with a weight constraint in the body.
+    """
+
+    choice: bool
+    head: Sequence[Atom]
+    lower_bound: Weight
+    body: Sequence[Tuple[Literal, Weight]]
+
+

Ancestors

+
    +
  • builtins.tuple
  • +
+

Instance variables

+
+
var body : Sequence[Tuple[int, int]]
+
+

Alias for field number 3

+
+
var choice : bool
+
+

Alias for field number 0

+
+
var head : Sequence[int]
+
+

Alias for field number 1

+
+
var lower_bound : int
+
+

Alias for field number 2

+
+
+
+
+
+
+ +
+ + + \ No newline at end of file diff --git a/clingo/python-api/5.7/clingox/reify.html b/clingo/python-api/5.7/clingox/reify.html new file mode 100644 index 0000000..69c4aec --- /dev/null +++ b/clingo/python-api/5.7/clingox/reify.html @@ -0,0 +1,1967 @@ + + + + + + +clingox.reify API documentation + + + + + + + + + + + +
+
+
+

Module clingox.reify

+
+
+

This module provides functions to reify programs.

+

This includes a Reifier implementing clingo's Observer +interface that can be registered with a Control object.

+

Additionally, the module provides a ReifiedTheory class that provides a +similar interface as clingo's theory atoms but uses the reified symbols.

+

Examples

+

The following example uses the reify_program() function to reify a program:

+
>>> from clingox.reify import reify_program
+>>> prg = 'b :- a. {a}.'
+>>> symbols = reify_program(prg)
+>>> print([str(sym) for sym in symbols])
+['tag(incremental)', 'atom_tuple(0)', 'atom_tuple(0,1)', 'literal_tuple(0)',
+'rule(choice(0),normal(0))', 'atom_tuple(1)', 'atom_tuple(1,2)',
+'literal_tuple(1)', 'literal_tuple(1,1)', 'rule(disjunction(1),normal(1))',
+'output(a,1)', 'literal_tuple(2)', 'literal_tuple(2,2)', 'output(b,2)']
+
+

The last example shows how to use the ReifiedTheory class.

+
>>> from clingox.reify import ReifiedTheory, reify_program
+>>> prg = '#theory theory { t { }; &p/0 : t, any }. &p { t }.'
+>>> thy = ReifiedTheory(reify_program(prg))
+>>> print([str(atm) for atm in thy])
+['&p { t: literal_tuple(0) }']
+>>> from clingox.theory import evaluate
+>>> evaluate(next(iter(thy)).term)
+Function('p', [], True)
+
+
+ +Expand source code + +
"""
+This module provides functions to reify programs.
+
+This includes a `Reifier` implementing clingo's `clingo.backend.Observer`
+interface that can be registered with a `clingo.control.Control` object.
+
+Additionally, the module provides a `ReifiedTheory` class that provides a
+similar interface as clingo's theory atoms but uses the reified symbols.
+
+Examples
+--------
+
+The following example uses the `reify_program` function to reify a program:
+
+```python-repl
+>>> from clingox.reify import reify_program
+>>> prg = 'b :- a. {a}.'
+>>> symbols = reify_program(prg)
+>>> print([str(sym) for sym in symbols])
+['tag(incremental)', 'atom_tuple(0)', 'atom_tuple(0,1)', 'literal_tuple(0)',
+'rule(choice(0),normal(0))', 'atom_tuple(1)', 'atom_tuple(1,2)',
+'literal_tuple(1)', 'literal_tuple(1,1)', 'rule(disjunction(1),normal(1))',
+'output(a,1)', 'literal_tuple(2)', 'literal_tuple(2,2)', 'output(b,2)']
+```
+
+The last example shows how to use the `ReifiedTheory` class.
+
+```python-repl
+>>> from clingox.reify import ReifiedTheory, reify_program
+>>> prg = '#theory theory { t { }; &p/0 : t, any }. &p { t }.'
+>>> thy = ReifiedTheory(reify_program(prg))
+>>> print([str(atm) for atm in thy])
+['&p { t: literal_tuple(0) }']
+>>> from clingox.theory import evaluate
+>>> evaluate(next(iter(thy)).term)
+Function('p', [], True)
+```
+"""
+
+from dataclasses import dataclass, field
+from typing import (
+    Callable,
+    Dict,
+    Generic,
+    Iterator,
+    List,
+    Optional,
+    Sequence,
+    Set,
+    Tuple,
+    TypeVar,
+)
+
+from clingo.backend import HeuristicType, Observer, TruthValue
+from clingo.control import Control
+from clingo.symbol import Function, Number, String, Symbol
+from clingo.theory_atoms import TheoryTermType
+
+from .theory import is_operator
+
+__all__ = [
+    "Reifier",
+    "ReifiedTheory",
+    "ReifiedTheoryAtom",
+    "ReifiedTheoryElement",
+    "ReifiedTheoryTerm",
+    "ReifiedTheory",
+    "reify_program",
+]
+
+T = TypeVar("T")  # pylint: disable=invalid-name
+U = TypeVar("U", int, Tuple[int, int])  # pylint: disable=invalid-name
+
+
+@dataclass
+class _Vertex(Generic[T]):
+    """
+    Vertex data to calculate SCCs of a graph.
+    """
+
+    name: T
+    visited: int
+    index: int = 0
+    edges: List[int] = field(default_factory=list)
+
+
+class _Graph(Generic[T]):
+    """
+    Simple class to compute strongly connected components using Tarjan's
+    algorithm.
+    """
+
+    _names: Dict[T, int]
+    _vertices: List[_Vertex]
+    _phase: bool
+
+    def __init__(self):
+        self._names = {}
+        self._vertices = []
+        self._phase = True
+
+    def _visited(self, key_u: int) -> bool:
+        return self._vertices[key_u].visited != int(not self._phase)
+
+    def _active(self, key_u: int) -> bool:
+        return self._vertices[key_u].visited != int(self._phase)
+
+    def _add_vertex(self, val_u: T) -> int:
+        n = len(self._vertices)
+        key_u = self._names.setdefault(val_u, n)
+        if n == key_u:
+            self._vertices.append(_Vertex(val_u, int(not self._phase)))
+        return key_u
+
+    def add_edge(self, val_u: T, val_v: T) -> None:
+        """
+        Add an edge to the graph.
+        """
+        key_u = self._add_vertex(val_u)
+        key_v = self._add_vertex(val_v)
+        self._vertices[key_u].edges.append(key_v)
+
+    def tarjan(self) -> List[List[T]]:
+        """
+        Returns the strictly connected components of the graph.
+        """
+        sccs: List[List[T]] = []
+        stack = []
+        trail = []
+        index = 1
+
+        def push(key_u: int):
+            nonlocal index
+            index += 1
+            vtx_u = self._vertices[key_u]
+            vtx_u.visited = index
+            vtx_u.index = 0
+            stack.append(key_u)
+            trail.append(key_u)
+
+        for key_u in range(len(self._vertices)):
+            if self._visited(key_u):
+                continue
+            index = 1
+            push(key_u)
+            while stack:
+                key_v = stack[-1]
+                vtx_v = self._vertices[key_v]
+                len_v = len(vtx_v.edges)
+                while vtx_v.index < len_v:
+                    key_w = vtx_v.edges[vtx_v.index]
+                    vtx_v.index += 1
+                    if not self._visited(key_w):
+                        push(key_w)
+                        break
+                else:
+                    stack.pop()
+                    root = True
+                    for key_w in vtx_v.edges:
+                        vtx_w = self._vertices[key_w]
+                        if self._active(key_w) and vtx_w.visited < vtx_v.visited:
+                            root = False
+                            vtx_v.visited = vtx_w.visited
+                    if root:
+                        key_last = None
+                        sccs.append([])
+                        while key_last != key_v:
+                            key_last = trail[-1]
+                            vtx_last = self._vertices[key_last]
+                            sccs[-1].append(vtx_last.name)
+                            vtx_last.visited = int(self._phase)
+                            trail.pop()
+                        if len(sccs[-1]) == 1:
+                            sccs.pop()
+
+        self._phase = not self._phase
+        return sccs
+
+
+@dataclass
+class _StepData:
+    atom_tuples: Dict[Sequence[int], int] = field(default_factory=dict)
+    lit_tuples: Dict[Sequence[int], int] = field(default_factory=dict)
+    wlit_tuples: Dict[Sequence[Tuple[int, int]], int] = field(default_factory=dict)
+    theory_tuples: Dict[Sequence[int], int] = field(default_factory=dict)
+    theory_element_tuples: Dict[Sequence[int], int] = field(default_factory=dict)
+    graph: _Graph = field(default_factory=_Graph)
+
+
+def _theory(i: Symbol, pos: int, lit: int) -> Sequence[Symbol]:
+    return [i, Number(pos), Number(lit)]
+
+
+def _lit(i: Symbol, pos: int, lit: int) -> Sequence[Symbol]:
+    # pylint: disable=unused-argument
+    return [i, Number(lit)]
+
+
+def _wlit(i: Symbol, pos: int, wlit: Tuple[int, int]) -> Sequence[Symbol]:
+    # pylint: disable=unused-argument
+    return [i, Number(wlit[0]), Number(wlit[1])]
+
+
+class Reifier(Observer):
+    """
+    An observer that will gather the symbols of the reification, in the same way as `clingo --output=reify`.
+
+    Parameters
+    ----------
+    cb
+        A callback function that will be called with each symbol of the reification
+    calculate_sccs
+        Flag to calculate the SCCs
+    reify_steps
+        Flag to add a number as the last argument of all reification symbols for the corresponding step
+
+    """
+
+    # pylint:disable=too-many-public-methods
+    _step: int
+    # Bug in mypy???
+    # _cb: Callable[[Symbol], None]
+    _calculate_sccs: bool
+    _reify_steps: bool
+    _step_data: _StepData
+
+    def __init__(
+        self,
+        cb: Callable[[Symbol], None],
+        calculate_sccs: bool = False,
+        reify_steps: bool = False,
+    ):
+        self._step = 0
+        self._cb = cb
+        self._calculate_sccs = calculate_sccs
+        self._reify_steps = reify_steps
+        self._step_data = _StepData()
+
+    def calculate_sccs(self) -> None:
+        """
+        Trigger computation of SCCs.
+
+        SCCs can only be computed if the Reifier has been initialized with
+        `calculate_sccs=True`, This function is called automatically if
+        `reify_steps=True` has been set when initializing the Reifier.
+        """
+        for idx, scc in enumerate(self._step_data.graph.tarjan()):
+            for atm in scc:
+                self._output("scc", [Number(idx), Number(atm)])
+
+    def _add_edges(self, head: Sequence[int], body: Sequence[int]):
+        if self._calculate_sccs:
+            for u in head:
+                for v in body:
+                    if v > 0:
+                        self._step_data.graph.add_edge(u, v)
+
+    def _output(self, name: str, args: Sequence[Symbol]):
+        if self._reify_steps:
+            args = list(args) + [Number(self._step)]
+        self._cb(Function(name, args))
+
+    def _tuple(
+        self,
+        name: str,
+        snmap: Dict[Sequence[U], int],
+        elems: Sequence[U],
+        afun: Callable[[Symbol, int, U], Sequence[Symbol]],
+        ordered: bool = False,
+    ) -> Symbol:
+        pruned: Sequence[U]
+        if ordered:
+            pruned = elems
+            ident = tuple(elems)
+        else:
+            seen: Set[U] = set()
+            pruned = []
+            for elem in elems:
+                if elem not in seen:
+                    seen.add(elem)
+                    pruned.append(elem)
+            ident = tuple(sorted(pruned))
+
+        n = len(snmap)
+        i = Number(snmap.setdefault(ident, n))
+        if n == i.number:
+            self._output(name, [i])
+            for idx, atm in enumerate(pruned):
+                self._output(name, afun(i, idx, atm))
+        return i
+
+    def _atom_tuple(self, atoms: Sequence[int]):
+        return self._tuple("atom_tuple", self._step_data.atom_tuples, atoms, _lit)
+
+    def _lit_tuple(self, lits: Sequence[int]):
+        return self._tuple("literal_tuple", self._step_data.lit_tuples, lits, _lit)
+
+    def _wlit_tuple(self, wlits: Sequence[Tuple[int, int]]):
+        return self._tuple(
+            "weighted_literal_tuple", self._step_data.wlit_tuples, wlits, _wlit
+        )
+
+    def init_program(self, incremental: bool) -> None:
+        if incremental:
+            self._cb(Function("tag", [Function("incremental")]))
+
+    def begin_step(self) -> None:
+        pass
+
+    def rule(self, choice: bool, head: Sequence[int], body: Sequence[int]) -> None:
+        hn = "choice" if choice else "disjunction"
+        hd = Function(hn, [self._atom_tuple(head)])
+        bd = Function("normal", [self._lit_tuple(body)])
+        self._output("rule", [hd, bd])
+        self._add_edges(head, body)
+
+    def weight_rule(
+        self,
+        choice: bool,
+        head: Sequence[int],
+        lower_bound: int,
+        body: Sequence[Tuple[int, int]],
+    ) -> None:
+        hn = "choice" if choice else "disjunction"
+        hd = Function(hn, [self._atom_tuple(head)])
+        bd = Function("sum", [self._wlit_tuple(body), Number(lower_bound)])
+        self._output("rule", [hd, bd])
+        self._add_edges(head, [lit for lit, w in body])
+
+    def minimize(self, priority: int, literals: Sequence[Tuple[int, int]]) -> None:
+        self._output("minimize", [Number(priority), self._wlit_tuple(literals)])
+
+    def project(self, atoms: Sequence[int]) -> None:
+        for atom in atoms:
+            self._output("project", [Number(atom)])
+
+    def output_atom(self, symbol: Symbol, atom: int) -> None:
+        self._output("output", [symbol, self._lit_tuple([] if atom == 0 else [atom])])
+
+    def output_term(self, symbol: Symbol, condition: Sequence[int]) -> None:
+        self._output("output", [symbol, self._lit_tuple(condition)])
+
+    def external(self, atom: int, value: TruthValue) -> None:
+        value_name = str(value).replace("TruthValue.", "").lower().rstrip("_")
+        self._output("external", [Number(atom), Function(value_name)])
+
+    def assume(self, literals: Sequence[int]) -> None:
+        for lit in literals:
+            self._output("assume", [Number(lit)])
+
+    def heuristic(
+        self,
+        atom: int,
+        type_: HeuristicType,
+        bias: int,
+        priority: int,
+        condition: Sequence[int],
+    ) -> None:
+        type_name = str(type_).replace("HeuristicType.", "").lower().rstrip("_")
+        condition_lit = self._lit_tuple(condition)
+        self._output(
+            "heuristic",
+            [
+                Number(atom),
+                Function(type_name),
+                Number(bias),
+                Number(priority),
+                condition_lit,
+            ],
+        )
+
+    def acyc_edge(self, node_u: int, node_v: int, condition: Sequence[int]) -> None:
+        self._output(
+            "edge", [Number(node_u), Number(node_v), self._lit_tuple(condition)]
+        )
+
+    def theory_term_number(self, term_id: int, number: int) -> None:
+        self._output("theory_number", [Number(term_id), Number(number)])
+
+    def theory_term_string(self, term_id: int, name: str) -> None:
+        self._output("theory_string", [Number(term_id), String(name)])
+
+    def theory_term_compound(
+        self, term_id: int, name_id_or_type: int, arguments: Sequence[int]
+    ) -> None:
+        names = {-1: "tuple", -2: "set", -3: "list"}
+        if name_id_or_type in names:
+            name = "theory_sequence"
+            value = Function(names[name_id_or_type])
+        else:
+            name = "theory_function"
+            value = Number(name_id_or_type)
+        tuple_id = self._tuple(
+            "theory_tuple", self._step_data.theory_tuples, arguments, _theory, True
+        )
+        self._output(name, [Number(term_id), value, tuple_id])
+
+    def theory_element(
+        self, element_id: int, terms: Sequence[int], condition: Sequence[int]
+    ) -> None:
+        tuple_id = self._tuple(
+            "theory_tuple", self._step_data.theory_tuples, terms, _theory, True
+        )
+        condition_id = self._tuple(
+            "literal_tuple", self._step_data.lit_tuples, condition, _lit
+        )
+        self._output("theory_element", [Number(element_id), tuple_id, condition_id])
+
+    def theory_atom(
+        self, atom_id_or_zero: int, term_id: int, elements: Sequence[int]
+    ) -> None:
+        tuple_e_id = self._tuple(
+            "theory_element_tuple",
+            self._step_data.theory_element_tuples,
+            elements,
+            _lit,
+        )
+        self._output(
+            "theory_atom", [Number(atom_id_or_zero), Number(term_id), tuple_e_id]
+        )
+
+    def theory_atom_with_guard(
+        self,
+        atom_id_or_zero: int,
+        term_id: int,
+        elements: Sequence[int],
+        operator_id: int,
+        right_hand_side_id: int,
+    ) -> None:
+        tuple_id = self._tuple(
+            "theory_element_tuple",
+            self._step_data.theory_element_tuples,
+            elements,
+            _lit,
+        )
+        self._output(
+            "theory_atom",
+            [
+                Number(atom_id_or_zero),
+                Number(term_id),
+                tuple_id,
+                Number(operator_id),
+                Number(right_hand_side_id),
+            ],
+        )
+
+    def end_step(self) -> None:
+        if self._reify_steps:
+            self.calculate_sccs()
+            self._step += 1
+            self._step_data = _StepData()
+
+
+def _set(
+    matches: Sequence[Tuple[str, int]],
+    lst: List[Symbol],
+    sym,
+    append: bool = False,
+    default: Symbol = Number(0),
+) -> bool:
+    for match in matches:
+        if not sym.match(*match):
+            continue
+        idx = len(lst) if append else sym.arguments[0].number
+        while len(lst) <= idx:
+            lst.append(default)
+        lst[idx] = sym
+        return True
+    return False
+
+
+def _ensure(name: str, lst: List[List[int]], sym: Symbol, ordered=False) -> bool:
+    empty = sym.match(name, 1)
+    if empty or sym.match(name, 3 if ordered else 2):
+        idx = sym.arguments[0].number
+        while len(lst) <= idx:
+            lst.append([])
+        if not empty:
+            if ordered:
+                tup = lst[idx]
+                jdx = sym.arguments[1].number
+                while len(tup) <= jdx:
+                    tup.append(0)
+                tup[jdx] = sym.arguments[2].number
+            else:
+                lst[idx].append(sym.arguments[1].number)
+        return True
+    return False
+
+
+class ReifiedTheory:
+    """
+    Class indexing the symbols related to a theory.
+
+    The `ReifiedTheoryTerm`, `ReifiedTheoryElement`, and `ReifiedTheoryElement`
+    classes provide views on this data that behave as the corresponding classes
+    in clingo's `clingo.theory_atoms` module.
+    """
+
+    terms: List[Symbol]
+    elements: List[Symbol]
+    atoms: List[Symbol]
+    term_tuples: List[List[int]]
+    element_tuples: List[List[int]]
+
+    def __init__(self, symbols: Sequence[Symbol]):
+        self.terms = []
+        self.elements = []
+        self.atoms = []
+        self.term_tuples = []
+        self.element_tuples = []
+
+        for sym in symbols:
+            _ = (
+                _set((("theory_atom", 3), ("theory_atom", 5)), self.atoms, sym, True)
+                or _set((("theory_element", 3),), self.elements, sym)
+                or _set(
+                    (
+                        ("theory_sequence", 3),
+                        ("theory_string", 2),
+                        ("theory_number", 2),
+                        ("theory_function", 3),
+                    ),
+                    self.terms,
+                    sym,
+                )
+                or _ensure("theory_tuple", self.term_tuples, sym, True)
+                or _ensure("theory_element_tuple", self.element_tuples, sym)
+            )
+
+    def __iter__(self) -> Iterator["ReifiedTheoryAtom"]:
+        for idx in range(len(self.atoms)):
+            yield ReifiedTheoryAtom(idx, self)
+
+
+class ReifiedTheoryTerm:
+    """
+    Class to represent theory terms.
+
+    ReifiedTheory terms have a readable string representation, implement Python's rich
+    comparison operators, and can be used as dictionary keys.
+    """
+
+    _idx: int
+    _theory: ReifiedTheory
+
+    def __init__(self, idx: int, theory: ReifiedTheory):
+        self._idx = idx
+        self._theory = theory
+        assert self.index < len(theory.terms)
+
+    @property
+    def index(self) -> int:
+        """
+        The index of the corresponding reified fact.
+        """
+        return self._idx
+
+    @property
+    def _args(self) -> Sequence[Symbol]:
+        return self._theory.terms[self._idx].arguments
+
+    @property
+    def arguments(self) -> List["ReifiedTheoryTerm"]:
+        """
+        The arguments of the term (for functions, tuples, list, and sets).
+        """
+        assert self.type in (
+            TheoryTermType.List,
+            TheoryTermType.Set,
+            TheoryTermType.Tuple,
+            TheoryTermType.Function,
+        )
+        term_ids = self._theory.term_tuples[self._args[2].number]
+        return [ReifiedTheoryTerm(term_id, self._theory) for term_id in term_ids]
+
+    @property
+    def name(self) -> str:
+        """
+        The name of the term (for symbols and functions).
+        """
+        assert self.type in (TheoryTermType.Symbol, TheoryTermType.Function)
+        if self.type == TheoryTermType.Function:
+            return self._theory.terms[self._args[1].number].arguments[1].string
+        return self._args[1].string
+
+    @property
+    def number(self) -> int:
+        """
+        The numeric representation of the term (for numbers).
+        """
+        assert self.type == TheoryTermType.Number
+        return self._args[1].number
+
+    @property
+    def type(self) -> TheoryTermType:
+        """
+        The type of the theory term.
+        """
+        name = self._theory.terms[self._idx].name
+        if name == "theory_number":
+            return TheoryTermType.Number
+        if name == "theory_string":
+            return TheoryTermType.Symbol
+        if name == "theory_function":
+            return TheoryTermType.Function
+        assert name == "theory_sequence"
+        type_ = self._args[1].name
+        if type_ == "tuple":
+            return TheoryTermType.Tuple
+        if type_ == "set":
+            return TheoryTermType.Set
+        assert type_ == "list"
+        return TheoryTermType.List
+
+    def __hash__(self):
+        return self._idx
+
+    def __eq__(self, other):
+        return self._idx == other._idx
+
+    def __lt__(self, other):
+        return self._idx < other._idx
+
+    def __str__(self):
+        type_ = self.type
+
+        if type_ == TheoryTermType.Number:
+            return f"{self.number}"
+
+        if type_ == TheoryTermType.Symbol:
+            return f"{self.name}"
+
+        if type_ == TheoryTermType.Function:
+            args = self.arguments
+            name = self.name
+            if len(args) == 1 and is_operator(name):
+                return f"{name}({args[0]})"
+            if len(args) == 2 and is_operator(name):
+                return f"({args[0]}){name}({args[1]})"
+            return f'{name}({",".join(str(arg) for arg in args)})'
+
+        if type_ == TheoryTermType.Tuple:
+            lhs, rhs = "(", ")"
+        elif type_ == TheoryTermType.List:
+            lhs, rhs = "[", "]"
+        else:
+            lhs, rhs = "{", "}"
+        return f'{lhs}{",".join(str(arg) for arg in self.arguments)}{rhs}'
+
+
+class ReifiedTheoryElement:
+    """
+    Class to represent theory elements.
+
+    ReifiedTheory elements have a readable string representation, implement Python's
+    rich comparison operators, and can be used as dictionary keys.
+    """
+
+    _idx: int
+    _theory: ReifiedTheory
+
+    def __init__(self, idx: int, theory: ReifiedTheory):
+        self._idx = idx
+        self._theory = theory
+        assert self.index < len(theory.elements)
+
+    @property
+    def index(self) -> int:
+        """
+        The index of the corresponding reified fact.
+        """
+        return self._idx
+
+    @property
+    def _args(self) -> Sequence[Symbol]:
+        return self._theory.elements[self._idx].arguments
+
+    @property
+    def condition_id(self) -> int:
+        """
+        The id of the literal tuple of the condition.
+        """
+        return self._args[2].number
+
+    @property
+    def terms(self) -> List[ReifiedTheoryTerm]:
+        """
+        The tuple of the element.
+        """
+        term_ids = self._theory.term_tuples[self._args[1].number]
+        return [ReifiedTheoryTerm(term_id, self._theory) for term_id in term_ids]
+
+    def __hash__(self):
+        return self._idx
+
+    def __eq__(self, other):
+        return self._idx == other._idx
+
+    def __lt__(self, other):
+        return self._idx < other._idx
+
+    def __str__(self):
+        return f'{",".join(str(term) for term in self.terms)}: literal_tuple({self.condition_id})'
+
+
+class ReifiedTheoryAtom:
+    """
+    Class to represent theory atoms.
+
+    Theory atoms have a readable string representation, implement Python's rich
+    comparison operators, and can be used as dictionary keys.
+    """
+
+    _idx: int
+    _theory: ReifiedTheory
+
+    def __init__(self, idx: int, theory: ReifiedTheory):
+        self._idx = idx
+        self._theory = theory
+        assert self.index < len(theory.atoms)
+
+    @property
+    def index(self) -> int:
+        """
+        The index of the corresponding reified fact.
+        """
+        return self._idx
+
+    @property
+    def _args(self) -> Sequence[Symbol]:
+        return self._theory.atoms[self._idx].arguments
+
+    @property
+    def elements(self) -> List[ReifiedTheoryElement]:
+        """
+        The elements of the atom.
+        """
+        tuple_id = self._args[2].number
+        return [
+            ReifiedTheoryElement(elem_id, self._theory)
+            for elem_id in self._theory.element_tuples[tuple_id]
+        ]
+
+    @property
+    def guard(self) -> Optional[Tuple[str, ReifiedTheoryTerm]]:
+        """
+        The guard of the atom or None if the atom has no guard.
+        """
+        args = self._args
+        if len(args) <= 3:
+            return None
+
+        op = self._theory.terms[args[3].number].arguments[1].string
+        return (op, ReifiedTheoryTerm(args[4].number, self._theory))
+
+    @property
+    def literal(self) -> int:
+        """
+        The reified literal associated with the atom.
+        """
+        return self._args[0].number
+
+    @property
+    def term(self) -> ReifiedTheoryTerm:
+        """
+        The term of the atom.
+        """
+        return ReifiedTheoryTerm(self._args[1].number, self._theory)
+
+    def __hash__(self):
+        return self._idx
+
+    def __eq__(self, other):
+        return self._idx == other._idx
+
+    def __lt__(self, other):
+        return self._idx < other._idx
+
+    def __str__(self):
+        name = f"&{self.term}"
+
+        elems = self.elements
+        if elems:
+            estr = f' {{ {"; ".join(str(elem) for elem in elems)} }}'
+        else:
+            estr = ""
+
+        guard = self.guard
+        if guard:
+            gstr = f" {guard[0]} {guard[1]}"
+        else:
+            gstr = ""
+
+        return f"{name}{estr}{gstr}"
+
+
+def reify_program(
+    prg: str, calculate_sccs: bool = False, reify_steps: bool = False
+) -> List[Symbol]:
+    """
+    Reify the given program and return the reified symbols.
+
+    Parameters
+    ----------
+    prg
+        The program to reify in form of a string.
+    calculate_sccs
+        Whether to calculate SCCs of the reified program.
+    reify_steps
+        Whether to add a step number to the reified facts.
+
+    Returns
+    -------
+    A list of symbols containing the reified facts.
+    """
+    ret: List[Symbol] = []
+    ctl = Control()
+    reifier = Reifier(ret.append, calculate_sccs, reify_steps)
+    ctl.register_observer(reifier)
+    ctl.add("base", [], prg)
+    ctl.ground([("base", [])])
+    if calculate_sccs and not reify_steps:
+        reifier.calculate_sccs()
+
+    return ret
+
+
+
+
+
+
+
+

Functions

+
+
+def reify_program(prg: str, calculate_sccs: bool = False, reify_steps: bool = False) ‑> List[Symbol] +
+
+

Reify the given program and return the reified symbols.

+

Parameters

+
+
prg
+
The program to reify in form of a string.
+
calculate_sccs
+
Whether to calculate SCCs of the reified program.
+
reify_steps
+
Whether to add a step number to the reified facts.
+
+

Returns

+

A list of symbols containing the reified facts.

+
+ +Expand source code + +
def reify_program(
+    prg: str, calculate_sccs: bool = False, reify_steps: bool = False
+) -> List[Symbol]:
+    """
+    Reify the given program and return the reified symbols.
+
+    Parameters
+    ----------
+    prg
+        The program to reify in form of a string.
+    calculate_sccs
+        Whether to calculate SCCs of the reified program.
+    reify_steps
+        Whether to add a step number to the reified facts.
+
+    Returns
+    -------
+    A list of symbols containing the reified facts.
+    """
+    ret: List[Symbol] = []
+    ctl = Control()
+    reifier = Reifier(ret.append, calculate_sccs, reify_steps)
+    ctl.register_observer(reifier)
+    ctl.add("base", [], prg)
+    ctl.ground([("base", [])])
+    if calculate_sccs and not reify_steps:
+        reifier.calculate_sccs()
+
+    return ret
+
+
+
+
+
+

Classes

+
+
+class ReifiedTheory +(symbols: Sequence[Symbol]) +
+
+

Class indexing the symbols related to a theory.

+

The ReifiedTheoryTerm, ReifiedTheoryElement, and ReifiedTheoryElement +classes provide views on this data that behave as the corresponding classes +in clingo's clingo.theory_atoms module.

+
+ +Expand source code + +
class ReifiedTheory:
+    """
+    Class indexing the symbols related to a theory.
+
+    The `ReifiedTheoryTerm`, `ReifiedTheoryElement`, and `ReifiedTheoryElement`
+    classes provide views on this data that behave as the corresponding classes
+    in clingo's `clingo.theory_atoms` module.
+    """
+
+    terms: List[Symbol]
+    elements: List[Symbol]
+    atoms: List[Symbol]
+    term_tuples: List[List[int]]
+    element_tuples: List[List[int]]
+
+    def __init__(self, symbols: Sequence[Symbol]):
+        self.terms = []
+        self.elements = []
+        self.atoms = []
+        self.term_tuples = []
+        self.element_tuples = []
+
+        for sym in symbols:
+            _ = (
+                _set((("theory_atom", 3), ("theory_atom", 5)), self.atoms, sym, True)
+                or _set((("theory_element", 3),), self.elements, sym)
+                or _set(
+                    (
+                        ("theory_sequence", 3),
+                        ("theory_string", 2),
+                        ("theory_number", 2),
+                        ("theory_function", 3),
+                    ),
+                    self.terms,
+                    sym,
+                )
+                or _ensure("theory_tuple", self.term_tuples, sym, True)
+                or _ensure("theory_element_tuple", self.element_tuples, sym)
+            )
+
+    def __iter__(self) -> Iterator["ReifiedTheoryAtom"]:
+        for idx in range(len(self.atoms)):
+            yield ReifiedTheoryAtom(idx, self)
+
+

Class variables

+
+
var atoms : List[Symbol]
+
+
+
+
var element_tuples : List[List[int]]
+
+
+
+
var elements : List[Symbol]
+
+
+
+
var term_tuples : List[List[int]]
+
+
+
+
var terms : List[Symbol]
+
+
+
+
+
+
+class ReifiedTheoryAtom +(idx: int, theory: ReifiedTheory) +
+
+

Class to represent theory atoms.

+

Theory atoms have a readable string representation, implement Python's rich +comparison operators, and can be used as dictionary keys.

+
+ +Expand source code + +
class ReifiedTheoryAtom:
+    """
+    Class to represent theory atoms.
+
+    Theory atoms have a readable string representation, implement Python's rich
+    comparison operators, and can be used as dictionary keys.
+    """
+
+    _idx: int
+    _theory: ReifiedTheory
+
+    def __init__(self, idx: int, theory: ReifiedTheory):
+        self._idx = idx
+        self._theory = theory
+        assert self.index < len(theory.atoms)
+
+    @property
+    def index(self) -> int:
+        """
+        The index of the corresponding reified fact.
+        """
+        return self._idx
+
+    @property
+    def _args(self) -> Sequence[Symbol]:
+        return self._theory.atoms[self._idx].arguments
+
+    @property
+    def elements(self) -> List[ReifiedTheoryElement]:
+        """
+        The elements of the atom.
+        """
+        tuple_id = self._args[2].number
+        return [
+            ReifiedTheoryElement(elem_id, self._theory)
+            for elem_id in self._theory.element_tuples[tuple_id]
+        ]
+
+    @property
+    def guard(self) -> Optional[Tuple[str, ReifiedTheoryTerm]]:
+        """
+        The guard of the atom or None if the atom has no guard.
+        """
+        args = self._args
+        if len(args) <= 3:
+            return None
+
+        op = self._theory.terms[args[3].number].arguments[1].string
+        return (op, ReifiedTheoryTerm(args[4].number, self._theory))
+
+    @property
+    def literal(self) -> int:
+        """
+        The reified literal associated with the atom.
+        """
+        return self._args[0].number
+
+    @property
+    def term(self) -> ReifiedTheoryTerm:
+        """
+        The term of the atom.
+        """
+        return ReifiedTheoryTerm(self._args[1].number, self._theory)
+
+    def __hash__(self):
+        return self._idx
+
+    def __eq__(self, other):
+        return self._idx == other._idx
+
+    def __lt__(self, other):
+        return self._idx < other._idx
+
+    def __str__(self):
+        name = f"&{self.term}"
+
+        elems = self.elements
+        if elems:
+            estr = f' {{ {"; ".join(str(elem) for elem in elems)} }}'
+        else:
+            estr = ""
+
+        guard = self.guard
+        if guard:
+            gstr = f" {guard[0]} {guard[1]}"
+        else:
+            gstr = ""
+
+        return f"{name}{estr}{gstr}"
+
+

Instance variables

+
+
var elements : List[ReifiedTheoryElement]
+
+

The elements of the atom.

+
+ +Expand source code + +
@property
+def elements(self) -> List[ReifiedTheoryElement]:
+    """
+    The elements of the atom.
+    """
+    tuple_id = self._args[2].number
+    return [
+        ReifiedTheoryElement(elem_id, self._theory)
+        for elem_id in self._theory.element_tuples[tuple_id]
+    ]
+
+
+
var guard : Optional[Tuple[str, ReifiedTheoryTerm]]
+
+

The guard of the atom or None if the atom has no guard.

+
+ +Expand source code + +
@property
+def guard(self) -> Optional[Tuple[str, ReifiedTheoryTerm]]:
+    """
+    The guard of the atom or None if the atom has no guard.
+    """
+    args = self._args
+    if len(args) <= 3:
+        return None
+
+    op = self._theory.terms[args[3].number].arguments[1].string
+    return (op, ReifiedTheoryTerm(args[4].number, self._theory))
+
+
+
var index : int
+
+

The index of the corresponding reified fact.

+
+ +Expand source code + +
@property
+def index(self) -> int:
+    """
+    The index of the corresponding reified fact.
+    """
+    return self._idx
+
+
+
var literal : int
+
+

The reified literal associated with the atom.

+
+ +Expand source code + +
@property
+def literal(self) -> int:
+    """
+    The reified literal associated with the atom.
+    """
+    return self._args[0].number
+
+
+
var termReifiedTheoryTerm
+
+

The term of the atom.

+
+ +Expand source code + +
@property
+def term(self) -> ReifiedTheoryTerm:
+    """
+    The term of the atom.
+    """
+    return ReifiedTheoryTerm(self._args[1].number, self._theory)
+
+
+
+
+
+class ReifiedTheoryElement +(idx: int, theory: ReifiedTheory) +
+
+

Class to represent theory elements.

+

ReifiedTheory elements have a readable string representation, implement Python's +rich comparison operators, and can be used as dictionary keys.

+
+ +Expand source code + +
class ReifiedTheoryElement:
+    """
+    Class to represent theory elements.
+
+    ReifiedTheory elements have a readable string representation, implement Python's
+    rich comparison operators, and can be used as dictionary keys.
+    """
+
+    _idx: int
+    _theory: ReifiedTheory
+
+    def __init__(self, idx: int, theory: ReifiedTheory):
+        self._idx = idx
+        self._theory = theory
+        assert self.index < len(theory.elements)
+
+    @property
+    def index(self) -> int:
+        """
+        The index of the corresponding reified fact.
+        """
+        return self._idx
+
+    @property
+    def _args(self) -> Sequence[Symbol]:
+        return self._theory.elements[self._idx].arguments
+
+    @property
+    def condition_id(self) -> int:
+        """
+        The id of the literal tuple of the condition.
+        """
+        return self._args[2].number
+
+    @property
+    def terms(self) -> List[ReifiedTheoryTerm]:
+        """
+        The tuple of the element.
+        """
+        term_ids = self._theory.term_tuples[self._args[1].number]
+        return [ReifiedTheoryTerm(term_id, self._theory) for term_id in term_ids]
+
+    def __hash__(self):
+        return self._idx
+
+    def __eq__(self, other):
+        return self._idx == other._idx
+
+    def __lt__(self, other):
+        return self._idx < other._idx
+
+    def __str__(self):
+        return f'{",".join(str(term) for term in self.terms)}: literal_tuple({self.condition_id})'
+
+

Instance variables

+
+
var condition_id : int
+
+

The id of the literal tuple of the condition.

+
+ +Expand source code + +
@property
+def condition_id(self) -> int:
+    """
+    The id of the literal tuple of the condition.
+    """
+    return self._args[2].number
+
+
+
var index : int
+
+

The index of the corresponding reified fact.

+
+ +Expand source code + +
@property
+def index(self) -> int:
+    """
+    The index of the corresponding reified fact.
+    """
+    return self._idx
+
+
+
var terms : List[ReifiedTheoryTerm]
+
+

The tuple of the element.

+
+ +Expand source code + +
@property
+def terms(self) -> List[ReifiedTheoryTerm]:
+    """
+    The tuple of the element.
+    """
+    term_ids = self._theory.term_tuples[self._args[1].number]
+    return [ReifiedTheoryTerm(term_id, self._theory) for term_id in term_ids]
+
+
+
+
+
+class ReifiedTheoryTerm +(idx: int, theory: ReifiedTheory) +
+
+

Class to represent theory terms.

+

ReifiedTheory terms have a readable string representation, implement Python's rich +comparison operators, and can be used as dictionary keys.

+
+ +Expand source code + +
class ReifiedTheoryTerm:
+    """
+    Class to represent theory terms.
+
+    ReifiedTheory terms have a readable string representation, implement Python's rich
+    comparison operators, and can be used as dictionary keys.
+    """
+
+    _idx: int
+    _theory: ReifiedTheory
+
+    def __init__(self, idx: int, theory: ReifiedTheory):
+        self._idx = idx
+        self._theory = theory
+        assert self.index < len(theory.terms)
+
+    @property
+    def index(self) -> int:
+        """
+        The index of the corresponding reified fact.
+        """
+        return self._idx
+
+    @property
+    def _args(self) -> Sequence[Symbol]:
+        return self._theory.terms[self._idx].arguments
+
+    @property
+    def arguments(self) -> List["ReifiedTheoryTerm"]:
+        """
+        The arguments of the term (for functions, tuples, list, and sets).
+        """
+        assert self.type in (
+            TheoryTermType.List,
+            TheoryTermType.Set,
+            TheoryTermType.Tuple,
+            TheoryTermType.Function,
+        )
+        term_ids = self._theory.term_tuples[self._args[2].number]
+        return [ReifiedTheoryTerm(term_id, self._theory) for term_id in term_ids]
+
+    @property
+    def name(self) -> str:
+        """
+        The name of the term (for symbols and functions).
+        """
+        assert self.type in (TheoryTermType.Symbol, TheoryTermType.Function)
+        if self.type == TheoryTermType.Function:
+            return self._theory.terms[self._args[1].number].arguments[1].string
+        return self._args[1].string
+
+    @property
+    def number(self) -> int:
+        """
+        The numeric representation of the term (for numbers).
+        """
+        assert self.type == TheoryTermType.Number
+        return self._args[1].number
+
+    @property
+    def type(self) -> TheoryTermType:
+        """
+        The type of the theory term.
+        """
+        name = self._theory.terms[self._idx].name
+        if name == "theory_number":
+            return TheoryTermType.Number
+        if name == "theory_string":
+            return TheoryTermType.Symbol
+        if name == "theory_function":
+            return TheoryTermType.Function
+        assert name == "theory_sequence"
+        type_ = self._args[1].name
+        if type_ == "tuple":
+            return TheoryTermType.Tuple
+        if type_ == "set":
+            return TheoryTermType.Set
+        assert type_ == "list"
+        return TheoryTermType.List
+
+    def __hash__(self):
+        return self._idx
+
+    def __eq__(self, other):
+        return self._idx == other._idx
+
+    def __lt__(self, other):
+        return self._idx < other._idx
+
+    def __str__(self):
+        type_ = self.type
+
+        if type_ == TheoryTermType.Number:
+            return f"{self.number}"
+
+        if type_ == TheoryTermType.Symbol:
+            return f"{self.name}"
+
+        if type_ == TheoryTermType.Function:
+            args = self.arguments
+            name = self.name
+            if len(args) == 1 and is_operator(name):
+                return f"{name}({args[0]})"
+            if len(args) == 2 and is_operator(name):
+                return f"({args[0]}){name}({args[1]})"
+            return f'{name}({",".join(str(arg) for arg in args)})'
+
+        if type_ == TheoryTermType.Tuple:
+            lhs, rhs = "(", ")"
+        elif type_ == TheoryTermType.List:
+            lhs, rhs = "[", "]"
+        else:
+            lhs, rhs = "{", "}"
+        return f'{lhs}{",".join(str(arg) for arg in self.arguments)}{rhs}'
+
+

Instance variables

+
+
var arguments : List[ReifiedTheoryTerm]
+
+

The arguments of the term (for functions, tuples, list, and sets).

+
+ +Expand source code + +
@property
+def arguments(self) -> List["ReifiedTheoryTerm"]:
+    """
+    The arguments of the term (for functions, tuples, list, and sets).
+    """
+    assert self.type in (
+        TheoryTermType.List,
+        TheoryTermType.Set,
+        TheoryTermType.Tuple,
+        TheoryTermType.Function,
+    )
+    term_ids = self._theory.term_tuples[self._args[2].number]
+    return [ReifiedTheoryTerm(term_id, self._theory) for term_id in term_ids]
+
+
+
var index : int
+
+

The index of the corresponding reified fact.

+
+ +Expand source code + +
@property
+def index(self) -> int:
+    """
+    The index of the corresponding reified fact.
+    """
+    return self._idx
+
+
+
var name : str
+
+

The name of the term (for symbols and functions).

+
+ +Expand source code + +
@property
+def name(self) -> str:
+    """
+    The name of the term (for symbols and functions).
+    """
+    assert self.type in (TheoryTermType.Symbol, TheoryTermType.Function)
+    if self.type == TheoryTermType.Function:
+        return self._theory.terms[self._args[1].number].arguments[1].string
+    return self._args[1].string
+
+
+
var number : int
+
+

The numeric representation of the term (for numbers).

+
+ +Expand source code + +
@property
+def number(self) -> int:
+    """
+    The numeric representation of the term (for numbers).
+    """
+    assert self.type == TheoryTermType.Number
+    return self._args[1].number
+
+
+
var typeTheoryTermType
+
+

The type of the theory term.

+
+ +Expand source code + +
@property
+def type(self) -> TheoryTermType:
+    """
+    The type of the theory term.
+    """
+    name = self._theory.terms[self._idx].name
+    if name == "theory_number":
+        return TheoryTermType.Number
+    if name == "theory_string":
+        return TheoryTermType.Symbol
+    if name == "theory_function":
+        return TheoryTermType.Function
+    assert name == "theory_sequence"
+    type_ = self._args[1].name
+    if type_ == "tuple":
+        return TheoryTermType.Tuple
+    if type_ == "set":
+        return TheoryTermType.Set
+    assert type_ == "list"
+    return TheoryTermType.List
+
+
+
+
+
+class Reifier +(cb: Callable[[Symbol], None], calculate_sccs: bool = False, reify_steps: bool = False) +
+
+

An observer that will gather the symbols of the reification, in the same way as clingo --output=reify.

+

Parameters

+
+
cb
+
A callback function that will be called with each symbol of the reification
+
calculate_sccs
+
Flag to calculate the SCCs
+
reify_steps
+
Flag to add a number as the last argument of all reification symbols for the corresponding step
+
+
+ +Expand source code + +
class Reifier(Observer):
+    """
+    An observer that will gather the symbols of the reification, in the same way as `clingo --output=reify`.
+
+    Parameters
+    ----------
+    cb
+        A callback function that will be called with each symbol of the reification
+    calculate_sccs
+        Flag to calculate the SCCs
+    reify_steps
+        Flag to add a number as the last argument of all reification symbols for the corresponding step
+
+    """
+
+    # pylint:disable=too-many-public-methods
+    _step: int
+    # Bug in mypy???
+    # _cb: Callable[[Symbol], None]
+    _calculate_sccs: bool
+    _reify_steps: bool
+    _step_data: _StepData
+
+    def __init__(
+        self,
+        cb: Callable[[Symbol], None],
+        calculate_sccs: bool = False,
+        reify_steps: bool = False,
+    ):
+        self._step = 0
+        self._cb = cb
+        self._calculate_sccs = calculate_sccs
+        self._reify_steps = reify_steps
+        self._step_data = _StepData()
+
+    def calculate_sccs(self) -> None:
+        """
+        Trigger computation of SCCs.
+
+        SCCs can only be computed if the Reifier has been initialized with
+        `calculate_sccs=True`, This function is called automatically if
+        `reify_steps=True` has been set when initializing the Reifier.
+        """
+        for idx, scc in enumerate(self._step_data.graph.tarjan()):
+            for atm in scc:
+                self._output("scc", [Number(idx), Number(atm)])
+
+    def _add_edges(self, head: Sequence[int], body: Sequence[int]):
+        if self._calculate_sccs:
+            for u in head:
+                for v in body:
+                    if v > 0:
+                        self._step_data.graph.add_edge(u, v)
+
+    def _output(self, name: str, args: Sequence[Symbol]):
+        if self._reify_steps:
+            args = list(args) + [Number(self._step)]
+        self._cb(Function(name, args))
+
+    def _tuple(
+        self,
+        name: str,
+        snmap: Dict[Sequence[U], int],
+        elems: Sequence[U],
+        afun: Callable[[Symbol, int, U], Sequence[Symbol]],
+        ordered: bool = False,
+    ) -> Symbol:
+        pruned: Sequence[U]
+        if ordered:
+            pruned = elems
+            ident = tuple(elems)
+        else:
+            seen: Set[U] = set()
+            pruned = []
+            for elem in elems:
+                if elem not in seen:
+                    seen.add(elem)
+                    pruned.append(elem)
+            ident = tuple(sorted(pruned))
+
+        n = len(snmap)
+        i = Number(snmap.setdefault(ident, n))
+        if n == i.number:
+            self._output(name, [i])
+            for idx, atm in enumerate(pruned):
+                self._output(name, afun(i, idx, atm))
+        return i
+
+    def _atom_tuple(self, atoms: Sequence[int]):
+        return self._tuple("atom_tuple", self._step_data.atom_tuples, atoms, _lit)
+
+    def _lit_tuple(self, lits: Sequence[int]):
+        return self._tuple("literal_tuple", self._step_data.lit_tuples, lits, _lit)
+
+    def _wlit_tuple(self, wlits: Sequence[Tuple[int, int]]):
+        return self._tuple(
+            "weighted_literal_tuple", self._step_data.wlit_tuples, wlits, _wlit
+        )
+
+    def init_program(self, incremental: bool) -> None:
+        if incremental:
+            self._cb(Function("tag", [Function("incremental")]))
+
+    def begin_step(self) -> None:
+        pass
+
+    def rule(self, choice: bool, head: Sequence[int], body: Sequence[int]) -> None:
+        hn = "choice" if choice else "disjunction"
+        hd = Function(hn, [self._atom_tuple(head)])
+        bd = Function("normal", [self._lit_tuple(body)])
+        self._output("rule", [hd, bd])
+        self._add_edges(head, body)
+
+    def weight_rule(
+        self,
+        choice: bool,
+        head: Sequence[int],
+        lower_bound: int,
+        body: Sequence[Tuple[int, int]],
+    ) -> None:
+        hn = "choice" if choice else "disjunction"
+        hd = Function(hn, [self._atom_tuple(head)])
+        bd = Function("sum", [self._wlit_tuple(body), Number(lower_bound)])
+        self._output("rule", [hd, bd])
+        self._add_edges(head, [lit for lit, w in body])
+
+    def minimize(self, priority: int, literals: Sequence[Tuple[int, int]]) -> None:
+        self._output("minimize", [Number(priority), self._wlit_tuple(literals)])
+
+    def project(self, atoms: Sequence[int]) -> None:
+        for atom in atoms:
+            self._output("project", [Number(atom)])
+
+    def output_atom(self, symbol: Symbol, atom: int) -> None:
+        self._output("output", [symbol, self._lit_tuple([] if atom == 0 else [atom])])
+
+    def output_term(self, symbol: Symbol, condition: Sequence[int]) -> None:
+        self._output("output", [symbol, self._lit_tuple(condition)])
+
+    def external(self, atom: int, value: TruthValue) -> None:
+        value_name = str(value).replace("TruthValue.", "").lower().rstrip("_")
+        self._output("external", [Number(atom), Function(value_name)])
+
+    def assume(self, literals: Sequence[int]) -> None:
+        for lit in literals:
+            self._output("assume", [Number(lit)])
+
+    def heuristic(
+        self,
+        atom: int,
+        type_: HeuristicType,
+        bias: int,
+        priority: int,
+        condition: Sequence[int],
+    ) -> None:
+        type_name = str(type_).replace("HeuristicType.", "").lower().rstrip("_")
+        condition_lit = self._lit_tuple(condition)
+        self._output(
+            "heuristic",
+            [
+                Number(atom),
+                Function(type_name),
+                Number(bias),
+                Number(priority),
+                condition_lit,
+            ],
+        )
+
+    def acyc_edge(self, node_u: int, node_v: int, condition: Sequence[int]) -> None:
+        self._output(
+            "edge", [Number(node_u), Number(node_v), self._lit_tuple(condition)]
+        )
+
+    def theory_term_number(self, term_id: int, number: int) -> None:
+        self._output("theory_number", [Number(term_id), Number(number)])
+
+    def theory_term_string(self, term_id: int, name: str) -> None:
+        self._output("theory_string", [Number(term_id), String(name)])
+
+    def theory_term_compound(
+        self, term_id: int, name_id_or_type: int, arguments: Sequence[int]
+    ) -> None:
+        names = {-1: "tuple", -2: "set", -3: "list"}
+        if name_id_or_type in names:
+            name = "theory_sequence"
+            value = Function(names[name_id_or_type])
+        else:
+            name = "theory_function"
+            value = Number(name_id_or_type)
+        tuple_id = self._tuple(
+            "theory_tuple", self._step_data.theory_tuples, arguments, _theory, True
+        )
+        self._output(name, [Number(term_id), value, tuple_id])
+
+    def theory_element(
+        self, element_id: int, terms: Sequence[int], condition: Sequence[int]
+    ) -> None:
+        tuple_id = self._tuple(
+            "theory_tuple", self._step_data.theory_tuples, terms, _theory, True
+        )
+        condition_id = self._tuple(
+            "literal_tuple", self._step_data.lit_tuples, condition, _lit
+        )
+        self._output("theory_element", [Number(element_id), tuple_id, condition_id])
+
+    def theory_atom(
+        self, atom_id_or_zero: int, term_id: int, elements: Sequence[int]
+    ) -> None:
+        tuple_e_id = self._tuple(
+            "theory_element_tuple",
+            self._step_data.theory_element_tuples,
+            elements,
+            _lit,
+        )
+        self._output(
+            "theory_atom", [Number(atom_id_or_zero), Number(term_id), tuple_e_id]
+        )
+
+    def theory_atom_with_guard(
+        self,
+        atom_id_or_zero: int,
+        term_id: int,
+        elements: Sequence[int],
+        operator_id: int,
+        right_hand_side_id: int,
+    ) -> None:
+        tuple_id = self._tuple(
+            "theory_element_tuple",
+            self._step_data.theory_element_tuples,
+            elements,
+            _lit,
+        )
+        self._output(
+            "theory_atom",
+            [
+                Number(atom_id_or_zero),
+                Number(term_id),
+                tuple_id,
+                Number(operator_id),
+                Number(right_hand_side_id),
+            ],
+        )
+
+    def end_step(self) -> None:
+        if self._reify_steps:
+            self.calculate_sccs()
+            self._step += 1
+            self._step_data = _StepData()
+
+

Ancestors

+ +

Methods

+
+
+def calculate_sccs(self) ‑> None +
+
+

Trigger computation of SCCs.

+

SCCs can only be computed if the Reifier has been initialized with +calculate_sccs=True, This function is called automatically if +reify_steps=True has been set when initializing the Reifier.

+
+ +Expand source code + +
def calculate_sccs(self) -> None:
+    """
+    Trigger computation of SCCs.
+
+    SCCs can only be computed if the Reifier has been initialized with
+    `calculate_sccs=True`, This function is called automatically if
+    `reify_steps=True` has been set when initializing the Reifier.
+    """
+    for idx, scc in enumerate(self._step_data.graph.tarjan()):
+        for atm in scc:
+            self._output("scc", [Number(idx), Number(atm)])
+
+
+
+

Inherited members

+ +
+
+
+
+ +
+ + + \ No newline at end of file diff --git a/clingo/python-api/5.7/clingox/solving.html b/clingo/python-api/5.7/clingox/solving.html new file mode 100644 index 0000000..69bb196 --- /dev/null +++ b/clingo/python-api/5.7/clingox/solving.html @@ -0,0 +1,198 @@ + + + + + + +clingox.solving API documentation + + + + + + + + + + + +
+
+
+

Module clingox.solving

+
+
+

This module provides functions to approximate the cautious consequences of a +program

+
+ +Expand source code + +
"""
+This module provides functions to approximate the cautious consequences of a
+program
+"""
+
+from typing import Optional, Sequence, Tuple
+
+from clingo.configuration import Configuration
+from clingo.control import Control
+from clingo.symbol import Symbol
+
+
+def approximate(ctl: Control) -> Optional[Tuple[Sequence[Symbol], Sequence[Symbol]]]:
+    """
+    Approximate the stable models of a program.
+
+    Parameters
+    ----------
+    ctl
+        A control object with a program. Grounding should be performed on this
+        control object before calling this function.
+
+    Returns
+    -------
+    Returns `None` if the problem is determined unsatisfiable. Otherwise,
+    returns an approximation of the stable models of the program in form of a
+    pair of sequences of symbols. Atoms contained in the first sequence are
+    true and atoms not contained in the second sequence are false in all stable
+    models.
+
+    Notes
+    -----
+    Runs in polynomial time. An approximation might be returned even if the
+    problem is unsatisfiable.
+    """
+    # solve with a limit of 0 conflicts to propagate direct consequences
+    assert isinstance(ctl.configuration.solve, Configuration)
+    solve_limit = ctl.configuration.solve.solve_limit
+    ctl.configuration.solve.solve_limit = 0
+    ctl.solve()
+    ctl.configuration.solve.solve_limit = solve_limit
+    ctl.cleanup()
+
+    # check if the problem is conflicting
+    if ctl.is_conflicting:
+        return None
+
+    # return approximation
+    lower = []
+    upper = []
+    for sa in ctl.symbolic_atoms:
+        upper.append(sa.symbol)
+        if sa.is_fact:
+            lower.append(sa.symbol)
+    return lower, upper
+
+
+
+
+
+
+
+

Functions

+
+
+def approximate(ctl: Control) ‑> Optional[Tuple[Sequence[Symbol], Sequence[Symbol]]] +
+
+

Approximate the stable models of a program.

+

Parameters

+
+
ctl
+
A control object with a program. Grounding should be performed on this +control object before calling this function.
+
+

Returns

+
+
Returns None if the problem is determined unsatisfiable. Otherwise,
+
returns an approximation of the stable models of the program in form of a
+
 
+
pair of sequences of symbols. Atoms contained in the first sequence are
+
 
+
true and atoms not contained in the second sequence are false in all stable
+
 
+
+

models.

+

Notes

+

Runs in polynomial time. An approximation might be returned even if the +problem is unsatisfiable.

+
+ +Expand source code + +
def approximate(ctl: Control) -> Optional[Tuple[Sequence[Symbol], Sequence[Symbol]]]:
+    """
+    Approximate the stable models of a program.
+
+    Parameters
+    ----------
+    ctl
+        A control object with a program. Grounding should be performed on this
+        control object before calling this function.
+
+    Returns
+    -------
+    Returns `None` if the problem is determined unsatisfiable. Otherwise,
+    returns an approximation of the stable models of the program in form of a
+    pair of sequences of symbols. Atoms contained in the first sequence are
+    true and atoms not contained in the second sequence are false in all stable
+    models.
+
+    Notes
+    -----
+    Runs in polynomial time. An approximation might be returned even if the
+    problem is unsatisfiable.
+    """
+    # solve with a limit of 0 conflicts to propagate direct consequences
+    assert isinstance(ctl.configuration.solve, Configuration)
+    solve_limit = ctl.configuration.solve.solve_limit
+    ctl.configuration.solve.solve_limit = 0
+    ctl.solve()
+    ctl.configuration.solve.solve_limit = solve_limit
+    ctl.cleanup()
+
+    # check if the problem is conflicting
+    if ctl.is_conflicting:
+        return None
+
+    # return approximation
+    lower = []
+    upper = []
+    for sa in ctl.symbolic_atoms:
+        upper.append(sa.symbol)
+        if sa.is_fact:
+            lower.append(sa.symbol)
+    return lower, upper
+
+
+
+
+
+
+
+ +
+ + + \ No newline at end of file diff --git a/clingo/python-api/5.7/clingox/testing/ast.html b/clingo/python-api/5.7/clingox/testing/ast.html new file mode 100644 index 0000000..59631c6 --- /dev/null +++ b/clingo/python-api/5.7/clingox/testing/ast.html @@ -0,0 +1,293 @@ + + + + + + +clingox.testing.ast API documentation + + + + + + + + + + + +
+
+
+

Module clingox.testing.ast

+
+
+

This module provides high-level functions to create unit tests for +ASTs.

+
+ +Expand source code + +
"""
+This module provides high-level functions to create unit tests for
+`clingo.ast.AST`s.
+"""
+
+from typing import Any, List, cast
+from unittest import TestCase
+
+from clingo.ast import AST, ASTType, parse_string
+
+from clingox.pprint import pformat
+
+__all__ = [
+    "ASTTestCase",
+    "parse_literal",
+    "parse_statement",
+    "parse_term",
+]
+
+
+def parse_statement(stm: str) -> AST:
+    """
+    Parse a statement.
+    """
+    stms: List[AST] = []
+    parse_string(stm, stms.append, logger=lambda code, msg: None, message_limit=1)
+    if len(stms) != 2:
+        raise RuntimeError(
+            f"syntax error: stm must contain exactly one statement, {len(stms)} given"
+        )
+    return cast(AST, stms[1])
+
+
+def parse_literal(lit: str) -> AST:
+    """
+    Parse a literal.
+    """
+    stm = parse_statement(f":-{lit}.")
+    if stm.body[0].ast_type != ASTType.Literal:
+        raise RuntimeError("syntax error: lit must be a string representing a literal")
+    return stm.body[0]
+
+
+def parse_term(term: str) -> AST:
+    """
+    Parse a term.
+    """
+    lit = parse_literal(f"atom({term})")
+    return lit.atom.symbol.arguments[0]
+
+
+class ASTTestCase(TestCase):
+    """
+    Class for comparing with `clingo.ast.AST`s.
+    """
+
+    def __init__(self, methodName: str = "runTest"):
+        """
+        Create an instance of the class that will use the named test method
+        when executed. Raises a ValueError if the instance does not have a
+        method with the specified name.
+        """
+        super().__init__(methodName)
+        self.addTypeEqualityFunc(AST, self.assertASTEqual)
+
+    def assertASTEqual(self, first: AST, second: AST, msg: Any = None):
+        """
+        Test whether two `clingo.ast.AST`s are equal.
+        """
+        # pylint: disable=invalid-name
+        self.assertIsInstance(first, AST, "First argument is not an AST")
+        self.assertIsInstance(second, AST, "Second argument is not an AST")
+
+        self.assertEqual(str(first), str(second), msg)
+        first_repr = pformat(first, hide_location=True) + "\n"
+        second_repr = pformat(second, hide_location=True) + "\n"
+        self.assertEqual(first_repr, second_repr, msg)
+        assert first == second
+
+
+
+
+
+
+
+

Functions

+
+
+def parse_literal(lit: str) ‑> AST +
+
+

Parse a literal.

+
+ +Expand source code + +
def parse_literal(lit: str) -> AST:
+    """
+    Parse a literal.
+    """
+    stm = parse_statement(f":-{lit}.")
+    if stm.body[0].ast_type != ASTType.Literal:
+        raise RuntimeError("syntax error: lit must be a string representing a literal")
+    return stm.body[0]
+
+
+
+def parse_statement(stm: str) ‑> AST +
+
+

Parse a statement.

+
+ +Expand source code + +
def parse_statement(stm: str) -> AST:
+    """
+    Parse a statement.
+    """
+    stms: List[AST] = []
+    parse_string(stm, stms.append, logger=lambda code, msg: None, message_limit=1)
+    if len(stms) != 2:
+        raise RuntimeError(
+            f"syntax error: stm must contain exactly one statement, {len(stms)} given"
+        )
+    return cast(AST, stms[1])
+
+
+
+def parse_term(term: str) ‑> AST +
+
+

Parse a term.

+
+ +Expand source code + +
def parse_term(term: str) -> AST:
+    """
+    Parse a term.
+    """
+    lit = parse_literal(f"atom({term})")
+    return lit.atom.symbol.arguments[0]
+
+
+
+
+
+

Classes

+
+
+class ASTTestCase +(methodName: str = 'runTest') +
+
+

Class for comparing with ASTs.

+

Create an instance of the class that will use the named test method +when executed. Raises a ValueError if the instance does not have a +method with the specified name.

+
+ +Expand source code + +
class ASTTestCase(TestCase):
+    """
+    Class for comparing with `clingo.ast.AST`s.
+    """
+
+    def __init__(self, methodName: str = "runTest"):
+        """
+        Create an instance of the class that will use the named test method
+        when executed. Raises a ValueError if the instance does not have a
+        method with the specified name.
+        """
+        super().__init__(methodName)
+        self.addTypeEqualityFunc(AST, self.assertASTEqual)
+
+    def assertASTEqual(self, first: AST, second: AST, msg: Any = None):
+        """
+        Test whether two `clingo.ast.AST`s are equal.
+        """
+        # pylint: disable=invalid-name
+        self.assertIsInstance(first, AST, "First argument is not an AST")
+        self.assertIsInstance(second, AST, "Second argument is not an AST")
+
+        self.assertEqual(str(first), str(second), msg)
+        first_repr = pformat(first, hide_location=True) + "\n"
+        second_repr = pformat(second, hide_location=True) + "\n"
+        self.assertEqual(first_repr, second_repr, msg)
+        assert first == second
+
+

Ancestors

+
    +
  • unittest.case.TestCase
  • +
+

Methods

+
+
+def assertASTEqual(self, first: AST, second: AST, msg: Any = None) +
+
+

Test whether two ASTs are equal.

+
+ +Expand source code + +
def assertASTEqual(self, first: AST, second: AST, msg: Any = None):
+    """
+    Test whether two `clingo.ast.AST`s are equal.
+    """
+    # pylint: disable=invalid-name
+    self.assertIsInstance(first, AST, "First argument is not an AST")
+    self.assertIsInstance(second, AST, "Second argument is not an AST")
+
+    self.assertEqual(str(first), str(second), msg)
+    first_repr = pformat(first, hide_location=True) + "\n"
+    second_repr = pformat(second, hide_location=True) + "\n"
+    self.assertEqual(first_repr, second_repr, msg)
+    assert first == second
+
+
+
+
+
+
+
+ +
+ + + \ No newline at end of file diff --git a/clingo/python-api/5.7/clingox/testing/index.html b/clingo/python-api/5.7/clingox/testing/index.html new file mode 100644 index 0000000..2af8aa3 --- /dev/null +++ b/clingo/python-api/5.7/clingox/testing/index.html @@ -0,0 +1,78 @@ + + + + + + +clingox.testing API documentation + + + + + + + + + + + +
+
+
+

Module clingox.testing

+
+
+

The clingox.testing module provides auxiliary functions to create unit test for +the clingo package.

+
+ +Expand source code + +
"""
+The clingox.testing module provides auxiliary functions to create unit test for
+the clingo package.
+"""
+
+
+
+

Sub-modules

+
+
clingox.testing.ast
+
+

This module provides high-level functions to create unit tests for +ASTs.

+
+
+
+
+
+
+
+
+
+
+ +
+ + + \ No newline at end of file diff --git a/clingo/python-api/5.7/clingox/theory.html b/clingo/python-api/5.7/clingox/theory.html new file mode 100644 index 0000000..59944d2 --- /dev/null +++ b/clingo/python-api/5.7/clingox/theory.html @@ -0,0 +1,825 @@ + + + + + + +clingox.theory API documentation + + + + + + + + + + + +
+
+
+

Module clingox.theory

+
+
+

This module provides functions to work with clingo's theories.

+

Example

+
>>> from clingo.control import Control
+>>> from clingox.theory import evaluate
+>>>
+>>> prg = """... #theory test {
+...     term {
+...         -  : 3, unary;
+...         ** : 2, binary, right;
+...         *  : 1, binary, left;
+...         +  : 0, binary, left;
+...         -  : 0, binary, left
+...     };
+...     &eval/0 : term, head
+... }.
+...
+... &eval{ 3**5-201 }.
+... """
+>>>
+>>> ctl = Control()
+>>> ctl.add('base', [], prg)
+>>> ctl.ground([('base', [])])
+>>>
+>>> atom = next(ctl.theory_atoms)
+>>> print(evaluate(atom.elements[0].terms[0]))
+42
+
+
+ +Expand source code + +
'''
+This module provides functions to work with clingo's theories.
+
+Example
+-------
+
+```python-repl
+>>> from clingo.control import Control
+>>> from clingox.theory import evaluate
+>>>
+>>> prg = """\
+... #theory test {
+...     term {
+...         -  : 3, unary;
+...         ** : 2, binary, right;
+...         *  : 1, binary, left;
+...         +  : 0, binary, left;
+...         -  : 0, binary, left
+...     };
+...     &eval/0 : term, head
+... }.
+...
+... &eval{ 3**5-201 }.
+... """
+>>>
+>>> ctl = Control()
+>>> ctl.add('base', [], prg)
+>>> ctl.ground([('base', [])])
+>>>
+>>> atom = next(ctl.theory_atoms)
+>>> print(evaluate(atom.elements[0].terms[0]))
+42
+```
+'''
+
+from typing import Any
+
+from clingo import Function, Number, String, Symbol, SymbolType, TheoryTermType, Tuple_
+
+__all__ = [
+    "evaluate",
+    "invert_symbol",
+    "is_clingo_operator",
+    "is_operator",
+    "require_number",
+    "TermEvaluator",
+]
+__pdoc__ = {}
+
+
+def require_number(x: Symbol) -> int:
+    """
+    Requires the argument to be a number returning the given number or throwing
+    a type error.
+    """
+    if x.type == SymbolType.Number:
+        return x.number
+
+    raise TypeError("number exepected")
+
+
+def invert_symbol(sym: Symbol) -> Symbol:
+    """
+    Inverts the given symbol.
+
+    Parameters
+    ----------
+    sym
+        The symbol to invert.
+
+    Returns
+    -------
+    The inverted symbol.
+    """
+    if sym.type == SymbolType.Number:
+        return Number(-sym.number)
+
+    if sym.type == SymbolType.Function and sym.name:
+        return Function(sym.name, sym.arguments, not sym.positive)
+
+    raise TypeError("cannot invert symbol")
+
+
+def is_clingo_operator(op: str):
+    """
+    Return true if the given string is a operator as supported by the
+    Evaluator.
+    """
+    return op in ("+", "-", "*", "\\", "/")
+
+
+def is_operator(op: str):
+    """
+    Return true if the given string is an operator.
+
+    Parameters
+    ----------
+    op
+        The operator name to check.
+
+    Returns
+    -------
+    Whether the string is an operator name.
+    """
+    return (op and op[0] in "/!<=>+-*\\?&@|:;~^.") or (op == "not")
+
+
+def _unquote(s: str) -> str:
+    """
+    Remove quotes in the same fashion as clingo.
+    """
+    ret = []
+    slash = False
+    for c in s:
+        if slash:
+            if c == "n":
+                ret.append("\n")
+            else:
+                assert c in '\\"'
+                ret.append(c)
+            slash = False
+        elif c == "\\":
+            slash = True
+        else:
+            ret.append(c)
+
+    return "".join(ret)
+
+
+class TermEvaluator:
+    """
+    This class provides a call operator to evaluate the operators in a theory
+    term in the same fashion as clingo evaluates its arithmetic functions.
+
+    This class can easily be extended for additional binary and unary
+    operators.
+    """
+
+    def evaluate_binary(self, op: str, lhs: Symbol, rhs: Symbol) -> Symbol:
+        """
+        Evaluate binary terms as clingo would.
+
+        Parameters
+        ----------
+        op
+            The operator name.
+        lhs
+            The left-hand-side argument.
+        lhs
+            The right-hand-side argument.
+
+        Returns
+        -------
+        The evaluated operator in form of a symbol.
+        """
+        if op == "+":
+            return Number(require_number(lhs) + require_number(rhs))
+        if op == "-":
+            return Number(require_number(lhs) - require_number(rhs))
+        if op == "*":
+            return Number(require_number(lhs) * require_number(rhs))
+        if op == "**":
+            return Number(require_number(lhs) ** require_number(rhs))
+        if op == "\\":
+            if rhs == Number(0):
+                raise ZeroDivisionError("division by zero")
+            return Number(require_number(lhs) % require_number(rhs))
+        if op == "/":
+            if rhs == Number(0):
+                raise ZeroDivisionError("division by zero")
+            return Number(require_number(lhs) // require_number(rhs))
+
+        if is_operator(op):
+            raise AttributeError("unexpected operator")
+
+        return Function(op, [lhs, rhs])
+
+    def evaluate_unary(self, op: str, arg: Symbol):
+        """
+        Evaluate unary terms as clingo would.
+
+        Parameters
+        ----------
+        op
+            The operator name.
+        arg
+            The argument of the operator.
+
+        Returns
+        -------
+        The evaluated operator in form of a symbol.
+        """
+        if op == "+":
+            return Number(require_number(arg))
+        if op == "-":
+            return invert_symbol(arg)
+        if is_operator(op):
+            raise AttributeError("unexpected operator")
+
+        return Function(op, [arg])
+
+    def __call__(self, term: Any):
+        """
+        Evaluate the given term.
+
+        Parameters
+        ----------
+        term
+            The term to evaluate.
+
+        Returns
+        -------
+        The evaluated term in form of a symbol.
+        """
+        # tuples
+        if term.type == TheoryTermType.Tuple:
+            return Tuple_([self(x) for x in term.arguments])
+
+        # functions and arithmetic operations
+        if term.type == TheoryTermType.Function:
+            arguments = [self(x) for x in term.arguments]
+            # binary operations
+            if len(arguments) == 2:
+                return self.evaluate_binary(term.name, *arguments)
+
+            # unary operations
+            if len(arguments) == 1:
+                return self.evaluate_unary(term.name, *arguments)
+
+            # functions
+            return Function(term.name, arguments)
+
+        # constants
+        if term.type == TheoryTermType.Symbol:
+            if term.name.startswith('"') and term.name.endswith('"'):
+                return String(_unquote(term.name[1:-1]))
+
+            return Function(term.name)
+
+        # numbers
+        if term.type == TheoryTermType.Number:
+            return Number(term.number)
+
+        raise RuntimeError("cannot evaluate term")
+
+
+__pdoc__["TermEvaluator.__call__"] = True
+
+
+def evaluate(term: Any) -> Symbol:
+    """
+    Evaluates the operators in a theory term in the same fashion as clingo
+    evaluates its arithmetic functions.
+
+    We use `Any` as a type hint here to allow for evaluating terms that are
+    duck typing copmatible with clingo's `TheoryTerm` class.
+
+    Parameters
+    ----------
+    term
+        The theory term to evaluate.
+
+    Returns
+    -------
+    The evaluated term in form of a symbol.
+    """
+    return TermEvaluator()(term)
+
+
+
+
+
+
+
+

Functions

+
+
+def evaluate(term: Any) ‑> Symbol +
+
+

Evaluates the operators in a theory term in the same fashion as clingo +evaluates its arithmetic functions.

+

We use Any as a type hint here to allow for evaluating terms that are +duck typing copmatible with clingo's TheoryTerm class.

+

Parameters

+
+
term
+
The theory term to evaluate.
+
+

Returns

+

The evaluated term in form of a symbol.

+
+ +Expand source code + +
def evaluate(term: Any) -> Symbol:
+    """
+    Evaluates the operators in a theory term in the same fashion as clingo
+    evaluates its arithmetic functions.
+
+    We use `Any` as a type hint here to allow for evaluating terms that are
+    duck typing copmatible with clingo's `TheoryTerm` class.
+
+    Parameters
+    ----------
+    term
+        The theory term to evaluate.
+
+    Returns
+    -------
+    The evaluated term in form of a symbol.
+    """
+    return TermEvaluator()(term)
+
+
+
+def invert_symbol(sym: Symbol) ‑> Symbol +
+
+

Inverts the given symbol.

+

Parameters

+
+
sym
+
The symbol to invert.
+
+

Returns

+

The inverted symbol.

+
+ +Expand source code + +
def invert_symbol(sym: Symbol) -> Symbol:
+    """
+    Inverts the given symbol.
+
+    Parameters
+    ----------
+    sym
+        The symbol to invert.
+
+    Returns
+    -------
+    The inverted symbol.
+    """
+    if sym.type == SymbolType.Number:
+        return Number(-sym.number)
+
+    if sym.type == SymbolType.Function and sym.name:
+        return Function(sym.name, sym.arguments, not sym.positive)
+
+    raise TypeError("cannot invert symbol")
+
+
+
+def is_clingo_operator(op: str) +
+
+

Return true if the given string is a operator as supported by the +Evaluator.

+
+ +Expand source code + +
def is_clingo_operator(op: str):
+    """
+    Return true if the given string is a operator as supported by the
+    Evaluator.
+    """
+    return op in ("+", "-", "*", "\\", "/")
+
+
+
+def is_operator(op: str) +
+
+

Return true if the given string is an operator.

+

Parameters

+
+
op
+
The operator name to check.
+
+

Returns

+

Whether the string is an operator name.

+
+ +Expand source code + +
def is_operator(op: str):
+    """
+    Return true if the given string is an operator.
+
+    Parameters
+    ----------
+    op
+        The operator name to check.
+
+    Returns
+    -------
+    Whether the string is an operator name.
+    """
+    return (op and op[0] in "/!<=>+-*\\?&@|:;~^.") or (op == "not")
+
+
+
+def require_number(x: Symbol) ‑> int +
+
+

Requires the argument to be a number returning the given number or throwing +a type error.

+
+ +Expand source code + +
def require_number(x: Symbol) -> int:
+    """
+    Requires the argument to be a number returning the given number or throwing
+    a type error.
+    """
+    if x.type == SymbolType.Number:
+        return x.number
+
+    raise TypeError("number exepected")
+
+
+
+
+
+

Classes

+
+
+class TermEvaluator +
+
+

This class provides a call operator to evaluate the operators in a theory +term in the same fashion as clingo evaluates its arithmetic functions.

+

This class can easily be extended for additional binary and unary +operators.

+
+ +Expand source code + +
class TermEvaluator:
+    """
+    This class provides a call operator to evaluate the operators in a theory
+    term in the same fashion as clingo evaluates its arithmetic functions.
+
+    This class can easily be extended for additional binary and unary
+    operators.
+    """
+
+    def evaluate_binary(self, op: str, lhs: Symbol, rhs: Symbol) -> Symbol:
+        """
+        Evaluate binary terms as clingo would.
+
+        Parameters
+        ----------
+        op
+            The operator name.
+        lhs
+            The left-hand-side argument.
+        lhs
+            The right-hand-side argument.
+
+        Returns
+        -------
+        The evaluated operator in form of a symbol.
+        """
+        if op == "+":
+            return Number(require_number(lhs) + require_number(rhs))
+        if op == "-":
+            return Number(require_number(lhs) - require_number(rhs))
+        if op == "*":
+            return Number(require_number(lhs) * require_number(rhs))
+        if op == "**":
+            return Number(require_number(lhs) ** require_number(rhs))
+        if op == "\\":
+            if rhs == Number(0):
+                raise ZeroDivisionError("division by zero")
+            return Number(require_number(lhs) % require_number(rhs))
+        if op == "/":
+            if rhs == Number(0):
+                raise ZeroDivisionError("division by zero")
+            return Number(require_number(lhs) // require_number(rhs))
+
+        if is_operator(op):
+            raise AttributeError("unexpected operator")
+
+        return Function(op, [lhs, rhs])
+
+    def evaluate_unary(self, op: str, arg: Symbol):
+        """
+        Evaluate unary terms as clingo would.
+
+        Parameters
+        ----------
+        op
+            The operator name.
+        arg
+            The argument of the operator.
+
+        Returns
+        -------
+        The evaluated operator in form of a symbol.
+        """
+        if op == "+":
+            return Number(require_number(arg))
+        if op == "-":
+            return invert_symbol(arg)
+        if is_operator(op):
+            raise AttributeError("unexpected operator")
+
+        return Function(op, [arg])
+
+    def __call__(self, term: Any):
+        """
+        Evaluate the given term.
+
+        Parameters
+        ----------
+        term
+            The term to evaluate.
+
+        Returns
+        -------
+        The evaluated term in form of a symbol.
+        """
+        # tuples
+        if term.type == TheoryTermType.Tuple:
+            return Tuple_([self(x) for x in term.arguments])
+
+        # functions and arithmetic operations
+        if term.type == TheoryTermType.Function:
+            arguments = [self(x) for x in term.arguments]
+            # binary operations
+            if len(arguments) == 2:
+                return self.evaluate_binary(term.name, *arguments)
+
+            # unary operations
+            if len(arguments) == 1:
+                return self.evaluate_unary(term.name, *arguments)
+
+            # functions
+            return Function(term.name, arguments)
+
+        # constants
+        if term.type == TheoryTermType.Symbol:
+            if term.name.startswith('"') and term.name.endswith('"'):
+                return String(_unquote(term.name[1:-1]))
+
+            return Function(term.name)
+
+        # numbers
+        if term.type == TheoryTermType.Number:
+            return Number(term.number)
+
+        raise RuntimeError("cannot evaluate term")
+
+

Methods

+
+
+def __call__(self, term: Any) +
+
+

Evaluate the given term.

+

Parameters

+
+
term
+
The term to evaluate.
+
+

Returns

+

The evaluated term in form of a symbol.

+
+ +Expand source code + +
def __call__(self, term: Any):
+    """
+    Evaluate the given term.
+
+    Parameters
+    ----------
+    term
+        The term to evaluate.
+
+    Returns
+    -------
+    The evaluated term in form of a symbol.
+    """
+    # tuples
+    if term.type == TheoryTermType.Tuple:
+        return Tuple_([self(x) for x in term.arguments])
+
+    # functions and arithmetic operations
+    if term.type == TheoryTermType.Function:
+        arguments = [self(x) for x in term.arguments]
+        # binary operations
+        if len(arguments) == 2:
+            return self.evaluate_binary(term.name, *arguments)
+
+        # unary operations
+        if len(arguments) == 1:
+            return self.evaluate_unary(term.name, *arguments)
+
+        # functions
+        return Function(term.name, arguments)
+
+    # constants
+    if term.type == TheoryTermType.Symbol:
+        if term.name.startswith('"') and term.name.endswith('"'):
+            return String(_unquote(term.name[1:-1]))
+
+        return Function(term.name)
+
+    # numbers
+    if term.type == TheoryTermType.Number:
+        return Number(term.number)
+
+    raise RuntimeError("cannot evaluate term")
+
+
+
+def evaluate_binary(self, op: str, lhs: Symbol, rhs: Symbol) ‑> Symbol +
+
+

Evaluate binary terms as clingo would.

+

Parameters

+
+
op
+
The operator name.
+
lhs
+
The left-hand-side argument.
+
lhs
+
The right-hand-side argument.
+
+

Returns

+

The evaluated operator in form of a symbol.

+
+ +Expand source code + +
def evaluate_binary(self, op: str, lhs: Symbol, rhs: Symbol) -> Symbol:
+    """
+    Evaluate binary terms as clingo would.
+
+    Parameters
+    ----------
+    op
+        The operator name.
+    lhs
+        The left-hand-side argument.
+    lhs
+        The right-hand-side argument.
+
+    Returns
+    -------
+    The evaluated operator in form of a symbol.
+    """
+    if op == "+":
+        return Number(require_number(lhs) + require_number(rhs))
+    if op == "-":
+        return Number(require_number(lhs) - require_number(rhs))
+    if op == "*":
+        return Number(require_number(lhs) * require_number(rhs))
+    if op == "**":
+        return Number(require_number(lhs) ** require_number(rhs))
+    if op == "\\":
+        if rhs == Number(0):
+            raise ZeroDivisionError("division by zero")
+        return Number(require_number(lhs) % require_number(rhs))
+    if op == "/":
+        if rhs == Number(0):
+            raise ZeroDivisionError("division by zero")
+        return Number(require_number(lhs) // require_number(rhs))
+
+    if is_operator(op):
+        raise AttributeError("unexpected operator")
+
+    return Function(op, [lhs, rhs])
+
+
+
+def evaluate_unary(self, op: str, arg: Symbol) +
+
+

Evaluate unary terms as clingo would.

+

Parameters

+
+
op
+
The operator name.
+
arg
+
The argument of the operator.
+
+

Returns

+

The evaluated operator in form of a symbol.

+
+ +Expand source code + +
def evaluate_unary(self, op: str, arg: Symbol):
+    """
+    Evaluate unary terms as clingo would.
+
+    Parameters
+    ----------
+    op
+        The operator name.
+    arg
+        The argument of the operator.
+
+    Returns
+    -------
+    The evaluated operator in form of a symbol.
+    """
+    if op == "+":
+        return Number(require_number(arg))
+    if op == "-":
+        return invert_symbol(arg)
+    if is_operator(op):
+        raise AttributeError("unexpected operator")
+
+    return Function(op, [arg])
+
+
+
+
+
+
+
+ +
+ + + \ No newline at end of file diff --git a/clingo/python-api/5.7/index.html b/clingo/python-api/5.7/index.html new file mode 100644 index 0000000..2aa3f46 --- /dev/null +++ b/clingo/python-api/5.7/index.html @@ -0,0 +1,58 @@ + + + + + + + + + + Python module list + + + + + + + + + + + + + + + + + + + + +
+
+ +

Python module list

+ +
+
+
clingo
+

Module providing functions and classes to control the grounding and solving +process …

+
+
+
clingox
+

The clingox package provides auxiliary functions that extend the functionality +of the clingo package.

+
+
+ +
+
+ + + + + diff --git a/clingo/python-api/5.7/index_files/github.min.css b/clingo/python-api/5.7/index_files/github.min.css new file mode 100644 index 0000000..f5c1fa8 --- /dev/null +++ b/clingo/python-api/5.7/index_files/github.min.css @@ -0,0 +1 @@ +.hljs{display:block;overflow-x:auto;padding:.5em;color:#333;background:#f8f8f8}.hljs-comment,.hljs-quote{color:#998;font-style:italic}.hljs-keyword,.hljs-selector-tag,.hljs-subst{color:#333;font-weight:700}.hljs-literal,.hljs-number,.hljs-tag .hljs-attr,.hljs-template-variable,.hljs-variable{color:teal}.hljs-doctag,.hljs-string{color:#d14}.hljs-section,.hljs-selector-id,.hljs-title{color:#900;font-weight:700}.hljs-subst{font-weight:400}.hljs-class .hljs-title,.hljs-type{color:#458;font-weight:700}.hljs-attribute,.hljs-name,.hljs-tag{color:navy;font-weight:400}.hljs-link,.hljs-regexp{color:#009926}.hljs-bullet,.hljs-symbol{color:#990073}.hljs-built_in,.hljs-builtin-name{color:#0086b3}.hljs-meta{color:#999;font-weight:700}.hljs-deletion{background:#fdd}.hljs-addition{background:#dfd}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700} \ No newline at end of file diff --git a/clingo/python-api/5.7/index_files/highlight.min.js b/clingo/python-api/5.7/index_files/highlight.min.js new file mode 100644 index 0000000..ea8775a --- /dev/null +++ b/clingo/python-api/5.7/index_files/highlight.min.js @@ -0,0 +1,44 @@ +/* + Highlight.js 10.1.1 (93fd0d73) + License: BSD-3-Clause + Copyright (c) 2006-2020, Ivan Sagalaev +*/ +var hljs=function(){"use strict";function e(n){Object.freeze(n);var t="function"==typeof n;return Object.getOwnPropertyNames(n).forEach((function(r){!Object.hasOwnProperty.call(n,r)||null===n[r]||"object"!=typeof n[r]&&"function"!=typeof n[r]||t&&("caller"===r||"callee"===r||"arguments"===r)||Object.isFrozen(n[r])||e(n[r])})),n}class n{constructor(e){void 0===e.data&&(e.data={}),this.data=e.data}ignoreMatch(){this.ignore=!0}}function t(e){return e.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")}function r(e,...n){var t={};for(const n in e)t[n]=e[n];return n.forEach((function(e){for(const n in e)t[n]=e[n]})),t}function a(e){return e.nodeName.toLowerCase()}var i=Object.freeze({__proto__:null,escapeHTML:t,inherit:r,nodeStream:function(e){var n=[];return function e(t,r){for(var i=t.firstChild;i;i=i.nextSibling)3===i.nodeType?r+=i.nodeValue.length:1===i.nodeType&&(n.push({event:"start",offset:r,node:i}),r=e(i,r),a(i).match(/br|hr|img|input/)||n.push({event:"stop",offset:r,node:i}));return r}(e,0),n},mergeStreams:function(e,n,r){var i=0,s="",o=[];function l(){return e.length&&n.length?e[0].offset!==n[0].offset?e[0].offset"}function u(e){s+=""}function d(e){("start"===e.event?c:u)(e.node)}for(;e.length||n.length;){var g=l();if(s+=t(r.substring(i,g[0].offset)),i=g[0].offset,g===e){o.reverse().forEach(u);do{d(g.splice(0,1)[0]),g=l()}while(g===e&&g.length&&g[0].offset===i);o.reverse().forEach(c)}else"start"===g[0].event?o.push(g[0].node):o.pop(),d(g.splice(0,1)[0])}return s+t(r.substr(i))}});const s="",o=e=>!!e.kind;class l{constructor(e,n){this.buffer="",this.classPrefix=n.classPrefix,e.walk(this)}addText(e){this.buffer+=t(e)}openNode(e){if(!o(e))return;let n=e.kind;e.sublanguage||(n=`${this.classPrefix}${n}`),this.span(n)}closeNode(e){o(e)&&(this.buffer+=s)}value(){return this.buffer}span(e){this.buffer+=``}}class c{constructor(){this.rootNode={children:[]},this.stack=[this.rootNode]}get top(){return this.stack[this.stack.length-1]}get root(){return this.rootNode}add(e){this.top.children.push(e)}openNode(e){const n={kind:e,children:[]};this.add(n),this.stack.push(n)}closeNode(){if(this.stack.length>1)return this.stack.pop()}closeAllNodes(){for(;this.closeNode(););}toJSON(){return JSON.stringify(this.rootNode,null,4)}walk(e){return this.constructor._walk(e,this.rootNode)}static _walk(e,n){return"string"==typeof n?e.addText(n):n.children&&(e.openNode(n),n.children.forEach(n=>this._walk(e,n)),e.closeNode(n)),e}static _collapse(e){"string"!=typeof e&&e.children&&(e.children.every(e=>"string"==typeof e)?e.children=[e.children.join("")]:e.children.forEach(e=>{c._collapse(e)}))}}class u extends c{constructor(e){super(),this.options=e}addKeyword(e,n){""!==e&&(this.openNode(n),this.addText(e),this.closeNode())}addText(e){""!==e&&this.add(e)}addSublanguage(e,n){const t=e.root;t.kind=n,t.sublanguage=!0,this.add(t)}toHTML(){return new l(this,this.options).value()}finalize(){return!0}}function d(e){return e?"string"==typeof e?e:e.source:null}const g="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",h={begin:"\\\\[\\s\\S]",relevance:0},f={className:"string",begin:"'",end:"'",illegal:"\\n",contains:[h]},p={className:"string",begin:'"',end:'"',illegal:"\\n",contains:[h]},b={begin:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/},m=function(e,n,t={}){var a=r({className:"comment",begin:e,end:n,contains:[]},t);return a.contains.push(b),a.contains.push({className:"doctag",begin:"(?:TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):",relevance:0}),a},v=m("//","$"),x=m("/\\*","\\*/"),E=m("#","$");var _=Object.freeze({__proto__:null,IDENT_RE:"[a-zA-Z]\\w*",UNDERSCORE_IDENT_RE:"[a-zA-Z_]\\w*",NUMBER_RE:"\\b\\d+(\\.\\d+)?",C_NUMBER_RE:g,BINARY_NUMBER_RE:"\\b(0b[01]+)",RE_STARTERS_RE:"!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",SHEBANG:(e={})=>{const n=/^#![ ]*\//;return e.binary&&(e.begin=function(...e){return e.map(e=>d(e)).join("")}(n,/.*\b/,e.binary,/\b.*/)),r({className:"meta",begin:n,end:/$/,relevance:0,"on:begin":(e,n)=>{0!==e.index&&n.ignoreMatch()}},e)},BACKSLASH_ESCAPE:h,APOS_STRING_MODE:f,QUOTE_STRING_MODE:p,PHRASAL_WORDS_MODE:b,COMMENT:m,C_LINE_COMMENT_MODE:v,C_BLOCK_COMMENT_MODE:x,HASH_COMMENT_MODE:E,NUMBER_MODE:{className:"number",begin:"\\b\\d+(\\.\\d+)?",relevance:0},C_NUMBER_MODE:{className:"number",begin:g,relevance:0},BINARY_NUMBER_MODE:{className:"number",begin:"\\b(0b[01]+)",relevance:0},CSS_NUMBER_MODE:{className:"number",begin:"\\b\\d+(\\.\\d+)?(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",relevance:0},REGEXP_MODE:{begin:/(?=\/[^/\n]*\/)/,contains:[{className:"regexp",begin:/\//,end:/\/[gimuy]*/,illegal:/\n/,contains:[h,{begin:/\[/,end:/\]/,relevance:0,contains:[h]}]}]},TITLE_MODE:{className:"title",begin:"[a-zA-Z]\\w*",relevance:0},UNDERSCORE_TITLE_MODE:{className:"title",begin:"[a-zA-Z_]\\w*",relevance:0},METHOD_GUARD:{begin:"\\.\\s*[a-zA-Z_]\\w*",relevance:0},END_SAME_AS_BEGIN:function(e){return Object.assign(e,{"on:begin":(e,n)=>{n.data._beginMatch=e[1]},"on:end":(e,n)=>{n.data._beginMatch!==e[1]&&n.ignoreMatch()}})}}),N="of and for in not or if then".split(" ");function w(e,n){return n?+n:function(e){return N.includes(e.toLowerCase())}(e)?0:1}const R=t,y=r,{nodeStream:k,mergeStreams:O}=i,M=Symbol("nomatch");return function(t){var a=[],i={},s={},o=[],l=!0,c=/(^(<[^>]+>|\t|)+|\n)/gm,g="Could not find the language '{}', did you forget to load/include a language module?";const h={disableAutodetect:!0,name:"Plain text",contains:[]};var f={noHighlightRe:/^(no-?highlight)$/i,languageDetectRe:/\blang(?:uage)?-([\w-]+)\b/i,classPrefix:"hljs-",tabReplace:null,useBR:!1,languages:null,__emitter:u};function p(e){return f.noHighlightRe.test(e)}function b(e,n,t,r){var a={code:n,language:e};S("before:highlight",a);var i=a.result?a.result:m(a.language,a.code,t,r);return i.code=a.code,S("after:highlight",i),i}function m(e,t,a,s){var o=t;function c(e,n){var t=E.case_insensitive?n[0].toLowerCase():n[0];return Object.prototype.hasOwnProperty.call(e.keywords,t)&&e.keywords[t]}function u(){null!=y.subLanguage?function(){if(""!==A){var e=null;if("string"==typeof y.subLanguage){if(!i[y.subLanguage])return void O.addText(A);e=m(y.subLanguage,A,!0,k[y.subLanguage]),k[y.subLanguage]=e.top}else e=v(A,y.subLanguage.length?y.subLanguage:null);y.relevance>0&&(I+=e.relevance),O.addSublanguage(e.emitter,e.language)}}():function(){if(!y.keywords)return void O.addText(A);let e=0;y.keywordPatternRe.lastIndex=0;let n=y.keywordPatternRe.exec(A),t="";for(;n;){t+=A.substring(e,n.index);const r=c(y,n);if(r){const[e,a]=r;O.addText(t),t="",I+=a,O.addKeyword(n[0],e)}else t+=n[0];e=y.keywordPatternRe.lastIndex,n=y.keywordPatternRe.exec(A)}t+=A.substr(e),O.addText(t)}(),A=""}function h(e){return e.className&&O.openNode(e.className),y=Object.create(e,{parent:{value:y}})}function p(e){return 0===y.matcher.regexIndex?(A+=e[0],1):(L=!0,0)}var b={};function x(t,r){var i=r&&r[0];if(A+=t,null==i)return u(),0;if("begin"===b.type&&"end"===r.type&&b.index===r.index&&""===i){if(A+=o.slice(r.index,r.index+1),!l){const n=Error("0 width match regex");throw n.languageName=e,n.badRule=b.rule,n}return 1}if(b=r,"begin"===r.type)return function(e){var t=e[0],r=e.rule;const a=new n(r),i=[r.__beforeBegin,r["on:begin"]];for(const n of i)if(n&&(n(e,a),a.ignore))return p(t);return r&&r.endSameAsBegin&&(r.endRe=RegExp(t.replace(/[-/\\^$*+?.()|[\]{}]/g,"\\$&"),"m")),r.skip?A+=t:(r.excludeBegin&&(A+=t),u(),r.returnBegin||r.excludeBegin||(A=t)),h(r),r.returnBegin?0:t.length}(r);if("illegal"===r.type&&!a){const e=Error('Illegal lexeme "'+i+'" for mode "'+(y.className||"")+'"');throw e.mode=y,e}if("end"===r.type){var s=function(e){var t=e[0],r=o.substr(e.index),a=function e(t,r,a){let i=function(e,n){var t=e&&e.exec(n);return t&&0===t.index}(t.endRe,a);if(i){if(t["on:end"]){const e=new n(t);t["on:end"](r,e),e.ignore&&(i=!1)}if(i){for(;t.endsParent&&t.parent;)t=t.parent;return t}}if(t.endsWithParent)return e(t.parent,r,a)}(y,e,r);if(!a)return M;var i=y;i.skip?A+=t:(i.returnEnd||i.excludeEnd||(A+=t),u(),i.excludeEnd&&(A=t));do{y.className&&O.closeNode(),y.skip||y.subLanguage||(I+=y.relevance),y=y.parent}while(y!==a.parent);return a.starts&&(a.endSameAsBegin&&(a.starts.endRe=a.endRe),h(a.starts)),i.returnEnd?0:t.length}(r);if(s!==M)return s}if("illegal"===r.type&&""===i)return 1;if(B>1e5&&B>3*r.index)throw Error("potential infinite loop, way more iterations than matches");return A+=i,i.length}var E=T(e);if(!E)throw console.error(g.replace("{}",e)),Error('Unknown language: "'+e+'"');var _=function(e){function n(n,t){return RegExp(d(n),"m"+(e.case_insensitive?"i":"")+(t?"g":""))}class t{constructor(){this.matchIndexes={},this.regexes=[],this.matchAt=1,this.position=0}addRule(e,n){n.position=this.position++,this.matchIndexes[this.matchAt]=n,this.regexes.push([n,e]),this.matchAt+=function(e){return RegExp(e.toString()+"|").exec("").length-1}(e)+1}compile(){0===this.regexes.length&&(this.exec=()=>null);const e=this.regexes.map(e=>e[1]);this.matcherRe=n(function(e,n="|"){for(var t=/\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./,r=0,a="",i=0;i0&&(a+=n),a+="(";o.length>0;){var l=t.exec(o);if(null==l){a+=o;break}a+=o.substring(0,l.index),o=o.substring(l.index+l[0].length),"\\"===l[0][0]&&l[1]?a+="\\"+(+l[1]+s):(a+=l[0],"("===l[0]&&r++)}a+=")"}return a}(e),!0),this.lastIndex=0}exec(e){this.matcherRe.lastIndex=this.lastIndex;const n=this.matcherRe.exec(e);if(!n)return null;const t=n.findIndex((e,n)=>n>0&&void 0!==e),r=this.matchIndexes[t];return n.splice(0,t),Object.assign(n,r)}}class a{constructor(){this.rules=[],this.multiRegexes=[],this.count=0,this.lastIndex=0,this.regexIndex=0}getMatcher(e){if(this.multiRegexes[e])return this.multiRegexes[e];const n=new t;return this.rules.slice(e).forEach(([e,t])=>n.addRule(e,t)),n.compile(),this.multiRegexes[e]=n,n}considerAll(){this.regexIndex=0}addRule(e,n){this.rules.push([e,n]),"begin"===n.type&&this.count++}exec(e){const n=this.getMatcher(this.regexIndex);n.lastIndex=this.lastIndex;const t=n.exec(e);return t&&(this.regexIndex+=t.position+1,this.regexIndex===this.count&&(this.regexIndex=0)),t}}function i(e,n){const t=e.input[e.index-1],r=e.input[e.index+e[0].length];"."!==t&&"."!==r||n.ignoreMatch()}if(e.contains&&e.contains.includes("self"))throw Error("ERR: contains `self` is not supported at the top-level of a language. See documentation.");return function t(s,o){const l=s;if(s.compiled)return l;s.compiled=!0,s.__beforeBegin=null,s.keywords=s.keywords||s.beginKeywords;let c=null;if("object"==typeof s.keywords&&(c=s.keywords.$pattern,delete s.keywords.$pattern),s.keywords&&(s.keywords=function(e,n){var t={};return"string"==typeof e?r("keyword",e):Object.keys(e).forEach((function(n){r(n,e[n])})),t;function r(e,r){n&&(r=r.toLowerCase()),r.split(" ").forEach((function(n){var r=n.split("|");t[r[0]]=[e,w(r[0],r[1])]}))}}(s.keywords,e.case_insensitive)),s.lexemes&&c)throw Error("ERR: Prefer `keywords.$pattern` to `mode.lexemes`, BOTH are not allowed. (see mode reference) ");return l.keywordPatternRe=n(s.lexemes||c||/\w+/,!0),o&&(s.beginKeywords&&(s.begin="\\b("+s.beginKeywords.split(" ").join("|")+")(?=\\b|\\s)",s.__beforeBegin=i),s.begin||(s.begin=/\B|\b/),l.beginRe=n(s.begin),s.endSameAsBegin&&(s.end=s.begin),s.end||s.endsWithParent||(s.end=/\B|\b/),s.end&&(l.endRe=n(s.end)),l.terminator_end=d(s.end)||"",s.endsWithParent&&o.terminator_end&&(l.terminator_end+=(s.end?"|":"")+o.terminator_end)),s.illegal&&(l.illegalRe=n(s.illegal)),void 0===s.relevance&&(s.relevance=1),s.contains||(s.contains=[]),s.contains=[].concat(...s.contains.map((function(e){return function(e){return e.variants&&!e.cached_variants&&(e.cached_variants=e.variants.map((function(n){return r(e,{variants:null},n)}))),e.cached_variants?e.cached_variants:function e(n){return!!n&&(n.endsWithParent||e(n.starts))}(e)?r(e,{starts:e.starts?r(e.starts):null}):Object.isFrozen(e)?r(e):e}("self"===e?s:e)}))),s.contains.forEach((function(e){t(e,l)})),s.starts&&t(s.starts,o),l.matcher=function(e){const n=new a;return e.contains.forEach(e=>n.addRule(e.begin,{rule:e,type:"begin"})),e.terminator_end&&n.addRule(e.terminator_end,{type:"end"}),e.illegal&&n.addRule(e.illegal,{type:"illegal"}),n}(l),l}(e)}(E),N="",y=s||_,k={},O=new f.__emitter(f);!function(){for(var e=[],n=y;n!==E;n=n.parent)n.className&&e.unshift(n.className);e.forEach(e=>O.openNode(e))}();var A="",I=0,S=0,B=0,L=!1;try{for(y.matcher.considerAll();;){B++,L?L=!1:(y.matcher.lastIndex=S,y.matcher.considerAll());const e=y.matcher.exec(o);if(!e)break;const n=x(o.substring(S,e.index),e);S=e.index+n}return x(o.substr(S)),O.closeAllNodes(),O.finalize(),N=O.toHTML(),{relevance:I,value:N,language:e,illegal:!1,emitter:O,top:y}}catch(n){if(n.message&&n.message.includes("Illegal"))return{illegal:!0,illegalBy:{msg:n.message,context:o.slice(S-100,S+100),mode:n.mode},sofar:N,relevance:0,value:R(o),emitter:O};if(l)return{illegal:!1,relevance:0,value:R(o),emitter:O,language:e,top:y,errorRaised:n};throw n}}function v(e,n){n=n||f.languages||Object.keys(i);var t=function(e){const n={relevance:0,emitter:new f.__emitter(f),value:R(e),illegal:!1,top:h};return n.emitter.addText(e),n}(e),r=t;return n.filter(T).filter(I).forEach((function(n){var a=m(n,e,!1);a.language=n,a.relevance>r.relevance&&(r=a),a.relevance>t.relevance&&(r=t,t=a)})),r.language&&(t.second_best=r),t}function x(e){return f.tabReplace||f.useBR?e.replace(c,e=>"\n"===e?f.useBR?"
":e:f.tabReplace?e.replace(/\t/g,f.tabReplace):e):e}function E(e){let n=null;const t=function(e){var n=e.className+" ";n+=e.parentNode?e.parentNode.className:"";const t=f.languageDetectRe.exec(n);if(t){var r=T(t[1]);return r||(console.warn(g.replace("{}",t[1])),console.warn("Falling back to no-highlight mode for this block.",e)),r?t[1]:"no-highlight"}return n.split(/\s+/).find(e=>p(e)||T(e))}(e);if(p(t))return;S("before:highlightBlock",{block:e,language:t}),f.useBR?(n=document.createElement("div")).innerHTML=e.innerHTML.replace(/\n/g,"").replace(//g,"\n"):n=e;const r=n.textContent,a=t?b(t,r,!0):v(r),i=k(n);if(i.length){const e=document.createElement("div");e.innerHTML=a.value,a.value=O(i,k(e),r)}a.value=x(a.value),S("after:highlightBlock",{block:e,result:a}),e.innerHTML=a.value,e.className=function(e,n,t){var r=n?s[n]:t,a=[e.trim()];return e.match(/\bhljs\b/)||a.push("hljs"),e.includes(r)||a.push(r),a.join(" ").trim()}(e.className,t,a.language),e.result={language:a.language,re:a.relevance,relavance:a.relevance},a.second_best&&(e.second_best={language:a.second_best.language,re:a.second_best.relevance,relavance:a.second_best.relevance})}const N=()=>{if(!N.called){N.called=!0;var e=document.querySelectorAll("pre code");a.forEach.call(e,E)}};function T(e){return e=(e||"").toLowerCase(),i[e]||i[s[e]]}function A(e,{languageName:n}){"string"==typeof e&&(e=[e]),e.forEach(e=>{s[e]=n})}function I(e){var n=T(e);return n&&!n.disableAutodetect}function S(e,n){var t=e;o.forEach((function(e){e[t]&&e[t](n)}))}Object.assign(t,{highlight:b,highlightAuto:v,fixMarkup:x,highlightBlock:E,configure:function(e){f=y(f,e)},initHighlighting:N,initHighlightingOnLoad:function(){window.addEventListener("DOMContentLoaded",N,!1)},registerLanguage:function(e,n){var r=null;try{r=n(t)}catch(n){if(console.error("Language definition for '{}' could not be registered.".replace("{}",e)),!l)throw n;console.error(n),r=h}r.name||(r.name=e),i[e]=r,r.rawDefinition=n.bind(null,t),r.aliases&&A(r.aliases,{languageName:e})},listLanguages:function(){return Object.keys(i)},getLanguage:T,registerAliases:A,requireLanguage:function(e){var n=T(e);if(n)return n;throw Error("The '{}' language is required, but not loaded.".replace("{}",e))},autoDetection:I,inherit:y,addPlugin:function(e){o.push(e)}}),t.debugMode=function(){l=!1},t.safeMode=function(){l=!0},t.versionString="10.1.1";for(const n in _)"object"==typeof _[n]&&e(_[n]);return Object.assign(t,_),t}({})}();"object"==typeof exports&&"undefined"!=typeof module&&(module.exports=hljs); +hljs.registerLanguage("apache",function(){"use strict";return function(e){var n={className:"number",begin:"\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}(:\\d{1,5})?"};return{name:"Apache config",aliases:["apacheconf"],case_insensitive:!0,contains:[e.HASH_COMMENT_MODE,{className:"section",begin:"",contains:[n,{className:"number",begin:":\\d{1,5}"},e.inherit(e.QUOTE_STRING_MODE,{relevance:0})]},{className:"attribute",begin:/\w+/,relevance:0,keywords:{nomarkup:"order deny allow setenv rewriterule rewriteengine rewritecond documentroot sethandler errordocument loadmodule options header listen serverroot servername"},starts:{end:/$/,relevance:0,keywords:{literal:"on off all deny allow"},contains:[{className:"meta",begin:"\\s\\[",end:"\\]$"},{className:"variable",begin:"[\\$%]\\{",end:"\\}",contains:["self",{className:"number",begin:"[\\$%]\\d+"}]},n,{className:"number",begin:"\\d+"},e.QUOTE_STRING_MODE]}}],illegal:/\S/}}}()); +hljs.registerLanguage("bash",function(){"use strict";return function(e){const s={};Object.assign(s,{className:"variable",variants:[{begin:/\$[\w\d#@][\w\d_]*/},{begin:/\$\{/,end:/\}/,contains:[{begin:/:-/,contains:[s]}]}]});const t={className:"subst",begin:/\$\(/,end:/\)/,contains:[e.BACKSLASH_ESCAPE]},n={className:"string",begin:/"/,end:/"/,contains:[e.BACKSLASH_ESCAPE,s,t]};t.contains.push(n);const a={begin:/\$\(\(/,end:/\)\)/,contains:[{begin:/\d+#[0-9a-f]+/,className:"number"},e.NUMBER_MODE,s]},i=e.SHEBANG({binary:"(fish|bash|zsh|sh|csh|ksh|tcsh|dash|scsh)",relevance:10}),c={className:"function",begin:/\w[\w\d_]*\s*\(\s*\)\s*\{/,returnBegin:!0,contains:[e.inherit(e.TITLE_MODE,{begin:/\w[\w\d_]*/})],relevance:0};return{name:"Bash",aliases:["sh","zsh"],keywords:{$pattern:/\b-?[a-z\._]+\b/,keyword:"if then else elif fi for while in do done case esac function",literal:"true false",built_in:"break cd continue eval exec exit export getopts hash pwd readonly return shift test times trap umask unset alias bind builtin caller command declare echo enable help let local logout mapfile printf read readarray source type typeset ulimit unalias set shopt autoload bg bindkey bye cap chdir clone comparguments compcall compctl compdescribe compfiles compgroups compquote comptags comptry compvalues dirs disable disown echotc echoti emulate fc fg float functions getcap getln history integer jobs kill limit log noglob popd print pushd pushln rehash sched setcap setopt stat suspend ttyctl unfunction unhash unlimit unsetopt vared wait whence where which zcompile zformat zftp zle zmodload zparseopts zprof zpty zregexparse zsocket zstyle ztcp",_:"-ne -eq -lt -gt -f -d -e -s -l -a"},contains:[i,e.SHEBANG(),c,a,e.HASH_COMMENT_MODE,n,{className:"",begin:/\\"/},{className:"string",begin:/'/,end:/'/},s]}}}()); +hljs.registerLanguage("c-like",function(){"use strict";return function(e){function t(e){return"(?:"+e+")?"}var n="(decltype\\(auto\\)|"+t("[a-zA-Z_]\\w*::")+"[a-zA-Z_]\\w*"+t("<.*?>")+")",r={className:"keyword",begin:"\\b[a-z\\d_]*_t\\b"},a={className:"string",variants:[{begin:'(u8?|U|L)?"',end:'"',illegal:"\\n",contains:[e.BACKSLASH_ESCAPE]},{begin:"(u8?|U|L)?'(\\\\(x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4,8}|[0-7]{3}|\\S)|.)",end:"'",illegal:"."},e.END_SAME_AS_BEGIN({begin:/(?:u8?|U|L)?R"([^()\\ ]{0,16})\(/,end:/\)([^()\\ ]{0,16})"/})]},i={className:"number",variants:[{begin:"\\b(0b[01']+)"},{begin:"(-?)\\b([\\d']+(\\.[\\d']*)?|\\.[\\d']+)(u|U|l|L|ul|UL|f|F|b|B)"},{begin:"(-?)(\\b0[xX][a-fA-F0-9']+|(\\b[\\d']+(\\.[\\d']*)?|\\.[\\d']+)([eE][-+]?[\\d']+)?)"}],relevance:0},s={className:"meta",begin:/#\s*[a-z]+\b/,end:/$/,keywords:{"meta-keyword":"if else elif endif define undef warning error line pragma _Pragma ifdef ifndef include"},contains:[{begin:/\\\n/,relevance:0},e.inherit(a,{className:"meta-string"}),{className:"meta-string",begin:/<.*?>/,end:/$/,illegal:"\\n"},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},o={className:"title",begin:t("[a-zA-Z_]\\w*::")+e.IDENT_RE,relevance:0},c=t("[a-zA-Z_]\\w*::")+e.IDENT_RE+"\\s*\\(",l={keyword:"int float while private char char8_t char16_t char32_t catch import module export virtual operator sizeof dynamic_cast|10 typedef const_cast|10 const for static_cast|10 union namespace unsigned long volatile static protected bool template mutable if public friend do goto auto void enum else break extern using asm case typeid wchar_t short reinterpret_cast|10 default double register explicit signed typename try this switch continue inline delete alignas alignof constexpr consteval constinit decltype concept co_await co_return co_yield requires noexcept static_assert thread_local restrict final override atomic_bool atomic_char atomic_schar atomic_uchar atomic_short atomic_ushort atomic_int atomic_uint atomic_long atomic_ulong atomic_llong atomic_ullong new throw return and and_eq bitand bitor compl not not_eq or or_eq xor xor_eq",built_in:"std string wstring cin cout cerr clog stdin stdout stderr stringstream istringstream ostringstream auto_ptr deque list queue stack vector map set pair bitset multiset multimap unordered_set unordered_map unordered_multiset unordered_multimap priority_queue make_pair array shared_ptr abort terminate abs acos asin atan2 atan calloc ceil cosh cos exit exp fabs floor fmod fprintf fputs free frexp fscanf future isalnum isalpha iscntrl isdigit isgraph islower isprint ispunct isspace isupper isxdigit tolower toupper labs ldexp log10 log malloc realloc memchr memcmp memcpy memset modf pow printf putchar puts scanf sinh sin snprintf sprintf sqrt sscanf strcat strchr strcmp strcpy strcspn strlen strncat strncmp strncpy strpbrk strrchr strspn strstr tanh tan vfprintf vprintf vsprintf endl initializer_list unique_ptr _Bool complex _Complex imaginary _Imaginary",literal:"true false nullptr NULL"},d=[r,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,i,a],_={variants:[{begin:/=/,end:/;/},{begin:/\(/,end:/\)/},{beginKeywords:"new throw return else",end:/;/}],keywords:l,contains:d.concat([{begin:/\(/,end:/\)/,keywords:l,contains:d.concat(["self"]),relevance:0}]),relevance:0},u={className:"function",begin:"("+n+"[\\*&\\s]+)+"+c,returnBegin:!0,end:/[{;=]/,excludeEnd:!0,keywords:l,illegal:/[^\w\s\*&:<>]/,contains:[{begin:"decltype\\(auto\\)",keywords:l,relevance:0},{begin:c,returnBegin:!0,contains:[o],relevance:0},{className:"params",begin:/\(/,end:/\)/,keywords:l,relevance:0,contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,a,i,r,{begin:/\(/,end:/\)/,keywords:l,relevance:0,contains:["self",e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,a,i,r]}]},r,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,s]};return{aliases:["c","cc","h","c++","h++","hpp","hh","hxx","cxx"],keywords:l,disableAutodetect:!0,illegal:"",keywords:l,contains:["self",r]},{begin:e.IDENT_RE+"::",keywords:l},{className:"class",beginKeywords:"class struct",end:/[{;:]/,contains:[{begin://,contains:["self"]},e.TITLE_MODE]}]),exports:{preprocessor:s,strings:a,keywords:l}}}}()); +hljs.registerLanguage("c",function(){"use strict";return function(e){var n=e.getLanguage("c-like").rawDefinition();return n.name="C",n.aliases=["c","h"],n}}()); +hljs.registerLanguage("coffeescript",function(){"use strict";const e=["as","in","of","if","for","while","finally","var","new","function","do","return","void","else","break","catch","instanceof","with","throw","case","default","try","switch","continue","typeof","delete","let","yield","const","class","debugger","async","await","static","import","from","export","extends"],n=["true","false","null","undefined","NaN","Infinity"],a=[].concat(["setInterval","setTimeout","clearInterval","clearTimeout","require","exports","eval","isFinite","isNaN","parseFloat","parseInt","decodeURI","decodeURIComponent","encodeURI","encodeURIComponent","escape","unescape"],["arguments","this","super","console","window","document","localStorage","module","global"],["Intl","DataView","Number","Math","Date","String","RegExp","Object","Function","Boolean","Error","Symbol","Set","Map","WeakSet","WeakMap","Proxy","Reflect","JSON","Promise","Float64Array","Int16Array","Int32Array","Int8Array","Uint16Array","Uint32Array","Float32Array","Array","Uint8Array","Uint8ClampedArray","ArrayBuffer"],["EvalError","InternalError","RangeError","ReferenceError","SyntaxError","TypeError","URIError"]);return function(r){var t={keyword:e.concat(["then","unless","until","loop","by","when","and","or","is","isnt","not"]).filter((e=>n=>!e.includes(n))(["var","const","let","function","static"])).join(" "),literal:n.concat(["yes","no","on","off"]).join(" "),built_in:a.concat(["npm","print"]).join(" ")},i="[A-Za-z$_][0-9A-Za-z$_]*",s={className:"subst",begin:/#\{/,end:/}/,keywords:t},o=[r.BINARY_NUMBER_MODE,r.inherit(r.C_NUMBER_MODE,{starts:{end:"(\\s*/)?",relevance:0}}),{className:"string",variants:[{begin:/'''/,end:/'''/,contains:[r.BACKSLASH_ESCAPE]},{begin:/'/,end:/'/,contains:[r.BACKSLASH_ESCAPE]},{begin:/"""/,end:/"""/,contains:[r.BACKSLASH_ESCAPE,s]},{begin:/"/,end:/"/,contains:[r.BACKSLASH_ESCAPE,s]}]},{className:"regexp",variants:[{begin:"///",end:"///",contains:[s,r.HASH_COMMENT_MODE]},{begin:"//[gim]{0,3}(?=\\W)",relevance:0},{begin:/\/(?![ *]).*?(?![\\]).\/[gim]{0,3}(?=\W)/}]},{begin:"@"+i},{subLanguage:"javascript",excludeBegin:!0,excludeEnd:!0,variants:[{begin:"```",end:"```"},{begin:"`",end:"`"}]}];s.contains=o;var c=r.inherit(r.TITLE_MODE,{begin:i}),l={className:"params",begin:"\\([^\\(]",returnBegin:!0,contains:[{begin:/\(/,end:/\)/,keywords:t,contains:["self"].concat(o)}]};return{name:"CoffeeScript",aliases:["coffee","cson","iced"],keywords:t,illegal:/\/\*/,contains:o.concat([r.COMMENT("###","###"),r.HASH_COMMENT_MODE,{className:"function",begin:"^\\s*"+i+"\\s*=\\s*(\\(.*\\))?\\s*\\B[-=]>",end:"[-=]>",returnBegin:!0,contains:[c,l]},{begin:/[:\(,=]\s*/,relevance:0,contains:[{className:"function",begin:"(\\(.*\\))?\\s*\\B[-=]>",end:"[-=]>",returnBegin:!0,contains:[l]}]},{className:"class",beginKeywords:"class",end:"$",illegal:/[:="\[\]]/,contains:[{beginKeywords:"extends",endsWithParent:!0,illegal:/[:="\[\]]/,contains:[c]},c]},{begin:i+":",end:":",returnBegin:!0,returnEnd:!0,relevance:0}])}}}()); +hljs.registerLanguage("cpp",function(){"use strict";return function(e){var t=e.getLanguage("c-like").rawDefinition();return t.disableAutodetect=!1,t.name="C++",t.aliases=["cc","c++","h++","hpp","hh","hxx","cxx"],t}}()); +hljs.registerLanguage("csharp",function(){"use strict";return function(e){var n={keyword:"abstract as base bool break byte case catch char checked const continue decimal default delegate do double enum event explicit extern finally fixed float for foreach goto if implicit in int interface internal is lock long object operator out override params private protected public readonly ref sbyte sealed short sizeof stackalloc static string struct switch this try typeof uint ulong unchecked unsafe ushort using virtual void volatile while add alias ascending async await by descending dynamic equals from get global group into join let nameof on orderby partial remove select set value var when where yield",literal:"null false true"},i=e.inherit(e.TITLE_MODE,{begin:"[a-zA-Z](\\.?\\w)*"}),a={className:"number",variants:[{begin:"\\b(0b[01']+)"},{begin:"(-?)\\b([\\d']+(\\.[\\d']*)?|\\.[\\d']+)(u|U|l|L|ul|UL|f|F|b|B)"},{begin:"(-?)(\\b0[xX][a-fA-F0-9']+|(\\b[\\d']+(\\.[\\d']*)?|\\.[\\d']+)([eE][-+]?[\\d']+)?)"}],relevance:0},s={className:"string",begin:'@"',end:'"',contains:[{begin:'""'}]},t=e.inherit(s,{illegal:/\n/}),l={className:"subst",begin:"{",end:"}",keywords:n},r=e.inherit(l,{illegal:/\n/}),c={className:"string",begin:/\$"/,end:'"',illegal:/\n/,contains:[{begin:"{{"},{begin:"}}"},e.BACKSLASH_ESCAPE,r]},o={className:"string",begin:/\$@"/,end:'"',contains:[{begin:"{{"},{begin:"}}"},{begin:'""'},l]},g=e.inherit(o,{illegal:/\n/,contains:[{begin:"{{"},{begin:"}}"},{begin:'""'},r]});l.contains=[o,c,s,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,a,e.C_BLOCK_COMMENT_MODE],r.contains=[g,c,t,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,a,e.inherit(e.C_BLOCK_COMMENT_MODE,{illegal:/\n/})];var d={variants:[o,c,s,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE]},E={begin:"<",end:">",contains:[{beginKeywords:"in out"},i]},_=e.IDENT_RE+"(<"+e.IDENT_RE+"(\\s*,\\s*"+e.IDENT_RE+")*>)?(\\[\\])?",b={begin:"@"+e.IDENT_RE,relevance:0};return{name:"C#",aliases:["cs","c#"],keywords:n,illegal:/::/,contains:[e.COMMENT("///","$",{returnBegin:!0,contains:[{className:"doctag",variants:[{begin:"///",relevance:0},{begin:"\x3c!--|--\x3e"},{begin:""}]}]}),e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,{className:"meta",begin:"#",end:"$",keywords:{"meta-keyword":"if else elif endif define undef warning error line region endregion pragma checksum"}},d,a,{beginKeywords:"class interface",end:/[{;=]/,illegal:/[^\s:,]/,contains:[{beginKeywords:"where class"},i,E,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{beginKeywords:"namespace",end:/[{;=]/,illegal:/[^\s:]/,contains:[i,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{className:"meta",begin:"^\\s*\\[",excludeBegin:!0,end:"\\]",excludeEnd:!0,contains:[{className:"meta-string",begin:/"/,end:/"/}]},{beginKeywords:"new return throw await else",relevance:0},{className:"function",begin:"("+_+"\\s+)+"+e.IDENT_RE+"\\s*(\\<.+\\>)?\\s*\\(",returnBegin:!0,end:/\s*[{;=]/,excludeEnd:!0,keywords:n,contains:[{begin:e.IDENT_RE+"\\s*(\\<.+\\>)?\\s*\\(",returnBegin:!0,contains:[e.TITLE_MODE,E],relevance:0},{className:"params",begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:n,relevance:0,contains:[d,a,e.C_BLOCK_COMMENT_MODE]},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},b]}}}()); +hljs.registerLanguage("css",function(){"use strict";return function(e){var n={begin:/(?:[A-Z\_\.\-]+|--[a-zA-Z0-9_-]+)\s*:/,returnBegin:!0,end:";",endsWithParent:!0,contains:[{className:"attribute",begin:/\S/,end:":",excludeEnd:!0,starts:{endsWithParent:!0,excludeEnd:!0,contains:[{begin:/[\w-]+\(/,returnBegin:!0,contains:[{className:"built_in",begin:/[\w-]+/},{begin:/\(/,end:/\)/,contains:[e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,e.CSS_NUMBER_MODE]}]},e.CSS_NUMBER_MODE,e.QUOTE_STRING_MODE,e.APOS_STRING_MODE,e.C_BLOCK_COMMENT_MODE,{className:"number",begin:"#[0-9A-Fa-f]+"},{className:"meta",begin:"!important"}]}}]};return{name:"CSS",case_insensitive:!0,illegal:/[=\/|'\$]/,contains:[e.C_BLOCK_COMMENT_MODE,{className:"selector-id",begin:/#[A-Za-z0-9_-]+/},{className:"selector-class",begin:/\.[A-Za-z0-9_-]+/},{className:"selector-attr",begin:/\[/,end:/\]/,illegal:"$",contains:[e.APOS_STRING_MODE,e.QUOTE_STRING_MODE]},{className:"selector-pseudo",begin:/:(:)?[a-zA-Z0-9\_\-\+\(\)"'.]+/},{begin:"@(page|font-face)",lexemes:"@[a-z-]+",keywords:"@page @font-face"},{begin:"@",end:"[{;]",illegal:/:/,returnBegin:!0,contains:[{className:"keyword",begin:/@\-?\w[\w]*(\-\w+)*/},{begin:/\s/,endsWithParent:!0,excludeEnd:!0,relevance:0,keywords:"and or not only",contains:[{begin:/[a-z-]+:/,className:"attribute"},e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,e.CSS_NUMBER_MODE]}]},{className:"selector-tag",begin:"[a-zA-Z-][a-zA-Z0-9_-]*",relevance:0},{begin:"{",end:"}",illegal:/\S/,contains:[e.C_BLOCK_COMMENT_MODE,n]}]}}}()); +hljs.registerLanguage("diff",function(){"use strict";return function(e){return{name:"Diff",aliases:["patch"],contains:[{className:"meta",relevance:10,variants:[{begin:/^@@ +\-\d+,\d+ +\+\d+,\d+ +@@$/},{begin:/^\*\*\* +\d+,\d+ +\*\*\*\*$/},{begin:/^\-\-\- +\d+,\d+ +\-\-\-\-$/}]},{className:"comment",variants:[{begin:/Index: /,end:/$/},{begin:/={3,}/,end:/$/},{begin:/^\-{3}/,end:/$/},{begin:/^\*{3} /,end:/$/},{begin:/^\+{3}/,end:/$/},{begin:/^\*{15}$/}]},{className:"addition",begin:"^\\+",end:"$"},{className:"deletion",begin:"^\\-",end:"$"},{className:"addition",begin:"^\\!",end:"$"}]}}}()); +hljs.registerLanguage("go",function(){"use strict";return function(e){var n={keyword:"break default func interface select case map struct chan else goto package switch const fallthrough if range type continue for import return var go defer bool byte complex64 complex128 float32 float64 int8 int16 int32 int64 string uint8 uint16 uint32 uint64 int uint uintptr rune",literal:"true false iota nil",built_in:"append cap close complex copy imag len make new panic print println real recover delete"};return{name:"Go",aliases:["golang"],keywords:n,illegal:"e(n)).join("")}return function(a){var s={className:"number",relevance:0,variants:[{begin:/([\+\-]+)?[\d]+_[\d_]+/},{begin:a.NUMBER_RE}]},i=a.COMMENT();i.variants=[{begin:/;/,end:/$/},{begin:/#/,end:/$/}];var t={className:"variable",variants:[{begin:/\$[\w\d"][\w\d_]*/},{begin:/\$\{(.*?)}/}]},r={className:"literal",begin:/\bon|off|true|false|yes|no\b/},l={className:"string",contains:[a.BACKSLASH_ESCAPE],variants:[{begin:"'''",end:"'''",relevance:10},{begin:'"""',end:'"""',relevance:10},{begin:'"',end:'"'},{begin:"'",end:"'"}]},c={begin:/\[/,end:/\]/,contains:[i,r,t,l,s,"self"],relevance:0},g="("+[/[A-Za-z0-9_-]+/,/"(\\"|[^"])*"/,/'[^']*'/].map(n=>e(n)).join("|")+")";return{name:"TOML, also INI",aliases:["toml"],case_insensitive:!0,illegal:/\S/,contains:[i,{className:"section",begin:/\[+/,end:/\]+/},{begin:n(g,"(\\s*\\.\\s*",g,")*",n("(?=",/\s*=\s*[^#\s]/,")")),className:"attr",starts:{end:/$/,contains:[i,c,r,t,l,s]}}]}}}()); +hljs.registerLanguage("java",function(){"use strict";function e(e){return e?"string"==typeof e?e:e.source:null}function n(e){return a("(",e,")?")}function a(...n){return n.map(n=>e(n)).join("")}function s(...n){return"("+n.map(n=>e(n)).join("|")+")"}return function(e){var t="false synchronized int abstract float private char boolean var static null if const for true while long strictfp finally protected import native final void enum else break transient catch instanceof byte super volatile case assert short package default double public try this switch continue throws protected public private module requires exports do",i={className:"meta",begin:"@[À-ʸa-zA-Z_$][À-ʸa-zA-Z_$0-9]*",contains:[{begin:/\(/,end:/\)/,contains:["self"]}]},r=e=>a("[",e,"]+([",e,"_]*[",e,"]+)?"),c={className:"number",variants:[{begin:`\\b(0[bB]${r("01")})[lL]?`},{begin:`\\b(0${r("0-7")})[dDfFlL]?`},{begin:a(/\b0[xX]/,s(a(r("a-fA-F0-9"),/\./,r("a-fA-F0-9")),a(r("a-fA-F0-9"),/\.?/),a(/\./,r("a-fA-F0-9"))),/([pP][+-]?(\d+))?/,/[fFdDlL]?/)},{begin:a(/\b/,s(a(/\d*\./,r("\\d")),r("\\d")),/[eE][+-]?[\d]+[dDfF]?/)},{begin:a(/\b/,r(/\d/),n(/\.?/),n(r(/\d/)),/[dDfFlL]?/)}],relevance:0};return{name:"Java",aliases:["jsp"],keywords:t,illegal:/<\/|#/,contains:[e.COMMENT("/\\*\\*","\\*/",{relevance:0,contains:[{begin:/\w+@/,relevance:0},{className:"doctag",begin:"@[A-Za-z]+"}]}),e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,{className:"class",beginKeywords:"class interface",end:/[{;=]/,excludeEnd:!0,keywords:"class interface",illegal:/[:"\[\]]/,contains:[{beginKeywords:"extends implements"},e.UNDERSCORE_TITLE_MODE]},{beginKeywords:"new throw return else",relevance:0},{className:"function",begin:"([À-ʸa-zA-Z_$][À-ʸa-zA-Z_$0-9]*(<[À-ʸa-zA-Z_$][À-ʸa-zA-Z_$0-9]*(\\s*,\\s*[À-ʸa-zA-Z_$][À-ʸa-zA-Z_$0-9]*)*>)?\\s+)+"+e.UNDERSCORE_IDENT_RE+"\\s*\\(",returnBegin:!0,end:/[{;=]/,excludeEnd:!0,keywords:t,contains:[{begin:e.UNDERSCORE_IDENT_RE+"\\s*\\(",returnBegin:!0,relevance:0,contains:[e.UNDERSCORE_TITLE_MODE]},{className:"params",begin:/\(/,end:/\)/,keywords:t,relevance:0,contains:[i,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,e.C_NUMBER_MODE,e.C_BLOCK_COMMENT_MODE]},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},c,i]}}}()); +hljs.registerLanguage("javascript",function(){"use strict";const e=["as","in","of","if","for","while","finally","var","new","function","do","return","void","else","break","catch","instanceof","with","throw","case","default","try","switch","continue","typeof","delete","let","yield","const","class","debugger","async","await","static","import","from","export","extends"],n=["true","false","null","undefined","NaN","Infinity"],a=[].concat(["setInterval","setTimeout","clearInterval","clearTimeout","require","exports","eval","isFinite","isNaN","parseFloat","parseInt","decodeURI","decodeURIComponent","encodeURI","encodeURIComponent","escape","unescape"],["arguments","this","super","console","window","document","localStorage","module","global"],["Intl","DataView","Number","Math","Date","String","RegExp","Object","Function","Boolean","Error","Symbol","Set","Map","WeakSet","WeakMap","Proxy","Reflect","JSON","Promise","Float64Array","Int16Array","Int32Array","Int8Array","Uint16Array","Uint32Array","Float32Array","Array","Uint8Array","Uint8ClampedArray","ArrayBuffer"],["EvalError","InternalError","RangeError","ReferenceError","SyntaxError","TypeError","URIError"]);function s(e){return r("(?=",e,")")}function r(...e){return e.map(e=>(function(e){return e?"string"==typeof e?e:e.source:null})(e)).join("")}return function(t){var i="[A-Za-z$_][0-9A-Za-z$_]*",c={begin:/<[A-Za-z0-9\\._:-]+/,end:/\/[A-Za-z0-9\\._:-]+>|\/>/},o={$pattern:"[A-Za-z$_][0-9A-Za-z$_]*",keyword:e.join(" "),literal:n.join(" "),built_in:a.join(" ")},l={className:"number",variants:[{begin:"\\b(0[bB][01]+)n?"},{begin:"\\b(0[oO][0-7]+)n?"},{begin:t.C_NUMBER_RE+"n?"}],relevance:0},E={className:"subst",begin:"\\$\\{",end:"\\}",keywords:o,contains:[]},d={begin:"html`",end:"",starts:{end:"`",returnEnd:!1,contains:[t.BACKSLASH_ESCAPE,E],subLanguage:"xml"}},g={begin:"css`",end:"",starts:{end:"`",returnEnd:!1,contains:[t.BACKSLASH_ESCAPE,E],subLanguage:"css"}},u={className:"string",begin:"`",end:"`",contains:[t.BACKSLASH_ESCAPE,E]};E.contains=[t.APOS_STRING_MODE,t.QUOTE_STRING_MODE,d,g,u,l,t.REGEXP_MODE];var b=E.contains.concat([{begin:/\(/,end:/\)/,contains:["self"].concat(E.contains,[t.C_BLOCK_COMMENT_MODE,t.C_LINE_COMMENT_MODE])},t.C_BLOCK_COMMENT_MODE,t.C_LINE_COMMENT_MODE]),_={className:"params",begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,contains:b};return{name:"JavaScript",aliases:["js","jsx","mjs","cjs"],keywords:o,contains:[t.SHEBANG({binary:"node",relevance:5}),{className:"meta",relevance:10,begin:/^\s*['"]use (strict|asm)['"]/},t.APOS_STRING_MODE,t.QUOTE_STRING_MODE,d,g,u,t.C_LINE_COMMENT_MODE,t.COMMENT("/\\*\\*","\\*/",{relevance:0,contains:[{className:"doctag",begin:"@[A-Za-z]+",contains:[{className:"type",begin:"\\{",end:"\\}",relevance:0},{className:"variable",begin:i+"(?=\\s*(-)|$)",endsParent:!0,relevance:0},{begin:/(?=[^\n])\s/,relevance:0}]}]}),t.C_BLOCK_COMMENT_MODE,l,{begin:r(/[{,\n]\s*/,s(r(/(((\/\/.*)|(\/\*(.|\n)*\*\/))\s*)*/,i+"\\s*:"))),relevance:0,contains:[{className:"attr",begin:i+s("\\s*:"),relevance:0}]},{begin:"("+t.RE_STARTERS_RE+"|\\b(case|return|throw)\\b)\\s*",keywords:"return throw case",contains:[t.C_LINE_COMMENT_MODE,t.C_BLOCK_COMMENT_MODE,t.REGEXP_MODE,{className:"function",begin:"(\\([^(]*(\\([^(]*(\\([^(]*\\))?\\))?\\)|"+t.UNDERSCORE_IDENT_RE+")\\s*=>",returnBegin:!0,end:"\\s*=>",contains:[{className:"params",variants:[{begin:t.UNDERSCORE_IDENT_RE},{className:null,begin:/\(\s*\)/,skip:!0},{begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:o,contains:b}]}]},{begin:/,/,relevance:0},{className:"",begin:/\s/,end:/\s*/,skip:!0},{variants:[{begin:"<>",end:""},{begin:c.begin,end:c.end}],subLanguage:"xml",contains:[{begin:c.begin,end:c.end,skip:!0,contains:["self"]}]}],relevance:0},{className:"function",beginKeywords:"function",end:/\{/,excludeEnd:!0,contains:[t.inherit(t.TITLE_MODE,{begin:i}),_],illegal:/\[|%/},{begin:/\$[(.]/},t.METHOD_GUARD,{className:"class",beginKeywords:"class",end:/[{;=]/,excludeEnd:!0,illegal:/[:"\[\]]/,contains:[{beginKeywords:"extends"},t.UNDERSCORE_TITLE_MODE]},{beginKeywords:"constructor",end:/\{/,excludeEnd:!0},{begin:"(get|set)\\s+(?="+i+"\\()",end:/{/,keywords:"get set",contains:[t.inherit(t.TITLE_MODE,{begin:i}),{begin:/\(\)/},_]}],illegal:/#(?!!)/}}}()); +hljs.registerLanguage("json",function(){"use strict";return function(n){var e={literal:"true false null"},i=[n.C_LINE_COMMENT_MODE,n.C_BLOCK_COMMENT_MODE],t=[n.QUOTE_STRING_MODE,n.C_NUMBER_MODE],a={end:",",endsWithParent:!0,excludeEnd:!0,contains:t,keywords:e},l={begin:"{",end:"}",contains:[{className:"attr",begin:/"/,end:/"/,contains:[n.BACKSLASH_ESCAPE],illegal:"\\n"},n.inherit(a,{begin:/:/})].concat(i),illegal:"\\S"},s={begin:"\\[",end:"\\]",contains:[n.inherit(a)],illegal:"\\S"};return t.push(l,s),i.forEach((function(n){t.push(n)})),{name:"JSON",contains:t,keywords:e,illegal:"\\S"}}}()); +hljs.registerLanguage("kotlin",function(){"use strict";return function(e){var n={keyword:"abstract as val var vararg get set class object open private protected public noinline crossinline dynamic final enum if else do while for when throw try catch finally import package is in fun override companion reified inline lateinit init interface annotation data sealed internal infix operator out by constructor super tailrec where const inner suspend typealias external expect actual trait volatile transient native default",built_in:"Byte Short Char Int Long Boolean Float Double Void Unit Nothing",literal:"true false null"},a={className:"symbol",begin:e.UNDERSCORE_IDENT_RE+"@"},i={className:"subst",begin:"\\${",end:"}",contains:[e.C_NUMBER_MODE]},s={className:"variable",begin:"\\$"+e.UNDERSCORE_IDENT_RE},t={className:"string",variants:[{begin:'"""',end:'"""(?=[^"])',contains:[s,i]},{begin:"'",end:"'",illegal:/\n/,contains:[e.BACKSLASH_ESCAPE]},{begin:'"',end:'"',illegal:/\n/,contains:[e.BACKSLASH_ESCAPE,s,i]}]};i.contains.push(t);var r={className:"meta",begin:"@(?:file|property|field|get|set|receiver|param|setparam|delegate)\\s*:(?:\\s*"+e.UNDERSCORE_IDENT_RE+")?"},l={className:"meta",begin:"@"+e.UNDERSCORE_IDENT_RE,contains:[{begin:/\(/,end:/\)/,contains:[e.inherit(t,{className:"meta-string"})]}]},c=e.COMMENT("/\\*","\\*/",{contains:[e.C_BLOCK_COMMENT_MODE]}),o={variants:[{className:"type",begin:e.UNDERSCORE_IDENT_RE},{begin:/\(/,end:/\)/,contains:[]}]},d=o;return d.variants[1].contains=[o],o.variants[1].contains=[d],{name:"Kotlin",aliases:["kt"],keywords:n,contains:[e.COMMENT("/\\*\\*","\\*/",{relevance:0,contains:[{className:"doctag",begin:"@[A-Za-z]+"}]}),e.C_LINE_COMMENT_MODE,c,{className:"keyword",begin:/\b(break|continue|return|this)\b/,starts:{contains:[{className:"symbol",begin:/@\w+/}]}},a,r,l,{className:"function",beginKeywords:"fun",end:"[(]|$",returnBegin:!0,excludeEnd:!0,keywords:n,illegal:/fun\s+(<.*>)?[^\s\(]+(\s+[^\s\(]+)\s*=/,relevance:5,contains:[{begin:e.UNDERSCORE_IDENT_RE+"\\s*\\(",returnBegin:!0,relevance:0,contains:[e.UNDERSCORE_TITLE_MODE]},{className:"type",begin://,keywords:"reified",relevance:0},{className:"params",begin:/\(/,end:/\)/,endsParent:!0,keywords:n,relevance:0,contains:[{begin:/:/,end:/[=,\/]/,endsWithParent:!0,contains:[o,e.C_LINE_COMMENT_MODE,c],relevance:0},e.C_LINE_COMMENT_MODE,c,r,l,t,e.C_NUMBER_MODE]},c]},{className:"class",beginKeywords:"class interface trait",end:/[:\{(]|$/,excludeEnd:!0,illegal:"extends implements",contains:[{beginKeywords:"public protected internal private constructor"},e.UNDERSCORE_TITLE_MODE,{className:"type",begin://,excludeBegin:!0,excludeEnd:!0,relevance:0},{className:"type",begin:/[,:]\s*/,end:/[<\(,]|$/,excludeBegin:!0,returnEnd:!0},r,l]},t,{className:"meta",begin:"^#!/usr/bin/env",end:"$",illegal:"\n"},{className:"number",begin:"\\b(0[bB]([01]+[01_]+[01]+|[01]+)|0[xX]([a-fA-F0-9]+[a-fA-F0-9_]+[a-fA-F0-9]+|[a-fA-F0-9]+)|(([\\d]+[\\d_]+[\\d]+|[\\d]+)(\\.([\\d]+[\\d_]+[\\d]+|[\\d]+))?|\\.([\\d]+[\\d_]+[\\d]+|[\\d]+))([eE][-+]?\\d+)?)[lLfF]?",relevance:0}]}}}()); +hljs.registerLanguage("less",function(){"use strict";return function(e){var n="([\\w-]+|@{[\\w-]+})",a=[],s=[],t=function(e){return{className:"string",begin:"~?"+e+".*?"+e}},r=function(e,n,a){return{className:e,begin:n,relevance:a}},i={begin:"\\(",end:"\\)",contains:s,relevance:0};s.push(e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,t("'"),t('"'),e.CSS_NUMBER_MODE,{begin:"(url|data-uri)\\(",starts:{className:"string",end:"[\\)\\n]",excludeEnd:!0}},r("number","#[0-9A-Fa-f]+\\b"),i,r("variable","@@?[\\w-]+",10),r("variable","@{[\\w-]+}"),r("built_in","~?`[^`]*?`"),{className:"attribute",begin:"[\\w-]+\\s*:",end:":",returnBegin:!0,excludeEnd:!0},{className:"meta",begin:"!important"});var c=s.concat({begin:"{",end:"}",contains:a}),l={beginKeywords:"when",endsWithParent:!0,contains:[{beginKeywords:"and not"}].concat(s)},o={begin:n+"\\s*:",returnBegin:!0,end:"[;}]",relevance:0,contains:[{className:"attribute",begin:n,end:":",excludeEnd:!0,starts:{endsWithParent:!0,illegal:"[<=$]",relevance:0,contains:s}}]},g={className:"keyword",begin:"@(import|media|charset|font-face|(-[a-z]+-)?keyframes|supports|document|namespace|page|viewport|host)\\b",starts:{end:"[;{}]",returnEnd:!0,contains:s,relevance:0}},d={className:"variable",variants:[{begin:"@[\\w-]+\\s*:",relevance:15},{begin:"@[\\w-]+"}],starts:{end:"[;}]",returnEnd:!0,contains:c}},b={variants:[{begin:"[\\.#:&\\[>]",end:"[;{}]"},{begin:n,end:"{"}],returnBegin:!0,returnEnd:!0,illegal:"[<='$\"]",relevance:0,contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,l,r("keyword","all\\b"),r("variable","@{[\\w-]+}"),r("selector-tag",n+"%?",0),r("selector-id","#"+n),r("selector-class","\\."+n,0),r("selector-tag","&",0),{className:"selector-attr",begin:"\\[",end:"\\]"},{className:"selector-pseudo",begin:/:(:)?[a-zA-Z0-9\_\-\+\(\)"'.]+/},{begin:"\\(",end:"\\)",contains:c},{begin:"!important"}]};return a.push(e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,g,d,o,b),{name:"Less",case_insensitive:!0,illegal:"[=>'/<($\"]",contains:a}}}()); +hljs.registerLanguage("lua",function(){"use strict";return function(e){var t={begin:"\\[=*\\[",end:"\\]=*\\]",contains:["self"]},a=[e.COMMENT("--(?!\\[=*\\[)","$"),e.COMMENT("--\\[=*\\[","\\]=*\\]",{contains:[t],relevance:10})];return{name:"Lua",keywords:{$pattern:e.UNDERSCORE_IDENT_RE,literal:"true false nil",keyword:"and break do else elseif end for goto if in local not or repeat return then until while",built_in:"_G _ENV _VERSION __index __newindex __mode __call __metatable __tostring __len __gc __add __sub __mul __div __mod __pow __concat __unm __eq __lt __le assert collectgarbage dofile error getfenv getmetatable ipairs load loadfile loadstring module next pairs pcall print rawequal rawget rawset require select setfenv setmetatable tonumber tostring type unpack xpcall arg self coroutine resume yield status wrap create running debug getupvalue debug sethook getmetatable gethook setmetatable setlocal traceback setfenv getinfo setupvalue getlocal getregistry getfenv io lines write close flush open output type read stderr stdin input stdout popen tmpfile math log max acos huge ldexp pi cos tanh pow deg tan cosh sinh random randomseed frexp ceil floor rad abs sqrt modf asin min mod fmod log10 atan2 exp sin atan os exit setlocale date getenv difftime remove time clock tmpname rename execute package preload loadlib loaded loaders cpath config path seeall string sub upper len gfind rep find match char dump gmatch reverse byte format gsub lower table setn insert getn foreachi maxn foreach concat sort remove"},contains:a.concat([{className:"function",beginKeywords:"function",end:"\\)",contains:[e.inherit(e.TITLE_MODE,{begin:"([_a-zA-Z]\\w*\\.)*([_a-zA-Z]\\w*:)?[_a-zA-Z]\\w*"}),{className:"params",begin:"\\(",endsWithParent:!0,contains:a}].concat(a)},e.C_NUMBER_MODE,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,{className:"string",begin:"\\[=*\\[",end:"\\]=*\\]",contains:[t],relevance:5}])}}}()); +hljs.registerLanguage("makefile",function(){"use strict";return function(e){var i={className:"variable",variants:[{begin:"\\$\\("+e.UNDERSCORE_IDENT_RE+"\\)",contains:[e.BACKSLASH_ESCAPE]},{begin:/\$[@%`]+/}]}]}]};return{name:"HTML, XML",aliases:["html","xhtml","rss","atom","xjb","xsd","xsl","plist","wsf","svg"],case_insensitive:!0,contains:[{className:"meta",begin:"",relevance:10,contains:[a,i,t,s,{begin:"\\[",end:"\\]",contains:[{className:"meta",begin:"",contains:[a,s,i,t]}]}]},e.COMMENT("\x3c!--","--\x3e",{relevance:10}),{begin:"<\\!\\[CDATA\\[",end:"\\]\\]>",relevance:10},n,{className:"meta",begin:/<\?xml/,end:/\?>/,relevance:10},{className:"tag",begin:")",end:">",keywords:{name:"style"},contains:[c],starts:{end:"",returnEnd:!0,subLanguage:["css","xml"]}},{className:"tag",begin:")",end:">",keywords:{name:"script"},contains:[c],starts:{end:"<\/script>",returnEnd:!0,subLanguage:["javascript","handlebars","xml"]}},{className:"tag",begin:"",contains:[{className:"name",begin:/[^\/><\s]+/,relevance:0},c]}]}}}()); +hljs.registerLanguage("markdown",function(){"use strict";return function(n){const e={begin:"<",end:">",subLanguage:"xml",relevance:0},a={begin:"\\[.+?\\][\\(\\[].*?[\\)\\]]",returnBegin:!0,contains:[{className:"string",begin:"\\[",end:"\\]",excludeBegin:!0,returnEnd:!0,relevance:0},{className:"link",begin:"\\]\\(",end:"\\)",excludeBegin:!0,excludeEnd:!0},{className:"symbol",begin:"\\]\\[",end:"\\]",excludeBegin:!0,excludeEnd:!0}],relevance:10},i={className:"strong",contains:[],variants:[{begin:/_{2}/,end:/_{2}/},{begin:/\*{2}/,end:/\*{2}/}]},s={className:"emphasis",contains:[],variants:[{begin:/\*(?!\*)/,end:/\*/},{begin:/_(?!_)/,end:/_/,relevance:0}]};i.contains.push(s),s.contains.push(i);var c=[e,a];return i.contains=i.contains.concat(c),s.contains=s.contains.concat(c),{name:"Markdown",aliases:["md","mkdown","mkd"],contains:[{className:"section",variants:[{begin:"^#{1,6}",end:"$",contains:c=c.concat(i,s)},{begin:"(?=^.+?\\n[=-]{2,}$)",contains:[{begin:"^[=-]*$"},{begin:"^",end:"\\n",contains:c}]}]},e,{className:"bullet",begin:"^[ \t]*([*+-]|(\\d+\\.))(?=\\s+)",end:"\\s+",excludeEnd:!0},i,s,{className:"quote",begin:"^>\\s+",contains:c,end:"$"},{className:"code",variants:[{begin:"(`{3,})(.|\\n)*?\\1`*[ ]*"},{begin:"(~{3,})(.|\\n)*?\\1~*[ ]*"},{begin:"```",end:"```+[ ]*$"},{begin:"~~~",end:"~~~+[ ]*$"},{begin:"`.+?`"},{begin:"(?=^( {4}|\\t))",contains:[{begin:"^( {4}|\\t)",end:"(\\n)$"}],relevance:0}]},{begin:"^[-\\*]{3,}",end:"$"},a,{begin:/^\[[^\n]+\]:/,returnBegin:!0,contains:[{className:"symbol",begin:/\[/,end:/\]/,excludeBegin:!0,excludeEnd:!0},{className:"link",begin:/:\s*/,end:/$/,excludeBegin:!0}]}]}}}()); +hljs.registerLanguage("nginx",function(){"use strict";return function(e){var n={className:"variable",variants:[{begin:/\$\d+/},{begin:/\$\{/,end:/}/},{begin:"[\\$\\@]"+e.UNDERSCORE_IDENT_RE}]},a={endsWithParent:!0,keywords:{$pattern:"[a-z/_]+",literal:"on off yes no true false none blocked debug info notice warn error crit select break last permanent redirect kqueue rtsig epoll poll /dev/poll"},relevance:0,illegal:"=>",contains:[e.HASH_COMMENT_MODE,{className:"string",contains:[e.BACKSLASH_ESCAPE,n],variants:[{begin:/"/,end:/"/},{begin:/'/,end:/'/}]},{begin:"([a-z]+):/",end:"\\s",endsWithParent:!0,excludeEnd:!0,contains:[n]},{className:"regexp",contains:[e.BACKSLASH_ESCAPE,n],variants:[{begin:"\\s\\^",end:"\\s|{|;",returnEnd:!0},{begin:"~\\*?\\s+",end:"\\s|{|;",returnEnd:!0},{begin:"\\*(\\.[a-z\\-]+)+"},{begin:"([a-z\\-]+\\.)+\\*"}]},{className:"number",begin:"\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}(:\\d{1,5})?\\b"},{className:"number",begin:"\\b\\d+[kKmMgGdshdwy]*\\b",relevance:0},n]};return{name:"Nginx config",aliases:["nginxconf"],contains:[e.HASH_COMMENT_MODE,{begin:e.UNDERSCORE_IDENT_RE+"\\s+{",returnBegin:!0,end:"{",contains:[{className:"section",begin:e.UNDERSCORE_IDENT_RE}],relevance:0},{begin:e.UNDERSCORE_IDENT_RE+"\\s",end:";|{",returnBegin:!0,contains:[{className:"attribute",begin:e.UNDERSCORE_IDENT_RE,starts:a}],relevance:0}],illegal:"[^\\s\\}]"}}}()); +hljs.registerLanguage("objectivec",function(){"use strict";return function(e){var n=/[a-zA-Z@][a-zA-Z0-9_]*/,_={$pattern:n,keyword:"@interface @class @protocol @implementation"};return{name:"Objective-C",aliases:["mm","objc","obj-c"],keywords:{$pattern:n,keyword:"int float while char export sizeof typedef const struct for union unsigned long volatile static bool mutable if do return goto void enum else break extern asm case short default double register explicit signed typename this switch continue wchar_t inline readonly assign readwrite self @synchronized id typeof nonatomic super unichar IBOutlet IBAction strong weak copy in out inout bycopy byref oneway __strong __weak __block __autoreleasing @private @protected @public @try @property @end @throw @catch @finally @autoreleasepool @synthesize @dynamic @selector @optional @required @encode @package @import @defs @compatibility_alias __bridge __bridge_transfer __bridge_retained __bridge_retain __covariant __contravariant __kindof _Nonnull _Nullable _Null_unspecified __FUNCTION__ __PRETTY_FUNCTION__ __attribute__ getter setter retain unsafe_unretained nonnull nullable null_unspecified null_resettable class instancetype NS_DESIGNATED_INITIALIZER NS_UNAVAILABLE NS_REQUIRES_SUPER NS_RETURNS_INNER_POINTER NS_INLINE NS_AVAILABLE NS_DEPRECATED NS_ENUM NS_OPTIONS NS_SWIFT_UNAVAILABLE NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_END NS_REFINED_FOR_SWIFT NS_SWIFT_NAME NS_SWIFT_NOTHROW NS_DURING NS_HANDLER NS_ENDHANDLER NS_VALUERETURN NS_VOIDRETURN",literal:"false true FALSE TRUE nil YES NO NULL",built_in:"BOOL dispatch_once_t dispatch_queue_t dispatch_sync dispatch_async dispatch_once"},illegal:"/,end:/$/,illegal:"\\n"},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{className:"class",begin:"("+_.keyword.split(" ").join("|")+")\\b",end:"({|$)",excludeEnd:!0,keywords:_,contains:[e.UNDERSCORE_TITLE_MODE]},{begin:"\\."+e.UNDERSCORE_IDENT_RE,relevance:0}]}}}()); +hljs.registerLanguage("perl",function(){"use strict";return function(e){var n={$pattern:/[\w.]+/,keyword:"getpwent getservent quotemeta msgrcv scalar kill dbmclose undef lc ma syswrite tr send umask sysopen shmwrite vec qx utime local oct semctl localtime readpipe do return format read sprintf dbmopen pop getpgrp not getpwnam rewinddir qq fileno qw endprotoent wait sethostent bless s|0 opendir continue each sleep endgrent shutdown dump chomp connect getsockname die socketpair close flock exists index shmget sub for endpwent redo lstat msgctl setpgrp abs exit select print ref gethostbyaddr unshift fcntl syscall goto getnetbyaddr join gmtime symlink semget splice x|0 getpeername recv log setsockopt cos last reverse gethostbyname getgrnam study formline endhostent times chop length gethostent getnetent pack getprotoent getservbyname rand mkdir pos chmod y|0 substr endnetent printf next open msgsnd readdir use unlink getsockopt getpriority rindex wantarray hex system getservbyport endservent int chr untie rmdir prototype tell listen fork shmread ucfirst setprotoent else sysseek link getgrgid shmctl waitpid unpack getnetbyname reset chdir grep split require caller lcfirst until warn while values shift telldir getpwuid my getprotobynumber delete and sort uc defined srand accept package seekdir getprotobyname semop our rename seek if q|0 chroot sysread setpwent no crypt getc chown sqrt write setnetent setpriority foreach tie sin msgget map stat getlogin unless elsif truncate exec keys glob tied closedir ioctl socket readlink eval xor readline binmode setservent eof ord bind alarm pipe atan2 getgrent exp time push setgrent gt lt or ne m|0 break given say state when"},t={className:"subst",begin:"[$@]\\{",end:"\\}",keywords:n},s={begin:"->{",end:"}"},r={variants:[{begin:/\$\d/},{begin:/[\$%@](\^\w\b|#\w+(::\w+)*|{\w+}|\w+(::\w*)*)/},{begin:/[\$%@][^\s\w{]/,relevance:0}]},i=[e.BACKSLASH_ESCAPE,t,r],a=[r,e.HASH_COMMENT_MODE,e.COMMENT("^\\=\\w","\\=cut",{endsWithParent:!0}),s,{className:"string",contains:i,variants:[{begin:"q[qwxr]?\\s*\\(",end:"\\)",relevance:5},{begin:"q[qwxr]?\\s*\\[",end:"\\]",relevance:5},{begin:"q[qwxr]?\\s*\\{",end:"\\}",relevance:5},{begin:"q[qwxr]?\\s*\\|",end:"\\|",relevance:5},{begin:"q[qwxr]?\\s*\\<",end:"\\>",relevance:5},{begin:"qw\\s+q",end:"q",relevance:5},{begin:"'",end:"'",contains:[e.BACKSLASH_ESCAPE]},{begin:'"',end:'"'},{begin:"`",end:"`",contains:[e.BACKSLASH_ESCAPE]},{begin:"{\\w+}",contains:[],relevance:0},{begin:"-?\\w+\\s*\\=\\>",contains:[],relevance:0}]},{className:"number",begin:"(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b",relevance:0},{begin:"(\\/\\/|"+e.RE_STARTERS_RE+"|\\b(split|return|print|reverse|grep)\\b)\\s*",keywords:"split return print reverse grep",relevance:0,contains:[e.HASH_COMMENT_MODE,{className:"regexp",begin:"(s|tr|y)/(\\\\.|[^/])*/(\\\\.|[^/])*/[a-z]*",relevance:10},{className:"regexp",begin:"(m|qr)?/",end:"/[a-z]*",contains:[e.BACKSLASH_ESCAPE],relevance:0}]},{className:"function",beginKeywords:"sub",end:"(\\s*\\(.*?\\))?[;{]",excludeEnd:!0,relevance:5,contains:[e.TITLE_MODE]},{begin:"-\\w\\b",relevance:0},{begin:"^__DATA__$",end:"^__END__$",subLanguage:"mojolicious",contains:[{begin:"^@@.*",end:"$",className:"comment"}]}];return t.contains=a,s.contains=a,{name:"Perl",aliases:["pl","pm"],keywords:n,contains:a}}}()); +hljs.registerLanguage("php",function(){"use strict";return function(e){var r={begin:"\\$+[a-zA-Z_-ÿ][a-zA-Z0-9_-ÿ]*"},t={className:"meta",variants:[{begin:/<\?php/,relevance:10},{begin:/<\?[=]?/},{begin:/\?>/}]},a={className:"string",contains:[e.BACKSLASH_ESCAPE,t],variants:[{begin:'b"',end:'"'},{begin:"b'",end:"'"},e.inherit(e.APOS_STRING_MODE,{illegal:null}),e.inherit(e.QUOTE_STRING_MODE,{illegal:null})]},n={variants:[e.BINARY_NUMBER_MODE,e.C_NUMBER_MODE]},i={keyword:"__CLASS__ __DIR__ __FILE__ __FUNCTION__ __LINE__ __METHOD__ __NAMESPACE__ __TRAIT__ die echo exit include include_once print require require_once array abstract and as binary bool boolean break callable case catch class clone const continue declare default do double else elseif empty enddeclare endfor endforeach endif endswitch endwhile eval extends final finally float for foreach from global goto if implements instanceof insteadof int integer interface isset iterable list new object or private protected public real return string switch throw trait try unset use var void while xor yield",literal:"false null true",built_in:"Error|0 AppendIterator ArgumentCountError ArithmeticError ArrayIterator ArrayObject AssertionError BadFunctionCallException BadMethodCallException CachingIterator CallbackFilterIterator CompileError Countable DirectoryIterator DivisionByZeroError DomainException EmptyIterator ErrorException Exception FilesystemIterator FilterIterator GlobIterator InfiniteIterator InvalidArgumentException IteratorIterator LengthException LimitIterator LogicException MultipleIterator NoRewindIterator OutOfBoundsException OutOfRangeException OuterIterator OverflowException ParentIterator ParseError RangeException RecursiveArrayIterator RecursiveCachingIterator RecursiveCallbackFilterIterator RecursiveDirectoryIterator RecursiveFilterIterator RecursiveIterator RecursiveIteratorIterator RecursiveRegexIterator RecursiveTreeIterator RegexIterator RuntimeException SeekableIterator SplDoublyLinkedList SplFileInfo SplFileObject SplFixedArray SplHeap SplMaxHeap SplMinHeap SplObjectStorage SplObserver SplObserver SplPriorityQueue SplQueue SplStack SplSubject SplSubject SplTempFileObject TypeError UnderflowException UnexpectedValueException ArrayAccess Closure Generator Iterator IteratorAggregate Serializable Throwable Traversable WeakReference Directory __PHP_Incomplete_Class parent php_user_filter self static stdClass"};return{aliases:["php","php3","php4","php5","php6","php7"],case_insensitive:!0,keywords:i,contains:[e.HASH_COMMENT_MODE,e.COMMENT("//","$",{contains:[t]}),e.COMMENT("/\\*","\\*/",{contains:[{className:"doctag",begin:"@[A-Za-z]+"}]}),e.COMMENT("__halt_compiler.+?;",!1,{endsWithParent:!0,keywords:"__halt_compiler"}),{className:"string",begin:/<<<['"]?\w+['"]?$/,end:/^\w+;?$/,contains:[e.BACKSLASH_ESCAPE,{className:"subst",variants:[{begin:/\$\w+/},{begin:/\{\$/,end:/\}/}]}]},t,{className:"keyword",begin:/\$this\b/},r,{begin:/(::|->)+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/},{className:"function",beginKeywords:"fn function",end:/[;{]/,excludeEnd:!0,illegal:"[$%\\[]",contains:[e.UNDERSCORE_TITLE_MODE,{className:"params",begin:"\\(",end:"\\)",excludeBegin:!0,excludeEnd:!0,keywords:i,contains:["self",r,e.C_BLOCK_COMMENT_MODE,a,n]}]},{className:"class",beginKeywords:"class interface",end:"{",excludeEnd:!0,illegal:/[:\(\$"]/,contains:[{beginKeywords:"extends implements"},e.UNDERSCORE_TITLE_MODE]},{beginKeywords:"namespace",end:";",illegal:/[\.']/,contains:[e.UNDERSCORE_TITLE_MODE]},{beginKeywords:"use",end:";",contains:[e.UNDERSCORE_TITLE_MODE]},{begin:"=>"},a,n]}}}()); +hljs.registerLanguage("php-template",function(){"use strict";return function(n){return{name:"PHP template",subLanguage:"xml",contains:[{begin:/<\?(php|=)?/,end:/\?>/,subLanguage:"php",contains:[{begin:"/\\*",end:"\\*/",skip:!0},{begin:'b"',end:'"',skip:!0},{begin:"b'",end:"'",skip:!0},n.inherit(n.APOS_STRING_MODE,{illegal:null,className:null,contains:null,skip:!0}),n.inherit(n.QUOTE_STRING_MODE,{illegal:null,className:null,contains:null,skip:!0})]}]}}}()); +hljs.registerLanguage("plaintext",function(){"use strict";return function(t){return{name:"Plain text",aliases:["text","txt"],disableAutodetect:!0}}}()); +hljs.registerLanguage("properties",function(){"use strict";return function(e){var n="[ \\t\\f]*",t="("+n+"[:=]"+n+"|[ \\t\\f]+)",a="([^\\\\:= \\t\\f\\n]|\\\\.)+",s={end:t,relevance:0,starts:{className:"string",end:/$/,relevance:0,contains:[{begin:"\\\\\\n"}]}};return{name:".properties",case_insensitive:!0,illegal:/\S/,contains:[e.COMMENT("^\\s*[!#]","$"),{begin:"([^\\\\\\W:= \\t\\f\\n]|\\\\.)+"+t,returnBegin:!0,contains:[{className:"attr",begin:"([^\\\\\\W:= \\t\\f\\n]|\\\\.)+",endsParent:!0,relevance:0}],starts:s},{begin:a+t,returnBegin:!0,relevance:0,contains:[{className:"meta",begin:a,endsParent:!0,relevance:0}],starts:s},{className:"attr",relevance:0,begin:a+n+"$"}]}}}()); +hljs.registerLanguage("python",function(){"use strict";return function(e){var n={keyword:"and elif is global as in if from raise for except finally print import pass return exec else break not with class assert yield try while continue del or def lambda async await nonlocal|10",built_in:"Ellipsis NotImplemented",literal:"False None True"},a={className:"meta",begin:/^(>>>|\.\.\.) /},i={className:"subst",begin:/\{/,end:/\}/,keywords:n,illegal:/#/},s={begin:/\{\{/,relevance:0},r={className:"string",contains:[e.BACKSLASH_ESCAPE],variants:[{begin:/(u|b)?r?'''/,end:/'''/,contains:[e.BACKSLASH_ESCAPE,a],relevance:10},{begin:/(u|b)?r?"""/,end:/"""/,contains:[e.BACKSLASH_ESCAPE,a],relevance:10},{begin:/(fr|rf|f)'''/,end:/'''/,contains:[e.BACKSLASH_ESCAPE,a,s,i]},{begin:/(fr|rf|f)"""/,end:/"""/,contains:[e.BACKSLASH_ESCAPE,a,s,i]},{begin:/(u|r|ur)'/,end:/'/,relevance:10},{begin:/(u|r|ur)"/,end:/"/,relevance:10},{begin:/(b|br)'/,end:/'/},{begin:/(b|br)"/,end:/"/},{begin:/(fr|rf|f)'/,end:/'/,contains:[e.BACKSLASH_ESCAPE,s,i]},{begin:/(fr|rf|f)"/,end:/"/,contains:[e.BACKSLASH_ESCAPE,s,i]},e.APOS_STRING_MODE,e.QUOTE_STRING_MODE]},l={className:"number",relevance:0,variants:[{begin:e.BINARY_NUMBER_RE+"[lLjJ]?"},{begin:"\\b(0o[0-7]+)[lLjJ]?"},{begin:e.C_NUMBER_RE+"[lLjJ]?"}]},t={className:"params",variants:[{begin:/\(\s*\)/,skip:!0,className:null},{begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,contains:["self",a,l,r,e.HASH_COMMENT_MODE]}]};return i.contains=[r,l,a],{name:"Python",aliases:["py","gyp","ipython"],keywords:n,illegal:/(<\/|->|\?)|=>/,contains:[a,l,{beginKeywords:"if",relevance:0},r,e.HASH_COMMENT_MODE,{variants:[{className:"function",beginKeywords:"def"},{className:"class",beginKeywords:"class"}],end:/:/,illegal:/[${=;\n,]/,contains:[e.UNDERSCORE_TITLE_MODE,t,{begin:/->/,endsWithParent:!0,keywords:"None"}]},{className:"meta",begin:/^[\t ]*@/,end:/$/},{begin:/\b(print|exec)\(/}]}}}()); +hljs.registerLanguage("python-repl",function(){"use strict";return function(n){return{aliases:["pycon"],contains:[{className:"meta",starts:{end:/ |$/,starts:{end:"$",subLanguage:"python"}},variants:[{begin:/^>>>(?=[ ]|$)/},{begin:/^\.\.\.(?=[ ]|$)/}]}]}}}()); +hljs.registerLanguage("ruby",function(){"use strict";return function(e){var n="[a-zA-Z_]\\w*[!?=]?|[-+~]\\@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?",a={keyword:"and then defined module in return redo if BEGIN retry end for self when next until do begin unless END rescue else break undef not super class case require yield alias while ensure elsif or include attr_reader attr_writer attr_accessor",literal:"true false nil"},s={className:"doctag",begin:"@[A-Za-z]+"},i={begin:"#<",end:">"},r=[e.COMMENT("#","$",{contains:[s]}),e.COMMENT("^\\=begin","^\\=end",{contains:[s],relevance:10}),e.COMMENT("^__END__","\\n$")],c={className:"subst",begin:"#\\{",end:"}",keywords:a},t={className:"string",contains:[e.BACKSLASH_ESCAPE,c],variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/`/,end:/`/},{begin:"%[qQwWx]?\\(",end:"\\)"},{begin:"%[qQwWx]?\\[",end:"\\]"},{begin:"%[qQwWx]?{",end:"}"},{begin:"%[qQwWx]?<",end:">"},{begin:"%[qQwWx]?/",end:"/"},{begin:"%[qQwWx]?%",end:"%"},{begin:"%[qQwWx]?-",end:"-"},{begin:"%[qQwWx]?\\|",end:"\\|"},{begin:/\B\?(\\\d{1,3}|\\x[A-Fa-f0-9]{1,2}|\\u[A-Fa-f0-9]{4}|\\?\S)\b/},{begin:/<<[-~]?'?(\w+)(?:.|\n)*?\n\s*\1\b/,returnBegin:!0,contains:[{begin:/<<[-~]?'?/},e.END_SAME_AS_BEGIN({begin:/(\w+)/,end:/(\w+)/,contains:[e.BACKSLASH_ESCAPE,c]})]}]},b={className:"params",begin:"\\(",end:"\\)",endsParent:!0,keywords:a},d=[t,i,{className:"class",beginKeywords:"class module",end:"$|;",illegal:/=/,contains:[e.inherit(e.TITLE_MODE,{begin:"[A-Za-z_]\\w*(::\\w+)*(\\?|\\!)?"}),{begin:"<\\s*",contains:[{begin:"("+e.IDENT_RE+"::)?"+e.IDENT_RE}]}].concat(r)},{className:"function",beginKeywords:"def",end:"$|;",contains:[e.inherit(e.TITLE_MODE,{begin:n}),b].concat(r)},{begin:e.IDENT_RE+"::"},{className:"symbol",begin:e.UNDERSCORE_IDENT_RE+"(\\!|\\?)?:",relevance:0},{className:"symbol",begin:":(?!\\s)",contains:[t,{begin:n}],relevance:0},{className:"number",begin:"(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b",relevance:0},{begin:"(\\$\\W)|((\\$|\\@\\@?)(\\w+))"},{className:"params",begin:/\|/,end:/\|/,keywords:a},{begin:"("+e.RE_STARTERS_RE+"|unless)\\s*",keywords:"unless",contains:[i,{className:"regexp",contains:[e.BACKSLASH_ESCAPE,c],illegal:/\n/,variants:[{begin:"/",end:"/[a-z]*"},{begin:"%r{",end:"}[a-z]*"},{begin:"%r\\(",end:"\\)[a-z]*"},{begin:"%r!",end:"![a-z]*"},{begin:"%r\\[",end:"\\][a-z]*"}]}].concat(r),relevance:0}].concat(r);c.contains=d,b.contains=d;var g=[{begin:/^\s*=>/,starts:{end:"$",contains:d}},{className:"meta",begin:"^([>?]>|[\\w#]+\\(\\w+\\):\\d+:\\d+>|(\\w+-)?\\d+\\.\\d+\\.\\d(p\\d+)?[^>]+>)",starts:{end:"$",contains:d}}];return{name:"Ruby",aliases:["rb","gemspec","podspec","thor","irb"],keywords:a,illegal:/\/\*/,contains:r.concat(g).concat(d)}}}()); +hljs.registerLanguage("rust",function(){"use strict";return function(e){var n="([ui](8|16|32|64|128|size)|f(32|64))?",t="drop i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize f32 f64 str char bool Box Option Result String Vec Copy Send Sized Sync Drop Fn FnMut FnOnce ToOwned Clone Debug PartialEq PartialOrd Eq Ord AsRef AsMut Into From Default Iterator Extend IntoIterator DoubleEndedIterator ExactSizeIterator SliceConcatExt ToString assert! assert_eq! bitflags! bytes! cfg! col! concat! concat_idents! debug_assert! debug_assert_eq! env! panic! file! format! format_args! include_bin! include_str! line! local_data_key! module_path! option_env! print! println! select! stringify! try! unimplemented! unreachable! vec! write! writeln! macro_rules! assert_ne! debug_assert_ne!";return{name:"Rust",aliases:["rs"],keywords:{$pattern:e.IDENT_RE+"!?",keyword:"abstract as async await become box break const continue crate do dyn else enum extern false final fn for if impl in let loop macro match mod move mut override priv pub ref return self Self static struct super trait true try type typeof unsafe unsized use virtual where while yield",literal:"true false Some None Ok Err",built_in:t},illegal:""}]}}}()); +hljs.registerLanguage("scss",function(){"use strict";return function(e){var t={className:"variable",begin:"(\\$[a-zA-Z-][a-zA-Z0-9_-]*)\\b"},i={className:"number",begin:"#[0-9A-Fa-f]+"};return e.CSS_NUMBER_MODE,e.QUOTE_STRING_MODE,e.APOS_STRING_MODE,e.C_BLOCK_COMMENT_MODE,{name:"SCSS",case_insensitive:!0,illegal:"[=/|']",contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,{className:"selector-id",begin:"\\#[A-Za-z0-9_-]+",relevance:0},{className:"selector-class",begin:"\\.[A-Za-z0-9_-]+",relevance:0},{className:"selector-attr",begin:"\\[",end:"\\]",illegal:"$"},{className:"selector-tag",begin:"\\b(a|abbr|acronym|address|area|article|aside|audio|b|base|big|blockquote|body|br|button|canvas|caption|cite|code|col|colgroup|command|datalist|dd|del|details|dfn|div|dl|dt|em|embed|fieldset|figcaption|figure|footer|form|frame|frameset|(h[1-6])|head|header|hgroup|hr|html|i|iframe|img|input|ins|kbd|keygen|label|legend|li|link|map|mark|meta|meter|nav|noframes|noscript|object|ol|optgroup|option|output|p|param|pre|progress|q|rp|rt|ruby|samp|script|section|select|small|span|strike|strong|style|sub|sup|table|tbody|td|textarea|tfoot|th|thead|time|title|tr|tt|ul|var|video)\\b",relevance:0},{className:"selector-pseudo",begin:":(visited|valid|root|right|required|read-write|read-only|out-range|optional|only-of-type|only-child|nth-of-type|nth-last-of-type|nth-last-child|nth-child|not|link|left|last-of-type|last-child|lang|invalid|indeterminate|in-range|hover|focus|first-of-type|first-line|first-letter|first-child|first|enabled|empty|disabled|default|checked|before|after|active)"},{className:"selector-pseudo",begin:"::(after|before|choices|first-letter|first-line|repeat-index|repeat-item|selection|value)"},t,{className:"attribute",begin:"\\b(src|z-index|word-wrap|word-spacing|word-break|width|widows|white-space|visibility|vertical-align|unicode-bidi|transition-timing-function|transition-property|transition-duration|transition-delay|transition|transform-style|transform-origin|transform|top|text-underline-position|text-transform|text-shadow|text-rendering|text-overflow|text-indent|text-decoration-style|text-decoration-line|text-decoration-color|text-decoration|text-align-last|text-align|tab-size|table-layout|right|resize|quotes|position|pointer-events|perspective-origin|perspective|page-break-inside|page-break-before|page-break-after|padding-top|padding-right|padding-left|padding-bottom|padding|overflow-y|overflow-x|overflow-wrap|overflow|outline-width|outline-style|outline-offset|outline-color|outline|orphans|order|opacity|object-position|object-fit|normal|none|nav-up|nav-right|nav-left|nav-index|nav-down|min-width|min-height|max-width|max-height|mask|marks|margin-top|margin-right|margin-left|margin-bottom|margin|list-style-type|list-style-position|list-style-image|list-style|line-height|letter-spacing|left|justify-content|initial|inherit|ime-mode|image-orientation|image-resolution|image-rendering|icon|hyphens|height|font-weight|font-variant-ligatures|font-variant|font-style|font-stretch|font-size-adjust|font-size|font-language-override|font-kerning|font-feature-settings|font-family|font|float|flex-wrap|flex-shrink|flex-grow|flex-flow|flex-direction|flex-basis|flex|filter|empty-cells|display|direction|cursor|counter-reset|counter-increment|content|column-width|column-span|column-rule-width|column-rule-style|column-rule-color|column-rule|column-gap|column-fill|column-count|columns|color|clip-path|clip|clear|caption-side|break-inside|break-before|break-after|box-sizing|box-shadow|box-decoration-break|bottom|border-width|border-top-width|border-top-style|border-top-right-radius|border-top-left-radius|border-top-color|border-top|border-style|border-spacing|border-right-width|border-right-style|border-right-color|border-right|border-radius|border-left-width|border-left-style|border-left-color|border-left|border-image-width|border-image-source|border-image-slice|border-image-repeat|border-image-outset|border-image|border-color|border-collapse|border-bottom-width|border-bottom-style|border-bottom-right-radius|border-bottom-left-radius|border-bottom-color|border-bottom|border|background-size|background-repeat|background-position|background-origin|background-image|background-color|background-clip|background-attachment|background-blend-mode|background|backface-visibility|auto|animation-timing-function|animation-play-state|animation-name|animation-iteration-count|animation-fill-mode|animation-duration|animation-direction|animation-delay|animation|align-self|align-items|align-content)\\b",illegal:"[^\\s]"},{begin:"\\b(whitespace|wait|w-resize|visible|vertical-text|vertical-ideographic|uppercase|upper-roman|upper-alpha|underline|transparent|top|thin|thick|text|text-top|text-bottom|tb-rl|table-header-group|table-footer-group|sw-resize|super|strict|static|square|solid|small-caps|separate|se-resize|scroll|s-resize|rtl|row-resize|ridge|right|repeat|repeat-y|repeat-x|relative|progress|pointer|overline|outside|outset|oblique|nowrap|not-allowed|normal|none|nw-resize|no-repeat|no-drop|newspaper|ne-resize|n-resize|move|middle|medium|ltr|lr-tb|lowercase|lower-roman|lower-alpha|loose|list-item|line|line-through|line-edge|lighter|left|keep-all|justify|italic|inter-word|inter-ideograph|inside|inset|inline|inline-block|inherit|inactive|ideograph-space|ideograph-parenthesis|ideograph-numeric|ideograph-alpha|horizontal|hidden|help|hand|groove|fixed|ellipsis|e-resize|double|dotted|distribute|distribute-space|distribute-letter|distribute-all-lines|disc|disabled|default|decimal|dashed|crosshair|collapse|col-resize|circle|char|center|capitalize|break-word|break-all|bottom|both|bolder|bold|block|bidi-override|below|baseline|auto|always|all-scroll|absolute|table|table-cell)\\b"},{begin:":",end:";",contains:[t,i,e.CSS_NUMBER_MODE,e.QUOTE_STRING_MODE,e.APOS_STRING_MODE,{className:"meta",begin:"!important"}]},{begin:"@(page|font-face)",lexemes:"@[a-z-]+",keywords:"@page @font-face"},{begin:"@",end:"[{;]",returnBegin:!0,keywords:"and or not only",contains:[{begin:"@[a-z-]+",className:"keyword"},t,e.QUOTE_STRING_MODE,e.APOS_STRING_MODE,i,e.CSS_NUMBER_MODE]}]}}}()); +hljs.registerLanguage("shell",function(){"use strict";return function(s){return{name:"Shell Session",aliases:["console"],contains:[{className:"meta",begin:"^\\s{0,3}[/\\w\\d\\[\\]()@-]*[>%$#]",starts:{end:"$",subLanguage:"bash"}}]}}}()); +hljs.registerLanguage("sql",function(){"use strict";return function(e){var t=e.COMMENT("--","$");return{name:"SQL",case_insensitive:!0,illegal:/[<>{}*]/,contains:[{beginKeywords:"begin end start commit rollback savepoint lock alter create drop rename call delete do handler insert load replace select truncate update set show pragma grant merge describe use explain help declare prepare execute deallocate release unlock purge reset change stop analyze cache flush optimize repair kill install uninstall checksum restore check backup revoke comment values with",end:/;/,endsWithParent:!0,keywords:{$pattern:/[\w\.]+/,keyword:"as abort abs absolute acc acce accep accept access accessed accessible account acos action activate add addtime admin administer advanced advise aes_decrypt aes_encrypt after agent aggregate ali alia alias all allocate allow alter always analyze ancillary and anti any anydata anydataset anyschema anytype apply archive archived archivelog are as asc ascii asin assembly assertion associate asynchronous at atan atn2 attr attri attrib attribu attribut attribute attributes audit authenticated authentication authid authors auto autoallocate autodblink autoextend automatic availability avg backup badfile basicfile before begin beginning benchmark between bfile bfile_base big bigfile bin binary_double binary_float binlog bit_and bit_count bit_length bit_or bit_xor bitmap blob_base block blocksize body both bound bucket buffer_cache buffer_pool build bulk by byte byteordermark bytes cache caching call calling cancel capacity cascade cascaded case cast catalog category ceil ceiling chain change changed char_base char_length character_length characters characterset charindex charset charsetform charsetid check checksum checksum_agg child choose chr chunk class cleanup clear client clob clob_base clone close cluster_id cluster_probability cluster_set clustering coalesce coercibility col collate collation collect colu colum column column_value columns columns_updated comment commit compact compatibility compiled complete composite_limit compound compress compute concat concat_ws concurrent confirm conn connec connect connect_by_iscycle connect_by_isleaf connect_by_root connect_time connection consider consistent constant constraint constraints constructor container content contents context contributors controlfile conv convert convert_tz corr corr_k corr_s corresponding corruption cos cost count count_big counted covar_pop covar_samp cpu_per_call cpu_per_session crc32 create creation critical cross cube cume_dist curdate current current_date current_time current_timestamp current_user cursor curtime customdatum cycle data database databases datafile datafiles datalength date_add date_cache date_format date_sub dateadd datediff datefromparts datename datepart datetime2fromparts day day_to_second dayname dayofmonth dayofweek dayofyear days db_role_change dbtimezone ddl deallocate declare decode decompose decrement decrypt deduplicate def defa defau defaul default defaults deferred defi defin define degrees delayed delegate delete delete_all delimited demand dense_rank depth dequeue des_decrypt des_encrypt des_key_file desc descr descri describ describe descriptor deterministic diagnostics difference dimension direct_load directory disable disable_all disallow disassociate discardfile disconnect diskgroup distinct distinctrow distribute distributed div do document domain dotnet double downgrade drop dumpfile duplicate duration each edition editionable editions element ellipsis else elsif elt empty enable enable_all enclosed encode encoding encrypt end end-exec endian enforced engine engines enqueue enterprise entityescaping eomonth error errors escaped evalname evaluate event eventdata events except exception exceptions exchange exclude excluding execu execut execute exempt exists exit exp expire explain explode export export_set extended extent external external_1 external_2 externally extract failed failed_login_attempts failover failure far fast feature_set feature_value fetch field fields file file_name_convert filesystem_like_logging final finish first first_value fixed flash_cache flashback floor flush following follows for forall force foreign form forma format found found_rows freelist freelists freepools fresh from from_base64 from_days ftp full function general generated get get_format get_lock getdate getutcdate global global_name globally go goto grant grants greatest group group_concat group_id grouping grouping_id groups gtid_subtract guarantee guard handler hash hashkeys having hea head headi headin heading heap help hex hierarchy high high_priority hosts hour hours http id ident_current ident_incr ident_seed identified identity idle_time if ifnull ignore iif ilike ilm immediate import in include including increment index indexes indexing indextype indicator indices inet6_aton inet6_ntoa inet_aton inet_ntoa infile initial initialized initially initrans inmemory inner innodb input insert install instance instantiable instr interface interleaved intersect into invalidate invisible is is_free_lock is_ipv4 is_ipv4_compat is_not is_not_null is_used_lock isdate isnull isolation iterate java join json json_exists keep keep_duplicates key keys kill language large last last_day last_insert_id last_value lateral lax lcase lead leading least leaves left len lenght length less level levels library like like2 like4 likec limit lines link list listagg little ln load load_file lob lobs local localtime localtimestamp locate locator lock locked log log10 log2 logfile logfiles logging logical logical_reads_per_call logoff logon logs long loop low low_priority lower lpad lrtrim ltrim main make_set makedate maketime managed management manual map mapping mask master master_pos_wait match matched materialized max maxextents maximize maxinstances maxlen maxlogfiles maxloghistory maxlogmembers maxsize maxtrans md5 measures median medium member memcompress memory merge microsecond mid migration min minextents minimum mining minus minute minutes minvalue missing mod mode model modification modify module monitoring month months mount move movement multiset mutex name name_const names nan national native natural nav nchar nclob nested never new newline next nextval no no_write_to_binlog noarchivelog noaudit nobadfile nocheck nocompress nocopy nocycle nodelay nodiscardfile noentityescaping noguarantee nokeep nologfile nomapping nomaxvalue nominimize nominvalue nomonitoring none noneditionable nonschema noorder nopr nopro noprom nopromp noprompt norely noresetlogs noreverse normal norowdependencies noschemacheck noswitch not nothing notice notnull notrim novalidate now nowait nth_value nullif nulls num numb numbe nvarchar nvarchar2 object ocicoll ocidate ocidatetime ociduration ociinterval ociloblocator ocinumber ociref ocirefcursor ocirowid ocistring ocitype oct octet_length of off offline offset oid oidindex old on online only opaque open operations operator optimal optimize option optionally or oracle oracle_date oradata ord ordaudio orddicom orddoc order ordimage ordinality ordvideo organization orlany orlvary out outer outfile outline output over overflow overriding package pad parallel parallel_enable parameters parent parse partial partition partitions pascal passing password password_grace_time password_lock_time password_reuse_max password_reuse_time password_verify_function patch path patindex pctincrease pctthreshold pctused pctversion percent percent_rank percentile_cont percentile_disc performance period period_add period_diff permanent physical pi pipe pipelined pivot pluggable plugin policy position post_transaction pow power pragma prebuilt precedes preceding precision prediction prediction_cost prediction_details prediction_probability prediction_set prepare present preserve prior priority private private_sga privileges procedural procedure procedure_analyze processlist profiles project prompt protection public publishingservername purge quarter query quick quiesce quota quotename radians raise rand range rank raw read reads readsize rebuild record records recover recovery recursive recycle redo reduced ref reference referenced references referencing refresh regexp_like register regr_avgx regr_avgy regr_count regr_intercept regr_r2 regr_slope regr_sxx regr_sxy reject rekey relational relative relaylog release release_lock relies_on relocate rely rem remainder rename repair repeat replace replicate replication required reset resetlogs resize resource respect restore restricted result result_cache resumable resume retention return returning returns reuse reverse revoke right rlike role roles rollback rolling rollup round row row_count rowdependencies rowid rownum rows rtrim rules safe salt sample save savepoint sb1 sb2 sb4 scan schema schemacheck scn scope scroll sdo_georaster sdo_topo_geometry search sec_to_time second seconds section securefile security seed segment select self semi sequence sequential serializable server servererror session session_user sessions_per_user set sets settings sha sha1 sha2 share shared shared_pool short show shrink shutdown si_averagecolor si_colorhistogram si_featurelist si_positionalcolor si_stillimage si_texture siblings sid sign sin size size_t sizes skip slave sleep smalldatetimefromparts smallfile snapshot some soname sort soundex source space sparse spfile split sql sql_big_result sql_buffer_result sql_cache sql_calc_found_rows sql_small_result sql_variant_property sqlcode sqldata sqlerror sqlname sqlstate sqrt square standalone standby start starting startup statement static statistics stats_binomial_test stats_crosstab stats_ks_test stats_mode stats_mw_test stats_one_way_anova stats_t_test_ stats_t_test_indep stats_t_test_one stats_t_test_paired stats_wsr_test status std stddev stddev_pop stddev_samp stdev stop storage store stored str str_to_date straight_join strcmp strict string struct stuff style subdate subpartition subpartitions substitutable substr substring subtime subtring_index subtype success sum suspend switch switchoffset switchover sync synchronous synonym sys sys_xmlagg sysasm sysaux sysdate sysdatetimeoffset sysdba sysoper system system_user sysutcdatetime table tables tablespace tablesample tan tdo template temporary terminated tertiary_weights test than then thread through tier ties time time_format time_zone timediff timefromparts timeout timestamp timestampadd timestampdiff timezone_abbr timezone_minute timezone_region to to_base64 to_date to_days to_seconds todatetimeoffset trace tracking transaction transactional translate translation treat trigger trigger_nestlevel triggers trim truncate try_cast try_convert try_parse type ub1 ub2 ub4 ucase unarchived unbounded uncompress under undo unhex unicode uniform uninstall union unique unix_timestamp unknown unlimited unlock unnest unpivot unrecoverable unsafe unsigned until untrusted unusable unused update updated upgrade upped upper upsert url urowid usable usage use use_stored_outlines user user_data user_resources users using utc_date utc_timestamp uuid uuid_short validate validate_password_strength validation valist value values var var_samp varcharc vari varia variab variabl variable variables variance varp varraw varrawc varray verify version versions view virtual visible void wait wallet warning warnings week weekday weekofyear wellformed when whene whenev wheneve whenever where while whitespace window with within without work wrapped xdb xml xmlagg xmlattributes xmlcast xmlcolattval xmlelement xmlexists xmlforest xmlindex xmlnamespaces xmlpi xmlquery xmlroot xmlschema xmlserialize xmltable xmltype xor year year_to_month years yearweek",literal:"true false null unknown",built_in:"array bigint binary bit blob bool boolean char character date dec decimal float int int8 integer interval number numeric real record serial serial8 smallint text time timestamp tinyint varchar varchar2 varying void"},contains:[{className:"string",begin:"'",end:"'",contains:[{begin:"''"}]},{className:"string",begin:'"',end:'"',contains:[{begin:'""'}]},{className:"string",begin:"`",end:"`"},e.C_NUMBER_MODE,e.C_BLOCK_COMMENT_MODE,t,e.HASH_COMMENT_MODE]},e.C_BLOCK_COMMENT_MODE,t,e.HASH_COMMENT_MODE]}}}()); +hljs.registerLanguage("swift",function(){"use strict";return function(e){var i={keyword:"#available #colorLiteral #column #else #elseif #endif #file #fileLiteral #function #if #imageLiteral #line #selector #sourceLocation _ __COLUMN__ __FILE__ __FUNCTION__ __LINE__ Any as as! as? associatedtype associativity break case catch class continue convenience default defer deinit didSet do dynamic dynamicType else enum extension fallthrough false fileprivate final for func get guard if import in indirect infix init inout internal is lazy left let mutating nil none nonmutating open operator optional override postfix precedence prefix private protocol Protocol public repeat required rethrows return right self Self set static struct subscript super switch throw throws true try try! try? Type typealias unowned var weak where while willSet",literal:"true false nil",built_in:"abs advance alignof alignofValue anyGenerator assert assertionFailure bridgeFromObjectiveC bridgeFromObjectiveCUnconditional bridgeToObjectiveC bridgeToObjectiveCUnconditional c compactMap contains count countElements countLeadingZeros debugPrint debugPrintln distance dropFirst dropLast dump encodeBitsAsWords enumerate equal fatalError filter find getBridgedObjectiveCType getVaList indices insertionSort isBridgedToObjectiveC isBridgedVerbatimToObjectiveC isUniquelyReferenced isUniquelyReferencedNonObjC join lazy lexicographicalCompare map max maxElement min minElement numericCast overlaps partition posix precondition preconditionFailure print println quickSort readLine reduce reflect reinterpretCast reverse roundUpToAlignment sizeof sizeofValue sort split startsWith stride strideof strideofValue swap toString transcode underestimateCount unsafeAddressOf unsafeBitCast unsafeDowncast unsafeUnwrap unsafeReflect withExtendedLifetime withObjectAtPlusZero withUnsafePointer withUnsafePointerToObject withUnsafeMutablePointer withUnsafeMutablePointers withUnsafePointer withUnsafePointers withVaList zip"},n=e.COMMENT("/\\*","\\*/",{contains:["self"]}),t={className:"subst",begin:/\\\(/,end:"\\)",keywords:i,contains:[]},a={className:"string",contains:[e.BACKSLASH_ESCAPE,t],variants:[{begin:/"""/,end:/"""/},{begin:/"/,end:/"/}]},r={className:"number",begin:"\\b([\\d_]+(\\.[\\deE_]+)?|0x[a-fA-F0-9_]+(\\.[a-fA-F0-9p_]+)?|0b[01_]+|0o[0-7_]+)\\b",relevance:0};return t.contains=[r],{name:"Swift",keywords:i,contains:[a,e.C_LINE_COMMENT_MODE,n,{className:"type",begin:"\\b[A-Z][\\wÀ-ʸ']*[!?]"},{className:"type",begin:"\\b[A-Z][\\wÀ-ʸ']*",relevance:0},r,{className:"function",beginKeywords:"func",end:"{",excludeEnd:!0,contains:[e.inherit(e.TITLE_MODE,{begin:/[A-Za-z$_][0-9A-Za-z$_]*/}),{begin://},{className:"params",begin:/\(/,end:/\)/,endsParent:!0,keywords:i,contains:["self",r,a,e.C_BLOCK_COMMENT_MODE,{begin:":"}],illegal:/["']/}],illegal:/\[|%/},{className:"class",beginKeywords:"struct protocol class extension enum",keywords:i,end:"\\{",excludeEnd:!0,contains:[e.inherit(e.TITLE_MODE,{begin:/[A-Za-z$_][\u00C0-\u02B80-9A-Za-z$_]*/})]},{className:"meta",begin:"(@discardableResult|@warn_unused_result|@exported|@lazy|@noescape|@NSCopying|@NSManaged|@objc|@objcMembers|@convention|@required|@noreturn|@IBAction|@IBDesignable|@IBInspectable|@IBOutlet|@infix|@prefix|@postfix|@autoclosure|@testable|@available|@nonobjc|@NSApplicationMain|@UIApplicationMain|@dynamicMemberLookup|@propertyWrapper)\\b"},{beginKeywords:"import",end:/$/,contains:[e.C_LINE_COMMENT_MODE,n]}]}}}()); +hljs.registerLanguage("typescript",function(){"use strict";const e=["as","in","of","if","for","while","finally","var","new","function","do","return","void","else","break","catch","instanceof","with","throw","case","default","try","switch","continue","typeof","delete","let","yield","const","class","debugger","async","await","static","import","from","export","extends"],n=["true","false","null","undefined","NaN","Infinity"],a=[].concat(["setInterval","setTimeout","clearInterval","clearTimeout","require","exports","eval","isFinite","isNaN","parseFloat","parseInt","decodeURI","decodeURIComponent","encodeURI","encodeURIComponent","escape","unescape"],["arguments","this","super","console","window","document","localStorage","module","global"],["Intl","DataView","Number","Math","Date","String","RegExp","Object","Function","Boolean","Error","Symbol","Set","Map","WeakSet","WeakMap","Proxy","Reflect","JSON","Promise","Float64Array","Int16Array","Int32Array","Int8Array","Uint16Array","Uint32Array","Float32Array","Array","Uint8Array","Uint8ClampedArray","ArrayBuffer"],["EvalError","InternalError","RangeError","ReferenceError","SyntaxError","TypeError","URIError"]);return function(r){var t={$pattern:"[A-Za-z$_][0-9A-Za-z$_]*",keyword:e.concat(["type","namespace","typedef","interface","public","private","protected","implements","declare","abstract","readonly"]).join(" "),literal:n.join(" "),built_in:a.concat(["any","void","number","boolean","string","object","never","enum"]).join(" ")},s={className:"meta",begin:"@[A-Za-z$_][0-9A-Za-z$_]*"},i={className:"number",variants:[{begin:"\\b(0[bB][01]+)n?"},{begin:"\\b(0[oO][0-7]+)n?"},{begin:r.C_NUMBER_RE+"n?"}],relevance:0},o={className:"subst",begin:"\\$\\{",end:"\\}",keywords:t,contains:[]},c={begin:"html`",end:"",starts:{end:"`",returnEnd:!1,contains:[r.BACKSLASH_ESCAPE,o],subLanguage:"xml"}},l={begin:"css`",end:"",starts:{end:"`",returnEnd:!1,contains:[r.BACKSLASH_ESCAPE,o],subLanguage:"css"}},E={className:"string",begin:"`",end:"`",contains:[r.BACKSLASH_ESCAPE,o]};o.contains=[r.APOS_STRING_MODE,r.QUOTE_STRING_MODE,c,l,E,i,r.REGEXP_MODE];var d={begin:"\\(",end:/\)/,keywords:t,contains:["self",r.QUOTE_STRING_MODE,r.APOS_STRING_MODE,r.NUMBER_MODE]},u={className:"params",begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:t,contains:[r.C_LINE_COMMENT_MODE,r.C_BLOCK_COMMENT_MODE,s,d]};return{name:"TypeScript",aliases:["ts"],keywords:t,contains:[r.SHEBANG(),{className:"meta",begin:/^\s*['"]use strict['"]/},r.APOS_STRING_MODE,r.QUOTE_STRING_MODE,c,l,E,r.C_LINE_COMMENT_MODE,r.C_BLOCK_COMMENT_MODE,i,{begin:"("+r.RE_STARTERS_RE+"|\\b(case|return|throw)\\b)\\s*",keywords:"return throw case",contains:[r.C_LINE_COMMENT_MODE,r.C_BLOCK_COMMENT_MODE,r.REGEXP_MODE,{className:"function",begin:"(\\([^(]*(\\([^(]*(\\([^(]*\\))?\\))?\\)|"+r.UNDERSCORE_IDENT_RE+")\\s*=>",returnBegin:!0,end:"\\s*=>",contains:[{className:"params",variants:[{begin:r.UNDERSCORE_IDENT_RE},{className:null,begin:/\(\s*\)/,skip:!0},{begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:t,contains:d.contains}]}]}],relevance:0},{className:"function",beginKeywords:"function",end:/[\{;]/,excludeEnd:!0,keywords:t,contains:["self",r.inherit(r.TITLE_MODE,{begin:"[A-Za-z$_][0-9A-Za-z$_]*"}),u],illegal:/%/,relevance:0},{beginKeywords:"constructor",end:/[\{;]/,excludeEnd:!0,contains:["self",u]},{begin:/module\./,keywords:{built_in:"module"},relevance:0},{beginKeywords:"module",end:/\{/,excludeEnd:!0},{beginKeywords:"interface",end:/\{/,excludeEnd:!0,keywords:"interface extends"},{begin:/\$[(.]/},{begin:"\\."+r.IDENT_RE,relevance:0},s,d]}}}()); +hljs.registerLanguage("yaml",function(){"use strict";return function(e){var n="true false yes no null",a="[\\w#;/?:@&=+$,.~*\\'()[\\]]+",s={className:"string",relevance:0,variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/\S+/}],contains:[e.BACKSLASH_ESCAPE,{className:"template-variable",variants:[{begin:"{{",end:"}}"},{begin:"%{",end:"}"}]}]},i=e.inherit(s,{variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/[^\s,{}[\]]+/}]}),l={end:",",endsWithParent:!0,excludeEnd:!0,contains:[],keywords:n,relevance:0},t={begin:"{",end:"}",contains:[l],illegal:"\\n",relevance:0},g={begin:"\\[",end:"\\]",contains:[l],illegal:"\\n",relevance:0},b=[{className:"attr",variants:[{begin:"\\w[\\w :\\/.-]*:(?=[ \t]|$)"},{begin:'"\\w[\\w :\\/.-]*":(?=[ \t]|$)'},{begin:"'\\w[\\w :\\/.-]*':(?=[ \t]|$)"}]},{className:"meta",begin:"^---s*$",relevance:10},{className:"string",begin:"[\\|>]([0-9]?[+-])?[ ]*\\n( *)[\\S ]+\\n(\\2[\\S ]+\\n?)*"},{begin:"<%[%=-]?",end:"[%-]?%>",subLanguage:"ruby",excludeBegin:!0,excludeEnd:!0,relevance:0},{className:"type",begin:"!\\w+!"+a},{className:"type",begin:"!<"+a+">"},{className:"type",begin:"!"+a},{className:"type",begin:"!!"+a},{className:"meta",begin:"&"+e.UNDERSCORE_IDENT_RE+"$"},{className:"meta",begin:"\\*"+e.UNDERSCORE_IDENT_RE+"$"},{className:"bullet",begin:"\\-(?=[ ]|$)",relevance:0},e.HASH_COMMENT_MODE,{beginKeywords:n,keywords:{literal:n}},{className:"number",begin:"\\b[0-9]{4}(-[0-9][0-9]){0,2}([Tt \\t][0-9][0-9]?(:[0-9][0-9]){2})?(\\.[0-9]*)?([ \\t])*(Z|[-+][0-9][0-9]?(:[0-9][0-9])?)?\\b"},{className:"number",begin:e.C_NUMBER_RE+"\\b"},t,g,s],c=[...b];return c.pop(),c.push(i),l.contains=c,{name:"YAML",case_insensitive:!0,aliases:["yml","YAML"],contains:b}}}()); \ No newline at end of file diff --git a/clingo/python-api/5.7/index_files/sanitize.min.css b/clingo/python-api/5.7/index_files/sanitize.min.css new file mode 100644 index 0000000..810f37e --- /dev/null +++ b/clingo/python-api/5.7/index_files/sanitize.min.css @@ -0,0 +1,2 @@ +*,::after,::before{box-sizing:border-box}::after,::before{text-decoration:inherit;vertical-align:inherit}html{cursor:default;line-height:1.5;-moz-tab-size:4;tab-size:4;-webkit-tap-highlight-color:transparent;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;word-break:break-word}body{margin:0}h1{font-size:2em;margin:.67em 0}dl dl,dl ol,dl ul,ol dl,ul dl{margin:0}ol ol,ol ul,ul ol,ul ul{margin:0}hr{height:0;overflow:visible}main{display:block}nav ol,nav ul{list-style:none;padding:0}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}audio,canvas,iframe,img,svg,video{vertical-align:middle}audio,video{display:inline-block}audio:not([controls]){display:none;height:0}iframe{border-style:none}img{border-style:none}svg:not([fill]){fill:currentColor}svg:not(:root){overflow:hidden}table{border-collapse:collapse}button,input,select{margin:0}button{overflow:visible;text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}fieldset{border:1px solid #a0a0a0;padding:.35em .75em .625em}input{overflow:visible}legend{color:inherit;display:table;max-width:100%;white-space:normal}progress{display:inline-block;vertical-align:baseline}select{text-transform:none}textarea{margin:0;overflow:auto;resize:vertical}[type=checkbox],[type=radio]{padding:0}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}::-webkit-input-placeholder{color:inherit;opacity:.54}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}::-moz-focus-inner{border-style:none;padding:0}:-moz-focusring{outline:1px dotted ButtonText}:-moz-ui-invalid{box-shadow:none}details{display:block}dialog{background-color:#fff;border:solid;color:#000;display:block;height:-moz-fit-content;height:-webkit-fit-content;height:fit-content;left:0;margin:auto;padding:1em;position:absolute;right:0;width:-moz-fit-content;width:-webkit-fit-content;width:fit-content}dialog:not([open]){display:none}summary{display:list-item}canvas{display:inline-block}template{display:none}[tabindex],a,area,button,input,label,select,summary,textarea{-ms-touch-action:manipulation;touch-action:manipulation}[hidden]{display:none}[aria-busy=true]{cursor:progress}[aria-controls]{cursor:pointer}[aria-disabled=true],[disabled]{cursor:not-allowed}[aria-hidden=false][hidden]{display:initial}[aria-hidden=false][hidden]:not(:focus){clip:rect(0,0,0,0);position:absolute} +/*# sourceMappingURL=sanitize.min.css.map */ \ No newline at end of file diff --git a/clingo/python-api/5.7/index_files/typography.min.css b/clingo/python-api/5.7/index_files/typography.min.css new file mode 100644 index 0000000..683d8a4 --- /dev/null +++ b/clingo/python-api/5.7/index_files/typography.min.css @@ -0,0 +1,2 @@ +html{font-family:system-ui,-apple-system,"Segoe UI",Roboto,Ubuntu,Cantarell,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji"}code,kbd,pre,samp{font-family:Menlo,Consolas,"Roboto Mono","Ubuntu Monospace","Noto Mono","Oxygen Mono","Liberation Mono",monospace,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji"} +/*# sourceMappingURL=typography.min.css.map */ \ No newline at end of file diff --git a/clingo/python-api/current b/clingo/python-api/current index 1b28632..43f030c 120000 --- a/clingo/python-api/current +++ b/clingo/python-api/current @@ -1 +1 @@ -5.6 \ No newline at end of file +5.7 \ No newline at end of file