class TripleSpline(object): _coeffs=[ [2 / 3.0, 0, -4, 4], [4 / 3.0, -4, 4, -4 / 3.0]] def __init__(self): self.func1=Polynomial(self._coeffs[0]) self.func2=Polynomial(self._coeffs[1]) self.func1_diff=self.func1.deriv() self.func2_diff=self.func2.deriv() self.diff_order=0 def __call__(self,x,result=None): if x<0: raise ValueError('input value should be nonnegative, not '+str(x)) if result is None: result=np.zeros((self._diff_order+1,),dtype=np.double) if x>=1: result.fill(0) return result if x<=0.5: result[0]=self.func1(x) if self.diff_order>=1: result[1]=self.func1_diff(x) else: result[0]=self.func2(x) if self.diff_order>=1: result[1]=self.func2_diff(x) return result def values(self,x,result): return self.__call__(x, result) def set_diff_order(self, diff_order): if diff_order < 0 or diff_order > 1: raise ValueError("only support _diff_order 0/1, not " + str(diff_order)) self._diff_order = diff_order def get_diff_order(self): return self._diff_order diff_order = property(get_diff_order, set_diff_order)
class TripleSpline(object): _coeffs = [[2 / 3.0, 0, -4, 4], [4 / 3.0, -4, 4, -4 / 3.0]] def __init__(self): self.func1 = Polynomial(self._coeffs[0]) self.func2 = Polynomial(self._coeffs[1]) self.func1_diff = self.func1.deriv() self.func2_diff = self.func2.deriv() self.diff_order = 0 def __call__(self, x, result=None): if x < 0: raise ValueError('input value should be nonnegative, not ' + str(x)) if result is None: result = np.zeros((self._diff_order + 1, ), dtype=np.double) if x >= 1: result.fill(0) return result if x <= 0.5: result[0] = self.func1(x) if self.diff_order >= 1: result[1] = self.func1_diff(x) else: result[0] = self.func2(x) if self.diff_order >= 1: result[1] = self.func2_diff(x) return result def values(self, x, result): return self.__call__(x, result) def set_diff_order(self, diff_order): if diff_order < 0 or diff_order > 1: raise ValueError("only support _diff_order 0/1, not " + str(diff_order)) self._diff_order = diff_order def get_diff_order(self): return self._diff_order diff_order = property(get_diff_order, set_diff_order)
def newton(width: int, height: int, *, p: Polynomial, a: complex, xr: Range = (-2.5, 1), yr: Range = (-1, 1), max_iterations: int = 100) -> (np.array, np.array): """ """ # To make navigation easier we calculate these values x_from, x_to = xr y_from, y_to = yr # Here the actual algorithm starts x = np.linspace(x_from, x_to, width).reshape((1, width)) y = np.linspace(y_from, y_to, height).reshape((height, 1)) z = x + 1j * y # Compute the derivative dp = p.deriv() # Compute roots roots = p.roots() epsilon = 1e-5 # Set the initial conditions a = np.full(z.shape, a) # To keep track in which iteration the point diverged div_time = np.zeros(z.shape, dtype=int) # To keep track on which points did not converge so far m = np.full(a.shape, True, dtype=bool) # To keep track which root each point converged to r = np.full(a.shape, 0, dtype=int) for i in range(max_iterations): z[m] = z[m] - a[m] * p(z[m]) / dp(z[m]) for j, root in enumerate(roots): converged = (np.abs(z.real - root.real) < epsilon) & (np.abs(z.imag - root.imag) < epsilon) m[converged] = False r[converged] = j + 1 div_time[m] = i return div_time, r
class NormPoly(object): def __init__(self, coef, omega): self.h = Poly(coef) self.omega = omega def __call__(self, x): return self.h(self.omega * x) / self.omega def deriv(self): return NormPoly(self.omega * self.h.deriv().coef, self.omega) def degree(self): return self.h.degree() def split(self): return False @property def coef(self): return self.h.coef
def polynomial(self, index, rphase=None, deriv=0, t0=None, time_unit=u.min, out_unit=None, convert=False): """Prediction polynomial set up for times in MJD Parameters ---------- index : int or float index into the polyco table (or MJD for finding closest) rphase : None or 'fraction' or float phase zero point; if None, use the one stored in polyco. (Those are typically large, so one looses some precision.) Can also set 'fraction' to use the stored one modulo 1, which is fine for folding, but breaks cycle count continuity between sets. deriv : int derivative of phase to take (1=frequency, 2=fdot, etc.); default 0 Returns ------- polynomial : Polynomial set up for MJDs between mjd_mid ± span Notes ----- Units for the polynomial are cycles/second**deriv. Taking a derivative outside will be per day (e.g., self.polynomial(1).deriv() gives frequencies in cycles/day) """ out_unit = out_unit or time_unit try: index = index.__index__() except (AttributeError, TypeError): index = self.searchclosest(index) window = np.array([-1, 1]) * self['span'][index] / 2 * u.min polynomial = Polynomial(self['coeff'][index], window.value, window.value) polynomial.coef[1] += self['f0'][index] * 60. if deriv == 0: if rphase is None: polynomial.coef[0] += self['rphase'][index] elif rphase == 'fraction': polynomial.coef[0] += self['rphase'][index] % 1 else: polynomial.coef[0] = rphase else: polynomial = polynomial.deriv(deriv) polynomial.coef /= u.min.to(out_unit)**deriv if t0 is None: dt = 0. * time_unit elif not hasattr(t0, 'jd1') and t0 == 0: dt = (-self['mjd_mid'][index] * u.day).to(time_unit) else: dt = ((t0 - Time(self['mjd_mid'][index], format='mjd', scale='utc')).jd * u.day).to(time_unit) polynomial.domain = (window.to(time_unit) - dt).value if convert: return polynomial.convert() else: return polynomial
a = 0 b = 2 P_n = Polynomial([0, 1, 0, 1]) # 0 + 1*x + 0*x^2 + 1*x^3 n = P_n.degree() # Zero approximation P_n_min = scipy.optimize.fminbound(P_n, a, b, full_output=True)[1] P_n_max = -scipy.optimize.fminbound(-P_n, a, b, full_output=True)[1] Q0 = (P_n_max + P_n_min) / 2 # First approximation alpha1 = (P_n(b) - P_n(a)) / (b - a) r = (P_n.deriv() - Polynomial([alpha1])).roots() d = next(t for t in r if a < t < b) alpha0 = (P_n(a) + P_n(d) - alpha1 * (a + d)) / 2 Q1 = alpha0 + alpha1 * x Q1 = sympy.lambdify(x, Q1) # Second approximation Q2 = P_n(x) - P_n.coef[n] * T(n)((2 * x - (a + b)) / (b - a)) * ((b - a) ** n) / (2 ** (2 * n - 1)) Q2 = sympy.lambdify(x, Q2) X = np.linspace(0, 2, 1000) plt.plot(X, X + X ** 3, color='tab:blue', label='x + x³') plt.axhline(Q0, color='tab:orange', label='Zero approximation') plt.plot(X, Q1(X), color='tab:green', label='First approximation') plt.plot(X, Q2(X), color='tab:red', label='Second approximation')
def polynomial(self, index, rphase=None, deriv=0, t0=None, time_unit=u.min, out_unit=None, convert=False): """Prediction polynomial set up for times in MJD Parameters ---------- index : int or float index into the polyco table (or MJD for finding closest) rphase : None or 'fraction' or 'ignore' or float Phase zero point; if None, use the one stored in polyco. (Those are typically large, so one looses some precision.) Can also set 'fraction' to use the stored one modulo 1, which is fine for folding, but breaks cycle count continuity between sets, 'ignore' for just keeping the value stored in the coefficients, or a value that should replace the zero point. deriv : int derivative of phase to take (1=frequency, 2=fdot, etc.); default 0 Returns ------- polynomial : Polynomial set up for MJDs between mjd_mid +/- span Notes ----- Units for the polynomial are cycles/second**deriv. Taking a derivative outside will be per day (e.g., self.polynomial(1).deriv() gives frequencies in cycles/day) """ out_unit = out_unit or time_unit try: index = index.__index__() except (AttributeError, TypeError): index = self.searchclosest(index) window = np.array([-1, 1]) * self['span'][index] / 2 polynomial = Polynomial(self['coeff'][index], window.value, window.value) polynomial.coef[1] += self['f0'][index].to_value(u.cycle / u.minute) if deriv == 0: if rphase is None: polynomial.coef[0] += self['rphase'][index].value elif rphase == 'fraction': polynomial.coef[0] += self['rphase']['frac'][index].value % 1 elif rphase != 'ignore': polynomial.coef[0] = rphase else: polynomial = polynomial.deriv(deriv) polynomial.coef /= u.min.to(out_unit)**deriv if t0 is not None: dt = Time(t0, format='mjd') - self['mjd_mid'][index] polynomial.domain = (window - dt).to(time_unit).value if convert: return polynomial.convert() else: return polynomial
def polynomial(self, index, rphase=None, deriv=0, t0=None, time_unit=u.min, out_unit=None, convert=False): """Prediction polynomial set up for times in MJD Parameters ---------- index : int or float index into the polyco table (or MJD for finding closest) rphase : None or 'fraction' or float phase zero point; if None, use the one stored in polyco. (Those are typically large, so one looses some precision.) Can also set 'fraction' to use the stored one modulo 1, which is fine for folding, but breaks phase continuity between sets. deriv : int derivative of phase to take (1=frequency, 2=fdot, etc.); default 0 Returns ------- polynomial : Polynomial set up for MJDs between mjd_mid ± span Notes ----- Units for the polynomial are cycles/second**deriv. Taking a derivative outside will be per day (e.g., self.polynomial(1).deriv() gives frequencies in cycles/day) """ out_unit = out_unit or time_unit try: window = np.array([-1, 1]) * self["span"][index] / 2 * u.min except (IndexError, TypeError): # assume index is really a Time or MJD index = self.searchclosest(index) window = np.array([-1, 1]) * self["span"][index] / 2 * u.min polynomial = Polynomial(self["coeff"][index], window.value, window.value) polynomial.coef[1] += self["f0"][index] * 60.0 if deriv == 0: if rphase is None: polynomial.coef[0] += self["rphase"][index] elif rphase == "fraction": polynomial.coef[0] += self["rphase"][index] % 1 else: polynomial.coef[0] = rphase else: polynomial = polynomial.deriv(deriv) polynomial.coef /= u.min.to(out_unit) ** deriv if t0 is None: dt = 0.0 * time_unit elif not hasattr(t0, "jd1") and t0 == 0: dt = (-self["mjd_mid"][index] * u.day).to(time_unit) else: dt = ((t0 - Time(self["mjd_mid"][index], format="mjd", scale="utc")).jd * u.day).to(time_unit) polynomial.domain = (window.to(time_unit) - dt).value if convert: return polynomial.convert() else: return polynomial
b_error = np.append(b_error, [((h_i * Y_correct) / 2.0)]) c_error = np.append(c_error, [((h_i * h_i * d_correct(x)) / 6)]) return f_error, b_error, c_error ################################## fig, ax = plt.subplots() ax.axhline(y=0, color='k') p = Polynomial([2.0, 1.0, -6.0, -2.0, 2.5, 1.0]) data = p.linspace(domain=[-2.4, 1.5]) ax.plot(data[0], data[1], label='Function') p_prime = p.deriv(1) data2 = p_prime.linspace(domain=[-2.4, 1.5]) ax.plot(data2[0], data2[1], label='Derivative') ax.legend() ################################## h = 1 fig, bx = plt.subplots() bx.axhline(y=0, color='k') x = np.linspace(-2.0, 1.3, 50, endpoint=True) y = forward_diff(p, h, x) bx.plot(x, y, label='Forward; h=1') y = backward_diff(p, h, x)
def Phi(P): return 3 * X * P.deriv() - (1 - X**2) * P.deriv(2)
import numpy as np import pandas as pd import matplotlib.pyplot as plt from numpy.polynomial import Polynomial # Define a polynomial named 'f' f = Polynomial([2.0, 1.0, -6.0, -2.0, 2.5, 1.0]) # Define the first derivative of polynomial 'f' named 'f_prime' f_prime = f.deriv(1) # Draw the X-axis plt.axhline(y=0, color='k') # Generate 100 values of x. x = np.linspace(-2.5, 1.6, 100) # Calculate y-values of corresponding x-values of f(x). y = f(x) # Plot the graph of f(x) using x-values and y-values plt.plot(x, y) # Plot the roots of the graph plt.plot(f.roots(), f(f.roots()), 'ro') # Print the roots of the function f(x) print(f.roots()) # Calcuate y-values for corresponding x-values of f'(x). y = f_prime(x)
est_definie_positive(calc(J, res[0]))) print() U00 = np.matrix([-0.5, 0.3, 0.2, -0.1]).T F = generate_F(4) J = generate_jacobienne(4) res2 = Newton_Raphson(F, J, U00, dx, IMAX, EPS) print(" Tests pour N = ", 4) print() print("\t Position initiale = ", U00.T) print() print("\t Nombre d'itérations = ", res2[1]) print() print("\t Position d'équilibre = ", res2[0].T) print() print("\t Correspond au minimum d'énergie :", est_definie_positive(calc(J, res2[0]))) print() p = Polynomial([0., 15 / 8, 0., -70 / 8, 0., 63 / 8]) print("\t Les racines de la dérivée du 5ème polynôme de Legendre = ", p.deriv().roots()) print() print("\t Gradient de E évalué en la position d'équilibre = ", calc(generate_F(4), res2[0]).T) print("Correspond au minimum d'énergie :", est_definie_positive(calc(J, res2[0]))) print()
class ToySGDEnv(AbstractEnv): """ Optimize toy functions with SGD + Momentum. """ def __init__(self, config): super(ToySGDEnv, self).__init__(config) self.n_steps_max = config.get("cutoff", 1000) self.velocity = 0 self.gradient = 0 self.history = [] self.n_dim = None # type: Optional[int] self.objective_function = None self.objective_function_deriv = None self.x_min = None self.f_min = None self.x_cur = None self.f_cur = None self.momentum = 0 # type: Optional[float] self.learning_rate = None # type: Optional[float] self.n_steps = 0 # type: Optional[int] def build_objective_function(self): if self.instance["family"] == "polynomial": order = int(self.instance["order"]) if order != 2: raise NotImplementedError( "Only order 2 is currently implemented for polynomial functions." ) self.n_dim = order coeffs_str = self.instance["coefficients"] coeffs_str = coeffs_str.strip("[]") coeffs = [float(item) for item in coeffs_str.split()] self.objective_function = Polynomial(coef=coeffs) self.objective_function_deriv = self.objective_function.deriv( m=1 ) # lambda x0: derivative(self.objective_function, x0, dx=1.0, n=1, args=(), order=3) self.x_min = -coeffs[1] / ( 2 * coeffs[0] + 1e-10 ) # add small epsilon to avoid numerical instabilities self.f_min = self.objective_function(self.x_min) self.x_cur = self.get_initial_position() else: raise NotImplementedError( "No other function families than polynomial are currently supported." ) def get_initial_position(self): return 0 # np.random.uniform(-5, 5, size=self.n_dim-1) def step(self, action: Union[float, Tuple[float, float]]): done = False info = {} # parse action if np.isscalar(action): log_momentum = 1 log_learning_rate = action elif len(action) == 2: log_learning_rate, log_momentum = action else: raise ValueError self.momentum = 10**log_momentum self.learning_rate = 10**log_learning_rate # SGD + Momentum update self.velocity = self.momentum * self.velocity + self.learning_rate * self.gradient self.x_cur -= self.velocity self.gradient = self.objective_function_deriv(self.x_cur) # State remaining_budget = self.n_steps_max - self.n_steps state = { "remaining_budget": remaining_budget, "gradient": self.gradient, "learning_rate": self.learning_rate, "momentum": self.momentum } # Reward # current function value self.f_cur = self.objective_function(self.x_cur) # log regret log_regret = np.log(np.abs(self.f_min - self.f_cur)) reward = -log_regret self.history.append(self.x_cur) # Stop criterion self.n_steps += 1 if self.n_steps > self.n_steps_max: done = True return state, reward, done, info def reset(self): """ Reset environment Returns ------- np.array Environment state """ super(ToySGDEnv, self).reset_() self.velocity = 0 self.gradient = 0 self.history = [] self.objective_function = None self.objective_function_deriv = None self.x_min = None self.f_min = None self.x_cur = None self.f_cur = None self.momentum = 0 self.learning_rate = 0 self.n_steps = 0 self.build_objective_function() return { "remaining_budget": self.n_steps_max, "gradient": self.gradient, "learning_rate": self.learning_rate, "momentum": self.momentum } def render(self, **kwargs): import matplotlib.pyplot as plt history = np.array(self.history).flatten() X = np.linspace(1.05 * np.amin(history), 1.05 * np.amax(history), 100) Y = self.objective_function(X) fig = plt.figure() ax = fig.add_subplot(111) ax.plot(X, Y) ax.plot(history, self.objective_function(history), marker="x", color="black") ax.plot(self.x_cur, self.objective_function(self.x_cur), marker="x", color="red") plt.show() def close(self): pass