def func(f1, b, set): """ This function Perform the gate application on the initial state of qubit and then the state tomography, at the same time compute the analytical bloch state. INCOME: f1="string", b="string" fig_data="svg",fig_data2="svg" """ #### Create the bloch-sphere on qutip b1 = Bloch() b2 = Bloch() ## create the analyical quantum state and perform tranformation ## Add states to the bloch sphere and plot it b1.add_states(analytic(f1, b)) if not set: states = qtomography(f1, b) b2.add_vectors(states) else: ### implements for states = qtomography_s(f1, b) for i in states: b2.add_points(i) b2.add_vectors(np.average(states, axis=0)) ### b2.render() fig_data = print_figure(b2.fig, 'svg') b1.render() fig_data2 = print_figure(b1.fig, 'svg') #b1.show() #b2.show() b1.clear() b2.clear() return fig_data, fig_data2
def draw_sphere_zenith(zenith_points, hv_points, root): b = Bloch() b.point_color = ['m', 'k', 'g', 'b', 'w', 'c', 'y', 'r'] b.zlabel = ['$z$', ''] b.point_marker = ['o'] b.point_size = [30] b.frame_width = 1.2 fig = plt.figure(figsize=(20, 20)) b.fig = fig x = (basis(2, 0) + (1 + 0j) * basis(2, 1)).unit() y = (basis(2, 0) + (0 + 1j) * basis(2, 1)).unit() z = (basis(2, 0) + (0 + 0j) * basis(2, 1)).unit() b.add_states([x, y, z]) for i in range(len(zenith_points)): # Transform xyz to zxy coordinates tmp1 = np.array( [zenith_points[i][2], zenith_points[i][0], zenith_points[i][1]]) tmp2 = np.vstack( [hv_points[i][:, 2], hv_points[i][:, 0], hv_points[i][:, 1]]).T tmp = np.vstack([tmp1, -tmp1, tmp2]).T b.add_points(tmp) # tmp1 = np.array([zenith_points[-1][2], zenith_points[-1][0], zenith_points[-1][1]]) # tmp = np.array([tmp1, -tmp1]).T # b.add_points(tmp) name = os.path.join(root, 'zenith_on_sphere.jpg') b.save(name=name)
def draw_consensus_rectified_sphere(hv_points, root): b = Bloch() b.point_color = ['m', 'k', 'g', 'b', 'w', 'c', 'y', 'r'] b.zlabel = ['$z$', ''] b.point_marker = ['o'] b.point_size = [80] b.frame_width = 1.2 fig = plt.figure(figsize=(20, 20)) b.fig = fig x = (basis(2, 0) + (1 + 0j) * basis(2, 1)).unit() y = (basis(2, 0) + (0 + 1j) * basis(2, 1)).unit() z = (basis(2, 0) + (0 + 0j) * basis(2, 1)).unit() b.add_states([x, y, z]) for i in range(len(hv_points)): # Transform xyz to zxy coordinates tmp2 = np.vstack( [hv_points[i][:, 2], hv_points[i][:, 0], hv_points[i][:, 1]]).T tmp = tmp2.T b.add_points(tmp) # b.add_points([ 0.99619469809174555, 0.087155742747658166, 0]) # b.add_points([0.99619469809174555, -0.087155742747658166, 0]) # b.add_points(tmp) name = os.path.join(root, 'consensus_zenith_on_rectified_sphere.jpg') b.save(name=name)
def create_gif(qstates, qstart, qtarget, name): ''' Inputs: # qstates: list of states as np.arrays # qstart, qtarget: respectively the target ans start state # name: name of the output gif ''' b = Bloch() duration = 5 #framerate images = [] for (qstate, i) in zip(qstates, range(0, len(qstates))): b.clear() b.point_color = "r" # options: 'r', 'g', 'b' etc. b.point_marker = ['o'] b.point_size = [40] b.add_states(qutip_qstate(qstart)) b.add_states(qutip_qstate(qtarget)) for previous in range(i): b.add_states(qutip_qstate(qstates[previous]), "point") #plots previous visited states as points b.add_states(qutip_qstate(qstate)) filename = 't.png' b.save(filename) images.append(imageio.imread(filename)) imageio.mimsave(name, images, 'GIF', fps=duration)
def bloch_from_dataframe(df, fig, axes): """ Plot Bloch sphere :param df: pd.DataFrame :param axes: :return: """ bloch = Bloch(fig=fig, axes=axes) bloch.vector_color = plt.get_cmap('viridis')(np.linspace(0, 1, len(df))) bloch.add_states([ Qobj([[row.Jxx, row.beta + 1j * row.gamma], [row.beta - 1j * row.gamma, row.Jyy]]) for _, row in df.iterrows() ]) bloch.make_sphere()
def draw_center_hvps_rectified_sphere(hv_points, root): b = Bloch() b.point_color = ['m', 'k', 'g', 'b', 'w', 'c', 'y', 'r'] b.zlabel = ['$z$', ''] b.point_marker = ['o'] b.point_size = [80] b.frame_width = 1.2 fig = plt.figure(figsize=(20, 20)) b.fig = fig x = (basis(2, 0) + (1 + 0j) * basis(2, 1)).unit() y = (basis(2, 0) + (0 + 1j) * basis(2, 1)).unit() z = (basis(2, 0) + (0 + 0j) * basis(2, 1)).unit() b.add_states([x, y, z]) for i in range(len(hv_points)): # Transform xyz to zxy coordinates tmp1 = np.array([hv_points[i][2], hv_points[i][0], hv_points[i][1]]) tmp2 = np.vstack([tmp1, -tmp1]).T tmp = tmp2 b.add_points(tmp) name = os.path.join(root, 'consensus_hvps_center_on_rectified_sphere.jpg') b.save(name=name)
b.add_vectors([v, [1, -1, 1] / np.sqrt(3)]) b.show() print('-5-') input('Press ENTER to continue.') # %% -6- b.clear() # Anstatt Vektoren einzugeben kann man sich auch # die Basiszustaende verwenden up = basis(2, 0) # entspricht |0> bzw. |H> down = basis(2, 1) # entspricht |1> bzw. |V> # jetzt muss jedoch add_states() verwendet werden # aber auch hier funktioniert wieder add_states(up) # oder das hinzufuegen einer Liste [up, down] b.add_states([up, down]) b.show() print('-6-') input('Press ENTER to continue.') # %% -7- b.clear() # diese Basen koennen auch kombiniert werde # (<Zustand>).unit() uebernimmt hier die Normalisierung # j wird hier als ersatz fuer imaginaer (i) verwendet x = (up + (1 + 0j) * down).unit() y = (basis(2, 0) + (0 + 1j) * basis(2, 1)).unit() z = (basis(2, 0) + (0 + 0j) * basis(2, 1)).unit() b.add_states([x, y]) b.add_states(z)
class CVisualizeAnim(object): """ Class for drawing animation """ def __init__(self, fig): ################################################################# # # Initialize plotting exact plots tools # ################################################################# # p = np.linspace(-20., 20., 1000)[:, np.newaxis] # q = np.linspace(-20., 20., 1000)[np.newaxis, :] # # self.hybrid = CAnalyticQCHybrid(p, q, kT=0.5) # # img_params = dict( # extent=[q.min(), q.max(), p.min(), p.max()], # origin='lower', # cmap='seismic', # # norm=WignerNormalize(vmin=-0.1, vmax=0.1) # norm=WignerSymLogNorm(linthresh=1e-10, vmin=-0.01, vmax=0.1) # ) p = np.linspace(-0.1, 0.1, 500)[:, np.newaxis] q = np.linspace(-0.1, 0.1, 500)[np.newaxis, :] self.hybrid = SolAGKEq(p=p, q=q, omega=1., beta=1e5, alpha=0.95) img_params = dict( extent=[q.min(), q.max(), p.min(), p.max()], origin='lower', cmap='seismic', #norm=WignerNormalize(vmin=-0.1, vmax=0.1) norm=WignerSymLogNorm(linthresh=1e-10, vmin=-0.01, vmax=0.1)) # List to save the total hybrid energy for testing (it must be a conserved quantity) self.total_energy = [] # List to save the x component of the Bloch vector self.sigma_1 = [] ################################################################# # # Initialize plotting facility # ################################################################# self.fig = fig self.fig.suptitle( "Quantum-classical hybrid $m=1$, $\omega=1$, $\\alpha=0.95$, $\\beta={:.1e}$ (a.u.) (a.u.)" .format(self.hybrid.beta)) self.ax = fig.add_subplot(221) self.ax.set_title('Classical density') # generate empty plots self.img_classical_density = self.ax.imshow([[0]], **img_params) self.ax.set_xlabel('$q$ (a.u.)') self.ax.set_ylabel('$p$ (a.u.)') ax = fig.add_subplot(222) ax.set_title('Quantum purity') self.quantum_purity_plot, = ax.plot([0., 1000000], [1, 0.5]) ax.set_xlabel('time (a.u.)') ax.set_ylabel("quantum purity") self.time = [] self.qpurity = [] ax = fig.add_subplot(223) ax.set_title("Coordinate distribution") self.c_coordinate_distribution, = ax.semilogy( [self.hybrid.q.min(), self.hybrid.q.max()], [1e-11, 1e0], label="hybrid") ax.legend() ax.set_xlabel('$q$ (a.u.)') ax.set_ylabel('Probability density') ax = fig.add_subplot(224, projection='3d', azim=0, elev=0) self.bloch = Bloch(axes=ax) self.bloch.make_sphere() def __call__(self, frame_num): """ Draw a new frame :param frame_num: current frame number :return: image objects """ # convert the frame number to time t = 4000. * frame_num # calculate the hybrid density matrix self.hybrid.calculate_D(t) # Save total energy self.total_energy.append(self.hybrid.energy()) # Save <sigma_1> self.sigma_1.append(self.hybrid.average_sigma_1()) # plot the classical density c_rho = self.hybrid.classical_density() self.img_classical_density.set_array(c_rho) self.ax.set_title( 'Classical density \n $t = {:.1f}$ (a.u.)'.format(t)) # plot the coordinate distribution for the classical density coordinate_marginal = c_rho.sum(axis=0) # coordinate_marginal *= self.hybrid.dp coordinate_marginal /= coordinate_marginal.max() self.c_coordinate_distribution.set_data(self.hybrid.q.reshape(-1), coordinate_marginal) # plot quantum purity self.time.append(t) self.qpurity.append(self.hybrid.quantum_purity()) self.quantum_purity_plot.set_data(self.time, self.qpurity) # plot Bloch vector self.bloch.clear() self.bloch.add_states(Qobj(self.hybrid.quantum_density())) self.bloch.make_sphere() # # self.pauli.propagate(100) return self.img_classical_density, self.quantum_purity_plot, self.bloch,
class CVisualizeAnim(object): """ Class for drawing animation """ def __init__(self, fig): ################################################################# # # Initialize plotting exact plots tools # ################################################################# # p = np.linspace(-20., 20., 1000)[:, np.newaxis] # q = np.linspace(-20., 20., 1000)[np.newaxis, :] # # self.hybrid = CAnalyticQCHybrid(p, q, kT=0.5) # # img_params = dict( # extent=[q.min(), q.max(), p.min(), p.max()], # origin='lower', # cmap='seismic', # # norm=WignerNormalize(vmin=-0.1, vmax=0.1) # norm=WignerSymLogNorm(linthresh=1e-10, vmin=-0.01, vmax=0.1) # ) p = np.linspace(-25, 25, 600)[:, np.newaxis] q = np.linspace(-25, 25, 600)[np.newaxis, :] self.hybrid = CAnalyticQCHybrid(p=p, q=q, omega=1., beta=2., alpha=0.95) img_params = dict( extent=[q.min(), q.max(), p.min(), p.max()], origin='lower', cmap='seismic', # norm=WignerNormalize(vmin=-0.1, vmax=0.1) norm=WignerSymLogNorm(linthresh=1e-10, vmin=-0.01, vmax=0.1)) ################################################################# # # Initialize Pauli propagator # ################################################################# self.pauli = SplitOpPauliLike1D( X_amplitude=2. * q.max(), X_gridDIM=512, dt=0.0001, K0="0.5 * P ** 2", V0="0.5 * X ** 2", V1="0.5 * 0.95 * X ** 2", # kT=self.hybrid.kT, # parameters controlling the width of the initial wavepacket ).set_wavefunction("exp(-0.5 * X ** 2)") ################################################################# # # Initialize plotting facility # ################################################################# self.fig = fig self.fig.suptitle( "Quantum-classical hybrid $m=1$, $\omega=1$, $\\alpha=0.95$, $\\beta={:.1e}$ (a.u.) (a.u.)" .format(self.hybrid.beta)) self.ax = fig.add_subplot(221) self.ax.set_title('Classical density') # generate empty plots self.img_classical_density = self.ax.imshow([[0]], **img_params) self.ax.set_xlabel('$q$ (a.u.)') self.ax.set_ylabel('$p$ (a.u.)') ax = fig.add_subplot(222) ax.set_title('Quantum purity') self.quantum_purity_plot, = ax.plot([0., 40], [1, 0.5], label='hybrid') self.pauli_quantum_purity_plot, = ax.plot([0., 40], [1, 0.5], label='Pauli') ax.set_xlabel('time (a.u.)') ax.set_ylabel("quantum purity") ax.legend() self.time = [] self.qpurity = [] self.pauli_qpurity = [] ax = fig.add_subplot(223) ax.set_title("Coordinate distribution") self.c_coordinate_distribution, = ax.semilogy( [self.hybrid.q.min(), self.hybrid.q.max()], [1e-11, 1e0], label="hybrid") self.pauli_coordinate_distribution, = ax.semilogy( [self.hybrid.q.min(), self.hybrid.q.max()], [1e-11, 1e0], label="Pauli") ax.legend() ax.set_xlabel('$q$ (a.u.)') ax.set_ylabel('Probability density') ax = fig.add_subplot(224, projection='3d', azim=90, elev=0) self.bloch = Bloch(axes=ax) self.bloch.make_sphere() def __call__(self, frame_num): """ Draw a new frame :param frame_num: current frame number :return: image objects """ # convert the frame number to time #t = 0.05 * frame_num t = self.pauli.t # calculate the hybrid density matrix self.hybrid.calculate_D(t) # plot the classical density c_rho = self.hybrid.classical_density() self.img_classical_density.set_array(c_rho) self.ax.set_title( 'Classical density \n $t = {:.1f}$ (a.u.)'.format(t)) # plot the coordinate distribution for the classical density coordinate_marginal = c_rho.sum(axis=0) # coordinate_marginal *= self.hybrid.dp coordinate_marginal /= coordinate_marginal.max() self.c_coordinate_distribution.set_data(self.hybrid.q.reshape(-1), coordinate_marginal) coordinate_density = self.pauli.coordinate_density coordinate_density /= coordinate_density.max() self.pauli_coordinate_distribution.set_data( self.pauli.X, coordinate_density) # plot quantum purity self.time.append(t) self.qpurity.append(self.hybrid.quantum_purity()) self.quantum_purity_plot.set_data(self.time, self.qpurity) # Get the Pauli density matrix rho12 = np.sum(self.pauli.psi1 * self.pauli.psi2.conjugate()) rho_pauli = np.array( [[np.sum(np.abs(self.pauli.psi1)**2), rho12], [rho12.conjugate(), np.sum(np.abs(self.pauli.psi2)**2)]]) rho_pauli *= self.pauli.dX # plot Pauli purity self.pauli_qpurity.append(rho_pauli.dot(rho_pauli).trace().real) self.pauli_quantum_purity_plot.set_data(self.time, self.pauli_qpurity) # plot Bloch vector self.bloch.clear() self.bloch.add_states( [Qobj(self.hybrid.quantum_density()), Qobj(rho_pauli)]) self.bloch.make_sphere() # self.pauli.propagate(1000) return self.img_classical_density, self.quantum_purity_plot, self.pauli_quantum_purity_plot,\ self.bloch, self.pauli_coordinate_distribution
for epoch in range(epochs): iters = 0 diff = 1 tol = 1e-7 while jnp.all(diff > tol) and iters < max_iters: prev_weights = weights der = jnp.asarray(der_cost(*prev_weights.T, init_ket)) weights = weights + alpha * der state_hist.append(Qobj(onp.dot(rot(*weights), init_ket))) iters += 1 diff = jnp.absolute(weights - prev_weights) fidel = cost(*weights.T, init_ket) progress = [epoch + 1, fidel] if (epoch) % 1 == 0: print("Epoch: {:2f} | Fidelity: {:3f}".format(*jnp.asarray(progress))) # ## Bloch Sphere Visualization # # As we see above, we started off with a very low fidelity (~0.26). With gradient descent iterations, we progressively achieve better fidelities via better parameters, $\phi$, $\theta$, and $\omega$. To see it visually, we render our states on to a Bloch sphere. # # We see how our optimizer (Gradient Descent in this case) finds a (nearly) optimal path to walk from $|1 \rangle$ (green arrow pointing exactly south) to very close to the target state $|0 \rangle$ (brown arrow pointing exactly north), as desired. b = Bloch() b.add_states(Qobj(init_ket)) b.add_states(basis(2, 0)) for state in range(0, len(state_hist), 6): b.add_states(state_hist[state]) b.show()