Convert from qubit operation to axis-angle Bloch sphere rotation - quantum-computing

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)

Related

How to create meshgrid with non-integer stepsize of list elements?

I have 2 lists of x and y coordinate that are independently generated, with a/h amount of points between 0 and a.
x = np.linspace(0, a, a/h)
y = np.linspace(0, d, d/h)
when a/h is such that 0 increases to a in steps of integers i.e. [0,1,2,..,a]. It's nice because then the number of elements within the list can be used as indices. And as a result I can usually create a meshgrid such that a third list V1 can be associated with it.
X, Y = plt.meshgrid(x, y)
def potential(V1):
return V1[X, Y]
where potential(V1) is now V1 corresponding to the meshgrid [x, y]. However I'm doing an assignment where I'm required to investigate how step-sizes affect my problem. As a result if I was to have a step-size of non-integers from 0 to a i.e. [0, 0.5, 1,...,a] Now I can't do what I did above since the indices are now non-integers. Raising the error
IndexError: arrays used as indices must be of integer (or boolean) type
How can I fix this so that I don't rely on the value of the element itself as the index of the elements, so that if there was a step-size of 0.25 between 0 to a for a list X say i.e.
X = [0, 0.25, 0.75. 1.0] or x = np.linspace(0,1,4)
such that I can have
x[0] = 0 corresponds to V[0]
x[1] = 0.25 corresponds to V[1]
x[2] = 0.75 corresponds to V[2]
x[3] = 1 corresponds to V[3]
?

Variable elimination in Bayes Net on a node with single child

If we have a node X, that has a child Y in a Bayes net, why is it correct to express P(Y) as P(Y|X)P(X)? Does it then follow that X is a necessary condition for Y?
Bayes Networks
An edge in a Bayes Network means the variable is conditionally dependent. If nodes are not connected by any path, they are conditionally independent.
Having a node X with a child Y means you need to learn:
Given X is True, what is the probability of Y being True?
Given X is False, what is the probability of Y being True?
More generally: If X can have n values and Y can have m values, then you have to learn n * (m - 1) values. The - 1 is there because the probabilities need to sum up to 1.
Example
Let's stick with the simple case that both variables are binary and use the following from Wikipedia:
Say X is RAIN and Y is SPRINKLER. You want to express Y (SPRINKLER) in terms of X (RAIN).
The Bayes theorem states:
P(Y|X) = P(X|Y) * P(Y) / P(X)
<=> P(Y) = P(Y | X) * P(X) / P(X | Y)
Now we apply the Law of total probability for X. This means, for X we simply go through all possible values:
P(Y) = P(Y | X = true) * P(X = true) +
P(Y | X = false) * P(X = false)
I guess this is what you refer to. P(X=true | Y) = 1, because the X=true means we already know that X=true happened. It doesn't matter what Y is.
To continue our case, we now look up the values in the tables (X is RAIN, Y is SPRINKLER):
P(Y) = 0.01 * 0.2 + 0.4 * 0.8
= 0.322

How to generate a multiplicative space vector in Matlab?

I am trying to generate "automatically" a vector 0.01, 0.03, 0.1, 0.3, 1, 3, 10, 30 (in multiplicative space).
I know linspace and logspace functions, but I couldn't find any similar function for multiplicative space.
Is there any? Otherwise, how to generate a vector like the one I need?
An easy way with bsxfun, also considering multiplication to smaller spaces:
x = [0.01,0.03,0.05] % initial vector, works for various lengths
n = 12; % times it should get multiplied in rising direction
m = 3; % times it should get multiplied in falling direction
Z = bsxfun( #times, x(:), 10.^(-m:n) )
Z = Z(:)
% if preferred, bulky one-liner:
% Z = reshape( bsxfun( #times, x(:), 10.^(-m:n) ) , 1 , [])
I assumed a multiplication with the multiplication vector, e.g.:
10.^(0:n) = 1 10 100 1000 10000 100000 ....
But custom vectors Y are also possible:
Z = bsxfun( #times, x(:), Y(:)' ) Z = Z(:)
A function that might help you achieving this in a very easy and compact way is the Kronecker tensor product kron.
You can use it to rewrite thewaywewalk's answer as:
v = [0.01;0.03;0.05]; % initial vector
emin = -3; % minimal exponent
emax = 12; % maximal exponent
Z = kron(10.^(emin:emax)',v(:))
which should give you the exact same result.
not very efficient but this will generate what you want. inputvec is your initial vector [0.01 0.03] in this case, multiplier is 10. length of the required string n is 8. n should be a multiple of nn (length of the input vector)
function newvec=multispace(n,inputvec,multiplier)
nn=length(inputvec);
newvec=zeros(1,n);
newvec(1:nn)=inputvec;
for i=1:n/nn-1
newvec(i*nn+1:(i+1)*nn)=(newvec((i-1)*nn+1:(i)*nn)).*multiplier;
end
end

Which library can efficiently deal with corner solutions in R?

At the moment I'm trying to do a minimization (optimization) problem in R, where I have a vector X1 that I want to approximate through a weighted average of a matrix X2 and a vector of weights w. That means I want to minimize
wg <- function(w)
{
t(X1 - X2 %*% w) %*% (X1 - X2 %*% w)
}
the constraints on the weights are w[i]>= 0 and sum(w) = 1 .
At the moment I'm using the DEoptim package to do my optimization, but I feel like it can't deal well with corner solutions.
I'm replicating a method that was used in an economics paper and in that paper almost all of the weights turned out to be zero. I expected a similar result in my case ( I want to model Arizona through a weighted average of the other states), especially due to the heterogeneity in the economic situation.
At the moment I feel like it's more of a problem with the DEoptim package than with my methodology and I don't really trust the results. Which other package can I use, preferrably ones that are stronger in looking for corner solutions?
my DEoptim is set up as follows:
controlDE <- list(reltol=.0000000001,steptol=150, itermax = 5000,trace = 250)
#control parameters
outDEoptim <- DEoptim(fn = wg, lower = rep(0, N), upper = rep(1, N),
control = controlDE)
Any help would be much appreciated!
A stochastic solver such as DEoptim will by nature have difficulties finding optimal solutions on lower dimensional subsets such as the one defined by sum(w) = 1.
There is a first, not quite correct way of doing this by reducing the problem to (n-1) dimensions by setting w <- c(w, 1-sum(w)). The last component might get less than 0, but normally it won't. Now apply DEoptim or optim:
set.seed(1357); m <- 4; n <- 5
X2 <- round(matrix(runif(20), m, n), 2)
X1 <- X2 %*% c(0, 1, 0, 0, 0) # solution c(0,1,0,0,0)
wg <- function(w) { # length(w) == 4
w <- c(w, 1 - sum(w))
t(X1 - X2 %*% w) %*% (X1 - X2 %*% w) # sum((X1 - X2 %*% w)^2)
}
w0 <- rep(1/n, n-1) # initial point (1/n, ..., 1/n)
optim(w0, wg, lower = rep(0, n), upper = rep(1, n),
method = "L-BFGS-B", control = list(factr = 1e-8))
## $par
## [1] 0 1 0 0 # wmin = c(0,1,0,0,0)
Or you apply one of the solvers in R that can handle equality constraints, for example Rdonlp2 (on R-Forge), auglag in package alabama, or slsqp in package nloptr. But I feel this would be overshooting.

How to plot specific points in matlab?

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))

Resources