def getInput(fromTraining, trainingDataset): """Generates initial conditions, ensuring that they represent a solvable problem""" if fromTraining: r = random.randrange(10_000) c = trainingDataset[r] return [ c[0], c[1], c[2], c[3], [c[4], c[5]], [c[6], c[7]], [c[8], c[9]], [c[10], c[11]], [c[12], c[13]], [c[14], c[15]], [c[16], c[17]], [c[18], c[19]] ] else: # Project-standard constants orbital_periods = 3 time_steps = 1500 # Find valid initial conditions; each problem must be checked to ensure the solver can handle it valid = False while not valid: # Generate a random problem m1 = data_gen.newMass() m2 = data_gen.newMass() m3 = data_gen.newMass() m4 = data_gen.newMass() p = data_gen.getPositions() v = data_gen.getVelocities() problem = FourBodyProblem(orbital_periods, time_steps, m1, m2, m3, m4, p[0], p[1], p[2], p[3], v[0], v[1], v[2], v[3]) # Check problem to ensure that it is valid output = problem.calculate_trajectories() valid = data_gen.testValidity(output) return [m1, m2, m3, m4, p[0], p[1], p[2], p[3], v[0], v[1], v[2], v[3]]
def assess(model, fromTraining, trainingDataset): """Compares the accuracy of the classical solution and the machine learning solution on one four-body problem""" # Define constants for this trial i = getInput(fromTraining, trainingDataset) calculateToPeriod = [0.5, 1.0, 1.5, 2.0, 2.5, 3.0] trialCounter = 1 # Raw Classical Output rCl = [] # Raw ML Output rMl = [] # Compute times computeTimes = [] # Each trial compares the accuracy of each solution at six different times for the same initial conditions for period in calculateToPeriod: # Assess the classical solution print(f"Period {trialCounter}:") classicalProblem = FourBodyProblem(period, 2, i[0], i[1], i[2], i[3], i[4], i[5], i[6], i[7], i[8], i[9], i[10], i[11]) s = time.perf_counter() classicalResults = classicalProblem.calculate_trajectories() e = time.perf_counter() clComputeTime = (e - s) * 1000 classicalResults = classicalResults[-1, :8] # Append results of output for this time point to raw data array if (len(rCl) == 0): rCl = [classicalResults] else: rCl = np.append(rCl, [classicalResults], axis=0) # Assess the machine learning solution mlInput = [[period] + i[:4] + i[4] + i[5] + i[6] + i[7] + i[8] + i[9] + i[10] + i[11]] mlInput = np.array(mlInput, dtype='float32') s = time.perf_counter() mlResults = model(mlInput) e = time.perf_counter() mlComputeTime = (e - s) * 1000 # Append results of output for this time point to raw data array if (len(rMl) == 0): rMl = mlResults else: rMl = np.append(rMl, mlResults, axis=0) trialCounter += 1 periodComputeTime = np.array([clComputeTime, mlComputeTime], dtype='float32') if (len(computeTimes) == 0): computeTimes = periodComputeTime else: computeTimes = np.append(computeTimes, periodComputeTime) # Sort the data before returning it return (sortRawData(rCl, rMl), computeTimes)
def main(): classical_solution = FourBodyProblem( 3, 1000, 1.493274915, 0.777043742, 0.69905188, 1.644425625, [-0.2235866560691493, 0.4662489456089146], [0.45460058216449073, 1.856775210402708], [-0.581630066079448, 2.652030222251113], [-1.0887887921718722, 1.8916735993939726], [-0.001983479092496618, -0.023803719445120764], [-0.04168724914664399, -0.022727286512001968], [-0.0006659848704990909, -0.01954219193498398], [0.0222475650915121, -0.019197877602321424]) classical_solution.calculate_trajectories() classical_solution.display_trajectories(animated=False, save_animation=False) model = Sequential([ Dense(256, activation='relu', input_shape=[21]), Dense(256, activation='relu'), Dense(256, activation='relu'), Dense(256, activation='relu'), Dense(256, activation='relu'), Dense(256, activation='relu'), Dense(256, activation='relu'), Dense(256, activation='relu'), Dense(256, activation='relu'), Dense(256, activation='relu'), Dense(8), ]) model.compile(optimizer='SGD', loss='mean_squared_error', metrics=['accuracy']) # Load the weights on the model model.load_weights("assets/sgd_checkpoints/cp.ckpt") time_span = np.linspace(0, 3, 1000) ml_outputs = [] for n in time_span: ml_input = [ n, 1.493274915, 0.777043742, 0.69905188, 1.644425625, -0.2235866560691493, 0.4662489456089146, 0.45460058216449073, 1.856775210402708, -0.581630066079448, 2.652030222251113, -1.0887887921718722, 1.8916735993939726, -0.001983479092496618, -0.023803719445120764, -0.04168724914664399, -0.022727286512001968, -0.0006659848704990909, -0.01954219193498398, 0.0222475650915121, -0.019197877602321424 ] ml_input = np.array([ml_input], dtype='float32') mlResults = model(ml_input) if (len(ml_outputs) == 0): ml_outputs = mlResults else: ml_outputs = np.append(ml_outputs, mlResults, axis=0) print(str(ml_outputs)) print(str(len(ml_outputs[0]))) display_trajectories(ml_outputs, animated=False, save_animation=False)
def getInput(fromTraining, trainingDataset): """Generates initial conditions, ensuring that they represent a solvable problem""" # Project-standard constants orbital_periods = 3 time_steps = 1500 if fromTraining: r = random.randrange(10_000) c = trainingDataset[r] inputs = [ c[0], c[1], c[2], c[3], [c[4], c[5]], [c[6], c[7]], [c[8], c[9]], [c[10], c[11]], [c[12], c[13]], [c[14], c[15]], [c[16], c[17]], [c[18], c[19]] ] problem = FourBodyProblem(orbital_periods, time_steps, c[0], c[1], c[2], c[3], [c[4], c[5]], [c[6], c[7]], [c[8], c[9]], [c[10], c[11]], [c[12], c[13]], [c[14], c[15]], [c[16], c[17]], [c[18], c[19]]) s = time.perf_counter() output = problem.calculate_trajectories() e = time.perf_counter() classical_output = np.concatenate( ([output[249, :8]], [output[499, :8]], [output[749, :8]], [output[999, :8]], [output[1249, :8]], [output[1499, :8]]), axis=0) computeTime = (e - s) * 1000 return inputs, classical_output, computeTime else: output = [] computeTime = 0 # Find valid initial conditions; each problem must be checked to ensure the solver can handle it valid = False while not valid: # Generate a random problem m1 = data_gen.newMass() m2 = data_gen.newMass() m3 = data_gen.newMass() m4 = data_gen.newMass() p = data_gen.getPositions() v = data_gen.getVelocities() problem = FourBodyProblem(orbital_periods, time_steps, m1, m2, m3, m4, p[0], p[1], p[2], p[3], v[0], v[1], v[2], v[3]) # Check problem to ensure that it is valid s = time.perf_counter() output = problem.calculate_trajectories() e = time.perf_counter() computeTime = (e - s) * 1000 valid = data_gen.testValidity(output) inputs = [ m1, m2, m3, m4, p[0], p[1], p[2], p[3], v[0], v[1], v[2], v[3] ] classical_output = np.concatenate( ([output[249, :8]], [output[499, :8]], [output[749, :8]], [output[999, :8]], [output[1249, :8]], [output[1499, :8]]), axis=0) print(str(len(classical_output))) return inputs, classical_output, computeTime
def createData(numProblems, time_steps, withAnimation, withHeader): # Constants and variables to track program performance orbital_periods = 3 numInvalid = 0 totalCalcTime = 0 # Prepare the master file with open("outputs/master.csv", 'w', newline='') as csvFile: header = ["Trial", "Path", "Mass 1", "Mass 2", "Mass 3", "Mass 4", "x Position 1", "y Position 1", "x Position 2", "y Position 2", "x Position 3", "y Position 3", "x Position 4", "y Position 4", "x Velocity 1", "y Velocity 1", "x Velocity 2", "y Velocity 2", "x Velocity 3", "y Velocity 3", "x Velocity 4", "y Velocity 4"] csvWriter = csv.writer(csvFile) if withHeader: csvWriter.writerow(header) dataset = [] for n in range(numProblems): print("Trial " + str(n+1)) calcTime = 0 valid = False # While loop used to keep generating problems until a valid one is solved while not valid: # Generate random masses in range 0 - 2 m1 = newMass() m2 = newMass() m3 = newMass() m4 = newMass() p = getPositions() v = getVelocities() problem = FourBodyProblem(orbital_periods, time_steps, m1, m2, m3, m4, p[0], p[1], p[2], p[3], v[0], v[1], v[2], v[3]) # Track time for performance comparisons s = time.perf_counter() output = problem.calculate_trajectories() e = time.perf_counter() calcTime = e - s # Ensure validity valid = testValidity(output) # Print to screen to notify of an invalid solution # Add one to the tracker variable if not valid: print("Solution invalid, recalculating...") numInvalid += 1 totalCalcTime += calcTime if withAnimation: problem.display_trajectories(animated=True, save_animation=False) # Problem can be written to csv file if the problem needs to be checked for matching the master file #problem.to_csv("outputs/num" + str(n) + ".csv", withHeader=withHeader) # Prepare row to be written to master file problemArgs = [str(n+1), "num" + str(n) + ".csv", str(m1), str(m2), str(m3), str(m4), str(p[0][0]), str(p[0][1]), str(p[1][0]), str(p[1][1]), str(p[2][0]), str(p[2][1]), str(p[3][0]), str(p[3][1]), str(v[0][0]), str(v[0][1]), str(v[1][0]), str(v[1][1]), str(v[2][0]), str(v[2][1]), str(v[3][0]), str(v[3][1])] with open('outputs/master.csv', 'a', newline='') as csvFile: csvWriter = csv.writer(csvFile) csvWriter.writerow(problemArgs) # Add the new problem to the dataset array, making sure only to add position values if (len(dataset) == 0): dataset = output[:,0:8] else: dataset = np.append(dataset, output[:,0:8], axis=0) # Save the dataset array to a npy file for transferring to ml program np.save("outputs/trainingOutputs.npy", dataset) # Calculate and print program performance statistics avgCalcTime = ( totalCalcTime / numProblems ) * 1000 print() print("Done Generating Solutions") print("=========================") print("Number Generated: " + str(numProblems)) print("Number Invalid: " + str(numInvalid)) print("Total Calculation Time (s): " + str(totalCalcTime)) print("Avg Calculation Time (ms): " + str(avgCalcTime)) #createData(500, time_steps=1500, withAnimation=False, withHeader=False)
from classical_solution_four_bodies import FourBodyProblem three_body_problem = FourBodyProblem(1, 1500, 0.2, 1.1, 2, 1.3, [0.5, 0], [-0.5, 0], [0, 0.5], [0, -0.5], [0, 0.01], [0, -0.01], [-0.03, 0], [0.05, 0.05]) results = three_body_problem.calculate_trajectories() print(str(results)) three_body_problem.display_trajectories(animated=False, save_animation=False) three_body_problem.to_csv("output.csv")