def test_single_symplectic(i, n): """ Tests a single symplectic matrix """ M = symplectic.symplectic(i, n) L = symplectic.get_lambda(n) result = (M.T @ L @ M) % 2 result = ((result == L).all()) return result
def store_all_two_qubit_gates(): m = 2 qubit_gates = dict() qubit_matrices = dict() for i in range(symplectic.numberofsymplectic(m)): S = symplectic.symplectic(i, m) S = decompose.transform_symplectic(S) gates = decompose.decompose_state(chp_py.CHP_Simulation(m, S)) qubit_gates[i] = gates qubit_matrices[i] = S save_data(qubit_gates, "two_qubit_gates") save_data(qubit_matrices, "two_qubit_matrices")
def test_collision_probability(): """ Test cases for the collision probability algorithm Returns True if passed all test cases, otherwise returns False """ print("Testing: collision probability algorithm") # n = number of qubits, m = size of qubit gate for n in range(1, 10): # sim1 is fast and sim2 is slow, as sim2 uses exponential # storage and runtime sim1 = chp_py.CHP_Simulation(n) sim2 = slow_sim.Slow_Simulation(n) for m in range(1, min(n, 5)): for j in range(100): # Get a random symplectic of size 2m x 2m i = np.random.randint(symplectic.numberofsymplectic(m)) S = symplectic.symplectic(i, m) S = decompose.transform_symplectic(S) # Get m random qubits qubits = np.arange(m) np.random.shuffle(qubits) qubits = qubits[:m] # Get the gates and matrix represention of S gates = decompose.decompose_state(chp_py.CHP_Simulation(m, S)) gates = decompose.change_gates(gates, qubits) decompose.apply_gates(gates, sim1) decompose.apply_gates(gates, sim2) k_1 = int(-sim1.log_collision_probability) k_2 = np.round(-np.log2(sim2.collision_probability)) result = (k_1 == k_2) if not result: print("Failed: collision probability algorithm returned " + "incorrect result with n = " + str(n) + " and m = " + str(m)) return False print("Passed: collision probability algorithm passed all tests\n") return True
def test_chp_py(): """ Test cases for the functions in chp_py.py Returns True if passed all test cases, otherwise returns False """ print("Testing: chp_py.py") # n = number of qubits, m = size of qubit gate for n in range(1, 50): # Create two simulations # sim1 uses decomposed gates and sim2 uses matrix multiplication # apply 100 random gates to each one sim1 = chp_py.CHP_Simulation(n) sim2 = chp_py.CHP_Simulation(n) for m in range(1, min(n, 5)): for j in range(100): # Get a random symplectic of size 2m x 2m i = np.random.randint(symplectic.numberofsymplectic(m)) S = symplectic.symplectic(i, m) S = decompose.transform_symplectic(S) # Get m random qubits qubits = np.arange(m) np.random.shuffle(qubits) qubits = qubits[:m] # Get the gates and matrix represention of S gates = decompose.decompose_state(chp_py.CHP_Simulation(m, S)) gates = decompose.change_gates(gates, qubits) M = decompose.symplectic_to_matrix(S, n, qubits) sim1.apply_gates(gates) sim2.state = (sim2.state @ M) % 2 result = (sim1.state == sim2.state).all() if not result: print("Failed: found two simulations with different " + "states for n = " + str(n)) return False print("Passed: chp_py.py passed all tests\n") return True
def apply_random_symplectic(self, qubits): """ Generates a random symplectic gate and then applies it to the qubits in the list qubits """ # Here m is the number of qubits that the gate will be applied to # while n is the total number of qubits in the simulation m = len(qubits) # Generate a random symplectic matrix that is # symplectic with L = direct_sum_{j=1}^n X i = np.random.randint(symplectic.numberofsymplectic(m)) S = symplectic.symplectic(i, m) # Convert this symplectic matrix to one that is symplectic # with L = [[0, I], [I, 0]] S = decompose.transform_symplectic(S) # Lastly, apply this to our state self.apply_symplectic(S, qubits)
def test_decompose(): """ Test cases for the functions in decompose.py Returns True if passed all test cases, otherwise returns False """ print("Testing: decompose.py") for n in range(1, 6): top = np.hstack((np.zeros((n, n)), np.identity(n))) bottom = np.hstack((np.identity(n), np.zeros((n, n)))) L = np.vstack((top, bottom)) for j in range(500): # Get a random symplectic i = np.random.randint(symplectic.numberofsymplectic(n)) S = symplectic.symplectic(i, n) S = decompose.transform_symplectic(S) # Make sure the transformation worked result = (S.T @ L @ S) % 2 result = ((result == L).all()) if not result: print("Failed: could not transform symplectic " + "matrix with (n, i)= " + str((n, i))) return False # Make sure we can decompose it # Applying the decomposed gates to the identity should give us S gates = decompose.decompose_state(chp_py.CHP_Simulation(n, S)) new_sim = chp_py.CHP_Simulation(n) new_sim.apply_gates(gates) result = (new_sim.state == S).all() if not result: print("Failed: found a bad decomposition for " + "symplectic matrix with (n, i)= " + str((n, i))) return False print("Passed: decompose.py passed all tests\n") return True
def trajectory(n,duration,pos,ang,burn,x0,y0,px0,py0): """Integrate trajectory for the reduced 3-body problem. Args: n (int): Positions stored. duration (float): Time duration of simulation. x0 (float): Initial x-coordinate y0 (float): Initial y-coordinate px0 (float): Initial generalized x-momentum py0 (float): Initial generalized y-momentum Returns: Tuple of time-, x-, y-, px- and py lists. """ print("# Running trajectory.") # Initialize arrays tlist = np.linspace(0,duration,n) xlist = np.zeros(n) ylist = np.zeros(n) pxlist = np.zeros(n) pylist = np.zeros(n) errlist = np.zeros(n) hlist = np.zeros(n) info = np.zeros(2) # Find orbits runtime = time.time() status = symplectic(n,duration,x0,y0,px0,py0,xlist,ylist,pxlist,pylist,errlist,hlist,info) runtime = time.time()-runtime # Display result print_search_results(status,pos,ang,burn,x0,y0,px0,py0,info[0],info[1]) print("# Runtime = %3.2fs" % (runtime)) return tlist,xlist,ylist,pxlist,pylist,errlist,hlist
from symplectic import symplectic import matplotlib.pyplot as plt from poincare import hh_sos import numpy as np H = lambda q, p: .5 * (np.dot(q, q) + np.dot(p, p)) + (q[0]**2) * q[1] - ( 1 / 3) * q[1]**3 dHdp = lambda p: p dHdq = lambda q: q + np.array([2 * q[0] * q[1], q[0]**2 - q[1]**2]) fig2 = symplectic(dHdq, [0.12, 0.12], [0.12, 0.12]) # fig3 = symplectic(dHdq, [0.0, 0.0], [np.sqrt(2*0.1592), 0.0], tf=10000) fig3c = symplectic(dHdq, [0.0, 0.0], [np.sqrt(2 * 0.1592), 0.0]) fig4 = symplectic(dHdq, [0.0, 0.0], [np.sqrt(2 * 0.11783), 0.0]) fig4b = symplectic(dHdq, [0.0, 0.0], [np.sqrt(2 * 0.117835), 0.0]) qp = np.array([next(fig2) for _ in range(1000000)]) # np.save("fig2_oneside.npy", qp) q, p = hh_sos(qp[:, 0], qp[:, 1]) plt.scatter(q, p, marker=".") plt.title("Fig 3c") plt.show()
def hohmann(threads,n): """Finding Hohmann trajectory for the reduced 3-body problem. Args: n (int): Positions stored. Returns: Tuple of time-, x-, y-, px- and py lists. """ print("# Running Hohmann.") # Hohmann trajectory < 6 days duration = 6/unit_time best_total_dv = 1e9 positions = 100 angles = 1 burns = 200 pos = -3*pi/4 ang = 0 burn = 3.11/unit_vel # Forward Hohmann #burn_low = -3.14/unit_vel # Reverse Hohmann # Super fast Hohmann trajectory < 1 days #duration = 3/unit_time #best_total_dv = 1e9 #positions = 10 #angles = 10 #burns = 200 #pos = -3*pi/4 #ang = 0 #burn = 3.7/unit_vel # Forward Hohmann pos_range = pi/4 ang_range = pi/8 burn_range = 0.1/unit_vel # Start search searches = 0 max_searches = 5 while searches < max_searches: runtime = time.time() searches += 1 print("############## Search %i ###############" % (searches)) print("# pos = %f" % (pos)) print("# ang = %f" % (ang)) print("# burn = %f" % (burn)) pos_low = pos-pos_range pos_high = pos+pos_range ang_low = ang-ang_range ang_high = ang+ang_range burn_low = burn-burn_range burn_high = burn+burn_range stat,pos,ang,burn,x0,y0,px0,py0,dv,toa = search_mt(threads,1,duration,positions,angles,burns,pos_low,pos_high,ang_low,ang_high,burn_low,burn_high) if stat < 0: total_dv = abs(burn)+dv if best_total_dv > total_dv: best_total_dv = total_dv best_stat = stat best_pos = pos best_ang = ang best_burn = burn best_x0 = x0 best_y0 = y0 best_px0 = px0 best_py0 = py0 best_dv = dv best_toa = toa else: break pos_range *= 0.1 ang_range *= 0.1 burn_range *= 0.1 runtime = time.time()-runtime print("# Search runtime = %3.2fs" % (runtime)) # Print best result print("################ Best ################") print("# Best dV(total) = %f km/s" % (best_total_dv*unit_vel)) print_search_results(best_stat,best_pos,best_ang,best_burn,best_x0,best_y0,best_px0,best_py0,best_dv,best_toa) # Initialize arrays tlist = np.linspace(0,duration,n) xlist = np.zeros(n) ylist = np.zeros(n) pxlist = np.zeros(n) pylist = np.zeros(n) errlist = np.zeros(n) hlist = np.zeros(n) info = np.zeros(2) # Do trajectory duration = 10/unit_time status = symplectic(n,duration,x0,y0,px0,py0,xlist,ylist,pxlist,pylist,errlist,hlist,info) return tlist,xlist,ylist,pxlist,pylist,errlist,hlist
def refine(threads,n,duration,pos,ang,burn,x0,y0,px0,py0): """Integrate trajectory for the reduced 3-body problem. Args: n (int): Positions stored. duration (float): Time duration of simulation. x0 (float): Initial x-coordinate y0 (float): Initial y-coordinate px0 (float): Initial generalized x-momentum py0 (float): Initial generalized y-momentum Returns: Tuple of time-, x-, y-, px- and py lists. """ print("# Running refine.") # Low-energy-long trajectory < 200 days #duration = 200/unit_time # Low-energy-short trajectory < 47 days #duration = 47/unit_time best_total_dv = 1e9 best_toa = 0 positions = 15 angles = 15 burns = 15 # Divide circular earth orbit into 8 parts pos_range = 2*pi/16*0.1 ang_range = pi/100*0.1 burn_range = 0.1/unit_vel*0.1 # Start search searches = 0 max_searches = 10 while searches < max_searches: runtime = time.time() searches += 1 print("############## Search %i ###############" % (searches)) print("# pos = %f" % (pos)) print("# ang = %f" % (ang)) print("# burn = %f" % (burn)) pos_low = pos-pos_range pos_high = pos+pos_range ang_low = ang-ang_range ang_high = ang+ang_range burn_low = burn-burn_range burn_high = burn+burn_range stat,pos,ang,burn,x0,y0,px0,py0,dv,toa = search_mt(threads,1,duration,positions,angles,burns,pos_low,pos_high,ang_low,ang_high,burn_low,burn_high) if stat < 0: total_dv = abs(burn)+dv if best_total_dv > total_dv: best_total_dv = total_dv best_stat = stat best_pos = pos best_ang = ang best_burn = burn best_x0 = x0 best_y0 = y0 best_px0 = px0 best_py0 = py0 best_dv = dv best_toa = toa else: break pos_range *= 0.1 ang_range *= 0.1 burn_range *= 0.1 runtime = time.time()-runtime print("# Search runtime = %3.2fs" % (runtime)) # Print best result print("################ Best ################") print("# Best dV(total) = %f km/s" % (best_total_dv*unit_vel)) print_search_results(best_stat,best_pos,best_ang,best_burn,best_x0,best_y0,best_px0,best_py0,best_dv,best_toa) # Initialize arrays tlist = np.linspace(0,duration,n) xlist = np.zeros(n) ylist = np.zeros(n) pxlist = np.zeros(n) pylist = np.zeros(n) errlist = np.zeros(n) hlist = np.zeros(n) info = np.zeros(2) # Do trajectory duration = toa+(2.0*pi*lunar_orbit/lunar_orbit_vel)/(unit_time*day) status = symplectic(n,duration,x0,y0,px0,py0,xlist,ylist,pxlist,pylist,errlist,hlist,info) #exit() return tlist,xlist,ylist,pxlist,pylist,errlist,hlist
def low_energy_parts8(threads,n): """Finding low energy transfer trajectory for the reduced 3-body problem. Args: n (int): Positions stored. Returns: Tuple of time-, x-, y-, px- and py lists. """ print("# Running low_energy_parts8.") # Low-energy-short trajectory < 47 days duration = 200/unit_time best_total_dv = 1e9 best_toa = 0 positions = 55 angles = 1 burns = 55 # Divide circular earth orbit into 8 parts for i in range(0,8): pos = i*pi/4 ang = 0 #burn = 3.12/unit_vel # moon burn = 3.09/unit_vel # L1 pos_range = 2*pi/16 ang_range = pi/2 burn_range = 0.1/unit_vel # Start search searches = 0 max_searches = 3 while searches < max_searches: runtime = time.time() searches += 1 print("############## Search %i ###############" % (searches)) print("# pos = %f" % (pos)) print("# ang = %f" % (ang)) print("# burn = %f" % (burn)) pos_low = pos-pos_range pos_high = pos+pos_range ang_low = ang-ang_range ang_high = ang+ang_range burn_low = burn-burn_range burn_high = burn+burn_range stat,pos,ang,burn,x0,y0,px0,py0,dv,toa = search_mt(threads,1,duration,positions,angles,burns,pos_low,pos_high,ang_low,ang_high,burn_low,burn_high) if stat < 0: total_dv = abs(burn)+dv if best_total_dv > total_dv: best_total_dv = total_dv best_stat = stat best_pos = pos best_ang = ang best_burn = burn best_x0 = x0 best_y0 = y0 best_px0 = px0 best_py0 = py0 best_dv = dv best_toa = toa else: break pos_range *= 0.1 ang_range *= 0.1 burn_range *= 0.1 runtime = time.time()-runtime print("# Search runtime = %3.2fs" % (runtime)) # Print best result if best_total_dv < 1e9: print("################ Best ################") print("# Best dV(total) = %f km/s" % (best_total_dv*unit_vel)) print_search_results(best_stat,best_pos,best_ang,best_burn,best_x0,best_y0,best_px0,best_py0,best_dv,best_toa) # Initialize arrays tlist = np.linspace(0,duration,n) xlist = np.zeros(n) ylist = np.zeros(n) pxlist = np.zeros(n) pylist = np.zeros(n) errlist = np.zeros(n) hlist = np.zeros(n) info = np.zeros(2) # Do trajectory #duration = toa+(2.0*pi*lunar_orbit/lunar_orbit_vel)/(unit_time*day) status = symplectic(n,duration,x0,y0,px0,py0,xlist,ylist,pxlist,pylist,errlist,hlist,info) #exit() return tlist,xlist,ylist,pxlist,pylist,errlist,hlist
def low_energy(threads,n): """Finding low energy transfer trajectory for the reduced 3-body problem. Args: n (int): Positions stored. Returns: Tuple of time-, x-, y-, px- and py lists. """ print("# Running low_energy.") # Low-energy trajectory < 200 days duration = 200/unit_time best_total_dv = 1e9 positions = 100 angles = 1 burns = 200 pos = -3*pi/4 ang = 0 burn = 3.12/unit_vel pos_range = pi ang_range = 0 burn_range = 0.01/unit_vel # Start search searches = 0 max_searches = 1 while searches < max_searches: runtime = time.time() searches += 1 print("############## Search %i ###############" % (searches)) print("# pos = %f" % (pos)) print("# ang = %f" % (ang)) print("# burn = %f" % (burn)) pos_low = pos-pos_range pos_high = pos+pos_range ang_low = ang-ang_range ang_high = ang+ang_range burn_low = burn-burn_range burn_high = burn+burn_range stat,pos,ang,burn,x0,y0,px0,py0,dv,toa = search_mt(threads,1,duration,positions,angles,burns,pos_low,pos_high,ang_low,ang_high,burn_low,burn_high) if stat < 0: total_dv = abs(burn)+dv if best_total_dv > total_dv: best_total_dv = total_dv best_stat = stat best_pos = pos best_ang = ang best_burn = burn best_x0 = x0 best_y0 = y0 best_px0 = px0 best_py0 = py0 best_dv = dv best_toa = toa else: break pos_range *= 0.1 ang_range *= 0.1 burn_range *= 0.1 runtime = time.time()-runtime print("# Search runtime = %3.2fs" % (runtime)) # Initialize arrays tlist = np.linspace(0,duration,n) xlist = np.zeros(n) ylist = np.zeros(n) pxlist = np.zeros(n) pylist = np.zeros(n) errlist = np.zeros(n) hlist = np.zeros(n) info = np.zeros(2) # Do trajectory duration = toa+(2.0*pi*lunar_orbit/lunar_orbit_vel)/(unit_time*day) status = symplectic(n,duration,x0,y0,px0,py0,xlist,ylist,pxlist,pylist,errlist,hlist,info) exit() return tlist,xlist,ylist,pxlist,pylist,errlist,hlist
from symplectic import symplectic, thirds, ab, fifth import matplotlib.pyplot as plt from poincare import poincare, hh_sos import numpy as np H = lambda q, p: .5 * (np.dot(q, q) + np.dot(p, p)) + (q[0]**2) * q[1] - ( 1 / 3) * q[1]**3 dHdp = lambda p: p dHdq = lambda q: q + np.array([2 * q[0] * q[1], q[0]**2 - q[1]**2]) for E in np.linspace(1 / 12, 1 / 6, 10): gen = symplectic(dHdq, [0.0, 0.0], [np.sqrt(2 * E), 0.0]) qp = np.array([next(gen) for _ in range(50000)]) q, p = hh_sos(qp[:, 0], qp[:, 1]) plt.scatter(q, p, marker=".", label=f"{E}") plt.legend() plt.show()
def search(thread, threads, n, duration, positions, angles, burns): #print("Start thread=%i" % (thread)) # Initialize arrays xlist = np.zeros(n) ylist = np.zeros(n) pxlist = np.zeros(n) pylist = np.zeros(n) errlist = np.zeros(n) hlist = np.zeros(n) info = np.zeros(2) # Search for orbits trials = len(positions) * len(angles) * len(burns) ld1 = len(angles) * len(burns) ld2 = len(burns) trial = 0 hit_earth = 0 hit_moon = 0 best_status = 1e9 progress = -1 i = thread while i < trials: # One-to-one mapping of i -> (pos_i,ang_i,burn_i) pos_i = i // ld1 ang_i = (i - pos_i * ld1) // ld2 burn_i = i - pos_i * ld1 - ang_i * ld2 i += threads # Find launch setup pos = positions[pos_i] ang = angles[ang_i] burn = burns[burn_i] # Calculate initial conditions r = leo_orbit / unit_len x0 = np.cos(pos) * r y0 = np.sin(pos) * r rx = -y0 / r ry = x0 / r vx = (leo_orbit_vel / unit_vel) * rx vy = (leo_orbit_vel / unit_vel) * ry x0 += earth_pos_x bx = np.cos(ang) * rx - np.sin(ang) * ry by = np.sin(ang) * rx + np.cos(ang) * ry px0 = ( burn / abs(burn) ) * vx + burn * bx - y0 # Sign of burn decides rotational direction of launch py0 = (burn / abs(burn)) * vy + burn * by + x0 # Call symplectic integration # status > 0 : Closest distance to moon achieved # status < 0 : Hit the moon using status=dV(moon)-10000 to get into orbit # status == 100 : Collided with earth #if thread == 1: # print(n,duration,x0,y0,px0,py0) status = symplectic(n, duration, x0, y0, px0, py0, xlist, ylist, pxlist, pylist, errlist, hlist, info) if status == 100: hit_earth += 1 if status < 0: hit_moon += 1 if status < best_status: best_status = status best_pos = pos best_ang = ang best_burn = burn best_x0 = x0 best_y0 = y0 best_px0 = px0 best_py0 = py0 best_dv = info[0] best_toa = info[1] # Show progress if thread == 0: # only thread 0 if (100 * trial / (1 + trials // threads)) // 10 > progress: progress = (100 * trial / (1 + trials // threads)) // 10 print(progress * 10, end="% ") sys.stdout.flush() trial += 1 #if thread == 13: # print("thread=%i status=%f best_status=%f trial=%i(%i) pos=%f ang=%f burn=%f" % (thread,status,best_status,trial,trials,pos,ang,burn)) #print("End thread=%i" % (thread)) return best_status, best_pos, best_ang, best_burn, best_x0, best_y0, best_px0, best_py0, best_dv, best_toa, hit_earth, hit_moon