Numpy: Comparing array elements within another array - arrays

I have a numpy array
X = [[1,2], [3,4], [5,6], [1,2], [5,6]]
I want a numpy array Y = [1, 2, 3, 1, 3], where [1,2] is replaced by 1, [3,4] replaced by 2 and so on. This is for a very large (think millions) X.
Intuition is Y[X == [1,2]] = 1. But this does't work.

Intuition is Y[X == [1,2]] = 1. But this does't work.
Here is how to make it work:
Y = np.empty(len(X), dtype=np.int)
Y[np.all(X == [1, 2], 1)] = 1
To process all the possible values:
s = set(map(tuple, X))
r = np.arange(1, len(s) + 1) # or assign whatever values you want
cond = [np.all(X == v, 1) for v in s]
Y = np.dot(r, cond)

Related

Big for loop for permutation

I receive 3 integers, "x", "y" and "z". Then a last integer which is "n".
I have to find all possible combinations between x, y and z as in a permutation, but I only need to save those ones where the sum of all values is not equal to n (x + y + z != n).
I have done this trough a big for loop. As you can see, the print output confirms that this logic works, so all the possible combinations are found with any 3 integers you use. Each combination is temporary saved on a list which is constantly overwritten.
I filter the combinations so you can see with the print function only those which sum of the values on the list is not n. However, when I want to save each combination found, it just saves repeated values and it seems that the append method is not working as I need to.
# Example:
#
# Input: x = 1
# y = 1
# z = 1
# n = 2
#
# Output = [[0,0,0],[0,0,1],[0,1,0],[1,0,0],[1,1,1]]
x = int(input())
y = int(input())
z = int(input())
n = int(input())
list_x = [x for x in range(x+1)] #numbers from 0 to x
list_y = [y for y in range(y+1)] #numbers from 0 to y
list_z = [z for z in range(z+1)] #numbers from 0 to z
results = []
#Big for loop which makes the permutation
combination = [0,0,0]
for num_x in list_x:
combination[0] = num_x
for num_y in list_y:
combination[1] = num_y
for num_z in list_z:
combination[2]=num_z
if sum(combination) != n: #Find combinations where total sum != to n
print(combination) #print the combination found
results.append(combination) #save the combination in a list of lists
print(results) #print the lists of lists
Any kind of help is really appreciated. Thank you.
It's because combination is a reference to an underlying list, and that's what you're storing in the results (the reference, not the list). This is one of those "a-ha" moments that all Python coders experience, when they start to fully grok the language :-)
Every time you change an element of the list (as opposed to the actual list), every reference to it seems to change as well, because there's only one list.
This makes it appear that you're changing things that have already been set at an earlier time but that's not actually the case.
You can see that in action with:
>>> xyzzy = [1, 2, 3] # The list.
>>> plugh = xyzzy # Copies reference, not list content.
>>> xyzzy[1] = 99 # Changes list content (for BOTH references).
>>> xyzzy ; plugh # Result: they are both changed.
[1, 99, 3]
[1, 99, 3]
>>> xyzzy = [4, 5, 6] # Makes xyzzy reference point to NEW list.
>>> xyzzy ; plugh # Result: they are different.
[4, 5, 6]
[1, 99, 3]
To fix that, you can just get rid of combination and just use something like:
for num_x in list_x:
for num_y in list_y:
for num_z in list_z:
if num_x + num_y + num_z != n:
results.append([num_x, num_y, num_z])
print(results[-1])
That creates and appends a new list each time, so changes won't seem to travel back through time.
And, for what it's worth, this can also be done with a more Pythonic list comprehension. Using your supplied test data, dummied up:
list_x, list_y, list_z, n = [0, 1], [0, 1], [0, 1], 2
result = [[x, y, z] \
for x in list_x \
for y in list_y \
for z in list_z \
if x + y + z != n]
print(result)
I've split the comprehension across multiple lines for readability but it could just as easily go on one line, and it gives the expected output as per below:
[[0, 0, 0], [0, 0, 1], [0, 1, 0], [1, 0, 0], [1, 1, 1]]

Modifying a 3d array using a 2D index with Numpy

I have an array in three dimensions (a, b, c) and I need to modify the positions c indexed by an array in two dimensions (a, b).
I wrote a code that works as expected, but does anyone know if there is a way to solve this problem without the for loop?
import numpy as np
arr = np.random.randn(100, 5, 2)
mod = np.random.randn(100, 5)
ids = np.random.randint(0, 2, size=[100,5])
for i in range(100):
for j in range(5):
arr[i,j,ids[i,j]] = mod[i,j]
You can refer to and set each slice of the array directly. I think this code shows the behaviour you are asking about:
import numpy as np
arr = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])
print(arr[:,:,2])
# Output:
#[[ 3 6]
# [ 9 12]]
new2DSlice = np.array([[23, 26], [29, 32]])
arr[:,:,2] = new2DSlice
print(arr[:,:,2])
# Outupt:
#[[23 26]
# [29 32]]
arr[:,:,2] refers to the third slice of the array and, in this example, sets it directly.
You can read about NumPy's array indexing and array slicing on W3Schools.
I got with this:
import numpy as np
arr = np.random.randn(100, 5, 2)
mod = np.random.randn(100, 5)
ids = np.random.randint(0, 2, size=[100,5])
x = np.arange(100)
y = np.arange(5)
arr[x[:,None],y,ids] = mod

Ruby Array: opposite of `&` for an array

In ruby you can intersect two arrays using the & operator.
I'm trying to obtain the remainder of the intersection.
If I use a simple case - is sufficient:
array_1 = [0, 1]
array_2 = [0]
array_1 - array_2 => [1]
Now imagine we have 0 appearing multiple times in the first array
array_1 = [0, 0, 1]
array_2 = [0]
array_1 - array_2 => [1]
I would like to know the easiest way to obtain the difference between the first array and the intersection of the first array and the second array
array_1 = [0, 0, 1]
array_2 = [0]
array_1 ??? array_2 => [0, 1]
I have proposed the method I think you want be added to the Ruby core. See the link for examples of its use.
class Array
def difference(other)
h = other.each_with_object(Hash.new(0)) { |e,h| h[e] += 1 }
reject { |e| h[e] > 0 && h[e] -= 1 }
end
end
a = [1,2,3,4,3,2,2,4]
b = [2,3,4,4,4]
a.difference b
#=> [1, 3, 2, 2]

How to stack arrays in repa (Haskell)

Suppose there are two 1-D arrays of the same length:
let x = fromListUnboxed (ix1 4) [1, 2, 3, 4]
let y = fromListUnboxed (ix1 4) [5, 6, 7, 8]
Now I would like to stack these two arrays into one 2-D array so that these arrays form the rows. How can I do it in repa?
Basically, I'm looking for an equivalent of numpy's row_stack:
>>> x = np.array([1, 2, 3, 4])
>>> y = np.array([5, 6, 7, 8])
>>> np.row_stack((x, y))
array([[1, 2, 3, 4],
[5, 6, 7, 8]])
Note. The two arrays, x and y, come from outside, i.e. I cannot create the 2-D array from scratch.
As I mentioned in the initial comment, all you need is to reshape then append (both in Data.Array.Repa.
ghci> let x' = reshape (ix2 4 1) x
ghci> let y' = reshape (ix2 4 1) y
ghci> z <- computeP $ x' `append` y' :: IO (Array U DIM2 Int)
ghci> z
AUnboxed ((Z :. 4) :. 2) [1,5,2,6,3,7,4,8]
As for pretty-printing, repa isn't very good (likely because there is no good pretty printing for higher dimensions). Here is a one-line hack to display z
ghci> putStr $ unlines [ unwords [ show $ z ! ix2 i j | i<-[0..3] ] | j<-[0..1] ]
1 2 3 4
5 6 7 8

z3py: how to represent an array of integers or characters in z3py

I am new to z3py and SMT and I haven't found a good tutorial about z3py.
Here is my problem setting:
Given an input integer array I=[1,2,3,4,5], and an output integer array O=[1,2,4,5].
I want to infer k for the operator Delete, which deletes the element at position k in an array, where
Delete(I,O) =  (ForAll 0<=x<k, O[x] = I[x] ) and (ForAll k<=x<length(I)-1, O[x] = I[x+1]) is true
Should I use Array or IntVector, or anything else to represent the input/output array?
Edit:
My code is as follows:
from z3 import *
k=Int('k')
s=Solver()
x = Int('x')
y = Int('y')
s.add(k >= 0)
s.add(k < 4)
s.add(x >= 0)
s.add(x < k)
s.add(y >= k)
s.add(y < 4)
I = Array('I',IntSort(),IntSort())
O = Array('O',IntSort(),IntSort())
Store(I, 0, 1)
Store(I, 1, 2)
Store(I, 2, 3)
Store(I, 3, 4)
Store(I, 4, 5)
Store(O, 0, 1)
Store(O, 1, 2)
Store(O, 2, 4)
Store(O, 3, 5)
s.add(And(ForAll(x,Select(O,x) == Select(I,x)),ForAll(y,Select(O,y) == Select(I,y+1))))
print s.check()
print s.model()
It returns
sat
[I = [2 -> 2, else -> 2],
O = [2 -> 2, else -> 2],
y = 1,
k = 1,
x = 0,
elem!0 = 2,
elem!1 = 2,
k!4 = [2 -> 2, else -> 2]]
I don't understand what I, O, elem!0, elem!1 and k!4 mean and this is clearly not what I expected.
Disclaimer: I've hardly ever used Z3py before, but I've used Z3 quite a bit.
I have the feeling that you are somewhat new to encoding logical problems as well - could that be? There are several (odd) things going on in your problem.
You put constraints on x and y, but you actually never use them - instead, you bind different x and y in your quantified assertions. The latter two may have the same names, but they are totally unrelated to the x and y that you constrained (since each forall binds its own variable, you could also use x in both). Hence, your quantified x and y range over all Int, whereas you probably want to limit them to the interval [0..4). Use an implication inside the forall for this.
According to the docs, Store(a, i, v) returns a new array a' that is identical to a, except that x[i] == v. That is, you need to call I = Store(I, 0, 1) etc. in order to finally get an array I that stores your desired values.
Since you don't do this, Z3 is free to pick a model that satisfies your constraints. As you can see from the output, the model for I is [2 -> 2, else -> 2], which says that I[2] == 2, and I[i] == 2 for any i != 2. I don't know why Z3 chose that particular model, but it (together with the model for O) satisfies your foralls.
You can probably ignore elem!0, elem!1 and k!4, they are internally generated symbols.
Here is a reduced version of your example that doesn't verify:
x = Int('x')  
I = Array('O',IntSort(),IntSort())
O = Array('O',IntSort(),IntSort())
I = Store(I, 0, 1)
I = Store(I, 1, 2)
s.add(
And(
ForAll(x, Select(O,x) == Select(I,x)),
ForAll(x, Select(O,x) == Select(I,x+1))))
print s.check() # UNSAT
The reason why it is unsatisfiable is that I[0] == 1 && I[1] == 2, which contradicts your foralls. If you instantiate both quantified x with 0, the you get O[0] == I[0] && O[0] == I[1] - a constrain that cannot be fulfilled, i.e. there is no model for O that satisfies it.
Edit (to address a comment):
If you are puzzled why, given a snippet such as
I = Array('O',IntSort(),IntSort())
I = Store(I, 0, 1)
I = Store(I, 1, 2)
# print(I)
s.check()
s.model()
Z3 reports sat and returns a model where I = [], then recall that each Store(...) returns a fresh Z3 expression that represents a store operation, each of which in turn returns a fresh array (which is equal to the initial one, modulo the update). As the print shows, the final value of I is the expression Store(Store(I, 0, 1), 1, 2). It therefore suffices to let I itself be the empty array, i.e. I - the updates (the Stores) will each yield a fresh array (think I1 and I2 in this case), but since they are nameless, they won't (or at least don't have to) show up in the model.
If you want to explicitly see the "final" values of your array in the model, you can achieve this by giving a name to the array that is created by the last Store, e.g
I = Array('I',IntSort(),IntSort())
I = Store(I, 0, 1)
I = Store(I, 1, 2)
II = Array('II',IntSort(),IntSort())
s.add(I == II)
s.check()
s.model() # includes II = [1 -> 2, 0 -> 1, else -> 3]
This is the correct answer to my question:
from z3 import *
x = Int('x')
y = Int('y')
k = Int('k')
s = Solver()
I = Array('I',IntSort(),IntSort())
O = Array('O',IntSort(),IntSort())
I = Store(I, 0, 1)
I = Store(I, 1, 2)
I = Store(I, 2, 3)
I = Store(I, 3, 4)
I = Store(I, 4, 5)
O = Store(O, 0, 1)
O = Store(O, 1, 2)
O = Store(O, 2, 4)
O = Store(O, 3, 5)
s.add(k >= 0)
s.add(k < 4)
s.add(And(ForAll([x],Implies(And(x>=0,x<k),Select(O,x) == Select(I,x))),ForAll([y],Implies(And(y>=k,y<4),Select(O,y) == Select(I,y+1)))))
print s.check()
if s.check() == z3.sat:
print s.model()
The answer is
sat
[I = [2 -> 2, else -> 2],
k = 2,
O = [2 -> 2, else -> 2],
k!17 = [2 -> 2, else -> 2]]

Resources