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)
Beispiel #3
0
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")