I'm a beginner on Event-B and I'm trying to model a hotel system. In context I have set of Rooms for booking Customer who can make a reservation, checkin, checkout and cancellation. I also have Permission when the room is Empty or Occupied and Options it means that the hotel has different types of room such as one beds, double beds, etc.
This is my context:
CONTEXT
HotelData ›
SETS
⚬ ROOMS ›
⚬ CUSTOMERS ›
⚬ PERMISSION ›
⚬ OPTION ›
CONSTANTS
⚬ ROOM_NUMBER ›
⚬ OCCUPIED ›
⚬ EMPTY ›
⚬ Options ›
AXIOMS
⚬ axm1: finite(ROOMS) not theorem ›
⚬ axm3: ROOM_NUMBER ∈ ROOMS → ℕ not theorem ›
⚬ axm4: partition(PERMISSION, {OCCUPIED}, {EMPTY}) not theorem ›
⚬ axm5: Options ∈ ROOMS ↔ OPTION not theorem ›
⚬ axm6: dom(Options) = ROOMS not theorem ›
⚬ axm7: ran(Options) = OPTION not theorem ›
END
And my machine:
room_numbers is showed at the first time as empty rooms.
vacant_room displayed whether it is OCCUPIED or EMPTY.
isBooked - relation between customer and room which our customer chose.
MACHINE
HotelSystemBooking ›
SEES
⚬ HotelData
VARIABLES
⚬ isBooked ›
⚬ customer ›
⚬ vacant_room ›
⚬ r_number ›
⚬ room_numbers ›
INVARIANTS
⚬ inv1: isBooked ∈ CUSTOMERS ↔ ROOMS not theorem ›
⚬ inv2: customer ∈ ℙ(CUSTOMERS) not theorem ›
⚬ inv3: vacant_room ∈ PERMISSION not theorem ›
⚬ inv4: r_number ∈ ROOMS ⇸ ℙ(ℕ) not theorem ›
⚬ inv5: room_numbers ∈ ROOMS ⇸ ℕ not theorem ›
⚬ inv6: ∀ f · f ∈ ROOMS ∧ f ∈ ran(isBooked) ⇒ f ∈ dom(r_number) ∧ f ∈ dom(room_numbers) ∧ f ∈ dom(Options) not theorem ›
⚬ inv7: ¬(vacant_room = OCCUPIED ∧ vacant_room = EMPTY) not theorem ›
EVENTS
⚬ INITIALISATION: not extended ordinary ›
THEN
⚬ act1: isBooked ≔ ∅ ›
⚬ act2: customer ≔ ∅ ›
⚬ act3: vacant_room ≔ EMPTY ›
⚬ act4: r_number ≔ ∅ ›
⚬ act5: room_numbers ≔ ROOMS × {0} ›
END
⚬ reservation: not extended ordinary ›
ANY
⚬ c ›
⚬ r ›
⚬ room_number ›
WHERE
⚬ grd1: c ∈ CUSTOMERS not theorem ›
⚬ grd2: r ∈ ROOMS not theorem ›
⚬ grd3: room_number ∈ ℕ not theorem ›
⚬ grd4: r ∈ dom(r_number) ∧ room_number ∉ r_number(r) not theorem ›
⚬ grd5: room_number < room_numbers(r) not theorem ›
THEN
⚬ act1: isBooked ≔ isBooked ∪ {c ↦ r} ›
⚬ act2: r_number(r) ≔ r_number(r) ∪ {room_number} ›
END
⚬ cancellation: not extended ordinary ›
ANY
⚬ c ›
⚬ r ›
⚬ room_number ›
WHERE
⚬ grd1: c ∈ CUSTOMERS ∧ r ∈ ROOMS ∧ (c ↦ r) ∈ isBooked not theorem ›
⚬ grd2: r ∈ dom(room_numbers) ∧ room_number < room_numbers(r) not theorem ›
⚬ grd3: r ∈ dom(r_number) ∧ room_number ∈ r_number(r) not theorem ›
THEN
⚬ act1: isBooked ≔ isBooked ∖ {c ↦ r} ›
⚬ act2: r_number(r) ≔ r_number(r) ∖ {room_number} ›
END
⚬ checkin: not extended ordinary ›
ANY
⚬ c ›
⚬ size1 ›
⚬ r ›
WHERE
⚬ grd1: c ∈ CUSTOMERS ∧ c ∈ dom(isBooked) not theorem ›
⚬ grd2: size1 ∈ ℕ not theorem ›
⚬ grd3: r ∈ ROOMS not theorem ›
THEN
⚬ act1: customer ≔ {c} ∪ dom(isBooked) ›
⚬ act2: room_numbers ≔ room_numbers ∪ {r ↦ size1} ›
END
⚬ checkout: not extended ordinary ›
ANY
⚬ c ›
⚬ r ›
WHERE
⚬ grd1: c ∈ CUSTOMERS ∧ c ∈ dom(isBooked) ∧ r ∈ ROOMS ∧ (c ↦ r) ∈ isBooked not theorem ›
THEN
⚬ act1: isBooked ≔ {c} ⩤ isBooked ›
⚬ act2: room_numbers ≔ {r} ⩤ room_numbers ›
⚬ act3: r_number ≔ {r} ⩤ r_number ›
END
⚬ reservation_query: not extended ordinary ›
ANY
⚬ r ›
WHERE
⚬ grd1: r ∈ ROOMS not theorem ›
THEN
⚬ act1: customer ≔ isBooked∼[{r}] ›
END
⚬ reservation_occupied: not extended ordinary ›
ANY
⚬ c ›
⚬ o ›
WHERE
⚬ grd1: c ∈ CUSTOMERS ∧ o ∈ OPTION ∧ (c ↦ o) ∈ isBooked;Options not theorem ›
THEN
⚬ act1: vacant_room ≔ OCCUPIED ›
END
⚬ reservation_free: not extended ordinary ›
ANY
⚬ c ›
⚬ o ›
WHERE
⚬ grd1: c ∈ CUSTOMERS ∧ o ∈ OPTION ∧ (c ↦ o) ∉ isBooked;Options not theorem ›
THEN
⚬ act1: vacant_room ≔ EMPTY ›
END
END
I have some problems with reservation this line -> grd5: room_number < room_numbers(r) what's wrog with that line? I have other problems in reservation but with inv6. The same inv but in cancellation. Inv5 - checkin and inv6 in checkout. I also want to improve it a little and want to know how can I express vacant_room in terms of room_numbers and thus I will remove that PERMISSION when it is OCCUPIED and EMPTY. Maybe you know how to make it better?
I tried to make a relations between different types of rooms and the customer but now it looks not so much as I expected. I think to update it a little bit and have some ideas. I thought that room_numbers need to decrease and to create a constant function for vacant_room to show maximum number of vacant rooms and maybe assign it once with room_numbers variable. And vacant_room variable express through room_numbers. But there is a question how can I make the relation between customer?
Related
Is (A -> B) /\ (C -> D) a subtype of (A /\ C) -> (B /\ D)?
It seems like it shouldn't be, simply on account of -> being contravariant, but I can't find a good counterexample.
If it is, how can I derive this?
If not, what would a counterexample be?
(To clarify, I'm using /\ for intersection here.)
These types are in a subtype relation, precisely because of contravariance. The union would be a supertype of A and C, so would violate contravariance.
Recall the subtyping rule for functions, which is contravariant in the domain type:
T → U <: T' → U' iff T' <: T and U <: U'
For intersection types, you also have a distributivity rule over arrow types:
(T → U) ∧ (T → V) = T → (U ∧ V)
And of course we have the usual elimination rules for intersection types:
T ∧ U <: T
T ∧ U <: U
Plugging these four rules together, you can easily derive the subtyping you're asking about:
(A → B) ∧ (C → D)
<: (by contravariance and left elimination)
((A ∧ C) → B) ∧ (C → D)
<: (by contravariance and right elimination)
((A ∧ C) → B) ∧ ((A ∧ C) → D)
<: (by distributivity)
(A ∧ C) → (B ∧ D)
FWIW, with union types, you also have the dual distributivity rule:
(U → T) ∨ (V → T) = (U ∨ V) → T
With that, you can analogously derive:
(A → B) ∨ (C → D) <: (A ∨ C) → (B ∨ D)
In Lean, the axiom choice is implemented as follows:
axiom choice {α : Sort u} : nonempty α → α
Given only the assertion h that α is nonempty, choice h magically produces an element of α.
Now if I read literature (Jech) on set theory and the axiom of choice:
Axiom of Choice (AC). Every family of nonempty sets has a choice function.
If S is a family of sets and ∅ not in S, then a choice function for S is a function f on S such that f(X) ∈ X for every X ∈ S.
To me, these things don't seem to be equivalent. Can someone elaborate on this?
The axiom choice in Lean is indeed not the same as the axiom of choice in set theory. The axiom choice in Lean doesn't really have a corresponding statement in set theory. It says that there is a function that takes a proof that some type α is nonempty, and produces an inhabitant of α. In set theory, we cannot define functions that take proofs as arguments since proofs are not objects in set theory; they are in the layer of logic on top of that.
That said, the two choice axioms are not completely unrelated. From Lean's axiom choice, you can prove the more familiar axiom of choice from set theory, which you can find here:
theorem axiomOfChoice {α : Sort u} {β : α → Sort v} {r : ∀ x, β x → Prop}
(h : ∀ x, ∃ y, r x y) : ∃ (f : ∀ x, β x), ∀ x, r x (f x) :=
⟨_, fun x => choose_spec (h x)⟩
In other parts of the library, other equivalent statements to the axiom of choice are proven, like the one stating that every surjective function has a right inverse.
Maybe the statement closest to the version of the axiom of choice you quoted is the following:
theorem axiomOfChoice' {α : Sort u} {β : α → Sort v} (h : ∀ x, Nonempty (β x)) :
Nonempty (∀ x, β x) :=
⟨fun x => Classical.choice (h x)⟩
In words, this says that given a family of nonempty types (sets), the type of choice functions is nonempty. As you can see the proof is immediate from Lean's choice.
Fd1 = {AB --> C, D --> E, E --> C}
Fd2 = { AB --> C, D --> E, AB --> E, E --> C}
are these two FD's are equivalent or not, i think they are. But in the answer it's shown as not equivalent.
You cannot produce AB → E from dependencies in the first set.
To mathematically prove their (in)equivalence, you should build closures for both sets and compare the closures.
There are a few simple induction rules to build the a closure. Quoting Wikipedia on Functional Dependency, the axioms are:
Reflexivity: If Y is a subset of X, then X → Y
Augmentation: If X → Y, then XZ → YZ
Transitivity: If X → Y and Y → Z, then X → Z
with by a few rules that follow from them:
Union: If X → Y and X → Z, then X → YZ
Decomposition: If X → YZ, then X → Y and X → Z
Pseudotransitivity: If X → Y and WY → Z, then WX → Z
Composition: If X → Y and Z → W, then XZ → YW
Using these rules and axioms, one can build a closure for a FDS.
Omitting trivial dependencies (the ones where right side is included into left side), first set { AB → C (1), D → E (2), E → C (3) } gives:
AB → C (1)
ABD → CE, ABD → C, ABD → E (composition 1+2, decomposition)
ABDE → CE, ABDE → C (composition 1+2+3, decomposition)
ABE → C (composition 1+3)
D → E, D → C, D → CE (2, transitivity 2+3, union)
DE → CE, DE → C (composition 2+3, decomposition)
E → C (3)
And the second set { AB → C (1), D → E (2), E → C (3), AB → E (4) } gives:
AB → C, AB → E, AB → CE (1, 4, union 1+4)
ABD → CE, ABD → C, ABD → E (composition 1+2, decomposition)
ABDE → CE, ABDE → C (composition 1+2+3, decomposition)
ABE → C (composition 1+3)
D → E, D → C, D → CE (2, transitivity 2+3, union)
DE → CE, DE → C (composition 2+3, decomposition)
E → C (3)
The second closure has AB → E, AB → CE, which is not present in the first closure, therefore original sets are different.
Suppose I have this definition of Subset in Agda
Subset : ∀ {α} → Set α → {ℓ : Level} → Set (α ⊔ suc ℓ)
Subset A {ℓ} = A → Set ℓ
and I have a set
data Q : Set where
a : Q
b : Q
Is it possible to prove that all subset of q is decidable and why?
Qs? : (qs : Subset Q {zero}) → Decidable qs
Decidable is defined here:
-- Membership
infix 10 _∈_
_∈_ : ∀ {α ℓ}{A : Set α} → A → Subset A → Set ℓ
a ∈ p = p a
-- Decidable
Decidable : ∀ {α ℓ}{A : Set α} → Subset A {ℓ} → Set (α ⊔ ℓ)
Decidable as = ∀ a → Dec (a ∈ as)
Not for that definition of Subset, since decidability would require to check whether "p a" is inhabited or not, i.e. excluded middle.
Decidable subsets would exactly be maps into Bool:
Subset : ∀ {α} (A : Set α) -> Set
Subset A = A → Bool
_∈_ : ∀ {α}{A : Set α} → A → Subset A → Set
a ∈ p = T (p a)
But if you want more flexibility on the shape of the membership proofs you could use your definition of Subset and carry around a proof that it is Decidable.
I have two closely related questions:
First, how can the Haskell's Arrow class be modeled / represented in Agda?
class Arrow a where
arr :: (b -> c) -> a b c
(>>>) :: a b c -> a c d -> a b d
first :: a b c -> a (b,d) (c,d)
second :: a b c -> a (d,b) (d,c)
(***) :: a b c -> a b' c' -> a (b,b') (c,c')
(&&&) :: a b c -> a b c' -> a b (c,c')
(the following Blog Post states that it should be possible...)
Second, in Haskell, the (->) is a first-class citizen and just another higher-order type and its straightforward to define (->) as one instance of the Arrow class. But how is that in Agda? I could be wrong, but I feel, that Agdas -> is a more integral part of Agda, than Haskell's -> is. So, can Agdas -> be seen as a higher-order type, i.e. a type function yielding Set which can be made an instance of Arrow?
Type classes are usually encoded as records in Agda, so you can encode the Arrow class as something like this:
open import Data.Product -- for tuples
record Arrow (A : Set → Set → Set) : Set₁ where
field
arr : ∀ {B C} → (B → C) → A B C
_>>>_ : ∀ {B C D} → A B C → A C D → A B D
first : ∀ {B C D} → A B C → A (B × D) (C × D)
second : ∀ {B C D} → A B C → A (D × B) (D × C)
_***_ : ∀ {B C B' C'} → A B C → A B' C' → A (B × B') (C × C')
_&&&_ : ∀ {B C C'} → A B C → A B C' → A B (C × C')
While you can't refer to the function type directly (something like _→_ is not valid syntax), you can write your own name for it, which you can then use when writing an instance:
_=>_ : Set → Set → Set
A => B = A → B
fnArrow : Arrow _=>_ -- Alternatively: Arrow (λ A B → (A → B)) or even Arrow _
fnArrow = record
{ arr = λ f → f
; _>>>_ = λ g f x → f (g x)
; first = λ { f (x , y) → (f x , y) }
; second = λ { f (x , y) → (x , f y) }
; _***_ = λ { f g (x , y) → (f x , g y) }
; _&&&_ = λ f g x → (f x , g x)
}
While hammar's answer is a correct port of the Haskell code, the definition of _=>_ is too limited compared to ->, since it doesn't support dependent functions. When adapting code from Haskell, that's a standard necessary change if you want to apply your abstractions to the functions you can write in Agda.
Moreover, by the usual convention of the standard library, this typeclass would be called RawArrow because to implement it you do not need to provide proofs that your instance satisfies the arrow laws; see RawFunctor and RawMonad for other examples (note: definitions of Functor and Monad are nowhere in sight in the standard library, as of version 0.7).
Here's a more powerful variant, which I wrote and tested with Agda 2.3.2 and the 0.7 standard library (should also work on version 0.6). Note that I only changed the type declaration of RawArrow's parameter and of _=>_, the rest is unchanged. When creating fnArrow, though, not all alternative type declarations work as before.
Warning: I only checked that the code typechecks and that => can be used sensibly, I didn't check whether examples using RawArrow typecheck.
module RawArrow where
open import Data.Product --actually needed by RawArrow
open import Data.Fin --only for examples
open import Data.Nat --ditto
record RawArrow (A : (S : Set) → (T : {s : S} → Set) → Set) : Set₁ where
field
arr : ∀ {B C} → (B → C) → A B C
_>>>_ : ∀ {B C D} → A B C → A C D → A B D
first : ∀ {B C D} → A B C → A (B × D) (C × D)
second : ∀ {B C D} → A B C → A (D × B) (D × C)
_***_ : ∀ {B C B' C'} → A B C → A B' C' → A (B × B') (C × C')
_&&&_ : ∀ {B C C'} → A B C → A B C' → A B (C × C')
_=>_ : (S : Set) → (T : {s : S} → Set) → Set
A => B = (a : A) -> B {a}
test1 : Set
test1 = ℕ => ℕ
-- With → we can also write:
test2 : Set
test2 = (n : ℕ) → Fin n
-- But also with =>, though it's more cumbersome:
test3 : Set
test3 = ℕ => (λ {n : ℕ} → Fin n)
--Note that since _=>_ uses Set instead of being level-polymorphic, it's still
--somewhat limited. But I won't go the full way.
--fnRawArrow : RawArrow _=>_
-- Alternatively:
fnRawArrow : RawArrow (λ A B → (a : A) → B {a})
fnRawArrow = record
{ arr = λ f → f
; _>>>_ = λ g f x → f (g x)
; first = λ { f (x , y) → (f x , y) }
; second = λ { f (x , y) → (x , f y) }
; _***_ = λ { f g (x , y) → (f x , g y) }
; _&&&_ = λ f g x → (f x , g x)
}