I want to change the service code of an object whenever there has been any service operated upon it. Suppose, I have a operation whenever that applies to an object, the service code of that object will be 1 and again when another operation executes then the service code will be 2. I want to save the latest service code to each object. Unfortunately, I am not able design my predicate well, that's why getting predicate inconsistent message from alloy.
I have tried some code for assigning service code to each object. The complete code shown below-
open util/ordering[Environment]
abstract sig Object{
name: String,
serviceCode: Int,
}{
serviceCode >= 0 and serviceCode <= 3
}
// Events
enum Event {Event1, Event2, Event3}
abstract sig Condition{
name: Event,
object: Object
}
abstract sig BaseOperation{
name: Event,
object: Object
// it will have more attributes than Condition later
}
abstract sig Connector{
condition: Condition,
baseOperation: BaseOperation,
}
sig Environment{
ev : set Event
}
pred execute [u:Environment, u':Environment, r:Connector] {
some e: u.ev | {
e = r.condition.name =>
u'.ev = u.ev + r.baseOperation.name
else
u'.ev = u.ev
}
}
fact {
all u:Environment-last, u':u.next, r:Connector {
execute [u, u', r]
}
}
sig Object1 extends Object{
}{
name = "Object1 Object"
}
sig Object2 extends Object{
}{
name = "Object2 Object"
}
sig Condition1 extends Condition{
}{
name = Event1
object = Object2
object.serviceCode = 1
}
sig Operation1 extends BaseOperation{
}{
name = Event2
object = Object1
object.serviceCode = 1
}
sig Operation2 extends BaseOperation{
}{
name = Event3
object = Object1
object.serviceCode = 0
}
one sig Connector1 extends Connector{
}{
condition = Condition1
baseOperation = Operation1
}
one sig Connector2 extends Connector{
}{
condition = Condition1
baseOperation = Operation2
}
fact {
Event3 !in first.ev &&
Event2 !in first.ev
}
run {Event1 in last.ev} for 10
The above code works fine when I have only one operation link to one object. I have attached the diagram for it here . Whenever there is more than one operation, then alloy fails to find an instance. Need help on designing alloy code for achieving my goal.
Another possible approach might be- instead of one service code, we may have a list of service code. Considering timestamp along with each service code. Then when need to find out the latest service code. We can take the service code of max timestamp. But I am not sure how to design this in alloy.
I think you should take a look at Daniel Jackson's book. Alloy is not a programming language with mutable assignments. It is basically a rule engine over relations that can generate an instance, a set of relations matching those rules. This means that if you need mutable assignments then you need a way to represent the mutable state over time in a relation. There are two ways:
Time
– Make each field have a column with Time
, where Time
is ordered. I find this quite cumbersome. The Electrum project made this easier by providing a var
keyword that then maintains the Time
column for you.Trace
– Instead of associating each field with a Time
, you can also place the associations in a state sig
that is ordered. That relation then shows how the values change over time.The key problem is that your problem description is almost completely disconnected from the specification. You talk about Service and then later Operation, are they the same? Where do Event
and Connector
come in? They are never mentioned in your problem description?
Let's take it one by one:
I want to change the service code of an object
open util/ordering[Environment]
sig Object {}
enum ServiceCode { _1, _2 }
sig Environment {
object : Object -> ServiceCode
}
In general, you do not want to use Ints for things like Service Code since they tend to blow up the state space.
The Environment
is our state. We want to execute one Service per Environment atom.
... whenever there has been any service operated upon it.
sig Service {
serviceCode : ServiceCode
}
pred execute[ e, e' : Environment, o : Object, s : Service ] {
e'.object = e.object ++ o -> s.serviceCode
}
Suppose, I have an Operation whenever that applies to an Object,
It is not clear what you mean with Operation, I assume this is the earlier Service?
... the Service Code of that Object will be 1 and again when another Operation executes then the ServiceCode will be 2. I want to save the latest service code to each object. Unfortunately,
pred trace {
no first.object
all t : Environment-last, t':t.next {
some o: Object, s : Service {
execute[t,t', o, s]
}
}
}
run trace
In the table view this gives you:
┌────────────────┐
│this/ServiceCode│
├────────────────┤
│_1⁰ │
├────────────────┤
│_2⁰ │
└────────────────┘
┌───────────┐
│this/Object│
├───────────┤
│Object⁰ │
├───────────┤
│Object¹ │
└───────────┘
┌────────────┬───────────┐
│this/Service│serviceCode│
├────────────┼───────────┤
│Service⁰ │_2⁰ │
├────────────┼───────────┤
│Service¹ │_2⁰ │
├────────────┼───────────┤
│Service² │_1⁰ │
└────────────┴───────────┘
┌────────────────┬───────────┐
│this/Environment│object │
├────────────────┼───────────┤
│Environment⁰ │ │
├────────────────┼───────┬───┤
│Environment¹ │Object¹│_2⁰│
├────────────────┼───────┼───┤
│Environment² │Object⁰│_1⁰│
│ ├───────┼───┤
│ │Object¹│_2⁰│
└────────────────┴───────┴───┘
When you use Alloy the first thing you should do is define the problem you want to specify in plain English. You then translate the concepts in this text to Alloy constructs. The goal of an Alloy spec is to make it read like prose.