From 353a8086aab8f46c7610ea1a544f7078e57f479f Mon Sep 17 00:00:00 2001 From: Francisco Coelho Date: Thu, 13 Jul 2023 11:12:06 +0100 Subject: [PATCH] alterações feitas pelo bruno à sub-secção 4.2 --- code/drafts/.ipynb_checkpoints/EventLattice-checkpoint.ipynb | 113 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ code/drafts/EventLattice.ipynb | 154 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ code/drafts/__init__.py | 0 code/drafts/__pycache__/event_lattice.cpython-39.pyc | Bin 0 -> 8094 bytes code/drafts/algebra.py | 30 ++++++++++++++++++++++++++++++ code/drafts/api_01.py | 26 ++++++++++++++++++++++++++ code/drafts/event_lattice.py | 301 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ code/drafts/explore_01.py | 13 +++++++++++++ code/drafts/sample.csv | 101 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ code/drafts/sample_analysis.jl | 5 +++++ code/drafts/sampling.jl | 28 ++++++++++++++++++++++++++++ code/drafts/symbops.py | 41 +++++++++++++++++++++++++++++++++++++++++ code/drafts/teste.ipynb | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ code/python/.ipynb_checkpoints/EventLattice-checkpoint.ipynb | 113 ----------------------------------------------------------------------------------------------------------------- code/python/EventLattice.ipynb | 154 ---------------------------------------------------------------------------------------------------------------------------------------------------------- code/python/__init__.py | 0 code/python/__pycache__/event_lattice.cpython-39.pyc | Bin 8094 -> 0 bytes code/python/algebra.py | 30 ------------------------------ code/python/api_01.py | 26 -------------------------- code/python/event_lattice.py | 301 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- code/python/explore_01.py | 13 ------------- code/python/symbops.py | 41 ----------------------------------------- code/python/teste.ipynb | 116 -------------------------------------------------------------------------------------------------------------------- sample.csv | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ students/amartins/tarefas/tarefa2.py | 19 +++++++++++++------ text/paper_01/pre-paper.pdf | Bin 119082 -> 0 bytes text/paper_01/pre-paper.tex | 221 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------------------------------------------------------------- 27 files changed, 1180 insertions(+), 882 deletions(-) create mode 100644 code/drafts/.ipynb_checkpoints/EventLattice-checkpoint.ipynb create mode 100644 code/drafts/EventLattice.ipynb create mode 100644 code/drafts/__init__.py create mode 100644 code/drafts/__pycache__/event_lattice.cpython-39.pyc create mode 100644 code/drafts/algebra.py create mode 100644 code/drafts/api_01.py create mode 100644 code/drafts/event_lattice.py create mode 100644 code/drafts/explore_01.py create mode 100644 code/drafts/sample.csv create mode 100644 code/drafts/sample_analysis.jl create mode 100644 code/drafts/sampling.jl create mode 100644 code/drafts/symbops.py create mode 100644 code/drafts/teste.ipynb delete mode 100644 code/python/.ipynb_checkpoints/EventLattice-checkpoint.ipynb delete mode 100644 code/python/EventLattice.ipynb delete mode 100644 code/python/__init__.py delete mode 100644 code/python/__pycache__/event_lattice.cpython-39.pyc delete mode 100644 code/python/algebra.py delete mode 100644 code/python/api_01.py delete mode 100644 code/python/event_lattice.py delete mode 100644 code/python/explore_01.py delete mode 100644 code/python/symbops.py delete mode 100644 code/python/teste.ipynb create mode 100644 sample.csv diff --git a/code/drafts/.ipynb_checkpoints/EventLattice-checkpoint.ipynb b/code/drafts/.ipynb_checkpoints/EventLattice-checkpoint.ipynb new file mode 100644 index 0000000..829cb1d --- /dev/null +++ b/code/drafts/.ipynb_checkpoints/EventLattice-checkpoint.ipynb @@ -0,0 +1,113 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "57fc5921-9d6b-4b43-a8f6-743a03650d63", + "metadata": {}, + "outputs": [], + "source": [ + "import event_lattice as el" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "00f0eb68", + "metadata": {}, + "outputs": [], + "source": [ + "def zoom_event(event_str, lattice, lower_op=el.sum_op, upper_op=el.prod_op):\n", + " event = el.Event.from_str(event_str)\n", + " event_class = lattice.event_class(event)\n", + " propagated = lattice.propagated_value(\n", + " event, lower_op=lower_op, upper_op=upper_op)\n", + "\n", + " print(\n", + " f\"Event: {event}\\n\\tClass: {event_class} \\n\\tValue: {propagated}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cdd8c6d6", + "metadata": {}, + "outputs": [], + "source": [ + "smodels = el.Lattice.parse({\n", + " \"A\": 2,\n", + " \"ab\": 3,\n", + " \"ac\": 5\n", + "})\n", + "\n", + "lattice = el.Lattice(smodels)\n", + "\n", + "print(lattice)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2b445339", + "metadata": {}, + "outputs": [], + "source": [ + "zoom_event(\"abc\", lattice)\n", + "zoom_event(\"a\", lattice)\n", + "zoom_event(\"b\", lattice)\n", + "zoom_event(\"bc\", lattice)\n", + "zoom_event(\"ac\", lattice)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f1b85255", + "metadata": {}, + "outputs": [], + "source": [ + "from itertools import *\n", + "\n", + "lits = lattice.literals()\n", + "for len_lit in range(len(lits)+1):\n", + " events = list(\"\".join(c) for c in combinations(lits, len_lit))\n", + " for event in events:\n", + " zoom_event(event, lattice)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "07973a47", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3.9.13 ('base')", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.13" + }, + "vscode": { + "interpreter": { + "hash": "a59afa236e16843183c59a167f072b6fa0409044b3c4938e82ac98aad91bf217" + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/code/drafts/EventLattice.ipynb b/code/drafts/EventLattice.ipynb new file mode 100644 index 0000000..8cd7d9e --- /dev/null +++ b/code/drafts/EventLattice.ipynb @@ -0,0 +1,154 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 4, + "id": "57fc5921-9d6b-4b43-a8f6-743a03650d63", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The autoreload extension is already loaded. To reload it, use:\n", + " %reload_ext autoreload\n" + ] + } + ], + "source": [ + "%load_ext autoreload\n", + "%autoreload 1\n", + "%aimport event_lattice" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "00f0eb68", + "metadata": {}, + "outputs": [], + "source": [ + "def zoom_event(event_str, lattice):\n", + " event = event_lattice.Event.from_str(event_str)\n", + " event_class = lattice.event_class(event)\n", + " propagated = lattice.extended_value(\n", + " event)\n", + "\n", + " print(\n", + " f\"Event: {event}\\n\\tClass: {event_class} \\n\\tValue: {propagated}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "cdd8c6d6", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{\n", + "\t'stable_models': {\n", + "\t\t A: 2,\n", + "\t\tab: 3,\n", + "\t\tac: 5 \n", + "\t}\n", + "\t'literals': { A,B,C,a,b,c } \n", + "}\n" + ] + } + ], + "source": [ + "smodels = event_lattice.Lattice.parse({\n", + " \"A\": 2,\n", + " \"ab\": 3,\n", + " \"ac\": 5\n", + "})\n", + "\n", + "lattice = event_lattice.Lattice(smodels)\n", + "\n", + "print(lattice)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "2b445339", + "metadata": {}, + "outputs": [ + { + "ename": "TypeError", + "evalue": "__init__() missing 1 required positional argument: 'lattice'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m/tmp/ipykernel_361713/2581811254.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mzoom_event\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"abc\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlattice\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2\u001b[0m \u001b[0mzoom_event\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"a\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlattice\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0mzoom_event\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"b\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlattice\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0mzoom_event\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"bc\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlattice\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0mzoom_event\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"ac\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlattice\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/tmp/ipykernel_361713/1675915232.py\u001b[0m in \u001b[0;36mzoom_event\u001b[0;34m(event_str, lattice)\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mzoom_event\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mevent_str\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlattice\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0mevent\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mevent_lattice\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mEvent\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfrom_str\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mevent_str\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0mevent_class\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mlattice\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mevent_class\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mevent\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 4\u001b[0m propagated = lattice.extended_value(\n\u001b[1;32m 5\u001b[0m event)\n", + "\u001b[0;32m~/sci/projetos/zugzwang/code/python/event_lattice.py\u001b[0m in \u001b[0;36mevent_class\u001b[0;34m(self, event)\u001b[0m\n\u001b[1;32m 146\u001b[0m \u001b[0;34m@\u001b[0m\u001b[0mcache\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 147\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mevent_class\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mevent\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 148\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mEventsClass\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mstable_core\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mevent\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 149\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 150\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mrelated\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mu\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mv\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mTypeError\u001b[0m: __init__() missing 1 required positional argument: 'lattice'" + ] + } + ], + "source": [ + "zoom_event(\"abc\", lattice)\n", + "zoom_event(\"a\", lattice)\n", + "zoom_event(\"b\", lattice)\n", + "zoom_event(\"bc\", lattice)\n", + "zoom_event(\"ac\", lattice)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f1b85255", + "metadata": {}, + "outputs": [], + "source": [ + "from itertools import *\n", + "\n", + "lits = lattice.literals()\n", + "events = []\n", + "for len_lit in range(len(lits)+1):\n", + " events = events + list(\"\".join(c) for c in combinations(lits, len_lit))\n", + "for event in events:\n", + " zoom_event(event, lattice)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "07973a47", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.15" + }, + "vscode": { + "interpreter": { + "hash": "a59afa236e16843183c59a167f072b6fa0409044b3c4938e82ac98aad91bf217" + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/code/drafts/__init__.py b/code/drafts/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/code/drafts/__init__.py diff --git a/code/drafts/__pycache__/event_lattice.cpython-39.pyc b/code/drafts/__pycache__/event_lattice.cpython-39.pyc new file mode 100644 index 0000000..a72fa05 Binary files /dev/null and b/code/drafts/__pycache__/event_lattice.cpython-39.pyc differ diff --git a/code/drafts/algebra.py b/code/drafts/algebra.py new file mode 100644 index 0000000..2cae6bb --- /dev/null +++ b/code/drafts/algebra.py @@ -0,0 +1,30 @@ +from itertools import combinations, product + +def fmt(expr): + """Doc string""" + return ",".join(f"{x:>2}" for x in expr) + +def c(expr): + """Doc string""" + def litcomp(x): + if x == "⊤": + return "⊥" + elif x == "⊥": + return "⊤" + elif x[0] == "¬": + return x[1:] + else: + return f"¬{x}" + return [litcomp(x) for x in expr] + +def domain(symbols, unary="¬"): + """Doc string""" + atoms = list(symbols) + literals = [ + [f"{u}{a}" for u in unary] + + [a, "⊤", "⊥"] for a in atoms ] + return product(*literals) + +d = sorted(domain("abc")) +for x in d: + print(f"{fmt(x)} | {fmt(c(x))}") diff --git a/code/drafts/api_01.py b/code/drafts/api_01.py new file mode 100644 index 0000000..f119ed2 --- /dev/null +++ b/code/drafts/api_01.py @@ -0,0 +1,26 @@ +from clingo.symbol import Number +from clingo.control import Control + +class Context: + def inc(self, x): + return Number(x.number + 1) + + def seq(self, x, y): + return [x, y] + +def on_model(m): + print(m) + +ctl = Control() +ctl.add("base", [], """\ +p(@inc(10)). +q(@seq(1,2)). +""") + +ctl.ground( + [("base", [])], + context=Context()) + +s = ctl.solve(on_model=on_model) + +print(s) \ No newline at end of file diff --git a/code/drafts/event_lattice.py b/code/drafts/event_lattice.py new file mode 100644 index 0000000..899d260 --- /dev/null +++ b/code/drafts/event_lattice.py @@ -0,0 +1,301 @@ +import math +from functools import cache +from itertools import accumulate, combinations, chain, groupby +import operator + + + +def uniform_op(x): + n = len(list(x)) + return 1.0 if n == 0 else 1.0/n + + +def max_op(x): + return max(x) + + +def min_op(x): + return min(x) + + +def sum_op(x): + return sum(x) + + +def stableprod_op(x): + log_x = map(math.log, x) + return math.exp(sum(log_x)) + + +def prod_op(x): + return list(accumulate(x, func=lambda a,b: a*b))[-1] + + +class Event: + """Events. + + An event is a set of literals - atoms and negated atoms. + + The convention is that atoms are represented by lower case single letters + and a negated atom by upper case single letters. + """ + + @staticmethod + def _parse(text): + return frozenset(text) + + @staticmethod + def parse(text): + """Convert a string to an event. + + Each letter in the string represents a literal. + """ + return Event(Event._parse(text)) + + + def __init__(self, literals): + """Instantiate from a (frozen) set of literals. + For example: e = Event(frozenset("abc")).""" + self._literals = frozenset(literals) + + + def literals(self): + return self._literals + + + def __iter__(self): + return self._literals.__iter__() + + @cache + def is_consistent(self): + """True if this event is consistent.""" + return all(x.swapcase() not in self._literals for x in self._literals) + + + def co(self): + """Negation of this event. + + Negation is case based: A = not a; a = not A.""" + return Event(x.swapcase() for x in self._literals) + + def invert(self): + """Negation of this event. + + See the method "co" + """ + return self.co() + + def __repr__(self) -> str: + return ''.join(str(x) for x in sorted(self._literals)) if len(self._literals) > 0 else '0' + + def latex(self): + """LaTeX representation of this even. + + Negation is represented by overline and the empty event by + + """ + return ''.join( + (str(x) if x.islower() else f"\co{{{x.lower()}}}") \ + for x in sorted(self._literals) + ) if len(self._literals) > 0 else "\set{}" + + def __hash__(self) -> int: + return self._literals.__hash__() + + + def __eq__(self, other): + """Event equality test.""" + return self._literals.__eq__(other._literals) + + def __or__(self, other): + """Event union operation.""" + return Event(self._literals | other._literals) + + def __le__(self, other): + """Event subset test.""" + return self._literals.__le__(other._literals) + + + def __lt__(self, other): + """Event strict subset test.""" + return self._literals.__lt__(other._literals) + + + def __ne__(self, other): + """Event not-equal test.""" + return self._literals.__ne__(other._literals) + + + def __ge__(self, other): + """Event superset test.""" + return self._literals.__ge__(other._literals) + + + def __gt__(self, other): + """Event strict superset test.""" + return self._literals.__gt__(other._literals) + + +class Lattice: + + @staticmethod + def parse(d): + """Input stable models. + + The input format is a dictionary associating a stable model in string form to an weight. + + For example: + + input_dict = { + "A": 0.3, + "ab": 0.2, + "ac": 0.5 + } + smodels = Lattice.parse(input_dict) + """ + result = dict() + for k, v in d.items(): + key = Event.parse(k) + result[key] = v + return result + + + @staticmethod + def close_literals(events): + """Closed set of literals entailed by a set of events. + + Includes the literals in the set of events and any missing negation.""" + base_lits = list(accumulate(events, func=operator.or_))[-1] + lits = set() + for x in base_lits.literals(): + lits.add(x) + lits.add(x.swapcase()) + return sorted(lits) + + def __init__(self, smodels_dict): + """Create an Events lattice.""" + self._smodels = smodels_dict + self._literals = Lattice.close_literals(self._smodels.keys()) + + def literals(self): + """The literals in this lattice.""" + return self._literals + + @cache + def stable_models(self): + """The stable models that generate this lattice.""" + return self._smodels.keys() + + #@cache + def events(self): + """All the events of this lattice.""" + return chain.from_iterable(map(Event, combinations(self._literals, r)) for r in range(len(self._literals)+1)) + + @cache + def stable_core(self, event): + """The stable core of an event in this lattice.""" + return set(filter(lambda sm: sm <= event or event <= sm, self.stable_models())) + + # @cache + # def event_class(self, event): + # """The equivalence class of an event.""" + # return EventsClass(self.stable_core(event), self) + + @cache + def classes(self): + """The classes of this lattice. + + Each class is presented as a key:value pair where the "key" is the stable core of the elements in "value".""" + map_ev_classes = [(e, tuple(self.stable_core(e))) for e in self.events() if e.is_consistent()] + groups = dict() + for e,c in map_ev_classes: + if c in groups.keys(): + groups[c].add(e) + else: + groups[c] = set([e]) + inconsistent = list(e for e in self.events() if not e.is_consistent()) + inconsistent_repr = inconsistent[0] + groups[(inconsistent_repr,)] = set(inconsistent) + return groups + + + def related(self, u, v): + """Tests if two events are related.""" + u_consistent = u.is_consistent() + v_consistent = v.is_consistent() + if u_consistent and (u_consistent == v_consistent): + return self.stable_core(u) == self.stable_core(v) + else: + return u_consistent == v_consistent + + def extended_value(self, event:Event, + op=prod_op): + """TODO: well...""" + value = 0 + # + # INCONSISTENT EVENTS + # + if not event.is_consistent(): + return value + # + # CONSISTENT EVENTS + # + score = self.stable_core(event) + len_score = len(score) + # CONSISTENT, INDEPENDENT + if len_score == 0: + value = 0 + elif len_score == 1: + value = self._smodels[score[0]] + else: + value = op(map(lambda sm: self._smodels[sm], score)) + + return value + + def __repr__(self): + smodels_repr = ',\n\t\t'.join(f"{k}: {v:<}" for k,v in self._smodels.items()) + lits_repr = ','.join(sorted(self._literals)) + + return "{\n" +\ + f"\t'stable_models': {{\n\t\t {smodels_repr} \n\t}}\n" +\ + f"\t'literals': {{ {lits_repr} }} \n" +\ + "}" + +# class EventsClass: +# def __init__(self, core, lattice:Lattice): +# self._core = core +# self._lattice = lattice + +# def __repr__(self): +# core_repr = "" if len(self._core) == 0 else ",".join(str(x) for x in self._core) +# return f"<{core_repr}>" + +# def __contains__(self, event:Event): +# return self.lattice.stable_core(event) == self._core + +if __name__ == "__main__": + def zoom_event(event_str, lattice): + event = Event.parse(event_str) + event_class = lattice.event_class(event) + propagated = lattice.extended_value( + event) + + print( + f"Event: {event}\n\tClass: {event_class} \n\tValue: {propagated}") + + smodels = Lattice.parse({ + "A": 2, + "ab": 3, + "ac": 5 + }) + + lattice = Lattice(smodels) + + ev_classes = lattice.classes() + for k,g in ev_classes.items(): + print(f"{tuple(s.latex() for s in k)} {set(e.latex() for e in g)}") + # zoom_event("abc", lattice) + # zoom_event("a", lattice) + # zoom_event("b", lattice) + # zoom_event("bc", lattice) + # zoom_event("ac", lattice) \ No newline at end of file diff --git a/code/drafts/explore_01.py b/code/drafts/explore_01.py new file mode 100644 index 0000000..f894bdd --- /dev/null +++ b/code/drafts/explore_01.py @@ -0,0 +1,13 @@ +from clingo.control import Control +from clingox.program import Program, ProgramObserver, Remapping + +prg = Program() +ctl_a = Control() +ctl_a.register_observer(ProgramObserver(prg)) +print(f"<1>\n{prg}\n") + +prog = "code/asp/alarm.lp" +ctl_a.load(prog) +ctl_a.ground([('base', [])]) +print(f"<2>\n{prg}\n") + diff --git a/code/drafts/sample.csv b/code/drafts/sample.csv new file mode 100644 index 0000000..38957f9 --- /dev/null +++ b/code/drafts/sample.csv @@ -0,0 +1,101 @@ +event +b +b +b +C +λ +BC +C +λ +bC +BC +Ac +λ +λ +abC +λ +BC +abC +A +a +B +b +abc +λ +B +λ +AC +C +Ac +C +B +Bc +c +aB +Ab +λ +C +aC +λ +a +aBC +abc +Ac +λ +c +c +λ +Bc +B +bc +aB +aB +ABc +C +λ +B +λ +ac +Ac +b +Abc +b +C +a +ab +C +ab +λ +A +bc +AC +λ +C +ABc +AC +ac +BC +c +Ac +ab +ABC +A +aB +bc +λ +aB +ABc +Ac +Ac +B +aB +Ac +c +λ +λ +b +c +Ab +BC +A +BC diff --git a/code/drafts/sample_analysis.jl b/code/drafts/sample_analysis.jl new file mode 100644 index 0000000..f050a86 --- /dev/null +++ b/code/drafts/sample_analysis.jl @@ -0,0 +1,5 @@ +using CSV +using DataFrames + +data = CSV.read("sample.csv", DataFrame) +println(describe(data, :all)) \ No newline at end of file diff --git a/code/drafts/sampling.jl b/code/drafts/sampling.jl new file mode 100644 index 0000000..a9d3b85 --- /dev/null +++ b/code/drafts/sampling.jl @@ -0,0 +1,28 @@ +neg(a) = islowercase(a) ? uppercase(a) : lowercase(a) + +function sample(atoms) + result = Char[] + for a in atoms + if rand(Bool) + push!(result, rand(Bool) ? a : neg(a)) + end + end + return length(result) > 0 ? join(result) : "λ" +end + +function sample(n::Int, atoms) + result = String[] + for _ in 1:n + push!(result, sample(atoms)) + end + return result +end + +using DelimitedFiles + +abc_atoms = [ 'a', 'b', 'c'] + +open("sample.csv", "w") do io + writedlm(io, [ "event" ]) + writedlm(io, sample(100, abc_atoms), ) +end \ No newline at end of file diff --git a/code/drafts/symbops.py b/code/drafts/symbops.py new file mode 100644 index 0000000..25fd6f8 --- /dev/null +++ b/code/drafts/symbops.py @@ -0,0 +1,41 @@ +from unicodedata import numeric +from sympy import * +from sympy.plotting import plot + +def variants(expr, with_plot=False): + print(f"Expr: {latex(expr)}") + print(f"Simplify: {latex(simplify(expr))}") + print(f"Expand: {latex(expand(expr))}") + print(f"Factor: {latex(factor(expr))}") + if with_plot: + plot(expr, (d, 0, 1, 10),ylabel="$\\mathrm{P(expr \\mid \\alpha = 0.3)}$") + +init_printing(use_unicode=True) + +a, d = symbols('a d') +A = 1 - a +D = 1 - d + +wab = a * d +wac = a * D +wA = A + +wabc = wab * wac +wAb = wA +wa = wab + wac +wb = wab +wc = wac +wE = wab + wab + wA + +z = wabc + 9 * wA + wab + wac + wa + wb +wc + wE +pabc = wabc/z + +z_03 = z.subs(a, 0.3) +wabc_03 = wabc.subs(a, 0.3) +pabc_03 = pabc.subs(a, 0.3) + +variants(z_03) +variants(wabc_03) +variants(pabc_03) +print(solve(wabc_03 - 0.0015 * z_03, d)) + diff --git a/code/drafts/teste.ipynb b/code/drafts/teste.ipynb new file mode 100644 index 0000000..c62a6aa --- /dev/null +++ b/code/drafts/teste.ipynb @@ -0,0 +1,116 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "4" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "2+2" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "import matplotlib.pyplot as plt\n", + "import numpy as np" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "x = np.linspace(-6, 6)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "y = np.sin(x)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjgAAAGdCAYAAAAfTAk2AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/NK7nSAAAACXBIWXMAAA9hAAAPYQGoP6dpAABn+klEQVR4nO3deXyU5dU//s/s2Scb2SAJCQQChCUkEAiiIBi07lWBalPtV2l5XJH6aKm2oo+Vn7WttrZabbVYF6SKVKyIBJVFCUtCwk5YQ/Y9mck66/37Y+YeCAnZyMw9y+f9es0fDHcmZwIzOXNd5zpHJgiCACIiIiIvIpc6ACIiIqLhxgSHiIiIvA4THCIiIvI6THCIiIjI6zDBISIiIq/DBIeIiIi8DhMcIiIi8jpMcIiIiMjrKKUOQApWqxVVVVUIDg6GTCaTOhwiIiIaAEEQ0Nrairi4OMjlfa/R+GSCU1VVhfj4eKnDICIioiEoLy/HqFGj+rzGJxOc4OBgALYfUEhIiMTREBER0UDo9XrEx8c7fo/3xScTHHFbKiQkhAkOERGRhxlIeQmLjImIiMjrMMEhIiIir8MEh4iIiLwOExwiIiLyOkxwiIiIyOswwSEiIiKvwwSHiIiIvA4THCIiIvI6THCIiIjI6zg1wdm5cyduvvlmxMXFQSaT4T//+U+/X7Njxw5kZGTAz88PycnJ+Nvf/tbjmg0bNmDixInQaDSYOHEiNm7c6IToiYiIyFM5NcFpb2/H1KlT8Ze//GVA1587dw4/+MEPMHfuXBQVFeFXv/oVHn30UWzYsMFxTX5+PpYsWYLc3FwcPHgQubm5WLx4Mfbu3eusp0FEREQeRiYIguCSbySTYePGjbjtttsue81TTz2FTZs24fjx4477li9fjoMHDyI/Px8AsGTJEuj1enz55ZeOa66//nqEhYVh3bp1A4pFr9dDq9VCp9NxFhUREZGHGMzvb7eqwcnPz0dOTk63+xYtWoSCggKYTKY+r9m9e/dlH9dgMECv13e7UXfnG9tR2tAOF+W7RDQMjGYrNhZV4K2dZ9BhNEsdDpFbcatp4jU1NYiOju52X3R0NMxmMxoaGhAbG3vZa2pqai77uGvWrMFzzz3nlJg9nSAI+Ff+eTz/32OwWAXEaf0wZ2wkrkqJRPaYSIwI1kgdIhFdQtdhwof7yrB29znU6g0AgPf2nMdvb5uMq8eNkDg6IvfgVgkO0HMEuriicPH9vV3T1+j0VatWYeXKlY4/6/V6xMfHD0e4Hs1otuLZTUexbl8ZAEAhl6FK14WPCyvwcWEFAGB8dLA94YnAzKQIBGnc7r8Mkc8ob+rAO9+fw/r95egwWgAAUcEaKOQylDd14ifv7MMP00fimZsmIjxQLXG0RNJyq99WMTExPVZi6urqoFQqERER0ec1l67qXEyj0UCj4UrExRrbDPifDw5g37kmyGTAqhtSkTtrNPaXNuH70w347nQDjlXrUVLbipLaVrzz/Tko5TJcmxqFV5dOQ4Darf7rEHm14vIW/H3XWXx5uBpW+y5yakwwHpibjFumxsFoseL3X5Xg3fxSfFpUie0n6/Gbmybi1mlxfX74I/JmbvVbavbs2fj888+73bd161ZkZmZCpVI5rsnLy8Pjjz/e7Zrs7GyXxurJjlfr8cC7Bahs6USwRok//ygd81OjAABXjxvhWOJuajci/0wjvjvdgO9PN6CsqQNbj9Xi1/85ij8snirlUyDyCd+fbsCftp3CvtImx31zUyKxbG4y5qZEOpIXtVKO1bdMwi3T4rBqw2GU1LZixfpifFpUid/elob48ACpngKRZJx6iqqtrQ2nT58GAKSnp+OPf/wj5s+fj/DwcCQkJGDVqlWorKzEv/71LwC2Y+JpaWn4+c9/jmXLliE/Px/Lly/HunXrcMcddwAAdu/ejauvvhq//e1vceutt+Kzzz7DM888g++++w5ZWVkDisuXT1FtOVKDlf8uRofRgtERAfjHvZkYGxU8oK/ddaoe976zD1YBePnOKbgrk9t8RM5yoKwZd76xG1YBUClkuGXqSDwwNwkTYvt+zzKarXhzxxm89s1pGC1W+KsU+EXOOPx0ThIUcq7mkGcbzO9vpyY427dvx/z583vcf++992Lt2rW47777UFpaiu3btzv+bseOHXj88cdx9OhRxMXF4amnnsLy5cu7ff0nn3yCZ555BmfPnsWYMWPw29/+Fj/84Q8HHJcvJjiCIOAv35zGH/JOAgCuGhuJv9ydjtCAwe3Tv/b1Kfwh7yT8VQpsengOUqIHlhwR0cB1mSy48c+7cKa+HQsnROGF2yYjRus3qMc4U9+GVZ8exr5zttWfKaO0+Me9mYgKHtzjELkTt0lw3JWvJTidRgue+OQgvjhUDQC4L3s0nrlxApSKwXcJsFgF3PvOPnx3ugEpUUH47OE5rMchGmYvbTmBN7afQWSQBttWXj3oDyIiq1XA+oJyvLj5OFq7zLhxciz+es/0YY6WyHU8tg8ODT9dhwl3vbkbXxyqhlIuw5ofTsbqWyYNKbkBbCetXlkyDSOCNThV14ZnPzs6zBET+bZDFS14a+dZAMALt6UNObkBALlchh/NTMBHP5sFuQz44nA1vj/dMFyhErk1Jjhe7tWvT+JIpR7hgWp88EAWfjQz4Yofc0SwBn9aOg1yGfBxYQU22I+UE9GVMZgt+N+PD8FiFXDz1DhcnxYzLI87KU6LH89KBACs3nQUJot1WB6XyJ0xwfFi5U0deH/PeQDAn5ZOQ1ZyxLA9dvaYSDy2YBwA4Jn/HMHputZhe2wiX/XXb06jpLYVEYFqPHfLpGF97JXXjUN4oBqn6trw7u7SYX1sInfEBMeL/THvJEwWAVeNjcTclOHvbvrwtWMxZ2wEOk0WPPRBETrtjceIaPCOVunw+vYzAIDnb00b9kZ9oQFqPLloPADgT9tOoa61a1gfn8jdMMHxUkerdPhPcSUA4KnrU53yPRRyGV5dko7IIA1KaluxehPrcYiGwmSx4n8/PgSzVcANaTG4cUqsU77P4sx4TBmlRavBjJe+LHHK9yByF0xwvNTvtpRAEICbp8Zh8iit077PiGAN/rx0GmQyYH1BOTYWsR6HaLDe2H4Gx6r1CAtQ4flb05z2feRymWPra8OBChSeb3ba9yKSGhMcL7T7TAN2nKyHUi7DL64b5/Tvlz02Eo9emwIAeHrjEZyua3P69yTyFidq9Hjtm1MAgNW3THL6gNv0hDDclTEKAPDspiOwWH2uUwj5CCY4XkYQBLy0xbb0fHdWAkZHBrrk+z66IAWzkyPQYbTg4Q8PoMvEehyi/pjtW1Mmi4CFE6Jxy9Q4l3zfJ69PRbCfEkcq9Vi/v9wl35PI1ZjgeJktR2pwsLwFAWoFHrGvqriCQi7Dn340DZFBGpyoaXWc3iKiy3tz51kcrtQhxE+JF29Pc9lgzBHBGjy+0La6+/JXJ9DSYXTJ9yVyJSY4XsRsseLlr2yrNw/MTXb6UvelooL98Ph1tqTqX/nnufRN1IdTta340zbb1tRvbp6EqBDXjlD4yexEjI8ORnOHCX/YetKl35vIFZjgeJF/F1TgbEM7wgPVWDY3SZIYbk8fiRA/JcqaOrC9pE6SGIjcncUq4H8/OQSjxYp540fgjukjXR6DUmGbQA4AH+w9j6NVOpfHQORMTHC8RKfRgle32T6FPXLtWAT7qSSJI0CtxFJ7t+S1bCZG1KvNh6tRXN6CYI0Sa3442WVbU5eaPSYCN02JhVUAnv3sKHxwNCF5MSY4XuKd78+hrtWA+HB/3J115eMYrkTurETIZcCuUw04VcsOx0SX+mCvrUbtp1clIVbrL2ksT984Af4qBQrONzt6ZxF5AyY4XqC53Yi/2Tug/uK68dAoFZLGEx8egIUTogEA7+aXShoLkbs5U9+GPWebIJcBS2fESx0OYrX+ePjasQCANZtPoM1gljgiouHBBMcLvL79NFoNZkyIDXHZMdP+3DdnNABgQ2EldJ0maYMhciPr9pYBAOaPj0JcqLSrN6IH5iZhdEQA6loNeGvHGanDIRoWTHA8XEVzB97dbVvufur68ZDLpdnLv9Ts5AiMjw5Gp8mCjwvYZ4MIALpMFnxywNbtW+qt5ItplAr87yLbSJeP9pfDzGnj5AWY4Hi4V/JOwWixYnZyBK4ZN/wDNYdKJpM5VnHezS/lkXEi2PpUtXSYEKf1w7zxUVKH0811E6MRHqhGXasBu041SB0O0RVjguPBSmpa8al99tNTN6RKdhLjcm6bNhJafxXKmzrxzQkeGSf60L49tWRGAhRustoqUivluHWabYv740KuupLnY4Ljwd7+7iwEAbghLQbT4kOlDqcHf7UCS2faiijX7j4ncTRE0jpd14p9pU1QyGVY4gbFxb25K8MW17ZjdWhuZ3dj8mxMcDxUl8mCLw/XAAB+Okeapn4DIR4Z//50I07yyDj5sA/32lZFrk2NQozWtV2LB2piXAgmxYXAaLHiMx4ZJw/HBMdDfX28Dq0GM0aG+iMzMUzqcC5rVFgAcibGAGDjP/JdXSYLNrhhcXFvxEnjHxdWSBwJ0ZVhguOhNhbZPl3dlh7nNienLkcsNv70QAV0HTwyTr5n8+Fq6DpNGBnqj6tT3OcwQG9unTYSaoUcR6v0OFallzocoiFjguOBmtqNjjlPt01z/QybwcpKCkdqTDC6TFasLyiTOhwilxOLi5fOiHe74uJLhQWqsXCi7YQXi43JkzHB8UBfHK6G2SpgUlwIUqKDpQ6nXzKZDD8Vj4zv5pRx8i0na1tRcL4ZCrkMi920uPhSYrHxZ8VVMJrZE4c8ExMcD/Qf+/bU7enuv3ojunXaSIQGqFDZ0oltx2ulDofIZcTVm4UTohAd4p7FxZeamxKJqGANmtqN+OYEX6/kmZjgeJiyxg4Unm+GXAbc7CZjGQbCT6XA0hn2KePfl0obDJGLdBovLi5OlDiagVMq5PjhdHuxcQGLjckzMcHxMOLRzTljIz3m06Aod7btyHj+2UaU1PDIOHm//x6qQmuXGfHh/pg7NlLqcAblrkxbgrP9ZD3qWrskjoZo8JjgeBBBELDRnuB4QnHxpUaG+mPRJB4ZJ9/x4T6xuDjB7U87XmrMiCBMTwiFxSpg4wH2xCHPwwTHgxyu1OFsfTv8VHIsSouROpwhuS97NABgY1EFWjrYKZW81/FqPYrKWqCUyxyrIZ7mrkxbsfHHhRUQBB4OIM/CBMeDiL1vrpsYgyCNUuJohmZmUjgmxIagy2Tl3j55NbG4OGdSNKKCPWs7WXTTlFj4qeQ4XdeG4vIWqcMhGhQmOB7CbLHi84PVAIDb0z2nuPhSMpkMd9vnU31xuFriaIico8Nodpx2vHum5xQXXyrYT4Ub0mIBsLMxeR6XJDivv/46kpKS4Ofnh4yMDOzateuy1953332QyWQ9bpMmTXJcs3bt2l6v6ery3kK47880oqHNgPBANea6eSfU/uTY63CKy1tQq/fefzPyXZ8frEKrwYzEiABkj4mQOpwrIo5u+PxgFbpMFomjIRo4pyc469evx4oVK/D000+jqKgIc+fOxQ033ICyst472v7pT39CdXW141ZeXo7w8HDcdddd3a4LCQnpdl11dTX8/DxzGXggxE+DN0+JhUrh2Qtv0SF+SE8IBQBsPcYeG+R9xO2pH830vOLiS81KjsCoMH+0dpnx1dEaqcMhGjCn/6b84x//iPvvvx8PPPAAJkyYgFdffRXx8fF44403er1eq9UiJibGcSsoKEBzczN++tOfdrtOJpN1uy4mxjOLbgei3WDGliO2N5ZbPai5X1/EAZxb+YZJXuZIpQ4HK3RQKWS4M8Mzi4svJpfLcAd74pAHcmqCYzQaUVhYiJycnG735+TkYPfu3QN6jLfffhsLFy5EYmL3fey2tjYkJiZi1KhRuOmmm1BUVHTZxzAYDNDr9d1uniTvWC06TRYkRgQgPT5U6nCGxaJJ0QCA/DON0HVyACd5D3G1NWdSDCKDNBJHMzzERO37Mw2obOmUOBqigXFqgtPQ0ACLxYLo6Ohu90dHR6Ompv9P7tXV1fjyyy/xwAMPdLs/NTUVa9euxaZNm7Bu3Tr4+flhzpw5OHXqVK+Ps2bNGmi1WsctPt4z5sGI/nNR7xuZzLOXu0XJI4IwNioIZqvgGBxK5OkEQXCMIrlpcqzE0Qyf+PAAzE6OgCAAG1hsTB7CJcUcl/5SFgRhQL+o165di9DQUNx2223d7p81axZ+/OMfY+rUqZg7dy7+/e9/Y9y4cXjttdd6fZxVq1ZBp9M5buXlnjMht77VgF2nGgAAt3nJ9pRIXMXhvj55izP17Sht7IBaIcfccZ59GOBSYi+fTworYOXAXPIATk1wIiMjoVAoeqzW1NXV9VjVuZQgCHjnnXeQm5sLtVrd57VyuRwzZsy47AqORqNBSEhIt5un+O+hKlisAqbGhyIpMlDqcIaVWIezvaSepzPIK3xtX72ZNSbCY3tVXc4NabEI0ihR1tSBfaVNUodD1C+nJjhqtRoZGRnIy8vrdn9eXh6ys7P7/NodO3bg9OnTuP/++/v9PoIgoLi4GLGx3rMkLHJMDp/mub1vLmfKKC1iQvzQYbTg+9MNUodDdMXE7amFE6IkjmT4+asVuGmKvScOi43JAzh9i2rlypX4xz/+gXfeeQfHjx/H448/jrKyMixfvhyAbfvoJz/5SY+ve/vtt5GVlYW0tLQef/fcc8/hq6++wtmzZ1FcXIz7778fxcXFjsf0Fmfr23CwQgeFXIabPGhy+EDJZDLk2Lepth7lcXHybM3tRhSebwYAXJvqfQkOAMeE8bxjNTBbrBJHQ9Q3p6+hLlmyBI2NjXj++edRXV2NtLQ0bN682XEqqrq6ukdPHJ1Ohw0bNuBPf/pTr4/Z0tKCn/3sZ6ipqYFWq0V6ejp27tyJmTNnOvvpuNR/iqsAAFenRHrNaYxLLZoUg3/ln8e247WwWAUoPLxnCPmub0vqYBWACbEhGBUWIHU4TpGRGIbQABVaOkwoKm/BjNHhUodEdFku2SR+8MEH8eCDD/b6d2vXru1xn1arRUdHx2Uf75VXXsErr7wyXOG5JUEQHNtT3lZcfLGZSeHQ+qvQaP/0OzOJb5jkmbx5e0qkkMtwzbgR+Ky4Ct+cqGOCQ27Ns1vierEDZS0oa+pAgFqB6yb2XZDtyVQKORbYl/PZ9I88lcFswc6TtjqyBRO89/UKXNh++/YE2zuQe2OC46bE1ZvrJ8UgQO1dpzEuJdbhfHWsBoLA46fkefaebUKbwYwRwRpMGamVOhynujplBOQy4ERNK6rY9I/cGBMcN3Rxs7CbvbC4+FJXjxsBjVKO8qZOnKhplTocokETj4cvSI3y+NlT/QkLVCM9IQyAre6IyF0xwXFDp+raUK3rgkYpx2wPn0Q8EAFqpWNCOpv+kaexfSCx/aL39u0p0fzxttfrtyfqJY6E6PKY4LghcXTB7DER8FMpJI7GNRbxuDh5qBM1rahs6YRGKcdVYyOlDscl5tvrcL4/3cAmneS2mOC4oR0nbZ+KrvGyVu99WTAhGnIZcKxaj/Kmy5+gI3I34vbUVWMj4a/2jQ8kE2NDEB2iQafJgn3n2NWY3BMTHDfTbjBj/zlbszBfSnDCA9WOI+Jbj3EVhzyHuD210ItPO15KJpNh/njbKs43PE1FbooJjpvZc7YRRosV8eH+Xjd7qj/ibCrW4ZCnqGvtQnF5CwA42h34CnGb6tuSOp5+JLfEBMfNXLw9NZCJ695EPC5eUNqExjaDxNEQ9U/sBTNllBZRIX4SR+Nac8ZGQqWQ4XxjB841tEsdDlEPTHDczIUEx7c+DQLAqLAATIoLgVUAvj7OZW9yf47tKR85PXWxII0SWUm2U57cpiJ3xATHjZQ2tON8YwdUCplPHA/vzaJJtm2qrce4TUXurctkwa5Ttg8kC7x4PENf5tmPi28v4XFxcj9McNyIuHqTmRiOII13dy++HHGbauepBrQbzBJHQ3R5u880oMtkRZzWDxNjQ6QORxLi2Ia95xrRxtcruRkmOG5E7H8jfiryReOjg5EQHgCj2YqdJ/mpkNxX3rELzf18rV5OlBQZiMSIAJgsAr4/3SB1OETdMMFxE10mC/LPNgIArvHhBEcmkzma/vE0FbkrQRDwzQn7eAYf3Z4Cuh8X5/BNcjdMcNzE/tImdJmsiA7RYHx0sNThSCrHXofz9Yk6mCxWiaMh6ulIpR61egMC1ArMSvbNejnRtTwuTm6KCY6b2FHiu8fDLzU9IQyRQWq0dpmxx76qReRO8uzdi69OGeEz41QuZ2ZSOPxVCtTqDThWrZc6HCIHJjhuwpePh19KIZc5jt1ym4rckWN6uA9vT4n8VArMsc/g4jYVuRMmOG6gsqUTp+raIJfBZ4b19ec6e9v7HSw0JjdTrevE0So9ZLIL2zO+bn6qfbo4j4uTG2GC4wbE00LpCWHQBqgkjsY9ZCVHQCmXobypk8M3ya2Izf2mJ4QhIkgjcTTuQSw0LiprRnO7UeJoiGyY4LgB8Xi4Lw3X7E+QRomp8aEAbP1GiNwFt6d6igv1R2pMMKwCsPMUV3HIPTDBkZjJYsX3p22FtL7c/6Y32fZuzrvPsNCY3EO7wez4/3idD45n6Is4fJNjG8hdMMGR2IHzzWgzmBEeqEZanFbqcNxK9hhbPdLuM408fkpuYdepBhjNViSEB2BsVJDU4bgVsR5px8l6WKx8vZL0mOBITCyivTolEnK5bx8Pv9T0xFBolHLUtxpwuq5N6nCIujX38/V2DpdKjw+F1l+Flg4TisubpQ6HiAmO1BzHw7k91YNGqcCM0eEAwDbwJDlBEC7aTmb9zaWUCjmuttcRcpuK3AETHAnVtXbhaJWtMdbcFCY4vckea6vD+Z51OCSx8qZOVLZ0QqWQYcboMKnDcUvz7R/Uvj3BQmOSHhMcCe06aVuVmDxSi0geN+2VWIez52wj9/VJUvlnba/XqaNCEaBWShyNe7J1YgeOVetRo+uSOhzycUxwJHShezFXby4nLS4EwX5KtHaZcaRSJ3U45MPy7auIs8f49uypvkQEaTB1VCiAC+0viKTCBEciFqvg6BfB+pvLUyrkyEricXGSliAIyLfPRZvt48M1+3Mtj4uTm2CCI5FDFS1o6TAh2E+JdHtDO+rdnLFigsNCY5LGuYZ21OoNUCvkmJ7I+pu+iF2NvzttO1JPJBUmOBIRt6fmpkRCqeA/Q1/EQX77S5tgMFskjoZ8kbh6k54Q6vPTw/szKS4EYQEqdBgtOMxtZZIQf7NKhPU3A5cSFYTIIA26TFYUlbVIHQ75INbfDJxcLnNsK+85y21lko5LEpzXX38dSUlJ8PPzQ0ZGBnbt2nXZa7dv3w6ZTNbjduLEiW7XbdiwARMnToRGo8HEiROxceNGZz+NYdPcbsTB8hYAcPSNoMuTyWQXxjawHw65mCAI2HO2CQDrbwZqVrKtf9Xec00SR0K+zOkJzvr167FixQo8/fTTKCoqwty5c3HDDTegrKysz68rKSlBdXW145aSkuL4u/z8fCxZsgS5ubk4ePAgcnNzsXjxYuzdu9fZT2dYfHe6AVYBGB8djFitv9TheATOpSKpnK5rQ0ObARqlHNMSQqUOxyNk2RPBgtImmCyswyFpOD3B+eMf/4j7778fDzzwACZMmIBXX30V8fHxeOONN/r8uqioKMTExDhuCsWFfe9XX30V1113HVatWoXU1FSsWrUKCxYswKuvvurkZzM82L148MQ6nOLyFrQbzBJHQ75ErL/JHB0GjZL1NwMxPjoYoazDIYk5NcExGo0oLCxETk5Ot/tzcnKwe/fuPr82PT0dsbGxWLBgAb799ttuf5efn9/jMRctWnTZxzQYDNDr9d1uUhEEATtZfzNo8eEBiA/3h9kqYF8pl73JdRz1N9yeGjC5XIaZ9jEre8/y9UrScGqC09DQAIvFgujo6G73R0dHo6ampteviY2NxVtvvYUNGzbg008/xfjx47FgwQLs3LnTcU1NTc2gHnPNmjXQarWOW3x8/BU+s6E729COulYD1Eo5MnjcdFCyk+3TxVmHQy5itQqOQlkWGA/OrGQWGpO0XNJv/NKpu4IgXHYS7/jx4zF+/HjHn2fPno3y8nL8/ve/x9VXXz2kx1y1ahVWrlzp+LNer5csydlnL7pLj+dx08HKHhuB9QXlrMMhlympbUVzhwkBagWm2Dv00sDMuqgOx2yxsh0GuZxT/8dFRkZCoVD0WFmpq6vrsQLTl1mzZuHUqVOOP8fExAzqMTUaDUJCQrrdpCImOFlJ4ZLF4KnET9DHqvVobjdKHA35AnF7KnN0OFT8BT0oqTHB0Pqr0G604EiVdGUB5Luc+opVq9XIyMhAXl5et/vz8vKQnZ094McpKipCbGys48+zZ8/u8Zhbt24d1GNKQRAE7LUv185M4nL3YEUF+2FcdBAE4ULhJ5EzcTzD0MnlMsy0f5DjNhVJwelbVCtXrkRubi4yMzMxe/ZsvPXWWygrK8Py5csB2LaPKisr8a9//QuA7YTU6NGjMWnSJBiNRrz//vvYsGEDNmzY4HjMxx57DFdffTVeeukl3Hrrrfjss8+wbds2fPfdd85+OlekorkTVbouKOUyTE8MlTocj5Q9JhIna9uw+0wDfjA5tv8vIBoii/XCBxLW3wzNrOQI5B2rxZ6zjVh+zRipwyEf4/QEZ8mSJWhsbMTzzz+P6upqpKWlYfPmzUhMTAQAVFdXd+uJYzQa8cQTT6CyshL+/v6YNGkSvvjiC/zgBz9wXJOdnY2PPvoIzzzzDH79619jzJgxWL9+PbKyspz9dK6I2PRq8igtAtQuKX/yOtljIrB2dyl2n+YnQnKu49V66LvMCNIokRYn3ba2JxO34gtKm1mHQy7nkt+yDz74IB588MFe/27t2rXd/vzkk0/iySef7Pcx77zzTtx5553DEZ7L7Dtn+6Wcxe2pIctKjoBcZjuNVq3rZKNEchpxuOvMpHD+Yh6iCbEhCPFTQt9lxtEqPaZysDC5EF+1LrSXBcZXTOuvwuSRWgDgKg45FfvfXDmFXOaoN2QdDrkaExwXqdF14XxjB+QyIGM0+99ciWx7V+Pvz7AfDjmH2WLF/tJmAKy/uVKcS0VSYYLjInvt21MT40IQ4qeSOBrPJs6lyj/TCEEQJI6GvNHhSh3aDGaE+CkxIZb1N1dC7Iez/5ytHw6RqzDBcZEL/W/4afBKZSaGQ62Qo1rXhXMN7VKHQ15IPB6elRwBhbz3BqI0MBNiQxDsp0SrwYxj1eyHQ67DBMdFxOXZmay/uWL+agXS7VOd2dWYnIH1N8NHwblUJBEmOC7Q0GbA6bo2AHC80OnKiNPFd7MOh4aZ0WxFAetvhhXnUpEUmOC4QIF9+vX46GCEBaoljsY7zBl7oQ7HamUdDg2fQxUt6DRZEBagwvjoYKnD8QpigrPvXBMsfL2SizDBcYE99mXZrGSu3gyXKaNCEahWoLnDhOM13Nen4SNuT81KjoCc9TfDYmJcCII1tjqc46zDIRdhguMC+1h/M+xUCrnj58l+ODSc8jmeYdgp5DLM4FwqcjEmOE6mu2iFgQnO8MoewzocGl4GswWF5+31NywwHlZiPxwmOOQqTHCcrOB8EwQBSI4MRFSwn9TheJXssRf29dlfg4ZDUVkLDGYrIoM0GBsVJHU4XkVskcE6HHIVJjhOxuPhzpMaY+uv0W604ERNq9ThkBe4UH8TDpmM9TfDaVJcCII0trlUrMMhV2CC42SO+VMsMB52CrkMGYm2sRf7S9lfg64c62+cR6mQY4Z9TA23qcgVmOA4UZvBjCOVOgBwDJyj4TXD3ldI7FtCNFRdJguKy1oAsP7GWbLsP1fOpSJXYILjRAfON8NiFTAqzB8jQ/2lDscrZV60gsO5VHQlCs83w2ixIjpEg6TIQKnD8UoX98Nh/ypyNiY4TiQO2GT9jfNMjQ+FSiFDXasB5U2dUodDHuzi8Qysv3GOtLgQBKoV0HWyfxU5HxMcJxL738zi9pTT+KkUSBupBWA7sUY0VKy/cT6lQo5MzqUiF2GC4yRdJgsOlov1N1zBcSaxDmc/63BoiLpMFhyqaAFwYRuFnINzqchVmOA4SVFZi2M/PzEiQOpwvJpYh1PAk1Q0RAfLW2CyCBgRrEFCOF+vziQ2/NvLOhxyMiY4TnJhPAP3851NPCp+qq4Nze1GiaMhT1Rg716cmRjG16uTpY3UIsBeh8P+VeRMTHCchAXGrhMRpMGYEbZTL2KbfaLBEP/fiMkyOY/q4jqcc9ymIudhguMERrMVB8psb5izmOC4hKMOh4XGNEhWq+BIcMRfvORcnEtFrsAExwkOV7agy2RFeKCa82xcJMNRh8MVHBqcM/Vt0HWa4KeSY1JciNTh+ARxLhXrcMiZmOA4gWP+1GjOs3EVcQXncIUOXSaLxNGQJxHrb6aOCoVKwbdEV5gySgt/lQItHSacrGMdDjkHX81OIPZ3YP2N6yRGBCAySAOjxYrD9vEYRAMhrvrN4PaUy6gUckxPDAXAVVdyHiY4w8xssTr28zlg03VkMpljkB8Hb9JgiA0iM0azwNiVMhJt7488GEDOwgRnmB2r1qPNYEawnxKpMdzPd6VMDt6kQapvNeB8YwdkMmB6AhMcVxLr5pjgkLMwwRlm+y6qv1HIWX/jSuIKTkEpCxdpYArtqzfjooKh9VdJHI1vSU8IhUwGlDV1oK61S+pwyAsxwRlme1h/I5mJsSEIUCug7zLjVF2b1OGQBxBX+7g95XohfiqMjw4GABzgKg45AROcYWS1Co76jyzOs3E5pUKOafGhADh4kwbm4g7G5Hps70DOxARnGJ2sa4Wu04QAtYL9NCTCOhwaqC6TBUerbCfueIJKGpnitjJXcMgJXJLgvP7660hKSoKfnx8yMjKwa9euy1776aef4rrrrsOIESMQEhKC2bNn46uvvup2zdq1ayGTyXrcurqk3ccN8VPhsQUpyJ2VyH4aEuFJKhooccBmVLAGo8L8pQ7HJ2Uk2BLLo1XsX0XDz+m/hdevX48VK1bg6aefRlFREebOnYsbbrgBZWVlvV6/c+dOXHfdddi8eTMKCwsxf/583HzzzSgqKup2XUhICKqrq7vd/Pz8nP10+hQX6o/HrxuHVT+YIGkcviw9IQxyGVDR3IlqXafU4ZAbc2xPjeaATanEh/tjRLAGJouAQxXsX0XDy+kJzh//+Efcf//9eOCBBzBhwgS8+uqriI+PxxtvvNHr9a+++iqefPJJzJgxAykpKXjxxReRkpKCzz//vNt1MpkMMTEx3W5EQRolJtq3B7lNRX0psK/yif1YyPVkMhkyEnhcnJzDqQmO0WhEYWEhcnJyut2fk5OD3bt3D+gxrFYrWltbER7e/U2ora0NiYmJGDVqFG666aYeKzwXMxgM0Ov13W7kvTITxTocblNR77oN2GSBsaTEOpxCHgygYebUBKehoQEWiwXR0dHd7o+OjkZNTc2AHuMPf/gD2tvbsXjxYsd9qampWLt2LTZt2oR169bBz88Pc+bMwalTp3p9jDVr1kCr1Tpu8fHxQ39S5PZYuEj9OV3fBn2XGf4qhWPFj6RxccM/QWD/Kho+LqmEvXR/WxCEAe15r1u3DqtXr8b69esRFRXluH/WrFn48Y9/jKlTp2Lu3Ln497//jXHjxuG1117r9XFWrVoFnU7nuJWXl1/ZEyK3Jq7gHK/Wo7XLJHE05I7E7cup8VoeCJDYpDgtNEo5mjtMONvQLnU45EWc+sqOjIyEQqHosVpTV1fXY1XnUuvXr8f999+Pf//731i4cGGf18rlcsyYMeOyKzgajQYhISHdbuS9YrR+iA/3h1UAispapA6H3JDYJ4nHw6WnVsoxdVQoAKCQdXM0jJya4KjVamRkZCAvL6/b/Xl5ecjOzr7s161btw733XcfPvzwQ9x44439fh9BEFBcXIzY2Ngrjpm8wwzW4VAfxPqbDNbfuIXpnEtFTqB09jdYuXIlcnNzkZmZidmzZ+Ott95CWVkZli9fDsC2fVRZWYl//etfAGzJzU9+8hP86U9/wqxZsxyrP/7+/tBqtQCA5557DrNmzUJKSgr0ej3+/Oc/o7i4GH/961+d/XTIQ2SODsenRZXYz0+EdIm61q4LAzaZ4LgFsdCbHchpODk9wVmyZAkaGxvx/PPPo7q6Gmlpadi8eTMSExMBANXV1d164rz55pswm8146KGH8NBDDznuv/fee7F27VoAQEtLC372s5+hpqYGWq0W6enp2LlzJ2bOnOnsp0MeQmz4V1TeDJPFyjoLchC3QcZHByPEjwM23YGYaJ6pb0dzuxFhgWqJIyJvIBN8sGxdr9dDq9VCp9OxHsdLWa0Cpr+Qh5YOE/7z0BzHjCqi//vvMbz93Tnck5WA394+WepwyO7aP2zH2fp2vH1vJhZM6LtGk3zXYH5/82MteSW5/EIDMdbh0MUu7mBM7uPCNhW3lWl4MMEhr8XBm3SpTqMFRyttIwEy2cHYrWSw0JiGGRMc8lozRl8oXPTBnVjqxcGKFpitAqJDOGDT3YgjMw6Wt8BotkocDXkDJjjktSaP0kKtlKOhzYjSxg6pwyE3cGE8QzgHbLqZ5MhAhAaoYDBbcaya43ToyjHBIa+lUSowdZSttcB+1uEQLh6wyfobd8O6ORpuTHDIq12ow+Ebpq/rNmCTBcZuKcP+73KgjHU4dOWY4JBX48kMEp2quzBgc0Is20O4owsrOBy8SVeOCQ55NXEr4mx9OxraDBJHQ1ISu+SmJ4Sy8aObmhofCqVchrpWAyqaO6UOhzwcX+Xk1UID1EiJCgLAwZu+TuxgnMn6G7flp1Jg0khb3RyPi9OVYoJDXo/9NQi4sE2ZwQnibo1zqWi4MMEhrzc9gYWLvq6utQtlTbYBm+kJoVKHQ33IdHwgaZE2EPJ4THDI64mD/A5VtMBkYQMxX8QBm55DXHEtqdGjtcskcTTkyZjgkNdLjgyE1l+FLpMVx9lAzCdx/pTniArxQ3y4P6wCUFzeInU45MGY4JDXk8tljm0J1uH4JrEPEudPeYaLj4sTDRUTHPIJGY46nBZpAyGX6zRacLTKtnLHFRzPIBaC8wMJXQkmOOQTxDqcA3zD9DmHLhqwOTKUAzY9gVhoXFTWDIuVDf9oaJjgkE+YGh8KuQyobOlErb5L6nDIhQrtp+cyEsM4YNNDjIsORrBGiXajBSdqWDdHQ8MEh3xCkEaJ8TG29vxcxfEtB+zHjcV2AeT+FHIZptnr5vh6paFigkM+IyMxFAD39X2JIAiO/kfT2cHYo2RwjhxdISY45DPY8M/3nG/sQFO7EWqFHJPiOGDTk4gn3niSioaKCQ75DPET4ZFKPQxmi8TRkCuIyWzayBBolAqJo6HBmJZwoW6uRse6ORo8JjjkMxLCAxARqIbRYsWRShYu+gJxOzKD21MeJ0ijRKq9bo7byjQUTHDIZ8hkMqQn8Li4LxH7HrHA2DOJiSm3lWkomOCQT+Ebpu9oM5hRYj9izAJjz5ThGLzJ1ysNHhMc8inTxaOnZc0QBDYQ82YHy1tgFYCRof6IDvGTOhwaAnHl7WiVDl0m1s3R4DDBIZ8yZVQolHIZavUGVLZ0Sh0OOZG4DcnVG88VH+6PyCANTBYBRyp1UodDHoYJDvkUf7UCE+3HhTmXyrs5OhjbV+3I88hksm6rrkSDwQSHfM50Fhp7PatVQJFYYMwVHI/GOhwaKiY45HOms9DY651taIOu0wQ/lRwTYtngz5NdeL22sG6OBoUJDvkc8RPhsSo9Oo0sXPRG4vypKaNCoVLwbc6TTR6phVIuQ32rARXNrJujgeMrn3xOnNYP0SEamK0CDlW0SB0OOYFj/hT733g8P5UCk0ZqAXDVlQbHJQnO66+/jqSkJPj5+SEjIwO7du3q8/odO3YgIyMDfn5+SE5Oxt/+9rce12zYsAETJ06ERqPBxIkTsXHjRmeFT17GVrho39fnG6ZXYgdj7zKdk8VpCJye4Kxfvx4rVqzA008/jaKiIsydOxc33HADysrKer3+3Llz+MEPfoC5c+eiqKgIv/rVr/Doo49iw4YNjmvy8/OxZMkS5Obm4uDBg8jNzcXixYuxd+9eZz8d8hKOhn/2rQzyHrpOE07VtQEA0nmCyis4Co35gYQGQSY4uWorKysL06dPxxtvvOG4b8KECbjtttuwZs2aHtc/9dRT2LRpE44fP+64b/ny5Th48CDy8/MBAEuWLIFer8eXX37puOb6669HWFgY1q1b129Mer0eWq0WOp0OISEsQPRFheebcccbuxERqEbBMwshk8mkDomGyfaSOtz3z/1IjAjAjv+dL3U4NAyqWjqR/f99A4VchsOrcxCgVkodEklkML+/nbqCYzQaUVhYiJycnG735+TkYPfu3b1+TX5+fo/rFy1ahIKCAphMpj6vudxjGgwG6PX6bjfybWkjQ6BWyNHYbsT5xg6pw6FhJPY3ymD9jdeIC/VHrNYPFquAg+Vs+EcD49QEp6GhARaLBdHR0d3uj46ORk1NTa9fU1NT0+v1ZrMZDQ0NfV5zucdcs2YNtFqt4xYfHz/Up0ReQqNUIG2k2PCPy97epMj+75nO+huv4uhfxdcrDZBLiowvXf4XBKHPLYHerr/0/sE85qpVq6DT6Ry38vLyQcVP3okNxLyP5aIGf1zB8S6Ofjh8vdIAOXUjMzIyEgqFosfKSl1dXY8VGFFMTEyv1yuVSkRERPR5zeUeU6PRQKPRDPVpkJeyfSI8x5ENXuRUXSvaDGYEqhUYHxMsdTg0jC4dlMu6OeqPU1dw1Go1MjIykJeX1+3+vLw8ZGdn9/o1s2fP7nH91q1bkZmZCZVK1ec1l3tMot6InwhLavRoM5gljoaGg7gaNzU+FAo5fwF6k0lxWqiVcjR3mHCuoV3qcMgDOH2LauXKlfjHP/6Bd955B8ePH8fjjz+OsrIyLF++HIBt++gnP/mJ4/rly5fj/PnzWLlyJY4fP4533nkHb7/9Np544gnHNY899hi2bt2Kl156CSdOnMBLL72Ebdu2YcWKFc5+OuRFokP8MDLUH1YBOFjeInU4NAzEY//sf+N91Eo5pjga/rVIGwx5BKcnOEuWLMGrr76K559/HtOmTcPOnTuxefNmJCYmAgCqq6u79cRJSkrC5s2bsX37dkybNg3/93//hz//+c+44447HNdkZ2fjo48+wj//+U9MmTIFa9euxfr165GVleXsp0NeZjrrcLxKETsYezXOkaPBcHofHHfEPjgkWvv9Oaz+/BjmjR+BtT+dKXU4dAWa2o2Y/n+2revi31yH0AC1xBHRcNtypAbL3y9Eakwwtqy4WupwSAJu0weHyN2JnwiLylpgtfpcru9VxNWbMSMCmdx4qemJoQCAktpWtHaZpA2G3B4THPJpE2JD4KeSQ9dpwtmGNqnDoSsgbjNye8p7RQX7IT7cH4IAFLNujvrBBId8mkohx5RRoQA4l8rTiXUZLDD2bo6Gf3y9Uj+Y4JDPY8M/z2e2WB0t/KczwfFqHLxJA8UEh3weW8B7vhM1reg0WRDsp8TYEUFSh0NOJL5ei8qaWTdHfWKCQz5P7JB6qq4Nug4WLnoiMTlNTwiDnA3+vFpqTDD8VQq0dplxup51c3R5THDI50UEaTA6IgAAcKCcqzie6EKBcai0gZDTKRVyTI23N/zjtjL1gQkOES46Ls43TI/EAmPfwm1lGggmOES48IuxgAmOx6lr7UJ5UydkMmBafKjU4ZAL8GAADQQTHCIAmYnhAGy9NcwWq8TR0GCIx4XHRQUj2E8lbTDkEun2FZwz9e1o6TBKHA25KyY4RABSooIQ7KdEh9GCEzWtUodDg+CYP8XtKZ8RHqhGcmQgAFsXcqLeMMEhAiCXyxz7+gWlTRJHQ4PBAmPflM46HOoHExwiu0xHA7EWaQOhATOarThUaWvwxwJj38I6HOoPExwiO8cbJldwPMaxaj2MZivCAlRIsm9ZkG8QB28eZN0cXQYTHCK7qfGhUMhlqNJ1oaqlU+pwaADE7cTpCWGQydjgz5ekRAUjSKNEu9GCklrWzVFPTHCI7AI1SkyIDQbAZW9PIf47ZYzm9pSvUchlSLfXXR3gtjL1ggkO0UXE4+JMcNyfIAiOvkXivxv5FkehMV+v1AsmOEQXYeGi5yhr6kB9qwEqhQxTRmmlDockIL5eeZKKesMEh+gi4hvmsWo92g1miaOhvhSU2n6ppY3Uwk+lkDgakoLYufp8Ywca2gzSBkNuhwkO0UXiQv0Rp/WDxSrgYEWL1OFQH8TtqRmjuT3lq7T+KoyLDgLAbSrqiQkO0SWmO46L8w3TnRWet52gYv8b3yY26CzkNhVdggkO0SUyOXjT7ek6TDhZ2waACY6vEz+QcAWHLsUEh+gSmfYtjwNlzbBaBYmjod6IRaVJkYGIDNJIHA1JSdyiPFiuQ5fJInE05E6Y4BBdIjUmGAFqBVq7zDhV1yZ1ONSL/aXcniKb0REBiAxSw2ix4oh9bAcRwASHqAelQu44ncHj4u7pQv8bJji+TiaTOfog7WfdHF2ECQ5RLzIcdTicS+VujGYrDpa3ALiwnUi+LdPeybqAc+ToIkxwiHrBhn/u62iVDgb7gM0xIzhgky7U4RSybo4uwgSHqBfpCWGQyWwNxOpb2UDMnTjmTyVywCbZTIwLgb9KgZYOE87Us26ObJjgEPVC66/CuCgO3nRHYgfjDM6fIjvVRXVzrMMhERMcossQJ1Rzzo376DZgkxPE6SIzWIdDl2CCQ3QZGQl8w3Q34swhtUKOySM5YJMuEAvO9/NgANk5NcFpbm5Gbm4utFottFotcnNz0dLSctnrTSYTnnrqKUyePBmBgYGIi4vDT37yE1RVVXW7bt68eZDJZN1uS5cudeZTIR8krhAcqdSzgZibEFdvJo/igE3qLj0hFHIZUN7UiVp9l9ThkBtwaoJz9913o7i4GFu2bMGWLVtQXFyM3Nzcy17f0dGBAwcO4Ne//jUOHDiATz/9FCdPnsQtt9zS49ply5ahurracXvzzTed+VTIByWEs4GYuxHnT7H/DV0q2E+FCbEhAC7UaZFvUzrrgY8fP44tW7Zgz549yMrKAgD8/e9/x+zZs1FSUoLx48f3+BqtVou8vLxu97322muYOXMmysrKkJCQ4Lg/ICAAMTExzgqfCDKZDBmJYfjqaC0Kzjez54obuFBgzASHespMDMPRKj32lzbhximxUodDEnPaCk5+fj60Wq0juQGAWbNmQavVYvfu3QN+HJ1OB5lMhtDQ0G73f/DBB4iMjMSkSZPwxBNPoLW19bKPYTAYoNfru92IBoL9cNxHS4fRMTqDCQ71RvwQwgadBDhxBaempgZRUVE97o+KikJNTc2AHqOrqwu//OUvcffddyMkJMRx/z333IOkpCTExMTgyJEjWLVqFQ4ePNhj9Ue0Zs0aPPfcc0N7IuTTxKPIB843QxAE9l2RkHiaLTkyEBEcsEm9EOvmjlXp0WYwI0jjtF9x5AEGvYKzevXqHgW+l94KCgoAoNdfBgP9JWEymbB06VJYrVa8/vrr3f5u2bJlWLhwIdLS0rB06VJ88skn2LZtGw4cONDrY61atQo6nc5xKy8vH+zTJh+VNjIEaqUcje1GnGtolzocn8btKepPrNYfo8L8YRWAIrZ38HmDTm8ffvjhfk8sjR49GocOHUJtbW2Pv6uvr0d0dHSfX28ymbB48WKcO3cO33zzTbfVm95Mnz4dKpUKp06dwvTp03v8vUajgUbDT3w0eBqlAlNGalFwvhmF55uRPCJI6pB8lpjgzGAtFPVhxuhwVDRXoqC0GXNTRkgdDklo0AlOZGQkIiMj+71u9uzZ0Ol02LdvH2bOnAkA2Lt3L3Q6HbKzsy/7dWJyc+rUKXz77beIiIjo93sdPXoUJpMJsbEsKqPhlzE6zJHg3JUZL3U4PslotuJgRQuACw0YiXqTOToMG4sqWYdDzisynjBhAq6//nosW7YMe/bswZ49e7Bs2TLcdNNN3U5QpaamYuPGjQAAs9mMO++8EwUFBfjggw9gsVhQU1ODmpoaGI1GAMCZM2fw/PPPo6CgAKWlpdi8eTPuuusupKenY86cOc56OuTDxIZ/LDSWzhH7gM3wQDWSIzlgky4v0143V1TWApPFKnE0vknfZcK97+zDX789DYuEw0+d2gfngw8+wOTJk5GTk4OcnBxMmTIF7733XrdrSkpKoNPZeoxUVFRg06ZNqKiowLRp0xAbG+u4iSev1Go1vv76ayxatAjjx4/Ho48+ipycHGzbtg0KBRt/0fATaz5O1bWhpcMocTS+qdC+PTU9gQM2qW8pUUEI8VOiw2jB8WqemJVCQWkTdpysx78LyqGQS/d6dWqJeXh4ON5///0+rxGEC9nd6NGju/25N/Hx8dixY8ewxEc0EBFBGiRHBuJsQzuKylowP7Xn6UByLnG7gfOnqD9yuQyZo8PxzYk67C9txpRRoVKH5HP2nrO9XrOSpK2X4ywqogGYbl/F4b6+6wmC4NgeZAdjGohMDt6U1N6ztp/7zKT+a2idiQkO0QCIv1jZAt71Shs70NBmhFohRxoHbNIAzHA0/Gvud1eAhle7wewYbcMVHCIPINbhHKxg4aKriZ/Cp3DAJg3Q5JFaqBVy1LcaUNbUIXU4PqWorAVmq4A4rR9GhflLGgsTHKIBGDMiCFp/FbpMVhyrYuGiK4nbUzweTgPlp1Jgyijbat9+rrq61N5zjQCArOQIyQ8EMMEhGgC5XIbpCaEAbMve5DoFjvobNvijgctgHY4kxALjmRJvTwFMcIgGTBzkt/8c3zBdpaXDiNMcsElDMMOeEO9nguMyXSYListbAEhffwMwwSEasFnJthfsvtImWCVsXuVLxO2p5BGBCA9USxwNeRIxIT5T346mdvavcoWD5S0wmq2IDNIgyQ0acjLBIRqgySND4a9SoKndiFP2VQVyrgIeD6chCgtUIyXKNjuOXchdw9H/Jjlc8vobgAkO0YCplXJHf409ZxsljsY3iPUTmRywSUMg/r9hHY5r7HOTBn8iJjhEgyC+cMWTAuQ8BrMFByts/TS4gkNDMcP+gYR1OM5nslgdK2VZEjf4EzHBIRqEWcm2F+6es01sIOZkRyr1MJqtiAhUu8V+Pnke8eTd4UodukwWiaPxbocrdeg0WRAaoHJsDUqNCQ7RIEwZFQo/lZx1OC5QaB+LMT2RAzZpaOLD/REVrIHJIuCg/XQPOYe4PTVzdDjkEg7YvBgTHKJBUCvljtMZe1mH41T5Z+wNw9xkP588j0wm6za2gZxHfD90h/43IiY4RIM0K+nCNhU5h9lidXSgFbcFiYaCgzedz2IVHHP63On1ygSHaJBmjbG9gPeea2QdjpMcrtShzWCG1l+FibEhUodDHuziFRz2r3KO49V6tBrMCNYoMcGNXq9McIgGacooLTRKORrajDhTzzocZ8g/e2F7yl3288kzpcYEI1CtQGuXGSfrWqUOxyuJ/W8yR4dB4UavVyY4RIOkUSocdTj53KZyCrH+ZvYY91nuJs+kVMiRniAeF2cdjjNcqL9xr9crExyiIbhwXJyFxsPNaLY69vOZ4NBwEOtwClmHM+ysVsHRZygr2X0KjAEmOERD4mj4x344w+5QRQs6TRaEB6oxLipY6nDIC4h1OHvP8fU63E7Xt6G5wwR/lQKTR2qlDqcbJjhEQzA1PtReh2PAmfp2qcPxKuL21Kxk1t/Q8MhIDINaIUe1rgvnGvh6HU7i9lRGYhhUCvdKKdwrGiIP4adSYHoC51I5g1hgPNuNjpuSZ/NTKTA9MRQAsPsMX6/DSSwwdqf+NyImOERDJO43iy9wunIGs8Uxz4b1NzSc5oyJBADsPtMgcSTeQxAEJjhE3ujiQmPu6w+PorIWGMxWjAjWYMwI95hnQ94he6zt9Zp/ppH9cIZJaWMH6lsNUCvkmBYfKnU4PTDBIRqiafGhUCvlqG814Cz39YfFhfqbCM6fomE1ZVQoAtUKNHeYcLxGL3U4XkGsv5kWHwo/lULiaHpigkM0RH4qBdLtn1r2sh/OsGD9DTmLSiFHlv3/1e7TrMMZDuKATXc7Hi5igkN0BdgPZ/h0mSwoLmsBwPobco5s+/8r1uEMD3euvwGY4BBdEdbhDJ/C880wWqyICfHD6IgAqcMhL5RtLzTed64JJotV4mg8W0VzBypbOqGUyxyd3d0NExyiK5CeEAq1Qo66VgNKGzukDsejXTyegfU35AypMcEID1Sj3WjBwfIWqcPxaOL2VNpILQLUSomj6R0THKIr4KdSYFpCKABuU10p1t+Qs8nlMsf/L/bDuTJi3aG71t8ATHCIrhjrcK5cu8Hs+ETN+htyJvG4+PenWYdzJfaJ86fctP4GYIJDdMVmcS7VFdtf2gSzVcDIUH/Eh7P+hpxHrMMpKmtBp9EicTSeqU5vG3khkwGZo300wWlubkZubi60Wi20Wi1yc3PR0tLS59fcd999kMlk3W6zZs3qdo3BYMAjjzyCyMhIBAYG4pZbbkFFRYUTnwnR5aUn2Obc1Oi7cJ51OEPi2J7i6g052eiIAMRp/WC0WFFwnu0dhkI8PTUxNgQhfiqJo7k8pyY4d999N4qLi7FlyxZs2bIFxcXFyM3N7ffrrr/+elRXVztumzdv7vb3K1aswMaNG/HRRx/hu+++Q1tbG2666SZYLMzGyfX81QpHF09uUw3NHns9RDYTHHIymUyG2fZVnO/ZD2dI9p6z/dyyktz79eq00ufjx49jy5Yt2LNnD7KysgAAf//73zF79myUlJRg/Pjxl/1ajUaDmJiYXv9Op9Ph7bffxnvvvYeFCxcCAN5//33Ex8dj27ZtWLRo0fA/GaJ+ZCWHY19pE/aea8LSmQlSh+NR9F0mHK7UAeAKDrnGnLER2HCgAvnshzMk+9y8/43IaSs4+fn50Gq1juQGAGbNmgWtVovdu3f3+bXbt29HVFQUxo0bh2XLlqGurs7xd4WFhTCZTMjJyXHcFxcXh7S0tMs+rsFggF6v73YjGk7shzN0+881wSrYtg5itf5Sh0M+QKzDOVypg67TJHE0nqWp3YiTtW0AfDjBqampQVRUVI/7o6KiUFNTc9mvu+GGG/DBBx/gm2++wR/+8Afs378f1157LQwGg+Nx1Wo1wsK6NxaKjo6+7OOuWbPGUQek1WoRHx9/Bc+MqKfpCWFQKWSo1nWhrIl1OINxcf8bIleI0foheUQgrMKFeUo0MOLqzbjoIIQHqiWOpm+DTnBWr17dowj40ltBQQEA9NqsSxCEPpt4LVmyBDfeeCPS0tJw880348svv8TJkyfxxRdf9BlXX4+7atUq6HQ6x628vHwQz5iofxfX4XAu1eCIBcaz2P+GXGiOfRWH/XAGRzxe7wmv10HX4Dz88MNYunRpn9eMHj0ahw4dQm1tbY+/q6+vR3R09IC/X2xsLBITE3Hq1CkAQExMDIxGI5qbm7ut4tTV1SE7O7vXx9BoNNBoNAP+nkRDkZUUgf2lzdhzthGLZ3CVcCBaOow4Vm3bMmaDP3Kl7DEReG/PefbDGQRBELD9pK1k5JpxIySOpn+DTnAiIyMRGRnZ73WzZ8+GTqfDvn37MHPmTADA3r17odPpLpuI9KaxsRHl5eWIjY0FAGRkZEClUiEvLw+LFy8GAFRXV+PIkSP43e9+N9inQzRsZiVH4C/fnnbU4XDcQP/2nmuCIABjRgQiKsRP6nDIh8xKjoBMBpyqa0Ndaxeigvn/rz+ljR0ob+qEWiH3iBUcp9XgTJgwAddffz2WLVuGPXv2YM+ePVi2bBluuummbieoUlNTsXHjRgBAW1sbnnjiCeTn56O0tBTbt2/HzTffjMjISNx+++0AAK1Wi/vvvx+/+MUv8PXXX6OoqAg//vGPMXnyZMepKiIpTE8MhUohQ5WuCxXNnVKH4xFYf0NSCQtUY2JsCIAL/w+pbztKbKs3M5LCEKhxz/lTF3NqH5wPPvgAkydPRk5ODnJycjBlyhS899573a4pKSmBTmc7IqpQKHD48GHceuutGDduHO69916MGzcO+fn5CA4OdnzNK6+8gttuuw2LFy/GnDlzEBAQgM8//xwKhcKZT4eoTwFqJaaMCgVwoa6E+rbHMX+q/1VhouE2Z6y9Dof9cAZk+8l6AJ6xPQU4sQ8OAISHh+P999/v85qLj9T6+/vjq6++6vdx/fz88Nprr+G111674hiJhtOs5HAUnrfX4WSyDqcvjW0GnKhpBWD7uRG5WvaYCLy18yy+Zz+cfnWZLI4PJNeM63lC2h1xFhXRMBJXIr471cB+OP0Q272Pjw5GRBAPAZDrzRgdDqVchormTpRxzEqf9p1rQpfJipgQP4yLDpI6nAFhgkM0jGYkhSFArUBdqwFHq9hQsi+svyGpBWqUSE8IBQDs5ipOn3ZctD3lKQcomOAQDSONUuHY1//2RF0/V/s29r8hd+CYS8VC4z45EpzxnlF/AzDBIRp216ba9qe/KWGCczl1rV04XdcGmYz1NyStOfYVxPwz3Fa+nIrmDpyua4NCLnN8gPMETHCIhtk8+yec4vIWNLUbJY7GPe2xd3ueEBOC0AD3bvdO3m1aQij8VHI0tF2YsUTd7Txp276bnhAKrb9K4mgGjgkO0TCL1fpjQmwIBAHYcZKrOL1h/Q25C41SgRmjbauI7Grcux0e1L34YkxwiJxgvn0V59sT9RJH4n4EQcB2+/bdVR603E3ey9EPh3U4PZgsVnx/2rOOh4uY4BA5gViHs+NkPcwWq8TRuJejVXpU67rgr1JwBYfcQrb9/+Hes418vV6i8Hwz2gxmRASqMSkuROpwBoUJDpETTIu37VXrOk0oKm+ROhy38vVx++pNSiT8VOw+TtKbFKdFiJ8SrQYzDlfqpA7HrYinp64eNwJyuWccDxcxwSFyAqVC7tiv5nHx7r4+UQsAWDjBs5a7yXsp5DJHuwJuU3W3o8SzxjNcjAkOkZM4joszwXGo1XfhUIUOMhlwbWq01OEQOVyow2GhsahO34Vj1XrIZMDcFM+rl2OCQ+QkV48bAZkMOFHTimodp4sDF7anpo4KxYhgjmcg9zFnrG0Fp6C0GZ1Gi8TRuIedp2zJ3uSRWo8cp8IEh8hJwgPVSI8PBcDTVKKvj3N7itzTmBFBGBnqD4PZil2n+HoFuo9n8ERMcIicaP542y/yb9nVGJ1GC76z9xlZOJHbU+ReZDIZcibZ/l9+dbRW4mikZ7EKjkRvngeNZ7gYExwiJ5pvr8P5/nQDDGbfXvb+7nQDDGYrRob6Y3x0sNThEPWwaFIMAFshvK8fFz9U0YKWDhNC/JSYOipU6nCGhAkOkRNNigtBVLAGHUYL9p1rkjocSV28PeUp04jJt2QmhiEsQIWWDhP2lfr263W7/fTU3JQRUCo8M1XwzKiJPIRMJnNsU/nyaSqrVcDX9ufP7SlyV0qFHAsn2P5/bvXxbSpPr78BmOAQOZ24TeXL/XAOVepQ32pAkEaJrCR2Lyb3lWPfpso7Vuuz08Wb2404WNECwHYa1FMxwSFysqtSIqFSyFDa2IFzDe1ShyMJcXvq6nGRUCv5tkPua25KJPxVClS2dOJolV7qcCSx63QDBAFIjQlGjNZP6nCGjO80RE4WpFFiZpJtWrGvblNts/e/EZf/idyVn0rh2JbZerRG4mik4cndiy/GBIfIBcQ6nO0+eFy8orkDx6v1kMsu/ByI3JkvHxe3WgWvqL8BmOAQuYRYh7P3bBPaDWaJo3EtcdUqIzEMYYFqiaMh6t+C1Ggo5DKU1Lai1Me2lY/X6NHQZkCAWoGM0WFSh3NFmOAQuUByZCASwgNgtFjx/WnfmnXD7SnyNNoAFWYl27aVtx7zrW0qcfUme0wENEqFxNFcGSY4RC4gk8kcwzd9qatxm8GMPfbpzAuY4JAHEZv++dpxcUf9jRdsJzPBIXIRsd35tyfqfeb46a6T9TBarBgdEYAxIwKlDodowK6z92sqLGtGfatB4mhco7XLhMLzzQCAa1I8u/4GYIJD5DKzkiPgr1KgRt+F49WtUofjEuL21IIJ0exeTB4lVuuPqaO0EARg23HfWMX5/nQjzFbBtqUeESB1OFeMCQ6Ri/ipFJgz1tbkzhe2qSxWwfE8WX9Dnkhs+veVjxwXF5uRenJzv4sxwSFyoXnjfaercVFZM5rajQjxUyLTw09jkG9aZD8uvvt0I1q7TBJH41wGswVfHqkGAOR4yTgVJjhELiQeFz9Q1ozmdqPE0TiXuD01b3wUVB46rI9825gRQUiODITRYnWcLvJW356oh77LjJgQP2Qle8c4Fb7rELnQyFB/jI8OhlUAdp7y7jdMsW6BwzXJU8lksou2qby7Duez4koAwK3T4qCQe0e9HBMcIhfzheGb5xvbcbquDUq5zOO7oZJvE7saf3uiDgazReJonEPXacLX9hXX29JHShzN8HFqgtPc3Izc3FxotVpotVrk5uaipaWlz6+RyWS93l5++WXHNfPmzevx90uXLnXmUyEaNvPtx8W3n6yH0WyVOBrnELenZowOh9ZfJXE0REM3bVQoooI1aDOYkW/v6eRtvjxcDaPFivHRwZgQGyJ1OMPGqQnO3XffjeLiYmzZsgVbtmxBcXExcnNz+/ya6urqbrd33nkHMpkMd9xxR7frli1b1u26N99805lPhWjYZCSGISpYg5YOk9cO39x2jNtT5B3kcpmjJ87WY965TbWxyLY95U2rN4ATE5zjx49jy5Yt+Mc//oHZs2dj9uzZ+Pvf/47//ve/KCkpuezXxcTEdLt99tlnmD9/PpKTk7tdFxAQ0O06rVbrrKdCNKyUCjlun257I/mksFziaIafrtOE/aVNAICFEzy/GyqR2NU471gtrFbvatJZ2dKJvedsr9dbp8VJHM3wclqCk5+fD61Wi6ysLMd9s2bNglarxe7duwf0GLW1tfjiiy9w//339/i7Dz74AJGRkZg0aRKeeOIJtLb6RuM08g53ZcQDAL4tqUdda5fE0QyvHSfrYbYKGBsVhMQIdi8mzzcrOQLBfkrUtxpQVN4idTjDalNxFQBgVnI44kL9JY5meDktwampqUFUVM9Pb1FRUaipGVjTpHfffRfBwcH44Q9/2O3+e+65B+vWrcP27dvx61//Ghs2bOhxzcUMBgP0en23G5GUxkYFIT0hFBargP/Yl4e9xdfi6Sk29yMvoVbKHbPktnpR0z9BELCxqAIAcLuXbU8BQ0hwVq9efdlCYPFWUFAAAL22ZhcEYcAt29955x3cc8898PPz63b/smXLsHDhQqSlpWHp0qX45JNPsG3bNhw4cKDXx1mzZo2j0Fmr1SI+Pn6Qz5po+N2ZMQoA8HFBhdfMpuowmvGNY3o4t6fIe+RMvNDV2Fter8erW3Gytg1qhRzXp8VKHc6wG3SC8/DDD+P48eN93tLS0hATE4Pa2p4FWfX19YiO7v+T3a5du1BSUoIHHnig32unT58OlUqFU6dO9fr3q1atgk6nc9zKy72v7oE8z81T46BRynGqrg0HK3RShzMsPj9YhVaDGYkRAZiewO7F5D2uGT8CaqUcpY0dOF3XJnU4w+I/9t43CyZEeeVpR+VgvyAyMhKRkZH9Xjd79mzodDrs27cPM2fOBADs3bsXOp0O2dnZ/X7922+/jYyMDEydOrXfa48ePQqTyYTY2N4zUI1GA41G0+/jELlSiJ8K16fF4LPiKnxcUI5p8aFSh3TFPtxn+/Dwo5kJkHtJszAiAAjSKHHV2Eh8c6IOXx2tQUp0sNQhXRGLVXA09/O201Mip9XgTJgwAddffz2WLVuGPXv2YM+ePVi2bBluuukmjB8/3nFdamoqNm7c2O1r9Xo9Pv74415Xb86cOYPnn38eBQUFKC0txebNm3HXXXchPT0dc+bMcdbTIXIKsdh408EqdJk8u4nY0SodDpa3QKWQObbfiLyJOJvKG46L7z3biFq9AVp/FeaN985mnE7tg/PBBx9g8uTJyMnJQU5ODqZMmYL33nuv2zUlJSXQ6bovz3/00UcQBAE/+tGPejymWq3G119/jUWLFmH8+PF49NFHkZOTg23btkGhUDjz6RANu+wxERgZ6o/WLrPHTyz+cG8ZANuR2sggrpiS91kwIRoyGXCoQoeK5g6pw7kiYu+bG6fEQqP0zt+dMsFbqqUGQa/XQ6vVQqfTISTEe7o2kmf649YS/Pmb05ibEon37s/q/wvcULvBjKwXv0abwYwPl2Uhe0z/29hEnuhHb+1B/tlGPDR/DP53UarU4QxJl8mCzBe2oc1gxr9/Phszk8KlDmnABvP7m7OoiCR2p32b6rvTDahs6ZQ4mqHZdLAKbQYzkiMDMdtLJhET9ebe7EQAthVLT91W3na8Fm0GM0aG+iMz0XsPAzDBIZJYQkQAspLCIQjAp4UVUoczJOL21I9mJgy4DQSRJ1o4IRojQ/3R3GHCpoNVUoczJP9xjGaI8+rDAExwiNzAXZm2VZxPDnheT5zDFTocrtRBrZDjDhYXk5dTKuTInW1bxVn7fanHvV6b2o3YXlIPALhtmneenhIxwSFyAz+YHINAtQLnGzuwzz4XxlN8uO88AOCGyTEID1RLHA2R8y2dEQ8/lRzHqvXYX9osdTiD8sXhapitAtJGhnj8Uff+MMEhcgMBaiVunGLr4/SxB21TtXaZ8Jl9ls3dMxMkjobINUID1I7RBmt3n5M4msFxbE95+eoNwASHyG2I21SbD1ej3WCWOJqB+ay4Ch1GC8ZGBXnUSQyiK3Vv9mgAwFdHa1HlIYcDyho7UHi+GXKZrZO6t2OCQ+QmMhPDkBQZiA6jBV8crpY6nH4JgsDiYvJZqTEhmJ0cAYtVwPt7zksdzoCIoxnmjI1EdIhfP1d7PiY4RG5CJrvQAfiTAvffpjpYocOxaj3USjnumO79y91El7pvzmgAwLp97n9kXBAER4LjC9tTABMcIrfyw+kjIZcB+0qbUNrQLnU4ffpwr+1T602TYxEawOJi8j3djowXu/eR8cOVOpytb4efSo5FaTFSh+MSTHCI3Eis1h9Xpdjmwmw44L6rOPouEz4/aNtGuzuLxcXkmxRymaPx3z93u/eRcXE0w3UTYxCkGfScbY/EBIfIzdxl36baUFgBi9U93zD/U1SJTpMF46KDkOHFnVCJ+rMkMwH+KgWOV+vdtsVDS4cRG+ynM29P9/7iYhETHCI3c93EaIT4KVGl68LuMw1Sh9PDxcXFd7O4mHycNkCF26eLR8ZLpQ3mMt7Yfgb6LjNSY4JxzbgoqcNxGSY4RG7GT6XArfYiwI/dsNj4QFkLTtS0wk8lx+3T2bmY6D7HkfEat5snV9XSiX/aE6+nrk+FwotHM1yKCQ6RG7or05Y4bDlag8Y2g8TRdCeu3tw0JQ5af5XE0RBJb1x0MOaMjYBVAN7Ld68j469uOwmj2YqZSeGYN36E1OG4FBMcIjc0eaQWaSNDYDRb8futJ6UOx0HXYcJ/D9k7F7O4mMjhvuwkAMBH+8vQaXSPI+Onalvxib325pc3pPrcdjITHCI3JJPJ8JubJgGwvWEertBJHJHNp0UVMJitSI0JRnp8qNThELmNa1OjEB/uj5YOEz6z95uR2u++KoFVAK6fFIPpCb53GIAJDpGbmpkUjlunxUEQgN9sOgKrxCeqBEHAun324uIsFhcTXUwhl+He2aMB2IqNpT4yXlDahLxjtZDLgCcWjZc0FqkwwSFyY7/6wQQEqhUoKmvBp0XSfir8d0E5Tta2wV+lwG3pvtEJlWgw7sqMh79KgRM1rdhzVroj44Ig4KUtJwAAS2bEY2xUkGSxSIkJDpEbiw7xwyMLUgAA/9+Xx6HvMkkSR7WuEy/89zgAYOV14xDix+Jioktp/VW4I0P6KeNfH6/D/tJmaJRyPLZgnGRxSI0JDpGb+39zkpAcGYiGNiNezTvl8u8vCAJ+9elhtBrMSE8Ixf+7KsnlMRB5CnGbKu9YLcqbOlz+/S1WAb/7yrZ68/+uSkKM1vuHal4OExwiN6dWyrH6FlvB8bv5pThZ2+rS7//pgUp8W1IPtVKOl++c4lN9NIgGKyU6GHNTImEVgKf/4/rauU8PVOBkbRu0/iosv2aMS7+3u2GCQ+QBrh43AjkTo2GxCnj2s6MuK2Cs1Xfhuc+PAgBWLEzB2Khgl3xfIk/2zI0T4aeSY+fJevxt5xmXfd8ukwWv5NnaSjw0f4zP96ligkPkIX5900RolHLkn23E5sM1Tv9+giDg6Y1HoO8yY8ooLX42N9np35PIG4yPCcZz9lXXP2w96bIZVe/ln0eVrguxWj/8xL5V5suY4BB5iPjwAMeS8wtfHEOH0ezU77fpYBW2Ha+FSiHDy3dOhVLBtwuigVqcGY/b00fCYhXw6LoiNLUbnfr9dJ0m/HX7aQDA49eNg59K4dTv5wn4jkXkQf5n3hiMCvNHta4Lr3/rvKXv+lYDnt1k25p65NoUjI/h1hTRYMhkMrxwWxqSRwSiRt+Flf8udmo9zps7zqClw4SUqCDcwRlxAJjgEHkUP5UCz9w4EQDw1s6zKG1od8r3+c1nR9DSYcLE2BD8zzzfLlQkGqpAjRKv3zMdGqUc20vq8ebOs075PrX6Lrzzve1Y+pM+NlCzL0xwiDzMoknRmJsSCaPFiuf/e2zYH/+LQ9X48kgNlHIZXr5rClTcmiIastSYEEc9zu+3lmB/6fDX47y67RS6TFZkJoZh4YSoYX98T8V3LiIPI5PJsPqWSVApZPjmRB2+Pl47bI/d2GbAbz47AgB4cN4YTIrTDttjE/mqJTPiceu0uGGvx7FaBbz81QnHCBVfHKjZFyY4RB5ozIgg/L85toZ7z//32LBNL179+TE0thsxPjoYD1+bMiyPSeTrZDIZfnv7ZCRHBqJa14VfDEM9TpvBjJ+/X4i/2mvxHrl2LDJHhw9HuF6DCQ6Rh3pkQQqigjU439iBH/x5F/LPNF7R4205UoPPD1ZBYd+aUiv59kA0XII0SvzVXo/zbUk93to19Hqc8qYO3PH6buQdq4VaKccfF0/FL3J8c6BmX/gORuShgjRK/OXu6YgO0eBcQzt+9Pc9eOqTQ9B1DG5elSAI+O5UA575j21r6mdXJ2PKqFAnREzk2ybEhuDZm231OC9/VYLC84Ovx8k/04hb/vIdSmpbMSJYg/U/m4Uf8tRUr5ya4Pz2t79FdnY2AgICEBoaOqCvEQQBq1evRlxcHPz9/TFv3jwcPXq02zUGgwGPPPIIIiMjERgYiFtuuQUVFRVOeAZE7m1mUjjyVl6De7ISAADrC8qx4I878MWh6n67HRvNVnx6oAI3/GkXfvz2XjS0GTA2KgiPLeDWFJGz/GhmPG6ZaqvHefjDIlS2dA74a9/fcx65b+9Fc4cJk0dqsenhOUhPCHNitJ5NJjix5/uzzz6L0NBQVFRU4O2330ZLS0u/X/PSSy/ht7/9LdauXYtx48bhhRdewM6dO1FSUoLgYFsvjv/5n//B559/jrVr1yIiIgK/+MUv0NTUhMLCQigU/Tc30uv10Gq10Ol0CAkJudKnSeQW9pc24ZcbDuFMve3o+MIJUfi/29IQq/Xvdp2u04R1+8rwz+/PoVZvAAD4qxRYMiMeD84bg6gQ3x3OR+QKbQYzbn7tO5yzt3kYFx2EOWMjMWdMJLKSwxHs133EgslixfOfH8N7e84DAG6eGoeX75zik838BvP726kJjmjt2rVYsWJFvwmOIAiIi4vDihUr8NRTTwGwrdZER0fjpZdews9//nPodDqMGDEC7733HpYsWQIAqKqqQnx8PDZv3oxFixb1Gw8THPJWBrMFf/32DN7Yfhomi4AgjRJPXj8eP85KRJWuE+98V4r1+8vQbi9KHhGswX3Zo3FPVgJCA9QSR0/kO07VtuJ/PzmEgxUtuPi3sEIuw7T4UHvCE4GkyEA89lEx8s/aauz+d9F4PDhvjM+elvLYBOfs2bMYM2YMDhw4gPT0dMf9t956K0JDQ/Huu+/im2++wYIFC9DU1ISwsAtLc1OnTsVtt92G5557rt94mOCQtztZ24pfbjiEA2UtAICkyECUNXXAYj+5MT46GA/MTcIt0+KgUfrep0Aid9HcbkT+2UZ8d7oB359uwPnGjl6vC1Qr8MqSaciZFOPiCN3LYH5/K10U04DU1NgGCEZHR3e7Pzo6GufPn3dco1aruyU34jXi11/KYDDAYDA4/qzX64czbCK3My46GJ8sz8YHe8/jpS0ljqXwq8ZGYtnVybg6JdJnPwESuZOwQDV+MDkWP5gcC8B2Qmr3mQZ8d7oRu083oLHdiFFh/vjHvZlIjeEH8sEYdIKzevXqfldJ9u/fj8zMzCEHdekbryAI/b4Z93XNmjVrBrSyQ+RN5HIZcmePxsKJ0dhUXIW5KSMwMY5vkETuLD48AEvCE7BkRgKsVgFnG9oRF+qHALVbrUd4hEH/xB5++GEsXbq0z2tGjx49pGBiYmxLbzU1NYiNjXXcX1dX51jViYmJgdFoRHNzc7dVnLq6OmRnZ/f6uKtWrcLKlSsdf9br9YiPjx9SjESeJlbrj59fw3lSRJ5GLpdhbFSQ1GF4rEEnOJGRkYiMjHRGLEhKSkJMTAzy8vIcNThGoxE7duzASy+9BADIyMiASqVCXl4eFi9eDACorq7GkSNH8Lvf/a7Xx9VoNNBoNE6JmYiIiNyPU9e8ysrK0NTUhLKyMlgsFhQXFwMAxo4di6AgW1aampqKNWvW4Pbbb4dMJsOKFSvw4osvIiUlBSkpKXjxxRcREBCAu+++GwCg1Wpx//334xe/+AUiIiIQHh6OJ554ApMnT8bChQud+XSIiIjIQzg1wfnNb36Dd9991/FncVXm22+/xbx58wAAJSUl0Ol0jmuefPJJdHZ24sEHH0RzczOysrKwdetWRw8cAHjllVegVCqxePFidHZ2YsGCBVi7du2AeuAQERGR93PJMXF3w2PiREREnmcwv785i4qIiIi8DhMcIiIi8jpMcIiIiMjrMMEhIiIir8MEh4iIiLwOExwiIiLyOkxwiIiIyOswwSEiIiKvwwSHiIiIvI5Pzl8Xmzfr9XqJIyEiIqKBEn9vD2QIg08mOK2trQCA+Ph4iSMhIiKiwWptbYVWq+3zGp+cRWW1WlFVVYXg4GDIZLJhfWy9Xo/4+HiUl5dzzlU/+LMaOP6sBo4/q4Hjz2pw+PMaOGf9rARBQGtrK+Li4iCX911l45MrOHK5HKNGjXLq9wgJCeELYID4sxo4/qwGjj+rgePPanD48xo4Z/ys+lu5EbHImIiIiLwOExwiIiLyOkxwhplGo8Gzzz4LjUYjdShujz+rgePPauD4sxo4/qwGhz+vgXOHn5VPFhkTERGRd+MKDhEREXkdJjhERETkdZjgEBERkddhgkNERERehwmOk33xxRfIysqCv78/IiMj8cMf/lDqkNyawWDAtGnTIJPJUFxcLHU4bqe0tBT3338/kpKS4O/vjzFjxuDZZ5+F0WiUOjS38frrryMpKQl+fn7IyMjArl27pA7J7axZswYzZsxAcHAwoqKicNttt6GkpETqsDzCmjVrIJPJsGLFCqlDcUuVlZX48Y9/jIiICAQEBGDatGkoLCyUJBYmOE60YcMG5Obm4qc//SkOHjyI77//HnfffbfUYbm1J598EnFxcVKH4bZOnDgBq9WKN998E0ePHsUrr7yCv/3tb/jVr34ldWhuYf369VixYgWefvppFBUVYe7cubjhhhtQVlYmdWhuZceOHXjooYewZ88e5OXlwWw2IycnB+3t7VKH5tb279+Pt956C1OmTJE6FLfU3NyMOXPmQKVS4csvv8SxY8fwhz/8AaGhodIEJJBTmEwmYeTIkcI//vEPqUPxGJs3bxZSU1OFo0ePCgCEoqIiqUPyCL/73e+EpKQkqcNwCzNnzhSWL1/e7b7U1FThl7/8pUQReYa6ujoBgLBjxw6pQ3Fbra2tQkpKipCXlydcc801wmOPPSZ1SG7nqaeeEq666iqpw3DgCo6THDhwAJWVlZDL5UhPT0dsbCxuuOEGHD16VOrQ3FJtbS2WLVuG9957DwEBAVKH41F0Oh3Cw8OlDkNyRqMRhYWFyMnJ6XZ/Tk4Odu/eLVFUnkGn0wEA/x/14aGHHsKNN96IhQsXSh2K29q0aRMyMzNx1113ISoqCunp6fj73/8uWTxMcJzk7NmzAIDVq1fjmWeewX//+1+EhYXhmmuuQVNTk8TRuRdBEHDfffdh+fLlyMzMlDocj3LmzBm89tprWL58udShSK6hoQEWiwXR0dHd7o+OjkZNTY1EUbk/QRCwcuVKXHXVVUhLS5M6HLf00Ucf4cCBA1izZo3Uobi1s2fP4o033kBKSgq++uorLF++HI8++ij+9a9/SRIPE5xBWr16NWQyWZ+3goICWK1WAMDTTz+NO+64AxkZGfjnP/8JmUyGjz/+WOJn4RoD/Vm99tpr0Ov1WLVqldQhS2agP6uLVVVV4frrr8ddd92FBx54QKLI3Y9MJuv2Z0EQetxHFzz88MM4dOgQ1q1bJ3Uobqm8vByPPfYY3n//ffj5+UkdjluzWq2YPn06XnzxRaSnp+PnP/85li1bhjfeeEOSeJSSfFcP9vDDD2Pp0qV9XjN69Gi0trYCACZOnOi4X6PRIDk52WcKHgf6s3rhhRewZ8+eHjNLMjMzcc899+Ddd991ZphuYaA/K1FVVRXmz5+P2bNn46233nJydJ4hMjISCoWix2pNXV1dj1UdsnnkkUewadMm7Ny5E6NGjZI6HLdUWFiIuro6ZGRkOO6zWCzYuXMn/vKXv8BgMEChUEgYofuIjY3t9jsPACZMmIANGzZIEg8TnEGKjIxEZGRkv9dlZGRAo9GgpKQEV111FQDAZDKhtLQUiYmJzg7TLQz0Z/XnP/8ZL7zwguPPVVVVWLRoEdavX4+srCxnhug2BvqzAmzHMOfPn+9YFZTLuRALAGq1GhkZGcjLy8Ptt9/uuD8vLw+33nqrhJG5H0EQ8Mgjj2Djxo3Yvn07kpKSpA7JbS1YsACHDx/udt9Pf/pTpKam4qmnnmJyc5E5c+b0aDdw8uRJyX7nMcFxkpCQECxfvhzPPvss4uPjkZiYiJdffhkAcNddd0kcnXtJSEjo9uegoCAAwJgxY/ip8hJVVVWYN28eEhIS8Pvf/x719fWOv4uJiZEwMvewcuVK5ObmIjMz07G6VVZWxhqlSzz00EP48MMP8dlnnyE4ONix6qXVauHv7y9xdO4lODi4R21SYGAgIiIiWLN0iccffxzZ2dl48cUXsXjxYuzbtw9vvfWWZKvMTHCc6OWXX4ZSqURubi46OzuRlZWFb775BmFhYVKHRh5q69atOH36NE6fPt0j+RMEQaKo3MeSJUvQ2NiI559/HtXV1UhLS8PmzZt9ZtV0oMSaiHnz5nW7/5///Cfuu+8+1wdEXmHGjBnYuHEjVq1aheeffx5JSUl49dVXcc8990gSj0zguyIRERF5GW7eExERkddhgkNERERehwkOEREReR0mOEREROR1mOAQERGR12GCQ0RERF6HCQ4RERF5HSY4RERE5HWY4BAREZHXYYJDREREXocJDhEREXkdJjhERETkdf5/ADmEhSQYkrAAAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.plot(x,y)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3.9.15 ('base')", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.15" + }, + "orig_nbformat": 4, + "vscode": { + "interpreter": { + "hash": "a59afa236e16843183c59a167f072b6fa0409044b3c4938e82ac98aad91bf217" + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/code/python/.ipynb_checkpoints/EventLattice-checkpoint.ipynb b/code/python/.ipynb_checkpoints/EventLattice-checkpoint.ipynb deleted file mode 100644 index 829cb1d..0000000 --- a/code/python/.ipynb_checkpoints/EventLattice-checkpoint.ipynb +++ /dev/null @@ -1,113 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "57fc5921-9d6b-4b43-a8f6-743a03650d63", - "metadata": {}, - "outputs": [], - "source": [ - "import event_lattice as el" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "00f0eb68", - "metadata": {}, - "outputs": [], - "source": [ - "def zoom_event(event_str, lattice, lower_op=el.sum_op, upper_op=el.prod_op):\n", - " event = el.Event.from_str(event_str)\n", - " event_class = lattice.event_class(event)\n", - " propagated = lattice.propagated_value(\n", - " event, lower_op=lower_op, upper_op=upper_op)\n", - "\n", - " print(\n", - " f\"Event: {event}\\n\\tClass: {event_class} \\n\\tValue: {propagated}\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "cdd8c6d6", - "metadata": {}, - "outputs": [], - "source": [ - "smodels = el.Lattice.parse({\n", - " \"A\": 2,\n", - " \"ab\": 3,\n", - " \"ac\": 5\n", - "})\n", - "\n", - "lattice = el.Lattice(smodels)\n", - "\n", - "print(lattice)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "2b445339", - "metadata": {}, - "outputs": [], - "source": [ - "zoom_event(\"abc\", lattice)\n", - "zoom_event(\"a\", lattice)\n", - "zoom_event(\"b\", lattice)\n", - "zoom_event(\"bc\", lattice)\n", - "zoom_event(\"ac\", lattice)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "f1b85255", - "metadata": {}, - "outputs": [], - "source": [ - "from itertools import *\n", - "\n", - "lits = lattice.literals()\n", - "for len_lit in range(len(lits)+1):\n", - " events = list(\"\".join(c) for c in combinations(lits, len_lit))\n", - " for event in events:\n", - " zoom_event(event, lattice)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "07973a47", - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3.9.13 ('base')", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.13" - }, - "vscode": { - "interpreter": { - "hash": "a59afa236e16843183c59a167f072b6fa0409044b3c4938e82ac98aad91bf217" - } - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/code/python/EventLattice.ipynb b/code/python/EventLattice.ipynb deleted file mode 100644 index 8cd7d9e..0000000 --- a/code/python/EventLattice.ipynb +++ /dev/null @@ -1,154 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 4, - "id": "57fc5921-9d6b-4b43-a8f6-743a03650d63", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The autoreload extension is already loaded. To reload it, use:\n", - " %reload_ext autoreload\n" - ] - } - ], - "source": [ - "%load_ext autoreload\n", - "%autoreload 1\n", - "%aimport event_lattice" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "00f0eb68", - "metadata": {}, - "outputs": [], - "source": [ - "def zoom_event(event_str, lattice):\n", - " event = event_lattice.Event.from_str(event_str)\n", - " event_class = lattice.event_class(event)\n", - " propagated = lattice.extended_value(\n", - " event)\n", - "\n", - " print(\n", - " f\"Event: {event}\\n\\tClass: {event_class} \\n\\tValue: {propagated}\")" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "cdd8c6d6", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{\n", - "\t'stable_models': {\n", - "\t\t A: 2,\n", - "\t\tab: 3,\n", - "\t\tac: 5 \n", - "\t}\n", - "\t'literals': { A,B,C,a,b,c } \n", - "}\n" - ] - } - ], - "source": [ - "smodels = event_lattice.Lattice.parse({\n", - " \"A\": 2,\n", - " \"ab\": 3,\n", - " \"ac\": 5\n", - "})\n", - "\n", - "lattice = event_lattice.Lattice(smodels)\n", - "\n", - "print(lattice)" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "2b445339", - "metadata": {}, - "outputs": [ - { - "ename": "TypeError", - "evalue": "__init__() missing 1 required positional argument: 'lattice'", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m/tmp/ipykernel_361713/2581811254.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mzoom_event\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"abc\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlattice\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2\u001b[0m \u001b[0mzoom_event\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"a\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlattice\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0mzoom_event\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"b\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlattice\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0mzoom_event\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"bc\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlattice\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0mzoom_event\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"ac\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlattice\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m/tmp/ipykernel_361713/1675915232.py\u001b[0m in \u001b[0;36mzoom_event\u001b[0;34m(event_str, lattice)\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mzoom_event\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mevent_str\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlattice\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0mevent\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mevent_lattice\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mEvent\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfrom_str\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mevent_str\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0mevent_class\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mlattice\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mevent_class\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mevent\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 4\u001b[0m propagated = lattice.extended_value(\n\u001b[1;32m 5\u001b[0m event)\n", - "\u001b[0;32m~/sci/projetos/zugzwang/code/python/event_lattice.py\u001b[0m in \u001b[0;36mevent_class\u001b[0;34m(self, event)\u001b[0m\n\u001b[1;32m 146\u001b[0m \u001b[0;34m@\u001b[0m\u001b[0mcache\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 147\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mevent_class\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mevent\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 148\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mEventsClass\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mstable_core\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mevent\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 149\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 150\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mrelated\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mu\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mv\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;31mTypeError\u001b[0m: __init__() missing 1 required positional argument: 'lattice'" - ] - } - ], - "source": [ - "zoom_event(\"abc\", lattice)\n", - "zoom_event(\"a\", lattice)\n", - "zoom_event(\"b\", lattice)\n", - "zoom_event(\"bc\", lattice)\n", - "zoom_event(\"ac\", lattice)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "f1b85255", - "metadata": {}, - "outputs": [], - "source": [ - "from itertools import *\n", - "\n", - "lits = lattice.literals()\n", - "events = []\n", - "for len_lit in range(len(lits)+1):\n", - " events = events + list(\"\".join(c) for c in combinations(lits, len_lit))\n", - "for event in events:\n", - " zoom_event(event, lattice)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "07973a47", - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.15" - }, - "vscode": { - "interpreter": { - "hash": "a59afa236e16843183c59a167f072b6fa0409044b3c4938e82ac98aad91bf217" - } - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/code/python/__init__.py b/code/python/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/code/python/__init__.py +++ /dev/null diff --git a/code/python/__pycache__/event_lattice.cpython-39.pyc b/code/python/__pycache__/event_lattice.cpython-39.pyc deleted file mode 100644 index a72fa05..0000000 Binary files a/code/python/__pycache__/event_lattice.cpython-39.pyc and /dev/null differ diff --git a/code/python/algebra.py b/code/python/algebra.py deleted file mode 100644 index 2cae6bb..0000000 --- a/code/python/algebra.py +++ /dev/null @@ -1,30 +0,0 @@ -from itertools import combinations, product - -def fmt(expr): - """Doc string""" - return ",".join(f"{x:>2}" for x in expr) - -def c(expr): - """Doc string""" - def litcomp(x): - if x == "⊤": - return "⊥" - elif x == "⊥": - return "⊤" - elif x[0] == "¬": - return x[1:] - else: - return f"¬{x}" - return [litcomp(x) for x in expr] - -def domain(symbols, unary="¬"): - """Doc string""" - atoms = list(symbols) - literals = [ - [f"{u}{a}" for u in unary] + - [a, "⊤", "⊥"] for a in atoms ] - return product(*literals) - -d = sorted(domain("abc")) -for x in d: - print(f"{fmt(x)} | {fmt(c(x))}") diff --git a/code/python/api_01.py b/code/python/api_01.py deleted file mode 100644 index f119ed2..0000000 --- a/code/python/api_01.py +++ /dev/null @@ -1,26 +0,0 @@ -from clingo.symbol import Number -from clingo.control import Control - -class Context: - def inc(self, x): - return Number(x.number + 1) - - def seq(self, x, y): - return [x, y] - -def on_model(m): - print(m) - -ctl = Control() -ctl.add("base", [], """\ -p(@inc(10)). -q(@seq(1,2)). -""") - -ctl.ground( - [("base", [])], - context=Context()) - -s = ctl.solve(on_model=on_model) - -print(s) \ No newline at end of file diff --git a/code/python/event_lattice.py b/code/python/event_lattice.py deleted file mode 100644 index 899d260..0000000 --- a/code/python/event_lattice.py +++ /dev/null @@ -1,301 +0,0 @@ -import math -from functools import cache -from itertools import accumulate, combinations, chain, groupby -import operator - - - -def uniform_op(x): - n = len(list(x)) - return 1.0 if n == 0 else 1.0/n - - -def max_op(x): - return max(x) - - -def min_op(x): - return min(x) - - -def sum_op(x): - return sum(x) - - -def stableprod_op(x): - log_x = map(math.log, x) - return math.exp(sum(log_x)) - - -def prod_op(x): - return list(accumulate(x, func=lambda a,b: a*b))[-1] - - -class Event: - """Events. - - An event is a set of literals - atoms and negated atoms. - - The convention is that atoms are represented by lower case single letters - and a negated atom by upper case single letters. - """ - - @staticmethod - def _parse(text): - return frozenset(text) - - @staticmethod - def parse(text): - """Convert a string to an event. - - Each letter in the string represents a literal. - """ - return Event(Event._parse(text)) - - - def __init__(self, literals): - """Instantiate from a (frozen) set of literals. - For example: e = Event(frozenset("abc")).""" - self._literals = frozenset(literals) - - - def literals(self): - return self._literals - - - def __iter__(self): - return self._literals.__iter__() - - @cache - def is_consistent(self): - """True if this event is consistent.""" - return all(x.swapcase() not in self._literals for x in self._literals) - - - def co(self): - """Negation of this event. - - Negation is case based: A = not a; a = not A.""" - return Event(x.swapcase() for x in self._literals) - - def invert(self): - """Negation of this event. - - See the method "co" - """ - return self.co() - - def __repr__(self) -> str: - return ''.join(str(x) for x in sorted(self._literals)) if len(self._literals) > 0 else '0' - - def latex(self): - """LaTeX representation of this even. - - Negation is represented by overline and the empty event by - - """ - return ''.join( - (str(x) if x.islower() else f"\co{{{x.lower()}}}") \ - for x in sorted(self._literals) - ) if len(self._literals) > 0 else "\set{}" - - def __hash__(self) -> int: - return self._literals.__hash__() - - - def __eq__(self, other): - """Event equality test.""" - return self._literals.__eq__(other._literals) - - def __or__(self, other): - """Event union operation.""" - return Event(self._literals | other._literals) - - def __le__(self, other): - """Event subset test.""" - return self._literals.__le__(other._literals) - - - def __lt__(self, other): - """Event strict subset test.""" - return self._literals.__lt__(other._literals) - - - def __ne__(self, other): - """Event not-equal test.""" - return self._literals.__ne__(other._literals) - - - def __ge__(self, other): - """Event superset test.""" - return self._literals.__ge__(other._literals) - - - def __gt__(self, other): - """Event strict superset test.""" - return self._literals.__gt__(other._literals) - - -class Lattice: - - @staticmethod - def parse(d): - """Input stable models. - - The input format is a dictionary associating a stable model in string form to an weight. - - For example: - - input_dict = { - "A": 0.3, - "ab": 0.2, - "ac": 0.5 - } - smodels = Lattice.parse(input_dict) - """ - result = dict() - for k, v in d.items(): - key = Event.parse(k) - result[key] = v - return result - - - @staticmethod - def close_literals(events): - """Closed set of literals entailed by a set of events. - - Includes the literals in the set of events and any missing negation.""" - base_lits = list(accumulate(events, func=operator.or_))[-1] - lits = set() - for x in base_lits.literals(): - lits.add(x) - lits.add(x.swapcase()) - return sorted(lits) - - def __init__(self, smodels_dict): - """Create an Events lattice.""" - self._smodels = smodels_dict - self._literals = Lattice.close_literals(self._smodels.keys()) - - def literals(self): - """The literals in this lattice.""" - return self._literals - - @cache - def stable_models(self): - """The stable models that generate this lattice.""" - return self._smodels.keys() - - #@cache - def events(self): - """All the events of this lattice.""" - return chain.from_iterable(map(Event, combinations(self._literals, r)) for r in range(len(self._literals)+1)) - - @cache - def stable_core(self, event): - """The stable core of an event in this lattice.""" - return set(filter(lambda sm: sm <= event or event <= sm, self.stable_models())) - - # @cache - # def event_class(self, event): - # """The equivalence class of an event.""" - # return EventsClass(self.stable_core(event), self) - - @cache - def classes(self): - """The classes of this lattice. - - Each class is presented as a key:value pair where the "key" is the stable core of the elements in "value".""" - map_ev_classes = [(e, tuple(self.stable_core(e))) for e in self.events() if e.is_consistent()] - groups = dict() - for e,c in map_ev_classes: - if c in groups.keys(): - groups[c].add(e) - else: - groups[c] = set([e]) - inconsistent = list(e for e in self.events() if not e.is_consistent()) - inconsistent_repr = inconsistent[0] - groups[(inconsistent_repr,)] = set(inconsistent) - return groups - - - def related(self, u, v): - """Tests if two events are related.""" - u_consistent = u.is_consistent() - v_consistent = v.is_consistent() - if u_consistent and (u_consistent == v_consistent): - return self.stable_core(u) == self.stable_core(v) - else: - return u_consistent == v_consistent - - def extended_value(self, event:Event, - op=prod_op): - """TODO: well...""" - value = 0 - # - # INCONSISTENT EVENTS - # - if not event.is_consistent(): - return value - # - # CONSISTENT EVENTS - # - score = self.stable_core(event) - len_score = len(score) - # CONSISTENT, INDEPENDENT - if len_score == 0: - value = 0 - elif len_score == 1: - value = self._smodels[score[0]] - else: - value = op(map(lambda sm: self._smodels[sm], score)) - - return value - - def __repr__(self): - smodels_repr = ',\n\t\t'.join(f"{k}: {v:<}" for k,v in self._smodels.items()) - lits_repr = ','.join(sorted(self._literals)) - - return "{\n" +\ - f"\t'stable_models': {{\n\t\t {smodels_repr} \n\t}}\n" +\ - f"\t'literals': {{ {lits_repr} }} \n" +\ - "}" - -# class EventsClass: -# def __init__(self, core, lattice:Lattice): -# self._core = core -# self._lattice = lattice - -# def __repr__(self): -# core_repr = "" if len(self._core) == 0 else ",".join(str(x) for x in self._core) -# return f"<{core_repr}>" - -# def __contains__(self, event:Event): -# return self.lattice.stable_core(event) == self._core - -if __name__ == "__main__": - def zoom_event(event_str, lattice): - event = Event.parse(event_str) - event_class = lattice.event_class(event) - propagated = lattice.extended_value( - event) - - print( - f"Event: {event}\n\tClass: {event_class} \n\tValue: {propagated}") - - smodels = Lattice.parse({ - "A": 2, - "ab": 3, - "ac": 5 - }) - - lattice = Lattice(smodels) - - ev_classes = lattice.classes() - for k,g in ev_classes.items(): - print(f"{tuple(s.latex() for s in k)} {set(e.latex() for e in g)}") - # zoom_event("abc", lattice) - # zoom_event("a", lattice) - # zoom_event("b", lattice) - # zoom_event("bc", lattice) - # zoom_event("ac", lattice) \ No newline at end of file diff --git a/code/python/explore_01.py b/code/python/explore_01.py deleted file mode 100644 index f894bdd..0000000 --- a/code/python/explore_01.py +++ /dev/null @@ -1,13 +0,0 @@ -from clingo.control import Control -from clingox.program import Program, ProgramObserver, Remapping - -prg = Program() -ctl_a = Control() -ctl_a.register_observer(ProgramObserver(prg)) -print(f"<1>\n{prg}\n") - -prog = "code/asp/alarm.lp" -ctl_a.load(prog) -ctl_a.ground([('base', [])]) -print(f"<2>\n{prg}\n") - diff --git a/code/python/symbops.py b/code/python/symbops.py deleted file mode 100644 index 25fd6f8..0000000 --- a/code/python/symbops.py +++ /dev/null @@ -1,41 +0,0 @@ -from unicodedata import numeric -from sympy import * -from sympy.plotting import plot - -def variants(expr, with_plot=False): - print(f"Expr: {latex(expr)}") - print(f"Simplify: {latex(simplify(expr))}") - print(f"Expand: {latex(expand(expr))}") - print(f"Factor: {latex(factor(expr))}") - if with_plot: - plot(expr, (d, 0, 1, 10),ylabel="$\\mathrm{P(expr \\mid \\alpha = 0.3)}$") - -init_printing(use_unicode=True) - -a, d = symbols('a d') -A = 1 - a -D = 1 - d - -wab = a * d -wac = a * D -wA = A - -wabc = wab * wac -wAb = wA -wa = wab + wac -wb = wab -wc = wac -wE = wab + wab + wA - -z = wabc + 9 * wA + wab + wac + wa + wb +wc + wE -pabc = wabc/z - -z_03 = z.subs(a, 0.3) -wabc_03 = wabc.subs(a, 0.3) -pabc_03 = pabc.subs(a, 0.3) - -variants(z_03) -variants(wabc_03) -variants(pabc_03) -print(solve(wabc_03 - 0.0015 * z_03, d)) - diff --git a/code/python/teste.ipynb b/code/python/teste.ipynb deleted file mode 100644 index c62a6aa..0000000 --- a/code/python/teste.ipynb +++ /dev/null @@ -1,116 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "4" - ] - }, - "execution_count": 1, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "2+2" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "import matplotlib.pyplot as plt\n", - "import numpy as np" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "x = np.linspace(-6, 6)" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "y = np.sin(x)" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[]" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "plt.plot(x,y)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3.9.15 ('base')", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.15" - }, - "orig_nbformat": 4, - "vscode": { - "interpreter": { - "hash": "a59afa236e16843183c59a167f072b6fa0409044b3c4938e82ac98aad91bf217" - } - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/sample.csv b/sample.csv new file mode 100644 index 0000000..240b732 --- /dev/null +++ b/sample.csv @@ -0,0 +1,100 @@ +c +a +B +c +ab +Ac +aBC +BC +Ab +b +c +AB +Ac +B +bC +Ab + +aB +B +a +aC +B +AB +B + +C +bc + +B +bc +AC +ABC +a +b +ac +AC +B +bC +b +C + +aC +AbC + +C +AC +bc + + +C +b + +b +abc +a +abc + +B +a +C +aB + +A +Bc +C +AB +aBc +A +b + +a +a +c +b +a +A +Ab +aC + +B +C +Ab +Bc +A +Ac +c +B +AC +ABC +Ab +aC +bC + + +C +a + +ABC +b +aB diff --git a/students/amartins/tarefas/tarefa2.py b/students/amartins/tarefas/tarefa2.py index 06fa275..d825253 100644 --- a/students/amartins/tarefas/tarefa2.py +++ b/students/amartins/tarefas/tarefa2.py @@ -26,13 +26,20 @@ if __name__ == "__main__": parents = model.get_parents(node) s = "" if len(parents) == 0: - s += str(yes_prob) + " :: " + str(node) + s += str(yes_prob) + " :: " + str(node) +"\n" print(s) elif len(parents) == 1: - s += str(yes_prob[0]) + " :: " + str(node) + " <- " + str(parents) + "\n" - s += str(yes_prob[1]) + " :: " + str(node) + " <- -" + str(parents) + "\n" + p = parents[0] + s += str(yes_prob[0]) + " :: " + str(node) + " <- " + str(p) + "\n" + s += str(yes_prob[1]) + " :: " + str(node) + " <- -" + str(p) + "\n" print(s) else: - print("Node:", node) - print("Probability of 'yes':", yes_prob) - print() + yes1 = yes_prob[0] + yes2 = yes_prob[1] + p0 = parents[0] + p1 = parents[1] + s += str(yes1[0]) + " :: " + str(node) + " <- " + str(p0) + ", " + str(p1) + "\n" + s += str(yes2[0]) + " :: " + str(node) + " <- -" + str(p0) + ", " + str(p1) + "\n" + s += str(yes1[1]) + " :: " + str(node) + " <- " + str(p0) + ", -" + str(p1) + "\n" + s += str(yes2[1]) + " :: " + str(node) + " <- -" + str(p0) + ", -" + str(p1) + "\n" + print(s) diff --git a/text/paper_01/pre-paper.pdf b/text/paper_01/pre-paper.pdf index 1d29bc9..9ec5929 100644 Binary files a/text/paper_01/pre-paper.pdf and b/text/paper_01/pre-paper.pdf differ diff --git a/text/paper_01/pre-paper.tex b/text/paper_01/pre-paper.tex index fdc8c24..ded2826 100644 --- a/text/paper_01/pre-paper.tex +++ b/text/paper_01/pre-paper.tex @@ -17,7 +17,7 @@ proptc/.style = {-latex, dashed}, propsm/.style = {-latex, thick}, doubt/.style = {gray} } -\usetikzlibrary{calc, positioning} +\usetikzlibrary{calc, positioning, patterns} \usepackage{hyperref} \hypersetup{ @@ -93,16 +93,18 @@ citecolor=blue, \acrodef{SC}[SC]{stable core} \acrodef{KL}[KL]{Kullback-Leibler} -\title{Zugzwang\\\emph{Logic and Artificial Intelligence}\\{\bruno Why this title?}} +\title{An Algebraic Approach to Stochastic ASP + %Zugzwang\\\emph{Logic and Artificial Intelligence}\\{\bruno Why this title?} + } \author{ \begin{tabular}{ccc} Francisco Coelho - \footnote{Universidade de Évora} + \footnote{Universidade de Évora, NOVALINCS, High Performance Computing Chair} & Bruno Dinis - \footnote{Universidade de Évora} + \footnote{Universidade de Évora, CIMA, CMAFcIO} & Salvador Abreu - \footnote{Universidade de Évora} + \footnote{Universidade de Évora, NOVALINCS} \\ \texttt{fc@uevora.pt} & \texttt{bruno.dinis@uevora.pt} @@ -148,8 +150,9 @@ Our idea to extend probabilities starts with the stance that a specification des 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. 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.} +\todo{Also remark that our apporach remains algebraic in the way that we address the problems concerning the extension of probabilities.} -\todo{cite \cite{sympy} \franc{--- why here? but cite \cite{cozman2020joy} and relate with our work.}} +\todo{cite \citetitle{sympy} \franc{--- why here? but cite \citetitle{cozman2020joy} and relate with our work.}} \todo{Discuss the least informed strategy and the corolary that \aclp{SM} should be conditionally independent on the \acl{TC}.} @@ -239,6 +242,8 @@ The \aclp{SM} $ab, ac$ from \cref{running.example} result from the clause $b \v \draw[doubt] (ac) to[bend right] (abc); \draw[doubt] (ac) to[bend left] (aBc); + + \draw[doubt, dash dot] (Ac) to (Abc); \draw[doubt] (A) to (Ac); \draw[doubt] (A) to (Abc); @@ -251,10 +256,10 @@ The \aclp{SM} $ab, ac$ from \cref{running.example} result from the clause $b \v \draw[doubt] (ac) to (c); % \draw[doubt] (ab) to[bend left] (a); % \draw[doubt] (ac) to[bend right] (a); - \draw[doubt] (c) to[bend right] (bc); - \draw[doubt] (abc) to[bend left] (bc); - \draw[doubt] (Abc) to (bc); - \draw[doubt] (c) to[bend right] (Ac); + \draw[doubt, dash dot] (c) to[bend right] (bc); + \draw[doubt, dash dot] (abc) to[bend left] (bc); + \draw[doubt, dash dot] (bc) to (Abc); + \draw[doubt, dash dot] (c) to[bend right] (Ac); \end{tikzpicture} \end{center} @@ -287,7 +292,7 @@ The diagram in \cref{fig:running.example} illustrates the problem of extending p \node[event, above = of A] (Ac) {$\co{a}c$}; \node[event, above right = of Ac] (Abc) {$\co{a}bc$}; % ---- - \path[draw, rounded corners, fill=cyan, fill opacity=0.1] + \path[draw, rounded corners, pattern=north west lines, opacity=0.2] (ab.west) -- (ab.north west) -- % @@ -316,7 +321,7 @@ The diagram in \cref{fig:running.example} illustrates the problem of extending p (ab.west) ; % ---- - \path[draw, rounded corners, fill=magenta, fill opacity=0.1] + \path[draw, rounded corners, pattern=north east lines, opacity=0.2] (ac.south west) -- (ac.west) -- (ac.north west) -- @@ -346,7 +351,7 @@ The diagram in \cref{fig:running.example} illustrates the problem of extending p (ac.south west) ; % ---- - \path[draw, rounded corners, fill=yellow, fill opacity=0.1] + \path[draw, rounded corners, pattern=horizontal lines, opacity=0.2] % (A.north west) -- % (Ac.north west) -- @@ -373,7 +378,7 @@ The diagram in \cref{fig:running.example} illustrates the problem of extending p \end{tikzpicture} \end{center} - \caption{Classes (of consistent events) related to the \aclp{SM} of \cref{running.example} are defined through inclusions. \todo{write the caption}} + \caption{Classes (of consistent events) related to the \aclp{SM} of \cref{running.example} are defined through intersections and inclusions. \todo{write the caption}} \label{fig:running.example.classes} \end{figure} @@ -559,7 +564,7 @@ The ``extension'' phase, traced by equations (\ref{eq:prob.total.choice}) and (\ \pw{\class{e}} := \sum_{t \in \fml{T}} \pw{\class{e}, t}\pw{t}. \label{eq:weight.class.unconditional} \end{equation} - \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.} + \end{description} % \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}. \item[\Aclp{SM}.] The $\theta_{s,t}$ parameters in this example are $$ \theta_{ab,\co{a}} = \theta_{ac,\co{a}} = \theta_{\co{a}, a} = 0 - $$ - and - $$ + % + \text{~and~} + % \theta_{\co{a}, \co{a}} = 1, \theta_{ab, a} = \theta, \theta_{ac, a} = \co{\theta} $$ with $\theta \in \intcc{0, 1}$. @@ -675,7 +680,7 @@ We continue with the specification from Equation \eqref{eq:example.1}. & 1 \end{array} \end{equation*} - \item[Normalization.] To get a weight that sums up to one, we compute the \emph{normalization factor}. Since $\pw{\cdot}$ is constant on classes, + \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.} \begin{equation*} Z := \sum_{e\in\fml{E}} \pw{e} = \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}. & 0 & 0 & 0 - \\ + \\[4pt] % \indepclass & 9 & 0 & 0 & 0 - \\ + \\[4pt] % \co{a} & 9 - & \lfrac{7}{10} - & \lfrac{7}{90} - & \lfrac{7}{792} - \\ + & \frac{7}{10} + & \frac{7}{90} + & \frac{7}{792} + \\[4pt] % ab & 3 - & \lfrac{3\theta}{10} - & \lfrac{\theta}{10} - & \lfrac{\theta}{88} - \\ + & \frac{3\theta}{10} + & \frac{\theta}{10} + & \frac{\theta}{88} + \\[4pt] % ac & 3 - & \lfrac{3\co{\theta}}{10} - & \lfrac{\co{\theta}}{10} - & \lfrac{\co{\theta}}{88} - \\ + & \frac{3\co{\theta}}{10} + & \frac{\co{\theta}}{10} + & \frac{\co{\theta}}{88} + \\[4pt] % \co{a}, ab & 0 - & - & - & - \\ + & \frac{7 + 3\theta}{10} + & 0 + & 0 + \\[4pt] % \co{a}, ac & 0 - & - & - & + & \frac{7 + 3\co{\theta}}{10} + & 0 + & 0 % - \\ + \\[4pt] % ab, ac & 2 - & \lfrac{3}{10} - & \lfrac{3}{20} - & \lfrac{3}{176} - \\ + & \frac{3}{10} + & \frac{3}{20} + & \frac{3}{176} + \\[4pt] % \co{a}, ab, ac & 1 & 1 & 1 - & \lfrac{5}{176} - \\ + & \frac{5}{176} + \\[4pt] % \hline & - & Z = 8.8 + & Z = \frac{44}{5} \end{array} \end{equation*} \end{description} + +\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.} % % % -\subsection{A Not So Simple Example} - -\todo{this subsection} - -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. - -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. - -Considering the probabilities given in \cref{Figure_Alarm} we obtain the following specification - -\begin{equation*} - \begin{aligned} - \probfact{0.001}{B}&,\cr - \probfact{0.002}{E}&,\cr - \probfact{??}{A}&,\cr - ... &. \cr - \end{aligned} - \label{eq:not_so_simple_example} -\end{equation*} +\subsection{An example involving Bayesian networks} +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. +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. @@ -808,8 +799,8 @@ Considering the probabilities given in \cref{Figure_Alarm} we obtain the followi \node[tchoice, below right of=A] (J) {J}; % Edges - \draw[->] (B) to[bend left] (A) node[right,xshift=1.1cm,yshift=0.8cm] {\footnotesize{$P(B)=0,001$}} ; - \draw[->] (E) to[bend right] (A) node[left, xshift=-1.4cm,yshift=0.8cm] {\footnotesize{$P(E)=0,002$}} ; + \draw[->] (B) to[bend left] (A) node[right,xshift=1.1cm,yshift=0.8cm] {\footnotesize{$P(B)=0.001$}} ; + \draw[->] (E) to[bend right] (A) node[left, xshift=-1.4cm,yshift=0.8cm] {\footnotesize{$P(E)=0.002$}} ; \draw[->] (A) to[bend right] (M) node[left,xshift=0.2cm,yshift=0.7cm] {\footnotesize{$P(M|A)$}}; \draw[->] (A) to[bend left] (J) node[right,xshift=-0.2cm,yshift=0.7cm] {\footnotesize{$P(J|A)$}} ; \end{tikzpicture} @@ -822,10 +813,10 @@ Considering the probabilities given in \cref{Figure_Alarm} we obtain the followi \begin{split} &P(M|A)\\ & \begin{array}{c|cc} - A & T & F \\ + & m & \neg m \\ \hline - T & 0,9 & 0,1\\ - F& 0,05 & 0,95 + a & 0.9 & 0.1\\ + \neg a& 0.05 & 0.95 \end{array} \end{split} \end{equation*} @@ -836,10 +827,10 @@ Considering the probabilities given in \cref{Figure_Alarm} we obtain the followi \begin{split} &P(J|A)\\ & \begin{array}{c|cc} - A & T & F \\ + & j & \neg j \\ \hline - T & 0,7 & 0,3\\ - F& 0,01 & 0,99 + a & 0.7 & 0.3\\ + \neg a& 0.01 & 0.99 \end{array} \end{split} \end{equation*} @@ -847,14 +838,14 @@ Considering the probabilities given in \cref{Figure_Alarm} we obtain the followi \footnotesize{ \begin{equation*} \begin{split} - P(A|B \vee E)\\ + P(A|B \wedge E)\\ \begin{array}{c|c|cc} - B & E& T & F \\ + & & a & \neg a \\ \hline - T & T & 0,95 & 0,05\\ - T & F & 0,94 & 0,06\\ - F & T & 0,29 & 0,71\\ - F & F & 0,001 & 0,999 + b & e & 0.95 & 0.05\\ + b & \neg e & 0.94 & 0.06\\ + \neg b & e & 0.29 & 0.71\\ + \neg b & \neg e & 0.001 & 0.999 \end{array} \end{split} \end{equation*} @@ -865,6 +856,64 @@ Considering the probabilities given in \cref{Figure_Alarm} we obtain the followi \end{figure} +Considering the probabilities given in \cref{Figure_Alarm} we obtain the following specification + +\begin{equation*} + \begin{aligned} + \probfact{0.001}{b}&,\cr + \probfact{0.002}{e}&,\cr + \end{aligned} + \label{eq:not_so_simple_example} +\end{equation*} + +For the table giving the probability $P(M|A)$ we obtain the specification: + + +\begin{equation*} + \begin{aligned} + &\probfact{0.9}{pm\_a},\cr + &\probfact{0.05}{pm\_na},\cr + m & \leftarrow a, pm\_a,\cr + \neg m & \leftarrow a, \neg pm\_a. + \end{aligned} +\end{equation*} + +This latter specification can be simplified by writing $\probfact{0.9}{m \leftarrow a}$ and $\probfact{0.05}{m \leftarrow \neg a}$. + +Similarly, for the probability $P(J|A)$ we obtain + +\begin{equation*} + \begin{aligned} + &\probfact{0.7}{pj\_a},\cr + &\probfact{0.01}{pj\_na},\cr + j & \leftarrow a, pj\_a,\cr + \neg j & \leftarrow a, \neg pj\_a.\cr + \end{aligned} +\end{equation*} + +Again, this can be simplified by writing $\probfact{0.7}{j \leftarrow a}$ and $\probfact{0.01}{j \leftarrow \neg a}$. + +Finally, for the probability $P(A|B \wedge E)$ we obtain + +\begin{equation*} + \begin{aligned} + &\probfact{0.95}{a\_be},\cr + &\probfact{0.94}{a\_bne},\cr + &\probfact{0.29}{a\_nbe},\cr + &\probfact{0.001}{a\_nbne},\cr + a & \leftarrow b, e, a\_be,\cr + \neg a & \leftarrow b,e, \neg a\_be, \cr + a & \leftarrow b,e, a\_bne,\cr + \neg a & \leftarrow b,e, \neg a\_bne, \cr + a & \leftarrow b,e, a\_nbe,\cr + \neg a & \leftarrow b,e, \neg a\_nbe, \cr + a & \leftarrow b,e, a\_nbne,\cr + \neg a & \leftarrow b,e, \neg a\_nbne. \cr + \end{aligned} +\end{equation*} + +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. + \section{Discussion} @@ -906,6 +955,14 @@ Considering the probabilities given in \cref{Figure_Alarm} we obtain the followi % % ================================================================ % + \begin{itemize} + \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. + \item \todo{The `up and down' choice in the equivalence relation and the possibility of describing any probability distribution.} + \item \todo{Remark that no benchmark was done with other SOTA efforts.} + \item \todo{The possibility to `import' bayesian theory and tools to this study.} + \end{itemize} + + \subsection{Dependence} \label{subsec:dependence} @@ -963,7 +1020,7 @@ Considering the probabilities given in \cref{Figure_Alarm} we obtain the followi Prove the four world cases (done), support the product (done) and sum (tbd) options, with the independence assumptions. \end{quotation} - \section{Final Remarks} + \subsection{Future Work} \todo{develop this section.} -- libgit2 0.21.2