Commit 353a8086aab8f46c7610ea1a544f7078e57f479f
1 parent
0ca70415
Exists in
master
alterações feitas pelo bruno à sub-secção 4.2
Showing
27 changed files
with
1180 additions
and
882 deletions
Show diff stats
code/drafts/.ipynb_checkpoints/EventLattice-checkpoint.ipynb
0 → 100644
@@ -0,0 +1,113 @@ | @@ -0,0 +1,113 @@ | ||
1 | +{ | ||
2 | + "cells": [ | ||
3 | + { | ||
4 | + "cell_type": "code", | ||
5 | + "execution_count": null, | ||
6 | + "id": "57fc5921-9d6b-4b43-a8f6-743a03650d63", | ||
7 | + "metadata": {}, | ||
8 | + "outputs": [], | ||
9 | + "source": [ | ||
10 | + "import event_lattice as el" | ||
11 | + ] | ||
12 | + }, | ||
13 | + { | ||
14 | + "cell_type": "code", | ||
15 | + "execution_count": null, | ||
16 | + "id": "00f0eb68", | ||
17 | + "metadata": {}, | ||
18 | + "outputs": [], | ||
19 | + "source": [ | ||
20 | + "def zoom_event(event_str, lattice, lower_op=el.sum_op, upper_op=el.prod_op):\n", | ||
21 | + " event = el.Event.from_str(event_str)\n", | ||
22 | + " event_class = lattice.event_class(event)\n", | ||
23 | + " propagated = lattice.propagated_value(\n", | ||
24 | + " event, lower_op=lower_op, upper_op=upper_op)\n", | ||
25 | + "\n", | ||
26 | + " print(\n", | ||
27 | + " f\"Event: {event}\\n\\tClass: {event_class} \\n\\tValue: {propagated}\")" | ||
28 | + ] | ||
29 | + }, | ||
30 | + { | ||
31 | + "cell_type": "code", | ||
32 | + "execution_count": null, | ||
33 | + "id": "cdd8c6d6", | ||
34 | + "metadata": {}, | ||
35 | + "outputs": [], | ||
36 | + "source": [ | ||
37 | + "smodels = el.Lattice.parse({\n", | ||
38 | + " \"A\": 2,\n", | ||
39 | + " \"ab\": 3,\n", | ||
40 | + " \"ac\": 5\n", | ||
41 | + "})\n", | ||
42 | + "\n", | ||
43 | + "lattice = el.Lattice(smodels)\n", | ||
44 | + "\n", | ||
45 | + "print(lattice)" | ||
46 | + ] | ||
47 | + }, | ||
48 | + { | ||
49 | + "cell_type": "code", | ||
50 | + "execution_count": null, | ||
51 | + "id": "2b445339", | ||
52 | + "metadata": {}, | ||
53 | + "outputs": [], | ||
54 | + "source": [ | ||
55 | + "zoom_event(\"abc\", lattice)\n", | ||
56 | + "zoom_event(\"a\", lattice)\n", | ||
57 | + "zoom_event(\"b\", lattice)\n", | ||
58 | + "zoom_event(\"bc\", lattice)\n", | ||
59 | + "zoom_event(\"ac\", lattice)" | ||
60 | + ] | ||
61 | + }, | ||
62 | + { | ||
63 | + "cell_type": "code", | ||
64 | + "execution_count": null, | ||
65 | + "id": "f1b85255", | ||
66 | + "metadata": {}, | ||
67 | + "outputs": [], | ||
68 | + "source": [ | ||
69 | + "from itertools import *\n", | ||
70 | + "\n", | ||
71 | + "lits = lattice.literals()\n", | ||
72 | + "for len_lit in range(len(lits)+1):\n", | ||
73 | + " events = list(\"\".join(c) for c in combinations(lits, len_lit))\n", | ||
74 | + " for event in events:\n", | ||
75 | + " zoom_event(event, lattice)" | ||
76 | + ] | ||
77 | + }, | ||
78 | + { | ||
79 | + "cell_type": "code", | ||
80 | + "execution_count": null, | ||
81 | + "id": "07973a47", | ||
82 | + "metadata": {}, | ||
83 | + "outputs": [], | ||
84 | + "source": [] | ||
85 | + } | ||
86 | + ], | ||
87 | + "metadata": { | ||
88 | + "kernelspec": { | ||
89 | + "display_name": "Python 3.9.13 ('base')", | ||
90 | + "language": "python", | ||
91 | + "name": "python3" | ||
92 | + }, | ||
93 | + "language_info": { | ||
94 | + "codemirror_mode": { | ||
95 | + "name": "ipython", | ||
96 | + "version": 3 | ||
97 | + }, | ||
98 | + "file_extension": ".py", | ||
99 | + "mimetype": "text/x-python", | ||
100 | + "name": "python", | ||
101 | + "nbconvert_exporter": "python", | ||
102 | + "pygments_lexer": "ipython3", | ||
103 | + "version": "3.9.13" | ||
104 | + }, | ||
105 | + "vscode": { | ||
106 | + "interpreter": { | ||
107 | + "hash": "a59afa236e16843183c59a167f072b6fa0409044b3c4938e82ac98aad91bf217" | ||
108 | + } | ||
109 | + } | ||
110 | + }, | ||
111 | + "nbformat": 4, | ||
112 | + "nbformat_minor": 5 | ||
113 | +} |
@@ -0,0 +1,154 @@ | @@ -0,0 +1,154 @@ | ||
1 | +{ | ||
2 | + "cells": [ | ||
3 | + { | ||
4 | + "cell_type": "code", | ||
5 | + "execution_count": 4, | ||
6 | + "id": "57fc5921-9d6b-4b43-a8f6-743a03650d63", | ||
7 | + "metadata": {}, | ||
8 | + "outputs": [ | ||
9 | + { | ||
10 | + "name": "stdout", | ||
11 | + "output_type": "stream", | ||
12 | + "text": [ | ||
13 | + "The autoreload extension is already loaded. To reload it, use:\n", | ||
14 | + " %reload_ext autoreload\n" | ||
15 | + ] | ||
16 | + } | ||
17 | + ], | ||
18 | + "source": [ | ||
19 | + "%load_ext autoreload\n", | ||
20 | + "%autoreload 1\n", | ||
21 | + "%aimport event_lattice" | ||
22 | + ] | ||
23 | + }, | ||
24 | + { | ||
25 | + "cell_type": "code", | ||
26 | + "execution_count": 5, | ||
27 | + "id": "00f0eb68", | ||
28 | + "metadata": {}, | ||
29 | + "outputs": [], | ||
30 | + "source": [ | ||
31 | + "def zoom_event(event_str, lattice):\n", | ||
32 | + " event = event_lattice.Event.from_str(event_str)\n", | ||
33 | + " event_class = lattice.event_class(event)\n", | ||
34 | + " propagated = lattice.extended_value(\n", | ||
35 | + " event)\n", | ||
36 | + "\n", | ||
37 | + " print(\n", | ||
38 | + " f\"Event: {event}\\n\\tClass: {event_class} \\n\\tValue: {propagated}\")" | ||
39 | + ] | ||
40 | + }, | ||
41 | + { | ||
42 | + "cell_type": "code", | ||
43 | + "execution_count": 6, | ||
44 | + "id": "cdd8c6d6", | ||
45 | + "metadata": {}, | ||
46 | + "outputs": [ | ||
47 | + { | ||
48 | + "name": "stdout", | ||
49 | + "output_type": "stream", | ||
50 | + "text": [ | ||
51 | + "{\n", | ||
52 | + "\t'stable_models': {\n", | ||
53 | + "\t\t A: 2,\n", | ||
54 | + "\t\tab: 3,\n", | ||
55 | + "\t\tac: 5 \n", | ||
56 | + "\t}\n", | ||
57 | + "\t'literals': { A,B,C,a,b,c } \n", | ||
58 | + "}\n" | ||
59 | + ] | ||
60 | + } | ||
61 | + ], | ||
62 | + "source": [ | ||
63 | + "smodels = event_lattice.Lattice.parse({\n", | ||
64 | + " \"A\": 2,\n", | ||
65 | + " \"ab\": 3,\n", | ||
66 | + " \"ac\": 5\n", | ||
67 | + "})\n", | ||
68 | + "\n", | ||
69 | + "lattice = event_lattice.Lattice(smodels)\n", | ||
70 | + "\n", | ||
71 | + "print(lattice)" | ||
72 | + ] | ||
73 | + }, | ||
74 | + { | ||
75 | + "cell_type": "code", | ||
76 | + "execution_count": 7, | ||
77 | + "id": "2b445339", | ||
78 | + "metadata": {}, | ||
79 | + "outputs": [ | ||
80 | + { | ||
81 | + "ename": "TypeError", | ||
82 | + "evalue": "__init__() missing 1 required positional argument: 'lattice'", | ||
83 | + "output_type": "error", | ||
84 | + "traceback": [ | ||
85 | + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", | ||
86 | + "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", | ||
87 | + "\u001b[0;32m/tmp/ipykernel_361713/2581811254.py\u001b[0m in \u001b[0;36m<module>\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", | ||
88 | + "\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", | ||
89 | + "\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", | ||
90 | + "\u001b[0;31mTypeError\u001b[0m: __init__() missing 1 required positional argument: 'lattice'" | ||
91 | + ] | ||
92 | + } | ||
93 | + ], | ||
94 | + "source": [ | ||
95 | + "zoom_event(\"abc\", lattice)\n", | ||
96 | + "zoom_event(\"a\", lattice)\n", | ||
97 | + "zoom_event(\"b\", lattice)\n", | ||
98 | + "zoom_event(\"bc\", lattice)\n", | ||
99 | + "zoom_event(\"ac\", lattice)" | ||
100 | + ] | ||
101 | + }, | ||
102 | + { | ||
103 | + "cell_type": "code", | ||
104 | + "execution_count": null, | ||
105 | + "id": "f1b85255", | ||
106 | + "metadata": {}, | ||
107 | + "outputs": [], | ||
108 | + "source": [ | ||
109 | + "from itertools import *\n", | ||
110 | + "\n", | ||
111 | + "lits = lattice.literals()\n", | ||
112 | + "events = []\n", | ||
113 | + "for len_lit in range(len(lits)+1):\n", | ||
114 | + " events = events + list(\"\".join(c) for c in combinations(lits, len_lit))\n", | ||
115 | + "for event in events:\n", | ||
116 | + " zoom_event(event, lattice)" | ||
117 | + ] | ||
118 | + }, | ||
119 | + { | ||
120 | + "cell_type": "code", | ||
121 | + "execution_count": null, | ||
122 | + "id": "07973a47", | ||
123 | + "metadata": {}, | ||
124 | + "outputs": [], | ||
125 | + "source": [] | ||
126 | + } | ||
127 | + ], | ||
128 | + "metadata": { | ||
129 | + "kernelspec": { | ||
130 | + "display_name": "Python 3 (ipykernel)", | ||
131 | + "language": "python", | ||
132 | + "name": "python3" | ||
133 | + }, | ||
134 | + "language_info": { | ||
135 | + "codemirror_mode": { | ||
136 | + "name": "ipython", | ||
137 | + "version": 3 | ||
138 | + }, | ||
139 | + "file_extension": ".py", | ||
140 | + "mimetype": "text/x-python", | ||
141 | + "name": "python", | ||
142 | + "nbconvert_exporter": "python", | ||
143 | + "pygments_lexer": "ipython3", | ||
144 | + "version": "3.9.15" | ||
145 | + }, | ||
146 | + "vscode": { | ||
147 | + "interpreter": { | ||
148 | + "hash": "a59afa236e16843183c59a167f072b6fa0409044b3c4938e82ac98aad91bf217" | ||
149 | + } | ||
150 | + } | ||
151 | + }, | ||
152 | + "nbformat": 4, | ||
153 | + "nbformat_minor": 5 | ||
154 | +} |
No preview for this file type
@@ -0,0 +1,30 @@ | @@ -0,0 +1,30 @@ | ||
1 | +from itertools import combinations, product | ||
2 | + | ||
3 | +def fmt(expr): | ||
4 | + """Doc string""" | ||
5 | + return ",".join(f"{x:>2}" for x in expr) | ||
6 | + | ||
7 | +def c(expr): | ||
8 | + """Doc string""" | ||
9 | + def litcomp(x): | ||
10 | + if x == "⊤": | ||
11 | + return "⊥" | ||
12 | + elif x == "⊥": | ||
13 | + return "⊤" | ||
14 | + elif x[0] == "¬": | ||
15 | + return x[1:] | ||
16 | + else: | ||
17 | + return f"¬{x}" | ||
18 | + return [litcomp(x) for x in expr] | ||
19 | + | ||
20 | +def domain(symbols, unary="¬"): | ||
21 | + """Doc string""" | ||
22 | + atoms = list(symbols) | ||
23 | + literals = [ | ||
24 | + [f"{u}{a}" for u in unary] + | ||
25 | + [a, "⊤", "⊥"] for a in atoms ] | ||
26 | + return product(*literals) | ||
27 | + | ||
28 | +d = sorted(domain("abc")) | ||
29 | +for x in d: | ||
30 | + print(f"{fmt(x)} | {fmt(c(x))}") |
@@ -0,0 +1,26 @@ | @@ -0,0 +1,26 @@ | ||
1 | +from clingo.symbol import Number | ||
2 | +from clingo.control import Control | ||
3 | + | ||
4 | +class Context: | ||
5 | + def inc(self, x): | ||
6 | + return Number(x.number + 1) | ||
7 | + | ||
8 | + def seq(self, x, y): | ||
9 | + return [x, y] | ||
10 | + | ||
11 | +def on_model(m): | ||
12 | + print(m) | ||
13 | + | ||
14 | +ctl = Control() | ||
15 | +ctl.add("base", [], """\ | ||
16 | +p(@inc(10)). | ||
17 | +q(@seq(1,2)). | ||
18 | +""") | ||
19 | + | ||
20 | +ctl.ground( | ||
21 | + [("base", [])], | ||
22 | + context=Context()) | ||
23 | + | ||
24 | +s = ctl.solve(on_model=on_model) | ||
25 | + | ||
26 | +print(s) | ||
0 | \ No newline at end of file | 27 | \ No newline at end of file |
@@ -0,0 +1,301 @@ | @@ -0,0 +1,301 @@ | ||
1 | +import math | ||
2 | +from functools import cache | ||
3 | +from itertools import accumulate, combinations, chain, groupby | ||
4 | +import operator | ||
5 | + | ||
6 | + | ||
7 | + | ||
8 | +def uniform_op(x): | ||
9 | + n = len(list(x)) | ||
10 | + return 1.0 if n == 0 else 1.0/n | ||
11 | + | ||
12 | + | ||
13 | +def max_op(x): | ||
14 | + return max(x) | ||
15 | + | ||
16 | + | ||
17 | +def min_op(x): | ||
18 | + return min(x) | ||
19 | + | ||
20 | + | ||
21 | +def sum_op(x): | ||
22 | + return sum(x) | ||
23 | + | ||
24 | + | ||
25 | +def stableprod_op(x): | ||
26 | + log_x = map(math.log, x) | ||
27 | + return math.exp(sum(log_x)) | ||
28 | + | ||
29 | + | ||
30 | +def prod_op(x): | ||
31 | + return list(accumulate(x, func=lambda a,b: a*b))[-1] | ||
32 | + | ||
33 | + | ||
34 | +class Event: | ||
35 | + """Events. | ||
36 | + | ||
37 | + An event is a set of literals - atoms and negated atoms. | ||
38 | + | ||
39 | + The convention is that atoms are represented by lower case single letters | ||
40 | + and a negated atom by upper case single letters. | ||
41 | + """ | ||
42 | + | ||
43 | + @staticmethod | ||
44 | + def _parse(text): | ||
45 | + return frozenset(text) | ||
46 | + | ||
47 | + @staticmethod | ||
48 | + def parse(text): | ||
49 | + """Convert a string to an event. | ||
50 | + | ||
51 | + Each letter in the string represents a literal. | ||
52 | + """ | ||
53 | + return Event(Event._parse(text)) | ||
54 | + | ||
55 | + | ||
56 | + def __init__(self, literals): | ||
57 | + """Instantiate from a (frozen) set of literals. | ||
58 | + For example: e = Event(frozenset("abc")).""" | ||
59 | + self._literals = frozenset(literals) | ||
60 | + | ||
61 | + | ||
62 | + def literals(self): | ||
63 | + return self._literals | ||
64 | + | ||
65 | + | ||
66 | + def __iter__(self): | ||
67 | + return self._literals.__iter__() | ||
68 | + | ||
69 | + @cache | ||
70 | + def is_consistent(self): | ||
71 | + """True if this event is consistent.""" | ||
72 | + return all(x.swapcase() not in self._literals for x in self._literals) | ||
73 | + | ||
74 | + | ||
75 | + def co(self): | ||
76 | + """Negation of this event. | ||
77 | + | ||
78 | + Negation is case based: A = not a; a = not A.""" | ||
79 | + return Event(x.swapcase() for x in self._literals) | ||
80 | + | ||
81 | + def invert(self): | ||
82 | + """Negation of this event. | ||
83 | + | ||
84 | + See the method "co" | ||
85 | + """ | ||
86 | + return self.co() | ||
87 | + | ||
88 | + def __repr__(self) -> str: | ||
89 | + return ''.join(str(x) for x in sorted(self._literals)) if len(self._literals) > 0 else '0' | ||
90 | + | ||
91 | + def latex(self): | ||
92 | + """LaTeX representation of this even. | ||
93 | + | ||
94 | + Negation is represented by overline and the empty event by | ||
95 | + | ||
96 | + """ | ||
97 | + return ''.join( | ||
98 | + (str(x) if x.islower() else f"\co{{{x.lower()}}}") \ | ||
99 | + for x in sorted(self._literals) | ||
100 | + ) if len(self._literals) > 0 else "\set{}" | ||
101 | + | ||
102 | + def __hash__(self) -> int: | ||
103 | + return self._literals.__hash__() | ||
104 | + | ||
105 | + | ||
106 | + def __eq__(self, other): | ||
107 | + """Event equality test.""" | ||
108 | + return self._literals.__eq__(other._literals) | ||
109 | + | ||
110 | + def __or__(self, other): | ||
111 | + """Event union operation.""" | ||
112 | + return Event(self._literals | other._literals) | ||
113 | + | ||
114 | + def __le__(self, other): | ||
115 | + """Event subset test.""" | ||
116 | + return self._literals.__le__(other._literals) | ||
117 | + | ||
118 | + | ||
119 | + def __lt__(self, other): | ||
120 | + """Event strict subset test.""" | ||
121 | + return self._literals.__lt__(other._literals) | ||
122 | + | ||
123 | + | ||
124 | + def __ne__(self, other): | ||
125 | + """Event not-equal test.""" | ||
126 | + return self._literals.__ne__(other._literals) | ||
127 | + | ||
128 | + | ||
129 | + def __ge__(self, other): | ||
130 | + """Event superset test.""" | ||
131 | + return self._literals.__ge__(other._literals) | ||
132 | + | ||
133 | + | ||
134 | + def __gt__(self, other): | ||
135 | + """Event strict superset test.""" | ||
136 | + return self._literals.__gt__(other._literals) | ||
137 | + | ||
138 | + | ||
139 | +class Lattice: | ||
140 | + | ||
141 | + @staticmethod | ||
142 | + def parse(d): | ||
143 | + """Input stable models. | ||
144 | + | ||
145 | + The input format is a dictionary associating a stable model in string form to an weight. | ||
146 | + | ||
147 | + For example: | ||
148 | + | ||
149 | + input_dict = { | ||
150 | + "A": 0.3, | ||
151 | + "ab": 0.2, | ||
152 | + "ac": 0.5 | ||
153 | + } | ||
154 | + smodels = Lattice.parse(input_dict) | ||
155 | + """ | ||
156 | + result = dict() | ||
157 | + for k, v in d.items(): | ||
158 | + key = Event.parse(k) | ||
159 | + result[key] = v | ||
160 | + return result | ||
161 | + | ||
162 | + | ||
163 | + @staticmethod | ||
164 | + def close_literals(events): | ||
165 | + """Closed set of literals entailed by a set of events. | ||
166 | + | ||
167 | + Includes the literals in the set of events and any missing negation.""" | ||
168 | + base_lits = list(accumulate(events, func=operator.or_))[-1] | ||
169 | + lits = set() | ||
170 | + for x in base_lits.literals(): | ||
171 | + lits.add(x) | ||
172 | + lits.add(x.swapcase()) | ||
173 | + return sorted(lits) | ||
174 | + | ||
175 | + def __init__(self, smodels_dict): | ||
176 | + """Create an Events lattice.""" | ||
177 | + self._smodels = smodels_dict | ||
178 | + self._literals = Lattice.close_literals(self._smodels.keys()) | ||
179 | + | ||
180 | + def literals(self): | ||
181 | + """The literals in this lattice.""" | ||
182 | + return self._literals | ||
183 | + | ||
184 | + @cache | ||
185 | + def stable_models(self): | ||
186 | + """The stable models that generate this lattice.""" | ||
187 | + return self._smodels.keys() | ||
188 | + | ||
189 | + #@cache | ||
190 | + def events(self): | ||
191 | + """All the events of this lattice.""" | ||
192 | + return chain.from_iterable(map(Event, combinations(self._literals, r)) for r in range(len(self._literals)+1)) | ||
193 | + | ||
194 | + @cache | ||
195 | + def stable_core(self, event): | ||
196 | + """The stable core of an event in this lattice.""" | ||
197 | + return set(filter(lambda sm: sm <= event or event <= sm, self.stable_models())) | ||
198 | + | ||
199 | + # @cache | ||
200 | + # def event_class(self, event): | ||
201 | + # """The equivalence class of an event.""" | ||
202 | + # return EventsClass(self.stable_core(event), self) | ||
203 | + | ||
204 | + @cache | ||
205 | + def classes(self): | ||
206 | + """The classes of this lattice. | ||
207 | + | ||
208 | + Each class is presented as a key:value pair where the "key" is the stable core of the elements in "value".""" | ||
209 | + map_ev_classes = [(e, tuple(self.stable_core(e))) for e in self.events() if e.is_consistent()] | ||
210 | + groups = dict() | ||
211 | + for e,c in map_ev_classes: | ||
212 | + if c in groups.keys(): | ||
213 | + groups[c].add(e) | ||
214 | + else: | ||
215 | + groups[c] = set([e]) | ||
216 | + inconsistent = list(e for e in self.events() if not e.is_consistent()) | ||
217 | + inconsistent_repr = inconsistent[0] | ||
218 | + groups[(inconsistent_repr,)] = set(inconsistent) | ||
219 | + return groups | ||
220 | + | ||
221 | + | ||
222 | + def related(self, u, v): | ||
223 | + """Tests if two events are related.""" | ||
224 | + u_consistent = u.is_consistent() | ||
225 | + v_consistent = v.is_consistent() | ||
226 | + if u_consistent and (u_consistent == v_consistent): | ||
227 | + return self.stable_core(u) == self.stable_core(v) | ||
228 | + else: | ||
229 | + return u_consistent == v_consistent | ||
230 | + | ||
231 | + def extended_value(self, event:Event, | ||
232 | + op=prod_op): | ||
233 | + """TODO: well...""" | ||
234 | + value = 0 | ||
235 | + # | ||
236 | + # INCONSISTENT EVENTS | ||
237 | + # | ||
238 | + if not event.is_consistent(): | ||
239 | + return value | ||
240 | + # | ||
241 | + # CONSISTENT EVENTS | ||
242 | + # | ||
243 | + score = self.stable_core(event) | ||
244 | + len_score = len(score) | ||
245 | + # CONSISTENT, INDEPENDENT | ||
246 | + if len_score == 0: | ||
247 | + value = 0 | ||
248 | + elif len_score == 1: | ||
249 | + value = self._smodels[score[0]] | ||
250 | + else: | ||
251 | + value = op(map(lambda sm: self._smodels[sm], score)) | ||
252 | + | ||
253 | + return value | ||
254 | + | ||
255 | + def __repr__(self): | ||
256 | + smodels_repr = ',\n\t\t'.join(f"{k}: {v:<}" for k,v in self._smodels.items()) | ||
257 | + lits_repr = ','.join(sorted(self._literals)) | ||
258 | + | ||
259 | + return "{\n" +\ | ||
260 | + f"\t'stable_models': {{\n\t\t {smodels_repr} \n\t}}\n" +\ | ||
261 | + f"\t'literals': {{ {lits_repr} }} \n" +\ | ||
262 | + "}" | ||
263 | + | ||
264 | +# class EventsClass: | ||
265 | +# def __init__(self, core, lattice:Lattice): | ||
266 | +# self._core = core | ||
267 | +# self._lattice = lattice | ||
268 | + | ||
269 | +# def __repr__(self): | ||
270 | +# core_repr = "" if len(self._core) == 0 else ",".join(str(x) for x in self._core) | ||
271 | +# return f"<{core_repr}>" | ||
272 | + | ||
273 | +# def __contains__(self, event:Event): | ||
274 | +# return self.lattice.stable_core(event) == self._core | ||
275 | + | ||
276 | +if __name__ == "__main__": | ||
277 | + def zoom_event(event_str, lattice): | ||
278 | + event = Event.parse(event_str) | ||
279 | + event_class = lattice.event_class(event) | ||
280 | + propagated = lattice.extended_value( | ||
281 | + event) | ||
282 | + | ||
283 | + print( | ||
284 | + f"Event: {event}\n\tClass: {event_class} \n\tValue: {propagated}") | ||
285 | + | ||
286 | + smodels = Lattice.parse({ | ||
287 | + "A": 2, | ||
288 | + "ab": 3, | ||
289 | + "ac": 5 | ||
290 | + }) | ||
291 | + | ||
292 | + lattice = Lattice(smodels) | ||
293 | + | ||
294 | + ev_classes = lattice.classes() | ||
295 | + for k,g in ev_classes.items(): | ||
296 | + print(f"{tuple(s.latex() for s in k)} {set(e.latex() for e in g)}") | ||
297 | + # zoom_event("abc", lattice) | ||
298 | + # zoom_event("a", lattice) | ||
299 | + # zoom_event("b", lattice) | ||
300 | + # zoom_event("bc", lattice) | ||
301 | + # zoom_event("ac", lattice) | ||
0 | \ No newline at end of file | 302 | \ No newline at end of file |
@@ -0,0 +1,13 @@ | @@ -0,0 +1,13 @@ | ||
1 | +from clingo.control import Control | ||
2 | +from clingox.program import Program, ProgramObserver, Remapping | ||
3 | + | ||
4 | +prg = Program() | ||
5 | +ctl_a = Control() | ||
6 | +ctl_a.register_observer(ProgramObserver(prg)) | ||
7 | +print(f"<1>\n{prg}\n</1>") | ||
8 | + | ||
9 | +prog = "code/asp/alarm.lp" | ||
10 | +ctl_a.load(prog) | ||
11 | +ctl_a.ground([('base', [])]) | ||
12 | +print(f"<2>\n{prg}\n</2>") | ||
13 | + |
@@ -0,0 +1,101 @@ | @@ -0,0 +1,101 @@ | ||
1 | +event | ||
2 | +b | ||
3 | +b | ||
4 | +b | ||
5 | +C | ||
6 | +λ | ||
7 | +BC | ||
8 | +C | ||
9 | +λ | ||
10 | +bC | ||
11 | +BC | ||
12 | +Ac | ||
13 | +λ | ||
14 | +λ | ||
15 | +abC | ||
16 | +λ | ||
17 | +BC | ||
18 | +abC | ||
19 | +A | ||
20 | +a | ||
21 | +B | ||
22 | +b | ||
23 | +abc | ||
24 | +λ | ||
25 | +B | ||
26 | +λ | ||
27 | +AC | ||
28 | +C | ||
29 | +Ac | ||
30 | +C | ||
31 | +B | ||
32 | +Bc | ||
33 | +c | ||
34 | +aB | ||
35 | +Ab | ||
36 | +λ | ||
37 | +C | ||
38 | +aC | ||
39 | +λ | ||
40 | +a | ||
41 | +aBC | ||
42 | +abc | ||
43 | +Ac | ||
44 | +λ | ||
45 | +c | ||
46 | +c | ||
47 | +λ | ||
48 | +Bc | ||
49 | +B | ||
50 | +bc | ||
51 | +aB | ||
52 | +aB | ||
53 | +ABc | ||
54 | +C | ||
55 | +λ | ||
56 | +B | ||
57 | +λ | ||
58 | +ac | ||
59 | +Ac | ||
60 | +b | ||
61 | +Abc | ||
62 | +b | ||
63 | +C | ||
64 | +a | ||
65 | +ab | ||
66 | +C | ||
67 | +ab | ||
68 | +λ | ||
69 | +A | ||
70 | +bc | ||
71 | +AC | ||
72 | +λ | ||
73 | +C | ||
74 | +ABc | ||
75 | +AC | ||
76 | +ac | ||
77 | +BC | ||
78 | +c | ||
79 | +Ac | ||
80 | +ab | ||
81 | +ABC | ||
82 | +A | ||
83 | +aB | ||
84 | +bc | ||
85 | +λ | ||
86 | +aB | ||
87 | +ABc | ||
88 | +Ac | ||
89 | +Ac | ||
90 | +B | ||
91 | +aB | ||
92 | +Ac | ||
93 | +c | ||
94 | +λ | ||
95 | +λ | ||
96 | +b | ||
97 | +c | ||
98 | +Ab | ||
99 | +BC | ||
100 | +A | ||
101 | +BC |
@@ -0,0 +1,28 @@ | @@ -0,0 +1,28 @@ | ||
1 | +neg(a) = islowercase(a) ? uppercase(a) : lowercase(a) | ||
2 | + | ||
3 | +function sample(atoms) | ||
4 | + result = Char[] | ||
5 | + for a in atoms | ||
6 | + if rand(Bool) | ||
7 | + push!(result, rand(Bool) ? a : neg(a)) | ||
8 | + end | ||
9 | + end | ||
10 | + return length(result) > 0 ? join(result) : "λ" | ||
11 | +end | ||
12 | + | ||
13 | +function sample(n::Int, atoms) | ||
14 | + result = String[] | ||
15 | + for _ in 1:n | ||
16 | + push!(result, sample(atoms)) | ||
17 | + end | ||
18 | + return result | ||
19 | +end | ||
20 | + | ||
21 | +using DelimitedFiles | ||
22 | + | ||
23 | +abc_atoms = [ 'a', 'b', 'c'] | ||
24 | + | ||
25 | +open("sample.csv", "w") do io | ||
26 | + writedlm(io, [ "event" ]) | ||
27 | + writedlm(io, sample(100, abc_atoms), ) | ||
28 | +end | ||
0 | \ No newline at end of file | 29 | \ No newline at end of file |
@@ -0,0 +1,41 @@ | @@ -0,0 +1,41 @@ | ||
1 | +from unicodedata import numeric | ||
2 | +from sympy import * | ||
3 | +from sympy.plotting import plot | ||
4 | + | ||
5 | +def variants(expr, with_plot=False): | ||
6 | + print(f"Expr: {latex(expr)}") | ||
7 | + print(f"Simplify: {latex(simplify(expr))}") | ||
8 | + print(f"Expand: {latex(expand(expr))}") | ||
9 | + print(f"Factor: {latex(factor(expr))}") | ||
10 | + if with_plot: | ||
11 | + plot(expr, (d, 0, 1, 10),ylabel="$\\mathrm{P(expr \\mid \\alpha = 0.3)}$") | ||
12 | + | ||
13 | +init_printing(use_unicode=True) | ||
14 | + | ||
15 | +a, d = symbols('a d') | ||
16 | +A = 1 - a | ||
17 | +D = 1 - d | ||
18 | + | ||
19 | +wab = a * d | ||
20 | +wac = a * D | ||
21 | +wA = A | ||
22 | + | ||
23 | +wabc = wab * wac | ||
24 | +wAb = wA | ||
25 | +wa = wab + wac | ||
26 | +wb = wab | ||
27 | +wc = wac | ||
28 | +wE = wab + wab + wA | ||
29 | + | ||
30 | +z = wabc + 9 * wA + wab + wac + wa + wb +wc + wE | ||
31 | +pabc = wabc/z | ||
32 | + | ||
33 | +z_03 = z.subs(a, 0.3) | ||
34 | +wabc_03 = wabc.subs(a, 0.3) | ||
35 | +pabc_03 = pabc.subs(a, 0.3) | ||
36 | + | ||
37 | +variants(z_03) | ||
38 | +variants(wabc_03) | ||
39 | +variants(pabc_03) | ||
40 | +print(solve(wabc_03 - 0.0015 * z_03, d)) | ||
41 | + |
@@ -0,0 +1,116 @@ | @@ -0,0 +1,116 @@ | ||
1 | +{ | ||
2 | + "cells": [ | ||
3 | + { | ||
4 | + "cell_type": "code", | ||
5 | + "execution_count": 1, | ||
6 | + "metadata": {}, | ||
7 | + "outputs": [ | ||
8 | + { | ||
9 | + "data": { | ||
10 | + "text/plain": [ | ||
11 | + "4" | ||
12 | + ] | ||
13 | + }, | ||
14 | + "execution_count": 1, | ||
15 | + "metadata": {}, | ||
16 | + "output_type": "execute_result" | ||
17 | + } | ||
18 | + ], | ||
19 | + "source": [ | ||
20 | + "2+2" | ||
21 | + ] | ||
22 | + }, | ||
23 | + { | ||
24 | + "cell_type": "code", | ||
25 | + "execution_count": 3, | ||
26 | + "metadata": {}, | ||
27 | + "outputs": [], | ||
28 | + "source": [ | ||
29 | + "import matplotlib.pyplot as plt\n", | ||
30 | + "import numpy as np" | ||
31 | + ] | ||
32 | + }, | ||
33 | + { | ||
34 | + "cell_type": "code", | ||
35 | + "execution_count": 4, | ||
36 | + "metadata": {}, | ||
37 | + "outputs": [], | ||
38 | + "source": [ | ||
39 | + "x = np.linspace(-6, 6)" | ||
40 | + ] | ||
41 | + }, | ||
42 | + { | ||
43 | + "cell_type": "code", | ||
44 | + "execution_count": 5, | ||
45 | + "metadata": {}, | ||
46 | + "outputs": [], | ||
47 | + "source": [ | ||
48 | + "y = np.sin(x)" | ||
49 | + ] | ||
50 | + }, | ||
51 | + { | ||
52 | + "cell_type": "code", | ||
53 | + "execution_count": 6, | ||
54 | + "metadata": {}, | ||
55 | + "outputs": [ | ||
56 | + { | ||
57 | + "data": { | ||
58 | + "text/plain": [ | ||
59 | + "[<matplotlib.lines.Line2D at 0x7f2d55566b50>]" | ||
60 | + ] | ||
61 | + }, | ||
62 | + "execution_count": 6, | ||
63 | + "metadata": {}, | ||
64 | + "output_type": "execute_result" | ||
65 | + }, | ||
66 | + { | ||
67 | + "data": { | ||
68 | + "image/png": "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", | ||
69 | + "text/plain": [ | ||
70 | + "<Figure size 640x480 with 1 Axes>" | ||
71 | + ] | ||
72 | + }, | ||
73 | + "metadata": {}, | ||
74 | + "output_type": "display_data" | ||
75 | + } | ||
76 | + ], | ||
77 | + "source": [ | ||
78 | + "plt.plot(x,y)" | ||
79 | + ] | ||
80 | + }, | ||
81 | + { | ||
82 | + "cell_type": "code", | ||
83 | + "execution_count": null, | ||
84 | + "metadata": {}, | ||
85 | + "outputs": [], | ||
86 | + "source": [] | ||
87 | + } | ||
88 | + ], | ||
89 | + "metadata": { | ||
90 | + "kernelspec": { | ||
91 | + "display_name": "Python 3.9.15 ('base')", | ||
92 | + "language": "python", | ||
93 | + "name": "python3" | ||
94 | + }, | ||
95 | + "language_info": { | ||
96 | + "codemirror_mode": { | ||
97 | + "name": "ipython", | ||
98 | + "version": 3 | ||
99 | + }, | ||
100 | + "file_extension": ".py", | ||
101 | + "mimetype": "text/x-python", | ||
102 | + "name": "python", | ||
103 | + "nbconvert_exporter": "python", | ||
104 | + "pygments_lexer": "ipython3", | ||
105 | + "version": "3.9.15" | ||
106 | + }, | ||
107 | + "orig_nbformat": 4, | ||
108 | + "vscode": { | ||
109 | + "interpreter": { | ||
110 | + "hash": "a59afa236e16843183c59a167f072b6fa0409044b3c4938e82ac98aad91bf217" | ||
111 | + } | ||
112 | + } | ||
113 | + }, | ||
114 | + "nbformat": 4, | ||
115 | + "nbformat_minor": 2 | ||
116 | +} |
code/python/.ipynb_checkpoints/EventLattice-checkpoint.ipynb
@@ -1,113 +0,0 @@ | @@ -1,113 +0,0 @@ | ||
1 | -{ | ||
2 | - "cells": [ | ||
3 | - { | ||
4 | - "cell_type": "code", | ||
5 | - "execution_count": null, | ||
6 | - "id": "57fc5921-9d6b-4b43-a8f6-743a03650d63", | ||
7 | - "metadata": {}, | ||
8 | - "outputs": [], | ||
9 | - "source": [ | ||
10 | - "import event_lattice as el" | ||
11 | - ] | ||
12 | - }, | ||
13 | - { | ||
14 | - "cell_type": "code", | ||
15 | - "execution_count": null, | ||
16 | - "id": "00f0eb68", | ||
17 | - "metadata": {}, | ||
18 | - "outputs": [], | ||
19 | - "source": [ | ||
20 | - "def zoom_event(event_str, lattice, lower_op=el.sum_op, upper_op=el.prod_op):\n", | ||
21 | - " event = el.Event.from_str(event_str)\n", | ||
22 | - " event_class = lattice.event_class(event)\n", | ||
23 | - " propagated = lattice.propagated_value(\n", | ||
24 | - " event, lower_op=lower_op, upper_op=upper_op)\n", | ||
25 | - "\n", | ||
26 | - " print(\n", | ||
27 | - " f\"Event: {event}\\n\\tClass: {event_class} \\n\\tValue: {propagated}\")" | ||
28 | - ] | ||
29 | - }, | ||
30 | - { | ||
31 | - "cell_type": "code", | ||
32 | - "execution_count": null, | ||
33 | - "id": "cdd8c6d6", | ||
34 | - "metadata": {}, | ||
35 | - "outputs": [], | ||
36 | - "source": [ | ||
37 | - "smodels = el.Lattice.parse({\n", | ||
38 | - " \"A\": 2,\n", | ||
39 | - " \"ab\": 3,\n", | ||
40 | - " \"ac\": 5\n", | ||
41 | - "})\n", | ||
42 | - "\n", | ||
43 | - "lattice = el.Lattice(smodels)\n", | ||
44 | - "\n", | ||
45 | - "print(lattice)" | ||
46 | - ] | ||
47 | - }, | ||
48 | - { | ||
49 | - "cell_type": "code", | ||
50 | - "execution_count": null, | ||
51 | - "id": "2b445339", | ||
52 | - "metadata": {}, | ||
53 | - "outputs": [], | ||
54 | - "source": [ | ||
55 | - "zoom_event(\"abc\", lattice)\n", | ||
56 | - "zoom_event(\"a\", lattice)\n", | ||
57 | - "zoom_event(\"b\", lattice)\n", | ||
58 | - "zoom_event(\"bc\", lattice)\n", | ||
59 | - "zoom_event(\"ac\", lattice)" | ||
60 | - ] | ||
61 | - }, | ||
62 | - { | ||
63 | - "cell_type": "code", | ||
64 | - "execution_count": null, | ||
65 | - "id": "f1b85255", | ||
66 | - "metadata": {}, | ||
67 | - "outputs": [], | ||
68 | - "source": [ | ||
69 | - "from itertools import *\n", | ||
70 | - "\n", | ||
71 | - "lits = lattice.literals()\n", | ||
72 | - "for len_lit in range(len(lits)+1):\n", | ||
73 | - " events = list(\"\".join(c) for c in combinations(lits, len_lit))\n", | ||
74 | - " for event in events:\n", | ||
75 | - " zoom_event(event, lattice)" | ||
76 | - ] | ||
77 | - }, | ||
78 | - { | ||
79 | - "cell_type": "code", | ||
80 | - "execution_count": null, | ||
81 | - "id": "07973a47", | ||
82 | - "metadata": {}, | ||
83 | - "outputs": [], | ||
84 | - "source": [] | ||
85 | - } | ||
86 | - ], | ||
87 | - "metadata": { | ||
88 | - "kernelspec": { | ||
89 | - "display_name": "Python 3.9.13 ('base')", | ||
90 | - "language": "python", | ||
91 | - "name": "python3" | ||
92 | - }, | ||
93 | - "language_info": { | ||
94 | - "codemirror_mode": { | ||
95 | - "name": "ipython", | ||
96 | - "version": 3 | ||
97 | - }, | ||
98 | - "file_extension": ".py", | ||
99 | - "mimetype": "text/x-python", | ||
100 | - "name": "python", | ||
101 | - "nbconvert_exporter": "python", | ||
102 | - "pygments_lexer": "ipython3", | ||
103 | - "version": "3.9.13" | ||
104 | - }, | ||
105 | - "vscode": { | ||
106 | - "interpreter": { | ||
107 | - "hash": "a59afa236e16843183c59a167f072b6fa0409044b3c4938e82ac98aad91bf217" | ||
108 | - } | ||
109 | - } | ||
110 | - }, | ||
111 | - "nbformat": 4, | ||
112 | - "nbformat_minor": 5 | ||
113 | -} |
code/python/EventLattice.ipynb
@@ -1,154 +0,0 @@ | @@ -1,154 +0,0 @@ | ||
1 | -{ | ||
2 | - "cells": [ | ||
3 | - { | ||
4 | - "cell_type": "code", | ||
5 | - "execution_count": 4, | ||
6 | - "id": "57fc5921-9d6b-4b43-a8f6-743a03650d63", | ||
7 | - "metadata": {}, | ||
8 | - "outputs": [ | ||
9 | - { | ||
10 | - "name": "stdout", | ||
11 | - "output_type": "stream", | ||
12 | - "text": [ | ||
13 | - "The autoreload extension is already loaded. To reload it, use:\n", | ||
14 | - " %reload_ext autoreload\n" | ||
15 | - ] | ||
16 | - } | ||
17 | - ], | ||
18 | - "source": [ | ||
19 | - "%load_ext autoreload\n", | ||
20 | - "%autoreload 1\n", | ||
21 | - "%aimport event_lattice" | ||
22 | - ] | ||
23 | - }, | ||
24 | - { | ||
25 | - "cell_type": "code", | ||
26 | - "execution_count": 5, | ||
27 | - "id": "00f0eb68", | ||
28 | - "metadata": {}, | ||
29 | - "outputs": [], | ||
30 | - "source": [ | ||
31 | - "def zoom_event(event_str, lattice):\n", | ||
32 | - " event = event_lattice.Event.from_str(event_str)\n", | ||
33 | - " event_class = lattice.event_class(event)\n", | ||
34 | - " propagated = lattice.extended_value(\n", | ||
35 | - " event)\n", | ||
36 | - "\n", | ||
37 | - " print(\n", | ||
38 | - " f\"Event: {event}\\n\\tClass: {event_class} \\n\\tValue: {propagated}\")" | ||
39 | - ] | ||
40 | - }, | ||
41 | - { | ||
42 | - "cell_type": "code", | ||
43 | - "execution_count": 6, | ||
44 | - "id": "cdd8c6d6", | ||
45 | - "metadata": {}, | ||
46 | - "outputs": [ | ||
47 | - { | ||
48 | - "name": "stdout", | ||
49 | - "output_type": "stream", | ||
50 | - "text": [ | ||
51 | - "{\n", | ||
52 | - "\t'stable_models': {\n", | ||
53 | - "\t\t A: 2,\n", | ||
54 | - "\t\tab: 3,\n", | ||
55 | - "\t\tac: 5 \n", | ||
56 | - "\t}\n", | ||
57 | - "\t'literals': { A,B,C,a,b,c } \n", | ||
58 | - "}\n" | ||
59 | - ] | ||
60 | - } | ||
61 | - ], | ||
62 | - "source": [ | ||
63 | - "smodels = event_lattice.Lattice.parse({\n", | ||
64 | - " \"A\": 2,\n", | ||
65 | - " \"ab\": 3,\n", | ||
66 | - " \"ac\": 5\n", | ||
67 | - "})\n", | ||
68 | - "\n", | ||
69 | - "lattice = event_lattice.Lattice(smodels)\n", | ||
70 | - "\n", | ||
71 | - "print(lattice)" | ||
72 | - ] | ||
73 | - }, | ||
74 | - { | ||
75 | - "cell_type": "code", | ||
76 | - "execution_count": 7, | ||
77 | - "id": "2b445339", | ||
78 | - "metadata": {}, | ||
79 | - "outputs": [ | ||
80 | - { | ||
81 | - "ename": "TypeError", | ||
82 | - "evalue": "__init__() missing 1 required positional argument: 'lattice'", | ||
83 | - "output_type": "error", | ||
84 | - "traceback": [ | ||
85 | - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", | ||
86 | - "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", | ||
87 | - "\u001b[0;32m/tmp/ipykernel_361713/2581811254.py\u001b[0m in \u001b[0;36m<module>\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", | ||
88 | - "\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", | ||
89 | - "\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", | ||
90 | - "\u001b[0;31mTypeError\u001b[0m: __init__() missing 1 required positional argument: 'lattice'" | ||
91 | - ] | ||
92 | - } | ||
93 | - ], | ||
94 | - "source": [ | ||
95 | - "zoom_event(\"abc\", lattice)\n", | ||
96 | - "zoom_event(\"a\", lattice)\n", | ||
97 | - "zoom_event(\"b\", lattice)\n", | ||
98 | - "zoom_event(\"bc\", lattice)\n", | ||
99 | - "zoom_event(\"ac\", lattice)" | ||
100 | - ] | ||
101 | - }, | ||
102 | - { | ||
103 | - "cell_type": "code", | ||
104 | - "execution_count": null, | ||
105 | - "id": "f1b85255", | ||
106 | - "metadata": {}, | ||
107 | - "outputs": [], | ||
108 | - "source": [ | ||
109 | - "from itertools import *\n", | ||
110 | - "\n", | ||
111 | - "lits = lattice.literals()\n", | ||
112 | - "events = []\n", | ||
113 | - "for len_lit in range(len(lits)+1):\n", | ||
114 | - " events = events + list(\"\".join(c) for c in combinations(lits, len_lit))\n", | ||
115 | - "for event in events:\n", | ||
116 | - " zoom_event(event, lattice)" | ||
117 | - ] | ||
118 | - }, | ||
119 | - { | ||
120 | - "cell_type": "code", | ||
121 | - "execution_count": null, | ||
122 | - "id": "07973a47", | ||
123 | - "metadata": {}, | ||
124 | - "outputs": [], | ||
125 | - "source": [] | ||
126 | - } | ||
127 | - ], | ||
128 | - "metadata": { | ||
129 | - "kernelspec": { | ||
130 | - "display_name": "Python 3 (ipykernel)", | ||
131 | - "language": "python", | ||
132 | - "name": "python3" | ||
133 | - }, | ||
134 | - "language_info": { | ||
135 | - "codemirror_mode": { | ||
136 | - "name": "ipython", | ||
137 | - "version": 3 | ||
138 | - }, | ||
139 | - "file_extension": ".py", | ||
140 | - "mimetype": "text/x-python", | ||
141 | - "name": "python", | ||
142 | - "nbconvert_exporter": "python", | ||
143 | - "pygments_lexer": "ipython3", | ||
144 | - "version": "3.9.15" | ||
145 | - }, | ||
146 | - "vscode": { | ||
147 | - "interpreter": { | ||
148 | - "hash": "a59afa236e16843183c59a167f072b6fa0409044b3c4938e82ac98aad91bf217" | ||
149 | - } | ||
150 | - } | ||
151 | - }, | ||
152 | - "nbformat": 4, | ||
153 | - "nbformat_minor": 5 | ||
154 | -} |
code/python/__init__.py
code/python/__pycache__/event_lattice.cpython-39.pyc
No preview for this file type
code/python/algebra.py
@@ -1,30 +0,0 @@ | @@ -1,30 +0,0 @@ | ||
1 | -from itertools import combinations, product | ||
2 | - | ||
3 | -def fmt(expr): | ||
4 | - """Doc string""" | ||
5 | - return ",".join(f"{x:>2}" for x in expr) | ||
6 | - | ||
7 | -def c(expr): | ||
8 | - """Doc string""" | ||
9 | - def litcomp(x): | ||
10 | - if x == "⊤": | ||
11 | - return "⊥" | ||
12 | - elif x == "⊥": | ||
13 | - return "⊤" | ||
14 | - elif x[0] == "¬": | ||
15 | - return x[1:] | ||
16 | - else: | ||
17 | - return f"¬{x}" | ||
18 | - return [litcomp(x) for x in expr] | ||
19 | - | ||
20 | -def domain(symbols, unary="¬"): | ||
21 | - """Doc string""" | ||
22 | - atoms = list(symbols) | ||
23 | - literals = [ | ||
24 | - [f"{u}{a}" for u in unary] + | ||
25 | - [a, "⊤", "⊥"] for a in atoms ] | ||
26 | - return product(*literals) | ||
27 | - | ||
28 | -d = sorted(domain("abc")) | ||
29 | -for x in d: | ||
30 | - print(f"{fmt(x)} | {fmt(c(x))}") |
code/python/api_01.py
@@ -1,26 +0,0 @@ | @@ -1,26 +0,0 @@ | ||
1 | -from clingo.symbol import Number | ||
2 | -from clingo.control import Control | ||
3 | - | ||
4 | -class Context: | ||
5 | - def inc(self, x): | ||
6 | - return Number(x.number + 1) | ||
7 | - | ||
8 | - def seq(self, x, y): | ||
9 | - return [x, y] | ||
10 | - | ||
11 | -def on_model(m): | ||
12 | - print(m) | ||
13 | - | ||
14 | -ctl = Control() | ||
15 | -ctl.add("base", [], """\ | ||
16 | -p(@inc(10)). | ||
17 | -q(@seq(1,2)). | ||
18 | -""") | ||
19 | - | ||
20 | -ctl.ground( | ||
21 | - [("base", [])], | ||
22 | - context=Context()) | ||
23 | - | ||
24 | -s = ctl.solve(on_model=on_model) | ||
25 | - | ||
26 | -print(s) | ||
27 | \ No newline at end of file | 0 | \ No newline at end of file |
code/python/event_lattice.py
@@ -1,301 +0,0 @@ | @@ -1,301 +0,0 @@ | ||
1 | -import math | ||
2 | -from functools import cache | ||
3 | -from itertools import accumulate, combinations, chain, groupby | ||
4 | -import operator | ||
5 | - | ||
6 | - | ||
7 | - | ||
8 | -def uniform_op(x): | ||
9 | - n = len(list(x)) | ||
10 | - return 1.0 if n == 0 else 1.0/n | ||
11 | - | ||
12 | - | ||
13 | -def max_op(x): | ||
14 | - return max(x) | ||
15 | - | ||
16 | - | ||
17 | -def min_op(x): | ||
18 | - return min(x) | ||
19 | - | ||
20 | - | ||
21 | -def sum_op(x): | ||
22 | - return sum(x) | ||
23 | - | ||
24 | - | ||
25 | -def stableprod_op(x): | ||
26 | - log_x = map(math.log, x) | ||
27 | - return math.exp(sum(log_x)) | ||
28 | - | ||
29 | - | ||
30 | -def prod_op(x): | ||
31 | - return list(accumulate(x, func=lambda a,b: a*b))[-1] | ||
32 | - | ||
33 | - | ||
34 | -class Event: | ||
35 | - """Events. | ||
36 | - | ||
37 | - An event is a set of literals - atoms and negated atoms. | ||
38 | - | ||
39 | - The convention is that atoms are represented by lower case single letters | ||
40 | - and a negated atom by upper case single letters. | ||
41 | - """ | ||
42 | - | ||
43 | - @staticmethod | ||
44 | - def _parse(text): | ||
45 | - return frozenset(text) | ||
46 | - | ||
47 | - @staticmethod | ||
48 | - def parse(text): | ||
49 | - """Convert a string to an event. | ||
50 | - | ||
51 | - Each letter in the string represents a literal. | ||
52 | - """ | ||
53 | - return Event(Event._parse(text)) | ||
54 | - | ||
55 | - | ||
56 | - def __init__(self, literals): | ||
57 | - """Instantiate from a (frozen) set of literals. | ||
58 | - For example: e = Event(frozenset("abc")).""" | ||
59 | - self._literals = frozenset(literals) | ||
60 | - | ||
61 | - | ||
62 | - def literals(self): | ||
63 | - return self._literals | ||
64 | - | ||
65 | - | ||
66 | - def __iter__(self): | ||
67 | - return self._literals.__iter__() | ||
68 | - | ||
69 | - @cache | ||
70 | - def is_consistent(self): | ||
71 | - """True if this event is consistent.""" | ||
72 | - return all(x.swapcase() not in self._literals for x in self._literals) | ||
73 | - | ||
74 | - | ||
75 | - def co(self): | ||
76 | - """Negation of this event. | ||
77 | - | ||
78 | - Negation is case based: A = not a; a = not A.""" | ||
79 | - return Event(x.swapcase() for x in self._literals) | ||
80 | - | ||
81 | - def invert(self): | ||
82 | - """Negation of this event. | ||
83 | - | ||
84 | - See the method "co" | ||
85 | - """ | ||
86 | - return self.co() | ||
87 | - | ||
88 | - def __repr__(self) -> str: | ||
89 | - return ''.join(str(x) for x in sorted(self._literals)) if len(self._literals) > 0 else '0' | ||
90 | - | ||
91 | - def latex(self): | ||
92 | - """LaTeX representation of this even. | ||
93 | - | ||
94 | - Negation is represented by overline and the empty event by | ||
95 | - | ||
96 | - """ | ||
97 | - return ''.join( | ||
98 | - (str(x) if x.islower() else f"\co{{{x.lower()}}}") \ | ||
99 | - for x in sorted(self._literals) | ||
100 | - ) if len(self._literals) > 0 else "\set{}" | ||
101 | - | ||
102 | - def __hash__(self) -> int: | ||
103 | - return self._literals.__hash__() | ||
104 | - | ||
105 | - | ||
106 | - def __eq__(self, other): | ||
107 | - """Event equality test.""" | ||
108 | - return self._literals.__eq__(other._literals) | ||
109 | - | ||
110 | - def __or__(self, other): | ||
111 | - """Event union operation.""" | ||
112 | - return Event(self._literals | other._literals) | ||
113 | - | ||
114 | - def __le__(self, other): | ||
115 | - """Event subset test.""" | ||
116 | - return self._literals.__le__(other._literals) | ||
117 | - | ||
118 | - | ||
119 | - def __lt__(self, other): | ||
120 | - """Event strict subset test.""" | ||
121 | - return self._literals.__lt__(other._literals) | ||
122 | - | ||
123 | - | ||
124 | - def __ne__(self, other): | ||
125 | - """Event not-equal test.""" | ||
126 | - return self._literals.__ne__(other._literals) | ||
127 | - | ||
128 | - | ||
129 | - def __ge__(self, other): | ||
130 | - """Event superset test.""" | ||
131 | - return self._literals.__ge__(other._literals) | ||
132 | - | ||
133 | - | ||
134 | - def __gt__(self, other): | ||
135 | - """Event strict superset test.""" | ||
136 | - return self._literals.__gt__(other._literals) | ||
137 | - | ||
138 | - | ||
139 | -class Lattice: | ||
140 | - | ||
141 | - @staticmethod | ||
142 | - def parse(d): | ||
143 | - """Input stable models. | ||
144 | - | ||
145 | - The input format is a dictionary associating a stable model in string form to an weight. | ||
146 | - | ||
147 | - For example: | ||
148 | - | ||
149 | - input_dict = { | ||
150 | - "A": 0.3, | ||
151 | - "ab": 0.2, | ||
152 | - "ac": 0.5 | ||
153 | - } | ||
154 | - smodels = Lattice.parse(input_dict) | ||
155 | - """ | ||
156 | - result = dict() | ||
157 | - for k, v in d.items(): | ||
158 | - key = Event.parse(k) | ||
159 | - result[key] = v | ||
160 | - return result | ||
161 | - | ||
162 | - | ||
163 | - @staticmethod | ||
164 | - def close_literals(events): | ||
165 | - """Closed set of literals entailed by a set of events. | ||
166 | - | ||
167 | - Includes the literals in the set of events and any missing negation.""" | ||
168 | - base_lits = list(accumulate(events, func=operator.or_))[-1] | ||
169 | - lits = set() | ||
170 | - for x in base_lits.literals(): | ||
171 | - lits.add(x) | ||
172 | - lits.add(x.swapcase()) | ||
173 | - return sorted(lits) | ||
174 | - | ||
175 | - def __init__(self, smodels_dict): | ||
176 | - """Create an Events lattice.""" | ||
177 | - self._smodels = smodels_dict | ||
178 | - self._literals = Lattice.close_literals(self._smodels.keys()) | ||
179 | - | ||
180 | - def literals(self): | ||
181 | - """The literals in this lattice.""" | ||
182 | - return self._literals | ||
183 | - | ||
184 | - @cache | ||
185 | - def stable_models(self): | ||
186 | - """The stable models that generate this lattice.""" | ||
187 | - return self._smodels.keys() | ||
188 | - | ||
189 | - #@cache | ||
190 | - def events(self): | ||
191 | - """All the events of this lattice.""" | ||
192 | - return chain.from_iterable(map(Event, combinations(self._literals, r)) for r in range(len(self._literals)+1)) | ||
193 | - | ||
194 | - @cache | ||
195 | - def stable_core(self, event): | ||
196 | - """The stable core of an event in this lattice.""" | ||
197 | - return set(filter(lambda sm: sm <= event or event <= sm, self.stable_models())) | ||
198 | - | ||
199 | - # @cache | ||
200 | - # def event_class(self, event): | ||
201 | - # """The equivalence class of an event.""" | ||
202 | - # return EventsClass(self.stable_core(event), self) | ||
203 | - | ||
204 | - @cache | ||
205 | - def classes(self): | ||
206 | - """The classes of this lattice. | ||
207 | - | ||
208 | - Each class is presented as a key:value pair where the "key" is the stable core of the elements in "value".""" | ||
209 | - map_ev_classes = [(e, tuple(self.stable_core(e))) for e in self.events() if e.is_consistent()] | ||
210 | - groups = dict() | ||
211 | - for e,c in map_ev_classes: | ||
212 | - if c in groups.keys(): | ||
213 | - groups[c].add(e) | ||
214 | - else: | ||
215 | - groups[c] = set([e]) | ||
216 | - inconsistent = list(e for e in self.events() if not e.is_consistent()) | ||
217 | - inconsistent_repr = inconsistent[0] | ||
218 | - groups[(inconsistent_repr,)] = set(inconsistent) | ||
219 | - return groups | ||
220 | - | ||
221 | - | ||
222 | - def related(self, u, v): | ||
223 | - """Tests if two events are related.""" | ||
224 | - u_consistent = u.is_consistent() | ||
225 | - v_consistent = v.is_consistent() | ||
226 | - if u_consistent and (u_consistent == v_consistent): | ||
227 | - return self.stable_core(u) == self.stable_core(v) | ||
228 | - else: | ||
229 | - return u_consistent == v_consistent | ||
230 | - | ||
231 | - def extended_value(self, event:Event, | ||
232 | - op=prod_op): | ||
233 | - """TODO: well...""" | ||
234 | - value = 0 | ||
235 | - # | ||
236 | - # INCONSISTENT EVENTS | ||
237 | - # | ||
238 | - if not event.is_consistent(): | ||
239 | - return value | ||
240 | - # | ||
241 | - # CONSISTENT EVENTS | ||
242 | - # | ||
243 | - score = self.stable_core(event) | ||
244 | - len_score = len(score) | ||
245 | - # CONSISTENT, INDEPENDENT | ||
246 | - if len_score == 0: | ||
247 | - value = 0 | ||
248 | - elif len_score == 1: | ||
249 | - value = self._smodels[score[0]] | ||
250 | - else: | ||
251 | - value = op(map(lambda sm: self._smodels[sm], score)) | ||
252 | - | ||
253 | - return value | ||
254 | - | ||
255 | - def __repr__(self): | ||
256 | - smodels_repr = ',\n\t\t'.join(f"{k}: {v:<}" for k,v in self._smodels.items()) | ||
257 | - lits_repr = ','.join(sorted(self._literals)) | ||
258 | - | ||
259 | - return "{\n" +\ | ||
260 | - f"\t'stable_models': {{\n\t\t {smodels_repr} \n\t}}\n" +\ | ||
261 | - f"\t'literals': {{ {lits_repr} }} \n" +\ | ||
262 | - "}" | ||
263 | - | ||
264 | -# class EventsClass: | ||
265 | -# def __init__(self, core, lattice:Lattice): | ||
266 | -# self._core = core | ||
267 | -# self._lattice = lattice | ||
268 | - | ||
269 | -# def __repr__(self): | ||
270 | -# core_repr = "" if len(self._core) == 0 else ",".join(str(x) for x in self._core) | ||
271 | -# return f"<{core_repr}>" | ||
272 | - | ||
273 | -# def __contains__(self, event:Event): | ||
274 | -# return self.lattice.stable_core(event) == self._core | ||
275 | - | ||
276 | -if __name__ == "__main__": | ||
277 | - def zoom_event(event_str, lattice): | ||
278 | - event = Event.parse(event_str) | ||
279 | - event_class = lattice.event_class(event) | ||
280 | - propagated = lattice.extended_value( | ||
281 | - event) | ||
282 | - | ||
283 | - print( | ||
284 | - f"Event: {event}\n\tClass: {event_class} \n\tValue: {propagated}") | ||
285 | - | ||
286 | - smodels = Lattice.parse({ | ||
287 | - "A": 2, | ||
288 | - "ab": 3, | ||
289 | - "ac": 5 | ||
290 | - }) | ||
291 | - | ||
292 | - lattice = Lattice(smodels) | ||
293 | - | ||
294 | - ev_classes = lattice.classes() | ||
295 | - for k,g in ev_classes.items(): | ||
296 | - print(f"{tuple(s.latex() for s in k)} {set(e.latex() for e in g)}") | ||
297 | - # zoom_event("abc", lattice) | ||
298 | - # zoom_event("a", lattice) | ||
299 | - # zoom_event("b", lattice) | ||
300 | - # zoom_event("bc", lattice) | ||
301 | - # zoom_event("ac", lattice) | ||
302 | \ No newline at end of file | 0 | \ No newline at end of file |
code/python/explore_01.py
@@ -1,13 +0,0 @@ | @@ -1,13 +0,0 @@ | ||
1 | -from clingo.control import Control | ||
2 | -from clingox.program import Program, ProgramObserver, Remapping | ||
3 | - | ||
4 | -prg = Program() | ||
5 | -ctl_a = Control() | ||
6 | -ctl_a.register_observer(ProgramObserver(prg)) | ||
7 | -print(f"<1>\n{prg}\n</1>") | ||
8 | - | ||
9 | -prog = "code/asp/alarm.lp" | ||
10 | -ctl_a.load(prog) | ||
11 | -ctl_a.ground([('base', [])]) | ||
12 | -print(f"<2>\n{prg}\n</2>") | ||
13 | - |
code/python/symbops.py
@@ -1,41 +0,0 @@ | @@ -1,41 +0,0 @@ | ||
1 | -from unicodedata import numeric | ||
2 | -from sympy import * | ||
3 | -from sympy.plotting import plot | ||
4 | - | ||
5 | -def variants(expr, with_plot=False): | ||
6 | - print(f"Expr: {latex(expr)}") | ||
7 | - print(f"Simplify: {latex(simplify(expr))}") | ||
8 | - print(f"Expand: {latex(expand(expr))}") | ||
9 | - print(f"Factor: {latex(factor(expr))}") | ||
10 | - if with_plot: | ||
11 | - plot(expr, (d, 0, 1, 10),ylabel="$\\mathrm{P(expr \\mid \\alpha = 0.3)}$") | ||
12 | - | ||
13 | -init_printing(use_unicode=True) | ||
14 | - | ||
15 | -a, d = symbols('a d') | ||
16 | -A = 1 - a | ||
17 | -D = 1 - d | ||
18 | - | ||
19 | -wab = a * d | ||
20 | -wac = a * D | ||
21 | -wA = A | ||
22 | - | ||
23 | -wabc = wab * wac | ||
24 | -wAb = wA | ||
25 | -wa = wab + wac | ||
26 | -wb = wab | ||
27 | -wc = wac | ||
28 | -wE = wab + wab + wA | ||
29 | - | ||
30 | -z = wabc + 9 * wA + wab + wac + wa + wb +wc + wE | ||
31 | -pabc = wabc/z | ||
32 | - | ||
33 | -z_03 = z.subs(a, 0.3) | ||
34 | -wabc_03 = wabc.subs(a, 0.3) | ||
35 | -pabc_03 = pabc.subs(a, 0.3) | ||
36 | - | ||
37 | -variants(z_03) | ||
38 | -variants(wabc_03) | ||
39 | -variants(pabc_03) | ||
40 | -print(solve(wabc_03 - 0.0015 * z_03, d)) | ||
41 | - |
code/python/teste.ipynb
@@ -1,116 +0,0 @@ | @@ -1,116 +0,0 @@ | ||
1 | -{ | ||
2 | - "cells": [ | ||
3 | - { | ||
4 | - "cell_type": "code", | ||
5 | - "execution_count": 1, | ||
6 | - "metadata": {}, | ||
7 | - "outputs": [ | ||
8 | - { | ||
9 | - "data": { | ||
10 | - "text/plain": [ | ||
11 | - "4" | ||
12 | - ] | ||
13 | - }, | ||
14 | - "execution_count": 1, | ||
15 | - "metadata": {}, | ||
16 | - "output_type": "execute_result" | ||
17 | - } | ||
18 | - ], | ||
19 | - "source": [ | ||
20 | - "2+2" | ||
21 | - ] | ||
22 | - }, | ||
23 | - { | ||
24 | - "cell_type": "code", | ||
25 | - "execution_count": 3, | ||
26 | - "metadata": {}, | ||
27 | - "outputs": [], | ||
28 | - "source": [ | ||
29 | - "import matplotlib.pyplot as plt\n", | ||
30 | - "import numpy as np" | ||
31 | - ] | ||
32 | - }, | ||
33 | - { | ||
34 | - "cell_type": "code", | ||
35 | - "execution_count": 4, | ||
36 | - "metadata": {}, | ||
37 | - "outputs": [], | ||
38 | - "source": [ | ||
39 | - "x = np.linspace(-6, 6)" | ||
40 | - ] | ||
41 | - }, | ||
42 | - { | ||
43 | - "cell_type": "code", | ||
44 | - "execution_count": 5, | ||
45 | - "metadata": {}, | ||
46 | - "outputs": [], | ||
47 | - "source": [ | ||
48 | - "y = np.sin(x)" | ||
49 | - ] | ||
50 | - }, | ||
51 | - { | ||
52 | - "cell_type": "code", | ||
53 | - "execution_count": 6, | ||
54 | - "metadata": {}, | ||
55 | - "outputs": [ | ||
56 | - { | ||
57 | - "data": { | ||
58 | - "text/plain": [ | ||
59 | - "[<matplotlib.lines.Line2D at 0x7f2d55566b50>]" | ||
60 | - ] | ||
61 | - }, | ||
62 | - "execution_count": 6, | ||
63 | - "metadata": {}, | ||
64 | - "output_type": "execute_result" | ||
65 | - }, | ||
66 | - { | ||
67 | - "data": { | ||
68 | - "image/png": "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", | ||
69 | - "text/plain": [ | ||
70 | - "<Figure size 640x480 with 1 Axes>" | ||
71 | - ] | ||
72 | - }, | ||
73 | - "metadata": {}, | ||
74 | - "output_type": "display_data" | ||
75 | - } | ||
76 | - ], | ||
77 | - "source": [ | ||
78 | - "plt.plot(x,y)" | ||
79 | - ] | ||
80 | - }, | ||
81 | - { | ||
82 | - "cell_type": "code", | ||
83 | - "execution_count": null, | ||
84 | - "metadata": {}, | ||
85 | - "outputs": [], | ||
86 | - "source": [] | ||
87 | - } | ||
88 | - ], | ||
89 | - "metadata": { | ||
90 | - "kernelspec": { | ||
91 | - "display_name": "Python 3.9.15 ('base')", | ||
92 | - "language": "python", | ||
93 | - "name": "python3" | ||
94 | - }, | ||
95 | - "language_info": { | ||
96 | - "codemirror_mode": { | ||
97 | - "name": "ipython", | ||
98 | - "version": 3 | ||
99 | - }, | ||
100 | - "file_extension": ".py", | ||
101 | - "mimetype": "text/x-python", | ||
102 | - "name": "python", | ||
103 | - "nbconvert_exporter": "python", | ||
104 | - "pygments_lexer": "ipython3", | ||
105 | - "version": "3.9.15" | ||
106 | - }, | ||
107 | - "orig_nbformat": 4, | ||
108 | - "vscode": { | ||
109 | - "interpreter": { | ||
110 | - "hash": "a59afa236e16843183c59a167f072b6fa0409044b3c4938e82ac98aad91bf217" | ||
111 | - } | ||
112 | - } | ||
113 | - }, | ||
114 | - "nbformat": 4, | ||
115 | - "nbformat_minor": 2 | ||
116 | -} |
@@ -0,0 +1,100 @@ | @@ -0,0 +1,100 @@ | ||
1 | +c | ||
2 | +a | ||
3 | +B | ||
4 | +c | ||
5 | +ab | ||
6 | +Ac | ||
7 | +aBC | ||
8 | +BC | ||
9 | +Ab | ||
10 | +b | ||
11 | +c | ||
12 | +AB | ||
13 | +Ac | ||
14 | +B | ||
15 | +bC | ||
16 | +Ab | ||
17 | + | ||
18 | +aB | ||
19 | +B | ||
20 | +a | ||
21 | +aC | ||
22 | +B | ||
23 | +AB | ||
24 | +B | ||
25 | + | ||
26 | +C | ||
27 | +bc | ||
28 | + | ||
29 | +B | ||
30 | +bc | ||
31 | +AC | ||
32 | +ABC | ||
33 | +a | ||
34 | +b | ||
35 | +ac | ||
36 | +AC | ||
37 | +B | ||
38 | +bC | ||
39 | +b | ||
40 | +C | ||
41 | + | ||
42 | +aC | ||
43 | +AbC | ||
44 | + | ||
45 | +C | ||
46 | +AC | ||
47 | +bc | ||
48 | + | ||
49 | + | ||
50 | +C | ||
51 | +b | ||
52 | + | ||
53 | +b | ||
54 | +abc | ||
55 | +a | ||
56 | +abc | ||
57 | + | ||
58 | +B | ||
59 | +a | ||
60 | +C | ||
61 | +aB | ||
62 | + | ||
63 | +A | ||
64 | +Bc | ||
65 | +C | ||
66 | +AB | ||
67 | +aBc | ||
68 | +A | ||
69 | +b | ||
70 | + | ||
71 | +a | ||
72 | +a | ||
73 | +c | ||
74 | +b | ||
75 | +a | ||
76 | +A | ||
77 | +Ab | ||
78 | +aC | ||
79 | + | ||
80 | +B | ||
81 | +C | ||
82 | +Ab | ||
83 | +Bc | ||
84 | +A | ||
85 | +Ac | ||
86 | +c | ||
87 | +B | ||
88 | +AC | ||
89 | +ABC | ||
90 | +Ab | ||
91 | +aC | ||
92 | +bC | ||
93 | + | ||
94 | + | ||
95 | +C | ||
96 | +a | ||
97 | + | ||
98 | +ABC | ||
99 | +b | ||
100 | +aB |
students/amartins/tarefas/tarefa2.py
@@ -26,13 +26,20 @@ if __name__ == "__main__": | @@ -26,13 +26,20 @@ if __name__ == "__main__": | ||
26 | parents = model.get_parents(node) | 26 | parents = model.get_parents(node) |
27 | s = "" | 27 | s = "" |
28 | if len(parents) == 0: | 28 | if len(parents) == 0: |
29 | - s += str(yes_prob) + " :: " + str(node) | 29 | + s += str(yes_prob) + " :: " + str(node) +"\n" |
30 | print(s) | 30 | print(s) |
31 | elif len(parents) == 1: | 31 | elif len(parents) == 1: |
32 | - s += str(yes_prob[0]) + " :: " + str(node) + " <- " + str(parents) + "\n" | ||
33 | - s += str(yes_prob[1]) + " :: " + str(node) + " <- -" + str(parents) + "\n" | 32 | + p = parents[0] |
33 | + s += str(yes_prob[0]) + " :: " + str(node) + " <- " + str(p) + "\n" | ||
34 | + s += str(yes_prob[1]) + " :: " + str(node) + " <- -" + str(p) + "\n" | ||
34 | print(s) | 35 | print(s) |
35 | else: | 36 | else: |
36 | - print("Node:", node) | ||
37 | - print("Probability of 'yes':", yes_prob) | ||
38 | - print() | 37 | + yes1 = yes_prob[0] |
38 | + yes2 = yes_prob[1] | ||
39 | + p0 = parents[0] | ||
40 | + p1 = parents[1] | ||
41 | + s += str(yes1[0]) + " :: " + str(node) + " <- " + str(p0) + ", " + str(p1) + "\n" | ||
42 | + s += str(yes2[0]) + " :: " + str(node) + " <- -" + str(p0) + ", " + str(p1) + "\n" | ||
43 | + s += str(yes1[1]) + " :: " + str(node) + " <- " + str(p0) + ", -" + str(p1) + "\n" | ||
44 | + s += str(yes2[1]) + " :: " + str(node) + " <- -" + str(p0) + ", -" + str(p1) + "\n" | ||
45 | + print(s) |
text/paper_01/pre-paper.pdf
No preview for this file type
text/paper_01/pre-paper.tex
@@ -17,7 +17,7 @@ proptc/.style = {-latex, dashed}, | @@ -17,7 +17,7 @@ proptc/.style = {-latex, dashed}, | ||
17 | propsm/.style = {-latex, thick}, | 17 | propsm/.style = {-latex, thick}, |
18 | doubt/.style = {gray} | 18 | doubt/.style = {gray} |
19 | } | 19 | } |
20 | -\usetikzlibrary{calc, positioning} | 20 | +\usetikzlibrary{calc, positioning, patterns} |
21 | 21 | ||
22 | \usepackage{hyperref} | 22 | \usepackage{hyperref} |
23 | \hypersetup{ | 23 | \hypersetup{ |
@@ -93,16 +93,18 @@ citecolor=blue, | @@ -93,16 +93,18 @@ citecolor=blue, | ||
93 | \acrodef{SC}[SC]{stable core} | 93 | \acrodef{SC}[SC]{stable core} |
94 | \acrodef{KL}[KL]{Kullback-Leibler} | 94 | \acrodef{KL}[KL]{Kullback-Leibler} |
95 | 95 | ||
96 | -\title{Zugzwang\\\emph{Logic and Artificial Intelligence}\\{\bruno Why this title?}} | 96 | +\title{An Algebraic Approach to Stochastic ASP |
97 | + %Zugzwang\\\emph{Logic and Artificial Intelligence}\\{\bruno Why this title?} | ||
98 | + } | ||
97 | 99 | ||
98 | \author{ | 100 | \author{ |
99 | \begin{tabular}{ccc} | 101 | \begin{tabular}{ccc} |
100 | Francisco Coelho | 102 | Francisco Coelho |
101 | - \footnote{Universidade de Évora} | 103 | + \footnote{Universidade de Évora, NOVALINCS, High Performance Computing Chair} |
102 | & Bruno Dinis | 104 | & Bruno Dinis |
103 | - \footnote{Universidade de Évora} | 105 | + \footnote{Universidade de Évora, CIMA, CMAFcIO} |
104 | & Salvador Abreu | 106 | & Salvador Abreu |
105 | - \footnote{Universidade de Évora} | 107 | + \footnote{Universidade de Évora, NOVALINCS} |
106 | \\ | 108 | \\ |
107 | \texttt{fc@uevora.pt} | 109 | \texttt{fc@uevora.pt} |
108 | & \texttt{bruno.dinis@uevora.pt} | 110 | & \texttt{bruno.dinis@uevora.pt} |
@@ -148,8 +150,9 @@ Our idea to extend probabilities starts with the stance that a specification des | @@ -148,8 +150,9 @@ Our idea to extend probabilities starts with the stance that a specification des | ||
148 | Extending probability from \acp{TC} to \acp{SM} faces a critical problem, illustrated by the example in \cref{sec:example.1}, concerning situations where multiple \acp{SM}, $ab$ and $ac$, result from a single \ac{TC}, $a$, but there is not enough information (in the specification) to assign a single probability to each \ac{SM}. We propose to address this issue by using algebraic variables to describe that lack of information and then estimate the value of those variables from empirical data. | 150 | Extending probability from \acp{TC} to \acp{SM} faces a critical problem, illustrated by the example in \cref{sec:example.1}, concerning situations where multiple \acp{SM}, $ab$ and $ac$, result from a single \ac{TC}, $a$, but there is not enough information (in the specification) to assign a single probability to each \ac{SM}. We propose to address this issue by using algebraic variables to describe that lack of information and then estimate the value of those variables from empirical data. |
149 | 151 | ||
150 | In a related work, \cite{verreet2022inference}, epistemic uncertainty (or model uncertainty) is considered as a lack of knowledge about the underlying model, that may be mitigated via further observations. This seems to presuppose a Bayesian approach to imperfect knowledge in the sense that having further observations allows to improve/correct the model. Indeed, the approach in that work uses Beta distributions in order to be able to learn the full distribution. This approach seems to be specially fitted to being able to tell when some probability lies beneath some given value. \todo{Our approach seems to be similar in spirit. If so, we should mention this in the introduction.} | 152 | In a related work, \cite{verreet2022inference}, epistemic uncertainty (or model uncertainty) is considered as a lack of knowledge about the underlying model, that may be mitigated via further observations. This seems to presuppose a Bayesian approach to imperfect knowledge in the sense that having further observations allows to improve/correct the model. Indeed, the approach in that work uses Beta distributions in order to be able to learn the full distribution. This approach seems to be specially fitted to being able to tell when some probability lies beneath some given value. \todo{Our approach seems to be similar in spirit. If so, we should mention this in the introduction.} |
153 | +\todo{Also remark that our apporach remains algebraic in the way that we address the problems concerning the extension of probabilities.} | ||
151 | 154 | ||
152 | -\todo{cite \cite{sympy} \franc{--- why here? but cite \cite{cozman2020joy} and relate with our work.}} | 155 | +\todo{cite \citetitle{sympy} \franc{--- why here? but cite \citetitle{cozman2020joy} and relate with our work.}} |
153 | 156 | ||
154 | \todo{Discuss the least informed strategy and the corolary that \aclp{SM} should be conditionally independent on the \acl{TC}.} | 157 | \todo{Discuss the least informed strategy and the corolary that \aclp{SM} should be conditionally independent on the \acl{TC}.} |
155 | 158 | ||
@@ -239,6 +242,8 @@ The \aclp{SM} $ab, ac$ from \cref{running.example} result from the clause $b \v | @@ -239,6 +242,8 @@ The \aclp{SM} $ab, ac$ from \cref{running.example} result from the clause $b \v | ||
239 | 242 | ||
240 | \draw[doubt] (ac) to[bend right] (abc); | 243 | \draw[doubt] (ac) to[bend right] (abc); |
241 | \draw[doubt] (ac) to[bend left] (aBc); | 244 | \draw[doubt] (ac) to[bend left] (aBc); |
245 | + | ||
246 | + \draw[doubt, dash dot] (Ac) to (Abc); | ||
242 | 247 | ||
243 | \draw[doubt] (A) to (Ac); | 248 | \draw[doubt] (A) to (Ac); |
244 | \draw[doubt] (A) to (Abc); | 249 | \draw[doubt] (A) to (Abc); |
@@ -251,10 +256,10 @@ The \aclp{SM} $ab, ac$ from \cref{running.example} result from the clause $b \v | @@ -251,10 +256,10 @@ The \aclp{SM} $ab, ac$ from \cref{running.example} result from the clause $b \v | ||
251 | \draw[doubt] (ac) to (c); | 256 | \draw[doubt] (ac) to (c); |
252 | % \draw[doubt] (ab) to[bend left] (a); | 257 | % \draw[doubt] (ab) to[bend left] (a); |
253 | % \draw[doubt] (ac) to[bend right] (a); | 258 | % \draw[doubt] (ac) to[bend right] (a); |
254 | - \draw[doubt] (c) to[bend right] (bc); | ||
255 | - \draw[doubt] (abc) to[bend left] (bc); | ||
256 | - \draw[doubt] (Abc) to (bc); | ||
257 | - \draw[doubt] (c) to[bend right] (Ac); | 259 | + \draw[doubt, dash dot] (c) to[bend right] (bc); |
260 | + \draw[doubt, dash dot] (abc) to[bend left] (bc); | ||
261 | + \draw[doubt, dash dot] (bc) to (Abc); | ||
262 | + \draw[doubt, dash dot] (c) to[bend right] (Ac); | ||
258 | \end{tikzpicture} | 263 | \end{tikzpicture} |
259 | \end{center} | 264 | \end{center} |
260 | 265 | ||
@@ -287,7 +292,7 @@ The diagram in \cref{fig:running.example} illustrates the problem of extending p | @@ -287,7 +292,7 @@ The diagram in \cref{fig:running.example} illustrates the problem of extending p | ||
287 | \node[event, above = of A] (Ac) {$\co{a}c$}; | 292 | \node[event, above = of A] (Ac) {$\co{a}c$}; |
288 | \node[event, above right = of Ac] (Abc) {$\co{a}bc$}; | 293 | \node[event, above right = of Ac] (Abc) {$\co{a}bc$}; |
289 | % ---- | 294 | % ---- |
290 | - \path[draw, rounded corners, fill=cyan, fill opacity=0.1] | 295 | + \path[draw, rounded corners, pattern=north west lines, opacity=0.2] |
291 | (ab.west) -- | 296 | (ab.west) -- |
292 | (ab.north west) -- | 297 | (ab.north west) -- |
293 | % | 298 | % |
@@ -316,7 +321,7 @@ The diagram in \cref{fig:running.example} illustrates the problem of extending p | @@ -316,7 +321,7 @@ The diagram in \cref{fig:running.example} illustrates the problem of extending p | ||
316 | (ab.west) | 321 | (ab.west) |
317 | ; | 322 | ; |
318 | % ---- | 323 | % ---- |
319 | - \path[draw, rounded corners, fill=magenta, fill opacity=0.1] | 324 | + \path[draw, rounded corners, pattern=north east lines, opacity=0.2] |
320 | (ac.south west) -- | 325 | (ac.south west) -- |
321 | (ac.west) -- | 326 | (ac.west) -- |
322 | (ac.north west) -- | 327 | (ac.north west) -- |
@@ -346,7 +351,7 @@ The diagram in \cref{fig:running.example} illustrates the problem of extending p | @@ -346,7 +351,7 @@ The diagram in \cref{fig:running.example} illustrates the problem of extending p | ||
346 | (ac.south west) | 351 | (ac.south west) |
347 | ; | 352 | ; |
348 | % ---- | 353 | % ---- |
349 | - \path[draw, rounded corners, fill=yellow, fill opacity=0.1] | 354 | + \path[draw, rounded corners, pattern=horizontal lines, opacity=0.2] |
350 | % (A.north west) -- | 355 | % (A.north west) -- |
351 | % | 356 | % |
352 | (Ac.north west) -- | 357 | (Ac.north west) -- |
@@ -373,7 +378,7 @@ The diagram in \cref{fig:running.example} illustrates the problem of extending p | @@ -373,7 +378,7 @@ The diagram in \cref{fig:running.example} illustrates the problem of extending p | ||
373 | \end{tikzpicture} | 378 | \end{tikzpicture} |
374 | \end{center} | 379 | \end{center} |
375 | 380 | ||
376 | - \caption{Classes (of consistent events) related to the \aclp{SM} of \cref{running.example} are defined through inclusions. \todo{write the caption}} | 381 | + \caption{Classes (of consistent events) related to the \aclp{SM} of \cref{running.example} are defined through intersections and inclusions. \todo{write the caption}} |
377 | \label{fig:running.example.classes} | 382 | \label{fig:running.example.classes} |
378 | \end{figure} | 383 | \end{figure} |
379 | 384 | ||
@@ -559,7 +564,7 @@ The ``extension'' phase, traced by equations (\ref{eq:prob.total.choice}) and (\ | @@ -559,7 +564,7 @@ The ``extension'' phase, traced by equations (\ref{eq:prob.total.choice}) and (\ | ||
559 | \pw{\class{e}} := \sum_{t \in \fml{T}} \pw{\class{e}, t}\pw{t}. | 564 | \pw{\class{e}} := \sum_{t \in \fml{T}} \pw{\class{e}, t}\pw{t}. |
560 | \label{eq:weight.class.unconditional} | 565 | \label{eq:weight.class.unconditional} |
561 | \end{equation} | 566 | \end{equation} |
562 | - \remark{}{Changed from $\prod$ to $\sum$ to represent ``either'' instead of ``both'' since the later is not consistent with the ``only one stable model at a time'' assumption.} | 567 | + |
563 | \end{description} | 568 | \end{description} |
564 | % | 569 | % |
565 | \item[Events.] \label{item:event.cases} Each (general) event $e$ is in the class defined by its \acl{SC}, $\stablecore{e}$. So, we set: | 570 | \item[Events.] \label{item:event.cases} Each (general) event $e$ is in the class defined by its \acl{SC}, $\stablecore{e}$. So, we set: |
@@ -618,9 +623,9 @@ We continue with the specification from Equation \eqref{eq:example.1}. | @@ -618,9 +623,9 @@ We continue with the specification from Equation \eqref{eq:example.1}. | ||
618 | \item[\Aclp{SM}.] The $\theta_{s,t}$ parameters in this example are | 623 | \item[\Aclp{SM}.] The $\theta_{s,t}$ parameters in this example are |
619 | $$ | 624 | $$ |
620 | \theta_{ab,\co{a}} = \theta_{ac,\co{a}} = \theta_{\co{a}, a} = 0 | 625 | \theta_{ab,\co{a}} = \theta_{ac,\co{a}} = \theta_{\co{a}, a} = 0 |
621 | - $$ | ||
622 | - and | ||
623 | - $$ | 626 | + % |
627 | + \text{~and~} | ||
628 | + % | ||
624 | \theta_{\co{a}, \co{a}} = 1, \theta_{ab, a} = \theta, \theta_{ac, a} = \co{\theta} | 629 | \theta_{\co{a}, \co{a}} = 1, \theta_{ab, a} = \theta, \theta_{ac, a} = \co{\theta} |
625 | $$ | 630 | $$ |
626 | with $\theta \in \intcc{0, 1}$. | 631 | with $\theta \in \intcc{0, 1}$. |
@@ -675,7 +680,7 @@ We continue with the specification from Equation \eqref{eq:example.1}. | @@ -675,7 +680,7 @@ We continue with the specification from Equation \eqref{eq:example.1}. | ||
675 | & 1 | 680 | & 1 |
676 | \end{array} | 681 | \end{array} |
677 | \end{equation*} | 682 | \end{equation*} |
678 | - \item[Normalization.] To get a weight that sums up to one, we compute the \emph{normalization factor}. Since $\pw{\cdot}$ is constant on classes, | 683 | + \item[Normalization.] To get a weight that sums up to one, we compute the \emph{normalization factor}. Since $\pw{\cdot}$ is constant on classes,\todo{prove that we get a probability.} |
679 | \begin{equation*} | 684 | \begin{equation*} |
680 | Z := \sum_{e\in\fml{E}} \pw{e} | 685 | Z := \sum_{e\in\fml{E}} \pw{e} |
681 | = \sum_{\class{e} \in\class{\fml{E}}} \frac{\pw{\class{e}}}{\#\class{e}}, | 686 | = \sum_{\class{e} \in\class{\fml{E}}} \frac{\pw{\class{e}}}{\#\class{e}}, |
@@ -704,95 +709,81 @@ We continue with the specification from Equation \eqref{eq:example.1}. | @@ -704,95 +709,81 @@ We continue with the specification from Equation \eqref{eq:example.1}. | ||
704 | & 0 | 709 | & 0 |
705 | & 0 | 710 | & 0 |
706 | & 0 | 711 | & 0 |
707 | - \\ | 712 | + \\[4pt] |
708 | % | 713 | % |
709 | \indepclass | 714 | \indepclass |
710 | & 9 | 715 | & 9 |
711 | & 0 | 716 | & 0 |
712 | & 0 | 717 | & 0 |
713 | & 0 | 718 | & 0 |
714 | - \\ | 719 | + \\[4pt] |
715 | % | 720 | % |
716 | \co{a} | 721 | \co{a} |
717 | & 9 | 722 | & 9 |
718 | - & \lfrac{7}{10} | ||
719 | - & \lfrac{7}{90} | ||
720 | - & \lfrac{7}{792} | ||
721 | - \\ | 723 | + & \frac{7}{10} |
724 | + & \frac{7}{90} | ||
725 | + & \frac{7}{792} | ||
726 | + \\[4pt] | ||
722 | % | 727 | % |
723 | ab | 728 | ab |
724 | & 3 | 729 | & 3 |
725 | - & \lfrac{3\theta}{10} | ||
726 | - & \lfrac{\theta}{10} | ||
727 | - & \lfrac{\theta}{88} | ||
728 | - \\ | 730 | + & \frac{3\theta}{10} |
731 | + & \frac{\theta}{10} | ||
732 | + & \frac{\theta}{88} | ||
733 | + \\[4pt] | ||
729 | % | 734 | % |
730 | ac | 735 | ac |
731 | & 3 | 736 | & 3 |
732 | - & \lfrac{3\co{\theta}}{10} | ||
733 | - & \lfrac{\co{\theta}}{10} | ||
734 | - & \lfrac{\co{\theta}}{88} | ||
735 | - \\ | 737 | + & \frac{3\co{\theta}}{10} |
738 | + & \frac{\co{\theta}}{10} | ||
739 | + & \frac{\co{\theta}}{88} | ||
740 | + \\[4pt] | ||
736 | % | 741 | % |
737 | \co{a}, ab | 742 | \co{a}, ab |
738 | & 0 | 743 | & 0 |
739 | - & | ||
740 | - & | ||
741 | - & | ||
742 | - \\ | 744 | + & \frac{7 + 3\theta}{10} |
745 | + & 0 | ||
746 | + & 0 | ||
747 | + \\[4pt] | ||
743 | % | 748 | % |
744 | \co{a}, ac | 749 | \co{a}, ac |
745 | & 0 | 750 | & 0 |
746 | - & | ||
747 | - & | ||
748 | - & | 751 | + & \frac{7 + 3\co{\theta}}{10} |
752 | + & 0 | ||
753 | + & 0 | ||
749 | % | 754 | % |
750 | - \\ | 755 | + \\[4pt] |
751 | % | 756 | % |
752 | ab, ac | 757 | ab, ac |
753 | & 2 | 758 | & 2 |
754 | - & \lfrac{3}{10} | ||
755 | - & \lfrac{3}{20} | ||
756 | - & \lfrac{3}{176} | ||
757 | - \\ | 759 | + & \frac{3}{10} |
760 | + & \frac{3}{20} | ||
761 | + & \frac{3}{176} | ||
762 | + \\[4pt] | ||
758 | % | 763 | % |
759 | \co{a}, ab, ac | 764 | \co{a}, ab, ac |
760 | & 1 | 765 | & 1 |
761 | & 1 | 766 | & 1 |
762 | & 1 | 767 | & 1 |
763 | - & \lfrac{5}{176} | ||
764 | - \\ | 768 | + & \frac{5}{176} |
769 | + \\[4pt] | ||
765 | % | 770 | % |
766 | \hline | 771 | \hline |
767 | & | 772 | & |
768 | - & Z = 8.8 | 773 | + & Z = \frac{44}{5} |
769 | \end{array} | 774 | \end{array} |
770 | \end{equation*} | 775 | \end{equation*} |
771 | \end{description} | 776 | \end{description} |
777 | + | ||
778 | +\todo{Continue this example with a set of observations to estimate $\theta$ and try to show some more. For example, that the resulting distribution is not very good when $t = \co{a}$. Also gather a sample following the specification.} | ||
772 | % | 779 | % |
773 | % | 780 | % |
774 | % | 781 | % |
775 | -\subsection{A Not So Simple Example} | ||
776 | - | ||
777 | -\todo{this subsection} | ||
778 | - | ||
779 | -In this section we see how the classical example of the Burglary, Earthquake, Alarm \cite{Judea88} works in our setting. This example is a commonly used example in Bayesian networks because it illustrates reasoning under uncertainty. The gist of example is given in \cref{Figure_Alarm}. It involves a simple network of events and conditional probabilities. | ||
780 | - | ||
781 | -The events are: Burglary ($B$), Earthquake ($E$), Alarm ($A$), Mary calls ($M$) and John calls ($J$). The initial events $B$ and $E$ are assumed to be independent events that occur with probabilities $P(B)$ and $P(E)$, respectively. There is an alarm system that can be triggered by either of the initial events $B$ and $E$. The probability of the alarm going off is a conditional probability depending on whether $B$, or $E$ as occurred. One denotes these probabilities, as per usual, by $P(A|B)$, and $P(A|E)$. There are two neighbours, Mary and John who have agreed to call if they hear the alarm. The probability that they do actually call is also a conditional probability denoted by $P(M|A)$ and $P(J|A)$, respectively. | ||
782 | - | ||
783 | -Considering the probabilities given in \cref{Figure_Alarm} we obtain the following specification | ||
784 | - | ||
785 | -\begin{equation*} | ||
786 | - \begin{aligned} | ||
787 | - \probfact{0.001}{B}&,\cr | ||
788 | - \probfact{0.002}{E}&,\cr | ||
789 | - \probfact{??}{A}&,\cr | ||
790 | - ... &. \cr | ||
791 | - \end{aligned} | ||
792 | - \label{eq:not_so_simple_example} | ||
793 | -\end{equation*} | 782 | +\subsection{An example involving Bayesian networks} |
794 | 783 | ||
784 | +As it turns out, our framework is suitable to deal with more sophisticated cases, for example cases involving Bayesian networks. In order to illustrate this, in this section we see how the classical example of the Burglary, Earthquake, Alarm \cite{Judea88} works in our setting. This example is a commonly used example in Bayesian networks because it illustrates reasoning under uncertainty. The gist of example is given in \cref{Figure_Alarm}. It involves a simple network of events and conditional probabilities. | ||
795 | 785 | ||
786 | +The events are: Burglary ($B$), Earthquake ($E$), Alarm ($A$), Mary calls ($M$) and John calls ($J$). The initial events $B$ and $E$ are assumed to be independent events that occur with probabilities $P(B)$ and $P(E)$, respectively. There is an alarm system that can be triggered by either of the initial events $B$ and $E$. The probability of the alarm going off is a conditional probability given that $B$ and $E$ have occurred. One denotes these probabilities, as per usual, by $P(A|B)$, and $P(A|E)$. There are two neighbours, Mary and John who have agreed to call if they hear the alarm. The probability that they do actually call is also a conditional probability denoted by $P(M|A)$ and $P(J|A)$, respectively. | ||
796 | 787 | ||
797 | 788 | ||
798 | 789 | ||
@@ -808,8 +799,8 @@ Considering the probabilities given in \cref{Figure_Alarm} we obtain the followi | @@ -808,8 +799,8 @@ Considering the probabilities given in \cref{Figure_Alarm} we obtain the followi | ||
808 | \node[tchoice, below right of=A] (J) {J}; | 799 | \node[tchoice, below right of=A] (J) {J}; |
809 | 800 | ||
810 | % Edges | 801 | % Edges |
811 | - \draw[->] (B) to[bend left] (A) node[right,xshift=1.1cm,yshift=0.8cm] {\footnotesize{$P(B)=0,001$}} ; | ||
812 | - \draw[->] (E) to[bend right] (A) node[left, xshift=-1.4cm,yshift=0.8cm] {\footnotesize{$P(E)=0,002$}} ; | 802 | + \draw[->] (B) to[bend left] (A) node[right,xshift=1.1cm,yshift=0.8cm] {\footnotesize{$P(B)=0.001$}} ; |
803 | + \draw[->] (E) to[bend right] (A) node[left, xshift=-1.4cm,yshift=0.8cm] {\footnotesize{$P(E)=0.002$}} ; | ||
813 | \draw[->] (A) to[bend right] (M) node[left,xshift=0.2cm,yshift=0.7cm] {\footnotesize{$P(M|A)$}}; | 804 | \draw[->] (A) to[bend right] (M) node[left,xshift=0.2cm,yshift=0.7cm] {\footnotesize{$P(M|A)$}}; |
814 | \draw[->] (A) to[bend left] (J) node[right,xshift=-0.2cm,yshift=0.7cm] {\footnotesize{$P(J|A)$}} ; | 805 | \draw[->] (A) to[bend left] (J) node[right,xshift=-0.2cm,yshift=0.7cm] {\footnotesize{$P(J|A)$}} ; |
815 | \end{tikzpicture} | 806 | \end{tikzpicture} |
@@ -822,10 +813,10 @@ Considering the probabilities given in \cref{Figure_Alarm} we obtain the followi | @@ -822,10 +813,10 @@ Considering the probabilities given in \cref{Figure_Alarm} we obtain the followi | ||
822 | \begin{split} | 813 | \begin{split} |
823 | &P(M|A)\\ | 814 | &P(M|A)\\ |
824 | & \begin{array}{c|cc} | 815 | & \begin{array}{c|cc} |
825 | - A & T & F \ | 816 | + & m & \neg m \ |
826 | \hline | 817 | \hline |
827 | - T & 0,9 & 0,1\\ | ||
828 | - F& 0,05 & 0,95 | 818 | + a & 0.9 & 0.1\\ |
819 | + \neg a& 0.05 & 0.95 | ||
829 | \end{array} | 820 | \end{array} |
830 | \end{split} | 821 | \end{split} |
831 | \end{equation*} | 822 | \end{equation*} |
@@ -836,10 +827,10 @@ Considering the probabilities given in \cref{Figure_Alarm} we obtain the followi | @@ -836,10 +827,10 @@ Considering the probabilities given in \cref{Figure_Alarm} we obtain the followi | ||
836 | \begin{split} | 827 | \begin{split} |
837 | &P(J|A)\\ | 828 | &P(J|A)\\ |
838 | & \begin{array}{c|cc} | 829 | & \begin{array}{c|cc} |
839 | - A & T & F \ | 830 | + & j & \neg j \ |
840 | \hline | 831 | \hline |
841 | - T & 0,7 & 0,3\\ | ||
842 | - F& 0,01 & 0,99 | 832 | + a & 0.7 & 0.3\\ |
833 | + \neg a& 0.01 & 0.99 | ||
843 | \end{array} | 834 | \end{array} |
844 | \end{split} | 835 | \end{split} |
845 | \end{equation*} | 836 | \end{equation*} |
@@ -847,14 +838,14 @@ Considering the probabilities given in \cref{Figure_Alarm} we obtain the followi | @@ -847,14 +838,14 @@ Considering the probabilities given in \cref{Figure_Alarm} we obtain the followi | ||
847 | \footnotesize{ | 838 | \footnotesize{ |
848 | \begin{equation*} | 839 | \begin{equation*} |
849 | \begin{split} | 840 | \begin{split} |
850 | - P(A|B \vee E)\ | 841 | + P(A|B \wedge E)\ |
851 | \begin{array}{c|c|cc} | 842 | \begin{array}{c|c|cc} |
852 | - B & E& T & F \ | 843 | + & & a & \neg a \ |
853 | \hline | 844 | \hline |
854 | - T & T & 0,95 & 0,05\\ | ||
855 | - T & F & 0,94 & 0,06\\ | ||
856 | - F & T & 0,29 & 0,71\\ | ||
857 | - F & F & 0,001 & 0,999 | 845 | + b & e & 0.95 & 0.05\\ |
846 | + b & \neg e & 0.94 & 0.06\\ | ||
847 | + \neg b & e & 0.29 & 0.71\\ | ||
848 | + \neg b & \neg e & 0.001 & 0.999 | ||
858 | \end{array} | 849 | \end{array} |
859 | \end{split} | 850 | \end{split} |
860 | \end{equation*} | 851 | \end{equation*} |
@@ -865,6 +856,64 @@ Considering the probabilities given in \cref{Figure_Alarm} we obtain the followi | @@ -865,6 +856,64 @@ Considering the probabilities given in \cref{Figure_Alarm} we obtain the followi | ||
865 | \end{figure} | 856 | \end{figure} |
866 | 857 | ||
867 | 858 | ||
859 | +Considering the probabilities given in \cref{Figure_Alarm} we obtain the following specification | ||
860 | + | ||
861 | +\begin{equation*} | ||
862 | + \begin{aligned} | ||
863 | + \probfact{0.001}{b}&,\cr | ||
864 | + \probfact{0.002}{e}&,\cr | ||
865 | + \end{aligned} | ||
866 | + \label{eq:not_so_simple_example} | ||
867 | +\end{equation*} | ||
868 | + | ||
869 | +For the table giving the probability $P(M|A)$ we obtain the specification: | ||
870 | + | ||
871 | + | ||
872 | +\begin{equation*} | ||
873 | + \begin{aligned} | ||
874 | + &\probfact{0.9}{pm\_a},\cr | ||
875 | + &\probfact{0.05}{pm\_na},\cr | ||
876 | + m & \leftarrow a, pm\_a,\cr | ||
877 | + \neg m & \leftarrow a, \neg pm\_a. | ||
878 | + \end{aligned} | ||
879 | +\end{equation*} | ||
880 | + | ||
881 | +This latter specification can be simplified by writing $\probfact{0.9}{m \leftarrow a}$ and $\probfact{0.05}{m \leftarrow \neg a}$. | ||
882 | + | ||
883 | +Similarly, for the probability $P(J|A)$ we obtain | ||
884 | + | ||
885 | +\begin{equation*} | ||
886 | + \begin{aligned} | ||
887 | + &\probfact{0.7}{pj\_a},\cr | ||
888 | + &\probfact{0.01}{pj\_na},\cr | ||
889 | + j & \leftarrow a, pj\_a,\cr | ||
890 | + \neg j & \leftarrow a, \neg pj\_a.\cr | ||
891 | + \end{aligned} | ||
892 | +\end{equation*} | ||
893 | + | ||
894 | +Again, this can be simplified by writing $\probfact{0.7}{j \leftarrow a}$ and $\probfact{0.01}{j \leftarrow \neg a}$. | ||
895 | + | ||
896 | +Finally, for the probability $P(A|B \wedge E)$ we obtain | ||
897 | + | ||
898 | +\begin{equation*} | ||
899 | + \begin{aligned} | ||
900 | + &\probfact{0.95}{a\_be},\cr | ||
901 | + &\probfact{0.94}{a\_bne},\cr | ||
902 | + &\probfact{0.29}{a\_nbe},\cr | ||
903 | + &\probfact{0.001}{a\_nbne},\cr | ||
904 | + a & \leftarrow b, e, a\_be,\cr | ||
905 | + \neg a & \leftarrow b,e, \neg a\_be, \cr | ||
906 | + a & \leftarrow b,e, a\_bne,\cr | ||
907 | + \neg a & \leftarrow b,e, \neg a\_bne, \cr | ||
908 | + a & \leftarrow b,e, a\_nbe,\cr | ||
909 | + \neg a & \leftarrow b,e, \neg a\_nbe, \cr | ||
910 | + a & \leftarrow b,e, a\_nbne,\cr | ||
911 | + \neg a & \leftarrow b,e, \neg a\_nbne. \cr | ||
912 | + \end{aligned} | ||
913 | +\end{equation*} | ||
914 | + | ||
915 | +One can then proceed as in the previous subsection and analyse this example. The details of such analysis are not given here since they are analogous, albeit admittedly more cumbersome. | ||
916 | + | ||
868 | 917 | ||
869 | \section{Discussion} | 918 | \section{Discussion} |
870 | 919 | ||
@@ -906,6 +955,14 @@ Considering the probabilities given in \cref{Figure_Alarm} we obtain the followi | @@ -906,6 +955,14 @@ Considering the probabilities given in \cref{Figure_Alarm} we obtain the followi | ||
906 | % | 955 | % |
907 | % ================================================================ | 956 | % ================================================================ |
908 | % | 957 | % |
958 | + \begin{itemize} | ||
959 | + \item Changed from $\prod$ to $\sum$ to represent ``either'' instead of ``both'' since the later is not consistent with the ``only one stable model at a time'' assumption. | ||
960 | + \item \todo{The `up and down' choice in the equivalence relation and the possibility of describing any probability distribution.} | ||
961 | + \item \todo{Remark that no benchmark was done with other SOTA efforts.} | ||
962 | + \item \todo{The possibility to `import' bayesian theory and tools to this study.} | ||
963 | + \end{itemize} | ||
964 | + | ||
965 | + | ||
909 | \subsection{Dependence} | 966 | \subsection{Dependence} |
910 | \label{subsec:dependence} | 967 | \label{subsec:dependence} |
911 | 968 | ||
@@ -963,7 +1020,7 @@ Considering the probabilities given in \cref{Figure_Alarm} we obtain the followi | @@ -963,7 +1020,7 @@ Considering the probabilities given in \cref{Figure_Alarm} we obtain the followi | ||
963 | Prove the four world cases (done), support the product (done) and sum (tbd) options, with the independence assumptions. | 1020 | Prove the four world cases (done), support the product (done) and sum (tbd) options, with the independence assumptions. |
964 | \end{quotation} | 1021 | \end{quotation} |
965 | 1022 | ||
966 | - \section{Final Remarks} | 1023 | + \subsection{Future Work} |
967 | 1024 | ||
968 | \todo{develop this section.} | 1025 | \todo{develop this section.} |
969 | 1026 |