Я думаю, вам стоит взглянуть на книгу Дэниела Джексона.Alloy не является языком программирования с изменяемыми назначениями.В основном это механизм правил над отношениями, который может генерировать экземпляр , набор отношений, соответствующих этим правилам.Это означает, что если вам нужны изменяемые назначения, вам нужен способ представления изменяемого состояния во времени в отношении.Есть два способа:
Time
- сделать так, чтобы в каждом поле был столбец с Time
, где упорядочено Time
.Я нахожу это довольно громоздким.Проект Electrum упростил эту задачу, предоставив ключевое слово var
, которое затем поддерживает столбец Time
. Trace
- Вместо того, чтобы связывать каждое поле с Time
Вы также можете поместить ассоциации в упорядоченное состояние sig
.Затем это соотношение показывает, как значения меняются со временем.
Ключевая проблема заключается в том, что описание вашей проблемы почти полностью отсоединено от спецификации.Вы говорите о Службе , а затем о Операции , они одинаковы?Откуда Event
и Connector
входят?Они никогда не упоминаются в описании вашей проблемы?
Давайте рассмотрим это один за другим:
Я хочу изменить сервисный код объекта
open util/ordering[Environment]
sig Object {}
enum ServiceCode { _1, _2 }
sig Environment {
object : Object -> ServiceCode
}
Как правило, вы не хотите использовать Ints для таких вещей, как код службы, поскольку они имеют тенденцию взрывать пространство состояний.
Environment
наше состояние .Мы хотим выполнить одну Службу для каждого атома Среды.
... всякий раз, когда какая-либо служба работала с ним.
sig Service {
serviceCode : ServiceCode
}
pred execute[ e, e' : Environment, o : Object, s : Service ] {
e'.object = e.object ++ o -> s.serviceCode
}
Предположим, у меня есть Операция всякий раз, когда это относится к Объекту ,
ItНепонятно, что вы имеете в виду под Операцией , я предполагаю, что это более ранняя Служба ?
... Сервисный код для этого Object будет 1, и снова, когда другая Operation будет выполнена, тогда ServiceCode будет 2. Я хочу сохранить последний сервисный код для каждого объекта.К сожалению,
pred trace {
no first.object
all t : Environment-last, t':t.next {
some o: Object, s : Service {
execute[t,t', o, s]
}
}
}
run trace
В табличном представлении это дает вам:
┌────────────────┐
│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⁰│
└────────────────┴───────┴───┘
Когда вы используете Alloy, первое, что вам нужно сделать, это определить проблему, которую вы хотите указать впростой английский.Затем вы переводите понятия в этом тексте в конструкции Alloy.Цель спецификации Alloy - сделать ее читаемой как проза.