I'm creating a truth table with Python and I have done so iteratively without any hassle, but I'm trying to figure out how to generate all possible values of True and False, for any number of variable recursively.
Starting with a list like: [[True], [False]]
I need to be able to generate a list like:
[[True, True, True],
[True, True, False],
[True, False, True],
[True, False, False],
[False, True, True],
[False, True, False],
[False, False, True],
[False, False, False]]
where every list is a row in the truth table.
Based on this, you go through and evaluate each row, appending the value of true or false to the end of each list based on the expression being evaluated.
I have already solved the problem iteratively, but doing it recursively doesn't make any sense to me. I've always thought of recursion as starting large and becoming small (reducing toward the base case). Like in merge sort. Not the other way around.
I cannot use anything like itertools.
The hint in the assignment is "Tips: You can use the following recursive algorithm to create all combinations of variables for the truth table:
Base case: For a single variable, the list of all combinations is [ [True], [False] ]
Recursive case: each element in the list (which is itself a list), is replaced with two lists, one with True appended to it, and one with False appended to it."
The algorithm doesn't make sense to me.
The following recursive implementation will work. Note that you can have an even simpler base case:
def bool_combs(n):
if not n:
return [[]]
result = []
for comb in bool_combs(n-1):
result.append(comb + [True])
result.append(comb + [False])
return result
>>> bool_combs(1)
[[True], [False]]
>>> bool_combs(2)
[[True, True], [True, False], [False, True], [False, False]]
>>> bool_combs(3)
[[True, True, True], [True, True, False], [True, False, True], [True, False, False], [False, True, True], [False, True, False], [False, False, True], [False, False, False]]
Related
i would like to know if there is a faster way, not O(n^2), to create a bool matrix out of an integer nxn-matrix.
Example:
given is the matrix:
matrix_int = [[-5,-8,6],[4,6,-9],[7,8,9]]
after transformation i want this:
matrix_bool = [[False,False,True],[True,True,False],[True,True,True]]
so all negative values should be False and all positive values should be True.
The brute force way is O(n^2) and this is too slow for me, too you have any ideas how to make this faster?
matrix_int = [[-5,-8,6],[4,6,-9],[7,8,9]]
matrix_int = np.array(matrix_int)
bool_mat = matrix_int > 0
result:
array([[False, False, True],
[ True, True, False],
[ True, True, True]])
matrix_int = [[-5,-8,6],[4,6,-9],[7,8,9]]
matrix_bool = [[num > 0 for num in row] for row in matrix_int]
# [[False, False, True], [True, True, False], [True, True, True]]
I know for 1d arrays there is a function called np.in1d that allows you to find the indices of an array that are present in another array, for example:
a = [0,0,0,24210,0,0,0,0,0,21220,0,0,0,0,0,24410]
b = [24210,24610,24410]
np.in1d(a,b)
yields [False, False, False, True, False, False, False, False, False,
False, False, False, False, False, False, True]
I was wondering if there was a command like this for finding lists in a list of lists?
c = [[1,0,1],[0,0,1],[0,0,0],[0,0,1],[1,1,1]]
d = [[0,0,1],[1,0,1]]
something like np.in2d(c,d)
would yield [True, True, False, True, False]
Edit: I should add, I tried this with in1d and it flattens the 2d lists so it does not give the correct output.
I did np.in1d(c,d) and the result was [ True, True, True,
True, True, True, True, True, True, True, True, True, True, True,
True]
What about this?
[x in d for x in c]
I have an array 2*n of True and False boolean.
array([[False, True],
[False, True],
[False, True],
...,
[False, True],
[False, True],
[False, True]])
What I want is a new vector, can be in another array that has False if any of the two values are False.
I can create a loop and check each value in the row, and make a new vector. but I'm guessing it's slow
boidx = np.empty(len(minindex), dtype=bool)
for idx in range(len(minindex)):
if minindex[idx,0] and minindex[idx,1]:
boidx[idx]=True
else:
boidx[idx]=False
but this is long and not pythonic.
The array is either 2n or 4n. so it should cover those options (my for loop does not)
but if needed, two solutions with an if for size is doable.
I also tried to use numpy.isin() command. but it works for each cell. I need per row.
As an answer already pointed out, you can use numpy.all() to solve it.
A simpler formulation without any loop would be:
np.all(minindex, axis=1)
If I understand correctly, a pythonic solution could use numpy.all:
import numpy as np
minindex = np.array([[False, True],
[False, True],
[True, True],
[True, False],
[False, True],
[False, False],
[False, False],
[True, True]
boidx = np.array([np.all(i) for i in minindex])
and you get:
[False False True False False False False True]
Another solution could be the use of prod:
boidx = np.array([bool(i.prod()) for i in minindex])
and you get the same result.
As suggested by #Jianyu, this way should be definitely faster:
boidx = np.all(minindex, axis=1)
So I need to generate a truth table for a bunch of different functions (like implies, not p and q, not p and q, and, or, etc.)
I have a recursive method that generates the first two terms of each index correctly ([False, False], [False, True], [True, False], [True, True]).
However what I need to do is take those two terms and then append the result of those two from one of the different functions to the end of the indices.
make_tt_ins(n): My recursive table builder with n rows (in this case two)
and callf2(f, p, q): a given function that generates the True / False term I'll need to append onto each index.
my_list = PA1.make_tt_ins(2)
p = True;
q = True;
val = [callf2(f, p, q)]
returnVal = [i + val for i in my_list]
return returnVal
Obviously, all I'm getting is True after my intial two values in each index. I just don't know how to correctly append the callf2 function result onto my first two values in each index.
For the function implies (p <-> q), I'm getting:
[[False, False, True], [False, True, True], [True, False, True], [True, True, True]]
It should look something like:
[[False, False, True], [False, True, False], [True, False, False], [True, True, True]]
Figured it out. To anyone wondering, I decided to use one massive while loop with a counter where at each step I would set p / q to different True/False values and then run them with the callf2 function. I then turned those values in a list, which I appended onto my first partial list.
This question already has answers here:
List of lists changes reflected across sublists unexpectedly
(17 answers)
Closed 5 years ago.
so I have a boolean list of lists and I changed a certain index from True to False, and it affects some others element in list of lists too. Why is it happening? is there any alternative?
test = [[True]*9]*9
test[0][1] = False
print(test)
The output:
[[True, False, True, True, True, True, True, True, True],
[True, False, True, True, True, True, True, True, True],
[True, False, True, True, True, True, True, True, True],
[True, False, True, True, True, True, True, True, True],
[True, False, True, True, True, True, True, True, True],
[True, False, True, True, True, True, True, True, True],
[True, False, True, True, True, True, True, True, True],
[True, False, True, True, True, True, True, True, True],
[True, False, True, True, True, True, True, True, True]]
What you want to do is :
test = [[True for i in range(cols)] for j in range(rows)]
#OR
test = [[True]*cols for j in range(rows)]
The problem with doing
test = [[True]*9]*9
is that you are creating a multi-dimensional list that is referencing the same memory address that holds the True value.
It is something like having :
test = [ [True, True, True, True, True, True, True, True, True] repeated 9 times ]
where the rows all point to the same memory location of their respective columns. So when you change value in one column, it changes for the whole set of column value.
So, with the desired way,
test = [[True for i in range(9)] for j in range(9)]
test[0][1] = False
print(test)
will print :
[[True, False, True, True, True, True, True, True, True],
[True, True, True, True, True, True, True, True, True],
[True, True, True, True, True, True, True, True, True],
[True, True, True, True, True, True, True, True, True],
[True, True, True, True, True, True, True, True, True],
[True, True, True, True, True, True, True, True, True],
[True, True, True, True, True, True, True, True, True],
[True, True, True, True, True, True, True, True, True],
[True, True, True, True, True, True, True, True, True]]
This is caused by the fact that the star (*) operator doesn't create n new independent lists. It creates n references to the same list. Creating a list with all independent lists can be done using a list comprehension, as is already suggested:
test = [[True for i in range(cols)] for j in range(rows)]
Yes, that's a classic python gotcha. In the inner multiplication, you make 9 copies of True. That generates a list of 9 instances of the same True object. However, the True object is immutable, so you can't change it, you just replace one of them, without affecting others.
On the contrary, in the outer multiplication, you create 9 copies of the same inner list. However, lists are mutable, so, when you change one of them, it really changes. Since the outer list consists of copies of the same list, the will all change.
You can only avoid it by creating 9 different lists
test = [[Test]*9 for i in range(9)]