Esempio n. 1
0
def test_evaluate_explicit():
    print("-----test_evaluate_explicit-----")
    n_lin = int(math.pow(500, 1.0 / 3)) + 1
    x_1 = np.linspace(0, 5, n_lin)
    x_2 = np.linspace(0, 5, n_lin)
    x_3 = np.linspace(0, 5, n_lin)
    x = np.array(np.meshgrid(x_1, x_2, x_3)).T.reshape(-1, 3)
    x = x[np.random.choice(x.shape[0], 500, replace=False), :]
    # make solution
    y_t = (x[:, 0] * x[:, 0] + 3.5 * x[:, 1])
    y = y_t.reshape(-1, 1)

    py_training_data = ExplicitTrainingData(x, y)
    py_explicit_regressor = StandardRegression()
    c_explicit_regressor = bingocpp.StandardRegression()
    c_training_data = bingocpp.ExplicitTrainingData(x, y)

    py_manip = AGraphCpp.AGraphCppManipulator(3, 64, nloads=2)
    py_manip.add_node_type(2)
    py_manip.add_node_type(3)
    py_manip.add_node_type(4)
    c_manip = bingocpp.AcyclicGraphManipulator(3, 64, nloads=2)
    c_manip.add_node_type(2)
    c_manip.add_node_type(3)
    c_manip.add_node_type(4)

    py_1 = py_manip.generate()
    c_1 = c_manip.generate()
    c_1.stack = np.copy(py_1.command_array)
    c_manip.simplify_stack(c_1)

    py_fit = py_explicit_regressor.evaluate_fitness(py_1, py_training_data)
    c_fit = c_explicit_regressor.evaluate_fitness(c_1, c_training_data)

    assert py_fit == pytest.approx(c_fit)
Esempio n. 2
0
def compare_agraphcpp_explicit(X, Y):
    """does the comparison"""
    # make solution manipulator
    sol_manip = agcm(X.shape[1], 16, nloads=2)
    sol_manip.add_node_type(2)
    sol_manip.add_node_type(4)

    # make predictor manipulator
    pred_manip = fpm(32, Y.shape[0])

    # create training data
    training_data = ExplicitTrainingData(X, Y)

    # create fitness metric
    explicit_regressor = StandardRegression()

    # make and run island manager
    islmngr = SerialIslandManager(N_ISLANDS,
                                  solution_training_data=training_data,
                                  solution_manipulator=sol_manip,
                                  predictor_manipulator=pred_manip,
                                  fitness_metric=explicit_regressor)
    assert islmngr.run_islands(MAX_STEPS,
                               EPSILON,
                               step_increment=N_STEPS,
                               make_plots=False)
Esempio n. 3
0
def test_explicit_get_item():
    print("-----test_explicit_get_item-----")
    n_lin = int(math.pow(500, 1.0 / 3)) + 1
    x_1 = np.linspace(0, 5, n_lin)
    x_2 = np.linspace(0, 5, n_lin)
    x_3 = np.linspace(0, 5, n_lin)
    x = np.array(np.meshgrid(x_1, x_2, x_3)).T.reshape(-1, 3)
    x = x[np.random.choice(x.shape[0], 500, replace=False), :]
    # make solution
    y_t = (x[:, 0] * x[:, 0] + 3.5 * x[:, 1])
    y = y_t.reshape(-1, 1)

    py_training_data = ExplicitTrainingData(x, y)
    c_training_data = bingocpp.ExplicitTrainingData(x, y)

    items = [5, 10, 15, 18, 64, 92, 129, 186, 201, 215, 293, 355, 389]

    py_result = py_training_data.__getitem__(items)
    c_result = c_training_data.__getitem__(items)

    assert py_result.x.all() == c_result.x.all()
    assert py_result.y.all() == c_result.y.all()
Esempio n. 4
0
def compare_ag_explicit(X, Y, operator, params):
    """does the comparison"""
    # make solution manipulator
    sol_manip = agm(X.shape[1], 16, nloads=2)
    sol_manip.add_node_type(AGNodes.Add)
    sol_manip.add_node_type(AGNodes.Subtract)
    sol_manip.add_node_type(AGNodes.Multiply)
    sol_manip.add_node_type(AGNodes.Divide)
    sol_manip.add_node_type(AGNodes.Exp)
    sol_manip.add_node_type(AGNodes.Log)
    sol_manip.add_node_type(AGNodes.Sin)
    sol_manip.add_node_type(AGNodes.Cos)
    sol_manip.add_node_type(AGNodes.Abs)
    sol_manip.add_node_type(AGNodes.Pow)

    # make true equation
    equ = sol_manip.generate()
    equ.command_list[0] = (AGNodes.LoadData, (0, ))
    equ.command_list[1] = (AGNodes.LoadData, (1, ))
    equ.command_list[-1] = (operator, params)

    # make predictor manipulator
    pred_manip = fpm(32, Y.shape[0])

    # make training data
    Y = Y.reshape([-1, 1])
    training_data = ExplicitTrainingData(X, Y)

    # make fitness_metric
    explicit_regressor = StandardRegression()

    # make and run island manager
    islmngr = SerialIslandManager(N_ISLANDS,
                                  solution_training_data=training_data,
                                  solution_manipulator=sol_manip,
                                  predictor_manipulator=pred_manip,
                                  fitness_metric=explicit_regressor)

    epsilon = 1.05 * islmngr.isles[0].solution_fitness_true(equ) + 1.0e-10

    assert islmngr.run_islands(MAX_STEPS,
                               epsilon,
                               step_increment=N_STEPS,
                               make_plots=False)
Esempio n. 5
0
def compare_agcpp_explicit(X, Y, operator, params):
    """does the comparison"""
    Y = Y.reshape([-1, 1])
    # make solution manipulator
    sol_manip = agm(X.shape[1], 16, nloads=2)
    sol_manip.add_node_type(2)
    sol_manip.add_node_type(3)
    sol_manip.add_node_type(4)
    sol_manip.add_node_type(5)

    # make true equation
    equ = sol_manip.generate()
    equ.command_array[0] = (0, 0, 0)
    equ.command_array[1] = (0, 1, 1)
    equ.command_array[-1] = (operator, params[0], params[1])

    # make predictor manipulator
    pred_manip = fpm(32, X.shape[0])

    # make training data
    training_data = ExplicitTrainingData(X, Y)

    # make fitness_metric
    explicit_regressor = StandardRegression(const_deriv=True)

    # make and run island manager
    islmngr = SerialIslandManager(N_ISLANDS,
                                  solution_training_data=training_data,
                                  solution_manipulator=sol_manip,
                                  predictor_manipulator=pred_manip,
                                  fitness_metric=explicit_regressor)
    epsilon = 1.05 * islmngr.isles[0].solution_fitness_true(equ) + 1.0e-10
    assert islmngr.run_islands(MAX_STEPS,
                               epsilon,
                               step_increment=N_STEPS,
                               make_plots=False)
Esempio n. 6
0
def main(max_steps, epsilon, data_size, n_islands):
    """main regression function"""

    # --------------------------------------------
    # MAKE DATA (uncomment one of the below lines)
    # --------------------------------------------

    # data for standard regression
    # (use with ExplicitTrainingData and StandardRegression)
    # x_true, y_true = make_1d_data(data_size, 1)
    x_true, y_true = make_1d_data(data_size, 2)
    # x_true, y_true = make_1d_data(data_size, 3)
    # x_true, y_true = make_1d_data(data_size, 4)
    # x_true, y_true = make_norm_data(data_size)

    # data for implicit regression
    # (use with ImplicitTrainingData and ImplicitRegression)
    # x_true = make_circle_data(data_size)

    # ------------------------------------------------
    # MAKE TRAINING DATA  (uncomment one of the below)
    # ------------------------------------------------
    training_data = ExplicitTrainingData(x_true, y_true)
    # training_data = ImplicitTrainingData(x_true)

    # ------------------------------------------------------------
    # MAKE SOLUTION MANIPULATOR (uncomment one of the below blocks)
    # ------------------------------------------------------------

    # using AGraph.py for the solution manipulator
    # sol_manip = agm(x_true.shape[1], 32, nloads=2)
    # sol_manip.add_node_type(AGNodes.Add)
    # sol_manip.add_node_type(AGNodes.Subtract)
    # sol_manip.add_node_type(AGNodes.Multiply)
    # sol_manip.add_node_type(AGNodes.Divide)
    # # sol_manip.add_node_type(AGNodes.Exp)
    # # sol_manip.add_node_type(AGNodes.Log)
    # # sol_manip.add_node_type(AGNodes.Sin)
    # # sol_manip.add_node_type(AGNodes.Cos)
    # # sol_manip.add_node_type(AGNodes.Abs)
    # sol_manip.add_node_type(AGNodes.Sqrt)

    # using AGraphCpp.py for the solution manipulator
    sol_manip = AGraphCpp.AGraphCppManipulator(x_true.shape[1], 32, nloads=2)
    sol_manip.add_node_type(2)  # +
    sol_manip.add_node_type(3)  # -
    sol_manip.add_node_type(4)  # *
    sol_manip.add_node_type(5)  # /
    sol_manip.add_node_type(12)  # sqrt

    # ----------------------------------
    # MAKE FITNESS PREDICTOR MANIPULATOR
    # ----------------------------------
    pred_manip = fpm(128, data_size)

    # ------------------------------------------------
    # MAKE FITNESS METRIC (uncomment one of the below)
    # ------------------------------------------------
    regressor = StandardRegression()
    # regressor = ImplicitRegression()

    # --------------------------------------
    # MAKE SERIAL ISLAND MANAGER THEN RUN IT
    # --------------------------------------
    islmngr = SerialIslandManager(n_islands,
                                  solution_training_data=training_data,
                                  solution_manipulator=sol_manip,
                                  predictor_manipulator=pred_manip,
                                  solution_pop_size=64,
                                  fitness_metric=regressor,
                                  solution_age_fitness=True
                                  )
    islmngr.run_islands(max_steps, epsilon, step_increment=100)
Esempio n. 7
0
def main(max_steps, epsilon, data_size):
    """main function which runs regression"""
    comm = MPI.COMM_WORLD
    rank = comm.Get_rank()

    # load data on rank 0 and send it to all ranks
    x_true = None
    y_true = None
    if rank == 0:
        # --------------------------------------------
        # MAKE DATA (uncomment one of the below lines)
        # --------------------------------------------

        # standard regression
        # (use with ExplicitTrainingData and StandardRegression)
        # x_true, y_true = make_1d_data(data_size, 1)
        x_true, y_true = make_1d_data(data_size, 2)
        # x_true, y_true = make_1d_data(data_size, 3)
        # x_true, y_true = make_1d_data(data_size, 4)
        # x_true, y_true = make_norm_data(data_size)

        # implicit regression
        # (use with ImplicitTrainingData and ImplicitRegression)
        # x_true = make_circle_data(data_size)

    # then broadcast to all ranks
    x_true = MPI.COMM_WORLD.bcast(x_true, root=0)
    y_true = MPI.COMM_WORLD.bcast(y_true, root=0)

    # ------------------------------------------------
    # MAKE TRAINING DATA  (uncomment one of the below)
    # ------------------------------------------------
    training_data = ExplicitTrainingData(x_true, y_true)
    # training_data = ImplicitTrainingData(x_true)

    # ------------------------------------------------------------
    # MAKE SOLUTION MANIPULATOR (uncomment one of the below blocks)
    # ------------------------------------------------------------

    # using AGraph.py for the solution manipulator
    # sol_manip = agm(x_true.shape[1], 32, nloads=2)
    # sol_manip.add_node_type(AGNodes.Add)
    # sol_manip.add_node_type(AGNodes.Subtract)
    # sol_manip.add_node_type(AGNodes.Multiply)
    # sol_manip.add_node_type(AGNodes.Divide)
    # # sol_manip.add_node_type(AGNodes.Exp)
    # # sol_manip.add_node_type(AGNodes.Log)
    # # sol_manip.add_node_type(AGNodes.Sin)
    # # sol_manip.add_node_type(AGNodes.Cos)
    # # sol_manip.add_node_type(AGNodes.Abs)
    # sol_manip.add_node_type(AGNodes.Sqrt)

    # using AGraphCpp.py for the solution manipulator
    sol_manip = AGraphCpp.AGraphCppManipulator(x_true.shape[1], 32, nloads=2)
    sol_manip.add_node_type(2)  # +
    sol_manip.add_node_type(3)  # -
    sol_manip.add_node_type(4)  # *
    sol_manip.add_node_type(5)  # /
    sol_manip.add_node_type(12)  # sqrt

    # ----------------------------------
    # MAKE FITNESS PREDICTOR MANIPULATOR
    # ----------------------------------
    pred_manip = fpm(128, data_size)

    # ------------------------------------------------
    # MAKE FITNESS METRIC (uncomment one of the below)
    # ------------------------------------------------
    regressor = StandardRegression(const_deriv=True)
    # regressor = ImplicitRegression()

    # --------------------------------------
    # MAKE SERIAL ISLAND MANAGER THEN RUN IT
    # --------------------------------------
    islmngr = ParallelIslandManager(solution_training_data=training_data,
                                    solution_manipulator=sol_manip,
                                    predictor_manipulator=pred_manip,
                                    solution_pop_size=64,
                                    fitness_metric=regressor,
                                    solution_age_fitness=True)
    islmngr.run_islands(max_steps,
                        epsilon,
                        min_steps=1000,
                        step_increment=1000)
Esempio n. 8
0
def main(max_steps, epsilon, data_size, parallel):
    # STEP 1
    # Create your x and y data, on parallel, broadcast it to all other ranks

    ##################################################
    ##################### SINGLE #####################
    ##################################################
    if not parallel:
        n_lin = int(math.pow(data_size, 1.0 / 3)) + 1
        x_1 = np.linspace(0, 5, n_lin)
        x_2 = np.linspace(0, 5, n_lin)
        x_3 = np.linspace(0, 5, n_lin)
        x = np.array(np.meshgrid(x_1, x_2, x_3)).T.reshape(-1, 3)
        x = x[np.random.choice(x.shape[0], data_size, replace=False), :]
        # make solution
        y = (x[:, 0] * x[:, 0] + 3.5 * x[:, 1])
        x_true = x
        y_true = y
        y_true = y_true.reshape(-1, 1)
    ##################################################
    ##################################################
    ##################################################

    ##################################################
    #################### PARALLEL ####################
    ##################################################
    if parallel:
        comm = MPI.COMM_WORLD
        rank = comm.Get_rank()

        if rank == 0:
            #n_lin = int(math.pow(data_size, 1.0/3)) + 1
            #x_1 = np.linspace(0, 5, n_lin)
            #x_2 = np.linspace(0, 5, n_lin)
            #x_3 = np.linspace(0, 5, n_lin)
            #x = np.array(np.meshgrid(x_1, x_2, x_3)).T.reshape(-1, 3)
            #x = x[np.random.choice(x.shape[0], data_size, replace=False), :]

            x_true = np.array([i for i in range(25, 425, 25)])
            y_true = np.array([
                5.38, 2.91, 2.07, 1.71, 1.46, 1.35, 1.29, 1.24, 1.2, 1.19,
                1.22, 1.23, 1.23, 1.23, 1.26, 1.26
            ])
            #y = (x[:,0]*x[:,0]+3.5*x[:,1])
            #x_true = x
            #y_true = y
            y_true = y_true.reshape(-1, 1)
        else:
            x_true = None
            y_true = None
        # then broadcast to all ranks
        x_true = MPI.COMM_WORLD.bcast(x_true, root=0)
        y_true = MPI.COMM_WORLD.bcast(y_true, root=0)
    ##################################################
    ##################################################
    ##################################################

    # STEP 2
    # Create solution manipulators. The solution manipulator is what creates
    # the representations of the functions as the acyclic graph

    ####### SOLUTION MANIPULATOR #######
    # nvars - number of independent variables
    # ag_size - length of the command stack
    # nloads - number of load operation which are required at the
    #          start of stack - Default 1
    # float_lim - (0, max) of floats which are generated - Default 10.0
    # terminal_prob: probability that a new node will be a terminal -Default .1
    sol_manip = AGraphCpp.AGraphCppManipulator(1, 64, nloads=2)

    ####### OPERATIONS #######
    sol_manip.add_node_type(2)  # +
    sol_manip.add_node_type(3)  # -
    sol_manip.add_node_type(4)  # *
    sol_manip.add_node_type(5)  # /
    sol_manip.add_node_type(6)  # sin
    sol_manip.add_node_type(7)  # cos
    sol_manip.add_node_type(8)  # exp
    sol_manip.add_node_type(9)  # log
    sol_manip.add_node_type(10)  # pow
    sol_manip.add_node_type(11)  # abs
    sol_manip.add_node_type(12)  # sqrt

    ####### PREDICTION MANIPULATOR #######
    pred_manip = fpm(16, data_size)

    # STEP 3
    # Create the training data from your x and y data,
    # and create the fitness metric.
    # For this example, we are using explicit (standard)

    ####### TRAINING DATA #######
    training_data = ExplicitTrainingData(x_true, y_true)

    ####### FITNESS METRIC #######
    explicit_regressor = StandardRegression()

    # STEP 4
    # Create the island manager, this will run the steps on the population, and
    # determine when to stop running

    ####### ISLAND MANAGER #######
    islmngr = ParallelIslandManager(  #restart_file='test.p',
        solution_training_data=training_data,
        solution_manipulator=sol_manip,
        predictor_manipulator=pred_manip,
        solution_pop_size=64,
        fitness_metric=explicit_regressor)

    ####### RUN ISLAND MANAGER #######

    ##################################################
    ##################### SINGLE #####################
    ##################################################
    # max_steps - Max amount to go if no convergence happens
    # epsilon - error which defines convergence
    # min_steps - minimum number of steps required - Default 0
    # step_increment - number of steps between convergence
    #                  checks / migration - Default 1000
    # make_plots - bool whether or not to produce plots - Default True
    # checkpoint_file - base file name for checkpoint files
    if not parallel:
        islmngr.run_islands(max_steps,
                            epsilon,
                            min_steps=500,
                            step_increment=500)
    ##################################################
    ##################################################
    ##################################################

    ##################################################
    #################### PARALLEL ####################
    ##################################################
    # when_update - how often rank 0 gets updated on ages - Default 10
    # non_block - bool to determine to run nonblocking - Default True
    if parallel:
        islmngr.run_islands(max_steps,
                            epsilon,
                            min_steps=500,
                            step_increment=500,
                            when_update=50)
Esempio n. 9
0
from bingo.CoevolutionIsland import CoevolutionIsland


import logging
logging.basicConfig(level=logging.INFO, format='%(message)s')

data_size = 1000
n_steps = 250

data_x = np.linspace(0,10,data_size)
data_y = 10 - (data_x - 5)*data_x

plt.plot(data_x, data_y, '.')
plt.savefig('raw_data.png')

training_data = ExplicitTrainingData(data_x.reshape((-1,1)), data_y.reshape((-1, 1)))
error_metric = StandardRegression()

def fitness(indv):
    return error_metric.evaluate_fitness(indv, training_data)

sol_manip = AGraphManipulator(1, 128, nloads=1)
sol_manip.add_node_type(AGNodes.Add)
sol_manip.add_node_type(AGNodes.Subtract)
sol_manip.add_node_type(AGNodes.Multiply)

pred_manip = FPManipulator(10, data_size)


i = Island(sol_manip, fitness)
t0 = time.time()
Esempio n. 10
0
def test_const_opt_agraph_explicit():
    """test optimization code"""
    print("-----test_const_opt_agraph_explicit-----")
    # get independent vars
    x_true = snake_walk()

    # make solutions
    consts = np.random.rand(6) * 90 + 10
    print("CONSTANTS: ", consts)
    y = consts[0] + consts[1] * x_true[:, 0] + consts[2] * x_true[:, 1] + \
        consts[3] * x_true[:, 0] * x_true[:, 0] + \
        consts[4] * x_true[:, 1] * x_true[:, 1] + \
        consts[5] * x_true[:, 0] * x_true[:, 1]

    # create manipulator to set things up
    sol_manip = agm(x_true.shape[1], 21, nloads=2)
    sol_manip.add_node_type(AGNodes.Add)
    sol_manip.add_node_type(AGNodes.Multiply)

    # create gene with proper functional form
    sol = sol_manip.generate()
    sol.command_list[0] = (AGNodes.LoadConst, (None, ))
    sol.command_list[1] = (AGNodes.LoadConst, (None, ))
    sol.command_list[2] = (AGNodes.LoadConst, (None, ))
    sol.command_list[3] = (AGNodes.LoadConst, (None, ))
    sol.command_list[4] = (AGNodes.LoadConst, (None, ))
    sol.command_list[5] = (AGNodes.LoadConst, (None, ))

    sol.command_list[6] = (AGNodes.LoadData, (0, ))
    sol.command_list[7] = (AGNodes.LoadData, (1, ))
    sol.command_list[8] = (AGNodes.Multiply, (6, 6))
    sol.command_list[9] = (AGNodes.Multiply, (7, 7))
    sol.command_list[10] = (AGNodes.Multiply, (6, 7))

    sol.command_list[11] = (AGNodes.Multiply, (1, 6))
    sol.command_list[12] = (AGNodes.Multiply, (2, 7))
    sol.command_list[13] = (AGNodes.Multiply, (3, 8))
    sol.command_list[14] = (AGNodes.Multiply, (4, 9))
    sol.command_list[15] = (AGNodes.Multiply, (5, 10))

    sol.command_list[16] = (AGNodes.Add, (0, 11))
    sol.command_list[17] = (AGNodes.Add, (16, 12))
    sol.command_list[18] = (AGNodes.Add, (17, 13))
    sol.command_list[19] = (AGNodes.Add, (18, 14))
    sol.command_list[20] = (AGNodes.Add, (19, 15))
    # print(sol.latexstring())
    sol.set_constants(consts)

    # create training data
    y = y.reshape([-1, 1])
    training_data = ExplicitTrainingData(x_true, y)

    # create fitness metric
    explicit_regressor = StandardRegression()

    # fit the constants
    explicit_regressor.evaluate_fitness(sol, training_data)

    # make sure constants are close
    c_fit = sol.constants
    print("FITTED:    ", c_fit)
    print("REL DIFF:  ", (consts - c_fit) / consts)
    for tru, fit in zip(consts, c_fit):
        assert np.abs(tru - fit) < 1e-8
Esempio n. 11
0
def test_const_opt_agraphcpp_explicit():
    """test optimization code"""
    print("-----test_const_opt_agraphcpp_explicit-----")
    # get independent vars
    x_true = snake_walk()

    # make solutions
    consts = np.random.rand(6) * 90 + 10
    print("CONSTANTS: ", consts)
    y = consts[0] + consts[1] * x_true[:, 0] + consts[2] * x_true[:, 1] + \
        consts[3] * x_true[:, 0] * x_true[:, 0] + \
        consts[4] * x_true[:, 1] * x_true[:, 1] + \
        consts[5] * x_true[:, 0] * x_true[:, 1]
    y = y.reshape([-1, 1])

    # create manipulator to set things up
    sol_manip = agcm(x_true.shape[1], 21, nloads=2)
    sol_manip.add_node_type(2)
    sol_manip.add_node_type(4)

    # create gene with proper functional form
    sol = sol_manip.generate()
    sol.command_array[0] = (1, -1, -1)
    sol.command_array[1] = (1, -1, -1)
    sol.command_array[2] = (1, -1, -1)
    sol.command_array[3] = (1, -1, -1)
    sol.command_array[4] = (1, -1, -1)
    sol.command_array[5] = (1, -1, -1)

    sol.command_array[6] = (0, 0, 0)
    sol.command_array[7] = (0, 1, 1)
    sol.command_array[8] = (4, 6, 6)
    sol.command_array[9] = (4, 7, 7)
    sol.command_array[10] = (4, 6, 7)

    sol.command_array[11] = (4, 1, 6)
    sol.command_array[12] = (4, 2, 7)
    sol.command_array[13] = (4, 3, 8)
    sol.command_array[14] = (4, 4, 9)
    sol.command_array[15] = (4, 5, 10)

    sol.command_array[16] = (2, 0, 11)
    sol.command_array[17] = (2, 16, 12)
    sol.command_array[18] = (2, 17, 13)
    sol.command_array[19] = (2, 18, 14)
    sol.command_array[20] = (2, 19, 15)
    # print(sol.latexstring())
    # sol.set_constants(consts)

    # create training data
    training_data = ExplicitTrainingData(x_true, y)

    # create fitness metric
    explicit_regressor = StandardRegression()
    explicit_regressor_w_deriv = StandardRegression(const_deriv=True)

    # fit the constants
    explicit_regressor.evaluate_fitness(sol, training_data)
    c_fit_1 = sol.constants

    # fit the constants ausing const derivatives
    sol.set_constants([])
    explicit_regressor_w_deriv.evaluate_fitness(sol, training_data)
    c_fit_2 = sol.constants

    # make sure constants are close
    print("FITTED:    ", c_fit_1)
    print("REL DIFF:  ", (consts - c_fit_1) / consts)
    print("FITTED W DERIV:    ", c_fit_2)
    print("REL DIFF W DERIV:  ", (consts - c_fit_2) / consts)
    for tru, fit1, fit2 in zip(consts, c_fit_1, c_fit_2):
        assert np.abs(tru - fit1) < 1e-8
        assert np.abs(tru - fit2) < 1e-8