I'm trying to write a simple (I thought) model in Alloy, but clearly I didn't get the point ...
The problem is very simple ... A graph that models a network of roads.
Obv a car can be on a Road OR on a CrossRoad, but not in both of them. Here there's my code:
//SIGNATURES
sig Cross {
var cars: set Car,
roads: some Road
}
sig Road {
var cars: set Car
}
sig Car {}
//FACTS
fact CrossConstraints {
(all r : Road |
#({cr : Cross | r in cr.roads}) = 2)
}
fact CarConstraints {
(all c : Car |
no cr1, cr2 : Cross |
c in cr1.cars and c in cr2.cars)
(all c : Car |
no r1, r2 : Road |
c in r1.cars and c in r2.cars)
(all c : Car |
(one r : Road | c in r.cars ) or
(one cr : Cross | c in cr.cars))
}
fact {
#Car > 1
}
It all seems good to me, but the analyser doesn't find and instance of my model ... It seems the problem lies in the constraints defined for `` Car ```, which actually seem very reasonable to me.
Any idea? Thanks
The usual solution to "debug" an inconsistent spec is to comment facts out and see if the spec becomes consistent, which gives hints to what may be an issue.
Here, the CarConstraints
fact is too strong indeed. You're saying that:
Here, you rather meant that a car cannot be in two crosses unless they happen to be the same cross. Said otherwise, you want cars
(for both Cross
and Road
to be injective). To state this (for crosses), you have several choices:
(all c : Car |
no disj cr1, cr2 : Cross |
c in cr1.cars and c in cr2.cars)
or
// I prefer this because it doesn't feature negation, which is error-prone
(all c : Car, cr1, cr2 : Cross |
c in cr1.cars and c in cr2.cars implies cr1 = cr2)
and finally, since this is a structural fact corresponding to a physical reality, you may directly state this in the domain model (and remove the corresponding fact statement at once):
sig Cross {
var cars: disj set Car,
roads: some Road
}
(technically, the last one is stronger since it comes with an implicit always
in front of it; in any case, your facts should probably come with an always
prepended).
Also, cardinality constraints related to the instances you want to witness (CrossConstraints
and #Car > 1
) should IMO go in a run
command rather than be stated as facts. Facts should IMO almost only be used for general truths.