Пример #1
0
    def fit(self):
        """
        Run problem with DFO.
        """
        if self.minimizer == 'dfogn':
            self._soln = dfogn.solve(self.problem.eval_r, self._pinit)
        elif self.minimizer == 'dfols':
            self._soln = dfols.solve(self.problem.eval_r, self._pinit)

        self._popt = self._soln.x
        self._status = self._soln.flag
Пример #2
0
    def fit(self):
        """
        Run problem with DFO-GN.
        """
        self.success = False

        self._soln = dfogn.solve(self._prediction_error, self._pinit)

        if (self._soln.flag == 0):
            self.success = True

        self._popt = self._soln.x
Пример #3
0
 def runTest(self):
     # n, m = 2, 2
     x0 = np.array([-1.2, 1.0])
     soln = dfogn.solve(rosenbrock, x0)
     self.assertTrue(
         array_compare(soln.x, np.array([1.0, 1.0]), thresh=1e-4),
         "Wrong xmin")
     self.assertTrue(
         array_compare(soln.resid, rosenbrock(soln.x), thresh=1e-10),
         "Wrong resid")
     self.assertTrue(
         array_compare(soln.jacobian,
                       rosenbrock_jacobian(soln.x),
                       thresh=2e-2), "Wrong Jacobian")
     self.assertTrue(abs(soln.f) < 1e-10, "Wrong fmin")
Пример #4
0
 def runTest(self):
     n, m = 2, 5
     np.random.seed(0)  # (fixing random seed)
     A = np.random.rand(m, n)
     b = np.random.rand(m)
     objfun = lambda x: np.dot(A, x) - b
     xmin = np.linalg.lstsq(A, b)[0]
     fmin = np.dot(objfun(xmin), objfun(xmin))
     x0 = np.zeros((n, ))
     soln = dfogn.solve(objfun, x0)
     self.assertTrue(array_compare(soln.x, xmin, thresh=1e-2), "Wrong xmin")
     self.assertTrue(
         array_compare(soln.resid, objfun(soln.x), thresh=1e-10),
         "Wrong resid")
     self.assertTrue(array_compare(soln.jacobian, A, thresh=1e-2),
                     "Wrong Jacobian")
     self.assertTrue(abs(soln.f - fmin) < 1e-4, "Wrong fmin")
Пример #5
0
 def runTest(self):
     # n, m = 2, 2
     x0 = np.array([-1.2,
                    0.7])  # standard start point too close to upper bounds
     lower = np.array([-2.0, -2.0])
     upper = np.array([0.9, 0.9])
     xmin = np.array([0.9, 0.81])  # approximate
     fmin = np.dot(rosenbrock(xmin), rosenbrock(xmin))
     soln = dfogn.solve(rosenbrock, x0, lower=lower, upper=upper)
     print(soln.x)
     self.assertTrue(array_compare(soln.x, xmin, thresh=1e-2), "Wrong xmin")
     self.assertTrue(
         array_compare(soln.resid, rosenbrock(soln.x), thresh=1e-10),
         "Wrong resid")
     self.assertTrue(
         array_compare(soln.jacobian,
                       rosenbrock_jacobian(soln.x),
                       thresh=1e-2), "Wrong Jacobian")
     self.assertTrue(abs(soln.f - fmin) < 1e-4, "Wrong fmin")
Пример #6
0
def do_parameter_fit(x0, datas, lsq_solver, model_solver, LARGE_V=50):
    """
    Function to fit parameters given a starting point and datas.
    Choice of which optimisation algorithm and which model to use.
    """
    def prediction_error(x,
                         show_plots=True,
                         show_stars=True,
                         save_plot_data=False):
        """
        Compare model to data and return array of differences
        """
        # Rescale x
        x = lower + (upper - lower) * x
        # Initial SOCs
        q0s = np.append([1], x[4:])
        # Prepare dict
        modelVs = {}
        for i, name in enumerate(datas.keys()):
            data = datas[name]

            # Make dict of fitting parameters from x
            pars = {
                "epsnmax": x[0],
                "epssmax": x[1],
                "epspmax": x[0],
                "cmax": 5.65,
                "jref_n": x[2],
                "jref_p": x[2] / 10,
                "qinit": q0s[i],
            }

            # Shape preserving interpolation of current: do the hard work offline
            interpclass = interp.PchipInterpolator(data["time"],
                                                   data["current"])

            def Icircuit(t):
                return interpclass(t)

            # Load parameters
            pars = Parameters(fit=pars,
                              Icircuit=Icircuit,
                              Ibar=np.max(Icircuit(data["time"])))

            # Nondimensionalise time
            t = data["time"] / pars.scales.time

            # Run model
            model = model_solver(t, pars, grid, Vonly=True)
            model.dimensionalise(pars, grid)

            # Take away resistance of the wires
            model.Vcircuit -= x[3] * data["current"][:, np.newaxis]

            # Remove NaNs
            model.Vcircuit[np.isnan(model.Vcircuit)] = LARGE_V

            # Store voltages
            modelVs[name] = model.Vcircuit

        # Plot data vs model
        if show_plots:
            plt.ion()
            fig = plt.figure(1)
            plt.clf()
            for i, name in enumerate(datas.keys()):
                plt.plot(
                    datas[name]["time"],
                    datas[name]["voltage"],
                    "o",
                    markersize=1,
                    color="C" + str(i),
                )
                plt.plot(datas[name]["time"],
                         modelVs[name],
                         color="C" + str(i),
                         label=name)
            # plt.title('params={}'.format(x))
            plt.xlabel("Time [h]")
            plt.ylabel("Voltage [V]")
            legend = plt.legend()
            fig.canvas.flush_events()
            time.sleep(0.01)

        # Make vector of differences (including weights)
        diffs = np.concatenate([
            (data["voltage"] - modelVs[name][:, 0]) * data["weights"]
            for name, data in datas.items()
        ])

        # Show progress
        # if show_stars:
        #     plt.figure(2)
        #     plt.plot(x, np.dot(diffs, diffs), 'rx')
        #     plt.pause(.01)

        # Save plot data
        if save_plot_data:
            # Set linestyles
            linestyles = {
                "3A": "",
                "2.5A": "",
                "2A": "",
                "1.5A": "",
                "1A": "",
                "0.5A": "",
            }
            with open(
                    "out/plot_calls/fits/{}_{}.txt".format(
                        lsq_solver, model_solver.__name__),
                    "w",
            ) as fit_plot_calls:
                # Save data and model from each current
                for i, name in enumerate(datas.keys()):
                    save_data(
                        "fits/{}/{}/{}_model".format(lsq_solver,
                                                     model_solver.__name__,
                                                     name),
                        datas[name]["time"],
                        modelVs[name],
                        fit_plot_calls,
                        linestyles[name],
                        n_coarse_points=100,
                    )
                    save_data(
                        "fits/{}/{}/{}_data".format(lsq_solver,
                                                    model_solver.__name__,
                                                    name),
                        datas[name]["time"],
                        datas[name]["voltage"],
                        fit_plot_calls,
                        linestyles[name],
                        n_coarse_points=100,
                    )
                # Add legend (two commas to ignore the data entries)
                fit_plot_calls.write(
                    ("\\legend{{{!s}" + ", ,{!s}" * (len(datas.keys()) - 1) +
                     "}}\n").format(*tuple(datas.keys())))
        return diffs

    # Compute grid (doesn't depend on base parameters)
    grid = Grid(10)

    fit_currents = datas.keys()

    # Set the bounds
    lower = np.concatenate(
        [np.array([0.0, 0.0, 0.01, 0.0]),
         np.zeros(len(datas) - 1)])
    upper = np.concatenate(
        [np.array([1.0, 1.0, 1.0, 1.0]),
         np.ones(len(datas) - 1)])

    # Rescale x0 so that all fitting parameters go from 0 to 1
    x0 = (x0 - lower) / (upper - lower)
    # errs = np.array([])
    # js = np.linspace(0.01,1,10)
    # for j in js:
    #     diffs = prediction_error(j, show_plots=True, show_stars=False)
    #     errs = np.append(errs, np.dot(diffs, diffs))
    # plt.figure(2)
    # plt.plot(js, errs)
    # plt.pause(0.01)
    # Do curve fitting
    print("Fit using {} on the {} model".format(lsq_solver,
                                                model_solver.__name__))
    print("-" * 60)
    if lsq_solver in ["dfogn", "dfols"]:
        # Set logging to INFO to view progress
        logging.basicConfig(level=logging.INFO, format="%(message)s")

        # Call and time DFO-GN or DFO-LS
        start = time.time()
        if lsq_solver == "dfogn":
            soln = dfogn.solve(
                prediction_error,
                x0,
                lower=np.zeros(len(x0)),
                upper=np.ones(len(x0)),
                rhoend=1e-5,
            )
        elif lsq_solver == "dfols":
            soln = dfols.solve(
                prediction_error,
                x0,
                bounds=(np.zeros(len(x0)), np.ones(len(x0))),
                rhoend=1e-5,
            )
        soln_time = time.time() - start

        # Scale x back to original scale
        x = lower + (upper - lower) * soln.x

        # Display output
        print(" *** DFO-GN results *** ")
        print("Solution xmin = %s" % str(x))
        print("Objective value f(xmin) = %.10g" % soln.f)
        print("Needed %g objective evaluations" % soln.nf)
        print("Exit flag = %g" % soln.flag)
        print(soln.msg)

        # Save solution parameters
        # save_output = {'y': True, 'n': False}[input('Save fitted params? (y/n): ')]
        # if save_output:
        #     filename = "out/fits/dfogn_{}.txt".format(model_solver.__name__)
        #     np.savetxt(filename, lower+(upper-lower)*soln.x)

        return (x, soln.f, soln_time)

    elif lsq_solver == "scipy":
        # Call and time scipy least squares
        start = time.time()
        soln = opt.least_squares(
            prediction_error,
            x0,
            bounds=(np.zeros(len(x0)), np.ones(len(x0))),
            method="trf",
            jac="2-point",
            diff_step=1e-5,
            ftol=1e-4,
            verbose=2,
        )
        soln_time = time.time() - start

        # Scale x back to original scale
        x = lower + (upper - lower) * soln.x

        # Display output
        print(" *** SciPy results *** ")
        print("Solution xmin = %s" % str(x))
        print("Objective value f(xmin) = %.10g" % (soln.cost * 2))
        print("Needed %g objective evaluations" % soln.nfev)
        print("Exit flag = %g" % soln.status)
        print(soln.message)

        # Save solution parameters
        # save_output = {'y': True, 'n': False}[input('Save fitted params? (y/n): ')]
        # if save_output:
        #     filename = "out/fits/scipy_{}.txt".format(model_solver.__name__)
        #     np.savetxt(filename, x)

        return (x, soln.cost * 2, soln_time)

    elif lsq_solver is None:
        # Do nothing
        diffs = prediction_error(x0)
        return (x0, np.dot(diffs, diffs), 0)

    # save plots (hacky!)
    prediction_error(x, save_plot_data=True)
Пример #7
0
def rosenbrock_noisy(x):
    return rosenbrock(x) * (1.0 + 1e-2 * np.random.normal(size=(2, )))


# Define the starting point
x0 = np.array([-1.2, 1.0])

np.random.seed(0)

print("Demonstrate noise in function evaluation:")
for i in range(5):
    print("objfun(x0) = %s" % str(rosenbrock_noisy(x0)))
print("")

soln = dfogn.solve(rosenbrock_noisy, x0)

# Display output
print(" *** DFO-GN results *** ")
print("Solution xmin = %s" % str(soln.x))
print("Objective value f(xmin) = %.10g" % soln.f)
print("Needed %g objective evaluations" % soln.nf)
print("Residual vector = %s" % str(soln.resid))
print("Approximate Jacobian = %s" % str(soln.jacobian))
print("Exit flag = %g" % soln.flag)
print(soln.msg)

# Compare with a derivative-based solver
import scipy.optimize as opt

soln = opt.least_squares(rosenbrock_noisy, x0)
Пример #8
0
# http://support.sas.com/documentation/cdl/en/imlug/66112/HTML/default/viewer.htm#imlug_genstatexpls_sect004.htm

from __future__ import print_function
import math
import numpy as np
import dfogn


# Want to solve:
#   x1 + x2 - x1*x2 + 2 = 0
#   x1 * exp(-x2) - 1   = 0
def nonlinear_system(x):
    return np.array(
        [x[0] + x[1] - x[0] * x[1] + 2, x[0] * math.exp(-x[1]) - 1.0])


# Warning: if there are multiple solutions, which one
#          DFO-GN returns will likely depend on x0!
x0 = np.array([0.1, -2.0])

soln = dfogn.solve(nonlinear_system, x0)

# Display output
print(" *** DFO-GN results *** ")
print("Solution xmin = %s" % str(soln.x))
print("Objective value f(xmin) = %.10g" % soln.f)
print("Needed %g objective evaluations" % soln.nf)
print("Residual vector = %s" % str(soln.resid))
print("Exit flag = %g" % soln.flag)
print(soln.msg)
Пример #9
0
# DFO-GN example: minimize the Rosenbrock function (with bounds)
from __future__ import print_function
import numpy as np
import dfogn

# Define the objective function
def rosenbrock(x):
    return np.array([10.0 * (x[1] - x[0] ** 2), 1.0 - x[0]])

# Define the starting point
x0 = np.array([-1.2, 1.0])

# Define optional bound constraints (a <= x <= b)
a = np.array([-10.0, -10.0])
b = np.array([0.9, 0.85])

soln = dfogn.solve(rosenbrock, x0, lower=a, upper=b)

# Display output
print(" *** DFO-GN results *** ")
print("Solution xmin = %s" % str(soln.x))
print("Objective value f(xmin) = %.10g" % soln.f)
print("Needed %g objective evaluations" % soln.nf)
print("Residual vector = %s" % str(soln.resid))
print("Approximate Jacobian = %s" % str(soln.jacobian))
print("Exit flag = %g" % soln.flag)
print(soln.msg)

Пример #10
0
# DFO-GN example: minimize the Rosenbrock function
from __future__ import print_function
import numpy as np
import dfogn


# Define the objective function
def rosenbrock(x):
    return np.array([10.0 * (x[1] - x[0]**2), 1.0 - x[0]])


# Define the starting point
x0 = np.array([-1.2, 1.0])

# For optional extra output details
# import logging
# logging.basicConfig(level=logging.INFO, format='%(message)s')

soln = dfogn.solve(rosenbrock, x0)

# Display output
print(" *** DFO-GN results *** ")
print("Solution xmin = %s" % str(soln.x))
print("Objective value f(xmin) = %.10g" % soln.f)
print("Needed %g objective evaluations" % soln.nf)
print("Residual vector = %s" % str(soln.resid))
print("Approximate Jacobian = %s" % str(soln.jacobian))
print("Exit flag = %g" % soln.flag)
print(soln.msg)
Пример #11
0
# Data fitting example
# https://uk.mathworks.com/help/optim/ug/lsqcurvefit.html#examples

from __future__ import print_function
import numpy as np
import dfogn

tdata = np.array([0.9, 1.5, 13.8, 19.8, 24.1, 28.2, 35.2, 60.3, 74.6, 81.3])
ydata = np.array(
    [455.2, 428.6, 124.1, 67.3, 43.2, 28.1, 13.1, -0.4, -1.3, -1.5])


def prediction_error(x):
    return ydata - x[0] * np.exp(x[1] * tdata)


x0 = np.array([100.0, -1.0])

upper = np.array([1e20, 0.0])

soln = dfogn.solve(prediction_error, x0, upper=upper)

# Display output
print(" *** DFO-GN results *** ")
print("Solution xmin = %s" % str(soln.x))
print("Objective value f(xmin) = %.10g" % soln.f)
print("Needed %g objective evaluations" % soln.nf)
print("Exit flag = %g" % soln.flag)
print(soln.msg)