Choosing one item from a symmetric set - tla+

I have a TLA+ spec akin to the following:
CONSTANT Items
VARIABLE item
And I'd like Items to be symmetric, and to select a single element from Items and store it into item.
I've been using item = CHOOSE x \in Items: TRUE, but I learned that this breaks symmetry on Items: TLC will always select the first item from the set.
I'd like to select a single item in a way that preserves symmetry, to allow TLC to explore all states. I don't care which item we select -- only that it is one, and that it is from Items. (Later, I need item to be \in Items.
While I'd prefer item to be a single element, it would also be okay for item to be a set of cardinality 1, so later I can check for \subseteq Items.
It was recommended to me to replace CHOOSE with {x \in Items: TRUE} to preserve symmetry and have the result be \subseteq Items, but this does not constrain the resulting set to cardinality 1.
Is there a way to ask TLA+ to give me a single item, or a set of cardinality 1, from a symmetric set of values?

I learned a bit more about TLA+/TLC since posting the question, and here's my answer:
To simply select an element from a symmetry set in the initial predicate:
item \in Items
or in an action:
item' \in Items
If you want to select an item that matches a predicate, as you can specify with CHOOSE, then this is the alternative:
item \in {x \in Items: P(x)}
This'll form a subset of Items that match the predicate, then select a single element of those.
Here's some data that shows the difference between this syntax and CHOOSE. Consider this module:
----------------------------- MODULE ChooseDemo -----------------------------
CONSTANT Items
VARIABLE item
TypeInvariant == item \in Items
Init == item = CHOOSE x \in Items: TRUE
Next == item' \in {x \in Items: x /= item}
=============================================================================
When Items has three items:
NOT a symmetry set: TLC finds 1 initial state and a total of 7 (3 distinct) states.
symmetry set: TLC finds 1 initial state and a total of 3 (1 distinct) states.
Now consider this module:
--------------------------- MODULE SetFormingDemo ---------------------------
CONSTANT Items
VARIABLE item
TypeInvariant == item \in Items
Init == item \in {x \in Items: TRUE}
Next == item' \in {x \in Items: x /= item}
=============================================================================
When Items has three items:
NOT a symmetry set: TLC finds 3 (3 distinct) initial states and a total of 9 (3 distinct) states.
symmetry set: TLC finds 3 (1 distinct) initial state and a total of 5 (1 distinct) states.
Hence, by using the set-forming syntax, TLC finds more states than it did with CHOOSE.

Related

AQL: How to get back the path that all edges must have an property(array) and that array must have at least one certain value

Suppose I have an graph like this:
A---edge1---B property P [P1,P2]
B---edge2---C property P [P2,P3]
C---edge3---D property P [P2,P3]
B---edge4---D property P [P1,P3]
And each edge have an property P which is an array of string [P1,P2,P3]. Each edge has their own value of P
Now I would like to return all vertexes that:
For Each vertex, check if exist a path where each edges, all of them must have at least P2 in property
Depth smaller or equals then 2
**
For entity in entities
For v,e,p in Collection in 0..2 ANY entity
Filter //What should I do here? I tried p.edges[*].P[*] ANY =="P2"
Collect v._key into groups
return {key:v._key,group:groups} //Get the vertex that satisfy the condition
**
p.edges[*].P[*] is an array of arrays. To get ANY == to compare array to individual element would require a flattened array, but then it cannot be determined whether each array has "P2".
One of the following conditions should work however:
FILTER p.edges[* RETURN "P2" IN CURRENT.P] ALL == true
FILTER (FOR arr IN p.edges[*].P RETURN "P2" IN arr) ALL == true
FILTER LENGTH(p.edges[* FILTER "P2" IN CURRENT.P]) == LENGTH(p.edges)

choose one list. choose the one whose nth element is the smallest. Python 3

I have two lists. I have to choose one. I have to choose the one with the smallest nth element. So I can choose the smallest element easy with min, but how do I back track it to the list itself. Have literally no idea how to solve this presumably easy problem.
a = [2,45,1,56]
b= [0,23,3,87]
Which list has the smallest element at position 2? The answer here is list a.
In case I wasnt clear, the program sould be able to solve this task for any pair of lists.
Here is a very simple snippet that does what you want, but you might want to check for the size of the arrays, in case the index is out of range.
def choose_smallest(a, b, i):
if len(a) >= i or len(b) >= i:
return 0 # do whatever you want here
if a[i] < b[i]:
return a
else:
return b
Also notice that both nth elements in your array can have the exact same value... In this example array b will be returned, but you can change that behaviour if needed.
EDIT
Added array length check
According to your example, here is a sample code you can try. You can change the code as per your requirement.
a = [2,45,1,56]
b = [0,23,3,87]
n= int(input('Enter element number: ')) # n starts from zero to length of list - 1
if a[n] > b[n]:
print('List b has smaller nth element')
elif a[n] < b[n]:
print('List a has smaller nth element')
else:
print('Both lists have equal nth element')

Return False if the same input is given more than once

I want to return False if the same input is given:
first_answer = input("select square number 1: ")
second_answer = input("select square number 2: ")
third_answer = input("select square number 3: ")
if first_answer == second_answer or first_answer == third_answer or
second_answer == first_answer or second_answer == third_answer or
third_answer == first_answer or third_answer == second_answer:
print("don\'t repeat squares")
Is there an easier way?
Do you like this:
set_answers = set()
set_answers.add(input("select square number 1: "))
set_answers.add(input("select square number 2: "))
set_answers.add(input("select square number 3: "))
if len(set_answers) < 3:
print("don\'t repeat squares")
?
The TRICK: set() stores only unique elements, so adding same value again to a set doesn't change the number of its elements.
Try this.
count = 3
answers = []
for i in range(0, count):
answers[i] = input("select square number " + str(i+1) + ": "
for i in range(0, count-1):
for j in range(i+1, count):
if answers[i] == answers[j]:
print("don\'t repeat squares")
It is (almost) always easier to abstract this kind of thing by using loops and arrays (or sets, or tuples) than to program each variable by hand.
answers is a list here, and the first loop inputs the data into the array. Note that you can easily change the amount of data you want simply by modifying the initial value of count -- this will change everything else as well (including the input messages!).
The second loop is actually a nested pair of for loops in order to generate all of the (relevant) pairs of data items to compare. Note that the first loop stops one short of the last element and that the second loop starts one after whatever the value of the first loop is. This is in order to avoid incorrectly comparing an element with itself.
CLARIFICATION:
[] is an empty list. A list in Python is just an ordered list of elements that can be accessed by their position (index) in the list. Indexes start from 0. (there are good reasons for this)
In general, the range function returns all the integers in the given range that includes the lower bound (the left argument) and does not include the upper bound (the right argument). (there are good reasons for this too)

Dictionary with list of tuples Python

if match:
occur=0
for item in tweets:
if candidate in item:
popular=item[4]+item[5]
occur+=popular
famous.append(occur)
return occur
I get 10161 only. Also for this function is there a way i can sort the list by numbers and return a list with candidates according the sorted number
the modification are simple, first you need to create a empty list where the result will be keep, then in the for loop you need to check if the condition is fulfilled and add that element to the list if its does, and finally return that list. I also choose some more meaningful variables names
def famous(data_tweet, lower, higher ):
result=[]
for person, tweets in data_tweet.items():
if all( lower <= tw[2] <= higher for tw in tweets ):
result.append( person )
return result
this can be reduced a little bit with the use of list comprehension
def famous(data_tweet, lower, higher ):
return [person for person, tweets in data_tweet.items() if all( lower <= tw[2] <= higher for tw in tweets )]
(notice the similarities)
in either case the result is
>>> famous(tweet,1470000000,1480000000)
['b', 'a']
>>>
As you are not allow to use all, then it should be done old school style, that is using flag, which is a variable which will tell us if the condition is fulfilled or not
def famous(data_tweet, lower, higher ):
result=[]
for person, tweets in data_tweet.items():
is_valid = True
for tw in tweets:
if not ( lower <= tw[2] <= higher):
is_valid = False
break
if is_valid:
result.append( person )
return result
here we first assume that the condition is fulfilled, then we check is that is effectively true, and if is not we change our flag to false and break that loop as there is no more reason to continue with further checks, which is the basically what all do for you. Afterwards, according to the value of the flag we append the person to the list or not.
(If you also are not allow to use break either, don't worry and just remove it, that would not affect the function)
about the counting stuff
result=[]
for person in tweet:
count = 0
for tw in tweet[person]:
count += tw[4] + tw[5]
result.append(count)

List outside of function cannot be tested if members contain a space

A have a function that takes a list and tests if the members of the list are equal to a value. If the value contains a space, this check fails. I used ord() on the target member and on the test value and the characters are indeed all the same.
My current workaround is to strip spaces from the list members, but this is not ideal.
Why is this happening? It seems like a major problem if a list called by a function can't actually be checked for membership if the members have spaces . . .
MWE:
list_ = ['a a', 'bb', 'cc']
for item in list_:
print(item + ' == a a?\t', item is 'a a')
def function_():
for item in list_:
print(item + ' == a a?\t', item is 'a a')
function_()
def function_(list_):
for item in list_:
print(item + ' == a a?\t', item is 'a a')
function_(list_)
The is operator is used to check whether two objects are the same object, but two identical strings don't necessarily point to the same position in memory. Instead, use the equality operator, ==.
def function_():
for item in list_:
print(item + ' == a a?\t', item == 'a a')
Your is check succeeded in your first example because your interpreter performed an optimization that consolidated the two 'a a' string literals into a single object in memory. In your other examples, the 'a a' outside the function and the 'a a' inside the function are in different scopes, so no such optimization occurs.

Resources