aa257377
Francisco Coelho
Post meeting 2022...
|
1
2
|
import math
from functools import cache
|
d080b400
Francisco Coelho
Paper draft: Exte...
|
3
|
from itertools import accumulate, combinations, chain, groupby
|
aa257377
Francisco Coelho
Post meeting 2022...
|
4
5
6
|
import operator
|
677cc471
Francisco Coelho
Further progress ...
|
7
|
|
aa257377
Francisco Coelho
Post meeting 2022...
|
8
9
|
def uniform_op(x):
n = len(list(x))
|
677cc471
Francisco Coelho
Further progress ...
|
10
|
return 1.0 if n == 0 else 1.0/n
|
aa257377
Francisco Coelho
Post meeting 2022...
|
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
def max_op(x):
return max(x)
def min_op(x):
return min(x)
def sum_op(x):
return sum(x)
|
677cc471
Francisco Coelho
Further progress ...
|
25
|
def stableprod_op(x):
|
aa257377
Francisco Coelho
Post meeting 2022...
|
26
27
28
29
|
log_x = map(math.log, x)
return math.exp(sum(log_x))
|
677cc471
Francisco Coelho
Further progress ...
|
30
31
32
33
34
|
def prod_op(x):
return list(accumulate(x, func=lambda a,b: a*b))[-1]
class Event:
|
d080b400
Francisco Coelho
Paper draft: Exte...
|
35
36
37
38
39
40
41
|
"""Events.
An event is a set of literals - atoms and negated atoms.
The convention is that atoms are represented by lower case single letters
and a negated atom by upper case single letters.
"""
|
677cc471
Francisco Coelho
Further progress ...
|
42
43
|
@staticmethod
|
d080b400
Francisco Coelho
Paper draft: Exte...
|
44
|
def _parse(text):
|
677cc471
Francisco Coelho
Further progress ...
|
45
46
47
|
return frozenset(text)
@staticmethod
|
d080b400
Francisco Coelho
Paper draft: Exte...
|
48
49
50
51
52
53
|
def parse(text):
"""Convert a string to an event.
Each letter in the string represents a literal.
"""
return Event(Event._parse(text))
|
677cc471
Francisco Coelho
Further progress ...
|
54
55
56
57
58
|
def __init__(self, literals):
"""Instantiate from a (frozen) set of literals.
For example: e = Event(frozenset("abc"))."""
|
d080b400
Francisco Coelho
Paper draft: Exte...
|
59
|
self._literals = frozenset(literals)
|
677cc471
Francisco Coelho
Further progress ...
|
60
61
62
63
64
65
66
67
|
def literals(self):
return self._literals
def __iter__(self):
return self._literals.__iter__()
|
677cc471
Francisco Coelho
Further progress ...
|
68
69
70
|
@cache
def is_consistent(self):
|
d080b400
Francisco Coelho
Paper draft: Exte...
|
71
|
"""True if this event is consistent."""
|
677cc471
Francisco Coelho
Further progress ...
|
72
73
|
return all(x.swapcase() not in self._literals for x in self._literals)
|
677cc471
Francisco Coelho
Further progress ...
|
74
|
|
d080b400
Francisco Coelho
Paper draft: Exte...
|
75
76
77
78
79
|
def co(self):
"""Negation of this event.
Negation is case based: A = not a; a = not A."""
return Event(x.swapcase() for x in self._literals)
|
677cc471
Francisco Coelho
Further progress ...
|
80
|
|
d080b400
Francisco Coelho
Paper draft: Exte...
|
81
82
|
def invert(self):
"""Negation of this event.
|
677cc471
Francisco Coelho
Further progress ...
|
83
|
|
d080b400
Francisco Coelho
Paper draft: Exte...
|
84
85
86
|
See the method "co"
"""
return self.co()
|
677cc471
Francisco Coelho
Further progress ...
|
87
88
|
def __repr__(self) -> str:
|
d080b400
Francisco Coelho
Paper draft: Exte...
|
89
|
return ''.join(str(x) for x in sorted(self._literals)) if len(self._literals) > 0 else '0'
|
aa257377
Francisco Coelho
Post meeting 2022...
|
90
|
|
d080b400
Francisco Coelho
Paper draft: Exte...
|
91
92
93
94
95
96
97
98
99
100
101
102
103
|
def latex(self):
"""LaTeX representation of this even.
Negation is represented by overline and the empty event by
"""
return ''.join(
(str(x) if x.islower() else f"\co{{{x.lower()}}}") \
for x in sorted(self._literals)
) if len(self._literals) > 0 else "\set{}"
def __hash__(self) -> int:
return self._literals.__hash__()
|
aa257377
Francisco Coelho
Post meeting 2022...
|
104
|
|
677cc471
Francisco Coelho
Further progress ...
|
105
106
|
def __eq__(self, other):
|
d080b400
Francisco Coelho
Paper draft: Exte...
|
107
|
"""Event equality test."""
|
677cc471
Francisco Coelho
Further progress ...
|
108
109
110
|
return self._literals.__eq__(other._literals)
def __or__(self, other):
|
d080b400
Francisco Coelho
Paper draft: Exte...
|
111
|
"""Event union operation."""
|
677cc471
Francisco Coelho
Further progress ...
|
112
113
|
return Event(self._literals | other._literals)
|
677cc471
Francisco Coelho
Further progress ...
|
114
|
def __le__(self, other):
|
d080b400
Francisco Coelho
Paper draft: Exte...
|
115
|
"""Event subset test."""
|
677cc471
Francisco Coelho
Further progress ...
|
116
117
118
119
|
return self._literals.__le__(other._literals)
def __lt__(self, other):
|
d080b400
Francisco Coelho
Paper draft: Exte...
|
120
|
"""Event strict subset test."""
|
677cc471
Francisco Coelho
Further progress ...
|
121
122
123
124
|
return self._literals.__lt__(other._literals)
def __ne__(self, other):
|
d080b400
Francisco Coelho
Paper draft: Exte...
|
125
|
"""Event not-equal test."""
|
677cc471
Francisco Coelho
Further progress ...
|
126
127
128
129
|
return self._literals.__ne__(other._literals)
def __ge__(self, other):
|
d080b400
Francisco Coelho
Paper draft: Exte...
|
130
|
"""Event superset test."""
|
677cc471
Francisco Coelho
Further progress ...
|
131
132
133
134
|
return self._literals.__ge__(other._literals)
def __gt__(self, other):
|
d080b400
Francisco Coelho
Paper draft: Exte...
|
135
|
"""Event strict superset test."""
|
677cc471
Francisco Coelho
Further progress ...
|
136
137
138
139
140
|
return self._literals.__gt__(other._literals)
class Lattice:
|
677cc471
Francisco Coelho
Further progress ...
|
141
142
|
@staticmethod
def parse(d):
|
d080b400
Francisco Coelho
Paper draft: Exte...
|
143
144
145
146
147
148
149
150
151
152
153
154
155
|
"""Input stable models.
The input format is a dictionary associating a stable model in string form to an weight.
For example:
input_dict = {
"A": 0.3,
"ab": 0.2,
"ac": 0.5
}
smodels = Lattice.parse(input_dict)
"""
|
aa257377
Francisco Coelho
Post meeting 2022...
|
156
157
|
result = dict()
for k, v in d.items():
|
d080b400
Francisco Coelho
Paper draft: Exte...
|
158
|
key = Event.parse(k)
|
aa257377
Francisco Coelho
Post meeting 2022...
|
159
160
|
result[key] = v
return result
|
aa257377
Francisco Coelho
Post meeting 2022...
|
161
162
|
|
aa257377
Francisco Coelho
Post meeting 2022...
|
163
|
@staticmethod
|
d080b400
Francisco Coelho
Paper draft: Exte...
|
164
165
166
167
168
|
def close_literals(events):
"""Closed set of literals entailed by a set of events.
Includes the literals in the set of events and any missing negation."""
base_lits = list(accumulate(events, func=operator.or_))[-1]
|
677cc471
Francisco Coelho
Further progress ...
|
169
170
|
lits = set()
for x in base_lits.literals():
|
aa257377
Francisco Coelho
Post meeting 2022...
|
171
172
|
lits.add(x)
lits.add(x.swapcase())
|
d080b400
Francisco Coelho
Paper draft: Exte...
|
173
|
return sorted(lits)
|
aa257377
Francisco Coelho
Post meeting 2022...
|
174
|
|
677cc471
Francisco Coelho
Further progress ...
|
175
|
def __init__(self, smodels_dict):
|
d080b400
Francisco Coelho
Paper draft: Exte...
|
176
|
"""Create an Events lattice."""
|
677cc471
Francisco Coelho
Further progress ...
|
177
178
|
self._smodels = smodels_dict
self._literals = Lattice.close_literals(self._smodels.keys())
|
aa257377
Francisco Coelho
Post meeting 2022...
|
179
180
|
def literals(self):
|
d080b400
Francisco Coelho
Paper draft: Exte...
|
181
|
"""The literals in this lattice."""
|
aa257377
Francisco Coelho
Post meeting 2022...
|
182
183
|
return self._literals
|
d080b400
Francisco Coelho
Paper draft: Exte...
|
184
|
@cache
|
aa257377
Francisco Coelho
Post meeting 2022...
|
185
|
def stable_models(self):
|
d080b400
Francisco Coelho
Paper draft: Exte...
|
186
187
|
"""The stable models that generate this lattice."""
return self._smodels.keys()
|
aa257377
Francisco Coelho
Post meeting 2022...
|
188
|
|
d080b400
Francisco Coelho
Paper draft: Exte...
|
189
190
191
192
|
#@cache
def events(self):
"""All the events of this lattice."""
return chain.from_iterable(map(Event, combinations(self._literals, r)) for r in range(len(self._literals)+1))
|
aa257377
Francisco Coelho
Post meeting 2022...
|
193
194
|
@cache
|
d080b400
Francisco Coelho
Paper draft: Exte...
|
195
196
197
198
199
200
201
202
|
def stable_core(self, event):
"""The stable core of an event in this lattice."""
return set(filter(lambda sm: sm <= event or event <= sm, self.stable_models()))
# @cache
# def event_class(self, event):
# """The equivalence class of an event."""
# return EventsClass(self.stable_core(event), self)
|
677cc471
Francisco Coelho
Further progress ...
|
203
|
|
d080b400
Francisco Coelho
Paper draft: Exte...
|
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
|
@cache
def classes(self):
"""The classes of this lattice.
Each class is presented as a key:value pair where the "key" is the stable core of the elements in "value"."""
map_ev_classes = [(e, tuple(self.stable_core(e))) for e in self.events() if e.is_consistent()]
groups = dict()
for e,c in map_ev_classes:
if c in groups.keys():
groups[c].add(e)
else:
groups[c] = set([e])
inconsistent = list(e for e in self.events() if not e.is_consistent())
inconsistent_repr = inconsistent[0]
groups[(inconsistent_repr,)] = set(inconsistent)
return groups
|
677cc471
Francisco Coelho
Further progress ...
|
220
|
|
aa257377
Francisco Coelho
Post meeting 2022...
|
221
222
|
def related(self, u, v):
|
d080b400
Francisco Coelho
Paper draft: Exte...
|
223
|
"""Tests if two events are related."""
|
677cc471
Francisco Coelho
Further progress ...
|
224
225
|
u_consistent = u.is_consistent()
v_consistent = v.is_consistent()
|
aa257377
Francisco Coelho
Post meeting 2022...
|
226
|
if u_consistent and (u_consistent == v_consistent):
|
d080b400
Francisco Coelho
Paper draft: Exte...
|
227
|
return self.stable_core(u) == self.stable_core(v)
|
aa257377
Francisco Coelho
Post meeting 2022...
|
228
229
230
|
else:
return u_consistent == v_consistent
|
d080b400
Francisco Coelho
Paper draft: Exte...
|
231
232
233
|
def extended_value(self, event:Event,
op=prod_op):
"""TODO: well..."""
|
677cc471
Francisco Coelho
Further progress ...
|
234
|
value = 0
|
d080b400
Francisco Coelho
Paper draft: Exte...
|
235
236
237
|
#
# INCONSISTENT EVENTS
#
|
677cc471
Francisco Coelho
Further progress ...
|
238
239
|
if not event.is_consistent():
return value
|
d080b400
Francisco Coelho
Paper draft: Exte...
|
240
241
242
243
244
245
246
247
248
249
|
#
# CONSISTENT EVENTS
#
score = self.stable_core(event)
len_score = len(score)
# CONSISTENT, INDEPENDENT
if len_score == 0:
value = 0
elif len_score == 1:
value = self._smodels[score[0]]
|
aa257377
Francisco Coelho
Post meeting 2022...
|
250
|
else:
|
d080b400
Francisco Coelho
Paper draft: Exte...
|
251
|
value = op(map(lambda sm: self._smodels[sm], score))
|
aa257377
Francisco Coelho
Post meeting 2022...
|
252
253
254
|
return value
|
677cc471
Francisco Coelho
Further progress ...
|
255
|
def __repr__(self):
|
d080b400
Francisco Coelho
Paper draft: Exte...
|
256
|
smodels_repr = ',\n\t\t'.join(f"{k}: {v:<}" for k,v in self._smodels.items())
|
677cc471
Francisco Coelho
Further progress ...
|
257
|
lits_repr = ','.join(sorted(self._literals))
|
aa257377
Francisco Coelho
Post meeting 2022...
|
258
|
|
677cc471
Francisco Coelho
Further progress ...
|
259
260
261
262
|
return "{\n" +\
f"\t'stable_models': {{\n\t\t {smodels_repr} \n\t}}\n" +\
f"\t'literals': {{ {lits_repr} }} \n" +\
"}"
|
aa257377
Francisco Coelho
Post meeting 2022...
|
263
|
|
d080b400
Francisco Coelho
Paper draft: Exte...
|
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
|
# class EventsClass:
# def __init__(self, core, lattice:Lattice):
# self._core = core
# self._lattice = lattice
# def __repr__(self):
# core_repr = "" if len(self._core) == 0 else ",".join(str(x) for x in self._core)
# return f"<{core_repr}>"
# def __contains__(self, event:Event):
# return self.lattice.stable_core(event) == self._core
if __name__ == "__main__":
def zoom_event(event_str, lattice):
event = Event.parse(event_str)
event_class = lattice.event_class(event)
propagated = lattice.extended_value(
event)
print(
f"Event: {event}\n\tClass: {event_class} \n\tValue: {propagated}")
smodels = Lattice.parse({
"A": 2,
"ab": 3,
"ac": 5
})
lattice = Lattice(smodels)
ev_classes = lattice.classes()
for k,g in ev_classes.items():
print(f"{tuple(s.latex() for s in k)} {set(e.latex() for e in g)}")
# zoom_event("abc", lattice)
# zoom_event("a", lattice)
# zoom_event("b", lattice)
# zoom_event("bc", lattice)
# zoom_event("ac", lattice)
|