Write some more in combining lattices

Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
This commit is contained in:
Danila Fedorin 2024-05-30 22:41:15 -07:00
parent b2b225f4ae
commit 4c70e61a14
2 changed files with 60 additions and 1 deletions

View File

@ -70,6 +70,7 @@ things we're trying to rank depend on the sort of analysis we're trying to
perform. Since I introduced sign analysis, we're ranking signs like `+` and `-`. perform. Since I introduced sign analysis, we're ranking signs like `+` and `-`.
For other analyses, the elements will be different. The _comparison_, however, For other analyses, the elements will be different. The _comparison_, however,
will be a permanent fixture. will be a permanent fixture.
{#specificity}
Suppose now that we have some program analysis, and we're feeding it some input Suppose now that we have some program analysis, and we're feeding it some input
information. Perhaps we're giving it the signs of variables `x` and `y`, and information. Perhaps we're giving it the signs of variables `x` and `y`, and

View File

@ -85,7 +85,16 @@ corresponding operators from \(L_1\) and \(L_2\) seems quite natural as well.
(l_1, l_2) \sqcap (j_1, j_2) \triangleq (l_1 \sqcap_1 j_1, l_2 \sqcap_2 j_2) (l_1, l_2) \sqcap (j_1, j_2) \triangleq (l_1 \sqcap_1 j_1, l_2 \sqcap_2 j_2)
{{< /latex >}} {{< /latex >}}
In Agda: As an example, consider the product lattice \(\text{Sign}\times\text{Sign}\),
which is made up of pairs of signs that we talked about in the previous
post. Two elements of this lattice are \((+, +)\) and \((+, -)\). Here's
how the \((\sqcup)\) operation is evaluated on them:
{{< latex >}}
(+, +) \sqcup (+, -) = (+ \sqcup + , + \sqcup -) = (+ , \top)
{{< /latex >}}
In Agda, the definition is written very similarly to its mathematical form:
{{< codelines "Agda" "agda-spa/Lattice/Prod.agda" 50 54 >}} {{< codelines "Agda" "agda-spa/Lattice/Prod.agda" 50 54 >}}
@ -106,3 +115,52 @@ proving lattice properties boils down to applying the lattice properties of
\(L_1\) and \(L_2\) to individual components. \(L_1\) and \(L_2\) to individual components.
{{< codelines "Agda" "agda-spa/Lattice/Prod.agda" 84 96 >}} {{< codelines "Agda" "agda-spa/Lattice/Prod.agda" 84 96 >}}
This concludes the definition of the product lattice, which is made up of
two other lattices. If we have a type of analysis that can be expressed as
{{< sidenote "right" "pair-note" "a pair of two signs," >}}
Perhaps the signs are the smallest and largest possible values of a variable.
{{< /sidenote >}} for example, we won't have to do all the work of
proving the (semi)lattice properties of those pairs. In fact, we can build up
even bigger data structures. By taking a product a product twice, like
\(L_1 \times (L_2 \times L_3)\), we can construct a lattice of 3-tuples. Any
of the lattices involved in that product can itself be a product; we can
therefore create lattices out of arbitrary bundles of data, so long as
the smallest pieces that make up the bundles are themselves lattices.
Products will come very handy a bit later in this series. For now though,
our goal is to create another type of lattice: the map lattice. We will
take the same approach we did with products: assuming the elements of the
map are lattices, we'll prove that the map itself is a lattice. Then, just
like we could put products inside products when building up lattices, we'll
be able to put a map inside a map. This will allow us to represent the
\(\text{Info}\) lattice, which is a map of maps.
### The Map Lattice
When I say "map", what I really means is something that associates keys with
values, like [dictionaries in Python](https://docs.python.org/3/tutorial/datastructures.html#dictionaries).
This data structure need not have a value for every possible key; a very precise
author might call such a map a "partial map". We might have a map
whose value (in Python-ish notation) is `{ "x": +, "y": - }`. Such a map states
that the sign of the variable `x` is `+`, and the sign of variable `y` is
`-`. Another possible map is `{ "y": +, "z": - }`; this one states that
the sign of `y` is `+`, and the sign of another variable `z` is `-`.
Let's start thinking about what sorts of lattices our maps will be.
The thing that [motivated our introduction]({{< relref "01_spa_agda_lattices#specificity" >}})
of lattices was comparing them by "specificity", so let's try figure out how
to compare maps. For that, we can begin small, by looking at singleton maps.
If we have `{"x": +}` and `{"x": }`, which one of them is smaller? Well, wehave previously established that `+` is more specific (and thus less than) ``. Thus, it shouldn't be too much of a stretch
to say that for singleton maps of the same key, the one with the smaller
value is smaller.
Now, what about a pair of singleton maps like `{"x": +}` and `{"y": }`? Among
these two, each contains some information that the other does not. Although the
value of `y` is larger than the value of `x`, it describes a different key, so
it seems wrong to use that to call the `y`-singleton "larger". Let's call
these maps incompatible, then. More generally, if we have two maps and each one
has a key that the other doesn't, we can't compare them.
If only one map has a unique key, though, things are different. Take for
instance `{"x": +}` and `{"x": +, "y": +}`.