-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpredicate.py
More file actions
210 lines (161 loc) · 7.69 KB
/
Copy pathpredicate.py
File metadata and controls
210 lines (161 loc) · 7.69 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
__metaclass__ = type
import dill
from sympy import *
from sympy import diff
import metitarski
from itertools import product
import re
#to find all functions.
from sympy.core.function import AppliedUndef
#assert diff
def get_derivs(n, seed, system, state):
#Input is a metit equation
derivatives = []
for n in range(n):
dn = MetitEquation(seed.equation.diff(seed.depvar).subs(system[state]['flow']))
derivatives.append(dn)
seed = dn
return derivatives
def gen_meti_string(cls, subsdict={'e[^x]':'*10^', '**':'^', 'Abs':'abs'}):
# Get a list of function names to metitarski variables of the form [[x1(t),X1],[x2(t),X2]]
#
# See http://docs.sympy.org/dev/modules/core.html for more info about atoms(AppliedUndef)
# It returns all undefined functions or in our case implicitly defined variables. Because
# we are dealing with dynamical systems, every variable implicitly depends on time.
var_replace_list = [[var, sympify(str(var).replace("("+str(cls.depvar)+")","").upper())] for var in cls.equation.atoms(AppliedUndef)]
# any other variables, such as parameters (they are considered free in sympy)
var_replace_list.extend([[var, sympify(str(var).upper())] for var in cls.equation.free_symbols])
# convert the equation into the MetiTarski representation
# modified this code from stackoverflow, can't find original link
#
# see : http://docs.python.org/2/library/re.html
# when replacing using REs and sub, you can pass a function, in our case that is the lambda below
# It will be applied for every non-overlapping occurrence of the patern. In this case we are replacing
# each variable from the list above, thats the .subs(var_replace_list) part, then going through
# and replacing each value from the subsdict
rep = dict((re.escape(k), v) for k, v in subsdict.iteritems())
pattern = re.compile("|".join(rep.keys()))
equation_out = pattern.sub(lambda m: subsdict[m.group(0)], str(cls.equation.subs(var_replace_list)))
return equation_out
class MetitEquation:
def __init__(self, equation, var_id=0, depvar=Symbol('t'), eq_num=666, is_lyapunov=False, oplist=['>','=','<']):
#only accept a sympy function
self.equation = equation
#self.derivative = sympify(equation).diff(depvar).subs(subs_dict)
self.depvar = depvar
#self.subs_dict = subs_dict
self.is_lyapunov = is_lyapunov
self.var_list = [sympify(str(var).replace("("+str(self.depvar)+")","").upper()) for var in self.equation.atoms(AppliedUndef)]
self.var_id = var_id
self.meti_string = gen_meti_string(self)
self.eq_num = eq_num
self.oplist = oplist
def __str__(self):
return self.meti_string
def plot_format(self, subs_dict):
return self.equation.subs(subs_dict)
class MetitPredicate(MetitEquation):
def __init__(self,equation,operator,var_id=0,is_lyapunov=False,eq_num=666):
super(MetitPredicate, self).__init__(equation,var_id=var_id,is_lyapunov=is_lyapunov,eq_num=eq_num)
self.operator = operator
# if self.operator == '>':
# self.pretty_pr = super(MetitPredicate, self).__str__() + self.operator + '10^-6'
# elif self.operator == '<':
# self.pretty_pr = super(MetitPredicate, self).__str__() + self.operator + '-10^-6'
# else:
# self.pretty_pr = super(MetitPredicate, self).__str__() + '< 10^-6 & ' + super(MetitPredicate, self).__str__() + '> -10^-6'
self.pretty_pr = super(MetitPredicate, self).__str__() + self.operator + '0'
# def __str__(self):
# if self.operator == '=':
# return super(MetitPredicate, self).__str__() + '<' + '10^-6' + ' & ' + super(MetitPredicate, self).__str__() + '>' + '-10^-6'
# else :
# if self.operator == '>':
# return super(MetitPredicate, self).__str__() + self.operator + '10^-6'
# elif self.operator == '<':
# return super(MetitPredicate, self).__str__() + self.operator + '-10^-6'
def __str__(self):
return self.pretty_pr
def pretty_print(self):
return self.pretty_pr[-20:]
def print_equation(self):
return super(MetitPredicate, self).__str__()
def __eq__(self, other):
return self.pretty_pr == other.pretty_pr
def get_var_string(exp):
var_list = []
for equation in exp.equations:
for variable in equation.var_list:
if str(variable) not in var_list:
var_list.append(str(variable))
return ','.join(var_list)
def plot_format(equation, operator):
if operator == '=':
return 'Eq(%s,0)' % equation
else:
return str(equation) + operator + '0'
class State:
def __init__(self, number, discrete_part, *predicates, **kwargs):
self.is_feasible = True
self.state = predicates
self.number = number
self.next_states = [] #no variable args and keyword with default
self.discrete_part = discrete_part
self.guards = []
self.feasability_checked = False
self.colour = kwargs.get('colour','white')
self.pretty_string = " & ".join([str(x) for x in self.state])
def __eq__(self, other):
# for pred in self.state:
# if pred not in other.state:
# return False
if str(self) != str(other):
return False
if self.discrete_part != other.discrete_part:
return False
return True
#def __iter__(self):
# return self
def __str__(self):
return self.pretty_string
def pretty_print(self):
return " & ".join([x.pretty_print() for x in self.state])
def print_state_number(self):
return str(self.number)
# def derivative(self,pred):
# if pred.equation.is_lyapunov:
# return metitarski_pp(pred.equation.equation.diff(pred.equation.depvar).subs(self.deriv_dict[self.discrete_part]['flow']).subs(pred.equation.vars_dict)) + '-10^-2'
# else:
# return metitarski_pp(pred.equation.equation.diff(pred.equation.depvar).subs(self.deriv_dict[self.discrete_part]['flow']).subs(pred.equation.vars_dict))
def metit_derivative(metit_equation, discrete_state, system):
if metit_equation.is_lyapunov:
# return MetitEquation(metit_equation.equation.diff(metit_equation.depvar).subs(system[discrete_state]['flow']) - 10**-2)
return MetitEquation(sympify(-1))
else:
sympy_equation = metit_equation.equation.diff(metit_equation.depvar).subs(system[discrete_state]['flow'])
return MetitEquation(sympy_equation)
def metit_substitution(metit_equation, discrete_state, system, updates):
sympy_equation = metit_equation.equation.subs(updates)
return MetitEquation(sympy_equation)
if __name__ == '__main__':
t = Symbol('t')
x1 = Function('x1')(t)
x2 = Function('x2')(t)
a = Symbol('a')
x = MetitEquation(-9.8*sin(x1))
y = MetitEquation(x2(t)+a)
z = MetitEquation(1.90843655*sin(x1(t))**2 + 1.90843655*cos(x1(t))**2 - 3.916868466*cos(x1(t)) + 0.19984*x2(t)**2 - 0.0084319171)
system_def_test = {('cont',): {'flow': {x1.diff(t): x2,
x2.diff(t): -9.8*sin(x1)},
't': [],
'inv': []}}
#flow = {x1.diff(t): x2, x2.diff(t): -9.8*sin(x1)}
z = MetitPredicate(-9.8*sin(x1(t)),'<')
#zz = MetitPredicate(-9.8*sin(x1(t)),'<')
#y = MetitEquation(-9.8*sin(x1(t)))
print x
print y
print z
for i in range(4):
xx = metit_derivative(x, ('cont',), system_def_test)
print x
x = xx