added horizon option to discretize

This commit is contained in:
Marcell Vazquez-Chanlatte 2018-05-04 19:50:04 -07:00
parent c1a6e18068
commit 7798fe679e

View file

@ -101,13 +101,14 @@ def implicit_validity_domain(phi, trace):
def require_discretizable(func): def require_discretizable(func):
@wraps(func) @wraps(func)
def _func(phi, dt, *args, **kwargs): def _func(phi, dt, *args, **kwargs):
if 'horizon' not in kwargs:
assert is_discretizable(phi, dt) assert is_discretizable(phi, dt)
return func(phi, dt, *args, **kwargs) return func(phi, dt, *args, **kwargs)
return _func return _func
def scope(phi, dt, *, _t=0): def scope(phi, dt, *, _t=0, horizon=oo):
if isinstance(phi, Next): if isinstance(phi, Next):
_t += dt _t += dt
elif isinstance(phi, (G, F)): elif isinstance(phi, (G, F)):
@ -115,32 +116,44 @@ def scope(phi, dt, *, _t=0):
elif isinstance(phi, Until): elif isinstance(phi, Until):
_t += float('inf') _t += float('inf')
return max((scope(c, dt, _t=_t) for c in phi.children), default=_t) _scope = max((scope(c, dt, _t=_t) for c in phi.children), default=_t)
return min(_scope, horizon)
# Code to discretize a bounded STL formula # Code to discretize a bounded STL formula
@require_discretizable @require_discretizable
def discretize(phi, dt, distribute=False): def discretize(phi, dt, distribute=False, *, horizon=None):
phi = _discretize(phi, dt) if horizon is None:
horizon = oo
phi = _discretize(phi, dt, horizon)
return _distribute_next(phi) if distribute else phi return _distribute_next(phi) if distribute else phi
def _discretize(phi, dt): def _discretize(phi, dt, horizon):
if isinstance(phi, (LinEq, AtomicPred, _Top, _Bot)): if isinstance(phi, (LinEq, AtomicPred, _Top, _Bot)):
return phi return phi
children = tuple(_discretize(arg, dt) for arg in phi.children) if not isinstance(phi, (F, G, Until)):
children = tuple(_discretize(arg, dt, horizon) for arg in phi.children)
if isinstance(phi, (And, Or)): if isinstance(phi, (And, Or)):
return bind(phi).args.set(children) return bind(phi).args.set(children)
elif isinstance(phi, (Neg, Next)): elif isinstance(phi, (Neg, Next)):
return bind(phi).arg.set(children[0]) return bind(phi).arg.set(children[0])
raise NotImplementedError
elif isinstance(phi, Until):
raise NotImplementedError
# Only remaining cases are G and F # Only remaining cases are G and F
psi = children[0] upper = min(phi.interval.upper, horizon)
l, u = round(phi.interval.lower / dt), round(phi.interval.upper / dt) l, u = round(phi.interval.lower / dt), round(upper / dt)
psis = (next(psi, i) for i in range(l, u + 1))
psis = (next(_discretize(phi.arg, dt, horizon - i), i)
for i in range(l, u + 1))
opf = andf if isinstance(phi, G) else orf opf = andf if isinstance(phi, G) else orf
return opf(*psis) return opf(*psis)
@ -174,7 +187,6 @@ def is_discretizable(phi, dt):
_interval_discretizable(c.interval, dt) for c in phi.walk() _interval_discretizable(c.interval, dt) for c in phi.walk()
if isinstance(c, (F, G))) if isinstance(c, (F, G)))
# EDSL # EDSL