What does it mean to order a set? - alloy

When the ordering module is called with a set then all these functions are suddenly available on the set: first, last, next, prev, etc.
first returns the first atom.
last returns the last atom.
first.next returns the second atom.
But wait!
A set is, by definition, unordered. So how can you order a set?
Consider this set of colors:
abstract sig Color {}
one sig red extends Color {}
one sig yellow extends Color {}
one sig green extends Color {}
What does it mean to order that set of colors? Suppose we call the ordering module:
open util/ordering[Color]
What does first return? What does last return? What does first.next return?
Let’s have Alloy generate some instances:
run {}
Here are a few of the instances that are generated:
Instance #1
first returns: yellow
last returns: green
first.next returns: red
Instance #2
first returns: yellow
last returns: red
first.next returns: green
Instance #3
first returns: green
last returns: yellow
first.next returns: red
Notice that the ordering is different with each instance.
Now, let’s order a plain signature:
open util/ordering[Time]
sig Time {}
run {}
Only one instance is generated:
Instance #1
first returns: Time0
last returns: Time2
first.next returns: Time1
No more instances!
Lessons Learned
For a set created by enumerating its atoms, the ordering module orders the set in any way.
For a set created by a signature, the ordering module orders the set this way: Blah0, Blah1, Blah2, …, where “Blah” is the signature name.
I think the real lesson, however, is that the functions provided in the ordering module (first, last, next, etc.) make it appear that the set is ordered. But that is an illusion, it is just a view placed on top of the set. The set, in fact, has no ordering.
Do I have a correct understanding? Anything you would add to this?

The reason behind this difference holds in 2 words: Symmetry breaking.
In short, Alloy wants to avoid returning isomorphic instances (instances which are the same up to label renaming).
Think of it that way:
When you analyze a model consisting solely of the signature one Time{} the analyzer will return a single instance composed of atom Time$0. Labeling this atom Time$1, Time$2 or CoolAtom won't change the fact that the instance is composed of a single atom of type Time.
When analyzing the model declaring Color as being either red, yellow or green, the analyzer will return 3 instances, each consisting of a different color.
Why you ask? That's because those atoms are semantically different in the sense that they do not have the same type.
Note that in no ways you have created a set enumerating its atoms. You have defined the set of colors as being composed of several sets (red, green, yellow) which all happen to have an arity of one.
Your final understanding however is correct in the sense that using ordering doesn't alter the essence of the signature it is used on (defining a set of atoms), but rather provides functions used to define an ordering on elements typed by the said signature.

When you invoke the ordering module on some set S, you are simply adding an ordering to every instance, as if you explicitly included a homogeneous relation on the set S. As Loic notes, the key reason this is better than doing it explicitly is that you get symmetry breaking for free so better performance (and more convenient atom numbering). And of course, you don't need to axiomatize the ordering yourself.

Related

Difference between initial and terminal objects in a category

Bartosz Milewski, in the section Terminal Object of Chapter 5 underlines the following
Notice that in this example the uniqueness condition is crucial, because there are other sets (actually, all of them, except for the empty set) that have incoming morphisms from every set. For instance, there is a Boolean-valued function (a predicate) defined for every type:
yes :: a -> Bool
yes _ = True
But Bool is not a terminal object. There is at least one more Bool-valued function from every type:
no :: a -> Bool
no _ = False
Insisting on uniqueness gives us just the right precision to narrow down the definition of the terminal object to just one type.
And all this come after the section Initial Object, where a similar observation is not made.
Therefore I have the feeling that I might be missing a key difference between initial and terminal objects.
From my understanding the uniqueness is crucial also for initial objects, because I could observe that there are other sets (actually, all of them) that have an outgoing morphisms to every set (except the empty set), but there would be in general more than one such a morphism (except for the one going to ().
So my question is: is there any difference between initial and terminal objects, beside the direction of the arrows that connect them to the other objects, that Bartosz is probably trying to underline with the quoted text?
I know that question like What does the author mean? can be a bit ill posed, as we are not in his mind, but I guess who knows category theory can throw at least some plausible hypothesis.
that have an outgoing morphisms to every set (except the empty set)
That's the key part. The requirement is that there be outgoing morphisms to every set full stop. The existance of one set where this breaks down is enough to undermine it. That's why, indeed, the initial object in Set is already well-defined without even requiring uniqueness: the empty set is the only set that has an outgoing arrow to the empty set.
Meanwhile, every non-empty set has incoming arrows from truely every set including the empty one, but only for one-element sets is this arrow unique.
Here's the direct quote from the book: "The initial object is the object that has one and only one morphism going to any object in the category." Notice the only one part.
BTW, I was also careful not to say "any other object," because there also is a unique morphism from the initial object to itself: it's always the identity.

UML Class diagram object composed of 4 objects of another class?

I have one object, call it type A which has four data members of another object type, call it B. How do I show this in a UML class diagram so that its clear there are four B objects type in every A object?
Is the only solution to put "4" next to the arrow head pointing to class B?
It depends on what you want to achive, in sense of how you need to distinguish between those objects in context of their association/link, that is - what kind of role they play:
if there are all equal, no special differences in their role in context of A, them a multiplicity 4..4 will do the job, naming the association end properly (for example my_Bs)
If these object play different role in connection with A, then you can use separate associations with lower multiplicities each one, 2, 3 or even 4 pieces (for example, if B is a Wheel and A is Car, then you can put 2 associations with multiplicities 2..2 each, and call then "front" and "rear", or even 4 associations "front_left", "front_right"...)
Here is how the both cases look like. On the second one I showd different possible options (with max. 5 elements of B), just to give you an idea.
It's probably clear by now, but the fundamental concept here is the role of the association end.
Aleks answer is the best. However you can also represent the multiplicity in one box like this :
You cal also use composite structure diagram. See example below:
From my point of view, myBs defined as an attribute of type B on class A has a different meaning of myBs defined as a association's role between A and B (which is also different as defining it as a composition/aggregation).
If it is an attribute, then it's not a role. In that case, there is only a simple dependency relation between A and B, which must appear in the diagram.
I think that problem comes from unconsciously think from a "Relationnal Data (BMS)" and/or a "Object Oriented Programming" point of view, but UML is not intended for that.
:)

Hide a signature in the Show

Can I hide a inused signature when I show the model(when I execute the line "pred show{}
run show for 8")?
For inused signature, I mean the signature which are not connected by no arrow.
For example:
abstract sig TypeMessage{}
one sig RichiestaLogin, RichiestaRegistrazione, RichiestaShell
Not going into the details of my code, there are instances in which I use a message type and other instances in which their use, so that some istances remain unconnected.
I would not show those instances are not connected in my diagram of the model.
If you don't want them in your model, constrain your model (or probably better the 'show' predicate) to exclude models which have unconnected atoms (where 'connected' means whatever you want it to mean).
If you really want to allow them in the model instances, but exclude them just from the display, you can define a subset of TypeMessage which contains just those TypeMessage atoms which are not connected. Then customize your display theme to suppress display of members of that set.
If the only problem is that you find the unconnected atoms distracting, I'd try to learn not to be distracted by them.

The util/ordering module and ordered subsignatures

Consider the following Alloy model:
open util/ordering[C]
abstract sig A {}
sig B extends A {}
sig C extends A {}
pred show {}
run show for 7
I understand why, when I run show for 7, all the instances of this model have 7 atoms of signature C. (Well, that's not quite true. I understand that the ordered signature will always have as many atoms as the scope allows, because util/ordering tells me so. But that's not quite the same as why.)
But why do no instances of this model have any atoms of signature B? Is this a side-effect of the special handling performed for util/ordering? (Intended? Unintended?) Is util/ordering intended to be applied only to top-level signatures?
Or is there something else going on that I am missing?
In the model from this this is abstracted, I'd really like to have a name like A for the union of B and C, and I'd really like C to be ordered, and I'd really like B to be unordered and non-empty. At the moment, I seem to able to achieve any two of those goals; is there a way to manage all three at the same time?
[Addendum: I notice that specifying run show for 3 but 3 B, 3 C does achieve my three goals. By contrast, run show for 2 but 3 B produces no instances at all. Perhaps I need to understand the semantics of scope specifications better.]
Short answer: the phenomena reported result from the rules for default and implicit scopes; those rules are discussed in section B.7.6 of the Language Reference.
Longer answer:
The eventual suspicion that I should look at the semantics of scope specifications more closely proved to be warranted. In the example shown here, the rules work out exactly as documented:
For run show for 7, signature A has a default scope of 7; so do B and C. The use of the util/ordering module forces the number of C atoms to 7; that also exhausts the quota for signature A, which leaves signature B with an implicit scope of 0.
For run show for 2 but 3 B, signature A has a default scope of 2, and B has an explicit scope of 3. This leaves signature C with an implicit signature of 2 minus 3, or negative 1. That appears to count as an inconsistency; scope bounds are expected to be natural numbers.
For run show for 2 but 3 B, 3 C, signature A gets an implicit bound of 6 (the sum of its subsignatures' bounds).
As a way of gaining a better understanding of the scope rules, it proved useful to this user to execute all of the following commands:
run show for 3
run show for 3 but 2 C
run show for 3 but 2 B
run show for 3 but 2 B, 2 C
run show for 3 but 2 A
run show for 3 but 2 A, 2 C
run show for 3 but 2 A, 2 B
run show for 3 but 2 A, 2 B, 2 C
I'll leave this question in place for other answers and in the hope that it may help some other users.
I understand that the ordered signature will always have as many atoms as the scope allows, because util/ordering tells me so. But that's not quite the same as why.
The reason is that when forcing an ordered sig to contain as many atoms as the scope allows it is possible for the translator to generate an efficient symmetry breaking predicate, which, in most examples with ordered sigs, results in much better solving time. So it is simply a trade-off, and the design decision was to enforce this extra constraint in order to gain performance.

Achieving the right abstractions with Haskell's type system

I'm having trouble using Haskell's type system elegantly. I'm sure my problem is a common one, but I don't know how to describe it except in terms specific to my program.
The concepts I'm trying to represent are:
datapoints, each of which takes one of several forms, e.g. (id, number of cases, number of controls), (id, number of cases, population)
sets of datapoints and aggregate information: (set of id's, total cases, total controls), with functions for adding / removing points (so for each variety of point, there's a corresponding variety of set)
I could have a class of point types and define each variety of point as its own type. Alternatively, I could have one point type and a different data constructor for each variety. Similarly for the sets of points.
I have at least one concern with each approach:
With type classes: Avoiding function name collision will be annoying. For example, both types of points could use a function to extract "number of cases", but the type class can't require this function because some other point type might not have cases.
Without type classes: I'd rather not export the data constructors from, say, the Point module (providing other, safer functions to create a new value). Without the data constructors, I won't be able to determine of which variety a given Point value is.
What design might help minimize these (and other) problems?
To expand a bit on sclv's answer, there is an extended family of closely-related concepts that amount to providing some means of deconstructing a value: Catamorphisms, which are generalized folds; Church-encoding, which represents data by its operations, and is often equivalent to partially applying a catamorphism to the value it deconstructs; CPS transforms, where a Church encoding resembles a reified pattern match that takes separate continuations for each case; representing data as a collection of operations that use it, usually known as object-oriented programming; and so on.
In your case, what you seem to want is an an abstract type, i.e. one that doesn't export its internal representation, but not a completely sealed one, i.e. that leaves the representation open to functions in the module that defines it. This is the same pattern followed by things like Data.Map.Map. You probably don't want to go the type class route, since it sounds like you need to work with a variety of data points, rather than on an arbitrary choice of a single type of data point.
Most likely, some combination of "smart constructors" to create values, and a variety of deconstruction functions (as described above) exported from the module is the best starting point. Going from there, I expect most of the remaining details should have an obvious approach to take next.
With the latter solution (no type classes), you can export a catamorphism on the type rather than the constructors..
data MyData = PointData Double Double | ControlData Double Double Double | SomeOtherData String Double
foldMyData pf cf sf d = case d of
(PointData x y) -> pf x y
(ControlData x y z) -> cf x y z
(SomeOtherData s x) -> sf s x
That way you have a way to pull your data apart into whatever you want (including just ignoring the values and passing functions that return what type of constructor you used) without providing a general way to construct your data.
I find the type-classes-based approach better as long as you are not going to mix different data points in a single data structure.
The name collision problem you mentioned can be solved by creating a separate type class for each distinct field, like this:
class WithCases p where
cases :: p -> NumberOfCases

Resources