Improving the Compositionality of Separation Algebras Aquinas Hobor? National University of Singapore Abstract. We show how to improve one of the constructors of separation algebras to increase modularity and expressibility. Our technique has advantages for both paper and mechanized proofs. Our results are implemented in Coq. 1 Introduction Separation algebras are mathematical structures that track resource accounting and are most commonly used in semantic models of separation logic [1]. Dockins et al. showed that new separation algebras could be constructed from old ones by using some of the standard constructors of category theory [2]. This modular approach is extremely practical, especially in a machine-checked setting, and often provides theoretical insight. However, one of the common constructors presented by Dockins, the so-called “lift” operator, is not as modular as one could hope for because it limits the expressibility of the composed objects in an inconvenient way. Moreover, its implementation in Coq leads to undue hassle due to an awkwardly-placed dependent type. We present a new pair of constructors whose composition is the lift operator but that allow for greater modularity “in the middle”. Our key insight is that while the intermediate structure is not a separation algebra, it is a well-behaved structure in its own right, and by utilizing this structure directly we can allow for greater expressibility than we can by skipping over it. In addition, the new structure puts the dependent type in a much more convenient location, allowing for a much smoother mechanization. 2 Separation Algebras There are several related definitions of separation algebras; here we use a variant called a disjoint multi-unit separation algebra (DSA) [2]. Briefly, a DSA is a set S and an associated three-place partial join relation ⊕, written x ⊕ y = z, such that: (a) A function: x ⊕ y = z1 ⇒ x ⊕ y = z2 ⇒ z1 = z2 (b) Commutative: x ⊕ y = y ⊕ x (c) Associative: x ⊕ (y ⊕ z) = (x ⊕ y) ⊕ z (d) Cancellative: x1 ⊕ y = z ⇒ x2 ⊕ y = z ⇒ x1 = x2 (e) Multiple units: ∀x. ∃ux . x ⊕ ux = x (f) Disjointness: x ⊕ x = y ⇒ x = y We say that x ∈ S is an identity if ∀y, z. x ⊕ y = z ⇒ y = z. Observe that “identity” is much stronger than “unit” as given in axiom (e): a unit ux need only behave as an ? Supported by a Lee Kuan Yew Postdoctoral Fellowship. 2 identity for the associated element x; the axiom says nothing about how ux behaves with other elements. However, as it happens, the axioms together imply that all units are identities. Thus, x is an identity if and only if x ⊕ x = x. The elements in S can be partitioned into equivalence classes indexed by the identity elements. For each identity element i, two elements a and b are in the same equivalence class if a ⊕ i and b ⊕ i is defined. Within an equivalence class there is only a single identity; however, since the ⊕ operation is partial, multiple identities are possible for the set S as a whole. Elements from distinct equivalence classes never join together. 3 Constructors Over Separation Algebras Dockins develops a series of standard constructions for building DSAs. One simple construction is the discrete DSA, where any set S is given DSA structure by defining s1 ⊕ = s2 = ≡ s3 s1 = s2 = s3 (1) In the discrete DSA, every element is an identity, and no distinct elements join together. More powerful is the ability to build complicated DSAs from simpler DSAs, including products, sums, functions, etc. Most of these constructions define the joining operation in the “obvious” way. For example, if (A, ⊕A ) and (B, ⊕B ) are two DSAs, then the join function for the product DSA on A × B is defined componentwise: (a1 , b1 ) ⊕A×B (a2 , b2 ) = (a3 , b3 ) ≡ (a1 ⊕A a2 = a3 ) ∧ (b1 ⊕B b2 = b3 ) (2) Similarly, the function DSA from a set A to a DSA (B, ⊕B ) is defined pointwise: f ⊕A→B g = h ≡ ∀a. f (a) ⊕B g(a) = h(a) (3) Dockins also defines a “lift” operator, which is a kind of coercion between multiunit separation algebras and single-unit separation algebras. Hereafter we will call this the “smash” operator because of its relationship to the “smash product” of category theory. Starting from a DSA (A, ⊕) one first constructs the related set A+ as follows: A+ ≡ {a ∈ A | ¬identity a} (4) That is, A+ is obtained from A by removing all the identity elements over ⊕. One then adds some distinguished element ⊥ 6∈ A+ to reach the set A+ ⊥ and defines the join relation ⊕⊥ as the least relation satisfying the following rules: 1. ⊥ ⊕⊥ a = a 2. a ⊕⊥ ⊥ = a 3. a1 ⊕ a2 = a3 (5) → a1 ⊕ ⊥ a2 = a3 One common use for the smash operator is to construct a separation algebra for resource sharing in a concurrent language as follows. We start with a share model: a separation algebra (S, ⊕S ) that models what kinds of sharing we would like to support. One simple share model defines S = {q | 0 ≤ q ≤ 1} and ⊕S as partial addition (i.e., 3 undefined when the sum is greater than 1)1 . In a concurrent setting, a share of 1 (of some resource) will denote full ownership; 0 will denote no ownership; and 0 < x < 1 will denote partial ownership. Let L be a set of heap locations (addresses) and V be a set of values in our operational semantics. Now we can define heaps H as follows: H ≡ L → (S × V= )⊥ (6) This simple-looking equation describes both the type of heaps (functions from locations to a pointed set containing pairs of shares and values) and how the join function should be constructed: start with the function constructor (3) from L to the smashed (5) product (2) of shares S and values V under the discrete construction (1). That is, each location is associated with either the distinguished element ⊥, indicating that the thread has now ownership, or by a nonempty (¬identity) pair of share and value. Using the constructors guarantees that axioms (a)–(f) hold on heaps H without having to prove them directly. 4 The Problem with Smash As elegant as equation (6) is, its form conceals some problems, particularly with regard to the smash operator. The first problem is the location of the side condition from equation (4): that is, the side condition that (S × V= )+ contains no identity elements. A quick reflection reveals that under the product DSA constructor a pair is not an identity if and only if at least one of its components is not be an identity, i.e.: ¬identity(a, b) ⇔ (¬identity a) ∨ (¬identity b) (7) Since every element in V= is an identity, however, for (S×V= )+ we have the following: ¬identity(s, v) ⇔ ¬identity s (8) In other words, in set theory (S × V= )+ equals S +× V= . However, in type theory the two are not quite equal since the non-identity side condition is carried around via a dependent (Σ-) type, and the definitions differ due to where this is placed. That is, (S × V= )+ ≡ Σp : (S × V). ¬identity p (9) is what one gets by applying the smash operator, instead of the more preferable S +× V= ≡ (Σs : S. ¬identity s) × V (10) One reason to prefer equation (10) over equation (9) is that the dependent type is “closer” to the object being restricted. Consider the operation of updating a heap cell: one takes apart a share/value pair (s, v) and reconstitutes the new pair (s, v 0 ). If we are using equation (9), we discover a new proof obligation during reconstitution: identity (s, v) ⇒ identity (s, v 0 ) 1 Dockins develops more powerful kinds of share models, but this is sufficient here [2]. (11) 4 Of course, this obligation is not very hard to satisfy using equation (8), but it is inconvenient that it shows up at all. In fact, in a fully-formal development (mechanized or paper), almost every use of heaps runs into similar irritating problems. Although it may seem minor, these kinds of “stupid obligations” can take up a surprising amount of effort: for example, in a recent proof development approximately 5% of the Coq code (more than 500 lines, distributed over more than a hundred places in the development!) was dealing with this kind (and related) obligations [3]. Needless to say, these were not the most interesting parts of the mechanization effort. Using equation (10), breaking apart an (s, v) pair is simpler since one does not end up with an associated ¬identity (s, v) proof, and updating the value component of a pair is simpler since the dependency is directly attached to the share, which is reconstituted into the new pair unchanged. Only updating the share itself requires an update of the associated proof—and even then, the value does not get involved. Beyond the engineering concerns outlined above, there are good theoretical reasons to prefer a style closer to equation (10). In the particular example given in equation (6), the values V were only given the trivial discrete separation structure, but in general one wants to be able to use richer separation structures. However, if one does give V a richer structure, one runs into the problem that equation (8) no longer holds. Instead, even if one’s intention is to restrict the shares to the nonidentity elements, one must return to the more general disjunctive equivalence given in equation (7). This inconvenient disjunction may require the imposition of additional side conditions in awkward places. Why do we not apply the smash operator directly to shares S, as equation (10) would seem to suggest? Unfortunately, if we do so then we produce not the positive shares, but the positive shares plus a fresh bottom element. That is, we end up with S⊥ × V= instead of (S +× V= )⊥ . These are not the same: the left-hand has infinitely many identity elements ((⊥, v) for all v), whereas the right-hand has only one (⊥). Another question is why we do not simply define some constructor from a DSA (A, ⊕A ) to some positive subset DSA (A+ , ⊕A+ ). The answer is that the positive subset lacks identities and thus does not satisfy axiom (e)—that is, (A+ , ⊕A+ ) is not a DSA. 5 Positive Disjoint Separation Algebras The good news is that (S +× V= )⊥ does satisfy the DSA axioms; the bad news is that it is not decomposable componentwise into DSA subparts: we have lost modularity. However, S +×V= is almost a DSA; indeed, it is a member of a well-behaved mathematical structure hereby christened a positive disjoint separation algebra (PDSA). A PDSA, like a DSA, is a set S + and an associated 3-place positive join relation ⊕+ . A PDSA’s ⊕ satisfies axioms (a)–(d) from a DSA. Since it does not have any units, it drops axiom (e), and to enforce positivity it uses a modified version of axiom (f): (f0 ) Positive Disjointness: x ⊕ x = y ⇒ False That is, f0 says that no elements join with themselves. PDSAs are well-behaved because they also enjoy many of the constructions from category theory (e.g., products, sums). What is particularly interesting is how PDSAs and DSAs can be constructed from each other. For example, let us suppose that we have a PDSA such as S +× V= ; we can define the lowering constructor, which takes a PDSA (S + , ⊕+ ) and turns it into a DSA 5 by adding a fresh unit ⊥ and by defining ⊕↓ as the least relation satisfying: 1. ⊥ ⊕↓ a = a 2. a ⊕↓ ⊥ = a 3. a1 ⊕+ a2 = a3 (12) → a1 ⊕ ↓ a2 = a3 By design, this construction is remarkably similar to the construction for the smash operator; the difference is that while the smash operator takes a DSA and produces another DSA, the lowering operator takes a PDSA and produces a DSA. In contrast, the lift constructor takes a DSA and produces a PDSA by removing all of the units. If (S, ⊕) is a DSA, then the lifted join operation on S + , written ⊕↑ , is: + + s+ 1 ⊕ ↑ s2 = s3 ≡ + + s+ 1 ⊕ s2 = s3 (13) In other words, the lift operator gets its join structure directly from the underlying operation. The purpose is to move from a DSA to a PDSA by exchanging S with S + . We observe that the new lower and lift operators are at least as powerful as the old smash operator because for any DSA (S, ⊕) we have S⊥ ∼ = (S↑ )↓ . The question then is if we can get any additional leverage out of the intermediate structure. The answer, happily, is that we can by defining other operators that connect DSAs and PDSAs. One important additional operator we can define is the semiproduct constructor, which takes a PDSA (A+ , ⊕+ A+ ) and DSA (B, ⊕B ) and forms a PDSA over the set A+ × B by defining the positive join operation ⊕+ A+ ×B as follows + + + (a+ 1 , b1 ) ⊕A+ ×B (a2 , b2 ) = (a3 , b3 ) + + + (a+ 1 ⊕A+ a2 = a3 ) ∧ (b1 ⊕B b2 = b3 ) (14) That is, we define the semiproduct constructor componentwise in exactly the same fashion as the regular product constructor on DSAs (and also the regular product constructor on PDSAs). However, since the operation takes different structures on the left- and right-hand sides, we prefer to write A+ ∝ B to indicate the semiproduct2. There are other kinds of constructions that illustrate the connections between DSAs and PDSAs, but we already have enough to reformulate heaps H the way we want: H ≡ ≡ L → (S↑ ∝ V= )↓ (15) That is, heaps H are functions (3) from locations L to a lowered (12) semiproduct (14) of a lifted (13) share S and discrete (1) value V. Elements of H are functions to a pointed set whose nonidentity elements are exactly of the desirable form given in equation (10): that is, the dependent type is attached to the share instead of the share-value pair. We can illustrate the additional expressivity our PDSAs with the following observation. Suppose we have an additional DSA (O, ⊕O ) that we want to attach to the heap cells. We can easily modify our heaps to accommodate this as follows: H0 2 ≡ L → (S↑ ∝ (V= × O))↓ (16) We could also define a semiproduct that takes a DSA on the left and a PDSA on the right. 6 This is better than what we would obtain with the smash operator because it specifies exactly whence positivity is obtained. If we tried to do the same with smash: H00 ≡ L → (S × V= × O)⊥ (17) Now if we have a nonidentity (s, v, o) triple from H00 , then we do not know whether the share s is positive or if the other data o is positive. In contrast, the same triple from H0 (equation 16) must have s positive. This is a feature, not a bug, but if we did want o to be positive as well then we can use (S↑ ∝ V= ) × O↑ . We could allow the same ambiguity that the smash operator does by using ((S × O × V= )↑ )↓ , and so forth. The key point is that we have greater expressibility with lift/lower than we have with smash. 6 Conclusion References 1. Cristiano Calcagno, Peter W. O’Hearn, and Hongseok Yang. Local action and abstract separation logic. In Symposium on Logic in Computer Science, 2007. 2. Robert Dockins, Aquinas Hobor, and Andrew W. Appel. A fresh look at separation algebras and share accounting. In The 7th Asian Symposium on Programming Languages and Systems, pages 161–177. Springer ENTCS, 2009. 3. Aquinas Hobor and Cristian Gherghina. Barriers in concurrent separation logic. In 20th European Symposium of Programming (ESOP 2011), page to appear, 2011.

Download PDF

- Similar pages
- DeviceNet Starter Auxiliary (DSA), A-B 100-DNY
- PDFファイル - 医薬品医療機器総合機構
- Top Bracket for DSA250 Series Enclosure Bottom Bracket of
- Blacknote DSA 150 Special Owner`s manual
- DSA 52 CD 585/745
- Atomic Accessories DSA.122tu
- Airbloc AC quiet application retrofit kit. Technical Bulletin
- Director's Report - 02-18-14
- DSA 8805
- General Terms and Conditions - DSA Daten
- ibm_sw_smash_proxy-pt13_linux_i386