Skip to content
Snippets Groups Projects
Commit 946d41d9 authored by nguyed99's avatar nguyed99 Committed by jakut77
Browse files

Add bht+jpl, etc

parent edd0b380
Branches
No related tags found
No related merge requests found
Showing with 374 additions and 123 deletions
/__pycache__ /__pycache__
*.pyc *.pyc
*.DS_Store /playground
\ No newline at end of file \ No newline at end of file
...@@ -39,11 +39,11 @@ Jobs and tasks are run inside of docker containers. There is a docker build scri ...@@ -39,11 +39,11 @@ Jobs and tasks are run inside of docker containers. There is a docker build scri
The image is built now and ready to be used! The tests in the Docker container built from the image can be sanity-checked via : The image is built now and ready to be used! The tests in the Docker container built from the image can be sanity-checked via :
docker run -it --rm git.imp.fu-berlin.de:5000/comp-sci-project/jobs-n-tasks:local python jobs/tests/test_a_job.py docker run -it --rm git.imp.fu-berlin.de:5000/comp-sci-project/jobs-n-tasks:local pytest jobs/tests/test_a_job.py
or for testing a task: or for testing a task:
docker run -it --rm git.imp.fu-berlin.de:5000/comp-sci-project/jobs-n-tasks:local python tasks/tests/test_a_task.py docker run -it --rm git.imp.fu-berlin.de:5000/comp-sci-project/jobs-n-tasks:local pytest tasks/tests/test_a_task.py
For live experience (meaning you enter the container), run: For live experience (meaning you enter the container), run:
......
...@@ -6,10 +6,13 @@ authors = [] ...@@ -6,10 +6,13 @@ authors = []
readme = "README.md" readme = "README.md"
[tool.poetry.dependencies] [tool.poetry.dependencies]
python = ">=3.10" python = "3.11.5"
numpy = "~1.24" numpy = "1.24.4"
matplotlib = "3.8.0" matplotlib = "3.8.0"
astropy = "6.0.0"
sunpy = "5.1.1"
pytest = "^7.4.4" pytest = "^7.4.4"
astroquery = "^0.4.6"
[build-system] [build-system]
requires = ["poetry-core"] requires = ["poetry-core"]
......
""" """
This module contains functions to query and parse JPL Horizons This module contains functions to query and parse JPL Horizons
on-line solar system data (see https://ssd-api.jpl.nasa.gov/doc/horizons.html). on-line solar system data (see https://ssd-api.jpl.nasa.gov/doc/horizons.html).
To use, run the following command
INPUT_PATH = "jobs/inputs/"
r_E, v_E = parse_output(query_data(INPUT_PATH + "earth_ephemeris.txt"))
r_M, v_M = parse_output(query_data(INPUT_PATH + "moon_ephemeris.txt"))
""" """
import re import re
......
"""
This module contains functions to add Gaussian (white) noises
as random small perturbations in the initial configuration.
"""
\ No newline at end of file
import numpy as np
import matplotlib.pyplot as plt
def plot_trajectory(traj: np.ndarray, mass: list, update_interval=10):
"""
Args:
- traj: trajectory with shape (no_time_steps, no_bodies * dim)
- mass: masses of bodies
"""
n_time_step, n_bodies = traj.shape #
n_bodies //= 3
fig = plt.figure()
ax = fig.add_subplot(projection='3d')
for i in range(0, n_time_step, update_interval):
ax.clear()
for j in range(n_bodies):
start_idx = j * 3
end_idx = (j + 1) * 3
body_traj = traj[i, start_idx:end_idx]
ax.scatter(body_traj[0], body_traj[1], body_traj[2], s=10 * mass[j] / min(mass))
ax.set_xlabel("X")
ax.set_ylabel("Y")
ax.set_zlabel("Z")
ax.set_title(f"Time step: {i}")
ax.set_xticks([])
ax.set_yticks([])
ax.set_zticks([])
plt.pause(0.01)
...@@ -86,6 +86,17 @@ class IntegratorTest(unittest.TestCase): ...@@ -86,6 +86,17 @@ class IntegratorTest(unittest.TestCase):
t, p, q = system.simulation() t, p, q = system.simulation()
## plotting trajectories
plt.figure()
plt.plot(q[:, 0], q[:, 1], label="Earth")
plt.legend()
plt.show()
plt.figure()
plt.plot(q[:, 2] - q[:, 0], q[:, 3] - q[:, 1], label="Moon seen from Earth")
plt.legend()
plt.show()
## checking total energy conservation ## checking total energy conservation
H = np.linalg.norm(p[:,:2], axis=1)**2 / (2 * M_E) + np.linalg.norm(p[:,2:], axis=1)**2 / (2 * M_L) + \ H = np.linalg.norm(p[:,:2], axis=1)**2 / (2 * M_E) + np.linalg.norm(p[:,2:], axis=1)**2 / (2 * M_L) + \
-G * M_S * M_E / np.linalg.norm(q[:,:2], axis=1) - G * M_S * M_L / np.linalg.norm(q[:,2:], axis=1) + \ -G * M_S * M_E / np.linalg.norm(q[:,:2], axis=1) - G * M_S * M_L / np.linalg.norm(q[:,2:], axis=1) + \
......
...@@ -75,6 +75,17 @@ class IntegratorTest(unittest.TestCase): ...@@ -75,6 +75,17 @@ class IntegratorTest(unittest.TestCase):
t, p, q = system.simulation() t, p, q = system.simulation()
## plotting trajectories
plt.figure()
plt.plot(q[:, 0], q[:, 1], label="Earth")
plt.legend()
plt.show()
plt.figure()
plt.plot(q[:, 2] - q[:, 0], q[:, 3] - q[:, 1], label="Moon seen from Earth")
plt.legend()
plt.show()
## checking total energy conservation ## checking total energy conservation
H = np.linalg.norm(p[:,:2], axis=1)**2 / (2 * M_E) + np.linalg.norm(p[:,2:], axis=1)**2 / (2 * M_L) + \ H = np.linalg.norm(p[:,:2], axis=1)**2 / (2 * M_E) + np.linalg.norm(p[:,2:], axis=1)**2 / (2 * M_L) + \
-G * M_S * M_E / np.linalg.norm(q[:,:2], axis=1) - G * M_S * M_L / np.linalg.norm(q[:,2:], axis=1) + \ -G * M_S * M_E / np.linalg.norm(q[:,:2], axis=1) - G * M_S * M_L / np.linalg.norm(q[:,2:], axis=1) + \
......
"""
This unittest tests data query from JPL Horizons database
for the restricted three-body (sun-earth-moon) problem.
The sun is fixed at the origin (center of mass). For
simplicity, the moon is assumed to be in the eliptic plane,
so that vectors can be treated as two-dimensional.
The trajectories are plotted in Heliographic Stonyhurst coordinates.
"""
import unittest
import matplotlib.pyplot as plt
import astropy.units as u
from sunpy.coordinates import (get_body_heliographic_stonyhurst, get_horizons_coord)
from sunpy.time import parse_time
time = parse_time('2024-01-01 00:00')
class IntegratorTest(unittest.TestCase):
def test_data_query(self):
moon = get_horizons_coord('301', {'start': time - 30 * u.day, 'stop': time + 30 * u.day, 'step': '1d'})
earth = get_horizons_coord('399', {'start': time - 30 * u.day, 'stop': time + 30 * u.day, 'step': '1d'})
sun = get_body_heliographic_stonyhurst('Sun', time) # (lon, lat, radius) in (deg, deg, AU)
def coord_to_polar(coord):
return coord.lon.to_value('rad'), coord.radius.to_value('AU')
fig = plt.figure()
ax = fig.add_subplot(projection='polar')
ax.plot(0, 0, 'o', label='Sun', color='orange', markersize=10)
ax.plot(*coord_to_polar(earth.transform_to(sun)), label='Earth', color='blue', linestyle='-.')
ax.plot(*coord_to_polar(moon.transform_to(sun)), label='Moon', color='purple', linestyle='dashed')
ax.set_title('Stonyhurst heliographic coordinates')
ax.legend(loc='upper left', bbox_to_anchor=(1.0, 0.5))
plt.show()
...@@ -6,7 +6,7 @@ authors = [] ...@@ -6,7 +6,7 @@ authors = []
readme = "README.md" readme = "README.md"
[tool.poetry.dependencies] [tool.poetry.dependencies]
python = "~3.11" python = "3.11.5"
toml = "^0.10.2" toml = "^0.10.2"
[tool.poetry.group.dev.dependencies] [tool.poetry.group.dev.dependencies]
......
"""
This module implements the SWAP gate using the Pauli gates
"""
import numpy as np
from jobs.src.a_job import sigma_x, sigma_y, sigma_z
def swap_gate() -> np.ndarray:
swap_matrix = 1 / 2 * (np.kron(np.identity(2), np.identity(2)) + np.kron(sigma_x(), sigma_x()) +
np.kron(sigma_y(), sigma_y()) + np.kron(sigma_z(), sigma_z()))
return swap_matrix
""" """
This module contains functions for a direct simulation This module contains functions for a direct simulation
of gravitational n-body system using realistic data for various of gravitational 2-body system using realistic data for various
initial configurations initial configurations
""" """
import logging import astropy.units as u
import matplotlib.pyplot as plt
import numpy as np import numpy as np
from sunpy.coordinates import (get_body_heliographic_stonyhurst, get_horizons_coord)
from sunpy.time import parse_time
from jobs.src.integrators import verlet from jobs.src.integrators import verlet
from jobs.src.jpl_data_query import (parse_output, query_data)
from jobs.src.system import GravitationalSystem from jobs.src.system import GravitationalSystem
from jobs.src.visualization import plot_trajectory from tasks.src.utils import (coord_to_polar, xyz_to_polar)
logger = logging.getLogger(__name__)
logging.basicConfig(level=logging.INFO)
INPUT_PATH = "jobs/inputs/"
r_E, v_E = parse_output(query_data(INPUT_PATH + "earth_ephemeris.txt"))
r_M, v_M = parse_output(query_data(INPUT_PATH + "moon_ephemeris.txt"))
# system settings # system settings
M_S = 1 # solar mass M_S = 1 # solar mass
M_E = 3.00e-6 * M_S M_E = 3.00e-6 * M_S
M_L = 3.69e-8 * M_S M_L = 3.69e-8 * M_S
G = 4 * np.pi**2 # AU^3 / m / yr^2 G = 4 * np.pi**2 # AU^3 / m / yr^2
# JPL data
time = parse_time('2024-01-01 00:00')
moon = get_horizons_coord('301', {
'start': time - 40 * u.day,
'stop': time + 40 * u.day,
'step': '1d'
},
include_velocity=True)
earth = get_horizons_coord('399', {
'start': time - 40 * u.day,
'stop': time + 40 * u.day,
'step': '1d'
},
include_velocity=True)
sun = get_body_heliographic_stonyhurst('Sun', time) # (lon, lat, radius) in (deg, deg, AU)
moon = moon.transform_to(sun)
earth = earth.transform_to(sun)
# simulation settings # simulation settings
T = 0.3 # yr T = 0.23 # yr
n_order = 6 n_order = 6
dt = 4**(-n_order) # yr dt = 4**(-n_order) # yr
...@@ -45,8 +58,18 @@ def force(q: np.ndarray) -> np.ndarray: ...@@ -45,8 +58,18 @@ def force(q: np.ndarray) -> np.ndarray:
]).flatten() ]).flatten()
system = GravitationalSystem(r0=np.hstack((r_E[0], r_M[0])), # run direct simulation
v0=np.hstack((v_E[0], v_M[0])), moon_0_pos = moon[0].represent_as('cartesian')
earth_0_pos = earth[0].represent_as('cartesian')
x0 = np.array([
earth_0_pos.x.value, earth_0_pos.y.value, earth_0_pos.z.value, moon_0_pos.x.value, moon_0_pos.y.value,
moon_0_pos.z.value, earth[0].velocity.d_x.value, earth[0].velocity.d_y.value, earth[0].velocity.d_z.value,
moon[0].velocity.d_x.value, moon[0].velocity.d_y.value, moon[0].velocity.d_z.value
])
system = GravitationalSystem(r0=x0[:6],
v0=x0[6:],
m=np.array([M_E, M_E, M_E, M_L, M_L, M_L]), m=np.array([M_E, M_E, M_E, M_L, M_L, M_L]),
t=np.linspace(0, T, int(T // dt)), t=np.linspace(0, T, int(T // dt)),
force=force, force=force,
...@@ -54,4 +77,39 @@ system = GravitationalSystem(r0=np.hstack((r_E[0], r_M[0])), ...@@ -54,4 +77,39 @@ system = GravitationalSystem(r0=np.hstack((r_E[0], r_M[0])),
t, p, q = system.simulation() t, p, q = system.simulation()
plot_trajectory(q, mass=[M_E, M_L]) # plot trajectory in polar coordinates
q_E_polar = np.array([xyz_to_polar(pos[0], pos[1], pos[2]) for pos in q])
q_M_polar = np.array([xyz_to_polar(pos[3], pos[4], pos[5]) for pos in q])
fig = plt.figure()
ax = fig.add_subplot(projection='polar')
ax.plot(0, 0, 'o', label='Sun', color='orange', markersize=10)
ax.plot(q_E_polar[:, 0], q_E_polar[:, 1], label='Earth', color='blue', linestyle='-.')
ax.plot(q_M_polar[:, 0], q_M_polar[:, 1], label='Moon', color='purple', linestyle='dashed')
ax.plot(*coord_to_polar(earth.transform_to(sun)), label='Earth(JPL)', color='green', linestyle='-.')
ax.plot(*coord_to_polar(moon.transform_to(sun)), label='Moon(JPL)', color='red', linestyle='dashed')
ax.set_title('Stonyhurst heliographic coordinates')
ax.legend(loc='upper left', bbox_to_anchor=(1.0, 0.5))
plt.show()
# plot trajectory in Cartesian coordinates
moon_xyz = moon.represent_as('cartesian')
earth_xyz = earth.represent_as('cartesian')
moon_JPL = np.array([(i.x.value, i.y.value, i.z.value) for i in moon_xyz])
earth_JPL = np.array([(i.x.value, i.y.value, i.z.value) for i in earth_xyz])
fig = plt.figure()
ax = fig.add_subplot(projection='3d')
ax.plot(0, 0, 0, 'o', label='Sun', color='orange', markersize=10)
ax.plot(q[:, 0], q[:, 1], q[:, 2], label="Earth")
ax.plot(q[:, 3], q[:, 4], q[:, 5], label="Moon")
ax.plot(earth_JPL[:, 0], earth_JPL[:, 1], earth_JPL[:, 2], '--', label='Earth(JPL)')
ax.plot(moon_JPL[:, 0], moon_JPL[:, 1], moon_JPL[:, 2], '-.', label='Moon(JPL)')
ax.set_xlabel("X")
ax.set_ylabel("Y")
ax.set_zlabel("Z")
ax.set_xticks([])
ax.set_yticks([])
ax.set_zticks([])
ax.legend()
plt.show()
""" """
This module contains functions for a simulation with force field This module contains functions for a simulation with force field
of gravitational n-body system using realistic data for various of gravitational n-body system
initial configurations """
"""
\ No newline at end of file import matplotlib.pyplot as plt
import numpy as np
from jobs.src.bht_algorithm_3D import MainApp, Particle
# Simulation class for galaxy collision using Barnes-Hut and Euler method
class GalaxyCollisionSimulation:
def __init__(self, num_particles):
# Initialize the simulation with a given number of particles
self.num_particles = num_particles
self.particles = self.initialize_particles(initial='random') # Generate particles
self.barnes_hut = MainApp(self.particles) # Initialize Barnes-Hut algorithm instance
self.barnes_hut.BuildTree(self.particles) # Build the Barnes-Hut tree with particles
self.barnes_hut.rootNode.ComputeMassDistribution() #Compute the center of mass of the tree nodes
self.particle_positions = {
i: [(particle.x, particle.y, particle.z)]
for i, particle in enumerate(self.particles)
} # Store particle positions for each time step
self.particle_velocities = {
i: [(particle.vx, particle.vy, particle.vz)]
for i, particle in enumerate(self.particles)
} # Store particle velocities for each time step
self.particle_forces = {
i: [(particle.fx, particle.fy, particle.fz)]
for i, particle in enumerate(self.particles)
} # Store particle velocities for each time step
self.system_center_of_mass = {
0: (self.barnes_hut.rootNode.center_of_mass[0], self.barnes_hut.rootNode.center_of_mass[1],
self.barnes_hut.rootNode.center_of_mass[2])
}
def initialize_particles(self, initial='random'):
if initial == 'two':
particles = [Particle(60, 50, 40, 1000), Particle(40, 50, 60, 1000)]
particles[0].vx, particles[0].vy, particles[0].vz = 5, 3, 3
particles[1].vx, particles[1].vy, particles[1].vz = 5, -3, 3
#particles=particles[:2]
return particles
elif initial == 'random':
# Generate random particles within a specified range
particles = []
for _ in range(self.num_particles):
x = np.random.uniform(50, 150)
y = np.random.uniform(50, 150)
z = np.random.uniform(50, 150)
vx = np.random.uniform(-5, 5)
vy = np.random.uniform(-5, 5)
vz = np.random.uniform(-5, 5)
#mass = np.random.uniform(10, 100)
mass = 1000
particle = Particle(x, y, z, mass)
particle.vx = vx
particle.vy = vy
particle.vz = vz
particles.append(particle)
return particles
elif initial == 'four':
particles = [
Particle(60, 50, 40, 1000),
Particle(40, 50, 60, 1000),
Particle(50, 60, 70, 1000),
Particle(50, 40, 30, 1000)
]
particles[0].vx, particles[0].vy, particles[0].vz = 0, 3, 3
particles[1].vx, particles[1].vy, particles[1].vz = 0, -3, 3
particles[2].vx, particles[2].vy, particles[2].vz = -3, 0, -3
particles[3].vx, particles[3].vy, particles[3].vz = 3, 0, -3
#particles=particles[:2]
return particles
def simulate(self, num_steps, time_step):
# Simulate the galaxy collision for a certain number of steps
for step in range(num_steps):
# For each step, build the tree
self.barnes_hut.BuildTree(self.particles)
self.barnes_hut.rootNode.ComputeMassDistribution()
if step in np.arange(0, num_steps, 1000):
print(f'===Quadtree at step {step}===')
self.barnes_hut.rootNode.print_tree()
self.evaluate_forces() # Evaluate forces acting on each particle
self.integrate(time_step, 'velocity_verlet') # Integrate to update particle positions
self.system_center_of_mass[step] = (self.barnes_hut.rootNode.center_of_mass[0],
self.barnes_hut.rootNode.center_of_mass[1],
self.barnes_hut.rootNode.center_of_mass[2])
# Store particle positions, velocities and forces for each time step
for i, particle in enumerate(self.particles):
self.particle_positions[i].append((particle.x, particle.y, particle.z))
self.particle_velocities[i].append((particle.vx, particle.vy, particle.vz))
self.particle_forces[i].append((particle.fx, particle.fy, particle.fz))
def evaluate_forces(self):
# Evaluate forces acting on each particle using Barnes-Hut algorithm
for particle in self.particles:
force = self.barnes_hut.rootNode.CalculateForceFromTree(particle)
particle.fx, particle.fy, particle.fz = force
def calculate_force(self, particle):
# Calculate force acting on a single particle
force = self.barnes_hut.rootNode.CalculateForceFromTree(particle)
particle.fx, particle.fy, particle.fz = force
def integrate(self, time_step, method):
# Integrate to update particle positions based on calculated forces
if method == 'explicit_euler':
for particle in self.particles:
particle.vx += particle.fx * time_step / particle.mass # Update velocity components
particle.vy += particle.fy * time_step / particle.mass
particle.vz += particle.fz * time_step / particle.mass
particle.x += particle.vx * time_step # Update particle positions using velocity
particle.y += particle.vy * time_step
particle.z += particle.vz * time_step
elif method == 'velocity_verlet':
for particle in self.particles:
particle.vx += particle.fx * time_step / (2 * particle.mass) # First half-step
particle.vy += particle.fy * time_step / (2 * particle.mass)
particle.vz += particle.fz * time_step / (2 * particle.mass)
particle.x += particle.vx * time_step # Full step for position
particle.y += particle.vy * time_step
particle.z += particle.vz * time_step
self.calculate_force(particle) # Recalculate force for the particle
particle.vx += particle.fx * time_step / (2 * particle.mass) # Second half-step
particle.vy += particle.fy * time_step / (2 * particle.mass)
particle.vz += particle.fz * time_step / (2 * particle.mass)
def print_particle_positions(self):
# Print the positions of all particles for each time step
for i, positions in self.particle_positions.items():
print(f"Particle {i + 1} Positions:")
for step, pos in enumerate(positions):
print(f" Time Step {step}: Position ({pos[0]}, {pos[1]}, {pos[2]})")
def display_snapshots(self, num_shots, fix_axes=True):
# Display pictures for each time step
num_time_steps = len(next(iter(self.particle_positions.values())))
print('===Quadtree at the end===')
self.barnes_hut.rootNode.print_tree() # print the tree
axes_type = "fixed" if fix_axes else "unfixed"
#Fixed axis limits
print(f"For {axes_type} axis limits, num_particles={self.num_particles}")
for step in np.arange(0, num_time_steps, int(num_time_steps / num_shots)):
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
if fix_axes:
ax.set_xlim(0, 200)
ax.set_ylim(0, 200)
ax.set_zlim(0, 200)
ax.set_xlabel('X-axis')
ax.set_ylabel('Y-axis')
ax.set_zlabel('Z-axis')
ax.set_title(f'Time Step {step}')
ax.grid()
#print(f'Step {step}')
for particle_index, positions in self.particle_positions.items():
x, y, z = positions[step]
vx, vy, vz = self.particle_velocities[particle_index][step]
fx, fy, fz = self.particle_forces[particle_index][step]
#mass = self.particles[particle_index].mass
ax.scatter(x, y, z, c='blue', s=20, alpha=0.5) # Plot particle position for the current time step
c_x, c_y, c_z = self.system_center_of_mass[step]
ax.scatter(c_x, c_y, c_z, c='orange', s=20)
#print(
#f'i={particle_index}: x={round(x,2)}, y={round(y,2)}, z={round(z,2)}, vx={round(vx,2)}, vy={round(vy,2)}, vz={round(vz,2)}, fx={round(fx,2)}, fy={round(fy,2)}, fz={round(fz,2)}'
#)
#print(y)
plt.show()
if __name__ == "__main__":
sim = GalaxyCollisionSimulation(num_particles=10)
sim.simulate(num_steps=10000, time_step=0.001)
sim.display_snapshots(200, fix_axes=True)
import numpy as np
from astropy.coordinates import CartesianRepresentation, SphericalRepresentation
def rotation_matrix(phi, theta) -> np.ndarray:
"""
Rotate a vector represented in spherical coordinates.
Args:
phi (float): Azimuthal angle in radians.
theta (float): Polar angle in radians.
"""
# Construct the rotation matrix directly in spherical coordinates
rot_phi = np.array([[np.cos(phi), -np.sin(phi), 0], [np.sin(phi), np.cos(phi), 0], [0, 0,
1]]) # Rotation around z-axis
rot_theta = np.array([[np.sin(theta), 0, np.cos(theta)], [0, 1, 0], [-np.cos(theta), 0,
np.sin(theta)]]) # Rotation around y-axis
# Combine the rotation matrices
rotation_matrix = np.dot(rot_phi, rot_theta)
return rotation_matrix
def coord_to_polar(coord):
return coord.lon.to_value('rad'), coord.radius.to_value('AU')
def xyz_to_polar(x, y, z):
cart = CartesianRepresentation(x, y, z)
sph = cart.represent_as(SphericalRepresentation)
return sph.lon.value, sph.distance.value
import logging
import unittest
import numpy as np
from tasks.src.a_task import swap_gate
logger = logging.getLogger(__name__)
logging.basicConfig(level=logging.INFO)
class ATaskTest(unittest.TestCase):
def test_a_task(self):
"""
Test functionalities of swap gate on 2-qubits
"""
qubit_0 = np.array([1, 0])
qubit_1 = np.array([0, 1])
qubit_00 = np.kron(qubit_0, qubit_0)
qubit_11 = np.kron(qubit_1, qubit_1)
qubit_01 = np.kron(qubit_0, qubit_1)
qubit_10 = np.kron(qubit_1, qubit_0)
# ensure input is a 2-qubit
self.assertTrue(qubit_00.shape[0] == 4)
self.assertTrue(qubit_01.shape[0] == 4)
self.assertTrue(qubit_10.shape[0] == 4)
self.assertTrue(qubit_11.shape[0] == 4)
self.assertTrue(np.array_equal(np.dot(swap_gate(), qubit_00), qubit_00))
self.assertTrue(np.array_equal(np.dot(swap_gate(), qubit_11), qubit_11))
self.assertTrue(np.array_equal(np.dot(swap_gate(), qubit_01), qubit_10))
self.assertTrue(np.array_equal(np.dot(swap_gate(), qubit_10), qubit_01))
logger.info("Logging for fun!")
if __name__ == '__main__':
unittest.main()
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment