more latex

This commit is contained in:
Francesco Mecca 2020-04-07 21:05:08 +02:00
parent 8946d41fb4
commit a8791e3c5e
7 changed files with 215 additions and 103 deletions

View file

@ -3,8 +3,8 @@ import re
from sys import argv from sys import argv
allsymbols = json.load(open('./unicode-latex.json')) allsymbols = json.load(open('./unicode-latex.json'))
mysymbols = ['', '', '', '', '', '', '', '', '', '', 'ε','', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'ʲ', '', 'π', 'α', 'β', '', 'σ', '', '', '', '', '', '', '', '', '' ] mysymbols = ['', '', '', '', '', '', '', '', '', 'ε', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'ʲ', '', 'π', 'α', 'β', '', 'σ', '', '', '', '', '', '', '', '', '', '', '', 'ˡ', '', '', '', '' ]
extrasymbols = {'': '\llbracket', '': '\rrbracket'} extrasymbols = {'': '\llbracket', '': r'\rrbracket', '̸': '\neg', '¬̸': '\neg', '': '\in ', '': '_S', '': '_T'}
symbols = {s: allsymbols[s] for s in mysymbols} symbols = {s: allsymbols[s] for s in mysymbols}
symbols.update(extrasymbols) symbols.update(extrasymbols)
@ -13,8 +13,8 @@ mathsymbols = {s: '$'+v+'$' for s, v in symbols.items()}
def read_by_char(fname): def read_by_char(fname):
# Yield character and True/False if inside mathmode block # Yield character and True/False if inside mathmode block
mathmode = False mathmode = False
mathmode_begin = set(['\\begin{equation*}', '\\begin{equation}']) mathmode_begin = set(['\\begin{equation*}', '\\begin{equation}', '\[', '\\begin{mathpar}'])
mathmode_end = set(['\\end{equation*}', '\\end{equation}']) mathmode_end = set(['\\end{equation*}', '\\end{equation}', '\]', '\\end{mathpar}'])
cnt = 0 cnt = 0
with open(fname, 'r') as fp: with open(fname, 'r') as fp:
for line in fp.readlines(): for line in fp.readlines():
@ -50,11 +50,26 @@ def latex_errors_replacements(charlist):
yield from word yield from word
yield ' ' yield ' '
def ll_rr_bracket(charlist):
llrr_mode = False
for i, ch in enumerate(charlist):
if ch == '\\':
if charlist[i:i+10] == '\llbracket':
assert llrr_mode is False ; llrr_mode = True
elif charlist[i:i+10] == '\rrbracket':
assert llrr_mode is True ; llrr_mode = False
if not (llrr_mode and ch == '$'):
yield ch
# convert symbols except the one requiring math mode modifiers # convert symbols except the one requiring math mode modifiers
firstpass = [convert(*c) for c in read_by_char(argv[1])] firstpass = [convert(*c) for c in read_by_char(argv[1])]
# remove a latex error # remove a latex error
secondpass = latex_errors_replacements(firstpass) secondpass = latex_errors_replacements(firstpass)
thirdpass = ll_rr_bracket(list(secondpass))
newfile = ''.join(secondpass) newfile = ''.join(thirdpass)
with open(argv[2], 'w') as f: with open(argv[2], 'w') as f:
f.write(newfile) f.write(newfile)

1
tesi/files/symb_exec Normal file
View file

@ -0,0 +1 @@
<mxfile host="app.diagrams.net" modified="2020-04-07T18:00:18.130Z" agent="5.0 (X11)" etag="UqJT9eDZirhT4ZuYmnlI" version="12.9.9" type="device"><diagram id="vkyFxs9FE47iKiCmcqWQ" name="Page-1">7VpLk+I2EP41rpoccFnyA/sIDJsckspjDsnuJaWxBahiW0QWC+yvj2RLfsmzDCwBdoYqCqyvpZb0dUvqlrHcWbb7kaH16hea4NSCTrKz3EcLwjAIxLcE9hXgRVEFLBlJKgg0wBP5ghXoKHRDElx0KnJKU07WXTCmeY5j3sEQY3TbrbagabfXNVpiA3iKUWqif5KEr9S0fKfBf8JkudI9A0dJMqQrK6BYoYRuW5A7t9wZo5RXT9luhlPJnealavfhBWk9MIZz/poGPz99+n3y6dcYzpztl+c/wH7ERiOl5TNKN2rCMc3WiAvswbbtH9TQ+V7zwegmT7BUCSx3ul0Rjp/WKJbSrXAAga14liqxUo4Zx7sXRw1qLoQPYZphzvaiimrgavq0/6jitjFGTfmqZQhdDyn7L2vNDUXiQbF0BGPQYMzyp8DyHw2qxKR5l4+CM/oPntGUMoHkNBc1pwuSpj0IpWSZi2IsSMICn0oKiXDKiRJkJElkN4MGaEzknMcGMOzawDdt4A2YAP5fJnBNE4zFPEV3QSoZL9Yo75gi+HcjV9k0xQvxMxEy33Ns33PXO9lMkiR2lXUlGvuBDUPYEi1ozkdFuTXJCiC0QQjCfoUFyki6r6oUKC9GBWZk0XQunpbl7+yDFdZjFQRUw1VCBUuNUo/eD7USMKBPz3rzbECvIMJ37MgZDxIRQNtzjHm2iACnczC3yrl8jQMJm3MSaEWOgsu+RtYcWmFoRfPKDVAmF4Kq7+jeBiTtZuM3vIS94OASBuNLrmHPXMN98nGeTOQJLllMUVGQuGsKvCP8L0mR7avSx5bkcafYKwt7XcjF4FuNZPFjW9Y0K0v7jglwYgQLPQOICdANi/HhI5cjtsT8K/WCYYO2LOYPGExjDKeIk8/d4Q5ZUfXwGyXljqOPXa/rL7VzaBXVNFWrdtTRV9RzPND3qIoHQ1HpVPW0T/ezwPCzjMg98aHcht1yAxAfQdCs3CnaILy98Kem72rxz3go/oHvKv4B7pUDoPAMAVDg2KEDjwiAXn22HzGIUGzDbnizUdgL8ImR1hjYILh8pFXuaKdEWm89Br1Q9Dl00hjHzIHQ1L2nN9+Va91KeiMl8CQHus5mdWDf/f5PlBO9OJJePLychTWCzkrvzSr6JieGxzlxqdS27bedS/uHw8E67blIPBgZ8WCMCv6w+VskVfJwuc2rXOhcO5cB5vX3e7mFCF55CxHd0i1E/Vbo6FuIqLdkg8veQoDBtwbuu8qaa+NdK2sG53hvcE+b72nzPW0+S1bjWCrLjayJZ9WJ8j0bfmsec8+G79nwPRt+o2GeB/2DYV4dfl8mzvO/Pas7Y6Z13Qxq3AvCo1MzqL6i8MIZlPkiV686ohccw4UcMV3ILWGFpQF3ON5wQnNd95kNrFnSYLd2RRKai+lcVySi2Pz5sDJT8w9Od/4f</diagram></mxfile>

BIN
tesi/files/symb_exec.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

3
tesi/files/symb_exec.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

View file

@ -31,6 +31,7 @@ Magari prima pattern matching poi compilatore?
#+LANGUAGE: en #+LANGUAGE: en
#+LaTeX_CLASS: article #+LaTeX_CLASS: article
#+LaTeX_HEADER: \linespread{1.25}
#+LaTeX_HEADER: \usepackage{algorithm} #+LaTeX_HEADER: \usepackage{algorithm}
#+LaTeX_HEADER: \usepackage{comment} #+LaTeX_HEADER: \usepackage{comment}
#+LaTeX_HEADER: \usepackage{algpseudocode} #+LaTeX_HEADER: \usepackage{algpseudocode}
@ -41,11 +42,11 @@ Magari prima pattern matching poi compilatore?
#+LaTeX_HEADER: \usepackage{listings} #+LaTeX_HEADER: \usepackage{listings}
#+LaTeX_HEADER: \usepackage{color} #+LaTeX_HEADER: \usepackage{color}
#+LaTeX_HEADER: \usepackage{stmaryrd} #+LaTeX_HEADER: \usepackage{stmaryrd}
#+LaTeX_HEADER: \newcommand{\sem}[1]{{\llbracket{#1}\rrbracket}} #+LaTeX_HEADER: \newcommand{\semTEX}[1]{{\llbracket{#1}\rrbracket}}
#+LaTeX_HEADER: \newcommand{\Equiv}[3]{\mathsf{equiv}(#1, #2, #3)} % \equiv is already taken #+LaTeX_HEADER: \newcommand{\EquivTEX}[3]{\mathsf{equiv}(#1, #2, #3)} % \equiv is already taken
#+LaTeX_HEADER: \newcommand{\covers}[2]{#1 \mathrel{\mathsf{covers}} #2} #+LaTeX_HEADER: \newcommand{\coversTEX}[2]{#1 \mathrel{\mathsf{covers}} #2}
#+LaTeX_HEADER: \newcommand{\Yes}{\mathsf{Yes}} #+LaTeX_HEADER: \newcommand{\YesTEX}{\mathsf{Yes}}
#+LaTeX_HEADER: \newcommand{\No}[2]{\mathsf{No}(#1, #2)} #+LaTeX_HEADER: \newcommand{\NoTEX}[2]{\mathsf{No}(#1, #2)}
#+LaTeX_HEADER: \usepackage{comment} #+LaTeX_HEADER: \usepackage{comment}
#+LaTeX_HEADER: \usepackage{mathpartir} #+LaTeX_HEADER: \usepackage{mathpartir}
#+LaTeX_HEADER: \usepackage{stmaryrd} % llbracket, rrbracket #+LaTeX_HEADER: \usepackage{stmaryrd} % llbracket, rrbracket
@ -142,7 +143,6 @@ the case of a production compiler and to integrate with an existing code base. T
black-box and proof only depends on our equivalence algorithm. black-box and proof only depends on our equivalence algorithm.
\subsection{Our approach} \subsection{Our approach}
%% replace common TODO
Our algorithm translates both source and target programs into a common Our algorithm translates both source and target programs into a common
representation, decision trees. Decision trees where chosen because representation, decision trees. Decision trees where chosen because
they model the space of possible values at a given branch of they model the space of possible values at a given branch of
@ -227,12 +227,12 @@ matched by the source clauses.
\texttt{Unreachable} is used when we statically know that no value \texttt{Unreachable} is used when we statically know that no value
can flow to that subtree. can flow to that subtree.
We write $\sem{t_S}_S$ for the decision tree of the source program We write 〚tₛ〛ₛ for the decision tree of the source program
$t_S$, computed by a matrix decomposition algorithm (each column t_S, computed by a matrix decomposition algorithm (each column
decomposition step gives a \texttt{Switch} node). decomposition step gives a \texttt{Switch} node).
It satisfies the following correctness statement: It satisfies the following correctness statement:
\[ \[
\forall t_S, \forall v_S, \quad t_S(v_S) = \sem{t_S}_S(v_S) \forall t_s, \forall v_s, \quad t_s(v_s) = \semTEX{t_s}_s(v_s)
\] \]
Running any source value $v_S$ against the source program gives the Running any source value $v_S$ against the source program gives the
same result as running it against the decision tree. same result as running it against the decision tree.
@ -250,10 +250,10 @@ nodes are never emitted.
Guards result in branching. In comparison with the source decision Guards result in branching. In comparison with the source decision
trees, \texttt{Unreachable} nodes are never emitted. trees, \texttt{Unreachable} nodes are never emitted.
We write $\sem{t_T}_T$ for the decision tree of the target program We write $\semTEX{t_T}_T$ for the decision tree of the target program
$t_T$, satisfying the following correctness statement: $t_T$, satisfying the following correctness statement:
\[ \[
\forall t_T, \forall v_T, \quad t_T(v_T) = \sem{t_T}_T(v_T) \forall t_T, \forall v_T, \quad t_T(v_T) = \semTEX{t_T}_T(v_T)
\] \]
\subsection{Equivalence checking} \subsection{Equivalence checking}
@ -262,36 +262,36 @@ possible values \emph{S} and a pair of source and target decision trees and
in case the two trees are not equivalent it returns a counter example. in case the two trees are not equivalent it returns a counter example.
The algorithm respects the following correctness statement: The algorithm respects the following correctness statement:
\begin{comment} \begin{comment}
% TODO: we have to define what \covers mean for readers to understand the specifications % TODO: we have to define what \coversTEX mean for readers to understand the specifications
% (or we use a simplifying lie by hiding \covers in the statements). % (or we use a simplifying lie by hiding \coversTEX in the statements).
\end{comment} \end{comment}
\begin{align*} \begin{align*}
\Equiv S {C_S} {C_T} = \Yes \;\land\; \covers {C_T} S \EquivTEX S {C_S} {C_T} = \YesTEX \;\land\; \coversTEX {C_T} S
& \implies & \implies
\forall v_S \approx v_T \in S,\; C_S(v_S) = C_T(v_T) \forall v_S \approx v_T \in S,\; C_S(v_S) = C_T(v_T)
\\ \\
\Equiv S {C_S} {C_T} = \No {v_S} {v_T} \;\land\; \covers {C_T} S \EquivTEX S {C_S} {C_T} = \NoTEX {v_S} {v_T} \;\land\; \coversTEX {C_T} S
& \implies & \implies
v_S \approx v_T \in S \;\land\; C_S(v_S) \neq C_T(v_T) v_S \approx v_T \in S \;\land\; C_S(v_S) \neq C_T(v_T)
\end{align*} \end{align*}
The algorithm proceeds by case analysis. Inference rules are shown. The algorithm proceeds by case analysis. Inference rules are shown.
If $S$ is empty the results is $\Yes$. If $S$ is empty the results is $\YesTEX$.
\begin{mathpar} \begin{mathpar}
\infer{ } \infer{ }
{\Equivrel \emptyset {C_S} {C_T} G} {\EquivTEX \emptyset {C_S} {C_T} G}
\end{mathpar} \end{mathpar}
If the two decision trees are both terminal nodes the algorithm checks If the two decision trees are both terminal nodes the algorithm checks
for content equality. for content equality.
\begin{mathpar} \begin{mathpar}
\infer{ } \infer{ }
{\Equivrel S \Failure \Failure \emptyqueue} {\EquivTEX S \Failure \Failure \emptyqueue}
\\ \\
\infer \infer
{\trel {t_S} {t_T}} {\trel {t_S} {t_T}}
{\Equivrel S {\Leaf {t_S}} {\Leaf {t_T}} \emptyqueue} {\EquivTEX S {\Leaf {t_S}} {\Leaf {t_T}} \emptyqueue}
\end{mathpar} \end{mathpar}
@ -305,10 +305,10 @@ hand side.
\infer \infer
{C_S \in {\Leaf t, \Failure} {C_S \in {\Leaf t, \Failure}
\\ \\
\forall i,\; \Equivrel {(S \land a \in D_i)} {C_S} {C_i} G \forall i,\; \EquivTEX {(S \land a \in D_i)} {C_S} {C_i} G
\\ \\
\Equivrel {(S \land a \notin \Fam i {D_i})} {C_S} \Cfb G} \EquivTEX {(S \land a \notin \Fam i {D_i})} {C_S} \Cfb G}
{\Equivrel S {\EquivTEX S
{C_S} {\Switch a {\Fam i {D_i} {C_i}} \Cfb} G} {C_S} {\Switch a {\Fam i {D_i} {C_i}} \Cfb} G}
\end{mathpar} \end{mathpar}
@ -331,15 +331,15 @@ result in an empty intersection. If the accessors are different,
\begin{mathpar} \begin{mathpar}
\infer \infer
{\forall i,\; {\forall i,\;
\Equivrel \EquivTEX
{(S \land a = K_i)} {(S \land a = K_i)}
{C_i} {\trim {C_T} {a = K_i}} G {C_i} {\trim {C_T} {a = K_i}} G
\\ \\
\Equivrel \EquivTEX
{(S \land a \notin \Fam i {K_i})} {(S \land a \notin \Fam i {K_i})}
\Cfb {\trim {C_T} {a \notin \Fam i {K_i}}} G \Cfb {\trim {C_T} {a \notin \Fam i {K_i}}} G
} }
{\Equivrel S {\EquivTEX S
{\Switch a {\Fam i {K_i, C_i}} \Cfb} {C_T} G} {\Switch a {\Fam i {K_i, C_i}} \Cfb} {C_T} G}
\end{mathpar} \end{mathpar}
@ -355,17 +355,17 @@ Termination of the algorithm is successful only when the guards queue
is empty. is empty.
\begin{mathpar} \begin{mathpar}
\infer \infer
{\Equivrel S {C_0} {C_T} {G, (t_S = 0)} {\EquivTEX S {C_0} {C_T} {G, (t_S = 0)}
\\ \\
\Equivrel S {C_1} {C_T} {G, (t_S = 1)}} \EquivTEX S {C_1} {C_T} {G, (t_S = 1)}}
{\Equivrel S {\EquivTEX S
{\Guard {t_S} {C_0} {C_1}} {C_T} G} {\Guard {t_S} {C_0} {C_1}} {C_T} G}
\infer \infer
{\trel {t_S} {t_T} {\trel {t_S} {t_T}
\\ \\
\Equivrel S {C_S} {C_b} G} \EquivTEX S {C_S} {C_b} G}
{\Equivrel S {\EquivTEX S
{C_S} {\Guard {t_T} {C_0} {C_1}} {(t_S = b), G}} {C_S} {\Guard {t_T} {C_0} {C_1}} {(t_S = b), G}}
\end{mathpar} \end{mathpar}
@ -714,8 +714,8 @@ bad:
The tree of the execution when the function is evaluated considering The tree of the execution when the function is evaluated considering
/int len/ our symbolic variable α, sa->sa_len as symbolic variable β /int len/ our symbolic variable α, sa->sa_len as symbolic variable β
and π as the set of constraints on a symbolic variable: and π as the set of constraints on a symbolic variable:
[[./files/symb_exec.png]]
#+BEGIN_SRC \begin{comment}
[1] compat (...) { π_{α}: -∞ < α < ∞ } [1] compat (...) { π_{α}: -∞ < α < ∞ }
| |
[2] min (σ₁, σ₂) { π_{σ}: -∞ < (σ₁,σ₂) < ∞ ; π_{α}: -∞ < α < β ; π_{β}: ...} [2] min (σ₁, σ₂) { π_{σ}: -∞ < (σ₁,σ₂) < ∞ ; π_{α}: -∞ < α < β ; π_{β}: ...}
@ -723,7 +723,7 @@ and π as the set of constraints on a symbolic variable:
[3] cast(u_int) (...) { π_{σ}: 0 ≤ (σ) < ∞ ; π_{α}: -∞ < α < β ; π_{β}: ...} [3] cast(u_int) (...) { π_{σ}: 0 ≤ (σ) < ∞ ; π_{α}: -∞ < α < β ; π_{β}: ...}
| |
... // rest of the execution ... // rest of the execution
#+END_SRC \end{comment}
We can see that at step 3 the set of possible values of the scrutinee We can see that at step 3 the set of possible values of the scrutinee
α is bigger than the set of possible values of the input σ to the α is bigger than the set of possible values of the input σ to the
/cast/ directive, that is: π_{α} ⊈ π_{σ}. For this reason the /cast/ may fail when α is /len/ /cast/ directive, that is: π_{α} ⊈ π_{σ}. For this reason the /cast/ may fail when α is /len/
@ -731,9 +731,9 @@ negative number, outside the domain π_{σ}. In C this would trigger undefined b
overflow) that made the exploitation possible. overflow) that made the exploitation possible.
Every step of evaluation can be modelled as the following transition: Every step of evaluation can be modelled as the following transition:
#+BEGIN_SRC \[
_{σ}, (πᵢ)ⁱ) → (π'_{σ}, (π'ᵢ)ⁱ) _{σ}, (πᵢ)ⁱ) → (π'_{σ}, (π'ᵢ)ⁱ)
#+END_SRC \]
if we express the π constraints as logical formulas we can model the if we express the π constraints as logical formulas we can model the
execution of the program in terms of Hoare Logic. execution of the program in terms of Hoare Logic.
State of the computation is a Hoare triple {P}C{Q} where P and Q are State of the computation is a Hoare triple {P}C{Q} where P and Q are
@ -742,50 +742,47 @@ constitute the assertions of the program. C is the directive being
executed. executed.
The language of the assertions P is: The language of the assertions P is:
#+BEGIN_SRC #+BEGIN_SRC
P ::= true | false | a < b | P₁ ∧ P₂ | P₁ P₂ | ~P P ::= true | false | a < b | P_{1} \wedge P_{2} | P_{1} \lor P_{2} | \notP
#+END_SRC #+END_SRC
where a and b are numbers. where a and b are numbers.
In the Hoare rules assertions could also take the form of In the Hoare rules assertions could also take the form of
#+BEGIN_SRC #+BEGIN_SRC
P ::= ∀i. P | ∃i. P | P₁ ⇒ P₂ P ::= \forall i. P | \exists i. P | P_{1} \Rightarrow P_{2}
#+END_SRC #+END_SRC
where i is a logical variable, but assertions of these kinds increases where i is a logical variable, but assertions of these kinds increases
the complexity of the symbolic engine. the complexity of the symbolic engine.
Execution follows the rules of Hoare logic: Execution follows the rules of Hoare logic:
- Empty statement : - Empty statement :
\begin{verbatim} \begin{mathpar}
———————————— \infer{ }
{P}/skip/{P} { \{P\} skip \{P\} }
\end{verbatim} \end{mathpar}
- Assignment statement : The truthness of P[a/x] is equivalent to the - Assignment statement : The truthness of P[a/x] is equivalent to the
truth of {P} after the assignment. truth of {P} after the assignment.
\begin{verbatim} \begin{mathpar}
———————————— \infer{ }
{P[a/x]}x:=a{P} { \{P[a/x]\}x:=a\{P\} }
\end{verbatim} \end{mathpar}
- Composition : c₁ and c₂ are directives that are executed in order; - Composition : c₁ and c₂ are directives that are executed in order;
{Q} is the /midcondition/. {Q} is called the /midcondition/.
\begin{verbatim} \begin{mathpar}
{P}c₁{R}, {R}c₂{Q} \infer { \{P\}c_1\{R\}, \{R\}c_2\{Q\} }
—————————————————— { \{P\}c₁;c₂\{Q\} }
{P}c₁;c₂{Q} \end{mathpar}
\end{verbatim}
- Conditional : - Conditional :
\begin{verbatim} \begin{mathpar}
{P∧b}c₁{Q}, {P∧~b}c₂{Q} \infer { \{P \wedge b \} c_1 \{Q\}, \{P\wedge\not b\}c_2\{Q\} }
———————————————————————— { \{P\}if b then c_1 else c_2\{Q\} }
{P}if b then c₁ else c₂{Q} \end{mathpar}
\end{verbatim}
- Loop : {P} is the loop invariant. After the loop is finished /P/ - Loop : {P} is the loop invariant. After the loop is finished /P/
holds and ~b caused the loop to end. holds and ¬̸b caused the loop to end.
\begin{verbatim} \begin{mathpar}
{P∧b}c{P} \infer { \{P \wedge b \}c\{P\} }
———————————————————————— { \{P\} while b do c \{P \wedge \neg b\} }
{P}while b do c{P∧~b} \end{mathpar}
\end{verbatim}
Even if the semantics of symbolic execution engines are well defined, Even if the semantics of symbolic execution engines are well defined,
the user may run into different complications when applying such the user may run into different complications when applying such
@ -1176,22 +1173,24 @@ possible values \emph{S} and a pair of source and target decision trees and
in case the two trees are not equivalent it returns a counter example. in case the two trees are not equivalent it returns a counter example.
The algorithm respects the following correctness statement: The algorithm respects the following correctness statement:
% TODO: we have to define what \covers mean for readers to understand the specifications \begin{comment}
% (or we use a simplifying lie by hiding \covers in the statements). TODO: we have to define what \coversTEX mean for readers to understand the specifications
(or we use a simplifying lie by hiding \coversTEX in the statements).
\end{comment}
\begin{align*} \begin{align*}
\Equiv S {C_S} {C_T} \emptyqueue = \Yes \;\land\; \covers {C_T} S \EquivTEX S {C_S} {C_T} \emptyqueue = \YesTEX \;\land\; \coversTEX {C_T} S
& \implies & \implies
\forall v_S \approx v_T \in S,\; C_S(v_S) = C_T(v_T) \forall v_S \approx v_T \in S,\; C_S(v_S) = C_T(v_T)
\\ \\
\Equiv S {C_S} {C_T} \emptyqueue = \No {v_S} {v_T} \;\land\; \covers {C_T} S \EquivTEX S {C_S} {C_T} \emptyqueue = \NoTEX {v_S} {v_T} \;\land\; \coversTEX {C_T} S
& \implies & \implies
v_S \approx v_T \in S \;\land\; C_S(v_S) \neq C_T(v_T) v_S \approx v_T \in S \;\land\; C_S(v_S) \neq C_T(v_T)
\end{align*} \end{align*}
Our equivalence-checking algorithm $\Equiv S {C_S} {C_T} G$ is Our equivalence-checking algorithm $\EquivTEX S {C_S} {C_T} G$ is
a exactly decision procedure for the provability of the judgment a exactly decision procedure for the provability of the judgment
$(\Equivrel S {C_S} {C_T} G)$, defined below. $(\EquivTEX S {C_S} {C_T} G)$, defined below.
\begin{mathpar} \begin{mathpar}
\begin{array}{l@{~}r@{~}l} \begin{array}{l@{~}r@{~}l}
& & \text{\emph{constraint trees}} \\ & & \text{\emph{constraint trees}} \\
@ -1214,26 +1213,26 @@ $(\Equivrel S {C_S} {C_T} G)$, defined below.
\end{array} \end{array}
\\ \\
\infer{ } \infer{ }
{\Equivrel \emptyset {C_S} {C_T} G} {\EquivTEX \emptyset {C_S} {C_T} G}
\infer{ } \infer{ }
{\Equivrel S \Failure \Failure \emptyqueue} {\EquivTEX S \Failure \Failure \emptyqueue}
\infer \infer
{\trel {t_S} {t_T}} {\trel {t_S} {t_T}}
{\Equivrel S {\Leaf {t_S}} {\Leaf {t_T}} \emptyqueue} {\EquivTEX S {\Leaf {t_S}} {\Leaf {t_T}} \emptyqueue}
\infer \infer
{\forall i,\; {\forall i,\;
\Equivrel \EquivTEX
{(S \land a = K_i)} {(S \land a = K_i)}
{C_i} {\trim {C_T} {a = K_i}} G {C_i} {\trim {C_T} {a = K_i}} G
\\ \\
\Equivrel \EquivTEX
{(S \land a \notin \Fam i {K_i})} {(S \land a \notin \Fam i {K_i})}
\Cfb {\trim {C_T} {a \notin \Fam i {K_i}}} G \Cfb {\trim {C_T} {a \notin \Fam i {K_i}}} G
} }
{\Equivrel S {\EquivTEX S
{\Switch a {\Fam i {K_i, C_i}} \Cfb} {C_T} G} {\Switch a {\Fam i {K_i, C_i}} \Cfb} {C_T} G}
\begin{comment} \begin{comment}
@ -1244,30 +1243,30 @@ $(\Equivrel S {C_S} {C_T} G)$, defined below.
\infer \infer
{C_S \in {\Leaf t, \Failure} {C_S \in {\Leaf t, \Failure}
\\ \\
\forall i,\; \Equivrel {(S \land a \in D_i)} {C_S} {C_i} G \forall i,\; \EquivTEX {(S \land a \in D_i)} {C_S} {C_i} G
\\ \\
\Equivrel {(S \land a \notin \Fam i {D_i})} {C_S} \Cfb G} \EquivTEX {(S \land a \notin \Fam i {D_i})} {C_S} \Cfb G}
{\Equivrel S {\EquivTEX S
{C_S} {\Switch a {\Fam i {D_i} {C_i}} \Cfb} G} {C_S} {\Switch a {\Fam i {D_i} {C_i}} \Cfb} G}
\infer \infer
{\Equivrel S {C_0} {C_T} {G, (t_S = 0)} {\EquivTEX S {C_0} {C_T} {G, (t_S = 0)}
\\ \\
\Equivrel S {C_1} {C_T} {G, (t_S = 1)}} \EquivTEX S {C_1} {C_T} {G, (t_S = 1)}}
{\Equivrel S {\EquivTEX S
{\Guard {t_S} {C_0} {C_1}} {C_T} G} {\Guard {t_S} {C_0} {C_1}} {C_T} G}
\infer \infer
{\trel {t_S} {t_T} {\trel {t_S} {t_T}
\\ \\
\Equivrel S {C_S} {C_b} G} \EquivTEX S {C_S} {C_b} G}
{\Equivrel S {\EquivTEX S
{C_S} {\Guard {t_T} {C_0} {C_1}} {(t_S = b), G}} {C_S} {\Guard {t_T} {C_0} {C_1}} {(t_S = b), G}}
\end{mathpar} \end{mathpar}
* Correctness of the algorithm * Correctness of the algorithm
Running a program tₛ or its translation 〚tₛ〛 against an input vₛ Running a program tₛ or its translation 〚tₛ〛 against an input vₛ
produces as a result a result /r/ in the following way: produces as a result /r/ in the following way:
| ( 〚tₛ〛ₛ(vₛ) = Cₛ(vₛ) ) → r | ( 〚tₛ〛ₛ(vₛ) = Cₛ(vₛ) ) → r
| tₛ(vₛ) → r | tₛ(vₛ) → r
Likewise Likewise
@ -1342,6 +1341,7 @@ and an optional fallback.
Failure is emitted only when the patterns don't cover the whole set of Failure is emitted only when the patterns don't cover the whole set of
possible input values /S/. The fallback is not needed when the user possible input values /S/. The fallback is not needed when the user
doesn't use a wildcard pattern. doesn't use a wildcard pattern.
%%% Give example of thing
| Cₛ ::= Leaf bb | Node(a, (Kᵢ → Cᵢ)^{i∈S} , C?) | Cₛ ::= Leaf bb | Node(a, (Kᵢ → Cᵢ)^{i∈S} , C?)
| a ::= Here | n.a | a ::= Here | n.a
@ -1352,17 +1352,17 @@ Are K and Here clear here?
\end{comment} \end{comment}
We define the decomposition matrix /mₛ/ as We define the decomposition matrix /mₛ/ as
| SMatrix mₛ := (aⱼ)^{j∈J}, ((pᵢⱼ)^{j∈J} → bbᵢ)^{i∈I} | SMatrix mₛ := (aⱼ)^{j∈J}, ((p_{ij})^{j∈J} → bbᵢ)^{i∈I}
\begin{comment} \begin{comment}
Correggi prendendo in considerazione l'accessor Correggi prendendo in considerazione l'accessor
\end{comment} \end{comment}
We define the decision tree of source programs We define the decision tree of source programs
[|tₛ|] 〚tₛ〛
in terms of the decision tree of pattern matrices in terms of the decision tree of pattern matrices
[|mₛ|] 〚mₛ〛
by the following: by the following:
〚((pᵢ → bbᵢ)^{i∈I}〛 := 〚(Root), (pᵢ → bbᵢ)^{i∈I} 〛 # i ∈ I 〚((pᵢ → bbᵢ)^{i∈I}〛 := 〚(Root), (pᵢ → bbᵢ)^{i∈I} 〛
decision tree computed from pattern matrices respect the following invariant: decision tree computed from pattern matrices respect the following invariant:
| ∀v (vᵢ)^{i∈I} = v(aᵢ)^{i∈I} → 〚m〛(v) = m(vᵢ)^{i∈I} for m = ((aᵢ)^{i∈I}, (rᵢ)^{i∈I}) | ∀v (vᵢ)^{i∈I} = v(aᵢ)^{i∈I} → 〚m〛(v) = m(vᵢ)^{i∈I} for m = ((aᵢ)^{i∈I}, (rᵢ)^{i∈I})
@ -1385,10 +1385,95 @@ Base cases:
2. [| (aⱼ)ʲ, ∅ |] := Failure 2. [| (aⱼ)ʲ, ∅ |] := Failure
Regarding non base cases: Regarding non base cases:
We define Let's first define
| let Idx(k) = [0; arity(k)[ | let Idx(k) := [0; arity(k)[
| let First(∅) = ⊥ | let First(∅) := ⊥
| let First((aⱼ)ʲ) = a_{min(j)} ## where j ∈ J ≠ ∅ | let First((aⱼ)ʲ) := a_{min(j∈J≠∅)}
\[
m := ((a_i)^i ((p_{ij})^i \to e_j)^{ij})
\]
\[
(k_k)^k := headconstructor(p_{i0})^i
\]
\begin{equation}
\begin{align}
Groups(m) := ( k_k \to ((a)_{0.l})^{l \in Idx(k_k)} +++ (a_i)^{i \in I\backslash \{0\} }), \\
( if p_{0j} is k(q_l) then \\
(qₗ)^{l \in Idx(k_k)} +++ (p_{ij})^{i \in I\backslash \{0\}} \to e_j \\
if p_{0j} is \_ then \\
(\_)^{l \in Idx(k_k)} +++ (p_{ij})^{i \in I\backslash \{0\}} \to e_j \\
else \bot )^j ), \\
((a_i)^{i \in I\backslash \{0\}}, ((p_{ij})^{i \in I\backslash \{0\}} \to eⱼ if p_{0j} is \_ else \bot)^{j \in J})
\end{align}
\end{equation}
Groups(m) is an auxiliary function that decomposes a matrix m into
submatrices, according to the head constructor of their first pattern.
Groups(m) returns one submatrix m_r for each head constructor k that
occurs on the first row of m, plus one "wildcard submatrix" m_{wild}
that matches on all values that do not start with one of those head
constructors.
Intuitively, m is equivalent to its decompositionin the following
sense: if the first pattern of an input vector (v_i)^i starts with one
of the head constructors k, then running (v_i)^i against m is the same
as running it against the submatrix m_k; otherwise (its head
constructor is none of the k) it is equivalent to running it against
the wildcard submatrix.
We formalize this intuition as follows:
Lemma (Groups):
Let \[m\] be a matrix with \[Groups(m) = (k_r \to m_r)^k, m_{wild}\].
For any value vector \[(v_i)^l\] such that \[v_0 = k(v'_l)^l\] for some
constructor k,
we have:
\[
if k = kₖ for some k then
m(vᵢ)ⁱ = mₖ((v'ₗ)ˡ +++ (vᵢ)^{i∈I\backslash \{0\}})
else
m(vᵢ)ⁱ = m_{wild}(vᵢ)^{i∈I\backslash \{0\}}
\]
*** Proof:
Let \[m\] be a matrix with \[Group(m) = (k_r \to m_r)^k, m_{wild}\].
Let \[(v_i)^i\] be an input matrix with \[v_0 = k(v'_l)^l\] for some k.
We proceed by case analysis:
- either k is one of the kₖ for some k
- or k is none of the (kₖ)ᵏ
Both m(vᵢ)ⁱ and mₖ(vₖ)ᵏ are defined as the first matching result of
a family over each row rⱼ of a matrix
We know, from the definition of
Groups(m), that mₖ is
\[
((a){0.l})^{l∈Idx(kₖ)} +++ (aᵢ)^{i∈I\backslash \{0\}}),
(
if p_{0j} is k(qₗ) then
(qₗ)ˡ +++ (p_{ij})^{i∈I\backslash \{0\}} → eⱼ
if p_{0j} is _ then
(_)ˡ +++ (p_{ij})^{i∈I\backslash \{0\}} → eⱼ
else ⊥
\]
By definition, m(vᵢ)ⁱ is
m(vᵢ)ⁱ = First(rⱼ(vᵢ)ⁱ)ʲ for m = ((aᵢ)ⁱ, (rⱼ)ʲ)
(pᵢ)ⁱ (vᵢ)ⁱ = {
if p₀ = k(qₗ)ˡ, v₀ = k'(v'ₖ)ᵏ, k=Idx(k') and l=Idx(k)
if k ≠ k' then ⊥
if k = k' then ((qₗ)ˡ +++ (pᵢ)^{i∈I\backslash \{0\}}) ((v'ₖ)ᵏ +++ (vᵢ)^{i∈I\backslash \{0\}})
if p₀ = (q₁|q₂) then
First( (q₁pᵢ^{i∈I \backslash \{0\}}) vᵢ^{i∈I \backslash \{0\}}, (q₂pᵢ^{i∈I \backslash \{0\}}) vᵢ^{i∈I \backslash \{0\}} )
}
For this reason, if we can prova that
| ∀j, rⱼ(vᵢ)ⁱ = r'ⱼ((v'ₖ)ᵏ ++ (vᵢ)ⁱ)
it follows that
| m(vᵢ)ⁱ = mₖ((v'ₖ)ᵏ ++ (vᵢ)ⁱ)
from the above definition.
We can also show that aᵢ = a){0.l}ˡ +++ a_{i∈I\backslash \{0\}} because v(a₀) = K(v(a){0.l})ˡ)
@ -1426,7 +1511,10 @@ an accessor → π relation (In other words???)
Covering lemma: Covering lemma:
∀a,π covers(Cₜ,S) => covers(C_{t/a→π}, (S∩a→π)) ∀a,π covers(Cₜ,S) => covers(C_{t/a→π}, (S∩a→π))
Uᵢπⁱ ≈ Uᵢπ'∩(a→π) ≈ (Uᵢπ')∩(a→π) %% # TODO swap π and π' Uᵢπⁱ ≈ Uᵢπ'∩(a→π) ≈ (Uᵢπ')∩(a→π) %%
\begin{comment}
Should I swap π and π'
\end{comment}
\subsubsection Proof of equivalence checking \subsubsection Proof of equivalence checking
The equivalence checking algorithm takes as parameters an input space The equivalence checking algorithm takes as parameters an input space
@ -1462,12 +1550,16 @@ TODO: explain:
\end{comment} \end{comment}
We proceed by case analysis: We proceed by case analysis:
1. equiv(∅, Cₛ, Cₜ) := Yes
\begin{comment} \begin{comment}
Devo spiegarlo? I start numbering from zero to leave the numbers as they were on the blackboard, were we skipped some things
I think the unreachable case should go at the end.
\end{comment} \end{comment}
In the other subcases S is always non-empty.
0. in case of unreachable: Cₛ(vₛ) = Absurd(Unreachable) ≠ Cₜ(vₜ) ∀vₛ,vₜ 0. in case of unreachable: Cₛ(vₛ) = Absurd(Unreachable) ≠ Cₜ(vₜ) ∀vₛ,vₜ
1. In the case of an empty input space
| equiv(∅, Cₛ, Cₜ) := Yes
and that is trivial to prove because there is no pair of values (vₛ, vₜ) that could be
tested against the decision trees.
In the other subcases S is always non-empty.
2. equiv(S, Failure, Failure) := Yes 2. equiv(S, Failure, Failure) := Yes
the statement holds because of equality between Failure nodes in the statement holds because of equality between Failure nodes in
the case of every possible value /v/. the case of every possible value /v/.
@ -1491,7 +1583,7 @@ In the other subcases S is always non-empty.
| equiv(Sᵢ, Cₛ, Cₜᵢ) = No(vₛ, vₜ) for some minimal k∈I | equiv(Sᵢ, Cₛ, Cₜᵢ) = No(vₛ, vₜ) for some minimal k∈I
4. equiv(S, Node(a, (kᵢ → Cₛᵢ)ⁱ, C_{sf}), Cₜ) := 4. equiv(S, Node(a, (kᵢ → Cₛᵢ)ⁱ, C_{sf}), Cₜ) :=
let π' = ⋃π(kᵢ) ∀i in let π' = ⋃π(kᵢ) ∀i in
Forall(equiv( S∩(a→π(kᵢ)ⁱ), Cₛᵢ, C_{t/a→π(kᵢ)})ⁱ +++ equiv(S∩(a→π(kᵢ)), Cₛ, C_{/a¬̸π'})) Forall(equiv( S∩(a→π(kᵢ)ⁱ), Cₛᵢ, C_{t/a→π(kᵢ)})ⁱ +++ equiv(S∩(a→π(kᵢ)), Cₛ, C_{/a̸¬̸π'}))
The statement holds because: The statement holds because:
a. Forall(equiv( S∩(a→π(kᵢ)ⁱ), Cₛᵢ, C_{t/a→π(kᵢ)})ⁱ = Yes a. Forall(equiv( S∩(a→π(kᵢ)ⁱ), Cₛᵢ, C_{t/a→π(kᵢ)})ⁱ = Yes
In the yes case let's reason by case analysis: In the yes case let's reason by case analysis:
@ -1503,9 +1595,10 @@ In the other subcases S is always non-empty.
Putting all together: Putting all together:
Cₛ(vₛ) = Cₛᵢ(vₛ) = C_{t/a→πᵢ}(vₜ) = Cₜ(vₜ) Cₛ(vₛ) = Cₛᵢ(vₛ) = C_{t/a→πᵢ}(vₜ) = Cₜ(vₜ)
ii. or k∉(kᵢ)ⁱ ??? ii. when k∉(kᵢ)ⁱ ???
b. Forall(...) = No(vₛ, vₜ) b. Forall(...) = No(vₛ, vₜ)
for a minimum k, equiv(Sₖ, Cₛₖ, C_{t/a→πₖ} = No(vₛ, vₜ) for a minimum k, equiv(Sₖ, Cₛₖ, C_{t/a→πₖ} = No(vₛ, vₜ)
then Cₛₖ(vₛ) ≠ C_{t/a→πₖ}(vₜ) and C_{t/a→πₖ}(vₜ) = Cₜ(vt) then Cₛₖ(vₛ) ≠ C_{t/a→πₖ}(vₜ) and C_{t/a→πₖ}(vₜ) = Cₜ(vt)
=> (Cₛₖ(vₛ) = Cₛ(vₛ)) ≠ Cₜ(vₜ) # Same for fallback? => (Cₛₖ(vₛ) = Cₛ(vₛ)) ≠ Cₜ(vₜ)
# Same for fallback?

BIN
tesi/tesi_unicode.pdf Normal file

Binary file not shown.