diff --git a/.vscode/launch.json b/.vscode/launch.json index 306f58e..2f506e4 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -4,6 +4,8 @@ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ + + { "name": "Python: Current File", "type": "python", diff --git a/code/python/EventLattice.ipynb b/code/python/EventLattice.ipynb index 6fa5074..8cd7d9e 100644 --- a/code/python/EventLattice.ipynb +++ b/code/python/EventLattice.ipynb @@ -2,26 +2,37 @@ "cells": [ { "cell_type": "code", - "execution_count": 7, + "execution_count": 4, "id": "57fc5921-9d6b-4b43-a8f6-743a03650d63", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The autoreload extension is already loaded. To reload it, use:\n", + " %reload_ext autoreload\n" + ] + } + ], "source": [ - "import event_lattice as el" + "%load_ext autoreload\n", + "%autoreload 1\n", + "%aimport event_lattice" ] }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 5, "id": "00f0eb68", "metadata": {}, "outputs": [], "source": [ - "def zoom_event(event_str, lattice, lower_op=el.sum_op, upper_op=el.prod_op):\n", - " event = el.Event.from_str(event_str)\n", + "def zoom_event(event_str, lattice):\n", + " event = event_lattice.Event.from_str(event_str)\n", " event_class = lattice.event_class(event)\n", - " propagated = lattice.propagated_value(\n", - " event, lower_op=lower_op, upper_op=upper_op)\n", + " propagated = lattice.extended_value(\n", + " event)\n", "\n", " print(\n", " f\"Event: {event}\\n\\tClass: {event_class} \\n\\tValue: {propagated}\")" @@ -29,7 +40,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 6, "id": "cdd8c6d6", "metadata": {}, "outputs": [ @@ -49,42 +60,34 @@ } ], "source": [ - "smodels = el.Lattice.parse({\n", + "smodels = event_lattice.Lattice.parse({\n", " \"A\": 2,\n", " \"ab\": 3,\n", " \"ac\": 5\n", "})\n", "\n", - "lattice = el.Lattice(smodels)\n", + "lattice = event_lattice.Lattice(smodels)\n", "\n", "print(lattice)" ] }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 7, "id": "2b445339", "metadata": {}, "outputs": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - "Event: abc\n", - "\tClass: <|ac,ab> \n", - "\tValue: 8\n", - "Event: a\n", - "\tClass: \n", - "\tValue: 15\n", - "Event: b\n", - "\tClass: \n", - "\tValue: 3\n", - "Event: bc\n", - "\tClass: <|> \n", - "\tValue: 0\n", - "Event: ac\n", - "\tClass: \n", - "\tValue: 5\n" + "ename": "TypeError", + "evalue": "__init__() missing 1 required positional argument: 'lattice'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m/tmp/ipykernel_361713/2581811254.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mzoom_event\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"abc\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlattice\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2\u001b[0m \u001b[0mzoom_event\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"a\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlattice\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0mzoom_event\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"b\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlattice\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0mzoom_event\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"bc\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlattice\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0mzoom_event\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"ac\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlattice\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/tmp/ipykernel_361713/1675915232.py\u001b[0m in \u001b[0;36mzoom_event\u001b[0;34m(event_str, lattice)\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mzoom_event\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mevent_str\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlattice\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0mevent\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mevent_lattice\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mEvent\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfrom_str\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mevent_str\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0mevent_class\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mlattice\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mevent_class\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mevent\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 4\u001b[0m propagated = lattice.extended_value(\n\u001b[1;32m 5\u001b[0m event)\n", + "\u001b[0;32m~/sci/projetos/zugzwang/code/python/event_lattice.py\u001b[0m in \u001b[0;36mevent_class\u001b[0;34m(self, event)\u001b[0m\n\u001b[1;32m 146\u001b[0m \u001b[0;34m@\u001b[0m\u001b[0mcache\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 147\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mevent_class\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mevent\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 148\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mEventsClass\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mstable_core\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mevent\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 149\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 150\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mrelated\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mu\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mv\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mTypeError\u001b[0m: __init__() missing 1 required positional argument: 'lattice'" ] } ], @@ -98,209 +101,10 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "id": "f1b85255", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Event: \n", - "\tClass: \n", - "\tValue: 30\n", - "Event: A\n", - "\tClass: \n", - "\tValue: 2\n", - "Event: b\n", - "\tClass: \n", - "\tValue: 3\n", - "Event: a\n", - "\tClass: \n", - "\tValue: 15\n", - "Event: B\n", - "\tClass: <|> \n", - "\tValue: 0\n", - "Event: c\n", - "\tClass: \n", - "\tValue: 5\n", - "Event: C\n", - "\tClass: <|> \n", - "\tValue: 0\n", - "Event: Ab\n", - "\tClass: <|A> \n", - "\tValue: 2\n", - "Event: Aa\n", - "\tClass: <|A> \n", - "\tValue: 0\n", - "Event: AB\n", - "\tClass: <|A> \n", - "\tValue: 2\n", - "Event: Ac\n", - "\tClass: <|A> \n", - "\tValue: 2\n", - "Event: AC\n", - "\tClass: <|A> \n", - "\tValue: 2\n", - "Event: ab\n", - "\tClass: \n", - "\tValue: 3\n", - "Event: Bb\n", - "\tClass: <|> \n", - "\tValue: 0\n", - "Event: bc\n", - "\tClass: <|> \n", - "\tValue: 0\n", - "Event: Cb\n", - "\tClass: <|> \n", - "\tValue: 0\n", - "Event: Ba\n", - "\tClass: <|> \n", - "\tValue: 0\n", - "Event: ac\n", - "\tClass: \n", - "\tValue: 5\n", - "Event: Ca\n", - "\tClass: <|> \n", - "\tValue: 0\n", - "Event: Bc\n", - "\tClass: <|> \n", - "\tValue: 0\n", - "Event: BC\n", - "\tClass: <|> \n", - "\tValue: 0\n", - "Event: Cc\n", - "\tClass: <|> \n", - "\tValue: 0\n", - "Event: Aab\n", - "\tClass: <|A,ab> \n", - "\tValue: 0\n", - "Event: ABb\n", - "\tClass: <|A> \n", - "\tValue: 0\n", - "Event: Abc\n", - "\tClass: <|A> \n", - "\tValue: 2\n", - "Event: ACb\n", - "\tClass: <|A> \n", - "\tValue: 2\n", - "Event: ABa\n", - "\tClass: <|A> \n", - "\tValue: 0\n", - "Event: Aac\n", - "\tClass: <|A,ac> \n", - "\tValue: 0\n", - "Event: ACa\n", - "\tClass: <|A> \n", - "\tValue: 0\n", - "Event: ABc\n", - "\tClass: <|A> \n", - "\tValue: 2\n", - "Event: ABC\n", - "\tClass: <|A> \n", - "\tValue: 2\n", - "Event: ACc\n", - "\tClass: <|A> \n", - "\tValue: 0\n", - "Event: Bab\n", - "\tClass: <|ab> \n", - "\tValue: 0\n", - "Event: abc\n", - "\tClass: <|ac,ab> \n", - "\tValue: 8\n", - "Event: Cab\n", - "\tClass: <|ab> \n", - "\tValue: 3\n", - "Event: Bbc\n", - "\tClass: <|> \n", - "\tValue: 0\n", - "Event: BCb\n", - "\tClass: <|> \n", - "\tValue: 0\n", - "Event: Cbc\n", - "\tClass: <|> \n", - "\tValue: 0\n", - "Event: Bac\n", - "\tClass: <|ac> \n", - "\tValue: 5\n", - "Event: BCa\n", - "\tClass: <|> \n", - "\tValue: 0\n", - "Event: Cac\n", - "\tClass: <|ac> \n", - "\tValue: 0\n", - "Event: BCc\n", - "\tClass: <|> \n", - "\tValue: 0\n", - "Event: ABab\n", - "\tClass: <|A,ab> \n", - "\tValue: 0\n", - "Event: Aabc\n", - "\tClass: <|A,ac,ab> \n", - "\tValue: 0\n", - "Event: ACab\n", - "\tClass: <|A,ab> \n", - "\tValue: 0\n", - "Event: ABbc\n", - "\tClass: <|A> \n", - "\tValue: 0\n", - "Event: ABCb\n", - "\tClass: <|A> \n", - "\tValue: 0\n", - "Event: ACbc\n", - "\tClass: <|A> \n", - "\tValue: 0\n", - "Event: ABac\n", - "\tClass: <|A,ac> \n", - "\tValue: 0\n", - "Event: ABCa\n", - "\tClass: <|A> \n", - "\tValue: 0\n", - "Event: ACac\n", - "\tClass: <|A,ac> \n", - "\tValue: 0\n", - "Event: ABCc\n", - "\tClass: <|A> \n", - "\tValue: 0\n", - "Event: Babc\n", - "\tClass: <|ac,ab> \n", - "\tValue: 0\n", - "Event: BCab\n", - "\tClass: <|ab> \n", - "\tValue: 0\n", - "Event: Cabc\n", - "\tClass: <|ac,ab> \n", - "\tValue: 0\n", - "Event: BCbc\n", - "\tClass: <|> \n", - "\tValue: 0\n", - "Event: BCac\n", - "\tClass: <|ac> \n", - "\tValue: 0\n", - "Event: ABabc\n", - "\tClass: <|A,ac,ab> \n", - "\tValue: 0\n", - "Event: ABCab\n", - "\tClass: <|A,ab> \n", - "\tValue: 0\n", - "Event: ACabc\n", - "\tClass: <|A,ac,ab> \n", - "\tValue: 0\n", - "Event: ABCbc\n", - "\tClass: <|A> \n", - "\tValue: 0\n", - "Event: ABCac\n", - "\tClass: <|A,ac> \n", - "\tValue: 0\n", - "Event: BCabc\n", - "\tClass: <|ac,ab> \n", - "\tValue: 0\n", - "Event: ABCabc\n", - "\tClass: <|A,ac,ab> \n", - "\tValue: 0\n" - ] - } - ], + "outputs": [], "source": [ "from itertools import *\n", "\n", diff --git a/code/python/__pycache__/event_lattice.cpython-39.pyc b/code/python/__pycache__/event_lattice.cpython-39.pyc index 886bb1d..a72fa05 100644 Binary files a/code/python/__pycache__/event_lattice.cpython-39.pyc and b/code/python/__pycache__/event_lattice.cpython-39.pyc differ diff --git a/code/python/event_lattice.py b/code/python/event_lattice.py index 9b6376d..899d260 100644 --- a/code/python/event_lattice.py +++ b/code/python/event_lattice.py @@ -1,6 +1,6 @@ import math from functools import cache -from itertools import accumulate +from itertools import accumulate, combinations, chain, groupby import operator @@ -32,21 +32,31 @@ def prod_op(x): class Event: - """"Events.""" + """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. + """ @staticmethod - def parse(text): + def _parse(text): return frozenset(text) @staticmethod - def from_str(text): - return Event(Event.parse(text)) + def parse(text): + """Convert a string to an event. + + Each letter in the string represents a literal. + """ + return Event(Event._parse(text)) def __init__(self, literals): """Instantiate from a (frozen) set of literals. For example: e = Event(frozenset("abc")).""" - self._literals = literals + self._literals = frozenset(literals) def literals(self): @@ -55,56 +65,74 @@ class Event: def __iter__(self): return self._literals.__iter__() - - - def co(self): - """Negation is case based: A = not a; a = not A.""" - return Event(x.swapcase() for x in self._literals) - @cache def is_consistent(self): + """True if this event is consistent.""" return all(x.swapcase() not in self._literals for x in self._literals) - def __hash__(self) -> int: - return self._literals.__hash__() + 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) - def __eq__(self, other): - return self._literals.__eq__(other._literals) + def invert(self): + """Negation of this event. + See the method "co" + """ + return self.co() def __repr__(self) -> str: - return ''.join(str(x) for x in sorted(self._literals)) + return ''.join(str(x) for x in sorted(self._literals)) if len(self._literals) > 0 else '0' - def invert(self): - return self.co() + 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__() def __eq__(self, other): + """Event equality test.""" return self._literals.__eq__(other._literals) def __or__(self, other): + """Event union operation.""" return Event(self._literals | other._literals) - def __le__(self, other): + """Event subset test.""" return self._literals.__le__(other._literals) def __lt__(self, other): + """Event strict subset test.""" return self._literals.__lt__(other._literals) def __ne__(self, other): + """Event not-equal test.""" return self._literals.__ne__(other._literals) def __ge__(self, other): + """Event superset test.""" return self._literals.__ge__(other._literals) def __gt__(self, other): + """Event strict superset test.""" return self._literals.__gt__(other._literals) @@ -112,87 +140,120 @@ class Lattice: @staticmethod def parse(d): + """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) + """ result = dict() for k, v in d.items(): - key = Event.from_str(k) + key = Event.parse(k) result[key] = v return result @staticmethod - def close_literals(smodels): - base_lits = list(accumulate(smodels, func=operator.or_))[-1] + 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] lits = set() for x in base_lits.literals(): lits.add(x) lits.add(x.swapcase()) - return lits + return sorted(lits) def __init__(self, smodels_dict): - """Create base for Events Lattice.""" + """Create an Events lattice.""" self._smodels = smodels_dict self._literals = Lattice.close_literals(self._smodels.keys()) def literals(self): + """The literals in this lattice.""" return self._literals + @cache def stable_models(self): - return list(map(set, self._smodels.keys())) + """The stable models that generate this lattice.""" + return self._smodels.keys() - @cache - def lower_bound(self, event): - return list(set(filter(lambda sm: sm <= event, self._smodels))) + #@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)) @cache - def upper_bound(self, event): - return list(set(filter(lambda sm: event <= sm, self._smodels))) + 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) + @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 - def event_class(self, event): - return EventsClass( - self.upper_bound(event), - self.lower_bound(event), - self) def related(self, u, v): + """Tests if two events are related.""" u_consistent = u.is_consistent() v_consistent = v.is_consistent() if u_consistent and (u_consistent == v_consistent): - return \ - self.lower_bound(u) == self.lower_bound(v) and \ - self.upper_bound(u) == self.upper_bound(v) + return self.stable_core(u) == self.stable_core(v) else: return u_consistent == v_consistent - def factors(self, event): - return [self.lower_bound(event), self.upper_bound(event)] - - def propagated_value(self, event:Event, - lower_op=sum_op, - upper_op=prod_op): + def extended_value(self, event:Event, + op=prod_op): + """TODO: well...""" value = 0 - + # + # INCONSISTENT EVENTS + # if not event.is_consistent(): return value - - lb = self.lower_bound(event) - len_lb = len(lb) - if len_lb > 1: - value = lower_op(map(lambda sm: self._smodels[sm], lb)) - elif len_lb == 1: - value = self._smodels[lb[0]] + # + # 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]] else: - ub = self.upper_bound(event) - len_ub = len(ub) - if len_ub > 1: - value = upper_op(map(lambda sm: self._smodels[sm], ub)) - elif len_ub == 1: - value = self._smodels[ub[0]] + value = op(map(lambda sm: self._smodels[sm], score)) return value def __repr__(self): - smodels_repr = ',\n\t\t'.join(f"{Event.from_str(k)}: {v:>5}" for k,v in self._smodels.items()) + smodels_repr = ',\n\t\t'.join(f"{k}: {v:<}" for k,v in self._smodels.items()) lits_repr = ','.join(sorted(self._literals)) return "{\n" +\ @@ -200,19 +261,41 @@ class Lattice: f"\t'literals': {{ {lits_repr} }} \n" +\ "}" - - -class EventsClass: - def __init__(self, upper, lower, lattice:Lattice): - self._upper = upper - self._lower = lower - self._lattice = lattice - - def __repr__(self): - upper_repr = "" if len(self._upper) == 0 else ",".join(str(x) for x in self._upper) - lower_repr = "" if len(self._lower) == 0 else ",".join(str(x) for x in self._lower) - return f"<{upper_repr}|{lower_repr}>" - - def __contains__(self, event:Event): - return self.lattice.lower_bound(event) == self._lower and \ - self.lattice.upper_bound(event) == self._upper \ No newline at end of file +# 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) \ No newline at end of file diff --git a/students/amartins/tarefas/.ipynb_checkpoints/Untitled-checkpoint.ipynb b/students/amartins/tarefas/.ipynb_checkpoints/Untitled-checkpoint.ipynb new file mode 100644 index 0000000..363fcab --- /dev/null +++ b/students/amartins/tarefas/.ipynb_checkpoints/Untitled-checkpoint.ipynb @@ -0,0 +1,6 @@ +{ + "cells": [], + "metadata": {}, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/students/amartins/tarefas/.ipynb_checkpoints/Untitled1-checkpoint.ipynb b/students/amartins/tarefas/.ipynb_checkpoints/Untitled1-checkpoint.ipynb new file mode 100644 index 0000000..363fcab --- /dev/null +++ b/students/amartins/tarefas/.ipynb_checkpoints/Untitled1-checkpoint.ipynb @@ -0,0 +1,6 @@ +{ + "cells": [], + "metadata": {}, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/students/amartins/tarefas/.ipynb_checkpoints/tarefa1b-checkpoint.py b/students/amartins/tarefas/.ipynb_checkpoints/tarefa1b-checkpoint.py new file mode 100644 index 0000000..f0ddec1 --- /dev/null +++ b/students/amartins/tarefas/.ipynb_checkpoints/tarefa1b-checkpoint.py @@ -0,0 +1,35 @@ +import bnlearn as bn +import networkx as nx +import pydot +from networkx.drawing.nx_pydot import graphviz_layout + +asia = bn.import_DAG("asia2.bif") +model = asia['model'] + +# DiGraph do networkx +G = nx.DiGraph() + +for node in model.nodes: + G.add_node(node) + +for edge in model.edges: + G.add_edge(edge[0], edge[1]) + +# objeto pydot +dot = pydot.Dot(graph_type='digraph') + +for node in model.nodes: + dot.add_node(pydot.Node(node)) + +for edge in model.edges: + dot.add_edge(pydot.Edge(edge[0], edge[1])) + +# defina o layout do grafo +pos = graphviz_layout(G, prog='dot') + +# desenhe o grafo usando o networkx +nx.draw(G, pos, with_labels=True) + +# renderize o grafo com o pydot +graph = pydot.graph_from_dot_data(dot.to_string())[0] +graph.write_png('graph_asia2.png') diff --git a/students/amartins/tarefas/Untitled.ipynb b/students/amartins/tarefas/Untitled.ipynb new file mode 100644 index 0000000..363fcab --- /dev/null +++ b/students/amartins/tarefas/Untitled.ipynb @@ -0,0 +1,6 @@ +{ + "cells": [], + "metadata": {}, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/students/amartins/tarefas/notas.md b/students/amartins/tarefas/notas.md new file mode 100644 index 0000000..2235c4a --- /dev/null +++ b/students/amartins/tarefas/notas.md @@ -0,0 +1,67 @@ +# Notas com Alice Martins + +## 2023-05-04 + +### Problemas + +#### Tarefa 1A + +1. Está a contar os nós "in" e os nós "out" ao contrário, certo? `len(children)` diz quantas arestas saem de `x`. +2. Em + ```python + if len(parents) != 0: + asc += 1 + if len(children) != 0: + des += 1 + ``` + deve ser + ```python + if len(parents) != 0: + des += 1 + if len(children) != 0: + asc += 1 + ``` + porque o nó `x` é (mais) um descendente se tem ascendentes (e igualmente para ascendente). + +#### Tarefa 1B + +1. Não deve misturar o código para definir o grafo `G` com o código para o grafo `dot`. **Exceto** se quiser percorrer apenas uma vez `model.nodes` e `model.edges`. + +### Sugestões + +- **Use sempre, e só, o inglês no seu código**, não só porque não se podem usar acentos, como `nós_in`, mas também porque misturar português com inglês fica estranho (isto é, _feio_!). É melhor `nodes_in` do que `nos_in`. +- Use nomes descritivos nas suas variáveis: `node` em vez de `x`. +- Em vez de `asia = bn.import_DAG("asia2.bif")` talvez `dag = bn.import_DAG("asia2.bif")` seja melhor (**porquê?**) +- O código também fica mais simples se usar "f-strings": Em vez de + ```python + print("Número de nós:", len(nos)) + ``` + use + ```python + print(f"Número de nós: {len(nos)}") + ``` +### Desafios + +1. **Torne o seu código geral.** + 1. Coloque a parte essencial da tarefa 1A numa função, `summary_dag(filename)`, que tem argumento uma `string` com o nome do ficheiro e devolve um `dict` com chaves `dag_file`, `nodes`, `count_parents`, `count_children`, `count_in_edges`, `count_out_edges`. + 2. Use uma função `summary_str(d)` que tem argumento um `dict` como acima e devolve uma `string` com as perguntas e as respostas "bem formatadas". Por exemplo: + ```text + DAG file: asia2.bif + Number of nodes: 8 + Number of parents: 6 + Number of children: 6 + Average in-degree: 1.0 + Average out-degree: 1.0 + Nodes: + asia + tub + ... + ``` + 3. Por fim, combine as duas funções: + ```python + summary = summary_dag("asia2.bif") + message = summary_str(summary) + print(message) + ``` + 4. Coloque a parte essencial da tarefa 1B em funções `show_dag(model)` e `save_dag(model, target_filename)`. +2. **A biblioteca `bnlearn` é excessiva para estas tarefas.** Não só precisa de várias dependências irrelevantes para o que pretendemos, por exemplo o `pytorch`, como demora imenso tempo a ler o ficheiro. _Procure uma alternativa mais simples._ (**n.b.** não sei se existe!) \ No newline at end of file diff --git a/students/amartins/tarefas/tarefa1.py b/students/amartins/tarefas/tarefa1.py new file mode 100644 index 0000000..a956d45 --- /dev/null +++ b/students/amartins/tarefas/tarefa1.py @@ -0,0 +1,81 @@ +from pgmpy.readwrite import BIFReader +import networkx as nx +import pydot +from networkx.drawing.nx_pydot import graphviz_layout + +def summary_dag(filename): + file = BIFReader(filename) + model = file.get_model() # Cria um objeto BayesianModel + nodes = model.nodes() + + asc = 0 + des = 0 + nodes_in = 0 + nodes_out = 0 + + for x in nodes: + # Obtem os nós pais e filhos de cada nós + parents = model.get_parents(x) + children = model.get_children(x) + + if len(parents) != 0: + des += 1 + if len(children) != 0: + asc += 1 + nodes_in += len(children) + nodes_out += len(parents) + + return {'dag_file': filename, 'nodes': nodes, 'count_parents': des, 'count_children': asc, 'count_in_edges': nodes_in, 'count_out_edges': nodes_out} + +def summary_str(d): + s = "DAG file: " + d["dag_file"] + "\n" + s += " Number of nodes: " + str(len(d["nodes"])) + "\n" + s += " Number of parents: " + str(d["count_parents"]) + "\n" + s += " Number of children: " + str(d["count_children"]) + "\n" + s += " Average in-degree: " + str(d["count_in_edges"]/len(d["nodes"])) + "\n" + s += " Average out-degree: " + str(d["count_out_edges"]/len(d["nodes"])) + "\n" + s += " Nodes:" + "\n" + nodes = d["nodes"] + for x in nodes: + s += " " + str(x) + "\n" + return s + +def show_dag(model): + G = nx.DiGraph() + for node in model.nodes: + G.add_node(node) + for edge in model.edges: + G.add_edge(edge[0], edge[1]) + # objeto pydot + dot = pydot.Dot(graph_type='digraph') + for node in model.nodes: + dot.add_node(pydot.Node(node)) + for edge in model.edges: + dot.add_edge(pydot.Edge(edge[0], edge[1])) + # defina o layout do grafo + pos = graphviz_layout(G, prog='dot') + # desenhe o grafo usando o networkx + nx.draw(G, pos, with_labels=True) + +def save_dag(model, target_filename): + G = nx.DiGraph() + for node in model.nodes: + G.add_node(node) + for edge in model.edges: + G.add_edge(edge[0], edge[1]) + # objeto pydot + dot = pydot.Dot(graph_type='digraph') + for node in model.nodes: + dot.add_node(pydot.Node(node)) + for edge in model.edges: + dot.add_edge(pydot.Edge(edge[0], edge[1])) + # defina o layout do grafo + pos = graphviz_layout(G, prog='dot') + # renderize o grafo com o pydot + graph = pydot.graph_from_dot_data(dot.to_string())[0] + graph.write_png(target_filename) + + +summary = summary_dag("asia2.bif") +message = summary_str(summary) +print(message) \ No newline at end of file diff --git a/students/amartins/tarefas/tarefa1a.py b/students/amartins/tarefas/tarefa1a.py index a6c2fc4..f53898e 100644 --- a/students/amartins/tarefas/tarefa1a.py +++ b/students/amartins/tarefas/tarefa1a.py @@ -32,7 +32,7 @@ for x in nos: print("Nós ascendentes: ", asc) print("Nós descendentes: ", des) # resposta à pergunta "qual é o número médio de arestas "in"? e "out"?" -nos_in = nos_in/len(nos) -nos_out = nos_out/len(nos) +nos_in = float(nos_in/len(nos)) +nos_out = float(nos_out/len(nos)) print("Número médio de arestas in: ", nos_in) print("Número médio de arestas out: ", nos_out) \ No newline at end of file diff --git a/text/paper_01/pre-paper.pdf b/text/paper_01/pre-paper.pdf index 8d0fb21..76371b9 100644 Binary files a/text/paper_01/pre-paper.pdf and b/text/paper_01/pre-paper.pdf differ diff --git a/text/paper_01/pre-paper.tex b/text/paper_01/pre-paper.tex index f11334c..c7ff9db 100644 --- a/text/paper_01/pre-paper.tex +++ b/text/paper_01/pre-paper.tex @@ -246,6 +246,8 @@ The stable models $ab, ac$ from \cref{running.example} result from the clause $b The diagram in \cref{F:stableexample} illustrates the problem of extending probabilities from total choice nodes to stable models and then to general events in a \emph{node-wise} process. This quickly leads to coherence problems concerning probability, with no clear systematic approach --- Instead, weight extension can be based in the relation an event has with the stable models. +\subsection{An Equivalence Relation}\label{subsec:equivalence.relation} + Given an ASP specification % DONE: {\bruno This should be defined somewhere (maybe in the introduction).} \remark{{\bruno Introduce also the sets mentioned below}}{how?} @@ -277,24 +279,24 @@ This focus on the \acp{SM} leads to the following definition: % \lset{e} = \set{s \in \fml{S} \given e \supseteq s}, \label{eq:lset} % \end{equation} % \begin{equation} - % \stablecore{e} = \uset{e} \cup \lset{e} \label{eq:xset} + % \stablecore{e} = \uset{e} \cup \lset{e} \label{def:stable.core} % \end{equation} \begin{equation} - \stablecore{e} := \set{s \in \fml{S} \given e \subseteq s \vee s \subseteq e} \label{eq:xset} + \stablecore{e} := \set{s \in \fml{S} \given e \subseteq s \vee s \subseteq e} \label{eq:stable.core} \end{equation} \end{definition} We now define an equivalence relation, $\sim$, so that two events are related if they are either both inconsistent or both consistent with the same stable core. -\begin{definition}\label{D:equiv.rel} +\begin{definition}\label{def:equiv.rel} For a given specification, let $u, v \in \fml{E}$. The equivalence relation $\sim$ is defined by \begin{equation} - u \sim v :\iff u,v \not\in\fml{W} \vee \del{u,v \in \fml{W} \wedge \stablecore{u} = \stablecore{v}}.\label{eq:rel.events} + u \sim v :\iff u,v \not\in\fml{W} \vee \del{u,v \in \fml{W} \wedge \stablecore{u} = \stablecore{v}}.\label{eq:equiv.rel} \end{equation} \end{definition} -Observe that the minimality of stable models implies that, in \cref{eq:xset}, either $e$ is a stable model or one of $e \subseteq s, s \subseteq e$ is never true. +Observe that the minimality of stable models implies that, in \cref{def:stable.core}, either $e$ is a stable model or one of $e \subseteq s, s \subseteq e$ is never true. % % \begin{definition}\label{def:smodel.events} % For $\set{s_1, \ldots, s_n} \subseteq \fml{S}$ define @@ -321,21 +323,21 @@ This relation defines a partition of the events space, where each class holds a \set{u \in \fml{W} \given \stablecore{u} = \stablecore{e}} &\text{if~} e \in \fml{W}, \\ % \lclass{\uset{e}} &\text{if~} \uset{e} \not= \emptyset, \\ % \uclass{\lset{e}} &\text{otherwise}. - \end{cases} + \end{cases}\label{eq:event.class} \end{equation} -The stable core defines a \emph{canonical} representative of each class: -\begin{theorem} - Let $e\in\fml{E}$ and $\stablecore{e} = \set{s_1, \ldots, s_n} \subseteq \fml{S}$. Then - \begin{equation} - \class{e} = \class{s_1 \cup \cdots \cup s_n}. - \end{equation} - We simplify the notation with $\class{s_1, \ldots, s_n} := \class{s_1 \cup \cdots \cup s_n}$. - \todo{This only works for consistent $s_1, \ldots, s_n$: $\set{\set{}} = \class{\co{a}, ab, ac} \not= \class{a\co{a}bc} = \inconsistent$.} -\end{theorem} -\begin{proof} -\todo{tbd} -\end{proof} +% The stable core defines a \emph{canonical} representative of each class: +% \begin{theorem} +% Let $e\in\fml{E}$ and $\stablecore{e} = \set{s_1, \ldots, s_n} \subseteq \fml{S}$. Then +% \begin{equation} +% \class{e} = \class{s_1 \cup \cdots \cup s_n}. +% \end{equation} +% We simplify the notation with $\class{s_1, \ldots, s_n} := \class{s_1 \cup \cdots \cup s_n}$. +% \todo{This only works for consistent $s_1, \ldots, s_n$: $\set{\set{}} = \class{\co{a}, ab, ac} \not= \class{a\co{a}bc} = \inconsistent$.} +% \end{theorem} +% \begin{proof} +% \todo{tbd} +% \end{proof} The subsets of the stable models, together with $\inconsistent$, form a set of representatives. Consider again Example~\ref{running.example}. As previously mentioned, the stable models are $\fml{S} = \co{a}, ab, ac$ so the quotient set of this relation is $\class{\fml{E}}:$ \begin{equation} @@ -388,19 +390,21 @@ For example, % \item The extended probability \emph{events} are the \emph{classes}. \end{itemize} +\subsection{From Total Choices to Events}\label{subsec:from.tchoices.to.events} + \todo{Check adaptation} Our path to set a probability measure on $\fml{E}$ has two phases: \begin{itemize} \item Extending the probabilities, \emph{as weights}, of the total choices to events. \item Normalization of the weights. \end{itemize} -The ``extension'' phase, traced by equations (\ref{eq:prob.total.choice}) and (\ref{eq:weight.tchoice} --- \ref{eq:weight.events}), starts with the weight (probability) of total choices, $\pw{c} = \pr{C = c}$, expands it to stable models, $\pw{s}$, and then, within the equivalence relation from Equation \eqref{eq:rel.events}, to (general) events, $\pw{e}$, including (consistent) worlds. +The ``extension'' phase, traced by equations (\ref{eq:prob.total.choice}) and (\ref{eq:weight.tchoice} --- \ref{eq:weight.events}), starts with the weight (probability) of total choices, $\pw{c} = \pr{C = c}$, expands it to stable models, $\pw{s}$, and then, within the equivalence relation from Equation \eqref{eq:equiv.rel}, to (general) events, $\pw{e}$, including (consistent) worlds. \begin{description} % \item[Total Choices.] Using \eqref{eq:prob.total.choice}, this case is given by \begin{equation} - \pw{c} = \pr{C = c}= \prod_{a\in c} p \prod_{a \not\in c} \co{p} + \pw{c} := \pr{C = c}= \prod_{a\in c} p \prod_{a \not\in c} \co{p} \label{eq:weight.tchoice} \end{equation} % @@ -409,7 +413,7 @@ The ``extension'' phase, traced by equations (\ref{eq:prob.total.choice}) and (\ Given a stable model $s \in \fml{S}$, a total choice $c$, and variables/values $\theta_{s,c} \in \intcc{0, 1}$, \begin{equation} \pw{s, c} := \begin{cases} - \theta_{s,c} & \text{if~} s \in S_c\cr + \pw{c}\theta_{s,c} & \text{if~} s \in S_c\cr 0&\text{otherwise} \end{cases} \label{eq:weight.stablemodel} @@ -425,29 +429,141 @@ The ``extension'' phase, traced by equations (\ref{eq:prob.total.choice}) and (\ \end{equation} \item \textbf{Independent Class.} A world that neither contains nor is contained in a stable model describes a case that, according to the specification, should never be observed. So the respective weight is set to zero: \begin{equation} - \pw{\emptyset, c} := 0. + \pw{\class{e}, c} := 0,~\text{if}~\stablecore{e} = \emptyset. \label{eq:weight.class.independent} \end{equation} \item \textbf{Other Classes.} The extension must be constant within a class, its value should result from the elements in the stable core, and respect the assumption \ref{assumption:smodels.independence}: \begin{equation} - \pw{\stablecore{s_1, \ldots, s_n}, c} := \prod_{k}\pw{s_k, c}. - \label{eq:weight.class.upper} + \pw{\class{e}, c} := \prod_{k=1}^{n}\pw{s_k, c},~\text{if}~\stablecore{e} = \set{s_1, \ldots, s_n}. + \label{eq:weight.class.other} \end{equation} \end{itemize} % \item[Events.] \label{item:event.cases} Each (general) event $e$ is in the class defined by its stable core, $\stablecore{e}$. So, we set: \begin{equation} - \pw{e, c} := \pw{\stablecore{e}, c}. + \pw{e, c} := \pw{\class{e}, c}. \label{eq:weight.events} \end{equation} + and + \begin{equation} + \pw{e} := \sum_{c\in\fml{C}} \pw{e, c}. + \label{eq:weight.events.unconditional} + \end{equation} \end{description} % PARAMETERS FOR UNCERTAINTY +\begin{itemize} + \item \todo{Remark that $\pw{\inconsistent, c} = 0$ is independent of the total choice.} + \item \todo{Remark the example $bc$ for equation \ref{eq:weight.class.independent}.} + \item \todo{Remark that equation \eqref{eq:weight.events.unconditional}, together with observations, can be used to learn about the \emph{initial} probabilities of the atoms, in the specification.} +\end{itemize} -Equation \eqref{eq:weight.stablemodel} expresses the \emph{specification's} lack of knowledge about the weight assignment, when a single total choice entails more than one stable model. In this case, how to distribute the respective weights? Our \replace{answer}{proposal} to \replace{}{address} this problem consists in assigning an unknown weight, $\theta_{s,c}$, conditional {\bruno depending???} on the total choice, $c$, to each stable model $s$. This approach allows the expression of an unknown quantity and future estimation, given observed data. + +The $\theta_{s,c}$ parameters in equation \eqref{eq:weight.stablemodel} express the \emph{specification's} lack of knowledge about the weight assignment, when a single total choice entails more than one stable model. In that case, how to distribute the respective weights? Our \replace{answer}{proposal} to \replace{}{address} this problem consists in assigning an unknown weight, $\theta_{s,c}$, conditional {\bruno depending???} on the total choice, $c$, to each stable model $s$. This approach allows the expression of an unknown quantity and future estimation, given observed data. % SUPERSET -Equation \eqref{eq:weight.class.upper} results from conditional independence of stable models. +Equation \eqref{eq:weight.class.other} results from conditional independence of stable models. + + +\section{Developed Examples} + +\subsection{The SBF Example} + +We continue with the specification from Equation \eqref{eq:example.1}. + +\textbf{Total Choices.} The total choices, and respective stable models, are +\begin{center} + \begin{tabular}{l|r|r} + Total Choice ($c$) & $\pw{c}$ & Stable Models ($s$)\\ + \hline + $a$ & $0.3$ & $ab$ and $ac$.\\ + $\co{a} = \neg a$ & $\co{0.3} = 0.7$ & $\co{a}$. + \end{tabular} +\end{center} + +\textbf{Stable Models.} The weights from equation \eqref{eq:weight.stablemodel} can be tabulated by a matrix where a column represents a total choice and a row a stable model. We get: +\begin{multline*} + \pw{s, c} = + \begin{pmatrix} + \pw{ab, a} & \pw{ab, \co{a}} \\ + \pw{ac, a} & \pw{ac, \co{a}} \\ + \pw{\co{a}, a} & \pw{\co{a}, \co{a}} + \end{pmatrix} + = + \begin{pmatrix} + \pw{a} \theta_{ab, a} & \pw{\co{a}} \theta_{ab, \co{a}} \\ + \pw{a} \theta_{ac, a} & \pw{\co{a}} \theta_{ac, \co{a}} \\ + \pw{a} \theta_{\co{a}, a} & \pw{\co{a}} \theta_{\co{a}, \co{a}} + \end{pmatrix} + \\ + = + \begin{pmatrix} + 0.3 \times \theta_{ab, a} & 0.7 \times 0.0 \\ + 0.3 \times \theta_{ac, a} & 0.7 \times 0.0 \\ + 0.3 \times 0.0 & 0.7 \times 1.0 + \end{pmatrix} + = + \begin{pmatrix} + 0.3\theta & 0.0 \\ + 0.3\co{\theta} & 0.0 \\ + 0.0 & 7.0 + \end{pmatrix} +\end{multline*} +where we set $\theta = \theta_{ab, a}$ to simplify the notation. + +\textbf{Classes.} Following the definitions in \cref{eq:stable.core,eq:equiv.rel,eq:event.class} and in \cref{eq:weight.class.inconsistent,eq:weight.class.independent,eq:weight.class.other} we get the following quotient set, and weights: +\begin{equation*} + \begin{array}{ll|rr} + \text{\textbf{Core}} & \text{\textbf{Class}} & \text{\textbf{Parameters}} & \text{\textbf{Weights}}\\ + \hline + % + \inconsistent + & \text{inconsistent events} + & 0.0 + \\ + % + \emptyset + & \co{b}, \co{c}, bc, \co{b}a, \co{b}c, \co{b}\co{c}, \co{c}a, \co{c}b, \co{b}\co{c}a + & 0.0 + \\ + % + \co{a} + & \co{a}, \co{a}b, \co{a}c, \co{a}\co{b}, \co{a}\co{c}, \co{a}bc, \co{a}b\co{c}, \co{a}\co{b}c, \co{a}\co{b}\co{c} + & 1.0 + & 0.7 + \\ + % + ab + & b, ab, ab\co{c} + & \theta + & 0.3 + \\ + % + ac + & c, ac, a\co{b}c + & \co{\theta} + & 0.3 + \\ + % + ab, ac + & a, abc + & \co{\theta}\theta + & 0.3 + \\ + % + \co{a}, ab, ac + & \set{} + & \co{\theta}\theta, 1.0 + & 0.3, 0.7 + \end{array} +\end{equation*} +\remark{fc}{I really don't like those squares} + +\subsection{A Not So Simple Example} + +\todo{this subsection} + +\section{Discussion} % % SUBSET % \hrule @@ -543,55 +659,6 @@ $$ Prove the four world cases (done), support the product (done) and sum (tbd) options, with the independence assumptions. \end{quotation} - -\section{Developed Example} - -We continue with the specification from Equation \eqref{eq:example.1}. - -\textbf{Step 1: Total Choices.} The total choices, and respective stable models, are -\begin{center} - \begin{tabular}{l|r|r} - Total Choice ($c$) & $\pr{C = c}$ & Stable Models ($s$)\\ - \hline - $a$ & $0.3$ & $ab$ and $ac$.\\ - $\co{a} = \neg a$ & $\co{0.3} = 0.7$ & $\co{a}$. - \end{tabular} -\end{center} - -\textbf{Step 2: Stable Models.} Suppose now that -\begin{center} - \begin{tabular}{l|c|r} - Stable Models ($s$) & Total Choice ($c$) & $\pr{S = c \given C = c}$\\ - \hline - $\co{a}$ & $1.0$ & $\co{a}$. \\ - $ab$ & $0.8$ & $a$. \\ - $ac$ & $0.2 = \co{0.8}$ & $a$. - \end{tabular} -\end{center} - -\textbf{Step 3: Worlds.} Following equations \ref{eq:world.fold.stablemodel} --- \ref{eq:world.fold.independent} we get: -\begin{center} - \begin{tabular}{l|c|l|c|r} - Occ. ($o$) & S.M. ($s$) & Relation & T.C. ($c$) & $\pr{W = w}$\\ - \hline - $\emptyset$ & all & contained & $a$, $\co{a}$ & $1.0$ \\ - $a$ & $ab$, $ac$ & contained & $a$ & $0.8\times 0.3 + 0.2\times 0.3 = 0.3$ \\ - $b$ & $ab$ & contained & $a$ & $0.8\times 0.3 = 0.24$ \\ - $c$ & $ac$ & contained & $a$ & $0.2\times 0.3 = 0.06$ \\ - $\co{a}$ & $\co{a}$ & stable model & $\co{a}$ & $1.0\times 0.3 = 0.3$ \\ - $\co{b}$ & none & independent & none & $0.0$ \\ - $\co{c}$ & none & \ldots & & \\ - $ab$ & $ab$ & stable model & $a$ & $0.24$ \\ - $ac$ & $ac$ & stable model & $a$ & $0.06$ \\ - $a\co{b}$ & none & \ldots & & \\ - $a\co{c}$ & none & \ldots & & \\ - $\co{a}b$ & $\co{a}$ & contains & $\co{a}$ & $1.0$ \\ - $\co{a}c$ & $\co{a}$ & \ldots & & \\ - $\co{a}\co{b}$ & $\co{a}$ & \ldots & & \\ - $\co{a}\co{c}$ & $\co{a}$ & \ldots & & \\ - $abc$ & $ab$, $ac$ & contains & $a$ & $0.8\times 0.2 = 0.016$ \\ - \end{tabular} -\end{center} \section{Final Remarks} @@ -600,8 +667,13 @@ We continue with the specification from Equation \eqref{eq:example.1}. \begin{itemize} \item The measure of the inconsistent events doesn't need to be set to $0$ and, maybe, in some cases, it shouldn't. \item The physical system might have \emph{latent} variables, possibly also represented in the specification. These variables are never observed, so observations should be concentrated \emph{somewhere else}. + \item Comment on the possibility of extending equation \eqref{eq:weight.events.unconditional} with parameters expressing further uncertainties, enabling a tuning of the model's total choices, given observations. + \begin{equation*} + \pw{e} := \sum_{c\in\fml{C}} \pw{e, c}\theta_c. + \end{equation*} \end{itemize} + \section*{Acknowledgements} This work is supported by NOVA\textbf{LINCS} (UIDB/04516/2020) with the financial support of FCT.IP. -- libgit2 0.21.2