express equivalence between several instances - alloy

Suppose I have a sig A in my module that is related to a sig B.
Imagine now that we have the several instances :
A$1 -> B$1 , A$2 -> B$2
and
A$1 -> B$2 , A$2 -> B$1
I would like to express that B$1 and B$2 are equivalent (under certain conditions) such that only this instance would be generated A$1 -> B , A$2 -> B.
One of the solution might be to use the keyword "one" while declaring the sig B, but it won't work in my case, because B have several fields, making B atoms not necessarily equivalent . In short 2 atoms are equivalent only if they have their fields of same values.
Ideally I would like to remove the numbering for B. but still be able to have several atoms B .

The Alloy Analyzer doesn't give you much control over how the subsequent instances are generated (or how to break symmetries), so you typically have to work around those issues at the model level.
For your example, maybe this is the right model
sig B{}
one sig BA extends B {}
sig A {
b: one BA
}
run { #A=2 }

First you say that the two instances you describe are equivalent, although at a superficial level they appear to have distinct values for A$1 and A$2. Then you say "2 atoms are equivalent only if ... their fields [have the] same values". If that's the definition of equivalence, then your two instances are not equivalent; if your two instances are equivalent, then your definition is not capturing what you want.
It sounds as if you mean (1) that B atoms are either (1a) always equivalent, or (1b) equivalent under certain circumstances, and (2) that A atoms are equivalent if their fields all have values which are either identical or equivalent. And as if you want to prohibit equivalent A atoms. If that's so, then your jobs are:
Define a predicate that is true for two B elements if and only if they are equivalent.
Define a predicate for two A elements that is true if and only if they are equivalent.
Define a predicate (or a fact) that specifies that no two A atoms in the instance are equivalent.
If your problem is just that the Analyzer is showing you instances of the model which are not interestingly distinct from each other, then see Aleksandar Milicevic's response.

Related

How can I model a Observable who emits three values one of type A, the second one type B and the last one type C?

I love typing and I have a situations in which an observable emits always 3 values. The first one is type A, the middle one is type B, and the third one is type C.
The only way to model is
type Result = Observable<A | B | C> ?
is there a more concise way?
Thanks!

Why sum of products can be viewed as normal form in algebraic data types?

I am reading a haskell book (page 412). In this book, there is an explanation about normal form for sum of products:
All the existing algebraic rules for products and sums apply in type systems, and that includes the distributive property. Let’s take a look at how that works in arithmetic:
2 * (3 + 4)
2 * (7)
14
We can rewrite this with the multiplication distributed over the addition and obtain the same result:
2 * 3 + 2 * 4
(6) + (8)
14
This is known as a “sum of products.” In normal arithmetic, the expression is in normal form when it’s been reduced to a final result. However, if you think of the numerals in the above expressions as representations of set cardinality, then the sum of products expression is in normal form, as there is no computation to perform.
I've known that a normal form indiciates that an expression is fully reduced. In the above description, author of the book explains that sum of products can be seen as in normal form when we think of expression as representations of set cardinality. I don't understand that.
Cardinality of types means how many different values can be included in that type (like set). For example, Bool type in haskell has cardinality of 2, which is addition of 1 for False and 1 for True each.
Is sum of products (2 * 3 + 2 * 4) a normal form? This expression can be reduced furthre more because fully reduced expression would be 14. I don't understand why sum of products and cardinality of it are related to be normal form.
Let's declare ourselves some types to represent the numbers:
data Two = OneOfTwo | TwoOfTwo
data Three = OneOfThree | TwoOfThree | ThreeOfThree
data Four = ... (similar)
Now we can see that the number of possible values of type Two is, in fact, 2. Same for Three, Four, and Seven.
Now if we construct a sum type:
data A = A Two
This type just straight up wraps a value of Two, so the number of possible values of A is also 2. So far so good?
Now let's construct a more complex one:
data B = B1 Three | B2 Four
Now, this type wraps either a value of type Three or a value of type Four (but not both at the same time!) This means that the number of possible values would be 3 + 4. Following so far?
Now, going further:
data C = C Two B
This type wraps two values at the same time - one value of type Two and one value of type B. This means that the number of possible values of C is the number of possible combinations of Two and B, which, as we know from middle-school mathematics, would be their product, or 2 * (3 + 4) = 2 * (7) = 14.
But here's the trick: we can write down an equivalent type in a different way:
data CNew = C1 Two Three | C2 Two Four
See what I did there? For CNew, the set of all possible combinations between values of Two, Three, and Four is the same as for C. Look: in both cases it's either a value of Two combined with a value of Three, or it's a value of Two combined with a value of Four. Except in CNew they're combined directly, but in C they're combined via B.
But the formula for CNew would be different: 2 * 3 + 2 * 4 = (6) + (8) = 14. This is what the book means.
Now to answer this bit more directly:
Is sum of products (2 * 3 + 2 * 4) a normal form? This expression can be reduced further more because fully reduced expression would be 14
This would be true if we were dealing with integer numbers, but we're not. We can rewrite C in the form of CNew, because that gives us all the same possible combinations of values. But we cannot rewrite them as a type that has straight up 14 possible values without combining 2, 3, and 4. That would be a completely new, unrelated type, as opposed to a combination of Two, Three, and Four.
And a possible terminology misunderstanding:
Is sum of products (2 * 3 + 2 * 4) a normal form?
The term "normal form" doesn't mean "the shortest". This term is usually used to denote a form that is very regular, and therefore easier to work with, and, crucially, that can represent all possible cases in the domain. In this case, normal form is defined as a "sum of products".
Could it be a "product of sums" instead? No, it couldn't, because, while a product of sums can always be converted to a sum of products, the reverse is not always possible, and this means that not every possible type would be representable in the normal form defined as "product of sums".
Could it be "just the number of possible values", like 14? Again no, because converting to such form loses some information (see above).

How to produce a table of three inputs to reach a given output? (Excel model)

I have a very detailed excel model to calculate the profitability of a project, that we can call P.
The model has been simplified to compute from 3 unrelated variables. I would like to automatically create a table that shows how inputs A, B and C might vary in order to produce a pre-defined level of profitability, P. For instance, if A = 4 & B = 30, then C must = 2 in order for P to equal 20%. Likewise, if A = 5 & B = 25, then C must = 3 in order for P to equal 20%. A and B should be tested at sensible increments, perhaps 8 intervals each.
A laborious (not scalable) equivalent would be to manually define A and B, then goal-seek C to our pre-defined level of P - we'd then repeat for each combination of A and B at the given intervals and record in a two-way table.
I believe a conventional two-way data table would be pratical if the model sitting behind the inputs were greatly simplified, unfortunately this isn't possible.
Thanks to anyone that can lend a hand. Kind regards.
I think the best way to approach this will be with a VBA macro and the prebuilt GoalSeek Function something like this (p is in cell D1) :
Range(”D1”).GoalSeek Goal:=20 _
ChangingCell:=Range(“C1”)

Mutually dependent variables in a spreadsheet

Assume I have an input variable x and three parameters a,b,c such that:
Given b we have c = f(x,a,b) for some (known) function f
Given c we have b = g(x,a,c) for some (known, different) function g.
I want to model this in a spreadsheet (Excel for instance). More precisely, if the user provides x,a and b then c will be evaluated and if c is given then b will be evaluated. It seems like this cannot be achieved directly, since a cell can hold either a value or a formula.
Is there a canonical way to do this? If not, what would be a best-practice workaround (probably some VBA magic)?
You can separate input fields from the calculated values and add some validation that only one of the mutually exclusive field is used, e.g.:
in my example, I used following conditional formatting to highlight invalid input:
=AND($B$4<>"", $B$5<>"")
and I used following the formulas for calculated values:
=B2
=B3
=IF(AND($B$4<>"", $B$5<>""), "#ERROR: only 1 value can be specified",
IF($B$4<>"", $B$4, $B$5-1))
=IF(AND($B$4<>"", $B$5<>""), "#ERROR: only 1 value can be specified",
IF($B$5<>"", $B$5, $B$4+1))
more generally:
=if(error_condition, error_message, if(b_is_not_empty, b, g(x,a,c)))

Explanations about the mechanics of a simple factorial function

I'm new to Haskell, so I'm both naive and curious.
There is a definition of a factorial function:
factorial n = product [1..n]
I naively understand this as: make the product of every number between 1 and n. So, why does
factorial 0
return 1 (which is the good result as far as my maths are not too rusted)?
Thank you
That's because of how product is defined, something like:
product [] = 1
product (n:ns) = n * product ns
or equivalently
product = foldr (*) 1
via the important function foldr:
foldr f z [] = z
foldr f z (x:xs) = f x (foldr f z xs)
Read up on folding here. But basically, any recursion must have a base case, and product's base case (on an empty list) clearly has to be 1.
The story about empty product is long and interesting.
It has many sense to define it as 1.
Despite of that, there is some more debate about whether we are justified to define 00 as 1, although 00 can be thought of also as an empty product in most contexts. See the 00 debate here and also here.
Now I show an example, when empty product conventions can yield a surprising, unintuitive outcome.
How to define the concept of a prime, without the necessity to exclude 1 explicitly? It seems so unaesthetic, to say that "a prime is such and such, except for this and that". Can the concept of prime be defined with some handy definition which can exclude 1 in a "natural", "automatic" way, without mentioning the exclusion explicitly?
Let us try this approach:
Let us call a natural number c composite, iff c can be written as a product of some a1, ..., ⋅ an natural numbers, so that all of them must be different from c.
Let us call a natural number p prime, iff p cannot be written as a product of any a1, an natural numbers each differing from p.
Let us test whether this approach is any good:
6 = 6 ⋅ 1 3 ⋅ 26 is composite, this fact is witnessed by the following factorisation: 6 can be written as the product 3 ⋅ 2, or with other words, product of the ⟨3, 2⟩ sequence, notated as Π ⟨3, 2⟩.
Till now, our approach new is O.K.
5 = 5 ⋅ 1 1 ⋅ 55 is prime, there is no sequence ⟨a1, ... an⟩ such that
all its members a1, ... an would differ from 5
but the product itself, Π ⟨a1, ... an⟩ would equal 5.
Till now, our new approach is O.K.
Now let us investigate 1:
1 = Π ⟨⟩,
Empty product is a good witness, with it, 1 satisfies the definition of being a composite(!!!) Who is the witness? Where is the witnessing factorization? It is no other than the empty product Π ⟨⟩, the product of the empty sequence ⟨⟩.
Π ⟨⟩ equals 1
All factors of the empty product Π ⟨⟩, i.e. the members of the empty sequence ⟨⟩ satisfy that each of them differ from 1: simply because empty sequence ⟨⟩ does not have any members at all, thus none of its member can equal 1. (This argumentation is simply a vacuous truth, with members of the empty set).
thus 1 is a composite (with the trivial factorization of the Π ⟨⟩ empty product).
Thus, 1 is excluded being a prime, naturally and automatically, by definition. We have reached our goal. For this, we have exploited the convention about empty product being 1.
Some drawbacks: although we succeeded to exclude 1 being a prime, but at the same time, 0 "slipped in": 0 became a prime (at least in zero-divisor free rings, like natural numbers). Although this strange thing makes some theorems more concise formally (Goldbach conjecture, fundamental theorem of arithmetic), but I cannot stand for that it is not a drawback.
A bigger drawback, that some concepts of arithmetic seem to become untenable with this new approach.
In any case, I wanted only to demonstrate that defining the empty product as 1 can yield formalizing unintuitive things (which is not necessarily a problem, set theory abounds with unintuitive things, see how to produce gold for free), but at the same time, it can provide useful strength in some contexts.
It's traditional to define the product of all the elements of the empty list to be 1, just as it's traditional to define the sum of all the elements of the empty list to be 0. That way
(product list1) * (product list2) == product (list1 ++ list2)
among other convenient properties.
Also, your memory is correct, and 0! is defined to be 1. This also has many convenient properties, including being consistent with the definition of factorials in terms of the gamma function.
Not sure I understand your question, are you asking how to write such a function?
Just as an exercise, you could use pattern matching to approach it like this:
factorial :: Int->Int
factorial 0 = 1
factorial n = product [1..n]
The first line is the function declaration/type signature. The second two lines are equations defining the function - Haskell pattern matching matches up the actual runtime parameter to whichever equation is appropriate.
Of course as others have pointed out, the product function handles the zero case correctly for you.

Resources