Skip to content

Commit

Permalink
Merge pull request #182 from tulip-control/declare_vars
Browse files Browse the repository at this point in the history
TITLE: add method `GRSpec.declare`
#182
  • Loading branch information
slivingston committed Aug 24, 2017
2 parents 3851202 + 80247ac commit 4a6837b
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 3 deletions.
9 changes: 8 additions & 1 deletion README.rst
Expand Up @@ -14,7 +14,7 @@ TuLiP can be installed also `from PyPI <https://pypi.python.org/pypi/tulip>`_::

pip install tulip

This will install the required dependencies.
This will install the latest release, together with required dependencies.
To find out what dependencies (including optional ones) are installed, call::

tulip.interfaces.print_env()
Expand All @@ -24,6 +24,13 @@ consult https://tulip-control.sourceforge.io/doc/install.html
The next section describes how to build documentation.
A test suite is provided under ``tests/``. Consult the section "Testing" below.

Pip can install the latest *development* snapshot too::

pip install https://github.com/tulip-control/tulip-control/archive/master.zip

Code under development can be unstable so trying `pip install tulip` first
is recommended.


Documentation
-------------
Expand Down
43 changes: 43 additions & 0 deletions tests/form_test.py
Expand Up @@ -114,6 +114,49 @@ def test_init(self):
self.f.sys_vars["y"] == "boolean")


def test_declare_boolean_vars():
# declaring Boolean-valued variables
g = GRSpec()
g.declare('a')
assert g.sys_vars == dict(a='boolean'), g.sys_vars
assert g.env_vars == dict(), g.env_vars
g.declare('a', 'b')
assert g.sys_vars == dict(a='boolean', b='boolean'), g.sys_vars
assert g.env_vars == dict(), g.env_vars
g.declare('c', env=True)
assert g.sys_vars == dict(a='boolean', b='boolean'), g.sys_vars
assert g.env_vars == dict(c='boolean'), g.env_vars
# attempt to redeclare "c" as sys var
with nt.assert_raises(AssertionError):
g.declare('c')


def test_declare_int_vars():
# declaring integer-valued variables
g = GRSpec()
g.declare(i=[0, 10])
assert g.sys_vars == dict(i=(0, 10)), g.sys_vars
assert g.env_vars == dict(), g.env_vars
g.declare(j=(-5, 14), env=True)
assert g.sys_vars == dict(i=(0, 10)), g.sys_vars
assert g.env_vars == dict(j=(-5, 14)), g.env_vars
# attempt to redeclare "i" as env var
with nt.assert_raises(AssertionError):
g.declare(i=(0, 10), env=True)


def test_declare_str_vars():
# declaring string-valued variables
g = GRSpec()
# neither int nor str values
with nt.assert_raises(TypeError):
g.declare(i=(0, 10, 'wrong'))
d = dict(name=['a', 'b', 'c', 'w'])
g.declare(**d)
assert g.sys_vars == d, g.sys_vars
assert g.env_vars == dict(), g.env_vars


def test_str_to_int():
x = "a' = \"hehe\""
s = GRSpec(sys_vars={'a': ['hehe', 'haha']},
Expand Down
43 changes: 41 additions & 2 deletions tulip/spec/form.py
Expand Up @@ -76,8 +76,8 @@ class LTL(object):
examples, are:
- boolean (C{str}); this domain is specified by C{"boolean"};
- finite_set (C{set}); e.g., C{{1,3,5}};
- range (C{tuple} of length 2); e.g., C{(0,15)}.
- finite_set (C{set}); e.g., C{{1, 3, 5}};
- range (C{tuple} of length 2); e.g., C{(0, 15)}.
As with the C{formula} attribute, type-checking is only performed
if requested by the user. E.g., any iterable can act as a
Expand Down Expand Up @@ -410,6 +410,45 @@ def __init__(self, env_vars=None, sys_vars=None,
input_variables=self.env_vars,
output_variables=self.sys_vars)

def declare(self, *arg, **kw):
"""Declare flexible variables.
Positional arguments are names of Boolean-valued variables.
Keyword arguments are names of integer or string valued
variables, declared by a pair of integers, or a sequence of
strings respectively.
By default declare as system variables.
If `env=True` then declare as environment variables.
To declare a variable named `env`, use the constructor
or modify directly the attributes `env_vars`, `sys_vars`.
If already declared, the given type hints should
match existing ones.
"""
env = kw.pop('env', False)
assert isinstance(env, bool), env # "env" not a var name
d = dict()
for k, v in kw.items():
is_int = len(v) == 2 and all(
isinstance(q, int) for q in v)
if is_int:
d[k] = tuple(v)
continue
# duck check by appending ''
d[k] = list(s + '' for s in v)
d.update((v, 'boolean') for v in arg)
# `LTL.*_variables` equal these (see `self.__init__`)
target, other = self.sys_vars, self.env_vars
if env:
target, other = other, target
# redeclarations must match
for k, v in d.items():
assert k not in other, (k, other)
if k in target:
assert target[k] == v, (target[k], v)
target.update(d)

def __repr__(self):
args = (',\n\n'.join([
'env_vars={ev}',
Expand Down

0 comments on commit 4a6837b

Please sign in to comment.