EDFS 2001/2002: Exercises | |
---|---|
[ DI/UM ] |
Problem 1 [Modelling with Sets] |
In this exercise we are concerned with the design of the central database component which records road maps (distances, road alternatives and so on) - a component which we are going to model with sets.
We start from a very simple model (to be improved at a later stage): a road-map is a directed graph whose arcs A->B record the you can drive from A to B relation:
Map = set of Path; Path :: From: Location To: Location; Location = token;
UMap = set of UPath; UPath :: From: Location Info: PathInfo To: Location; PathInfo :: name: token distance: real speed: real; Location = token;
Scale up the function definitions above from Map to UMap. Clearly, you have to pay attention to the handling of PathInfos, by eg. summing up distances, computing average speeds and concatenating road names. (Hint: recall the notion of a weighted graph.)
Problem 2 [Modelling a Memory Cache]
[Back to Index
]
types Addr = token; Data = token; Memory :: addrs: set of Addr mapx: map Addr to Data; MainMemory = Memory; Cache :: addrs: set of Addr mapx: map Addr to Data dirty: set of Addr; System :: cache: Cache main: MainMemory inv system == system.cache.addrs subset system.main.addrs; functions badAddrs: System -> set of Addr badAddrs (s) == { x | x in set s.cache.addrs & s.cache.mapx(x) <> s.main.mapx(x) }; load: System * Addr -> System load (s, a) == mk_System( mk_Cache(s.cache.addrs union {a}, s.cache.mapx munion {a|->s.main.mapx(a)}, s.cache.dirty), s.main) pre a not in set s.cache.addrs; systemWrite: System * Data * Addr -> System systemWrite (s, d, a) == mk_System( mk_Cache(s.cache.addrs, s.cache.mapx ++ {a|->d}, s.cache.dirty union {a}), s.main); flush: System -> System flush (s) == let x in set s.cache.addrs in mk_System( mk_Cache(s.cache.addrs \ {x}, {x} <-: s.cache.mapx, s.cache.dirty \ {x}), mk_Memory(s.main.addrs, s.main.mapx ++ {x|->s.cache.mapx(x)}));
Problem 3 [A Naive Model of the WWW]
[Back to Index
]
WWW = map Ref to URL; -- (URL=Universal Resource Location) URL = seq of Unit; Unit = PlainText | HyperLink; PlainText = seq of Word; Word = seq of char; HyperLink :: link: Ref txt: PlainText; -- "underlined text"
wc : seq of char -> nat -- counts the number of words in a stringspecify
nrofwd : URL -> nat -- counts the number of words in a URL
refsTo : Ref * WWW -> set of Ref -- retrieves the addresses of all URLs which point at Ref
invert : WWW -> map Word to map Ref to nat1which computes, for every word, the URLs which mention it, weighted by the number of occurrences, ie. a multiset. Specify invert. (NB: this inversion operation is far more elaborate in practice!)
Problem 4 [Modelling with Mappings]
[Back to Index
]
types BAMS = map AccId to Account; Account :: H: set of AccHolder B: Amount; AccId = seq of char; AccHolder = seq of char; Amount = int; functions Init : () -> BAMS Init () == {|->}; OpenAccount : BAMS * AccId * set of AccHolder * Amount -> BAMS OpenAccount(bams,n,h,m) == bams munion ......................... pre not n in set dom bams; AddAccHolders: BAMS * AccId * set of AccHolder -> BAMS AddAccHolders(bams,n,h) == bams ++ { n |-> let a = bams(n) in mk_Account(a.H union h,a.B) } pre ...................; Credit: BAMS * AccId * Amount -> BAMS Credit(bams,n,m) == ............................... pre n in set dom bams; Withdraw: BAMS * AccId * Amount -> BAMS Withdraw(bams,n,m) == bams ++ { n |-> let a = bams(n) in mk_Account(a.H, a.B - m) } pre ....................................; GoodCostumers: BAMS * Amount -> set of AccId GoodCostumers(bams,m) == --- should select the accounts whose balance is greater than m
Problem 5 [Modelling with Inductive Types]
[Back to Index
]
Such a normalization not only helps in the packaging binary partition algorithm adopted by the robot system but also makes it possible to identify the dimensions of a particular box by a single number (its width in cm). We shall deliberately ignore the 3rd dimension of the problem. The picture on the right shows the structure of a palette containing three boxes A, B and C, where space can still be found to accept a box with the dimensions of C or be split in two space areas to accept boxes of smaller dimensions and so and so on. (Areas are always divided widthwise.) |
|
The following VDM-SL inductive datatype models palette binary partitioning trees:
Space = [ S ]; S = Box | BoxSplit; Box :: info: BoxInfo width: Width; BoxSplit :: one: Space two: Space; BoxInfo = token; Width = real;
whichBoxes : Space -> set of BoxInfo -- delivers the information of all boxes in the palette whichBoxes(s) == ..............; freeSpace : Space -> Width -- yields the width of the widest free space in the palette freeSpace(s) == ..............; insertBox : Box * Space -> Space -- "best fit" insertion of a box, if possible insertBox(b,s) == .....................; removeBox : Box * Space -> Space removeBox(b,s) == .....................; defragment : Space -> Space -- collapse all empty subareas as much as possible defragment(s) == .....................;
Problem 6 [Multisets «are» Mappings]
[Back to Index
]
map @A to nat
Multisets are very common in formal modelling. For instance, an inventory
|
m = {"chair"|->12,"table"|->3,"cupboard"|->1}Invoices are multisets, bank statements are multisets, etc.
The empty mapping {|->} models the empty multiset and set-union generalizes to multiplicity addition, that is, given two multisets n and m, their union is defined as follows:
mseCup[@A] : map @A to nat * map @A to nat -> map @A to nat mseCup(m,n) == m ++ n ++ { a |-> m(a) + n(a) | a in set dom n inter dom m };
Generalize this by defining
mseExMul[@A] : map @A to nat * nat -> map @A to natthe multiplication of a multiset by a numeric factor.
mseDiff[@A] : map @A to nat * map @A to nat -> map @A to natwhich computes multiset difference.
mseCUP[@A] : seq of map @A to nat -> map @A to nat
Problem 7 [Hash tables «are» Mappings]
[Back to Index
]
The idea of hashing is suggested by the informal meaning of the term itself: a large database file is «hashed» into as many «pieces» as possible, each of which is randomly accessed. Since each sub-database is smaller than the original, the time spent on accessing data is shortened by some order of magnitude. Random access is normally achieved by a so-called hash function,
which computes, for each data item, its location in the hash table. Standard terminology regards as synonyms all data competing for the same location. A set of synonyms is called a bucket. There are several ways in which data collision is handled, e.g. linear probing or overflow handling. Below we consider the latter.
Init : () -> HTable Insert : Data * HTable -> HTable Find : Data * HTable -> bool Remove : Data * HTable -> HTable
(Further readings: Hash Tables -- A Case Study in Sets-calculation. Technical Report DI/INESC 94-12-1, INESC Group 2361, Braga, December 1994.
Back to MFP-I's main URL.