Commit 353a8086aab8f46c7610ea1a544f7078e57f479f

Authored by Francisco Coelho
1 parent 0ca70415
Exists in master

alterações feitas pelo bruno à sub-secção 4.2

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 +}
code/drafts/EventLattice.ipynb 0 → 100644
@@ -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 +}
code/drafts/__init__.py 0 → 100644
code/drafts/__pycache__/event_lattice.cpython-39.pyc 0 → 100644
No preview for this file type
code/drafts/algebra.py 0 → 100644
@@ -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))}")
code/drafts/api_01.py 0 → 100644
@@ -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
code/drafts/event_lattice.py 0 → 100644
@@ -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
code/drafts/explore_01.py 0 → 100644
@@ -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 +
code/drafts/sample.csv 0 → 100644
@@ -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
code/drafts/sample_analysis.jl 0 → 100644
@@ -0,0 +1,5 @@ @@ -0,0 +1,5 @@
  1 +using CSV
  2 +using DataFrames
  3 +
  4 +data = CSV.read("sample.csv", DataFrame)
  5 +println(describe(data, :all))
0 \ No newline at end of file 6 \ No newline at end of file
code/drafts/sampling.jl 0 → 100644
@@ -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
code/drafts/symbops.py 0 → 100644
@@ -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 +
code/drafts/teste.ipynb 0 → 100644
@@ -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 -}  
sample.csv 0 → 100644
@@ -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__ == &quot;__main__&quot;: @@ -26,13 +26,20 @@ if __name__ == &quot;__main__&quot;:
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&#39;&#39; phase, traced by equations (\ref{eq:prob.total.choice}) and (\ @@ -559,7 +564,7 @@ The ``extension&#39;&#39; 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