def register_options(self, options): """ Extension point to add options to xorro like choosing the transformation to apply. """ group = "Xorro Options" options.add( group, "approach", _dedent("""\ Approach to handle XOR constraints [count] <arg>: {count|list|tree|countp|up|gje} count : Add count aggregates modulo 2 {list,tree}: Translate binary XOR operators to rules (binary operators are arranged in list/tree) countp : Propagator simply counting assigned literals up : Propagator implementing unit propagation gje : Propagator implementing Gauss-Jordan Elimination""" ), self.__parse_approach) options.add( group, "cutoff", _dedent("""\ Percentage of literals assigned before GJE [0-1]"""), self.__parse_cutoff) options.add_flag( group, "sampling", _dedent("""\ Enable sampling by generating random XOR constraints"""), self.__sampling) options.add( group, "s", _dedent("""\ Number of XOR constraints to generate. Default=0, log(#atoms)"""), self.__parse_s) options.add( group, "q", _dedent("""\ Density of each XOR constraint. Default=0.5"""), self.__parse_q) options.add_flag( group, "display", _dedent("""\ Display the random XOR constraints used in sampling"""), self.__display) options.add( group, "split", _dedent("""\ Split XOR constraints to smaller ones of size <n>. Default=0 (off) """ ), self.__parse_split) options.add_flag( group, "pre-gje", _dedent("""\ Enable GJE preprocessing for XOR constraints"""), self.__pre_gje)
def dedent(text: str) -> str: """Fix indentation of given text by removing leading spaces and tabs. Also removes leading newlines and trailing spaces and tabs, but keeps trailing newlines. """ return _dedent(text.lstrip("\n").rstrip(" \t"))
def normalized_indent (text) : """Returns `text` with normalized indentation.""" lines = text.strip ().split ("\n", 1) result = lines [0] rest = lines [1:] if rest : result = "\n".join ((result, _dedent (rest [0]))) return result
def normalized_indent(text): """Returns `text` with normalized indentation.""" lines = text.strip().split("\n", 1) result = lines[0] rest = lines[1:] if rest: result = "\n".join((result, _dedent(rest[0]))) return result
def _return_response_html_content(self, value, **args): def indented(string, level=1): return _indented(string, level, size=2) html = '''\ <!DOCTYPE html> <html> <head> <title>{resource_name}</title> </head> <body> <h1>{resource_name}</h1> {retval_html} {args_html} {auth_info_html} </body> </html> ''' html = _dedent(html) if value: retval_html = \ '<h2>Return value</h2>'\ '\n\n<p><code class="retval">{}</code></p>'\ .format(_cgi.escape(value.json())) else: retval_html = '' if args: args_html = '<h2>Given arguments</h2>\n\n<dl class="args">\n\n ' args_html += \ '\n\n '.join('<dt><code class="arg_name">{}</code></dt>' '\n <dd><code class="arg_value">{}</code></dd>' .format(_cgi.escape(name), _cgi.escape(value.json())) for name, value in sorted(args.items())) args_html += '\n\n</dl>' else: args_html = '' # XXX: use out-of-band current auth info # FIXME: use in-band auth info via auth info facet auth_info = self.current_auth_info auth_info_html = indented(self._auth_info_facet_html(auth_info)) html = html.format(resource_name=_cgi.escape(self.__class__.__name__), retval_html=retval_html, args_html=args_html, auth_info_html=auth_info_html) return html
def translate(mode, prg, cutoff): if mode == "count": prg.add( "__count", [], _dedent("""\ :- { __parity(ID,even,X) } = N, N\\2!=0, __parity(ID,even). :- { __parity(ID,odd ,X) } = N, N\\2!=1, __parity(ID,odd). """)) prg.ground([("__count", [])]) elif mode == "countp": prg.register_propagator(CountCheckPropagator()) elif mode == "up": prg.register_propagator(WatchesUnitPropagator()) elif mode == "gje": prg.register_propagator(WatchesUnitPropagator()) prg.register_propagator(Propagate_GJE(cutoff)) elif mode == "reason-gje": prg.register_propagator(Reason_GJE(cutoff)) elif mode in ["list", "tree"]: def to_tree(constraint): layer = [Leaf(literal) for literal in constraint] def tree(l, r): return l if r is None else Tree(l, r) while len(layer) > 1: layer = list( util.starmap(tree, util.zip_longest(layer[0::2], layer[1::2]))) return layer[0] def get_lit(atom): return atom.literal, True if atom.is_fact else None ret = util.symbols_to_xor_r(prg.symbolic_atoms, get_lit) with prg.backend() as b: if ret is None: b.add_rule([], []) else: constraints, facts = ret for fact in facts: b.add_rule([], [-fact]) for constraint in constraints: tree = List(constraint) if mode == "list" else to_tree( constraint) b.add_rule([], [-tree.translate(b)]) else: raise RuntimeError("unknow transformation mode: {}".format(mode))
def get_xors(prg, files): """ Get XORs from encoding(s)/instance(s) """ ## Load files for f in files: prg.load(f) ## Theory is added when Random XORs are built. ## So, if not sampling, theory must be added here. ## This must be substitute by using the AST prg.add( "base", [], _dedent("""\ #theory parity { element {}; &odd/0 : element, directive; &even/0 : element, directive }. """)) prg.ground([("base", [])]) ## Get XORS all_lits = [] xors_parities = [] xors_lits = [] for atom in prg.theory_atoms: xors_parities.append(get_parity(atom.term)) lits = [] for e in atom.elements: element_str = str(e) condition = element_str.split(':')[-1] if "not " in condition: condition = condition.replace("not ", '') lits.append(condition) if condition not in all_lits: all_lits.append(condition) #if len(e.terms) == 2: # lits.append(str(e.terms[1])) # if str(e.terms[1]) not in all_lits: # all_lits.append(str(e.terms[1])) #else: # lits.append(str(e.terms[0])) # if str(e.terms[0]) not in all_lits: # all_lits.append(str(e.terms[0])) xors_lits.append(lits) return xors_lits, xors_parities, all_lits
def get(self, sum, start, offset): html = '''\ <!DOCTYPE html> <html> <head> <title>Date and time sum</title> </head> <body> <p>Offsetting {start} by {offset} yields {sum}.</p> </body> </html> ''' html = _dedent(html) html = html.format(start=start.native(), offset=offset.native(), sum=sum.native()) return html
def generate_random_xors(prg, files, s, q): """ Of course adding the theory may not be the best way to do it. This is just a hack Maybe using the AST is a better alternative to extract the symbols to build the xor constraints. In the end, we just need the symbols to write a file with random constraints. """ for f in files: prg.load(f) prg.add( "base", [], _dedent("""\ #theory parity { element {}; &odd/0 : element, directive; &even/0 : element, directive }. """)) prg.ground([("base", [])]) estimated_s = s constraints = [] parities = [] xors = "" symbols = [ atom.symbol for atom in prg.symbolic_atoms if atom.is_fact is False and "__parity" not in str(atom.symbol) ] if len(symbols) > 0: if s == 0: estimated_s = int(log(len(symbols) + 1, 2)) print("Random XOR Constraints: %s" % estimated_s) for i in range(estimated_s): range_ = int((len(symbols)) * q) size = randint(range_, range_) terms = " ; ".join( str(x) + ":" + str(x) for x in sorted(sample(symbols, size))) xors += "&%s{ %s }.\n" % (get_str_parity(randint(0, 1)), terms) file_ = open("examples/xors.lp", "w") file_.write(xors) file_.close() return xors
def get(self, echo_dt, dt): html = '''\ <!DOCTYPE html> <html> <head> <title>Date and time echo</title> </head> <body> <p> {echo_dt} </p> </body> </html> ''' html = _dedent(html) html = html.format(echo_dt=echo_dt.native()) return html
def get(self, difference, start, end): html = '''\ <!DOCTYPE html> <html> <head> <title>Date and time difference</title> </head> <body> <p> The difference between {start} and {end} is {difference}. </p> </body> </html> ''' html = _dedent(html) html = html.format(start=start.native(), end=end.native(), difference=difference.native()) return html
def _dl_function(shell): if shell in (Shells.BASH, Shells.ZSH): s = '''\ # Download a Jutge problem and change to it %(fname)s () { %(jt)s download $@ && cd $(%(jt)s dl --get-dest $@) } ''' elif shell == Shells.TCSH: s = '''\ : Download a Jutge problem and change to it alias %(fname)s '%(jt)s download \\!* && cd `%(jt)s --get-dest \\!*` ''' elif shell == Shells.FISH: s = '''\ function %(fname)s --description \\ '# Download a Jutge problem and change to it' %(jt)s download $argv; and cd (%(jt)s dl --get-dest $argv) end ''' return _dedent(s)
def get(self, now): html = '''\ <!DOCTYPE html> <html> <head> <title>Current date and time</title> </head> <body> <p>It is currently {time} on {date} in the time zone {tz}.</p> </body> </html> ''' html = _dedent(html) now_dt = now.native() tz_str = now_dt.tzname() or now_dt.strftime('%z') html = html.format(date=now_dt.date(), time=now_dt.time().replace(microsecond=0), tz=tz_str) return html
def dedent(text): """ Sames as textwrap's dedent, except that handles the multi-line strings formated like this: dedent( ''' line 1 line 2 ''' ) """ from textwrap import dedent as _dedent # Ignores dedent if the text is a single line. if '\n' not in text: return text result = _dedent(text) # Removes (first) leading EOL if there's any. if result.startswith('\n'): result = result[1:] return result
def make_binary_ufunclike(method, name=None, module=None): """ Wraps an ArrayMethod to behave almost exactly like a binary ufunc that only works for the specific DTypes. Note that this uses private (Python side) API currently. This function is provided, because it is currently not possible to register an ArrayMethod as a ufunc "inner-loop" """ def func(arr1, arr2): casting, dtypes = method._resolve_descriptors( (arr1.dtype, arr2.dtype, None)) # Could check casting, but it is not interesting usually. it = np.nditer( (arr1, arr2, None), op_dtypes=dtypes, flags=["zerosize_ok", "grow_inner", "buffered", "external_loop"], op_flags=[["readonly"], ["readonly"], ["writeonly", "allocate"]]) res = it.operands[2] with it: for op1, op2, out in it: method._simple_strided_call((op1, op2, out)) return res if name: func.__name__ = name if module: func.__module__ = module func.__doc__ = _dedent(f""" Automatically generated ufunc-like for The ArrayMethod: {repr(method)} """) return func
def source_no_header_template(): return _dedent(_source_no_header_template)
def header_template(macroname): return _dedent(_header_template.format(macroname=macroname))
def source_template(header): return _dedent(_source_template.format(header=header))
def namedflagset_classes(classname, frozenclassname=None, baseclassname=None, doc=None, frozendoc=None): """Classes for sets of named flags. This method creates a class that defines a set of flags that are valid for its instances. Objects of this class contain zero or more of these registered flags. These objects support the full :class:`collections.MutableSet` API. """ if baseclassname is None: baseclassname = classname + 'ABC' if frozenclassname is None: frozenclassname = 'Frozen' + classname __doc__suffix = \ """ .. seealso:: :func:`spruce.lang.namedflagset_classes <spruce.lang._datatypes.namedflagset_classes>` :param flags: Flags. A union (using ``|``) of zero or more of the flags registered via :meth:`register_flags`. :type flags: ~\ :obj:`int` or :obj:`None` :raise TypeError: Raised if non-null *flags* are given that are of a type that cannot be converted to an :obj:`int`. :raise ValueError: Raised if non-null *flags* are given that cannot be converted to an :obj:`int`. """ __doc__suffix = _dedent(__doc__suffix) basedoc_shortdoc = \ """A set of named flags. .. seealso:: :class:`{}`, :class:`{}` """\ .format(classname, frozenclassname) baseclass__doc__ = _dedent(basedoc_shortdoc) + __doc__suffix __metaclass__ = _ABCMeta def __init__(self, flags=None): if not flags: flags = 0 try: flags = int(flags) except TypeError: raise TypeError('invalid flags type {!r}; expecting one that is' ' accepted by {!r}'.format(flags.__class__, int)) except ValueError: raise ValueError( 'invalid flags {!r}; expecting an integer'.format(flags)) self._flags = flags def __and__(self, other): return self.__class__(int(self) & int(other)) def __contains__(self, item): return item <= self def __eq__(self, other): return int(self) == int(other) def __int__(self): return self._flags def __iter__(self): for flag in self.valid_flags(): if self.__class__(flag) in self: yield flag def __le__(self, other): return (int(self) & int(other)) == int(self) def __len__(self): return sum(1 for flag in self.valid_flags() if self.__class__(flag) in self) def __nonzero__(self): return bool(int(self)) def __or__(self, other): return self.__class__(int(self) | int(other)) def __repr__(self): return '{}({})'.format( self.__class__.__name__, ' | '.join(self.flag_name(flag) for flag in self._repr_flags)) def __sub__(self, other): return self.__class__(int(self) - int(other)) def __str__(self): return '{{{}}}'.format(', '.join( self.flag_displayname(flag) for flag in self._repr_flags)) def __xor__(self, other): return self.__class__(int(self) ^ int(other)) def copy(self): return self.__class__(self) @classmethod def flag_displayname(cls, flag): try: return cls._flags_displaynames[flag] except KeyError: raise ValueError('invalid {} flag {!r}'.format(cls.__name__, flag)) @classmethod def flag_name(cls, flag): try: return cls._flags_names[flag] except KeyError: raise ValueError('invalid {} flag {!r}'.format(cls.__name__, flag)) @classmethod def register_flag(cls, name, displayname=None, implied=None): flag = cls._frozenclass(cls._reserve_next_flag_value()) if implied: flag |= implied cls._flags_names[flag] = name if displayname is None: displayname = name cls._flags_displaynames[flag] = displayname return flag @classmethod def valid_flags(cls): return cls._flags_names.keys() _flags_displaynames = {} _flags_names = {} _next_flag_value = 1 @property def _repr_flags(self): flags = [] f = int(self) for flag in reversed(sorted(int(flag) for flag in self.valid_flags())): if flag & f == flag: flags.append(flag) f -= flag return reversed(flags) @classmethod def _reserve_next_flag_value(cls): value = cls._next_flag_value cls._next_flag_value <<= 1 return value baseclass_attrs = { '__doc__': baseclass__doc__, '__metaclass__': __metaclass__, '__init__': __init__, '__and__': __and__, '__contains__': __contains__, '__eq__': __eq__, '__int__': __int__, '__iter__': __iter__, '__le__': __le__, '__len__': __len__, '__nonzero__': __nonzero__, '__or__': __or__, '__repr__': __repr__, '__str__': __str__, '__xor__': __xor__, 'copy': copy, 'flag_displayname': flag_displayname, 'flag_name': flag_name, 'register_flag': register_flag, 'valid_flags': valid_flags, '_flags_displaynames': _flags_displaynames, '_flags_names': _flags_names, '_next_flag_value': _next_flag_value, '_repr_flags': _repr_flags, '_reserve_next_flag_value': _reserve_next_flag_value, } baseclass = _total_ordering(type(baseclassname, (_Set, ), baseclass_attrs)) if frozendoc is None: frozendoc = basedoc_shortdoc frozenclass__doc__ = _dedent(frozendoc) + __doc__suffix def __hash__(self): return hash(self._flags) frozenclass_attrs = {'__doc__': frozenclass__doc__, '__hash__': __hash__} frozenclass = type(frozenclassname, (baseclass, ), frozenclass_attrs) baseclass._frozenclass = frozenclass if doc is None: doc = basedoc_shortdoc mutableclass__doc__ = _dedent(doc) + __doc__suffix def __iand__(self, other): self._flags &= int(other) return self def __ior__(self, other): self._flags |= int(other) return self def __isub__(self, other): self._flags -= int(other) return self def __ixor__(self, other): self._flags ^= int(other) return self def add(self, item): self._flags |= int(item) def discard(self, item): self._flags &= ~int(item) mutableclass_attrs = { '__doc__': mutableclass__doc__, '__iand__': __iand__, '__ior__': __ior__, '__ixor__': __ixor__, 'add': add, 'discard': discard } mutableclass = type(classname, (baseclass, _MutableSet), mutableclass_attrs) baseclass._mutableclass = mutableclass return baseclass, mutableclass, frozenclass
def main_template(): return _dedent(_main_template)
# ar2 = jnp.sort(ar2) # ind = jnp.searchsorted(ar2, ar1) # if invert: # return ar1 != ar2[ind] # else: # return ar1 == ar2[ind] if invert: return (ar1[:, None] != ar2[None, :]).all(-1) else: return (ar1[:, None] == ar2[None, :]).any(-1) @_wraps(np.setdiff1d, lax_description=_dedent(""" Because the size of the output of ``setdiff1d`` is data-dependent, the function is not typically compatible with JIT. The JAX version adds the optional ``size`` argument which must be specified statically for ``jnp.setdiff1d`` to be used within some of JAX's transformations."""), extra_params=_dedent(""" size : int, optional If specified, the first ``size`` elements of the result will be returned. If there are fewer elements than ``size`` indicates, the return value will be padded with ``fill_value``. fill_value : array_like, optional When ``size`` is specified and there are fewer than the indicated number of elements, the remaining elements will be filled with ``fill_value``, which defaults to zero.""" )) def setdiff1d(ar1, ar2, assume_unique=False, *, size=None, fill_value=None): _check_arraylike("setdiff1d", ar1, ar2) if size is None: ar1 = core.concrete_or_error(None, ar1, "The error arose in setdiff1d()")
def dedentfn(fn): fn.__doc__ = _dedent(fn.__doc__) return fn
def dedent(text: str) -> str: """Fix indentation and also trim given text string.""" return _dedent(text.lstrip("\n").rstrip(" \t\n"))
from textwrap import dedent as _dedent from battletech.starsystem import ( StarSystem, parse_systems_request as _parse_system_request, ) if __name__ == "__main__": # Select our desired system(s) biomes = set() user_input = input( _dedent( """Please select the system(s) you wish to modify. Systems can be comma-separated to act on many different systems, may be matched via regex with an input starting with /, or with * for all. \tEnter the system(s) to modify. > """ ) ) selected_systems = _parse_systems_request(user_input) for system in selected_systems: system: StarSystem # with system: # if 20 >= system.number_of_shop_items <= 6: # system.number_of_shop_items *= 2 # system.add_markets() # system.add_markets() biomes |= set(system.biomes) pprint(biomes)
def _exc_response_html_content(self, data): def indented(string, level=1): return _indented(string, level, size=2) html = '''\ <!DOCTYPE html> <html> <head> <title>{title}</title> <style type="text/css"> {css} </style> </head> <body> <h1>{title}</h1> {message_html} {tech_details_html} {auth_info_html} </body> </html> ''' html = _dedent(html) css_blocks = [] exc_facet = data['exc'] if _debug.DEBUG_EXC_NAME in exc_facet.debug_flags: displayname = exc_facet.displayname or exc_facet.name title = displayname[0].upper() if len(displayname) > 1: title += displayname[1:] else: title = 'Error' class_def_info_css = '''\ dl.class_def_info > dt { font-weight: bold; } ''' css_blocks.append(_dedent(class_def_info_css)) if exc_facet.message \ and _debug.DEBUG_EXC_MESSAGE in exc_facet.debug_flags: message_html = '<p class="exc_str">{}</p>'\ .format(_cgi.escape(exc_facet.message)) message_html = indented(message_html) else: message_html = '' if _debug.DEBUG_EXC_INSTANCE_INFO in exc_facet.debug_flags: tech_details_html = \ '''\ <h2>Technical details</h2> <h3>Exception class</h3> <dl class="exc_class_def_info"> <dt>Module</dt> <dd><code class="exc_class_def_module">{class_def_module}</code></dd> <dt>Name</dt> <dd><code class="exc_name">{name}</code></dd> </dl> {args_html} {traceback_html} ''' tech_details_html = indented(_dedent(tech_details_html)) if exc_facet.args: css = '''\ ol.exc_args { padding: 0; list-style: none; counter-reset: arg -1; } ol.exc_args > li::before { font-family: monospace; counter-increment: arg; content: "args[" counter(arg) "]: "; } ''' css_blocks.append(_dedent(css)) args_html = \ '<h3>Exception arguments</h3>'\ '\n\n<ol class="exc_args">\n\n ' args_html += \ '\n '.join('<li><code class="exc_arg">{}</code></li>' .format(_cgi.escape(arg)) for arg in exc_facet.args) args_html += '\n\n</ol>' args_html = indented(args_html) else: args_html = '' if exc_facet.traceback \ and _debug.DEBUG_EXC_TRACEBACK in exc_facet.debug_flags: traceback_html = \ '<h3>Traceback</h3>'\ '\n\n<pre><code class="exc_traceback">{}</code></pre>'\ .format(_cgi.escape(exc_facet.traceback)) traceback_html = indented(traceback_html) else: traceback_html = '' tech_details_html = \ tech_details_html\ .format(class_def_module= _cgi.escape(exc_facet.class_def_module), name=_cgi.escape(exc_facet.name), args_html=args_html, traceback_html=traceback_html) try: auth_info_facet = data['auth_info'] except KeyError: auth_info_html = '' else: auth_info_html = \ indented(self._auth_info_facet_html(auth_info_facet)) css = ''.join(indented(block, 2) for block in css_blocks) html = html.format(title=_cgi.escape(title), css=css, message_html=message_html, tech_details_html=tech_details_html, auth_info_html=auth_info_html) return html
# The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. #modindex_common_prefix = [] rst_prolog = \ '''\ .. role:: bash(code) :language: bash .. role:: python(code) :language: python ''' rst_prolog = _dedent(rst_prolog) nitpicky = True # FIXME: encapsulate this in a Sphinx extension. make ``rfc_uri_tmpl`` a # Sphinx config setting rfc_uri_tmpl = 'https://tools.ietf.org/html/rfc{}.html' def rfc_role(role, rawtext, text, lineno, inliner, options={}, content=[]): _rst.roles.set_classes(options) rfcrefpattern = r'(?:(?P<displaytext>[^<]*)'\ r' <)?(?P<refname>[^>]*)(?(displaytext)>|)' match = _re.match(rfcrefpattern, _rst.roles.utils.unescape(text)) if match: rfcnum, anchorsep, anchor = match.group('refname').partition('#')
def dedent(s): return _dedent(s.strip("\r\n"))
# The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. #modindex_common_prefix = [] rst_prolog = \ '''\ .. role:: bash(code) :language: bash .. role:: python(code) :language: python ''' rst_prolog = _dedent(rst_prolog) nitpicky = True # FIXME: encapsulate this in a Sphinx extension. make ``rfc_uri_tmpl`` a # Sphinx config setting rfc_uri_tmpl = 'https://tools.ietf.org/html/rfc{}.html' def rfc_role(role, rawtext, text, lineno, inliner, options={}, content=[]): _rst.roles.set_classes(options) rfcrefpattern = r'(?:(?P<displaytext>[^<]*)'\ r' <)?(?P<refname>[^>]*)(?(displaytext)>|)' match = _re.match(rfcrefpattern, _rst.roles.utils.unescape(text))
def transform(inputs, callback): """ Transforms the given list of temporal programs in string form into an ASP program. Returns the future predicates whose atoms have to be set to false if referring to the future, and program parts that have to be regrounded if there are constraints referring to the future. Arguments: inputs -- The list of inputs. callback -- Callback for rewritten statements. """ loc = { 'begin': { 'line': 1, 'column': 1, 'filename': '<transform>' }, 'end': { 'line': 1, 'column': 1, 'filename': '<transform>' } } future_predicates = set() constraint_parts = {} time = _ast.Symbol(loc, _clingo.Function(_tf.g_time_parameter_name)) wrap_lit = lambda a: _ast.Literal(loc, _ast.Sign.NoSign, a) # apply transformer to program def append(s): if s is not None: callback(s) aux_rules = [] transformer = _prg.ProgramTransformer(future_predicates, constraint_parts, aux_rules) for i in inputs: _clingo.parse_program(i, lambda s: append(transformer.visit(s))) if aux_rules: callback( _ast.Program(loc, "always", [ _ast.Id(loc, _tf.g_time_parameter_name), _ast.Id(loc, _tf.g_time_parameter_name_alt) ])) for rule in aux_rules: callback(rule) # add auxiliary rules for future predicates future_sigs = [] if len(future_predicates) > 0: callback( _ast.Program(loc, "always", [ _ast.Id(loc, _tf.g_time_parameter_name), _ast.Id(loc, _tf.g_time_parameter_name_alt) ])) for name, arity, positive, shift in sorted(future_predicates): variables = [ _ast.Variable(loc, "{}{}".format(_tf.g_variable_prefix, i)) for i in range(arity) ] s = _ast.Symbol(loc, _clingo.Number(shift)) t_shifted = _ast.BinaryOperation(loc, _ast.BinaryOperator.Plus, time, s) add_sign = lambda lit: lit if positive else _ast.UnaryOperation( loc, _ast.UnaryOperator.Minus, lit) p_current = _ast.SymbolicAtom( add_sign(_ast.Function(loc, name, variables + [time], False))) f_current = _ast.SymbolicAtom( add_sign( _ast.Function(loc, _tf.g_future_prefix + name, variables + [s, time], False))) callback(_ast.Rule(loc, wrap_lit(p_current), [wrap_lit(f_current)])) future_sigs.append( (_tf.g_future_prefix + name, arity + 2, positive)) # gather rules for constraints referring to the future reground_parts = [] if len(constraint_parts) > 0: for (name, shift), rules in constraint_parts.items(): assert (shift > 0) params = [ _ast.Id(loc, _tf.g_time_parameter_name), _ast.Id(loc, _tf.g_time_parameter_name_alt) ] # parts to be regrounded part = "{}_0_{}".format(name, shift - 1) callback(_ast.Program(loc, part, params)) for p, l in rules: callback(p) reground_parts.append((name, part, range(shift))) # parts that no longer have to be regrounded last_part = "{}_{}".format(name, shift) callback(_ast.Program(loc, last_part, params)) for p, l in rules: callback(l) reground_parts.append((name, last_part, range(shift, shift + 1))) def add_part(part_name, atom_name, statement, wrap=lambda x: x): params = [ _ast.Id(loc, _tf.g_time_parameter_name), _ast.Id(loc, _tf.g_time_parameter_name_alt) ] callback(_ast.Program(loc, part_name, params)) atom = wrap( _ast.SymbolicAtom(_ast.Function(loc, atom_name, [time], False))) callback(statement(loc, atom, [])) add_part('initial', '__initial', _ast.Rule, wrap_lit) add_part('always', '__final', _tf.External) reground_parts.append(('always', 'always', range(1))) reground_parts.append(('dynamic', 'dynamic', range(1))) reground_parts.append(('initial', 'initial', range(1))) def no_program(s): if s.type != _ast.ASTType.Program: callback(s) _clingo.parse_program( _dedent('''\ #theory tel { formula_body { & : 7, unary; % prefix for keywords - : 7, unary; % classical negation + : 6, binary, left; % arithmetic + - : 6, binary, left; % arithmetic - ~ : 5, unary; % negation < : 5, unary; % previous < : 5, binary, right; % n x previous <: : 5, unary; % weak previous <: : 5, binary, right; % n x weak previous <? : 5, unary; % eventually- <* : 5, unary; % always- << : 5, unary; % initially > : 5, unary; % next > : 5, binary, right; % n x next >: : 5, unary; % weak next >: : 5, binary, right; % n x weak next >? : 5, unary; % eventually+ >* : 5, unary; % always+ >> : 5, unary; % finally >* : 4, binary, left; % release >? : 4, binary, left; % until <* : 4, binary, left; % trigger <? : 4, binary, left; % since & : 3, binary, left; % and | : 2, binary, left; % or <- : 1, binary, left; % left implication -> : 1, binary, left; % right implication <> : 1, binary, left; % equivalence ;> : 0, binary, right; % sequence next ;>: : 0, binary, right; % sequence weak next <; : 0, binary, left; % sequence previous <:; : 0, binary, left % sequence weak previous }; formula_head { & : 7, unary; % prefix for keywords - : 7, unary; % classical negation + : 6, binary, left; % arithmetic + - : 6, binary, left; % arithmetic - ~ : 5, unary; % negation > : 5, unary; % next > : 5, binary, right; % n x next >: : 5, unary; % weak next >: : 5, binary, right; % n x weak next >? : 5, unary; % eventually+ >* : 5, unary; % always+ >> : 5, unary; % finally >* : 4, binary, left; % release >? : 4, binary, left; % until & : 3, binary, left; % and | : 2, binary, left; % or ;> : 0, binary, right; % sequence next ;>: : 0, binary, right % sequence weak next }; &tel/1 : formula_body, body; &__tel_head/1 : formula_body, head }. '''), no_program) _clingo.parse_program( _dedent('''\ #theory del { formula_body { & : 7, unary; % prefix for keywords ? : 4, unary; % check * : 3, unary; % kleene star + : 2, binary, left; % choice ;; : 1, binary, left; % sequence .>? : 0, binary, right; % diamond (eventually) .>* : 0, binary, right % box (always) }; &del/1 : formula_body, body }. '''), no_program) return future_sigs, reground_parts