Minor edits to 'lattices 2'
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
This commit is contained in:
		
							parent
							
								
									711b01175d
								
							
						
					
					
						commit
						04f12b545d
					
				| @ -16,7 +16,7 @@ of variables in a program. | ||||
| 
 | ||||
| At the end of that post, I introduced a source of complexity: the "full" | ||||
| lattices that we want to use for the program analysis aren't signs or numbers, | ||||
| but maps of states and variables to lattices-based states. The full lattice | ||||
| but maps of states and variables to lattice-based descriptions. The full lattice | ||||
| for sign analysis might something in the form: | ||||
| 
 | ||||
| {{< latex >}} | ||||
| @ -25,12 +25,12 @@ for sign analysis might something in the form: | ||||
| 
 | ||||
| Thus, we have to compare and find least upper bounds (e.g.) of not just | ||||
| signs, but maps! Proving the various lattice laws for signs was not too | ||||
| challenging, but for for a two-level map like \(\text{info}\) above, we'd | ||||
| need to do a lot more work. We need tools to build up such complicated lattices! | ||||
| challenging, but for for a two-level map like \(\text{Info}\) above, we'd | ||||
| need to do a lot more work. We need tools to build up such complicated lattices. | ||||
| 
 | ||||
| The way to do this, it turns out, is by using simpler lattices as building blocks. | ||||
| To start with, let's take a look at a very simple way of combining lattices: | ||||
| taking the Cartesian product. | ||||
| taking the [Cartesian product](https://mathworld.wolfram.com/CartesianProduct.html). | ||||
| 
 | ||||
| ### The Cartesian Product Lattice | ||||
| 
 | ||||
| @ -39,12 +39,13 @@ post, each lattice comes equipped with a "least upper bound" operator \((\sqcup) | ||||
| and a "greatest lower bound" operator \((\sqcap)\). Since we now have two lattices, | ||||
| let's use numerical suffixes to disambiguate between the operators | ||||
| of the first and second lattice: \((\sqcup_1)\) will be the LUB operator of | ||||
| the first lattice \(L_1\), and \((\sqcup_2)\) of the second lattice \(L_2\). | ||||
| the first lattice \(L_1\), and \((\sqcup_2)\) of the second lattice \(L_2\), | ||||
| and so on. | ||||
| 
 | ||||
| Then, let's take the Cartesian product of the elements of \(L_1\) and \(L_2\); | ||||
| mathematically, we'll write this as \(L_1 \times L_2\), and in Agda, we can | ||||
| just use the standard [`Data.Product`](https://agda.github.io/agda-stdlib/master/Data.Product.html) | ||||
| module. In Agda, I'll define the lattice as another [parameterized module](https://agda.readthedocs.io/en/latest/language/module-system.html#parameterised-modules). Since both \(L_1\) and \(L_2\) | ||||
| module. Then, I'll define the lattice as another [parameterized module](https://agda.readthedocs.io/en/latest/language/module-system.html#parameterised-modules). Since both \(L_1\) and \(L_2\) | ||||
| are lattices, this parameterized module will require `IsLattice` instances | ||||
| for both types: | ||||
| 
 | ||||
| @ -52,7 +53,7 @@ for both types: | ||||
| 
 | ||||
| Elements of \(L_1 \times L_2\) are in the form \((l_1, l_2)\), where | ||||
| \(l_1 \in L_1\) and \(l_2 \in L_2\). The first thing we can get out of the | ||||
| way is define what it means for two such elements to be equal. Recall that | ||||
| way is defining what it means for two such elements to be equal. Recall that | ||||
| we opted for a [custom equivalence relation]({{< relref "01_spa_agda_lattices#definitional-equality" >}}) | ||||
| instead of definitional equality to allow similar elements to be considered | ||||
| equal; we'll have to define a similar relation for our new product lattice. | ||||
| @ -75,7 +76,7 @@ relations. | ||||
| 
 | ||||
| {{< codelines "Agda" "agda-spa/Lattice/Prod.agda" 42 48 >}} | ||||
| 
 | ||||
| In fact, defining \((\sqcup)\) and \((\sqcap)\) by simply applying the | ||||
| Defining \((\sqcup)\) and \((\sqcap)\) by simply applying the | ||||
| corresponding operators from \(L_1\) and \(L_2\) seems quite natural as well. | ||||
| 
 | ||||
| {{< latex >}} | ||||
| @ -88,8 +89,8 @@ In Agda: | ||||
| {{< codelines "Agda" "agda-spa/Lattice/Prod.agda" 50 54 >}} | ||||
| 
 | ||||
| All that's left is to prove the various (semi)lattice properties. Intuitively, | ||||
| we can see that since the "combined" operator `_≈_` just independently applies | ||||
| the element operators `_≈₁_` and `_≈₂_`, as long as they are idempotent, | ||||
| we can see that since the "combined" operator `_⊔_` just independently applies | ||||
| the element operators `_⊔₁_` and `_⊔₂_`, as long as they are idempotent, | ||||
| commutative, and associative, so is the "combined" operator itself. | ||||
| Moreover, the proofs that `_⊔_` and `_⊓_` form semilattices are identical | ||||
| up to replacing \((\sqcup)\) with \((\sqcap)\). Thus, in Agda, we can write | ||||
| @ -98,8 +99,9 @@ that these operators obey the semilattice laws). | ||||
| 
 | ||||
| {{< codelines "Agda" "agda-spa/Lattice/Prod.agda" 56 82 >}} | ||||
| 
 | ||||
| Similarly to the semilattice properties, proving lattice properties boils | ||||
| down to applying the lattice properties of \(L_1\) and \(L_2\) to | ||||
| individual components. | ||||
| Above, I used `f₁` to stand for "either `_⊔₁_` or `_⊓₁_`", and similarly | ||||
| `f₂` for "either `_⊔₂_` or `_⊓₂_`". Much like the semilattice properties, | ||||
| proving lattice properties boils down to applying the lattice properties of | ||||
| \(L_1\) and \(L_2\) to individual components. | ||||
| 
 | ||||
| {{< codelines "Agda" "agda-spa/Lattice/Prod.agda" 84 96 >}} | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user