Source code for temo.fit.mutant_factories

import itertools
import numpy as np 
import teqp

[docs] def get_mutant_exponential(model, params, d=None, l=None): """ Build a teqp-based exponential mutant from the model parameters Args: model : The base model that is used to form the mutant params (iterable): iterable that contains the parameters in a flat iterable object d (list, optional): set of exponents on delta, optional l (list, optional): set of exponents on delta in exponential, optional Term is of the form: .. math:: \\alpha^{\\rm r} = \\sum_{i} n_i\\tau^{t_i}\\delta^{d_i}\\exp(-\\delta^{l_i}) where the params populate the n and t. Values of d and l are user-specified, or follow the automatic logic in this function """ depparams = np.array(params[4::]) Ndep = len(depparams)//2 if d is None: Diterator = itertools.cycle([1,1,2,3,4]) d = [next(Diterator) for _ in range(Ndep)] if l is None: Literator = itertools.cycle([2,2,3,1,2,3]) l = [next(Literator) for _ in range(Ndep)] s = { "0":{ "1": { "BIP":{ "type": "GERG", "betaT": params[0], "gammaT": params[1], "betaV": params[2], "gammaV": params[3], "Fij": 1.0 }, "departure":{ "type" : "Exponential", "n" : depparams[0:Ndep].tolist(), "t" : depparams[Ndep::].tolist(), "d" : d, "l" : l } } } } return teqp.build_multifluid_mutant(model, s)
# def get_mutant_polynomial(model, params, d=None): # """ Build a teqp-based mutant from the model parameters with polynomial terms """ # Ndep = len(depparams)//2 # l = [0.0]*Ndep # return get_mutant_exponential(model, params, d=d, l=l)
[docs] def get_mutant_Gaussian(model, params, d=None): r""" Build a teqp-based Gaussian-bell-shaped mutant from the model parameters Args: model : The base model that is used to form the mutant params (iterable): iterable that contains the parameters in a flat iterable object d (list, optional): set of exponents on delta, optional Term is of the form: .. math:: \\alpha^{\\rm r} = \\sum_{i} n_i\\tau^{t_i}\\delta^{d_i}\\exp(-\\eta_i(\delta-\\varepsilon_i)^2-\\beta_i(\\tau-\\gamma_i)^2) where the params populate the variables. Values of d are user-specified as a list, or follow the automatic logic in this function """ depparams = np.array(params[4::]) Nvar = 6 # How many variables are being fit Ndep = len(depparams)//Nvar # How many departure terms assert(Ndep*Nvar == len(depparams)) n,t,eta,beta,gamma,epsilon = [depparams[k*Ndep:(k+1)*Ndep].tolist() for k in range(Nvar)] if d is None: Diterator = itertools.cycle([1,2,3,4]) d = [next(Diterator) for _ in range(Ndep)] l = [0]*Ndep # Build a dictionary in the format that teqp needs. The conversion to # string passed to the C++ interface and upacking into the JSON # structure is handled implicitly in the pybind11 interface. # # The indices have to be strings (sigh...) as mandated # by the JSON standard: https://www.json.org/json-en.html s = { "0":{ "1": { "BIP":{ "type": "GERG", "betaT": params[0], "gammaT": params[1], "betaV": params[2], "gammaV": params[3], "Fij": 1.0 }, "departure":{ "type" : "Gaussian+Exponential", "Npower": 0, "n" : n, "t" : t, "d" : d, "l" : l, "eta": eta, "beta": beta, "gamma": gamma, "epsilon": epsilon } } } } return teqp.build_multifluid_mutant(model, s)
[docs] def chunked_iterable(iterable, size): it = iter(iterable) while True: chunk = tuple(itertools.islice(it, size)) if not chunk: break yield chunk
[docs] def get_mutant_exponentialGaussian(model, params, *, Npoly, Ngaussian, d=None,l=None, Nbg=4, bgindices=None): r""" Build a teqp-based Gaussian+exponential mutant from the model parameters Args: model : The base model that is used to form the mutant params (iterable): iterable that contains the parameters in a flat iterable object Npoly (int): number of polynomial-like terms Ngaussian (int): number of Gaussian terms d (list, optional): set of exponents on delta, optional l (list, optional): set of exponents on delta in exponential, optional Nbg (int, optional): the number of beta and gamma parameters being fit, usually 4 to indicate that all four are being fit bgindices (sequence, optional): the indices {0: betaT, 1: gammaT, 2: betaV, 3: gammaV} to be fit Term is of the form: .. math:: \\alpha^{\\rm r} = \\alpha^{\\rm r}_{\\rm G} + \\alpha^{\\rm r}_{\\rm P} with .. math:: \\alpha^{\\rm r}_{\\rm G} = \\sum_{i} n_i\\tau^{t_i}\\delta^{d_i}\\exp(-\\eta_i(\delta-\\varepsilon_i)^2-\\beta_i(\\tau-\\gamma_i)^2) .. math:: \\alpha^{\\rm r}_{\\rm P} = \\sum_{i} n_i\\tau^{t_i}\\delta^{d_i}\\exp(-\\delta^{l_i}) where the params populate the n and t. Values of d and l are user-specified, or follow the automatic logic in this function """ depparams = np.array(params[Nbg::]) Ndep = Npoly + Ngaussian assert(Ndep*2 + Ngaussian*4 == len(depparams)) if Ndep > 0: n, t = [g for g in chunked_iterable(depparams[0:(Ndep*2)], Ndep)] else: n, t = [],[] if Ngaussian > 0: eta,beta,gamma,epsilon = [[0.0]*Npoly + list(k) for k in chunked_iterable(depparams[(Ndep*2)::], Ngaussian)] else: eta,beta,gamma,epsilon = [0.0]*Npoly,[0.0]*Npoly,[0.0]*Npoly,[0.0]*Npoly if d is None: Diterator = itertools.cycle([1,2,3,4,5,6,4,3]) d = [next(Diterator) for _ in range(Ndep)] if l is None: Literator = itertools.cycle([1,1,1,1,2,2,2,3,3,3]) l = [next(Literator) for _ in range(Ndep)] if Nbg == 4: betaT, gammaT, betaV, gammaV = params[0:Nbg] else: assert(len(bgindices) == Nbg) bgparams = np.array([1.0]*4) bgparams[bgindices] = params[0:Nbg] betaT, gammaT, betaV, gammaV = bgparams # Build a dictionary in the format that teqp needs. The conversion to # string passed to the C++ interface and upacking into the JSON # structure is handled implicitly in the pybind11 interface. # # The indices have to be strings (sigh...) as mandated # by the JSON standard: https://www.json.org/json-en.html s = { "0":{ "1": { "BIP":{ "type": "GERG", "betaT": betaT, "gammaT": gammaT, "betaV": betaV, "gammaV": gammaV, "Fij": 1.0 }, "departure":{ "type" : "Gaussian+Exponential", "Npower": Npoly, "n" : n, "t" : t, "d" : d, "l" : l, "eta": eta, "beta": beta, "gamma": gamma, "epsilon": epsilon } } } } return teqp.build_multifluid_mutant(model, s)
[docs] def get_mutant_doubleexponential(model, params, *, d=None, ld=None): """ Build a teqp-based double-exponential mutant from the model parameters Args: model: the base model that is used to form the mutant params: iterable that contains the parameters in a flat iterable object d: set of exponents on delta, optional ld (list, optional): set of exponents on delta in exponential, optional """ depparams = np.array(params[4::]) Ndep = len(depparams)//5 if Ndep > 0: n, t, gd, lt, gt = [g for g in chunked_iterable(depparams[0:(Ndep*5)], Ndep)] if d is None: Diterator = itertools.cycle([1,2,3,4,5,2,3]) d = [next(Diterator) for _ in range(Ndep)] if ld is None: Literator = itertools.cycle([2,2,2,2,1,1,3,3,3]) ld = [next(Literator) for _ in range(Ndep)] # print(n,t,d,gd,ld,gt,lt) # Build a dictionary in the format that teqp needs. The conversion to # string passed to the C++ interface and upacking into the JSON # structure is handled implicitly in the pybind11 interface. # # The indices have to be strings (sigh...) as mandated # by the JSON standard: https://www.json.org/json-en.html s = { "0":{ "1": { "BIP":{ "type": "GERG", "betaT": params[0], "gammaT": params[1], "betaV": params[2], "gammaV": params[3], "Fij": 1.0 }, "departure":{ "type" : "DoubleExponential", "n" : n, "t" : t, "d" : d, "ld" : ld, "gd" : gd, "lt" : lt, "gt" : gt, } } } } # print(json.dumps(s,indent=1)) return teqp.build_multifluid_mutant(model, s)
[docs] def get_mutant_Gaussian_invariant(model, params, d=None): """ Build a teqp-based Gaussian-bell-shaped mutant from the model parameters and with an invariant reducing function Args: model: the base model that is used to form the mutant params: iterable that contains the parameters in a flat iterable object d: set of exponents on delta, optional """ depparams = np.array(params[4::]) Nvar = 6 # How many variables are being fit Ndep = len(depparams)//Nvar # How many departure terms assert(Ndep*Nvar == len(depparams)) n,t,eta,beta,gamma,epsilon = [depparams[k*Ndep:(k+1)*Ndep].tolist() for k in range(Nvar)] if d is None: Diterator = itertools.cycle([1,2,3,4]) d = [next(Diterator) for _ in range(Ndep)] l = [0]*Ndep # Build a dictionary in the format that teqp needs. The conversion to # string passed to the C++ interface and upacking into the JSON # structure is handled implicitly in the pybind11 interface. # # The indices have to be strings (sigh...) as mandated # by the JSON standard: https://www.json.org/json-en.html s = { "0":{ "1": { "BIP":{ "type": "invariant", "phiT": params[0], "lambdaT": params[1], "phiV": params[2], "lambdaV": params[3], "Fij": 1.0 }, "departure":{ "type" : "Gaussian+Exponential", "Npower": 0, "n" : n, "t" : t, "d" : d, "l" : l, "eta": eta, "beta": beta, "gamma": gamma, "epsilon": epsilon } } } } return teqp.build_multifluid_mutant_invariant(model, s)
[docs] def get_mutant_Chebyshev2D(model, params, *, taumin: float, taumax: float, deltamin: float, deltamax: float, Ntau: int, Ndelta: int): """ Build a teqp-based Gaussian+exponential mutant from the model parameters params: iterable that contains the parameters in a flat iterable object """ depparams = np.array(params[4::]) # Build a dictionary in the format that teqp needs. The conversion to # string passed to the C++ interface and upacking into the JSON # structure is handled implicitly in the pybind11 interface. # # The indices have to be strings (sigh...) as mandated # by the JSON standard: https://www.json.org/json-en.html s = { "0":{ "1": { "BIP":{ "type": "GERG", "betaT": params[0], "gammaT": params[1], "betaV": params[2], "gammaV": params[3], "Fij": 1.0 }, "departure":{ "type" : "Chebyshev2D", "a": depparams.tolist(), "taumin": taumin, "taumax": taumax, "deltamin": deltamin, "deltamax": deltamax, "Ntau": Ntau, "Ndelta": Ndelta } } } } return teqp.build_multifluid_mutant(model, s)