Experimental Features

Warning

The following are experimental features that shouldn’t be considered part of the official Clorm API. It is not meant to be used and mostly for exploring and developing ideas.

Reusable Components

This is a work in progress

The goal is to slowly build up a comprehensive set of Clorm components (definitions and functions) that could be used to build readable ASP programs that can be easily integrated into Python applications.

Library components that are currently in the works:

  • date: Contains definitions and functions for dealing with dates and enumerated dates.

  • timeslot: This library will help to deal with blocks of time; for example dividing a day into 15 minute blocks.

JSON Encoding and Decoding

Clorm provides functions for encoding and decoding facts as JSON. The motivation is to be able to pass around facts between different processes. For example, you may want to generate a problem instance as part of a main web application but then pass off the problem instance to a worker processes that actually calls the solver.

Note

The JSON encoding of the clingo.Symbol objects generated here is not the same as running clingo with the --outf=2 argument. The output here is intended as an format for passing around facts between processes and not to be particularly human readable. In contrast the clingo output in more human readable but would require parsing to regenerate the original symbol objects.

The FactBaseCoder class is a helper class to be able to encode/decode JSON for particular Predicate sub-classes. The predicates can be supplied at construction.

from clorm import Predicate
from clorm.json import FactBaseCoder

class Afact(Predicate):
    aint: int
    astr: str

fb_coder = FactBaseCoder([Afact])

Alternatively, the FactBaseCoder can also be used as a decorator to register predicates.

from clorm import Predicate
from clorm.json import FactBaseCoder

fb_coder = FactBaseCoder()

class Fun(Predicate):
    aint: int
    astr: str

class Tup(Predicate, name=""):
    aint: int
    astr: str

@fb_coder.register
class Afact(Predicate):
    aint: int
    afun: Fun

@fb_coder.register
class Bfact(Predicate):
    astr: str
    atup: Tup

Once the fact coder has been created and the appropriate predicates registered, it then provides encoder and decoder member functions that can be used with the standard Python JSON functions.

Assuming the above code:

import json

afact1 = Afact(aint=10, afun=Fun(aint=1, astr="a"))
afact2 = Afact(aint=20, afun=Fun(aint=2, astr="b"))
bfact1 = Bfact(astr="aa", atup=Tup(aint=1, astr="a"))
bfact2 = Bfact(astr="bb", atup=Tup(aint=2, astr="b"))

json_str = json.dumps([afact1,afact2,bfact1,bfact2], default=fb_coder.encoder)

facts = json.loads(json_str, object_hook=fb_coder.decoder)

As a convenience the fact coder provides member functions: dump, dumps, load, loads that call the respective json functions with the appropriate encoder and decoder functions. So the above calls to the json functions can be simplified to:

json_str = fb_coder.dumps([afact1,afact2,bfact1,bfact2])

facts = fb_coder.loads(json_str)