|
1 | | -# Bijections |
| 1 | +# Getting Started with `Bijections` |
2 | 2 |
|
3 | | -## What's New in 0.2 |
| 3 | +Julia dictionaries are not one-to-one. That is, two different keys might have the same value. |
| 4 | +A `Bijection` data structure behaves just like a dictionary, except it prevents the assignment of the same value to two different keys. |
4 | 5 |
|
5 | | -For the most part, 0.2.x versions of `Bijections` should be fully compatiable with the 0.1.x releases. |
| 6 | +## Constructors |
6 | 7 |
|
7 | | -### Breaking Changes |
8 | | - |
9 | | -* The underlying datastructure for a `Bijection` has been simplified. Users should not notice any difference. |
10 | | -* The functions `domain` and `image` returned a `Set` in 0.1. They now return iterators. |
11 | | - * `domain(b)` simply calls `keys(b)`. |
12 | | - * `image(b)` simply calls `values(b)`. |
13 | | - |
14 | | -### New Feature |
15 | | - |
16 | | -A `Bijection` contains two dictionaries which previously (and now by default) are type `Dict`. In this release, users can specify another `AbstractDict`. More information will be forthcoming, but one might create a `Bijection` like this: |
17 | | -``` |
18 | | -b = Bijection{Int, Vector{Int}, IdDict{Int,VectorInt}, IdDict{Vector{Int},Int}}() |
19 | | -``` |
20 | | -In this case, the mappings from keys to values (and vice versa) are held in an `IdDict` |
21 | | -instead of a `Dict`. |
22 | | - |
23 | | -# `README` for Version 0.1 |
24 | | - |
25 | | -A `Bijection` data type for Julia. |
26 | | - |
27 | | - |
28 | | -A `Dict` in Julia is not one-to-one. Two different keys might have the |
29 | | -same value. A `Bijection` data structure behaves just like a `Dict` except it |
30 | | -prevents assigning the same value to two different keys. |
31 | | - |
32 | | -## Getting Started |
33 | | - |
34 | | -After `using Bijections` we create a new `Bijection` in one of the |
35 | | -following ways: |
36 | | - |
37 | | -* `b = Bijection()`: This gives a new `Bijection` in which the keys |
38 | | -and values are of `Any` type. |
39 | | - |
40 | | -* `b = Bijection{S,T}()`: This gives a new `Bijection` in which the |
41 | | - keys are of type `S` and the values are of type `T`. |
42 | | - |
43 | | -* `b = Bijection(x,y)`: This gives a new `Bijection` in which the keys |
44 | | - are type `typeof(x)`, the values are type `typeof(y)` and the |
45 | | - key-value pair `(x,y)` is inserted into the `Bijection`. |
46 | | - |
47 | | -* `b = Bijection(dict::AbstractDict{S, T})`: This gives a new `Bijection` in which the keys |
48 | | - are type `S`, the values are type `T` and all |
49 | | - key-value pairs in `dict` are inserted into the `Bijection`. |
50 | | - |
51 | | -* `b = Bijection(pair_list::Vector{Pair{S, T}})`: Create a new `Bijection` using a list of pairs. |
52 | | - |
53 | | -## Adding and Deleting Pairs |
54 | | - |
55 | | -Once a `Bijection`, `b`, is created, we add a new key-value pair in |
56 | | -the same manner as with a `Dict`: |
57 | | -``` |
58 | | -julia> b[1] = "hello" |
59 | | -"hello" |
60 | | -
|
61 | | -julia> b[2] = "bye" |
62 | | -"bye" |
63 | | -``` |
64 | | -Notice, however, that if we add a new key with a value that already |
65 | | -exists in the `Bijection` an error ensues: |
66 | | -``` |
67 | | -julia> b = Bijection{Int, String}() |
68 | | -Bijection Dict{Int64, String}() |
69 | | -
|
70 | | -julia> b[3] = "hello" |
71 | | -ERROR: One of x or y already in this Bijection |
72 | | -``` |
73 | | -Likewise, if a key already has a value it cannot be changed by giving |
74 | | -it a new value: |
75 | | -``` |
76 | | -julia> b[1] = "ciao" |
77 | | -ERROR: One of x or y already in this Bijection |
78 | | -``` |
79 | | - |
80 | | -If we wish to change the value associated with a given key, the pair |
81 | | -must first be deleted using `delete!`: |
82 | | -``` |
83 | | -julia> delete!(b,1) |
84 | | -Bijection Dict{Int64, String} with 1 entry: |
85 | | - 2 => "bye" |
86 | | -
|
87 | | -julia> b[1] = "ciao" |
88 | | -"ciao" |
89 | | -``` |
90 | | - |
91 | | -## Using a `Bijection` |
92 | | - |
93 | | -To access a value associated with a given key, we use the same syntax |
94 | | -as for a `Dict`: |
95 | | -``` |
96 | | -julia> b[1] |
97 | | -"ciao" |
98 | | -
|
99 | | -julia> b[2] |
100 | | -"bye" |
101 | | -``` |
102 | | - |
103 | | -If the key is not in the `Bijection` an error is raised: |
104 | | -``` |
105 | | -julia> b[3] |
106 | | -ERROR: KeyError: 3 not found |
107 | | -``` |
108 | | - |
109 | | -Since the values in a `Bijection` must be distinct, we can give a |
110 | | -value as an input and retrieve its associate key. The function |
111 | | -`inverse(b,y)` finds the value `x` such that `b[x]==y`. However, we |
112 | | -provide the handy short cut `b(y)`: |
113 | | -``` |
114 | | -julia> b("bye") |
115 | | -2 |
116 | | -
|
117 | | -julia> b("ciao") |
118 | | -1 |
119 | | -``` |
120 | | - |
121 | | -Naturally, if the requested value is not in the `Bijection` an error |
122 | | -is raised: |
123 | | -``` |
124 | | -julia> b("hello") |
125 | | -ERROR: KeyError: hello not found |
126 | | -``` |
127 | | - |
128 | | -## Creating an Inverse `Bijection` |
129 | | - |
130 | | -There are two functions that take a `Bijection` and return a new |
131 | | -`Bijection` that is the functional inverse of the original: |
132 | | -`inv` and `active_inv`. |
133 | | - |
134 | | -### Independent inverse: `inv` |
135 | | -Given a `Bijection` `b`, calling `inv(b)` creates a new `Bijection` |
136 | | -that is the inverse of `b`. The new `Bijection` is completely independent |
137 | | -of the original, `b`. Changes to one do not affect the other: |
138 | | -``` |
139 | | -julia> b = Bijection{Int,String}() |
140 | | -Bijection Dict{Int64, String}() |
141 | | -
|
142 | | -julia> b[1] = "alpha" |
143 | | -"alpha" |
144 | | -
|
145 | | -julia> b[2] = "beta" |
146 | | -"beta" |
147 | | -
|
148 | | -julia> bb = inv(b) |
149 | | -Bijection Dict{String, Int64} with 2 entries: |
150 | | - "alpha" => 1 |
151 | | - "beta" => 2 |
152 | | -
|
153 | | -julia> bb["alpha"] |
154 | | -1 |
155 | | -
|
156 | | -julia> bb["alpha"] |
157 | | -1 |
158 | | -
|
159 | | -julia> b[3] = "gamma" |
160 | | -"gamma" |
161 | | -
|
162 | | -julia> bb["gamma"] |
163 | | -ERROR: KeyError: key "gamma" not found |
164 | | -``` |
165 | | - |
166 | | -### Active inverse: `active_inv` |
167 | | - |
168 | | -The `active_inv` function also creates an inverse `Bijection`, but in this |
169 | | -case the original and the inverse are actively tied together. |
170 | | -That is, modification of one immediately affects the other. |
171 | | -The two `Bijection`s remain inverses no matter how either is modified. |
172 | | - |
173 | | -``` |
174 | | -julia> b = Bijection{Int,String}() |
175 | | -Bijection Dict{Int64, String}() |
176 | | -
|
177 | | -julia> b[1] = "alpha" |
178 | | -"alpha" |
179 | | -
|
180 | | -julia> b[2] = "beta" |
181 | | -"beta" |
182 | | -
|
183 | | -julia> bb = active_inv(b) |
184 | | -Bijection Dict{String, Int64} with 2 entries: |
185 | | - "alpha" => 1 |
186 | | - "beta" => 2 |
187 | | - |
188 | | -julia> b[3] = "gamma" |
189 | | -"gamma" |
190 | | -
|
191 | | -julia> bb["gamma"] |
192 | | -3 |
193 | | -``` |
194 | | - |
195 | | -## Iteration |
196 | | - |
197 | | -`Bijection`s can be used in a `for` statement just like Julia |
198 | | -dictionaries: |
199 | | -``` |
200 | | -julia> for (x,y) in b; println("$x --> $y"); end |
201 | | -2 --> beta |
202 | | -3 --> gamma |
203 | | -1 --> alpha |
204 | | -``` |
205 | | - |
206 | | - |
207 | | - |
208 | | -## Inspection |
209 | | - |
210 | | -Thinking of a `Bijection` as a mapping between finite sets, we |
211 | | -provide the functions `domain` and `image`. These return, |
212 | | -respectively, the set of keys and the set of values of the |
213 | | -`Bijection`. |
214 | | -``` |
215 | | -julia> domain(b) |
216 | | -Set(Any[2,1]) |
217 | | -
|
218 | | -julia> image(b) |
219 | | -Set(Any["bye","ciao"]) |
220 | | -``` |
221 | | - |
222 | | -The `collect` function returns the `Bijection` as an array of |
223 | | -key-value pairs: |
224 | | -``` |
225 | | -julia> collect(b) |
226 | | -2-element Array{Tuple{Any,Any},1}: |
227 | | - (2,"bye") |
228 | | - (1,"ciao") |
229 | | -``` |
230 | | - |
231 | | -The `length` function returns the number of key-value pairs: |
232 | | -``` |
233 | | -julia> length(b) |
234 | | -2 |
235 | | -``` |
236 | | - |
237 | | -The `isempty` function returns `true` exactly when the `Bijection` |
238 | | -contains no pairs: |
239 | | -``` |
240 | | -julia> isempty(b) |
241 | | -false |
242 | | -``` |
243 | | - |
244 | | - |
245 | | -## Composition |
246 | | - |
247 | | -Given two `Bijection`s `a` and `b`, their composition `c = a*b` is a new |
248 | | -`Bijection` with the property that `c[x] = a[b[x]]` for all `x` in the |
249 | | -domain of `b`. |
250 | | - |
251 | | -``` |
252 | | -julia> a = Bijection{Int,Int}(); a[1] = 10; a[2] = 20; |
253 | | -
|
254 | | -julia> b = Bijection{String,Int}(); b["hi"] = 1; b["bye"] = 2; |
255 | | -
|
256 | | -julia> c = a * b; |
257 | | -
|
258 | | -julia> c["hi"] |
259 | | -10 |
260 | | -``` |
| 8 | +MORE TO COME |
0 commit comments