Вы находитесь на странице: 1из 14

Вращающаяся дверь

Во трехсекционную вращающуюся дверь можно войти/выйти с двух сторон. В


нормальном состоянии она неподвижна, а при приближении пользователя
начинает вращение. Вращение продолжается, пока пользователь находится
внутри пространства вращения. Вращение останавливается, когда
пользователь покидает это пространство. Вращение приостанавливается на
небольшое время, когда на секционные перегородки оказывается давление.

Требования и процессы

Параллельные процессы:
1. Вращение дверей
2. Датчик приближения пользователя(2)
3. Датчик внутри каждой секции(3)
4. Датчик касания на перегородки(3)
5. Контроллер
6. Пользователь

Требования к функционированию системы:


● Состояние по умолчанию - двери неподвижны
● При приближении пользователя, двери начинают вращаться
● Пока внутри дверей находится пользователь, то двери вращаются
● Вращение приостанавливается на некоторое время, когда пользователь
оказывает давление на секционные перегородки
● Вращение останавливается, если пользователь покидает пространство

События-состояния процессов
● Вращение дверей - engine_on, engine_off
● Пользователь - user_present, user_absent, user_touching
● Датчик приближения пользователя - detected_user, not_detecting,
user_present, user_absent
● Датчик внутри каждой секции - detected_user, not_detecting, user_present,
user_absent
● Датчик касания на перегородки - detected_touching, not_detecting,
user_touching
● Контроллер- почти половина от всего выше перечисленного
Структуры Крипке процессов
Требования в LTL
Требования к функционированию системы:
1. При приближении пользователя, двери начинают вращаться
G(user_detected(proximity sensor)→ F (engine_on) )
2. Вращение останавливается, если пользователь покидает пространство
G(not_detecting(proximity sensor) → F (engine_off U user_detected(proximity
sensor) ))
3. Вращение приостанавливается на некоторое время, когда пользователь
оказывает давление на секционные перегородки
G(user_touching → F ((engine off) ∧ F (engine_on)) )

CSP-процессы
Датчик приближения:
● αProximitySensor= { detected_user, not_detecting, user_present,
user_absent}.
● ProximitySensor=not_detecting → ProximitySensorMain
● ProximitySensorMain = not_detecting→ ProximitySensorMain |
not_detecting→ user_present→ detected_user→user_absent→
ProximitySensor

Датчик присутствия:
● αPresenceSensor= { detected_user, not_detecting, user_present,
user_absent}.
● PresenceSensor=not_detecting → PresenceSensorMain
● PresenceSensorMain = not_detecting→ PresenceSensorMain |
not_detecting→ user_present→ detected_user→user_absent→
PresenceSensor

Датчик прикосновения:
● αTouchSensor= { not_detecting, user_touching, detected_touching}.
● TouchSensor=not_detecting → TouchMain
● TouchMain = not_detecting→ TouchMain |
not_detecting→ user_touching→ detected_touching → TouchSensor

Двигатель:
● αEngine= { engine_on, engine_off }.
● Engine= engine_on → engine_off→ Engine

Контроллер:
● αCont= {wait, detected_touching, engine_off, engine_on,
detected_user(ProxS), not_detecting(ProxS), not_detecting(PresS),
detected_user(PresS) }.
● Cont= wait → detected_user(ProxS) → engine_on → ContChoice |
wait → detected_user(PresS) → engine_on → ContChoice
● ContChoice = not_detecting(ProxS) → engine_off→ wait → Cont |
not_detecting(PresS) → engine_off→ wait → Cont |
detected_touching → engine_off→ wait → Cont

Пользователь:

● αUser= {user_present, user_absent, user_touching}.


● Недетерминированное поведение

Трейсы процессов
Формализуйте 3 вида трейсов Контроллера длины 10
● t1 = <wait, detected_user(ProxS), engine_on, detected_touching, engine_off, wait,
detected_user(PresS), engine_on, not_detecting(PresS), wait>
● t2 = <wait, detected_user(ProxS), engine_on, not_detecting(PresS), engine_off,
wait, detected_user(ProxS), engine_on, not_detecting(PresS), wait>
● t3 = <wait, detected_user(ProxS), engine_on, detected_touching, engine_off, wait,
detected_user(PresS), engine_on, detected_touching, wait>

Постройте сужение (↾) трейсов относительно событий другого


процесса
● t1↾ αEngine = <engine_on, engine_off, engine_on>
● t2↾ αEngine = <engine_on, engine_off, engine_on>
● t3↾ αEngine = <engine_on, engine_off, engine_on>

Сравните исходные трейсы и их сужения.


Они несравнимы, поскольку никакой трейс не является префиксом другого. Можно
заметить, что сужения короче своих трейсов по длине, соответственно.
Выберите короткий процесс(Engine) и формализуйте его трейс
𝑛
● ⋃ (𝑒𝑛𝑔𝑖𝑛𝑒_𝑜𝑛 ˆ 𝑒𝑛𝑔𝑖𝑛𝑒_𝑜𝑓𝑓 )
𝑛≥1

Запишите процесс P after s, где P -- Контроллер, а s -- трейс длины 3


Пусть s = <wait, detected_user(ProxS), engine_on>
P / s = ContChoice

● Cont= wait → detected_user(ProxS) → engine_on → ContChoice |


wait → detected_user(PresS) → engine_on → ContChoice
● ContChoice = not_detecting(ProxS) → engine_off→ wait → Cont |
not_detecting(PresS) → engine_off→ wait → Cont |
detected_touching → engine_off→ wait → Cont

Определите, являются ли циклическими в CSP-смысле все


процессы Вашей системы и объясните, почему
Все процессы являются циклическими в CSP-смысле, потому что можно вернуться в
начальное состояние, что следует из определения.

Спецификация. Interaction and Concurrency.


Формализуйте спецификацию 3 свойств Контроллера в
CSP-терминах
1. При приближении пользователя, контроллер обязательно отправит
сигнал дверям начинать вращаться
S1(tr) = tr ↓ user_detected(proximity sensor) - tr ↓ engine_on <=1
2. Если контроллеру подается сигнал , что пользователь покинул
пространство, то он подает сигнал, чтобы двери остановились
S2(tr) = tr ↓ not_detecting(proximity sensor) - tr ↓ engine_ off<=1
3. Вращение приостанавливается на некоторое время, когда пользователь
оказывает давление на секционные перегородки
S3(tr) = (tr ↓ user_touching)≥1 → ((tr ↓ engine_off )≥(tr ↓ engine_on ) )
Задайте параллельное исполнение двух процессов своей системы с
пересекающимися алфавитами.с помощью законов для
параллельного исполнения опишите P1||P2 без использования ||.
Должны быть приведены процессы P1, P2 и P1||P2.

Двигатель:
● αEngine= { engine_on, engine_off }.
● Engine= engine_on → engine_off→ Engine

Контроллер:

● αCont= {wait, detected_touching, engine_off, engine_on,


detected_user(ProxS), not_detecting(ProxS), not_detecting(PresS),
detected_user(PresS) }.
● Cont= wait → detected_user(ProxS) → engine_on → ContChoice |
wait → detected_user(PresS) → engine_on → ContChoice
● ContChoice = not_detecting(ProxS) → engine_off→ wait → Cont |
not_detecting(PresS) → engine_off→ wait → Cont |
detected_touching → engine_off→ wait → Cont

Cont || Engine =( wait → detected_user(ProxS) → engine_on → ContChoice| wait


→ detected_user(PresS) → engine_on → ContChoice) || (engine_on →
engine_off→ Engine) =
(by L5A) ((wait → detected_user(ProxS) |detected_user(PresS) ) → engine_on →
ContChoice) || (engine_on → engine_off→ Engine) =
(by L4A) (wait → detected_user(ProxS) |detected_user(PresS) ) → engine_on→
(ContChoice || (engine_off→ Engine)) =
(by L6) ( (wait → detected_user(ProxS) |detected_user(PresS) )→
(engine_on→ContChoice) || (engine_off→ Engine) | engine_off→(ContChoice ||
Engine)) =
(by L5B) (wait → detected_user(ProxS) |detected_user(PresS) )→
engine_off→((engine_on→ ContChoice) || Engine) | engine_off→(ContChoice ||
Engine) =
((wait → detected_user(ProxS) |detected_user(PresS) )→
engine_off→engine_on→(ContChoice || (engine_off→ Engine)) | engine_off→(wait
→ detected_user(ProxS) |detected_user(PresS))→engine_on→(ContChoice ||
(engine_off→ Engine)) ) =
μX • ((wait → detected_user(ProxS) |detected_user(PresS) )→
engine_off→engine_on→X | engine_off→(wait → detected_user(ProxS)
|detected_user(PresS))→engine_on→X)
ContChoice || Engine = ContChoice = (not_detecting(ProxS) → engine_off→ wait
→ Cont | not_detecting(PresS) → engine_off→ wait → Cont |detected_touching →
engine_off→ wait → Cont) || (engine_on → engine_off→ Engine) =
((not_detecting(ProxS)| not_detecting(PresS)| detected_touching) → engine_off→ wait
→ Cont) || (engine_on→ engine_off→ Engine) =
(by L5B) engine_on→((((not_detecting(ProxS)| not_detecting(PresS)|
detected_touching) → engine_off→ wait → Cont) || (engine_off→ Engine))) =
(by L5A) engine_on→((not_detecting(ProxS)| not_detecting(PresS)|
detected_touching)→ ((engine_off→ wait → Cont) || (engine_off→ Engine))) =
(by L4A) engine_on→((not_detecting(ProxS)| not_detecting(PresS)|
detected_touching)→(engine_off→( (wait → Cont )|| Engine)) =
(by L6 ) engine_on→((not_detecting(ProxS)| not_detecting(PresS)|
detected_touching)→(engine_off→(wait →(Cont || Engine)) | ((wait→Cont ) ||
Engine))) =
(engine_on→(not_detecting(ProxS)| not_detecting(PresS)|
detected_touching)→(engine_off→(wait →Cont || Engine)) | (not_detecting(ProxS)|
not_detecting(PresS)| detected_touching)→ engine_on→(engine_off→(wait→Cont ||
Engine))) =
μX •(engine_on→(not_detecting(ProxS)| not_detecting(PresS)|
detected_touching)→(engine_off→X) | (not_detecting(ProxS)| not_detecting(PresS)|
detected_touching)→ engine_on→(engine_off→X))

Change of symbol. Multiple labelling.


Процесс BOOL
BOOL = f(DD)
DD = (setorange → O | setlemon → L)
O = (orange → O | setlemon → L | setorange → O)
L = (lemon → L | setorange → O | setlemon → L)
f(setorange) = assign0
f(setlemon) =assign1
f(orange) = fetch0
f(lemon) = fetch1

BOOL = (assign0 -> False | assign1 -> True)


False = (fetch0 -> False | assign1 -> True | assign0 -> False)
True = (fetch1 -> True | assign0 -> False | assign1 -> True )
Определить процессы, которые получаются изменением
символов.
ProximitySensor = f(PresenceSensor)
● f(not_detecting(PresenceSensor)) = not_detecting(ProximitySensor )
● f(detected_user(PresenceSensor)) = detected_user(ProximitySensor )
● f(user_present) = user_present
● f(user_absent) = user_absent

Построить полное описание своей параллельной системы с


использованием переименования и множественной
пометки.
S = {ProximitySensor, PresenceSensor}
Sensors = {S : Sensor}
αSensor = {not_detecting, user_touching, detected_touching}
Revolving doors = Sensors || TouchingSensor || Engine || Controller || User

Записать модифицированный процесс FOOTMAN со стр. 15


лекции 7 (+ 5). Доказать, что этот процесс гарантирует
сытость философов (+5).
𝐹𝑂𝑂𝑇0 = (𝑥 : 𝐷 → 𝐹𝑂𝑂𝑇1)
𝐹𝑂𝑂𝑇𝑗 = (𝑥 : 𝐷 → 𝐹𝑂𝑂𝑇𝑗+1 | 𝑦 : 𝑈 → 𝐹𝑂𝑂𝑇𝑗−1) 𝑓𝑜𝑟 𝑗 ∈ {1, 2, 3}
𝐹𝑂𝑂𝑇4 = (𝑦 : 𝑈 → 𝐹𝑂𝑂𝑇3)
4
● 𝑈 = ⋃ {𝑖. 𝑔𝑒𝑡𝑠 𝑢𝑝}
𝑖=0
4
● 𝐷 = ⋃ {𝑖. 𝑠𝑖𝑡𝑠 𝑑𝑜𝑤𝑛}
𝑖=0

𝐹'(𝑖. 𝑠𝑖𝑡𝑠 𝑑𝑜𝑤𝑛) = 𝑖. 𝑝𝑖𝑐𝑘𝑠 𝑢𝑝 𝑓𝑜𝑟𝑘. 𝑖 → 𝑖. 𝑝𝑖𝑐𝑘𝑠 𝑢𝑝 𝑓𝑜𝑟𝑘. (𝑖⊕1)

Д-во:
То есть никто не может сесть, пока философ не возьмет две вилки.
Предположим, что у нас есть философ A, который пока голодает. Почему он не
сможет голодать вечно в такой системе. Предположим, что он будет голодать
все время, но соседи(то есть либо левый, либо правый), не может вечно есть,
значит левый или правый сосед уйдет и тогда, чтобы наш философ продолжил
голодать, то новый пришедший сосед должен взять вилку раньше, чем наш. Но
это невозможно, потому что FOOTMAN не будет провожать соседа, пока наш
философ не возьмет вилку. То есть, что мы предположили, было неверно.
Deadlock - быть не может, ибо FOOTMAN ограничивает философов - 4-мя.

P.S.: Проблема моей реализации, что в ней ограничения больше, чем надо. То
есть можно было сделать ограничение только на то, что нельзя садиться
соседним философам, а не всем. Но я пока не смог придумать, как это
реализовать.

Specifications. Nondeterminism.

1. Найти в своей системе процессы, параллельная


комбинация которых точно не имеет тупиков (deadlocks).
● αProximitySensor ∩ αEngine = {} ⇒ [by L2] (ProximitySensor || Engine) never
stops.
● αPresenceSensor ∩ αEngine = {} ⇒ [by L2] (PresenceSensor || Engine)
never stops.
● αTouchSensor ∩ αEngine = {} ⇒ [by L2] (TouchSensor || Engine) never
stops.
● αUser ∩ αEngine = {} ⇒ [by L2] (User || Engine) never stops.
● αUser ∩ αTouchSensor = {user_touching} ⇒ [by L2] (User || TouchSensor )
never stops.
● αProximitySensor ∩ αTouchSensor = {} ⇒ [by L2] (ProximitySensor ||
TouchSensor ) never stops.
● αPresenceSensor ∩ αTouchSensor = {} ⇒ [by L2] (PresenceSensor ||
TouchSensor ) never stops.

2. Записать процесс пользователя (внешней среды),


используя строго недетерминированный выбор.
A_init = user_absent→ A
A = user_absent → A П (user_present →(A_init П user_touching → A_init ))

3. «Испортить» какой-либо процесс системы и записать


множества отказов связанных с ним параллельных
процессов.
A_init = user_absent→ A П user_touching → A_init
A = user_absent → A П (user_present →(A_init П user_touching → A_init ))
refuse(Cont)= {detected_touching}
refuse(TouchSensor) = {detected_touching}
Concealment. Specifications: Nondeterminism.

1. Выбрать процесс и множество его событий, в котором их


сокрытие не приводит к дивергенции. Записать это
множество событий, и процесс, получившийся в результате
их сокрытия.
αEngine= { engine_on, engine_off }.
E1 = {engine_on }
Engine/E1 = engine_off → Engine/E1

2. Выбрать процесс и множество его событий, в котором их


сокрытие приводит к дивергенции. Записать это множество
событий, и процесс, получившийся в результате их
сокрытия
αEngine= { engine_on, engine_off }.
E2 = {engine_on,engine_off }
Engine/E2 = Engine/E2

3. Записать спецификацию недетерминированного


процесса пользователя (среды) с учётом отказов.
NormalUser = (tr ↓ detected_touching = tr ↓ user_touching⟹ user_touching ∉ ref)

Communication.

Предположим, что пользователь(среда) может


генерировать последовательность сигналов быстрее, чем
контроллер может их обработать. Модифицировать
процессы системы, чтобы эта последовательность
сигналов обрабатывалась так, что Controller получал бы
значение последнего сигнала.
В моей системе такой сигнал пользователь может сгенерировать с помощью
прикосновения к перегородки в двери, то есть он может очень много и быстро
касаться ее. Для этого введем канал передачи данных между User и
TouchSensor и модифицируем соответствующие процессы:

User = user_absent → User_main


User_main = user_absent → User_main ⊓ user_absent → user_present →
User_main ⊓ user_absent → user_present →TouchChannel ! user_touching →
User

TouchSensor=not_detecting → TouchMain
TouchMain = not_detecting→ TouchMain |
not_detecting→ TouchChannel ? user_touching → detected_touching
→ TouchSensor

Subordination
Задать CSP-спецификацию параллельного взаимодействия
с подчинением для пары процессов системы.
Я взял процессы Двигатель и Контроллер(Двигатель подчиняется Контроллеру):
αCont ⊆ αEngine

Двигатель:

Engine= Left ? x → if x = engine_on then Right ! engine_off else Right ! engine_on


→ Engine

Контроллер:
Тут по сути Контроллер отправляет текущее состояние двигателя в левый
канал, а на правый получает новое состояние двигателя и продолжает работу,
или нет, если что-то не то.

m: Engine // Cont

● Cont= wait → detected_user(ProxS) → m.Left ! engine_off → m.Right ? x if x


= engine_on then ContChoice else Cont | wait → detected_user(PresS) →
m.Left ! engine_off → m.Right ? x if x = engine_on then ContChoice else
Cont
● ContChoice = not_detecting(ProxS) → m.Left ! engine_on → m.Right ? x if x
= engine_off then (wait → Cont) else ContChoice |
not_detecting(PresS) → m.Left ! engine_on → m.Right ? x if x =
engine_off then (wait → Cont) else ContChoice |
detected_touching → m.Left ! engine_on → m.Right ? x if x =
engine_off then (wait → Cont) else ContChoice
Sequential Processes. Interrupts

Найти все процессы системы, которые можно описать с


помощью прерываний другим процессом. Записать
соответствующую модификацию этих процессов с
указанием среды, которая регулирует эти прерывания.
User and Sensors:

● ProximitySensor = μX ((not_detecting→ X) △ (user_present→


detected_user→user_absent→ X))
● PresenceSensor =μX ((not_detecting→ X) △ ( user_present→
detected_user→user_absent→ X))
● TouchSensor = μX((not_detecting→ X) |(user_touching→ detected_touching
→ X))

Sharing by interleaving

Найти процесс системы, который могут разделить два


пользователя (или две среды). Записать соответствующую
модификацию этих процессов с запросами и
освобождениями.
TouchSensor = not_detecting → TouchSensor | acquire → (left ? touching) →
detected_touching → release → TouchSensor

User = user_absent → User_main


User_main = user_absent → User_main | user_absent → user_present →
User_main | user_absent → user_present →touchSensor.acquire → right !
touching → release → User

Multiple resources.
Найти процессы системы, которые могут быть
множественными ресурсами, которые разделяют другие
процессы системы. Записать соответствующую
модификацию этих процессов и всей системы.

Пусть будет несколько вращающихся дверей(RevolvingDoors) и несколько


пользователей(по сути приближенная система к реальности)

Вращающаяся дверь:
RevolvingDoor = ProximitySensor || PresenceSensor || TouchSensor || Engine ||
Cont

Вращающиеся двери:
RevolvingDoors = ||(i<B) i:RevolvingDoor

Датчик приближения:
● αProximitySensor= { detected_user, not_detecting, user_present,
user_absent}.
● ProximitySensor=not_detecting → ProximitySensorMain
● ProximitySensorMain = not_detecting→ ProximitySensorMain |
not_detecting → user_present→ □(i<B) RevolvingDoor.i.detected_user
→prox.right ! i. → user_absent→ ProximitySensor

Датчик присутствия:
● αPresenceSensor= { detected_user, not_detecting, user_present,
user_absent}.
● PresenceSensor=not_detecting → PresenceSensorMain
● PresenceSensorMain = not_detecting→ PresenceSensorMain |
not_detecting→ user_present→ □(i<B) RevolvingDoor.i.detected_user
→press.right ! i. →user_absent→ PresenceSensor

Датчик прикосновения:
● αTouchSensor= { not_detecting, user_touching, detected_touching}.
● TouchSensor=not_detecting → TouchMain
● TouchMain = not_detecting→ TouchMain |
not_detecting→ user_touching→ □(i<B)
RevolvingDoor.i.detected_touching →touch.right ! i.→ TouchSensor
Двигатель:
● αEngine= { engine_on, engine_off }.
● Engine= engine_on → engine_off→ Engine

Контроллер:
● αCont= {wait, detected_touching, engine_off, engine_on,
detected_user(ProxS), not_detecting(ProxS), not_detecting(PresS),
detected_user(PresS) }.
● Cont(i)= wait → detected_user(ProxS) → engine_on → ContChoice(i) |
wait → detected_user(PresS) → engine_on → ContChoice(i)
● ContChoice(i) = not_detecting(ProxS) → engine_off→ wait → Cont (i) |
not_detecting(PresS) → engine_off→ wait → Cont (i) |
detected_touching → engine_off→ wait → Cont(i)
Пользователь:
User(i) = user_absent → User_main(i)
User_main(i) = user_absent → User_main ⊓ user_absent → user_present →
prox.right ? i → User_main ⊓ user_absent → user_present → prox.right ? i
→pres.right ? i → User_main ⊓ user_absent → user_present → press.right ?
i → user_touching → touch.right ? i → User(i)

Вам также может понравиться