When running the following operations on 3 qubits:
H(qubits[0]);
CNOT(qubits[0], qubits[1]);
CNOT(qubits[0], qubits[2]);
CNOT(qubits[1], qubits[2]);
I get these results:
qubit 0 is in a superposition
qubit 1 is the same as qubit 0
qubit 2 is the same as qubit 0 half the time. e.g. superposition-like values.
Why does running CNOT on qubit 2 with both other qubits after running CNOT on qubit 1 with qubit 0 cause qubit 2 to enter a state of superposition between qubit 0 and not qubit 0?
If you do some quantum computing maths, you will find out that you end up in the following state:
|ψ 〉 = (|000〉 + |011〉) / √2
This is essentially a superposition between qubit 0 and entangled qubits 1 and 2.
|ψ 〉 = |0〉 ⊗ (|00〉 + |11〉) / √2
You can do this maths with IBM QISKit in Python:
from qiskit import QuantumProgram
from math import sqrt
import numpy as np
qp = QuantumProgram()
cname = '3-qubit'
num_qubits = 3
qr = qp.create_quantum_register('qr', num_qubits)
cr = qp.create_classical_register('cr', num_qubits)
qc = qp.create_circuit(cname, [qr], [cr])
qc.h(qr[0])
qc.cx(qr[0], qr[1])
qc.cx(qr[0], qr[2])
qc.cx(qr[1], qr[2])
qc.measure(qr, cr)
results = qp.execute(cname)
print(results.get_counts(cname))
This would give you a result similar to the following:
{'000': 530, '011': 494}
You can also explicitly obtain this state |ψ〉 by taking the unitary matrix of your circuit and applying it to your initial state |000〉, that is a vector [1,0,0,0,0,0,0,0]:
results = qp.execute(cname, backend='local_unitary_simulator', shots=1)
data = results.get_data(cname)
u = np.real(data['unitary'] * sqrt(2.0)).astype(int)
psi = np.zeros(2**num_qubits, dtype=np.int_)
psi[0] = 1
u # psi
The result is
array([1, 0, 0, 1, 0, 0, 0, 0])
The 0-th entry is |000〉, the 3-rd entry is |011〉.
you can see this quantum operation as the bitwise operator quantum in the following,
qubits[0]= a
qubits[1] = y
qubits[2] = z
and let # is bitwise operator,
x#x = 0 , any p#0 = p
qubits[0] = H(a) = x (superposition state, final x )
CNOT(qubits[0], qubits[1]) = CNOT(x,y) = (x, x # y) = (x, yy) (final qubits[1]=yy)
CNOT(qubits[0], qubits[2]) = CNOT(x,z) = (x, x # z) = (x, zz)
CNOT(qubits[1], qubits[2]) = CNOT(yy,zz) = (yy, zz# yy) = (x#y, x#z#x#y) = (x#y,z#y) (final qubits[2]=z#y)
(x,y,z) = (0,0,0) ==> (qubits[0],qubits[1],qubits[2]) = (0,0,0)
(x,y,z) = (0,0,1) ==> (qubits[0],qubits[1],qubits[2]) = (0,0,1)
(x,y,z) = (0,1,0) ==> (qubits[0],qubits[1],qubits[2]) = (0,1,1)
(x,y,z) = (0,1,1) ==> (qubits[0],qubits[1],qubits[2]) = (0,1,0)
(x,y,z) = (1,0,0) ==> (qubits[0],qubits[1],qubits[2]) = (1,1,0)
(x,y,z) = (1,0,1) ==> (qubits[0],qubits[1],qubits[2]) = (1,1,1)
(x,y,z) = (1,1,0) ==> (qubits[0],qubits[1],qubits[2]) = (1,0,1)
(x,y,z) = (1,1,1) ==> (qubits[0],qubits[1],qubits[2]) = (1,0,0)
Related
I have a list of coordinates (x,y) and I need to find the index of the first and last occurrence of each coordinate in the list.
Example (in my use-cast I have ~30M coordinates):
x = [1 3 7 1 3];
y = [5 1 6 5 1];
first = [1 2 3 1 2];
last = [4 5 3 4 5];
I implemented it using a Matrix and a loop, it looks like this, but it is slow:
x1 = min(x);
y1 = min(y);
x2 = max(x);
y2 = max(y);
tic
Mlast = zeros(y2-y1+1, x2-x1+1);
Mfirst = Mlast;
ind = sub2ind(size(Mlast),y-y1+1, x-x1+1);
for i1=1:length(ind)
first = Mfirst(ind(i1));
if first == 0
first = i1;
end
Mlast(ind(i1)) = i1;
Mfirst(ind(i1)) = first;
end
I tried to vectorize the whole process, but I only succeed with Mlast:
ind = sub2ind(size(Mlast),y-y1+1, x-x1+1);
t = (1:length(x))';
Mlast(ind) = t;
Mfirst = ???
Is there a way to get this for the first occurrence as well?
The unique function can do that:
[~, b, c] = unique([x(:) y(:)], 'rows', 'first');
first = b(c).';
[~, b, c] = unique([x(:) y(:)], 'rows', 'last');
last = b(c).';
Assuming that coordinates are positive integers and specially when the range of coordinates is small you can use accumarray:
x1 = min(x);
y1 = min(y);
x2 = max(x);
y2 = max(y);
sz = [y2-y1+1, x2-x1+1];
ind = sub2ind(sz,y-y1+1, x-x1+1);
ifirst = accumarray(ind(:), 1:numel(ind), [], #min);
ilast = accumarray(ind(:), 1:numel(ind), [], #max);
Mfirst = ifirst(ind);
Mlast = ilast(ind);
For higher ranges you can use the sparse option:
ifirst = accumarray(ind(:), 1:numel(ind), [], #min,[],1);
ilast = accumarray(ind(:), 1:numel(ind), [], #max,[],1);
If you've got 30M points then you likely don't have enough memory for this method... but it's pretty quick for smaller arrays
x = [1 3 7 1 3];
y = [5 1 6 5 1];
xy = cat( 3, x, y );
chk = all( xy == permute( xy, [2 1 3] ), 3 );
[~,first] = max( chk );
[~,last] = max( flipud( chk ) );
last = size(chk,1) - last + 1;
Edit You can also do this with findgroups, and looping over the unique coordinates instead of each coordinate to have a potentially much shorter loop...
x = [1 3 7 1 3];
y = [5 1 6 5 1];
g = findgroups( x, y );
first = zeros( size( x ) );
last = first;
for ii = 1:max(g)
idx = (ii==g);
first( idx ) = find( idx, 1, 'first' );
last( idx ) = find( idx, 1, 'last' );
end
Edit2 I think these are both pretty slow relative to other answers here...
Given the 2x2 unitary matrix representation of an operation to apply to a single qubit, how do I figure out the rotation it corresponds to on the Bloch sphere?
For example, the Hadamard matrix is a 180 degree rotation around the X+Z axis. How do I get from [[1,1],[1,-1]]*sqrt(0.5) to (X+Z, 180 deg)?
Single-qubit operations are basically just unit quaternions, but with an extra phase factor. The similarity is because the Pauli matrices, times sqrt(-1), satisfy the i^2=j^2=k^2=ijk=-1 relation that defines quaternions.
As a result, the hard part of the conversion method is already taken care of by any "quaternion to axis angle" code. Just pull out the phased quaternion components, figure out the phase factor, then apply the quaternion-to-angle-axis method.
import math
import cmath
def toBlochAngleAxis(matrix):
"""
Breaksdown a matrix U into axis, angle, and phase_angle components satisfying
U = exp(i phase_angle) (I cos(angle/2) - axis sigma i sin(angle/2))
:param matrix: The 2x2 unitary matrix U
:return: The breakdown (axis(x, y, z), angle, phase_angle)
"""
[[a, b], [c, d]] = matrix
# --- Part 1: convert to a quaternion ---
# Phased components of quaternion.
wp = (a + d) / 2.0
xp = (b + c) / 2.0j
yp = (b - c) / 2.0
zp = (a - d) / 2.0j
# Arbitrarily use largest value to determine the global phase factor.
phase = max([wp, xp, yp, zp], key=abs)
phase /= abs(phase)
# Cancel global phase factor, recovering quaternion components.
w = complex(wp / phase).real
x = complex(xp / phase).real
y = complex(yp / phase).real
z = complex(zp / phase).real
# --- Part 2: convert from quaternion to angle-axis ---
# Floating point error may have pushed w outside of [-1, +1]. Fix that.
w = min(max(w, -1), +1)
# Recover angle.
angle = -2*math.acos(w)
# Normalize axis.
n = math.sqrt(x*x + y*y + z*z);
if n < 0.000001:
# There's an axis singularity near angle=0.
# Just default to no rotation around the Z axis in this case.
angle = 0
x = 0
y = 0
z = 1
n = 1
x /= n
y /= n
z /= n
# --- Part 3: (optional) canonicalize ---
# Prefer angle in [-pi, pi]
if angle <= -math.pi:
angle += 2*math.pi
phase *= -1
# Prefer axes that point positive-ward.
if x + y + z < 0:
x *= -1
y *= -1
z *= -1
angle *= -1
phase_angle = cmath.polar(phase)[1]
return (x, y, z), angle, phase_angle
Testing it out:
print(toBlochAngleAxis([[1, 0], [0, 1]])) # Identity
# ([0, 0, 1], 0, 0.0)
print(toBlochAngleAxis([[0, 1], [1, 0]])) # Pauli X, 180 deg around X
# ([1.0, -0.0, -0.0], 3.141592653589793, 1.5707963267948966)
print(toBlochAngleAxis([[0, -1j], [1j, 0]])) # Pauli Y, 180 deg around Y
# ([-0.0, 1.0, -0.0], 3.141592653589793, 1.5707963267948966)
print(toBlochAngleAxis([[1, 0], [0, -1]])) # Pauli Z, 180 deg around Z
# ([-0.0, -0.0, 1.0], 3.141592653589793, 1.5707963267948966)
s = math.sqrt(0.5)
print(toBlochAngleAxis([[s, s], [s, -s]])) # Hadamard, 180 deg around X+Z
# ([0.7071067811865476, -0.0, 0.7071067811865476], 3.141592653589793, 1.5707963267948966)
print(toBlochAngleAxis([[s, s*1j], [s*1j, s]])) # -90 deg X axis, no phase
# ((1.0, 0.0, 0.0), -1.5707963267948966, 0.0)
I have 3 arrays in matlab that are 1xN, X Y Z respectively. I need to read these arrays into a 3xN matrix respectively so I get
x1 y1 z1
x2 y2 z2
.. .. ..
xn yn zn
I have currently got the data in a Nx 3 matrix, the wrong way round. The code I have is
X = [];
Y = [];
Z = [];
for ctr = 1:length(A)
X = [X A(ctr,1)];
Y = [Y A(ctr,2)];
Z = [Z A(ctr,3)];
end
M = [X;Y;Z];
Where A is the input data from a 624*600 double cell and M is my desired matrix.
Thanks
I guess you want that:
X = [];
Y = [];
Z = [];
for ctr = 1:length(A)
X(end+1, 1) = A(ctr,1);
Y(end+1, 1) = A(ctr,2);
Z(end+1, 1) = A(ctr,3);
end
M = [X Y Z];
Faster with 1 line code:
M = [A(:, 1) A(:, 2) A(:, 3)];
I just found that you can transpose with Mt = transpose(M); which has the overall intended result but feels like 3 rights to make a left.
I have a 3-dimensional array. Think of it as a brick. There are 24 possible rotations of this brick (that keep its edges parallel to coordinate axes). How do I generate all corresponding 3-dimensional arrays?
A die (half a pair of dice) is handy for observing the 24 different orientations, and can suggest operation sequences to generate them. You will see that any of six faces can be uppermost, and the sides below can be rotated into four different cardinal directions. Let us denote two operations: “turn” and “roll”, where turn rotates the die about the z axis from one cardinal to the next, and roll rotates the die 90° away from you, so the away-face becomes the bottom face and the near face the top. These operations can be expressed using rotation matrices as mentioned in the answer of Felipe Lopes, or can be expressed as simple functions that when given (x,y,z) return (-y,x,z) or (x,z,-y), respectively.
Anyhow, if you place the die with 1 on the near face, 2 at right, and 3 on top, you will find that the following sequence of steps generates the twelve different orientations with 1, 2, or 3 spots on top: RTTTRTTTRTTT. Then the sequence RTR exposes 6, 4, 5 where 1, 2, 3 originally were, and a repeat of the sequence RTTTRTTTRTTT generates the twelve orientations with 4, 5, or 6 spots on top. The mentioned sequence is embedded in the following python code.
def roll(v): return (v[0],v[2],-v[1])
def turn(v): return (-v[1],v[0],v[2])
def sequence (v):
for cycle in range(2):
for step in range(3): # Yield RTTT 3 times
v = roll(v)
yield(v) # Yield R
for i in range(3): # Yield TTT
v = turn(v)
yield(v)
v = roll(turn(roll(v))) # Do RTR
p = sequence(( 1, 1, 1))
q = sequence((-1,-1, 1))
for i in sorted(zip(p,q)):
print i
The rationale for printing out a sorted list of transformed pairs of points is twofold: (i) any face orientation can be specified by the locations of two of its corners; (ii) it then is easy to check for uniqueness of each pair, eg by piping output to uniq.
Here is how the sorted output begins:
((-1, -1, -1), (-1, 1, 1))
((-1, -1, -1), (1, -1, 1))
((-1, -1, -1), (1, 1, -1))
((-1, -1, 1), (-1, 1, -1))
((-1, -1, 1), (1, -1, -1))
((-1, -1, 1), (1, 1, 1))
((-1, 1, -1), (-1, -1, 1))
((-1, 1, -1), (1, -1, -1))
((-1, 1, -1), (1, 1, 1))
Let X rotate 90 degrees around the X-axis and Y rotate 90 degrees around the Y-axis then the 24 possible unique combinations are (all possible combinations up to 5 rotations are given except those with four times the same rotation (eg XXXX, XXXXY XYYYY, etc):
1. I
2. X
3. Y
4. XX = YXXY
5. XY
6. YX
7. YY = XYYX
8. XXX = XYXXY = YXXYX = YXYXY = YYXYY
9. XXY = YXXYY = YYYXX
10. XYX = YXY
11. XYY = XXYYX = YYXXX
12. YXX = XXYYY = YYXXY
13. YYX = XXXYY = XYYXX
14. YYY = XXYXX = XYXYX = XYYXY = YXYYX
15. XXXY
16. XXYX = XYXY = YXYY
17. XXYY = YYXX
18. XYXX = YXYX = YYXY
19. XYYY
20. YXXX
21. YYYX
22. XXXYX = XXYXY = XYXYY = YXYYY
23. XYXXX = YXYXX = YYXYX = YYYXY
24. XYYYX = YXXXY
Of course you can use any two 90 degree rotations in place of the X and Y. For example, Y and Z.
Or, if you also use Z, a 90 degree rotation around the Z axis then 4 rotations suffice:
1. I
2. X = YXZ
3. Y = ZYX
4. Z = XZY
5. XX = XYXZ = YXXY = YXYZ = YXZX = YYZZ = YZXZ = ZXXZ = ZZYY
6. XY = YZ = ZX = XZYX = YXZY = ZYXZ
7. XZ = XXZY = YXZZ = YYYX = ZYYY
8. YX = XZZZ = YYXZ = ZYXX = ZZZY
9. YY = XXZZ = XYYX = YZYX = ZXYX = ZYXY = ZYYZ = ZYZX = ZZXX
10. ZY = XXXZ = XZYY = YXXX = ZZYX
11. ZZ = XXYY = XYZY = XZXY = XZYZ = XZZX = YYXX = YZZY = ZXZY
12. XXX
13. XXY = XYZ = XZX = YZZ = ZXZ
14. XXZ = ZYY
15. XYX = YXY = YYZ = YZX = ZXX
16. XYY = YZY = ZXY = ZYZ = ZZX
17. XZZ = YYX
18. YXX = ZZY
19. YYY
20. ZZZ
21. XXXY = XXYZ = XXZX = XYZZ = XZXZ = YZZZ = ZXZZ = ZYYX
22. XXYX = XYXY = XYYZ = XYZX = XZXX = YXYY = YYZY = YZXY = YZYZ = YZZX = ZXXY = ZXYZ = ZXZX = ZYZZ = ZZXZ
23. XYXX = XZZY = YXYX = YYXY = YYYZ = YYZX = YZXX = ZXXX
24. XYYY = YXXZ = YZYY = ZXYY = ZYZY = ZZXY = ZZYZ = ZZZX
These 24 matrices all exist of three column vectors that each exist of two zeroes and a minus one or plus one. On every row there are also exactly two zeroes. As such, they can easily be generated: the first column vector has six possibilities ((1,0,0), (-1,0,0), (0,-1,0), (0,1,0), (0,0,-1) and (0,0,1)), this corresponds to moving the positive X-axis to the positive or negative x, y or z axis. The second column vector only has four possibilities because it must contain a zero where the first column has a non-zero value. Finally the third column vector has only one place left where its plus or minus one can be. This gives 6 * 4 * 2 = 48 matrices, half of them mirror the original as well however (they are combination of a mirror and optionally a rotation). Hence only 24 are pure rotations. The matrices that are mirror operations will have a determinant equal to -1, the determinant of the pure rotations is 1.
James Waldby's answer is inspiring, and I want to add a slightly improved version with only two for-loops.
We know that there are 24 unique orientations. I calculated this by imagining a dice: there are 6 possible choices for the top face, and 4 possible rotations for each face on top.
What if we iterate with that idea? I thought. If we can figure out a way to travel all 6 faces of the dice, then we only need to observe the 4 rotations on each face, and we are done!
So I grabbed the nearest "brick" (in my case, a Vitasoy carton) and started rotating to see what would be the easiest pattern to visit all 6 faces. If we introduce an additional counter-clockwise turn, such that our operations are:
Roll (in a fixed direction, e.g. so that the face facing you is now rotated downwards)
Turn CW (along a fixed axis, e.g. so that the face facing you is turned clockwise, but still facing you)
Turn CCW (along the same axis as the last one)
Then we can visit all faces by doing:
Roll -> Turn CW -> Roll -> Turn CCW -> Roll -> Turn CW -> Roll -> Turn CCW -> Roll -> Turn CW -> Roll -> Turn CCW
With the last roll and turn, we are back to the original orientation. As you can see, it is a repeated sequence of roll + alternating CW turns and CCW turns.
Now, if we expand this to include all rotations of each face we visit, this becomes:
Roll -> 3x Turn CW -> Roll -> 3x Turn CCW -> Roll -> 3x Turn CW -> Roll -> 3x Turn CCW -> Roll -> 3x Turn CW -> Roll -> 3x Turn CCW
...and we are back to where we started! This can be translated into two for-loops (one fewer!):
def sequence(m):
for roll_index in range(6):
m = roll(m)
yield(m)
for turn_index in range(3):
m = turn_cw(m) if roll_index % 2 == 0 else turn_ccw(m)
yield(m)
You can use rotation matrices. Rotating a 3D array around the x-axis means that the element at position (i,j,k) will be mapped to position (i,-k,j). Of course, if your array is 0-indexed, you probably have to replace -k with size-1-k or something like that.
Similarly, rotating around the y-axis maps (i,j,k) to (k,j,-i). These two rotations can be represented as matrices. For the x-axis rotation:
|i'| |1 0 0| |i|
|j'| = |0 0 -1|*|j|
|k'| |0 1 0| |k|
And for the y-axis rotation:
|i'| |0 0 1| |i|
|j'| = |0 1 0|*|j|
|k'| |-1 0 0| |k|
Any general rotation can be described as a sequence of those two rotations. Applying two rotations consecutively is just multiplying the 3x3 matrices. So, if you find all possible products of them, you'd get 24 matrices (including the identity), each one corresponds to a valid rotation of your array. It's a little tricky to find all possible multiplications, because they don't commute.
I think you can just brute-force all products of the form (A^p)*(B^q)*(A^r)*(B^s), where A and B are the two matrices before and p,q,r,s are their powers, and range from 0 to 3 (exponentiating A or B to 4 will take them back to the identity matrix).
Doing it this way, you can generate all 24 valid rotation matrices, and rotate the 3D array using each one of them, taking the care to shift the negative indexes so that you don't access out of bounds.
import numpy as np
def rotations(array):
for x, y, z in permutations([0, 1, 2]):
for sx, sy, sz in itertools.product([-1, 1], repeat=3):
rotation_matrix = np.zeros((3, 3))
rotation_matrix[0, x] = sx
rotation_matrix[1, y] = sy
rotation_matrix[2, z] = sz
if np.linalg.det(rotation_matrix) == 1:
yield np.matmul(rotation_matrix, array)
all_rotations = list(rotations(np.array(array)))
Idea is to generate all coordinates relabelings with possible axis' direction changes, ex. (-z, y, x). The question that remains is whether all coordinates relabelings are obtainable from (x, y, z) axes using only rotations. Half of the 6 * (2^3) = 48 labelings aren't because they are rotations of a mirrored version of the (x, y, z) cooridnates (left-handed coordinates, https://en.wikipedia.org/wiki/Right-hand_rule).
Rows of the corresponding rotation matrix A of relabeling operation will have only one value in each row. The value determines which axis to select on that index, and whether to flip the axis.
A * (x, y, z) = (-z, y, x)
| 0, 0, -1 |
A = | 0, 1, 0 |
| 1, 0, 0 |
We keep only those rotations, whose det(A) == 1 meaning that only rotations were applied by the operation. det(A) == -1 means that it is a rotation with mirroring.
I've X axis with values [2,6,10] and for Y axis [0.5,0.4,0.2,0.2,....0.5], all values between 0 and 1.
There are certain points which correspond to 2, let's say 1/3rd and the remaining 1/3rd for 6 and remaining 1/3rd for 10. The points corresponding to 2 can have any values between 0 and 1, same applies for point 6 and point 10.
How can I plot this?
I guess you have some way to match up each Y-value to its corresponding X-value. By generating a vector of the same length as Y with these X-values they can then be plotted against each other.
The two vectors will then have the following form:
X = [2,6,2,10,6,6,10,2,....6]
Y = [0.5,0.4,0.2,0.2,0.9,0.3....0.5]
Here is a sample code
% X-data
X = [2,6,10];
% Generate random Y-data
n1 = 10;
n2 = 20;
n3 = 30;
n = n1 + n2 + n3;
Y = rand(1,n);
% Match X indices corresponding to Y
% Xall = [2,2,2,...,2,6,6,6,...,6,10,10,10,...,10]
X1 = zeros(1,n1);
X1(:) = X(1);
X2 = zeros(1,n2);
X2(:) = X(2);
X3 = zeros(1,n3);
X3(:) = X(3);
Xall = [X1 X2 X3];
plot(Xall,Y,'o')
xlim([min(X)-2,max(X)+2])
which will generate a figure of the following form
plot(a(1:3:end))
This will plot every third point.
a=[0.5,0.4,0.2,0.2,....0.5]
b=[1:3:length(a)]
plot(a(b))