How Can I Specify All Members of a Set Are Unique in Alloy? - alloy

I have an alloy model. In the spirit of a small reproduction example, I've extracted the following:
sig SearchTerm {}
sig Document{
keyword: set SearchTerm
}
assert keywordsAreUniqueForDocument {
all k, k' : Document.keyword | k != k'
}
check keywordsAreUniqueForDocument for 5
What I'm trying to achieve is that the set of keywords associated with a particular document should be unique. But this is immediately showing me a trivial counterexample.
How can I specify that there should be no duplicated elements in a set?

document.keyword is a set and, by the set definition, is only unique elements. You're getting a counterexample where k = k'. If you instead write all disj k, k' : Document.keyword | k != k', it will trivially pass.
If you instead intended that no two documents share keywords, that'd be all disj d, d': Document | no d.keywork & d'.keyword.

Related

How to structure the state in activityOf() in CodeWorld?

I explore the usage of activityOf(state_0, change, picture) in CodeWorld framework.
The state is described as a tuple. I test the possibility to let one of the elements in the tuple to be a list, since I think that would be very useful and make coding more compact.
In the example below I show that it seems to work if I just print out the first element u1 in the u_list. I can control the value by keys for up and down and time t goes on. The second element u2 in the u_list is simply there and not changed.
program = activityOf(state_0, change, picture)
state_0(rs) = (t0, u_list_0)
u_list_0 = [u10,u20]
t0 = 0
u10 = 0
u20 = 7
t_of((t_value,_)) = t_value
u1_of((_, ulist)) = ulist#1
u2_of((_, ulist)) = ulist#2
change((t, u_list), KeyPress("Up")) = (t_of((t,u_list)), [u1_of((t, u_list))+1])
change((t, u_list), KeyPress("Down")) = (t_of((t,u_list)), [u1_of((t, u_list))-1])
change((t, u_list), TimePassing(dt)) = (t_of((t,u_list))+dt, u_list)
change((t, u_list), other) = (t, u_list)
picture((t, u_list)) = pictures [translated(lettering(printed(t_of((t, u_list)))),0,1),
lettering(printed(u1_of((t, u_list))))]
However, if I change the example on the last row to just print out u2, i.e. change u1_of (..) to u2_of(..) then I get get no compilation error and the program runs. But if I press any of the keys up and down then I get a runtime error for the line 11 of the code where u2_of() is defined.
Error message:
List index is too large.
When evaluating: error, called in the standard library idxErrorTooLarge, called
in the standard library #, used at Line 11, Column 21 in your code
What is going on here?
Is it at all possible to use a list as one element in the state tuple?
Link to run https://code.world/#PBKh1Aucqqxg48ePyxxAuUg
In your up and down key handlers, you are changing the list to have only one element:
change((t, u_list), KeyPress("Up")) = (t_of((t,u_list)), [u1_of((t, u_list))+1])
change((t, u_list), KeyPress("Down")) = (t_of((t,u_list)), [u1_of((t, u_list))-1])
^^^^^^^^^^^^^^^^^^^^^^
If you ask for the second element of the list (as picture does) after pressing one of those keys, there won't be one to access. You might want something like:
[u1_of((t, u_list))-1, u2_of(t, u_list)]
As a stylistic comment: it's fairly unusual to use accessor functions like this in Haskell if pattern matching gets you where you want to go. For example, this would be a bit more idiomatic:
change ((t, [r, c]), KeyPress "Up" ) = (t, [r+1, c])
change ((t, [r, c]), KeyPress "Down") = (t, [r-1, c])
This would be much more idiomatic:
data GameState = GameState
{ t :: Int
, r :: Int
, c :: Int
}
change (s, KeyPress "Up" ) = s { r = r s + 1 }
change (s, KeyPress "Down") = s { r = r s - 1 }
One benefit of this final style is that it's not possible to accidentally create a "list" with the wrong number of elements.

comparing two arrays and get the values which are not common

I am doing this problem a friend gave me where you are given 2 arrays say (a[1,2,3,4] and b[8,7,9,2,1]) and you have to find not common elements.
Expected output is [3,4,8,7,9]. Code below.
def disjoint(e,f):
c = e[:]
d = f[:]
for i in range(len(e)):
for j in range(len(f)):
if e[i] == f[j]:
c.remove(e[i])
d.remove(d[j])
final = c + d
print(final)
print(disjoint(a,b))
I tried with nested loops and creating copies of given arrays to modify them then add them but...
def disjoint(e,f):
c = e[:] # list copies
d = f[:]
for i in range(len(e)):
for j in range(len(f)):
if e[i] == f[j]:
c.remove(c[i]) # edited this line
d.remove(d[j])
final = c + d
print(final)
print(disjoint(a,b))
when I try removing common element from list copies, I get different output [2,4,8,7,9]. why ??
This is my first question in this website. I'll be thankful if anyone can clear my doubts.
Using sets you can do:
a = [1,2,3,4]
b = [8,7,9,2,1]
diff = (set(a) | set(b)) - (set(a) & set(b))
(set(a) | set(b)) is the union, set(a) & set(b) is the intersection and finally you do the difference between the two sets using -.
Your bug comes when you remove the elements in the lines c.remove(c[i]) and d.remove(d[j]). Indeed, the common elements are e[i]and f[j] while c and d are the lists you are updating.
To fix your bug you only need to change these lines to c.remove(e[i]) and d.remove(f[j]).
Note also that your method to delete items in both lists will not work if a list may contain duplicates.
Consider for instance the case a = [1,1,2,3,4] and b = [8,7,9,2,1].
You can simplify your code to make it works:
def disjoint(e,f):
c = e.copy() # [:] works also, but I think this is clearer
d = f.copy()
for i in e: # no need for index. just walk each items in the array
for j in f:
if i == j: # if there is a match, remove the match.
c.remove(i)
d.remove(j)
return c + d
print(disjoint([1,2,3,4],[8,7,9,2,1]))
Try it online!
There are a lot of more effecient way to achieve this. Check this stack overflow question to discover them: Get difference between two lists. My favorite way is to use set (like in #newbie's answer). What is a set? Lets check the documentation:
A set object is an unordered collection of distinct hashable objects. Common uses include membership testing, removing duplicates from a sequence, and computing mathematical operations such as intersection, union, difference, and symmetric difference. (For other containers see the built-in dict, list, and tuple classes, and the collections module.)
emphasis mine
Symmetric difference is perfect for our need!
Returns a new set with elements in either the set or the specified iterable but not both.
Ok here how to use it in your case:
def disjoint(e,f):
return list(set(e).symmetric_difference(set(f)))
print(disjoint([1,2,3,4],[8,7,9,2,1]))
Try it online!

Dependently typed bounded range in Lean

Suppose I would like to create a bounded integer Z with bounds a b.
def zbound (x₁ x₂ : ℤ) :=
{ n : ℤ // x₁ ≤ n ∧ n ≤ x₂ }
Is this a reasonable representation of a bounded integer?
Now I would like to create a range of numbers from a to b.
def range : ∀(a b : ℤ), list (zbound a b)
| fro to := if h : fro < to
then ⟨fro, and.intro (le_refl _) (int.le_of_lt h)⟩
:: range (fro + 1) to
else []
I can get this to work with range : ℤ → ℤ → list ℤ, including the proof of termination using using_well_founded. However, I find it impractical in this form, because it doesn't carry a proof that every number within the range is zbound a b.
As such, I would like to get my dependent version. However, I run into the isue that range (fro + 1) to is, naturally, of type list (zbound (fro + 1) to). What I need is list (zbound fro to). How does one get around this issue? I tried approaching the problem by showing that if x is lower bounded by a, then it is also bounded by every number less than a, therefore keeping the bound of form zbound fro to (os this obviously bounds zbound (fro + 1) to). I have however no idea how to use this idea, or even if it makes sense to use it.
I am not sure this is an ideal solution, but it does work for me.
First we need a lemma to weaken the bounded range:
def range_weaken {a b : ℤ} : zbound (a + 1) b → zbound a b
| ⟨i, ⟨lbound, rbound⟩⟩ :=
⟨i, and.intro
(le_of_add_le_left _ 1 _ dec_trivial lbound)
rbound⟩
Then we can redefine range in terms of weakened ranges:
def range : ∀(a b : ℤ), list (zbound a b)
| fro to := if h : fro < to
then ⟨fro, and.intro (le_refl _) h⟩
:: list.map range_weaken (range (fro + 1) to)
else []
using_well_founded { ... }
Note: I couldn't find a lemma I was looking for, so I hand-proved the following:
def le_of_add_le_left (a b c : ℤ) : 0 ≤ b → a + b ≤ c → a ≤ c

Python construction of value set dictionary

.I've been dealing with list comprehension recently, I came across a problem I can't seem to solve>
let's say I have pairs in the form of:
A,B,C,X="ABCX"
init = {(A,B),(B,C),(C,X)}
I am trying to construct a dictionary, where each key would be an individual letter, and each value all connections this letter has with other, so>
{A:{B},B:{A,C},C:{B,X},X:{C}}
Things I tried>
final_dict = {k : {j for p,j in init if p==k} for k,v in init}
but this returns me ony if the partner is located in the second place,
Trying to add the first place>
final_dict = {k : {j for p,j in init if p==k or p if j == k} for k,v in init}
An error occurs.
Here is the solution without dict comp
init = {('A','B'),('B','C'),('C','X')}
d = {}
for k, v in init:
d.setdefault(k, set()).add(v)
d.setdefault(v, set()).add(k)
The problem is that with your current format for the data you can't properly specify the key, values. Ideally it should be.
init = {('A','B'),('B','A'),('B','C'),('C','B'),('C','X'),('X','C')}
Which you can obtain by doing the following if you don't want to / can't adjust your current method for getting the pairs.
init2 = {(y, x) for x, y in init}.union(init)
So you can then do
d = { key : { v for k, v in init2 if k == key } for key, _ in init2 }
There is also this, but it doesn't include X, and again it would probably become much larger to make work due to the current format.
d = { k : {v1 if k == v2 else v for v1, v2 in init } for k, v in init }

set from the union of elements contained in two lists

this is for a pre-interview questioner. i believe i have the answer just wanted to get confirmation that im right.
Part 1 - Tell me what this code does, and its big-O performance
Part 2 - Re-write it yourself and tell me the big-O performance of your solution
def foo(a, b):
""" a and b are both lists """
c = []
for i in a:
if is_bar(b, i):
c.append(i)
return unique(c)
def is_bar(a, b):
for i in a:
if i == b:
return True
return False
def unique(arr):
b = {}
for i in arr:
b[i] = 1
return b.keys()
ANSWERS:
It creates a set from the union of elements contained in two lists. It big O performance is O(n2)
my solution which i believe achieves O(n)
Set A = getSetA();
Set B = getSetB();
Set UnionAB = new Set(A);
UnionAB.addAll(B);
for (Object inA : a)
if(B.contains(inA))
UnionAB.remove(inA);
It seems like the original code is doing an intersection not a union. It's traversing all the elements in the first list (a) and checking if it exists in the second list (b), in which case it is adding it to list c. Then it is returning the unique elements from c. Performance of O(n^2) seems right.

Resources