TLA+ Spec with assumptions about external systems - tla+

I am trying out TLA+ for a project at work. I want to prove that fetching data with the same key will return the same data despite some changes to the internals of the data. To do this, I'd like to model the external system as a black box whose responses have certain properties. For instance:
CONSTANT ValidKeys
CONSTANT DataPoints
CONSTANT FETCH(_)
\* Incorrect use of ASSUME, but for illustrative purposes.
ASSUME ValidKeys \in SUBSET DOMAIN FETCH(ValidKeys)
ASSUME \forall key in ValidKeys:
LET fetched == Fetch(ValidKeys)[key]
IN fetched \in Seq(DataPoints)
I would then like to write my own system where TLA+ would infer the behavior based on the specified assumptions. Is that possible?

Yes, but it is better -- especially if you want to use TLC, the TLA+ model checker that's part of the Toolbox -- to use nondeterminism directly, instead of relying on an axiomatic specification using constants and assumptions that requires you to provide a specific instance when model checking, which is probably not what you want.
You can do this:
CONSTANT ValidKey
CONSTANT DataPoint
VARIABLE x
Fetch(key) == key \in ValidKey /\ x' \in Seq(DataPoint)
This is basically saying that Fetch is some operation that returns a sequence of DataPoints, but you don't know which, and it doesn't matter. Now, when checking your system, it would be checked for all possible responses by Fetch (because Seq is unbounded, when model checking, you will need to override it with some operator that describes a bounded sequence up to some given length).
If you want Fetch to always "return" the same result for the same key, you can do something different:
CONSTANTS ValidKey, DataPoint
VARIABLE fetch
Init == fetch \in [ValidKey -> Seq(DataPoint)] /\ ...
Next == UNCHANGED fetch /\ ...
which says that fetch is some unknown function of the desired type. TLC will similarly check the spec for all possible fetch functions.

Related

How to interpret the Result of msat LTL commands of NuXMV

I am using NuXMV for checking LTL properties using msat_check_ltlspec_bmc command on a fairly large model. The result shows no counterexample found within the given bounds. Do I interpret it as that property is True. Or it can alternatively mean that analysis is not complete.
This is because, by changing the property proposition to true or false, the result is always no counterexample. Most of The results are counterintuitive.
Started with real variables based properties but since unable to understand the result, shifted to Boolean based properties on the same model, using the same command.
Bounded Model Checking is a bug-oriented technique which checks the validity of a property on execution traces up to a given lenght k.
When an execution trace violates a property, great: a bug was found.
Otherwise, (in the general case) the model checking result provides no useful information and it should be treated as such.
In some cases, knowing additional information about the model can help. In particular, if one knows that every execution trace of length k must loop-back to one of the k-1 states, then it is possible to draw stronger conclusions from the lack of counter-examples of length smaller or equal k.

Does Unbound always need to be in a `FreshM` monad?

I'm working on a project based on some existing code that uses the unbound library.
The code uses unsafeUnbind a bunch, which is causing me problems.
I've tried using freshen, but I get the following error:
error "fresh encountered bound name!
Please report this as a bug."
I'm wondering:
Is the library intended to be used entirely within a FreshM monad? Or are their ways to do things like lambda application without being in Fresh?
What kinds of values can I give to freshen, in order to avoid the errors they list?
If I end up using unsafeUnbind, under what conditions is it safe to use?
Is the library intended to be used entirely within a FreshM monad? Or are their ways to do things like lambda application without being in Fresh?
In most situations you will want to operate within a Fresh or an LFresh monad.
What kinds of values can I give to freshen, in order to avoid the errors they list?
So I think the reason you're getting the error is because you're passing a term to freshen rather than a pattern. In Unbound, patterns are like a generalization of names: a single Name E is a pattern consisting of a single variable which stands for Es, but also (p1, p2) or [p] are patterns comprised of a pair of patterns p1 and p2 or a list of patterns p, respectively. This lets you define terms that bind two variables at the same time, for example. Other more exotic type constructors include Embed t and Rebind p1 p2 former makes a pattern that embeds a term inside of a pattern, while the latter is similar to (p1,p2) except that the names within p1 scope over p2 (for example if p2 has Embeded terms in it, p1 will be scope over those terms). This is really powerful because it lets you define things like Scheme's let* form, or telescopes like in dependently typed languages. (See the paper for details).
Now finally the type constructorBind p t is what brings a term and a type together: A term Bind p t means that the names in p are bound in Bind p t and scope over t. So an (untyped) lambda term might be constructed with data Expr = Lam (Bind Var Expr) | App Expr Expr | V Var where type Var = Name Expr.
So back to freshen. You should only call freshen on patterns so calling it on something of type Bind p t is incorrect (and I suspect the source of the error message you're seeing) - you should call it on just the p and then apply the resulting permutation to the term t to apply the renaming that freshen constructs.
If I end up using `unsafeUnbind, under what conditions is it safe to use?
The place where I've used it is if I need to temporarily sneak under a binder and do some operation that I know for sure does not do anything to the names. An example might be collecting some source position annotations from a term, or replacing some global constant by a closed term. Also if you can guarantee that the term you're working with already has been renamed so any names that you unsafeUnbind are going to be unique already.
Hope this helps.
PS: I maintain unbound-generics which is a clone of Unbound, but using GHC.Generics instead of RepLib.

Is using util/ordering exactly the same as axiomatizing a total order in the usual way?

The util/ordering module contains a comment at the top of the file about the fact that the bound of the module parameter is constrained to have exactly the bound permitted by the scope for the said signature.
I have read a few times (here for instance) that it is an optimization that allows to generate a nice symmetry-breaking predicate, which I can grasp. (BTW, with respect to the said post, am I right to infer that the exactly keyword in the module parameter specification is here to enforce explictly this exact bound (while it was implicit in pre-4.x Alloy versions)?)
However, the comment also contains a part that does not seem to refer to optimization but really to an issue that has a semantic flavour:
* Technical comment:
* An important constraint: elem must contain all atoms permitted by the scope.
* This is to let the analyzer optimize the analysis by setting all fields of each
* instantiation of Ord to predefined values: e.g. by setting 'last' to the highest
* atom of elem and by setting 'next' to {<T0,T1>,<T1,T2>,...<Tn-1,Tn>}, where n is
* the scope of elem. Without this constraint, it might not be true that Ord.last is
* a subset of elem, and that the domain and range of Ord.next lie inside elem.
So, I do not understand this, in particular the last sentence about Ord.last and Ord.next... Suppose I model a totally-ordered signature S in the classical way (i.e. specifying a total, reflexive, antisymmetric, transitive relation in S -> S, all this being possible using plain first-order logic) and that I take care to specify an exact bound for S: will it be equivalent to stating open util/ordering[S] (ignoring efficiency and confusing atom-naming issues)?
Sorry for the slow response to this. This isn't very clear, is it? All it means is that because of the symmetry breaking, the values of last, prev and next are hardwired. If that were done, and independently elem were to be bound to a set that is smaller than the set of all possible atoms for elem, then you'd have strange violations of the declarations such as Ord.last not being in the set elem. So there's nothing to understand beyond: (1) that the exactly keyword forces elem to contain all the atoms in the given scope, and (2) the ordering relation is hardwired so that the atoms appear in the "natural" order.

How to get the matching element of a set in Python 3?

I am writing a Python program involving a graph over a number of states represented by immutable objects. The process of generating the graph produces many duplicate copies of each state. There are a large number of states, so to save memory I would like to keep just one copy of each state in the final graph object. Therefore, I would like to build a set of canonical states, and write a function like this:
def canonicalize(state, canonical_states):
if state in canonical_states:
state, = (cstate for cstate in canonical_states if cstate == state)
else:
canonical_states.add(state)
return state
This function takes a state and returns the "canonical" version of that state. If the state has not been seen before, it becomes the canonical version.
It should be possible to look up a set element in roughly constant time, but this implementation requires O(n) time for each lookup. Is there a better way?
One solution is to represent canonical_states as a dict mapping elements to themselves (see my answer below). I'd prefer a solution that achieved this performance without changing the type of canonical_states.
In a nutshell: Given that x in S for some set S, is there a way to get the element y of S such that x == y?
Represent the set of canonical states by a dict mapping each state to itself. Then the code becomes something like this:
def canonicalize(state, canonical_states):
return canonical_states.setdefault(state, state)

What is typestate?

What does TypeState refer to in respect to language design? I saw it mentioned in some discussions regarding a new language by mozilla called Rust.
Note: Typestate was dropped from Rust, only a limited version (tracking uninitialized and moved from variables) is left. See my note at the end.
The motivation behind TypeState is that types are immutable, however some of their properties are dynamic, on a per variable basis.
The idea is therefore to create simple predicates about a type, and use the Control-Flow analysis that the compiler execute for many other reasons to statically decorate the type with those predicates.
Those predicates are not actually checked by the compiler itself, it could be too onerous, instead the compiler will simply reasons in terms of graph.
As a simple example, you create a predicate even, which returns true if a number is even.
Now, you create two functions:
halve, which only acts on even numbers
double, which take any number, and return an even number.
Note that the type number is not changed, you do not create a evennumber type and duplicate all those functions that previously acted on number. You just compose number with a predicate called even.
Now, let's build some graphs:
a: number -> halve(a) #! error: `a` is not `even`
a: number, even -> halve(a) # ok
a: number -> b = double(a) -> b: number, even
Simple, isn't it ?
Of course it gets a bit more complicated when you have several possible paths:
a: number -> a = double(a) -> a: number, even -> halve(a) #! error: `a` is not `even`
\___________________________________/
This shows that you reason in terms of sets of predicates:
when joining two paths, the new set of predicates is the intersection of the sets of predicates given by those two paths
This can be augmented by the generic rule of a function:
to call a function, the set of predicates it requires must be satisfied
after a function is called, only the set of predicates it established is satisfied (note: arguments taken by value are not affected)
And thus the building block of TypeState in Rust:
check: checks that the predicate holds, if it does not fail, otherwise adds the predicate to set of predicates
Note that since Rust requires that predicates are pure functions, it can eliminate redundant check calls if it can prove that the predicate already holds at this point.
What Typestate lack is simple: composability.
If you read the description carefully, you will note this:
after a function is called, only the set of predicates it established is satisfied (note: arguments taken by value are not affected)
This means that predicates for a types are useless in themselves, the utility comes from annotating functions. Therefore, introducing a new predicate in an existing codebase is a bore, as the existing functions need be reviewed and tweaked to cater to explain whether or not they need/preserve the invariant.
And this may lead to duplicating functions at an exponential rate when new predicates pop up: predicates are not, unfortunately, composable. The very design issue they were meant to address (proliferation of types, thus functions), does not seem to be addressed.
It's basically an extension of types, where you don't just check whether some operation is allowed in general, but in this specific context. All that at compile time.
The original paper is actually quite readable.
There's a typestate checker written for Java, and Adam Warski's explanatory page gives some useful information. I'm only just figuring this material out myself, but if you are familiar with QuickCheck for Haskell, the application of QuickCheck to monadic state seems similar: categorise the states and explain how they change when they are mutated through the interface.
Typestate is explained as:
leverage type system to encode state changes
Implemented by creating a type for each state
Use move semantics to invalidate a state
Return the next state from the previous state
Optionally drop the state(close file, connections,...)
Compile time enforcement of logic
struct Data;
struct Signed;
impl Data {
fn sign(self) -> Signed {
Signed
}
}
let data = Data;
let singed = data.sign();
data.sign() // Compile error

Resources