26
Logica Relacional: Formulas form ::= expr in expr (subset) |!form (neg) | form && form (conj) | form || form (disj) | all v : type/form (univ) | some v : type/form (exist)

Logica R elacion al - UNICEN · Logica R elacion al: E xpresion es pr obl em ::= decl! fo rm decl ::= v ar : ty pexp r ty pexp r ::= ty pe | ty pe ! ty pe | ty pe " ty pexp r fo rm

  • Upload
    dothuy

  • View
    216

  • Download
    0

Embed Size (px)

Citation preview

Logica Relacional:Formulas

problem ::= decl!formdecl ::= var : typexprtypexpr ::=type| type ! type| type " typexpr

form ::=expr in expr (subset)|!form (neg)| form && form (conj)| form || form (disj)| all v : type/form (univ)| some v : type/form (exist)

expr ::=expr + expr (union)| expr & expr (intersection)| expr# expr (di!erence)|$ expr (transpose)| expr.expr (navigation)| +expr (transitive closure)| {v : t/form} (set former)| V ar

V ar ::=var (variable)| V ar[var] (application)

M : form ! env ! BooleanX : expr ! env ! valueenv = (var + type) ! valuevalue = (atom% · · ·% atom)+

(atom ! value)

M [a in b]e = X[a]e & X[b]eM [!F ]e = ¬M [F ]eM [F&&G]e = M [F ]e 'M [G]eM [F || G]e = M [F ]e (M [G]eM [all v : t/F ] =!

{M [F ](e) v*!{ x })/x + e(t)}M [some v : t/F ] ="

{M [F ](e) v*!{ x })/x + e(t)}

X[a + b]e = X[a]e ,X[b]eX[a&b]e = X[a]e -X[b]eX[a# b]e = X[a]e \ X[b]eX[$ a]e = { .x, y/ : .y, x/ + X[a]e }X[a.b]e = X[a]e ;X[b]eX[+a]e = the smallest r such that

r ;r & r and X[a]e & rX[{v : t/F}]e =

{x + e(t)/M [F ](e) v*!{ x })}X[v]e = e(v)X[a[v]]e = {.y1, . . . , yn//0x. .x, y1, . . . , yn/ + e(a) ' .x/ + e(v)}

Figure 2: Grammar and semantics of Alloy

The intended meaning of this definition can be easily un-derstood, having in mind that m’ is meant to denote thememory (or memory state) resulting of the application offunction Write, a -> d denotes the ordered pair !a, d", and++ denotes relational overriding, defined as follows2:

R++S =

{ !a1, . . . , an" : !a1, . . . , an" # R $ a1 /# dom (S) } % S .

We have already seen a number of constructs availablein Alloy, such as the dot notation and signature extension,that resemble object oriented definitions. Operations, how-ever, represented by functions in Alloy, are not “attached”to signature definitions, as in traditional object-oriented ap-proaches. Instead, functions describe operations of the wholeset of signatures, i.e., the model. So, there is no notion sim-ilar to that of class, as a mechanism for encapsulating data(attributes) and behaviour (operations or methods).

In order to illustrate a couple of further points, considerthe following more complex function definition:

fun SysWrite(s, s’: System, d: Data, a: Addr) {Write(s.cache, s’.cache, d, a)s’.cache.dirty = s.cache.dirty + as’.main = s.main

}

There are two important issues exhibited in this functiondefinition. First, function SysWrite is defined in terms ofthe more primitive Write. Second, the use of Write takesadvantage of the hierarchy defined by signature extension:note that function Write was defined for memories, and inSysWrite it is being “applied” to cache memories.

As explained in [24], an operation that flushes lines from acache to the corresponding memory is necessary in order tohave a realistic model of memories with cache, since usually

2Given a n-ary relation R, dom (R) denotes the set{ a1 : &a2, . . . , an such that !a1, a2, . . . , an" # R }.

caches are smaller than main memories. A (nondetermin-istic) operation that flushes information from the cache tomain memory can be specified in the following way:

fun Flush(s, s’: System) {some x: set s.cache.addrs {

s’.cache.map = s.cache.map - { x->Data }s’.cache.dirty = s.cache.dirty - xs’.main.map = s.main.map ++

{a: x, d: Data | d = s.cache.map[a]}}

}In the third line of the above definition of function Flush,x->Data denotes all the ordered pairs whose domains fallinto the set x, and that range over the domain Data. Func-tion Flush will be used in Section 4.1.5 to illustrate one ofthe main problems that we try to solve.

Functions can also be used to represent special states. Forinstance, we can characterise the states in which the cachelines not marked as dirty are consistent with main memory:

fun DirtyInv(s: System) {all a : !s.cache.dirty |

s.cache.map[a] = s.main.map[a] }(1)

In this context, the symbol “!” denotes negation, indicatingin the above formula that “a” ranges over atoms that arenon dirty addresses.

2.2 Properties of a ModelAs the reader might expect, a model can be enhanced

by adding properties (axioms) to it. These properties arewritten as logical formulas, much in the style of the ObjectConstraint Language [31]. Properties or constraints in Alloyare defined as facts. To give an idea of how constraints orproperties are specified, we reproduce some here. It mightbe necessary to say that the sets of main memories and cachememories are disjoint:

fact {no (MainMemory & Cache)}In the above expression, “no x” indicates that x has noelements, and & denotes intersection. Another importantconstraint inherent to the presented model is that, in ev-ery system, the addresses of its cache are a subset of theaddresses of its main memory:

fact {all s: System | s.cache.addrs in s.main.addrs}More complex facts can be expressed by using the quite

considerable expressive power of the relational logic.

2.3 AssertionsAssertions are the intended properties of a given model.

Consider, for instance, the following simple Alloy assertion,regarding the presented example:

assert {all s: System | DirtyInv(s) && no s.cache.dirty

=> s.cache.map in s.main.map}

This assertion states that, if “DirtyInv” holds in system “s”and there are no dirty addresses in the cache, then the cacheagrees in all its addresses with the main memory.

Assertions are used to check specifications. Using the Al-loy analyzer, it is possible to validate assertions, by searchingfor possible counterexamples for them, under the constraintsimposed in the specification of the system.

Logica Relacional:Expresiones

problem ::= decl!formdecl ::= var : typexprtypexpr ::=type| type ! type| type " typexpr

form ::=expr in expr (subset)|!form (neg)| form && form (conj)| form || form (disj)| all v : type/form (univ)| some v : type/form (exist)

expr ::=expr + expr (union)| expr & expr (intersection)| expr# expr (di!erence)|$ expr (transpose)| expr.expr (navigation)| +expr (transitive closure)| {v : t/form} (set former)| V ar

V ar ::=var (variable)| V ar[var] (application)

M : form ! env ! BooleanX : expr ! env ! valueenv = (var + type) ! valuevalue = (atom% · · ·% atom)+

(atom ! value)

M [a in b]e = X[a]e & X[b]eM [!F ]e = ¬M [F ]eM [F&&G]e = M [F ]e 'M [G]eM [F || G]e = M [F ]e (M [G]eM [all v : t/F ] =∧

{M [F ](e) v*!{ x })/x + e(t)}M [some v : t/F ] =∨

{M [F ](e) v*!{ x })/x + e(t)}

X[a + b]e = X[a]e ,X[b]eX[a&b]e = X[a]e -X[b]eX[a# b]e = X[a]e \ X[b]eX[$ a]e = { .x, y/ : .y, x/ + X[a]e }X[a.b]e = X[a]e ;X[b]eX[+a]e = the smallest r such that

r ;r & r and X[a]e & rX[{v : t/F}]e =

{x + e(t)/M [F ](e) v*!{ x })}X[v]e = e(v)X[a[v]]e = {.y1, . . . , yn//0x. .x, y1, . . . , yn/ + e(a) ' .x/ + e(v)}

Figure 2: Grammar and semantics of Alloy

The intended meaning of this definition can be easily un-derstood, having in mind that m’ is meant to denote thememory (or memory state) resulting of the application offunction Write, a -> d denotes the ordered pair !a, d", and++ denotes relational overriding, defined as follows2:

R++S =

{ !a1, . . . , an" : !a1, . . . , an" # R $ a1 /# dom (S) } % S .

We have already seen a number of constructs availablein Alloy, such as the dot notation and signature extension,that resemble object oriented definitions. Operations, how-ever, represented by functions in Alloy, are not “attached”to signature definitions, as in traditional object-oriented ap-proaches. Instead, functions describe operations of the wholeset of signatures, i.e., the model. So, there is no notion sim-ilar to that of class, as a mechanism for encapsulating data(attributes) and behaviour (operations or methods).

In order to illustrate a couple of further points, considerthe following more complex function definition:

fun SysWrite(s, s’: System, d: Data, a: Addr) {Write(s.cache, s’.cache, d, a)s’.cache.dirty = s.cache.dirty + as’.main = s.main

}

There are two important issues exhibited in this functiondefinition. First, function SysWrite is defined in terms ofthe more primitive Write. Second, the use of Write takesadvantage of the hierarchy defined by signature extension:note that function Write was defined for memories, and inSysWrite it is being “applied” to cache memories.

As explained in [24], an operation that flushes lines from acache to the corresponding memory is necessary in order tohave a realistic model of memories with cache, since usually

2Given a n-ary relation R, dom (R) denotes the set{ a1 : &a2, . . . , an such that !a1, a2, . . . , an" # R }.

caches are smaller than main memories. A (nondetermin-istic) operation that flushes information from the cache tomain memory can be specified in the following way:

fun Flush(s, s’: System) {some x: set s.cache.addrs {

s’.cache.map = s.cache.map - { x->Data }s’.cache.dirty = s.cache.dirty - xs’.main.map = s.main.map ++

{a: x, d: Data | d = s.cache.map[a]}}

}In the third line of the above definition of function Flush,x->Data denotes all the ordered pairs whose domains fallinto the set x, and that range over the domain Data. Func-tion Flush will be used in Section 4.1.5 to illustrate one ofthe main problems that we try to solve.

Functions can also be used to represent special states. Forinstance, we can characterise the states in which the cachelines not marked as dirty are consistent with main memory:

fun DirtyInv(s: System) {all a : !s.cache.dirty |

s.cache.map[a] = s.main.map[a] }(1)

In this context, the symbol “!” denotes negation, indicatingin the above formula that “a” ranges over atoms that arenon dirty addresses.

2.2 Properties of a ModelAs the reader might expect, a model can be enhanced

by adding properties (axioms) to it. These properties arewritten as logical formulas, much in the style of the ObjectConstraint Language [31]. Properties or constraints in Alloyare defined as facts. To give an idea of how constraints orproperties are specified, we reproduce some here. It mightbe necessary to say that the sets of main memories and cachememories are disjoint:

fact {no (MainMemory & Cache)}In the above expression, “no x” indicates that x has noelements, and & denotes intersection. Another importantconstraint inherent to the presented model is that, in ev-ery system, the addresses of its cache are a subset of theaddresses of its main memory:

fact {all s: System | s.cache.addrs in s.main.addrs}More complex facts can be expressed by using the quite

considerable expressive power of the relational logic.

2.3 AssertionsAssertions are the intended properties of a given model.

Consider, for instance, the following simple Alloy assertion,regarding the presented example:

assert {all s: System | DirtyInv(s) && no s.cache.dirty

=> s.cache.map in s.main.map}

This assertion states that, if “DirtyInv” holds in system “s”and there are no dirty addresses in the cache, then the cacheagrees in all its addresses with the main memory.

Assertions are used to check specifications. Using the Al-loy analyzer, it is possible to validate assertions, by searchingfor possible counterexamples for them, under the constraintsimposed in the specification of the system.

Logica Relacional:Semantica de las Formulas

problem ::= decl!formdecl ::= var : typexprtypexpr ::=type| type ! type| type " typexpr

form ::=expr in expr (subset)|!form (neg)| form && form (conj)| form || form (disj)| all v : type/form (univ)| some v : type/form (exist)

expr ::=expr + expr (union)| expr & expr (intersection)| expr# expr (di!erence)|$ expr (transpose)| expr.expr (navigation)| +expr (transitive closure)| {v : t/form} (set former)| V ar

V ar ::=var (variable)| V ar[var] (application)

M : form ! env ! BooleanX : expr ! env ! valueenv = (var + type) ! valuevalue = (atom% · · ·% atom)+

(atom ! value)

M [a in b]e = X[a]e & X[b]eM [!F ]e = ¬M [F ]eM [F&&G]e = M [F ]e 'M [G]eM [F || G]e = M [F ]e (M [G]eM [all v : t/F ] =!

{M [F ](e) v*!{ x })/x + e(t)}M [some v : t/F ] ="

{M [F ](e) v*!{ x })/x + e(t)}

X[a + b]e = X[a]e ,X[b]eX[a&b]e = X[a]e -X[b]eX[a# b]e = X[a]e \ X[b]eX[$ a]e = { .x, y/ : .y, x/ + X[a]e }X[a.b]e = X[a]e ;X[b]eX[+a]e = the smallest r such that

r ;r & r and X[a]e & rX[{v : t/F}]e =

{x + e(t)/M [F ](e) v*!{ x })}X[v]e = e(v)X[a[v]]e = {.y1, . . . , yn//0x. .x, y1, . . . , yn/ + e(a) ' .x/ + e(v)}

Figure 2: Grammar and semantics of Alloy

The intended meaning of this definition can be easily un-derstood, having in mind that m’ is meant to denote thememory (or memory state) resulting of the application offunction Write, a -> d denotes the ordered pair !a, d", and++ denotes relational overriding, defined as follows2:

R++S =

{ !a1, . . . , an" : !a1, . . . , an" # R $ a1 /# dom (S) } % S .

We have already seen a number of constructs availablein Alloy, such as the dot notation and signature extension,that resemble object oriented definitions. Operations, how-ever, represented by functions in Alloy, are not “attached”to signature definitions, as in traditional object-oriented ap-proaches. Instead, functions describe operations of the wholeset of signatures, i.e., the model. So, there is no notion sim-ilar to that of class, as a mechanism for encapsulating data(attributes) and behaviour (operations or methods).

In order to illustrate a couple of further points, considerthe following more complex function definition:

fun SysWrite(s, s’: System, d: Data, a: Addr) {Write(s.cache, s’.cache, d, a)s’.cache.dirty = s.cache.dirty + as’.main = s.main

}

There are two important issues exhibited in this functiondefinition. First, function SysWrite is defined in terms ofthe more primitive Write. Second, the use of Write takesadvantage of the hierarchy defined by signature extension:note that function Write was defined for memories, and inSysWrite it is being “applied” to cache memories.

As explained in [24], an operation that flushes lines from acache to the corresponding memory is necessary in order tohave a realistic model of memories with cache, since usually

2Given a n-ary relation R, dom (R) denotes the set{ a1 : &a2, . . . , an such that !a1, a2, . . . , an" # R }.

caches are smaller than main memories. A (nondetermin-istic) operation that flushes information from the cache tomain memory can be specified in the following way:

fun Flush(s, s’: System) {some x: set s.cache.addrs {

s’.cache.map = s.cache.map - { x->Data }s’.cache.dirty = s.cache.dirty - xs’.main.map = s.main.map ++

{a: x, d: Data | d = s.cache.map[a]}}

}In the third line of the above definition of function Flush,x->Data denotes all the ordered pairs whose domains fallinto the set x, and that range over the domain Data. Func-tion Flush will be used in Section 4.1.5 to illustrate one ofthe main problems that we try to solve.

Functions can also be used to represent special states. Forinstance, we can characterise the states in which the cachelines not marked as dirty are consistent with main memory:

fun DirtyInv(s: System) {all a : !s.cache.dirty |

s.cache.map[a] = s.main.map[a] }(1)

In this context, the symbol “!” denotes negation, indicatingin the above formula that “a” ranges over atoms that arenon dirty addresses.

2.2 Properties of a ModelAs the reader might expect, a model can be enhanced

by adding properties (axioms) to it. These properties arewritten as logical formulas, much in the style of the ObjectConstraint Language [31]. Properties or constraints in Alloyare defined as facts. To give an idea of how constraints orproperties are specified, we reproduce some here. It mightbe necessary to say that the sets of main memories and cachememories are disjoint:

fact {no (MainMemory & Cache)}In the above expression, “no x” indicates that x has noelements, and & denotes intersection. Another importantconstraint inherent to the presented model is that, in ev-ery system, the addresses of its cache are a subset of theaddresses of its main memory:

fact {all s: System | s.cache.addrs in s.main.addrs}More complex facts can be expressed by using the quite

considerable expressive power of the relational logic.

2.3 AssertionsAssertions are the intended properties of a given model.

Consider, for instance, the following simple Alloy assertion,regarding the presented example:

assert {all s: System | DirtyInv(s) && no s.cache.dirty

=> s.cache.map in s.main.map}

This assertion states that, if “DirtyInv” holds in system “s”and there are no dirty addresses in the cache, then the cacheagrees in all its addresses with the main memory.

Assertions are used to check specifications. Using the Al-loy analyzer, it is possible to validate assertions, by searchingfor possible counterexamples for them, under the constraintsimposed in the specification of the system.

problem ::= decl!formdecl ::= var : typexprtypexpr ::=type| type ! type| type " typexpr

form ::=expr in expr (subset)|!form (neg)| form && form (conj)| form || form (disj)| all v : type/form (univ)| some v : type/form (exist)

expr ::=expr + expr (union)| expr & expr (intersection)| expr# expr (di!erence)|$ expr (transpose)| expr.expr (navigation)| +expr (transitive closure)| {v : t/form} (set former)| V ar

V ar ::=var (variable)| V ar[var] (application)

M : form ! env ! BooleanX : expr ! env ! valueenv = (var + type) ! valuevalue = (atom% · · ·% atom)+

(atom ! value)

M [a in b]e = X[a]e & X[b]eM [!F ]e = ¬M [F ]eM [F&&G]e = M [F ]e 'M [G]eM [F || G]e = M [F ]e (M [G]eM [all v : t/F ] =!

{M [F ](e) v*!{ x })/x + e(t)}M [some v : t/F ] ="

{M [F ](e) v*!{ x })/x + e(t)}

X[a + b]e = X[a]e ,X[b]eX[a&b]e = X[a]e -X[b]eX[a# b]e = X[a]e \ X[b]eX[$ a]e = { .x, y/ : .y, x/ + X[a]e }X[a.b]e = X[a]e ;X[b]eX[+a]e = the smallest r such that

r ;r & r and X[a]e & rX[{v : t/F}]e =

{x + e(t)/M [F ](e) v*!{ x })}X[v]e = e(v)X[a[v]]e = {.y1, . . . , yn//0x. .x, y1, . . . , yn/ + e(a) ' .x/ + e(v)}

Figure 2: Grammar and semantics of Alloy

The intended meaning of this definition can be easily un-derstood, having in mind that m’ is meant to denote thememory (or memory state) resulting of the application offunction Write, a -> d denotes the ordered pair !a, d", and++ denotes relational overriding, defined as follows2:

R++S =

{ !a1, . . . , an" : !a1, . . . , an" # R $ a1 /# dom (S) } % S .

We have already seen a number of constructs availablein Alloy, such as the dot notation and signature extension,that resemble object oriented definitions. Operations, how-ever, represented by functions in Alloy, are not “attached”to signature definitions, as in traditional object-oriented ap-proaches. Instead, functions describe operations of the wholeset of signatures, i.e., the model. So, there is no notion sim-ilar to that of class, as a mechanism for encapsulating data(attributes) and behaviour (operations or methods).

In order to illustrate a couple of further points, considerthe following more complex function definition:

fun SysWrite(s, s’: System, d: Data, a: Addr) {Write(s.cache, s’.cache, d, a)s’.cache.dirty = s.cache.dirty + as’.main = s.main

}

There are two important issues exhibited in this functiondefinition. First, function SysWrite is defined in terms ofthe more primitive Write. Second, the use of Write takesadvantage of the hierarchy defined by signature extension:note that function Write was defined for memories, and inSysWrite it is being “applied” to cache memories.

As explained in [24], an operation that flushes lines from acache to the corresponding memory is necessary in order tohave a realistic model of memories with cache, since usually

2Given a n-ary relation R, dom (R) denotes the set{ a1 : &a2, . . . , an such that !a1, a2, . . . , an" # R }.

caches are smaller than main memories. A (nondetermin-istic) operation that flushes information from the cache tomain memory can be specified in the following way:

fun Flush(s, s’: System) {some x: set s.cache.addrs {

s’.cache.map = s.cache.map - { x->Data }s’.cache.dirty = s.cache.dirty - xs’.main.map = s.main.map ++

{a: x, d: Data | d = s.cache.map[a]}}

}In the third line of the above definition of function Flush,x->Data denotes all the ordered pairs whose domains fallinto the set x, and that range over the domain Data. Func-tion Flush will be used in Section 4.1.5 to illustrate one ofthe main problems that we try to solve.

Functions can also be used to represent special states. Forinstance, we can characterise the states in which the cachelines not marked as dirty are consistent with main memory:

fun DirtyInv(s: System) {all a : !s.cache.dirty |

s.cache.map[a] = s.main.map[a] }(1)

In this context, the symbol “!” denotes negation, indicatingin the above formula that “a” ranges over atoms that arenon dirty addresses.

2.2 Properties of a ModelAs the reader might expect, a model can be enhanced

by adding properties (axioms) to it. These properties arewritten as logical formulas, much in the style of the ObjectConstraint Language [31]. Properties or constraints in Alloyare defined as facts. To give an idea of how constraints orproperties are specified, we reproduce some here. It mightbe necessary to say that the sets of main memories and cachememories are disjoint:

fact {no (MainMemory & Cache)}In the above expression, “no x” indicates that x has noelements, and & denotes intersection. Another importantconstraint inherent to the presented model is that, in ev-ery system, the addresses of its cache are a subset of theaddresses of its main memory:

fact {all s: System | s.cache.addrs in s.main.addrs}More complex facts can be expressed by using the quite

considerable expressive power of the relational logic.

2.3 AssertionsAssertions are the intended properties of a given model.

Consider, for instance, the following simple Alloy assertion,regarding the presented example:

assert {all s: System | DirtyInv(s) && no s.cache.dirty

=> s.cache.map in s.main.map}

This assertion states that, if “DirtyInv” holds in system “s”and there are no dirty addresses in the cache, then the cacheagrees in all its addresses with the main memory.

Assertions are used to check specifications. Using the Al-loy analyzer, it is possible to validate assertions, by searchingfor possible counterexamples for them, under the constraintsimposed in the specification of the system.

Logica Relacional:Semantica de las Expresiones

problem ::= decl!formdecl ::= var : typexprtypexpr ::=type| type ! type| type " typexpr

form ::=expr in expr (subset)|!form (neg)| form && form (conj)| form || form (disj)| all v : type/form (univ)| some v : type/form (exist)

expr ::=expr + expr (union)| expr & expr (intersection)| expr# expr (di!erence)|$ expr (transpose)| expr.expr (navigation)| +expr (transitive closure)| {v : t/form} (set former)| V ar

V ar ::=var (variable)| V ar[var] (application)

M : form ! env ! BooleanX : expr ! env ! valueenv = (var + type) ! valuevalue = (atom% · · ·% atom)+

(atom ! value)

M [a in b]e = X[a]e & X[b]eM [!F ]e = ¬M [F ]eM [F&&G]e = M [F ]e 'M [G]eM [F || G]e = M [F ]e (M [G]eM [all v : t/F ] =!

{M [F ](e) v*!{ x })/x + e(t)}M [some v : t/F ] ="

{M [F ](e) v*!{ x })/x + e(t)}

X[a + b]e = X[a]e ,X[b]eX[a&b]e = X[a]e -X[b]eX[a# b]e = X[a]e \ X[b]eX[$ a]e = { .x, y/ : .y, x/ + X[a]e }X[a.b]e = X[a]e ;X[b]eX[+a]e = the smallest r such that

r ;r & r and X[a]e & rX[{v : t/F}]e =

{x + e(t)/M [F ](e) v*!{ x })}X[v]e = e(v)X[a[v]]e = {.y1, . . . , yn//0x. .x, y1, . . . , yn/ + e(a) ' .x/ + e(v)}

Figure 2: Grammar and semantics of Alloy

The intended meaning of this definition can be easily un-derstood, having in mind that m’ is meant to denote thememory (or memory state) resulting of the application offunction Write, a -> d denotes the ordered pair !a, d", and++ denotes relational overriding, defined as follows2:

R++S =

{ !a1, . . . , an" : !a1, . . . , an" # R $ a1 /# dom (S) } % S .

We have already seen a number of constructs availablein Alloy, such as the dot notation and signature extension,that resemble object oriented definitions. Operations, how-ever, represented by functions in Alloy, are not “attached”to signature definitions, as in traditional object-oriented ap-proaches. Instead, functions describe operations of the wholeset of signatures, i.e., the model. So, there is no notion sim-ilar to that of class, as a mechanism for encapsulating data(attributes) and behaviour (operations or methods).

In order to illustrate a couple of further points, considerthe following more complex function definition:

fun SysWrite(s, s’: System, d: Data, a: Addr) {Write(s.cache, s’.cache, d, a)s’.cache.dirty = s.cache.dirty + as’.main = s.main

}

There are two important issues exhibited in this functiondefinition. First, function SysWrite is defined in terms ofthe more primitive Write. Second, the use of Write takesadvantage of the hierarchy defined by signature extension:note that function Write was defined for memories, and inSysWrite it is being “applied” to cache memories.

As explained in [24], an operation that flushes lines from acache to the corresponding memory is necessary in order tohave a realistic model of memories with cache, since usually

2Given a n-ary relation R, dom (R) denotes the set{ a1 : &a2, . . . , an such that !a1, a2, . . . , an" # R }.

caches are smaller than main memories. A (nondetermin-istic) operation that flushes information from the cache tomain memory can be specified in the following way:

fun Flush(s, s’: System) {some x: set s.cache.addrs {

s’.cache.map = s.cache.map - { x->Data }s’.cache.dirty = s.cache.dirty - xs’.main.map = s.main.map ++

{a: x, d: Data | d = s.cache.map[a]}}

}In the third line of the above definition of function Flush,x->Data denotes all the ordered pairs whose domains fallinto the set x, and that range over the domain Data. Func-tion Flush will be used in Section 4.1.5 to illustrate one ofthe main problems that we try to solve.

Functions can also be used to represent special states. Forinstance, we can characterise the states in which the cachelines not marked as dirty are consistent with main memory:

fun DirtyInv(s: System) {all a : !s.cache.dirty |

s.cache.map[a] = s.main.map[a] }(1)

In this context, the symbol “!” denotes negation, indicatingin the above formula that “a” ranges over atoms that arenon dirty addresses.

2.2 Properties of a ModelAs the reader might expect, a model can be enhanced

by adding properties (axioms) to it. These properties arewritten as logical formulas, much in the style of the ObjectConstraint Language [31]. Properties or constraints in Alloyare defined as facts. To give an idea of how constraints orproperties are specified, we reproduce some here. It mightbe necessary to say that the sets of main memories and cachememories are disjoint:

fact {no (MainMemory & Cache)}In the above expression, “no x” indicates that x has noelements, and & denotes intersection. Another importantconstraint inherent to the presented model is that, in ev-ery system, the addresses of its cache are a subset of theaddresses of its main memory:

fact {all s: System | s.cache.addrs in s.main.addrs}More complex facts can be expressed by using the quite

considerable expressive power of the relational logic.

2.3 AssertionsAssertions are the intended properties of a given model.

Consider, for instance, the following simple Alloy assertion,regarding the presented example:

assert {all s: System | DirtyInv(s) && no s.cache.dirty

=> s.cache.map in s.main.map}

This assertion states that, if “DirtyInv” holds in system “s”and there are no dirty addresses in the cache, then the cacheagrees in all its addresses with the main memory.

Assertions are used to check specifications. Using the Al-loy analyzer, it is possible to validate assertions, by searchingfor possible counterexamples for them, under the constraintsimposed in the specification of the system.

problem ::= decl!formdecl ::= var : typexprtypexpr ::=type| type ! type| type " typexpr

form ::=expr in expr (subset)|!form (neg)| form && form (conj)| form || form (disj)| all v : type/form (univ)| some v : type/form (exist)

expr ::=expr + expr (union)| expr & expr (intersection)| expr# expr (di!erence)|$ expr (transpose)| expr.expr (navigation)| +expr (transitive closure)| {v : t/form} (set former)| V ar

V ar ::=var (variable)| V ar[var] (application)

M : form ! env ! BooleanX : expr ! env ! valueenv = (var + type) ! valuevalue = (atom% · · ·% atom)+

(atom ! value)

M [a in b]e = X[a]e & X[b]eM [!F ]e = ¬M [F ]eM [F&&G]e = M [F ]e 'M [G]eM [F || G]e = M [F ]e (M [G]eM [all v : t/F ] =!

{M [F ](e) v*!{ x })/x + e(t)}M [some v : t/F ] ="

{M [F ](e) v*!{ x })/x + e(t)}

X[a + b]e = X[a]e ,X[b]eX[a&b]e = X[a]e -X[b]eX[a# b]e = X[a]e \ X[b]eX[$ a]e = { .x, y/ : .y, x/ + X[a]e }X[a.b]e = X[a]e ;X[b]eX[+a]e = the smallest r such that

r ;r & r and X[a]e & rX[{v : t/F}]e =

{x + e(t)/M [F ](e) v*!{ x })}X[v]e = e(v)X[a[v]]e = {.y1, . . . , yn//0x. .x, y1, . . . , yn/ + e(a) ' .x/ + e(v)}

Figure 2: Grammar and semantics of Alloy

The intended meaning of this definition can be easily un-derstood, having in mind that m’ is meant to denote thememory (or memory state) resulting of the application offunction Write, a -> d denotes the ordered pair !a, d", and++ denotes relational overriding, defined as follows2:

R++S =

{ !a1, . . . , an" : !a1, . . . , an" # R $ a1 /# dom (S) } % S .

We have already seen a number of constructs availablein Alloy, such as the dot notation and signature extension,that resemble object oriented definitions. Operations, how-ever, represented by functions in Alloy, are not “attached”to signature definitions, as in traditional object-oriented ap-proaches. Instead, functions describe operations of the wholeset of signatures, i.e., the model. So, there is no notion sim-ilar to that of class, as a mechanism for encapsulating data(attributes) and behaviour (operations or methods).

In order to illustrate a couple of further points, considerthe following more complex function definition:

fun SysWrite(s, s’: System, d: Data, a: Addr) {Write(s.cache, s’.cache, d, a)s’.cache.dirty = s.cache.dirty + as’.main = s.main

}

There are two important issues exhibited in this functiondefinition. First, function SysWrite is defined in terms ofthe more primitive Write. Second, the use of Write takesadvantage of the hierarchy defined by signature extension:note that function Write was defined for memories, and inSysWrite it is being “applied” to cache memories.

As explained in [24], an operation that flushes lines from acache to the corresponding memory is necessary in order tohave a realistic model of memories with cache, since usually

2Given a n-ary relation R, dom (R) denotes the set{ a1 : &a2, . . . , an such that !a1, a2, . . . , an" # R }.

caches are smaller than main memories. A (nondetermin-istic) operation that flushes information from the cache tomain memory can be specified in the following way:

fun Flush(s, s’: System) {some x: set s.cache.addrs {

s’.cache.map = s.cache.map - { x->Data }s’.cache.dirty = s.cache.dirty - xs’.main.map = s.main.map ++

{a: x, d: Data | d = s.cache.map[a]}}

}In the third line of the above definition of function Flush,x->Data denotes all the ordered pairs whose domains fallinto the set x, and that range over the domain Data. Func-tion Flush will be used in Section 4.1.5 to illustrate one ofthe main problems that we try to solve.

Functions can also be used to represent special states. Forinstance, we can characterise the states in which the cachelines not marked as dirty are consistent with main memory:

fun DirtyInv(s: System) {all a : !s.cache.dirty |

s.cache.map[a] = s.main.map[a] }(1)

In this context, the symbol “!” denotes negation, indicatingin the above formula that “a” ranges over atoms that arenon dirty addresses.

2.2 Properties of a ModelAs the reader might expect, a model can be enhanced

by adding properties (axioms) to it. These properties arewritten as logical formulas, much in the style of the ObjectConstraint Language [31]. Properties or constraints in Alloyare defined as facts. To give an idea of how constraints orproperties are specified, we reproduce some here. It mightbe necessary to say that the sets of main memories and cachememories are disjoint:

fact {no (MainMemory & Cache)}In the above expression, “no x” indicates that x has noelements, and & denotes intersection. Another importantconstraint inherent to the presented model is that, in ev-ery system, the addresses of its cache are a subset of theaddresses of its main memory:

fact {all s: System | s.cache.addrs in s.main.addrs}More complex facts can be expressed by using the quite

considerable expressive power of the relational logic.

2.3 AssertionsAssertions are the intended properties of a given model.

Consider, for instance, the following simple Alloy assertion,regarding the presented example:

assert {all s: System | DirtyInv(s) && no s.cache.dirty

=> s.cache.map in s.main.map}

This assertion states that, if “DirtyInv” holds in system “s”and there are no dirty addresses in the cache, then the cacheagrees in all its addresses with the main memory.

Assertions are used to check specifications. Using the Al-loy analyzer, it is possible to validate assertions, by searchingfor possible counterexamples for them, under the constraintsimposed in the specification of the system.

El Lenguaje de Especificacion Alloy

Lenguaje de especificacion cuyo lenguaje y semantica estan basados en la logica relacional.

Provee mecanismos para definir tipos similar a las clases de los lenguajes orientados a objetos.

Permite introducir axiomas y operaciones que determinan el modelo formal.

Alloy: Ejemplos: Grafos

sig Nodo { }

sig Grafo {nodos : set Nodoarcos : nodos -> nodos}

Alloy: Ejemplos: Grafos Conexos

module grafosconexos

sig Nodo { }

one sig Grafo { nodos : set Nodo, arcos : nodos -> nodos}

fact conexo { all disj n1, n2 : Grafo.nodos | n2 in n1.(^(Grafo.arcos + ~(Grafo.arcos)))}

assert noTieneAislado{all n : Grafo.nodos | some n.(Grafo.arcos) || some n.(~(Grafo.arcos))}

check noTieneAislado for 5

Alloy: Ejemplos: Grafos Aciclicos

module grafoaciclico

sig Nodo { }

one sig Grafo { nodos : set Nodo, arcos : nodos -> nodos}

fact acyclic { no ^(Grafo.arcos) & iden}

Alloy: Ejemplos: Grafos Aciclicos Dirigidos

module grafoaciclicodirigido

sig Nodo { }

one sig Grafo { nodos : set Nodo, arcos : nodos -> nodos}

fact acyclic { no ^(Grafo.arcos) & iden}

fact hasRoot { one n : Grafo.nodos | n.(*(Grafo.arcos)) = Grafo.nodos}

pred conexo() { all disj n1, n2 : Grafo.nodos | n2 in n1.(^(Grafo.arcos + ~(Grafo.arcos)))}

assert DAGConexo {conexo()}

check DAGConexo for 8

Alloy: Ejemplos:Listas encadenadas

module listaSimplementeEncadenada

sig Data {}

sig List { first : lone Data, next : lone List}

one sig Empty extends List {}

fact emptyIsEmpty {no Empty.first && no Empty.next}

fact allToEmpty {all l : List | Empty in l.*next}

assert acyclic {all l : List | l not in l.(^next)}

check acyclic for 7

Como obtener Alloy?

http://alloy.mit.edu

Disponible para numerosas plataformas.

Fundamentos de DynAlloy: Logica Dinamica

Logica que permite modelar evolucion de los estados.

Permite modelar propiedades de la ejecucion de programas secuenciales no-deterministicos.

Sintaxis de la Logica Dinamica

5.4 A short case studyIn this section we will develop a short case-study to show

how this proof method is used. As an instance of (12), let usconsider a system whose cache agrees with main memory inall non-dirty addresses. A consistency criterion of the cachewith main memory is that after finitely many executions ofSysWrite or Flush, the resulting system must still satisfy theinvariant DirtyInv. This property is specified in DynAlloy by:

all s : System |DirtyInv(s)

{(SysWrite(s) + Flush(s))!}DirtyInv(s) .

(14)

Notice also that if after finitely many executions of SysWriteand Flush we flush all the dirty addresses in the cache tomain memory, the resulting cache should fully agree withmain memory. In order to specify this property we needto specify the function that flushes all the dirty cache ad-dresses. The specification is as follows:

s = s0

{DSFlush(s : System)}

s.cache.dirty = ! "s.cache.map = s0.cache.map #

s0.cache.map[s0.cache.dirty] "s.main.map = s0.main.map ++

s0.cache.map[s0.cache.dirty]

We specify the property establishing the agreement of thecache with main memory as follows:

FullyAgree(s : System)

$% s.cache.map in s.main.map .

Once “DSFlush” and “FullyAgree” have been specified,the property is specified in DynAlloy by:

all s : System |DirtyInv(s)

{(SysWrite(s) + Flush(s))! ;DSFlush(s)}FullyAgree(s) .

(15)Now, it only remains to apply function MT to formula

(15) and feed the Alloy analyzer with the resulting formula.

6. ACOMPLETECALCULUSFORDYNAMIC

ALLOYIn this section we present a complete calculus for reason-

ing about properties specified in DynAlloy. Recalling Fig. 1,in this Section we deal with the portion reproduced in Fig. 8.

The formalism FDL (Fork Dynamic Logic) can be suc-cinctly described as first-order dynamic logic over the equa-tional theory of fork algebras. The reason for using dynamiclogic is that there is a close relationship between this logicand partial correctness assertions. In Section 6.1 we presentthe syntax and semantics of first-order dynamic logic. InSection 6.2, dynamic logic is extended with fork algebras.We then extend function RL &' FRL so that it also trans-lates partial correctness assertions. Finally, in Section 6.3we present a complete calculus for FDL.

DynAlloy FDL!is interpreted

Figure 8: Relationships among the formalisms Dy-nAlloy and FDL.

6.1 Dynamic LogicDynamic logic is a formalism for reasoning about pro-

grams. From a set of atomic actions (usually assignments ofterms to variables), and using appropriate combinators, it ispossible to build complex actions. The logic then allows usto state properties of these actions, which may hold or not ina given structure. Actions can change (as usually programsdo), the values of variables. We will assume that each actionreads and/or modifies the value of finitely many variables.When compared with classical first–order logic, the essentialdi!erence is the dynamic content of dynamic logic, which isclear in the notion of satisfiability. While satisfiability inclassical first–order logic depends on the values of variablesin one valuation (state), in dynamic logic it is necessary toconsider two valuations in order to reflect the change of val-ues of program variables; one valuation holds the values ofvariables before the action is performed, and another holdsthe values of variables after the action is executed.

Along the section we will assume a fixed (but arbitrary)finite signature " = ( s, A, F, P ), where s is a sort, A ={ a1, . . . , ak } is the set of atomic action symbols, F is theset of function symbols, and P is the set of atomic predicatesymbols. Atomic actions contain input and output formalparameters. These parameters are later instantiated withactual variables when actions are used in a specification.

The sets of programs and formulae on " are mutuallydefined in Fig. 9.

action ::= a1, . . . ak (atomic actions)| skip| action+action (nondeterministic choice)| action;action (sequential composition)| action! (finite iteration)| dform? (test)

expr ::= var| f(expr1, . . . , exprk) (f ! F with arity k)

dform ::= p(expr1, . . . , exprn) (p ! P with arity n)| !dform (negation)| dform && dform (conjunction)| dform || dform (disjunction)| all v : type | dform (universal)| some v : type | dform (existential)| [action]dform (box)

Figure 9: Syntax of dynamic logic

As is standard in dynamic logic, states are valuations ofthe program variables (the actual parameters for actions).The environment env assigns a domain s to sort s in whichprogram variables take values. The set of states is denotedby ST . For each action symbol a * A, env yields a binary re-lation on the set of states, that is, a subset of ST +ST . Theenvironment maps function symbols to concrete functions,and predicate symbols to relations of the corresponding ar-ity. The semantics of the logic is given in Fig. 10.

Semantica de la Logica Dinamica

Q : form ! ST ! BooleanP : action ! P (ST " ST)Z : expr ! ST ! s

Q[p(t1, . . . , tn)]µ = (Z[t1]µ, . . . , Z[tn]µ) # env(p) (atomic formula)Q[!F ]µ = ¬Q[F ]µQ[F&&G]µ = Q[F ]µ $Q[G]µQ[F || G]µ = Q[F ]µ %Q[G]µQ[all v : t | F ]µ =

!{Q[F ](µ& v'!x) | x # env(t)}

Q[some v : t | F ]µ ="{Q[F ](µ& v'!x) | x # env(t)}

Q[ [a]F ]µ =!{Q[F ]! | (µ, !) # P (a)}

P [a] = env(a) (atomic action)P [skip] = { (µ, µ) : µ # ST }P [a + b] = P [a] * P [b]P [a ;b] = P [a]+P [b]P [a!] = (P [a])!

P ["?] = { (µ, µ) : Q["]µ }

Z[v]µ = µ(v)Z[f(t1, . . . , tk)]µ = env(f)(Z[t1]µ, . . . , Z[tk]µ)

Figure 10: Semantics of dynamic logic

6.2 FDL: Dynamic Logic over Fork AlgebrasIn Section 6.1 we introduced first-order dynamic logic.

As with classical first-order logic, it is possible to extendthe language of dynamic logic by adding new symbols, andalso to add new axioms giving meaning to these. In or-der to define FDL, we include in the set of function sym-bols of signature ! the set of constants { 0, 1, Id }, the setof unary symbols

! –, ,̆ !", and the set of binary symbols

{ + , · , ; , ! }. The only predicate we will consider is equal-ity. Since these signatures include all operation symbolsfrom fork algebras, they will be called fork signatures. OnceFDL is defined, the main result in this section (Thm. 6.4)is an interpretation of DynAlloy into FDL. That is, we willpresent a semantics–preserving mapping from DynAlloy for-mulas to FDL formulas. This will allow us, in Section 6.3,to present a complete calculus for FDL, that can be used forproving DynAlloy theorems.

Remark 1. Notice that FDL atomic formulae are equal-ities between fork algebra terms, and thus, for atomic for-mulae, function Q from Fig. 10 and function N from Fig. 3agree.

We will call theories containing the identities (axioms)specifying the class of fork algebras FDL theories. By work-ing with FDL theories we intend to describe structures fordynamic logic whose domains are sets of binary relations.This is indeed the case as it is shown in the following theo-rem.

Theorem 6.1. Let ! be a fork signature, and " be a FDLtheory. For each model A for " there exists a model B for", isomorphic to A, in which the domain s is a set of binaryrelations.

Proof. Let us consider the reduct A of the model A,obtained by keeping A’s domain and the fork algebra opera-tions. A is a structure of the form

#A, + , · , –, 0, 1, ; , ,̆ Id, !

$

in which the semantics of action, function and predicatesymbols is given through an environment env . Since " is aFDL theory (and therefore satisfies the axioms for fork al-gebras), A is a fork algebra. Thus, by [13][14, Thm. 4.2], Ais isomorphic to a proper fork algebra with domain B. Let

h : A " B be the isomorphism. In order to define the modelB we will define an environment env " for action, functionand predicate symbols as follows:

– Actions: #s, s"$ % env "(a) &'#h#1(s), h#1(s")

$%

env(a), where for a state s, h#1(s) is the state satisfy-ing (h#1(s))(v) = h#1(s(v)).

– Functions: [env "(f)] (b) = h%[env(f)] (h#1(b))

&.

– Predicates: b % env "(p) &' h#1(b) % env(p).

By construction, B is isomorphic to A.

The previous theorem is essential, and its proof (whichuses [14, Thm. 4.2]), heavily relies on the use of fork algebrasrather than plain relation algebras [39]. A model for a FDLtheory " is a structure satisfying all the formulae in ".Such a structure can, or cannot, have binary relations inits domain. Theorem 6.1 shows that models whose domainsare not a set of binary relations are isomorphic to models inwhich the domain is a set of binary relations. This allowsus to look at specifications in FDL, and interpret them asproperties predicating about binary relations.

We will end this section by presenting the extension offunction RL (" FRL to partial correctness assertions. Theextension, which is defined as RL (" FRL for the remainingformula patterns, is denoted by DynAlloy (" FDL. Then,

DynAlloy (" FDL (!{p}") =

RL (" FRL(!) =' [p] RL (" FRL(") .

In the following paragraphs we present a theorem describ-ing the relationship established by the translation, betweenthe formalisms DynAlloy and FDL.

Lemma 6.2. Let ! be a DynAlloy formula. Let e be a Dy-nAlloy environment, and A the function that assigns meaningto atomic actions. Then, there exists a FDL environment 'esuch that

M [!]e = Q[DynAlloy (" FDL(!)]'e .

Proof. Let environment 'e be defined by:

• for each variable v denoting a n-ary relation c, wedefine 'e(v) = c (the binary encoding of relation c,cf. 4.1.2),

• for each atomic action symbol a, we define

'e(a) =! #

e"1, e"2

$: #e1, e2$ % A(a)

",

where e"1, e"2 are defined from e1 and e2 as in Thm. 4.1.

The proof proceeds now by induction on the structure offormula !. For the sake of simplicity we will present theproof for atomic formulas and partial correctness assertions.

Let ! be atomic, i.e., ! = t1 in t2.

M [t1 in t2]e= {by Thm. 4.2}

N [RL (" FRL(t1 in t2)]e"

= {because no actions occur in !}N [RL (" FRL(t1 in t2)]'e

= {by Remark 1}Q[RL (" FRL(t1 in t2)]'e

= {because ! is a RL formula }Q[DynAlloy (" FDL(t1 in t2)]'e .

Ejemplo de Especificacion en Logica Dinamica

all x : Nat | x = x0 => [A(x)](x = x0+1)

(x=x0 && y=y0) => [Swap(x,y)](x=y0 && y=x0)

(x=x0 && y=y0) => [Swap(x,y) ; Swap(x,y)](x=x0 && y=y0)

Programas via Acciones

Programa atomico via accion atomica (por ejemplo +1, o Swap)

P1 ; P2 ---> T(P1) ; T(P2)

if C then P1 else P2 fi ---> C? ; T(P1) + (!C)? ; T(P2)

while C do P ---> (C? ; T(P))* ; (!C)?

Aserciones de Correccion Parcial

pre => [P]post

La formula es satisfecha for aquellos estados que satisfacen “pre”, y para los cuales todo estado alacanzable por P satisface “post”.

pre(s)

PP

P

post(s1)

post(s2)

!post(s3)

Como analizar aserciones de correccion parcial?

Mediante el calculo de la precondicion mas debil de un programa.

Permite caracterizar los estados que satisfacen la asercion en logica de primer orden.

Calculo de la Precondicion mas Debil

14 · Marcelo F. Frias et al.

The main rationale behind our technique for the analysis of DynAlloy specifica-tions is the translation of partial correctness assertions to first-order Alloy formulas,using weakest liberal preconditions [Dijkstra and Scholten 1990]. The generated Al-loy formulas, which may be large and quite di!cult to understand, are not visibleto the end user, who only accesses the declarative DynAlloy specification.

We define below a function

wlp : program ! formula " formula

that computes the weakest liberal precondition of a formula according to a program(composite action). We will in general use names x1, x2 . . . for program variables,and will use names x!1, x

!2, . . . for the value of program variables after action exe-

cution. We will denote by !|vx the substitution of all free occurrences of variable xby the fresh variable v in formula !.

When an atomic action a specified as #pre, post$(x) is used in a composite ac-tion, formal parameters are substituted by actual parameters. Since we assume allvariables are input/output variables, actual parameters are variables, let us say, y.In this situation, function wlp is defined as follows:

wlp[a(y), f ] = pre|y!

x =% all n!post|n

x! |y!

x =% f |ny!

". (5)

A few points need to be explained about (5). First, we assume that free variablesin f are amongst y!, x0. Variables in x0 are generated by the translation functionpcat given in (7). Second, n is an array of new variables, one for each variablemodified by the action. Last, notice that the resulting formula has again its freevariables amongst y!, x0. This is also preserved in the remaining cases in thedefinition of function wlp.

For the remaining action constructs, the definition of function wlp is the following:

wlp[g?, f ] = g =% fwlp[p1 + p2, f ] = wlp[p1, f ] & wlp[p2, f ]wlp[p1 ;p2, f ] = wlp[p1,wlp[p2, f ]]wlp[p", f ] =

##i=0 wlp[pi, f ] .

Notice that wlp yields Alloy formulas in all these cases, except for the iterationconstruct, where the resulting formula may be infinitary. In order to obtain anAlloy formula, we can impose a bound on the depth of iterations. This is equivalentto fixing a maximum length for traces. A function Bwlp (bounded weakest liberalprecondition) is then defined exactly as wlp, except for iteration, where it is definedby:

Bwlp[p", f ] =n$

i=0

Bwlp[pi, f ] . (6)

In (6), n is the scope set for the depth of iterations.We now define a function pcat that translates partial correctness assertions to

Alloy formulas. For a partial correctness assertion {!(y)} P (y) {"(y, y!)}

pcat ({!} P {"}) = 'y!! =%

!Bwlp

%p, "|x0

y

&"|yy! |

yx0

". (7)

Of course this analysis method where iteration is restricted to a fixed depth isnot complete, but clearly it is not meant to be; from the very beginning we placedACM Transactions on Software Engineering and Methodology, Vol. TBD, No. TDB, Month Year.

14 · Marcelo F. Frias et al.

The main rationale behind our technique for the analysis of DynAlloy specifica-tions is the translation of partial correctness assertions to first-order Alloy formulas,using weakest liberal preconditions [Dijkstra and Scholten 1990]. The generated Al-loy formulas, which may be large and quite di!cult to understand, are not visibleto the end user, who only accesses the declarative DynAlloy specification.

We define below a function

wlp : program ! formula " formula

that computes the weakest liberal precondition of a formula according to a program(composite action). We will in general use names x1, x2 . . . for program variables,and will use names x!1, x

!2, . . . for the value of program variables after action exe-

cution. We will denote by !|vx the substitution of all free occurrences of variable xby the fresh variable v in formula !.

When an atomic action a specified as #pre, post$(x) is used in a composite ac-tion, formal parameters are substituted by actual parameters. Since we assume allvariables are input/output variables, actual parameters are variables, let us say, y.In this situation, function wlp is defined as follows:

wlp[a(y), f ] = pre|y!

x =% all n!post|n

x! |y!

x =% f |ny!

". (5)

A few points need to be explained about (5). First, we assume that free variablesin f are amongst y!, x0. Variables in x0 are generated by the translation functionpcat given in (7). Second, n is an array of new variables, one for each variablemodified by the action. Last, notice that the resulting formula has again its freevariables amongst y!, x0. This is also preserved in the remaining cases in thedefinition of function wlp.

For the remaining action constructs, the definition of function wlp is the following:

wlp[g?, f ] = g =% fwlp[p1 + p2, f ] = wlp[p1, f ] & wlp[p2, f ]wlp[p1 ;p2, f ] = wlp[p1,wlp[p2, f ]]wlp[p", f ] =

##i=0 wlp[pi, f ] .

Notice that wlp yields Alloy formulas in all these cases, except for the iterationconstruct, where the resulting formula may be infinitary. In order to obtain anAlloy formula, we can impose a bound on the depth of iterations. This is equivalentto fixing a maximum length for traces. A function Bwlp (bounded weakest liberalprecondition) is then defined exactly as wlp, except for iteration, where it is definedby:

Bwlp[p", f ] =n$

i=0

Bwlp[pi, f ] . (6)

In (6), n is the scope set for the depth of iterations.We now define a function pcat that translates partial correctness assertions to

Alloy formulas. For a partial correctness assertion {!(y)} P (y) {"(y, y!)}

pcat ({!} P {"}) = 'y!! =%

!Bwlp

%p, "|x0

y

&"|yy! |

yx0

". (7)

Of course this analysis method where iteration is restricted to a fixed depth isnot complete, but clearly it is not meant to be; from the very beginning we placedACM Transactions on Software Engineering and Methodology, Vol. TBD, No. TDB, Month Year.

Entonces...

Una formula pre => [P]post es valida cuando

pre => wlp(P,post)

es valida.

DynAlloy

Extension de Alloy para facilitar el analisis de propiedades de ejecuciones.

Mejor separacion de intereses que utilizando trazas directamente en la especificacion.

El “DynAlloy Analyzer” permite analizar especificaciones DynAlloy automaticamente.

Sintaxis de DynAlloy

10 · Marcelo F. Frias et al.

function application. Recalling the definition of function Write, notice that thereis no actual change in the state of the system, since no variable actually changesits value.

Dynamic logic [Harel et al. 2000] arose in the early ’70s, with the intention offaithfully reflecting state change. Motivated by dynamic logic, we propose the useof actions to model state change in Alloy, as described below.

What we would like to say about an action is how it transforms the system stateafter its execution. A (now) traditional way of doing so is by using pre and postcondition assertions. An assertion of the form

{!}A

{"}

a!rms that whenever action A is executed on a state satisfying !, if it terminates,it does so in a state satisfying ". This approach is particularly appropriate, sincebehaviors described by functions are better viewed as the result of performing anaction on an input state. Thus, the definition of function Write could be expressedas an action definition, of the following form:

{true}Write(m : Memory,d : Data, a : Addr){m!.map = m.map ++ (a ! d)} .

(3)

At first glance it is di!cult to see the di"erences between (1) and (3), sinceboth formulas seem to provide the same information. The crucial di"erences arereflected in the semantics, as well as in the fact that actions can be sequentiallycomposed, iterated or composed by nondeterministic choice, while Alloy functions,in principle, cannot.

An immediately apparent di"erence between (1) and (3) is that action Writedoes not involve the parameter m!, while function Write uses it. This is so becausewe use the convention that m! denotes the state of variable m after execution ofaction Write. This time, “after” means that m! gets its value in an environmentreachable through the execution of action Write (cf. Fig. 3). Since Write denotes abinary relation on the set of environments, there is a precise notion of input/outputinducing a before/after relationship.

3.2 Syntax and Semantics of DynAlloy

The syntax of DynAlloy’s formulas extends the one presented in Fig. 1 with theaddition of the following clause for building partial correctness statements:

formula ::= . . . | {formula} program {formula}“partial correctness”

The syntax for programs (cf. Fig. 2) is the class of regular programs defined in[Harel et al. 2000], plus a new rule to allow for the construction of atomic actionsfrom their pre and post conditions. In the definition of atomic actions, x denotesa sequence of formal parameters. Thus, it is to be expected that the preconditionis a formula whose free variables are within x, while postcondition variables mightalso include primed versions of the formal parameters.ACM Transactions on Software Engineering and Methodology, Vol. TBD, No. TDB, Month Year.

E!cient Analysis of DynAlloy Specifications · 11

program ::= !formula, formula"(x) “atomic action”| formula? “test”| program + program “non-deterministic choice”| program ;program “sequential composition”| program! “iteration”

Fig. 2. Grammar for composite actions in DynAlloy

In Fig. 3 we extend the definition of function M to partial correctness assertionsand define the denotational semantics of programs as binary relations over env . Thedefinition of function M on a partial correctness assertion makes clear that we areactually considering a partial correctness semantics. This follows from the fact thatwe are not requesting environment e to belong to the domain of the relation P [p].In order to provide semantics for atomic actions, we will assume that there is afunction A assigning, to each atomic action, a binary relation on the environments.We define function A as follows:

A(!pre, post") = { !e, e"" : M [pre]e # M [post ]e" } .

There is a subtle point in the definition of the semantics of atomic programs. Whileactions may modify the value of all variables, we assume that those variables whoseprimed versions do not occur in the post condition retain their corresponding inputvalues. Thus, the atomic action Write modifies the value of variable m, but aand d keep their initial values. This allows us to use simpler formulas in preand post conditions. Notice that, since parallel composition of actions is not anallowed action combinator, this assumption does not restrict the sound compositionof actions or programs. Although parallel composition is not available, one couldstill define it by means of interleaving of atomic actions, via nondeterministic choiceand sequential composition, as usual in concurrent programming.

M [{!}p{"}]e = M [!]e =! "e!!"

e, e!## P [p] =! M ["]e!

$

P : program $ P (env % env)

P [&pre, post'] = A(&pre, post')P [!?] = { &e, e!' : M [!]e ( e = e! }P [p1 + p2] = P [p1] ) P [p2]P [p1 ;p2] = P [p1] ;P [p2]P [p"] = P [p]"

Fig. 3. Semantics of DynAlloy.

3.3 Specifying Properties of Executions in Alloy and DynAlloy

Suppose that we want to specify that a given property P is invariant under se-quences of applications of the operations “SysFlush” and “SysWrite”, from certaininitial state. A useful technique for stating the invariance of a property P consists

ACM Transactions on Software Engineering and Methodology, Vol. TBD, No. TDB, Month Year.

Semantica de DynAlloy

E!cient Analysis of DynAlloy Specifications · 11

program ::= !formula, formula"(x) “atomic action”| formula? “test”| program + program “non-deterministic choice”| program ;program “sequential composition”| program! “iteration”

Fig. 2. Grammar for composite actions in DynAlloy

In Fig. 3 we extend the definition of function M to partial correctness assertionsand define the denotational semantics of programs as binary relations over env . Thedefinition of function M on a partial correctness assertion makes clear that we areactually considering a partial correctness semantics. This follows from the fact thatwe are not requesting environment e to belong to the domain of the relation P [p].In order to provide semantics for atomic actions, we will assume that there is afunction A assigning, to each atomic action, a binary relation on the environments.We define function A as follows:

A(!pre, post") = { !e, e"" : M [pre]e # M [post ]e" } .

There is a subtle point in the definition of the semantics of atomic programs. Whileactions may modify the value of all variables, we assume that those variables whoseprimed versions do not occur in the post condition retain their corresponding inputvalues. Thus, the atomic action Write modifies the value of variable m, but aand d keep their initial values. This allows us to use simpler formulas in preand post conditions. Notice that, since parallel composition of actions is not anallowed action combinator, this assumption does not restrict the sound compositionof actions or programs. Although parallel composition is not available, one couldstill define it by means of interleaving of atomic actions, via nondeterministic choiceand sequential composition, as usual in concurrent programming.

M [{!}p{"}]e = M [!]e =! "e!!"

e, e!## P [p] =! M ["]e!

$

P : program $ P (env % env)

P [&pre, post'] = A(&pre, post')P [!?] = { &e, e!' : M [!]e ( e = e! }P [p1 + p2] = P [p1] ) P [p2]P [p1 ;p2] = P [p1] ;P [p2]P [p"] = P [p]"

Fig. 3. Semantics of DynAlloy.

3.3 Specifying Properties of Executions in Alloy and DynAlloy

Suppose that we want to specify that a given property P is invariant under se-quences of applications of the operations “SysFlush” and “SysWrite”, from certaininitial state. A useful technique for stating the invariance of a property P consists

ACM Transactions on Software Engineering and Methodology, Vol. TBD, No. TDB, Month Year.

Ejemplo:

E!cient Analysis of DynAlloy Specifications · 5

incremental specification; once a component C together with programs regardingthis component are validated (this involves the analysis of execution traces), onecan build new components in terms of the defined one C, and new programs, inwhich (some of) the programs corresponding to C are considered as atomic. Intu-itively, this technique allows us to compress the size of the traces of new programs,leading to the exploration of longer computations during the analysis, as we willshow.

The remainder of this paper is organized as follows. In Section 2 we summarizethe main characteristics of the Alloy specification language. In Section 3 we intro-duce the reader to our extension of Alloy, the DynAlloy language. In Section 4 wepresent the DynAlloy tool, the tool that extends the Alloy Analyzer with supportfor actions, partial correctness assertions and their corresponding analysis. In Sec-tion 5 we present the program atomization technique, and its impact on incrementalvalidation. In Section 6 we present the case-studies used to compare our approachwith standard Alloy’s, and their corresponding running times. Finally, in Section7 we present our conclusions and proposals for further work.

2. THE ALLOY SPECIFICATION LANGUAGE

In this section, we introduce the reader to the Alloy specification language by meansof an example extracted from [Jackson et al. 2001]. This example serves as a meansfor illustrating the standard features of the language and their associated semantics,the shortcomings overcome by our alternative semantics, and will be used as a basisfor the properties of traces we will analyze.

Suppose we want to specify systems involving memories with cache. We mightrecognize that, in order to specify memories, data types for data and addresses areespecially necessary. We can then start by indicating the existence of disjoint sets(of atoms) for data and addresses, which in Alloy are specified using signatures:

sig Addr { } sig Data { }

These are basic signatures. We do not assume any special properties regarding thestructures of data and addresses.

With data and addresses already defined, we can now specify what constitutes amemory. A possible way of defining memories is by saying that a memory consistsof a set of addresses, and a (total) mapping from these addresses to data values. Inour case, we will use memories in order to model what is common to a cache anda main memory, so the signature must be declared as abstract:

abstract sig Memory {addrs: set Addr,map: addrs -> lone Data

}

The modifier “lone” in the above definition indicates that “map” is functional andtotal (for each element a of addrs, there exists exactly one element d in Data suchthat map(a) = d).

Alloy allows for the definition of signatures as subsets of the set denoted byanother “parent” signature. This is done via what is called signature extension.

ACM Transactions on Software Engineering and Methodology, Vol. TBD, No. TDB, Month Year.

E!cient Analysis of DynAlloy Specifications · 5

incremental specification; once a component C together with programs regardingthis component are validated (this involves the analysis of execution traces), onecan build new components in terms of the defined one C, and new programs, inwhich (some of) the programs corresponding to C are considered as atomic. Intu-itively, this technique allows us to compress the size of the traces of new programs,leading to the exploration of longer computations during the analysis, as we willshow.

The remainder of this paper is organized as follows. In Section 2 we summarizethe main characteristics of the Alloy specification language. In Section 3 we intro-duce the reader to our extension of Alloy, the DynAlloy language. In Section 4 wepresent the DynAlloy tool, the tool that extends the Alloy Analyzer with supportfor actions, partial correctness assertions and their corresponding analysis. In Sec-tion 5 we present the program atomization technique, and its impact on incrementalvalidation. In Section 6 we present the case-studies used to compare our approachwith standard Alloy’s, and their corresponding running times. Finally, in Section7 we present our conclusions and proposals for further work.

2. THE ALLOY SPECIFICATION LANGUAGE

In this section, we introduce the reader to the Alloy specification language by meansof an example extracted from [Jackson et al. 2001]. This example serves as a meansfor illustrating the standard features of the language and their associated semantics,the shortcomings overcome by our alternative semantics, and will be used as a basisfor the properties of traces we will analyze.

Suppose we want to specify systems involving memories with cache. We mightrecognize that, in order to specify memories, data types for data and addresses areespecially necessary. We can then start by indicating the existence of disjoint sets(of atoms) for data and addresses, which in Alloy are specified using signatures:

sig Addr { } sig Data { }

These are basic signatures. We do not assume any special properties regarding thestructures of data and addresses.

With data and addresses already defined, we can now specify what constitutes amemory. A possible way of defining memories is by saying that a memory consistsof a set of addresses, and a (total) mapping from these addresses to data values. Inour case, we will use memories in order to model what is common to a cache anda main memory, so the signature must be declared as abstract:

abstract sig Memory {addrs: set Addr,map: addrs -> lone Data

}

The modifier “lone” in the above definition indicates that “map” is functional andtotal (for each element a of addrs, there exists exactly one element d in Data suchthat map(a) = d).

Alloy allows for the definition of signatures as subsets of the set denoted byanother “parent” signature. This is done via what is called signature extension.

ACM Transactions on Software Engineering and Methodology, Vol. TBD, No. TDB, Month Year.

6 · Marcelo F. Frias et al.

For the example, one could define other (perhaps more complex) kinds of memoriesas extensions of the Memory signature:

sig MainMemory extends Memory {}

sig Cache extends Memory {dirty: set addrs

}

As specified in these definitions, MainMemory and Cache are special kinds of mem-ories. In caches, a subset of addrs is recognized as dirty.

A system might now be defined to be composed of a main memory and a cache:

sig System {cache: Cache,main: MainMemory

}

As the previous definitions show, signatures are used to define data domains andtheir structure. The attributes of a signature denote relations. For instance, the“addrs” attribute in signature Memory represents a binary relation, from memoryatoms to sets of atoms from Addr. Given a set m (not necessarily a singleton)of Memory atoms, m.addrs denotes the relational image of m under the relationdenoted by addrs. This leads to a relational view of the dot notation, which issimple and elegant, and preserves the intuitive navigational reading of dot, as inobject orientation. Signature extension, as we mentioned before, is interpreted asinclusion of the set of atoms of the extending signature into the set of atoms of theextended signature.

In Fig. 1, we present the grammar and semantics of Alloy’s relational logic, thecore logic on top of which all of Alloy’s syntax and semantics are defined. Animportant di!erence with respect to previous versions of Alloy, as for instance theone presented in [Jackson 2002a], is that expressions now range over relations ofarbitrary rank, instead of being restricted to binary relations. Composition ofbinary relations is well understood; but for relations of higher rank, the followingdefinition for the composition of relations has to be considered:

R ;S = {!a1, . . . , ai!1, b2, . . . , bj" :#b (!a1, . . . , ai!1, b" $ R % !b, b2, . . . , bj" $ S)} .

Operations for transitive closure and transposition are only defined for binaryrelations. Thus, function X in Fig. 1 is partial.

2.1 Operations in a Model

So far, we have just shown how the structure of data domains can be specified inAlloy. Of course, one would like to be able to define operations over the defineddomains. Following the style of Z specifications, operations in Alloy can be definedas expressions, relating states from the state spaces described by the signaturedefinitions. Primed variables are used to denote the resulting values, although thisis just a convention, not reflected in the semantics.ACM Transactions on Software Engineering and Methodology, Vol. TBD, No. TDB, Month Year.

6 · Marcelo F. Frias et al.

For the example, one could define other (perhaps more complex) kinds of memoriesas extensions of the Memory signature:

sig MainMemory extends Memory {}

sig Cache extends Memory {dirty: set addrs

}

As specified in these definitions, MainMemory and Cache are special kinds of mem-ories. In caches, a subset of addrs is recognized as dirty.

A system might now be defined to be composed of a main memory and a cache:

sig System {cache: Cache,main: MainMemory

}

As the previous definitions show, signatures are used to define data domains andtheir structure. The attributes of a signature denote relations. For instance, the“addrs” attribute in signature Memory represents a binary relation, from memoryatoms to sets of atoms from Addr. Given a set m (not necessarily a singleton)of Memory atoms, m.addrs denotes the relational image of m under the relationdenoted by addrs. This leads to a relational view of the dot notation, which issimple and elegant, and preserves the intuitive navigational reading of dot, as inobject orientation. Signature extension, as we mentioned before, is interpreted asinclusion of the set of atoms of the extending signature into the set of atoms of theextended signature.

In Fig. 1, we present the grammar and semantics of Alloy’s relational logic, thecore logic on top of which all of Alloy’s syntax and semantics are defined. Animportant di!erence with respect to previous versions of Alloy, as for instance theone presented in [Jackson 2002a], is that expressions now range over relations ofarbitrary rank, instead of being restricted to binary relations. Composition ofbinary relations is well understood; but for relations of higher rank, the followingdefinition for the composition of relations has to be considered:

R ;S = {!a1, . . . , ai!1, b2, . . . , bj" :#b (!a1, . . . , ai!1, b" $ R % !b, b2, . . . , bj" $ S)} .

Operations for transitive closure and transposition are only defined for binaryrelations. Thus, function X in Fig. 1 is partial.

2.1 Operations in a Model

So far, we have just shown how the structure of data domains can be specified inAlloy. Of course, one would like to be able to define operations over the defineddomains. Following the style of Z specifications, operations in Alloy can be definedas expressions, relating states from the state spaces described by the signaturedefinitions. Primed variables are used to denote the resulting values, although thisis just a convention, not reflected in the semantics.ACM Transactions on Software Engineering and Methodology, Vol. TBD, No. TDB, Month Year.

Ejemplo (continuacion)

10 · Marcelo F. Frias et al.

function application. Recalling the definition of function Write, notice that thereis no actual change in the state of the system, since no variable actually changesits value.

Dynamic logic [Harel et al. 2000] arose in the early ’70s, with the intention offaithfully reflecting state change. Motivated by dynamic logic, we propose the useof actions to model state change in Alloy, as described below.

What we would like to say about an action is how it transforms the system stateafter its execution. A (now) traditional way of doing so is by using pre and postcondition assertions. An assertion of the form

{!}A

{"}

a!rms that whenever action A is executed on a state satisfying !, if it terminates,it does so in a state satisfying ". This approach is particularly appropriate, sincebehaviors described by functions are better viewed as the result of performing anaction on an input state. Thus, the definition of function Write could be expressedas an action definition, of the following form:

{true}Write(m : Memory,d : Data, a : Addr){m!.map = m.map ++ (a ! d)} .

(3)

At first glance it is di!cult to see the di"erences between (1) and (3), sinceboth formulas seem to provide the same information. The crucial di"erences arereflected in the semantics, as well as in the fact that actions can be sequentiallycomposed, iterated or composed by nondeterministic choice, while Alloy functions,in principle, cannot.

An immediately apparent di"erence between (1) and (3) is that action Writedoes not involve the parameter m!, while function Write uses it. This is so becausewe use the convention that m! denotes the state of variable m after execution ofaction Write. This time, “after” means that m! gets its value in an environmentreachable through the execution of action Write (cf. Fig. 3). Since Write denotes abinary relation on the set of environments, there is a precise notion of input/outputinducing a before/after relationship.

3.2 Syntax and Semantics of DynAlloy

The syntax of DynAlloy’s formulas extends the one presented in Fig. 1 with theaddition of the following clause for building partial correctness statements:

formula ::= . . . | {formula} program {formula}“partial correctness”

The syntax for programs (cf. Fig. 2) is the class of regular programs defined in[Harel et al. 2000], plus a new rule to allow for the construction of atomic actionsfrom their pre and post conditions. In the definition of atomic actions, x denotesa sequence of formal parameters. Thus, it is to be expected that the preconditionis a formula whose free variables are within x, while postcondition variables mightalso include primed versions of the formal parameters.ACM Transactions on Software Engineering and Methodology, Vol. TBD, No. TDB, Month Year.

E!cient Analysis of DynAlloy Specifications · 13

{ true }

SysWrite(s: System)

{ some d: Data, a: Addr |s’.cache = s.cache ++ (a! d) ands’.cache.dirty = s.cache.dirty + a ands’.main = s.main }

{ true }

SysFlush(s: System)

{ some x: set s.cache.addrs |s’.cache.map = s.cache.map - x!Data ands’.cache.dirty = s.cache.dirty - x ands’.main.map = s.main.map ++

{a: x, d: Data | d = s.cache.map[a]} }

Notice that the previous specifications are as understandable as the ones givenin Alloy. Moreover, by using partial correctness statements on the set of regularprograms generated by the set of atomic actions {SysWrite,SysFlush }, we canassert the invariance of a property P under finite applications of functions SysWriteand SysFlush in a simple and elegant way, as follows:

{Init(s) " P (s)}(SysWrite(s) + SysFlush(s))!

{P (s")}More generally, suppose now that we want to show that a property Q is invariant

under sequences of applications of arbitrary operations O1, . . . , Ok, starting fromstates s described by a formula Init . The specification of this assertion in oursetting is done via the following formula:

{Init(x ) "Q(x)}(O1(x) + · · · + Ok(x))! (4)

{Q(x")}

Notice that there is no need to mention traces in the specification of the previousproperties. This is so due to the fact that finite traces get determined by thesemantics of reflexive-transitive closure.

3.4 Analysis of DynAlloy Specifications

Alloy’s design was deeply influenced by the intention of producing an automaticallyanalyzable language. While DynAlloy is, to our understanding, better suited thanAlloy for the specification of properties of executions, the use of ticks and traces asdefined in [Jackson et al. 2001] has as an advantage that it allows one to automati-cally analyze properties of executions. Therefore, a question is immediately raised:Can DynAlloy specifications be automatically analyzed, and if so, how e!ciently?

ACM Transactions on Software Engineering and Methodology, Vol. TBD, No. TDB, Month Year.

Ejemplo (continuacion)

8 · Marcelo F. Frias et al.

over, operations, represented by functions in Alloy, can be “attached” to signaturedefinitions, as in traditional object-oriented approaches. However, this is just aconvenient notation, and functions describe operations of the whole set of signa-tures, i.e., the model. So, there is no notion similar to that of class, as a mechanismfor encapsulating data (attributes or fields) and behavior (operations or methods).

In order to illustrate a couple of further points, consider the following morecomplex function definition:

pred SysWrite(s, s’: System, d: Data, a: Addr) {Write(s.cache, s’.cache, d, a)s’.cache.dirty = s.cache.dirty + as’.main = s.main

}There are two important issues exhibited in this function definition. First, functionSysWrite is defined in terms of the more primitive Write. Second, the use of Writetakes advantage of the hierarchy defined by signature extension: note that functionWrite was defined for memories, and in SysWrite it is being “applied” to cachememories.

As explained in [Jackson et al. 2001], an operation that flushes lines from acache to the corresponding memory is necessary in order to have a realistic modelof memories with cache, since usually caches are smaller than main memories.A (nondeterministic) operation that flushes information from the cache to mainmemory can be specified in the following way:

pred SysFlush(s, s’: System) {some x: set s.cache.addrs {

s’.cache.map = s.cache.map - { x->Data }s’.cache.dirty = s.cache.dirty - xs’.main.map = s.main.map ++

{a: x, d: Data | d = s.cache.map[a]}}

}In the third line of the above definition of function SysFlush, x->Data denotes theset of all ordered pairs whose first elements fall into the set x, and whose secondelements range over Data.

Functions can also be used to represent special states. For instance, we cancharacterize the states in which the cache lines not marked as dirty are consistentwith main memory:

pred DirtyInv(s: System) {all a : !s.cache.dirty |

s.cache.map[a] = s.main.map[a] }(2)

In this context, the symbol “!” denotes negation, indicating in the above formulathat “a” ranges over atoms that are non dirty addresses.

2.2 Properties of a Model

As the reader might expect, a model can be enhanced by adding properties (axioms)to it. These properties are written as logical formulas, much in the style of theACM Transactions on Software Engineering and Methodology, Vol. TBD, No. TDB, Month Year.

{ DirtyInv(s) }(SysWrite(s) + SysFlush(s))*

{ DirtyInv(s’) }