class TestFunctionGenerator(TestCase): def setUp(self): self.generator = FunctionGenerator() def getFunctionLength(self, function): return len(signature(function).parameters) def test_getFunction_returns_function_taking_two_arguments(self): test_func = self.generator.getFunction self.assertTrue(callable(test_func(1, 1))) self.assertEqual(self.getFunctionLength(test_func), 2) def test_getFunction_returns_1_argument_function_given_1(self): test_func = self.generator.getFunction(1, 0) self.assertEqual(self.getFunctionLength(test_func), 1) def test_getFunction_returns_2_argument_function_given_2(self): test_func = self.generator.getFunction(2, 0) self.assertEqual(self.getFunctionLength(test_func), 2) def test_getFunction_raises_ValuEerror_if_not_supplied_with_1_or_2(self): test_func = self.generator.getFunction with self.assertRaises(ValueError): test_func(0, 0) with self.assertRaises(ValueError): test_func(3, 0) with self.assertRaises(ValueError): test_func("anything", 0) def test_getFunction_returns_different_functions_for_some_func_num(self): test_func = self.generator.getFunction self.assertNotEqual(test_func(1, 0)(0), test_func(1, 1)(0)) self.assertNotEqual(test_func(2, 0)(0, 1), test_func(2, 1)(0, 1))
def get_MH_Eval(k): if k not in MH_eval_functions: try: print('trying fast') from function_generator import FunctionGenerator from scipy.special import k0 fast_k0 = FunctionGenerator(k0, 0.0, 1000.0, tol=1e-14, verbose=True) _fast_k0 = fast_k0.get_base_function(check=False) @numba.njit(fastmath=True) def func(sx, sy, tx, ty): dx = tx - sx dy = ty - sy d = np.sqrt(dx * dx + dy * dy) return _fast_k0(k * d) print('fast success') except: @numba.njit(fastmath=True) def func(sx, sy, tx, ty): dx = tx - sx dy = ty - sy d = np.sqrt(dx * dx + dy * dy) return _numba_k0(k * d) MH_eval_functions[k] = func return MH_eval_functions[k]
def __init__(self, c, funcgen_tol, funcgen_order): # c: boundary coordinates, complex self.c = c self.cx = self.c.real.copy() self.cy = self.c.imag.copy() # get some useful boundary-related information self.n = self.c.size self.dt = 2 * np.pi / self.n self.ts = np.arange(self.n) * self.dt self.ik = np.fft.fftfreq(self.n, 1.0 / self.n) # get derivatives of this self.cp = fourier_derivative_1d(f=self.c, d=1, ik=self.ik) self.cpp = fourier_derivative_1d(f=self.c, d=2, ik=self.ik) # get direct fourier evaluator for this self.dirf_c = periodic_interp1d(self.c) self.dirf_cp = periodic_interp1d(self.cp) self.dirf_cpp = periodic_interp1d(self.cpp) # build function generator representations of these functions self.funcgen_c = FunctionGenerator(self.dirf_c, 0, 2 * np.pi, funcgen_tol, n=funcgen_order) self.funcgen_cp = FunctionGenerator(self.dirf_cp, 0, 2 * np.pi, funcgen_tol, n=funcgen_order) self.funcgen_cpp = FunctionGenerator(self.dirf_cpp, 0, 2 * np.pi, funcgen_tol, n=funcgen_order)
def __init__(self, var_wires, dd_mgr, code_generator=None, marduk_vars=None, num_class_vectors=1024, strat_dc=None): """ 'var_wires' is supposed to be a dictionary which maps the string representation of a BDD object to the corresponding signal in the code generator, for all inputs (and their negations) on which the function(s) to be handled by this IrrsopGenerator depend. """ FunctionGenerator.__init__(self, var_wires, dd_mgr, code_generator, marduk_vars, num_class_vectors, strat_dc) self._irrsop_recur = 0
Difference Palindromes vs Susie """ from function_generator import FunctionGenerator from function_indexed_grammar import FunctionIndexedGrammar import time from regex_tree import RegexTree from node import Node # number relations n_relations = 10 size_max = 3 n_functions = 30 generator = FunctionGenerator(n_relations) functions = [] for j in range(5, 70, 5): n_functions = j # for j in range(2, 20, 2): # n_relations = j generator = FunctionGenerator(n_relations) for i in range(0, 200): # 1 function, size_max is 10 functions = [] temp = generator.generate(n_functions, size_max) functions += temp query = generator.get_random_query(functions)
return [rgb_tuple[0], rgb_tuple[1], rgb_tuple[2], 1] if __name__ == '__main__': ''' Cool looking seed values 2, 52, 94, 124396, 123456789, 123454321''' from function_generator import FunctionGenerator as FG unary_ops = { "sin": lambda x: np.sin(x), "cos": lambda x: np.cos(x), "tan": lambda x: np.tan(x), "sinh": lambda x: np.sinh(x), "cosh": lambda x: np.cosh(x), "tanh": lambda x: np.tanh(x), "repr": lambda x: 1 / x, } f_gen = FG(unary_op=unary_ops) f1 = f_gen.generate_function(rand_seed=5) def f(z): ans = f1(z) if np.isfinite(ans): return ans else: return 0 d = Domain(-3, 3, -3, 3) f_p = FunctionPlot(f, domain_colouring, d, 512, 512, grid=False) f_p.save() f_p.plot()
print(' Standard error model means normalization by max(1, value)') print(' Relative error model means normalization by value') for func, disp, error_model in zip(true_funcs, true_func_disp, error_models): print('\n Function is: ', disp) # test scipy function st = time.time() ft = func(xtest) true_func_time = time.time() - st # test approximation function without checks st = time.time() approx_func = FG(func, approx_range[0], approx_range[1], tol, order, error_model=error_model) build_time = time.time() - st fa = approx_func(xtest, check_bounds=False) out = np.empty(n, dtype=fa.dtype) st = time.time() fa = approx_func(xtest, check_bounds=False, out=out) approx_func_time1 = time.time() - st # test approximation function with checks fa = approx_func(xtest, check_bounds=True) st = time.time() fa1 = approx_func(xtest, check_bounds=True) approx_func_time2 = time.time() - st
If N <= 50000, will do a direct sum and compare to this Otherwise, will try to call FMMLIB2D through pyfmmlib2d To compare to If this fails, no comparison for correctness! On my macbook pro N=50,000 takes the direct method ~7s, the FMM <1s (with N_equiv=64, N_cutoff=500) And gives error <5e-14 """ cpu_num = int(os.cpu_count() / 2) helmholtz_k = 5.0 # fast version of Greens Function k0 = FunctionGenerator(scipy.special.k0, a=1e-20, b=1000, tol=1e-8, n=8) k1 = FunctionGenerator(scipy.special.k1, a=1e-20, b=1000, tol=1e-8, n=8) # extract compilable _k0 = k0.get_base_function() _k1 = k1.get_base_function() # Kernel @numba.njit(fastmath=True) def Eval(sx, sy, tx, ty): dx = tx - sx dy = ty - sy d = np.sqrt(dx**2 + dy**2) scale = 1.0 / (2 * np.pi) return _k0(helmholtz_k * d) * scale
def create_continuous_view(plpy, cv_name: str, query: str) -> None: # wrap plpy object db = DatabaseAccess(plpy) # register continuous view, will fail if another view with the same name exists db.continuous_views_insert(cv_name) # extract common table expressions and the actual query (ordering of the ctes does not change) parsed_query = sqlparse.parse(query) query_string, ctes = parse_cte(parsed_query) upper_pipelines = [] # new schema for the view (add to search path allows to use same table names) db.create_schema(f'cv_{cv_name}') db.add_to_search_path(f'cv_{cv_name}') for cte_name, cte in ctes.items(): pipeline_name = f'cv_{cv_name}.{cte_name}' if cte.pipeline_type == PipelineType.STREAM: stream_name = cte.get_stream() # construct the insert function for the stream function_name = construct_insert_function_name(stream_name) # create an auxiliary table for aggregates db.create_stream_pipeline(pipeline_name, cte.query.normalized) # store stream query for later use db.stream_pipelines_insert(cv_name, stream_name, pipeline_name, function_name, cte.query.normalized) # if we group by attributes create an index on the primary keys if len(cte.primary_keys()) > 0: db.create_index(f'cv_{cv_name}_{cte_name}_index', pipeline_name, cte.primary_keys()) # construct the insert function for the stream declarations, body = FunctionGenerator( ).generate_stream_insert_function(f'cv_{cv_name}', stream_name, pipeline_name, cte) # create insert function db.create_insert_function(function_name, stream_name, declarations, body) elif cte.pipeline_type == PipelineType.STATIC: # evaluate static pipelines and save them db.create_static_pipeline(pipeline_name, cte.query.normalized) # create index on static pipeline if len(cte.keys_for_index()) > 0: db.create_index(f'cv_{cv_name}_{cte_name}_index', pipeline_name, cte.keys_for_index()) elif cte.pipeline_type == PipelineType.UPPER: # merge all upper pipelines upper_pipelines.append(cte) # create query from all upper pipelines db.create_upper_pipeline(f'cv.{cv_name}', upper_pipelines, query_string)
from function_generator import FunctionGenerator from function_generator.error_models import relative_error_model from scipy.special import k0, k1 import numpy as np import numba import time """ Generate function generator based versions of k0(x), k1(x). These are good to 1e-14, in relative error out to x=200. Past x=200, they return 0. The absolute value for these values is < 2e-88. """ fk0 = FunctionGenerator(k0, 0, 200, tol=1e-14, n=8, mw=1e-15, error_model=relative_error_model) fk1 = FunctionGenerator(k1, 0, 200, tol=1e-14, n=8, mw=1e-15, error_model=relative_error_model) _fk0 = fk0.get_base_function() _fk1 = fk1.get_base_function()
"tanh": lambda x: np.tanh(x), "repr": lambda x: 1 / complex(x), "exp": lambda x: np.exp(x), "log": lambda x: np.log(x), } binary_ops = { "add": lambda x, y: complex(x) + complex(y), "sub": lambda x, y: complex(x) - complex(y), "mul": lambda x, y: complex(x) * complex(y), "div": lambda x, y: complex(x) / complex(y), } while True: done = False try: f_gen = FG(unary_op=unary_ops, binary_op=binary_ops) f1 = f_gen.generate_function() def f(z): ans = f1(z) if np.isfinite(ans): return ans else: return 0 d = d_c.Domain(-3, 3, -3, 3) f_p = d_c.FunctionPlot(f, d_c.domain_colouring, d, 512, 512,
* the maximum size of the functions * the file where to write the functions * the file where to write the query """ if len(sys.argv) != 6: sys.exit( "Correct usage : python3 function_generator_main.py n_relations " + "n_functions max_size_functions function_file query_file") # Read arguments n_relations = int(sys.argv[1]) n_functions = int(sys.argv[2]) max_size_functions = int(sys.argv[3]) generator = FunctionGenerator(n_relations) lasts = [] f = open(sys.argv[4], "w") # Generate the functions, in prolog format for f_rel in generator.generate(n_functions, max_size_functions): f.write(f_rel.get_prolog()) lasts.append(f_rel.get_last()) f.close() # Generate the query with open(sys.argv[5], "w") as f: f.write(random.choice(lasts) + "\n")
Tests the time it takes to get the emptyness """ import time from function_generator import FunctionGenerator from function_indexed_grammar import FunctionIndexedGrammar import cProfile def get_millis(): return int(round(time.time() * 1000)) current_time = get_millis() total = 0 n_loop = 10 for _ in range(n_loop): generator = FunctionGenerator(5) functions = generator.generate(25, 10) query = generator.get_random_query(functions) # print(functions) # print(query) grammar = FunctionIndexedGrammar(functions, query) # cProfile.run("grammar.is_empty()") print(get_millis() - current_time) total += get_millis() - current_time current_time = get_millis() print("Mean :" + str(total / n_loop))
def _interpolate(self, f): fi = sp.interpolate.InterpolatedUnivariateSpline(self._x, f, k=5) return FunctionGenerator(fi, -1, 1, 1e-14)
If N <= 50000, will do a direct sum and compare to this Otherwise, will try to call FMMLIB2D through pyfmmlib2d To compare to If this fails, no comparison for correctness! On my macbook pro N=50,000 takes the direct method ~7s, the FMM <1s (with N_equiv=64, N_cutoff=500) And gives error <5e-14 """ cpu_num = int(os.cpu_count()/2) helmholtz_k = 5.0 # fast version of Greens Function k0 = FunctionGenerator(scipy.special.k0, a=1e-20, b=1000, tol=1e-12, n=12) # extract compilable _k0 = k0.get_base_function() # Modified Helmholtz Kernel @numba.njit(fastmath=True) def Modified_Helmholtz_Eval(sx, sy, tx, ty): dx = tx-sx dy = ty-sy d = np.sqrt(dx**2 + dy**2) scale = 1.0/(2*np.pi) return _k0(helmholtz_k*d)*scale N_source = 1000*20 N_target = 1000*2000 test = 'circle' # clustered or circle or uniform
def __init__(self, gf, fs, ifs, h, spread_width, kernel_kwargs=None, funcgen_tol=1e-10, inline_core=True): """ Backend class for re-usable 'ewald' sum grid evaluation for reusability, the grid must have the same h and the ewald sum must use the same spread width gf: numba callable greens function, gf(r) fs: Fourier symbol for operator, fs(kx, ky) ifs: Inverse Fourier symbol for operator, ifs(kx, ky) h: grid spacing spread_width: width to do spreading on for Laplace, 15 gives ~7 digits 20 gives ~10 digits can't seem to do much better than that, right now kernel_kwargs: dict of arguments to be passed to gf, fs, ifs, tsgf functions funcgen_tol: tolerance for function generator representation of functions used in interior spread funciton. can't seem to beat ~10 digits overall now, so no real reason to do more than that inline_core: whether to inline the function generator functions into the compiled ewald functions (inlining may speed things up but slows compilation time, sometimes dramatically) """ self.kernel_kwargs = {} if kernel_kwargs is None else kernel_kwargs self.gf = lambda r: gf(r, **self.kernel_kwargs) self.fourier_symbol = lambda kx, ky: fs(kx, ky, **self.kernel_kwargs) self.inverse_fourier_symbol = lambda kx, ky: ifs( kx, ky, **self.kernel_kwargs) self.h = h self.spread_width = spread_width self.funcgen_tol = funcgen_tol self.inline_core = inline_core # construct mollifier self.mollifier = SlepianMollifier(2 * self.spread_width) self.ssw = self.spread_width * self.h # screened greens function _excisor_gf = lambda d: excisor(d, 0.0, self.ssw, self.mollifier ) * self.gf(d) try: self.ex_funcgen = FunctionGenerator(_excisor_gf, 0.0, self.ssw, tol=self.funcgen_tol, inline_core=self.inline_core) self.excisor_gf = self.ex_funcgen.get_base_function(check=False) except: raise Exception( 'Failed constructing FunctionGenerator function for mollifier') # construct differential operator applied to residual of screened greens function _sn = 4 * self.spread_width _sgv = np.linspace(0, 4 * self.ssw, _sn, endpoint=False) _sgx, _sgy = np.meshgrid(_sgv, _sgv, indexing='ij') _skv = np.fft.fftfreq(_sn, self.h / (2 * np.pi)) _skx, _sky = np.meshgrid(_skv, _skv, indexing='ij') _slap = self.fourier_symbol(_skx, _sky) pt = np.array([[2 * self.ssw], [2 * self.ssw]]) targ = np.row_stack([_sgx.ravel(), _sgy.ravel()]) u = gf_apply(self.gf, pt[0], pt[1], targ[0], targ[1], np.array([ 1.0, ])).reshape(_sn, _sn) u[_sn // 2, _sn // 2] = 0.0 dist = np.hypot(_sgx - 2 * self.ssw, _sgy - 2 * self.ssw) dec1 = excisor(dist, 0.0, self.ssw, self.mollifier) dec2 = excisor(dist, self.ssw, 2 * self.ssw, self.mollifier) uf = u * (1 - dec1) * dec2 self.do_ufd = ifft2(fft2(uf) * _slap).real # get an interpolater for this _ax = np.linspace(np.pi, 1.5 * np.pi, 1000) _ay = np.repeat(np.pi, _ax.size) _ar = np.linspace(0, self.ssw, _ax.size) _fh = fft2(self.do_ufd) / (_sn * _sn) out = finufft.nufft2d2(_ax, _ay, _fh, isign=1, eps=1e-15, modeord=1) self._do_ufd_interpolater = sp.interpolate.InterpolatedUnivariateSpline( _ar, out.real, k=5, bbox=[0, self.ssw], ext=1) try: self.do_ufd_funcgen = FunctionGenerator( self._do_ufd_interpolater, 0.0, self.ssw, tol=self.funcgen_tol, inline_core=self.inline_core) self.do_ufd_interpolater = self.do_ufd_funcgen.get_base_function( check=False) except: raise Exception( 'Failed constructing FunctionGenerator function for laplacian of greens function times mollifier' )
class ScalarGridBackend(object): def __init__(self, gf, fs, ifs, h, spread_width, kernel_kwargs=None, funcgen_tol=1e-10, inline_core=True): """ Backend class for re-usable 'ewald' sum grid evaluation for reusability, the grid must have the same h and the ewald sum must use the same spread width gf: numba callable greens function, gf(r) fs: Fourier symbol for operator, fs(kx, ky) ifs: Inverse Fourier symbol for operator, ifs(kx, ky) h: grid spacing spread_width: width to do spreading on for Laplace, 15 gives ~7 digits 20 gives ~10 digits can't seem to do much better than that, right now kernel_kwargs: dict of arguments to be passed to gf, fs, ifs, tsgf functions funcgen_tol: tolerance for function generator representation of functions used in interior spread funciton. can't seem to beat ~10 digits overall now, so no real reason to do more than that inline_core: whether to inline the function generator functions into the compiled ewald functions (inlining may speed things up but slows compilation time, sometimes dramatically) """ self.kernel_kwargs = {} if kernel_kwargs is None else kernel_kwargs self.gf = lambda r: gf(r, **self.kernel_kwargs) self.fourier_symbol = lambda kx, ky: fs(kx, ky, **self.kernel_kwargs) self.inverse_fourier_symbol = lambda kx, ky: ifs( kx, ky, **self.kernel_kwargs) self.h = h self.spread_width = spread_width self.funcgen_tol = funcgen_tol self.inline_core = inline_core # construct mollifier self.mollifier = SlepianMollifier(2 * self.spread_width) self.ssw = self.spread_width * self.h # screened greens function _excisor_gf = lambda d: excisor(d, 0.0, self.ssw, self.mollifier ) * self.gf(d) try: self.ex_funcgen = FunctionGenerator(_excisor_gf, 0.0, self.ssw, tol=self.funcgen_tol, inline_core=self.inline_core) self.excisor_gf = self.ex_funcgen.get_base_function(check=False) except: raise Exception( 'Failed constructing FunctionGenerator function for mollifier') # construct differential operator applied to residual of screened greens function _sn = 4 * self.spread_width _sgv = np.linspace(0, 4 * self.ssw, _sn, endpoint=False) _sgx, _sgy = np.meshgrid(_sgv, _sgv, indexing='ij') _skv = np.fft.fftfreq(_sn, self.h / (2 * np.pi)) _skx, _sky = np.meshgrid(_skv, _skv, indexing='ij') _slap = self.fourier_symbol(_skx, _sky) pt = np.array([[2 * self.ssw], [2 * self.ssw]]) targ = np.row_stack([_sgx.ravel(), _sgy.ravel()]) u = gf_apply(self.gf, pt[0], pt[1], targ[0], targ[1], np.array([ 1.0, ])).reshape(_sn, _sn) u[_sn // 2, _sn // 2] = 0.0 dist = np.hypot(_sgx - 2 * self.ssw, _sgy - 2 * self.ssw) dec1 = excisor(dist, 0.0, self.ssw, self.mollifier) dec2 = excisor(dist, self.ssw, 2 * self.ssw, self.mollifier) uf = u * (1 - dec1) * dec2 self.do_ufd = ifft2(fft2(uf) * _slap).real # get an interpolater for this _ax = np.linspace(np.pi, 1.5 * np.pi, 1000) _ay = np.repeat(np.pi, _ax.size) _ar = np.linspace(0, self.ssw, _ax.size) _fh = fft2(self.do_ufd) / (_sn * _sn) out = finufft.nufft2d2(_ax, _ay, _fh, isign=1, eps=1e-15, modeord=1) self._do_ufd_interpolater = sp.interpolate.InterpolatedUnivariateSpline( _ar, out.real, k=5, bbox=[0, self.ssw], ext=1) try: self.do_ufd_funcgen = FunctionGenerator( self._do_ufd_interpolater, 0.0, self.ssw, tol=self.funcgen_tol, inline_core=self.inline_core) self.do_ufd_interpolater = self.do_ufd_funcgen.get_base_function( check=False) except: raise Exception( 'Failed constructing FunctionGenerator function for laplacian of greens function times mollifier' ) def initialize_periodic(self): """ Define periodic local evaluator function """ _ex_gf = self.excisor_gf _do_ufd = self.do_ufd_interpolater h = self.h sw = self.spread_width @numba.njit(parallel=True, fastmath=True) def ewald_local_periodic(source, charge, xv, yv): xmin = xv[0] ymin = yv[0] shape = (charge.size, 2 * sw + 2, 2 * sw + 2) fwork1 = np.empty(shape, dtype=numba.float64) fwork2 = np.empty(shape, dtype=numba.float64) iwork1 = np.empty(shape, dtype=numba.int64) iwork2 = np.empty(shape, dtype=numba.int64) bwork1 = np.zeros(shape, dtype=numba.boolean) sh = (xv.size, yv.size) op = np.zeros(sh, dtype=numba.float64) u = np.zeros_like(op) N = source.shape[1] nx = xv.size ny = yv.size md = sw * h for i in numba.prange(N): sx = source[0, i] sy = source[1, i] ch = charge[i] indx = int((sx - xmin) // h) indy = int((sy - ymin) // h) lxi = indx - sw - 1 lyi = indy - sw - 1 hxi = indx + sw + 1 hyi = indy + sw + 1 for ixind, ix in enumerate(range(lxi, hxi)): ixm = ix % nx xvh = xmin + ix * h for iyind, iy in enumerate(range(lyi, hyi)): iym = iy % ny yvh = ymin + iy * h d = np.hypot(xvh - sx, yvh - sy) if d <= md: fwork1[i, ixind, iyind] = _ex_gf(d) * ch fwork2[i, ixind, iyind] = _do_ufd(d) * ch iwork1[i, ixind, iyind] = ixm iwork2[i, ixind, iyind] = iym bwork1[i, ixind, iyind] = True for i in range(N): for ixind in range(2 * sw + 2): for iyind in range(2 * sw + 2): if bwork1[i, ixind, iyind]: ixm = iwork1[i, ixind, iyind] iym = iwork2[i, ixind, iyind] u[ixm, iym] += fwork1[i, ixind, iyind] op[ixm, iym] += fwork2[i, ixind, iyind] return op, u self.ewald_local_periodic = ewald_local_periodic def initialize_freespace(self): """ Define periodic local evaluator function """ _ex_gf = self.excisor_gf _do_ufd = self.do_ufd_interpolater h = self.h sw = self.spread_width @numba.njit(parallel=True) def ewald_local_freespace(source, charge, xv, yv, op, u, op_na): xmin = xv[0] ymin = yv[0] shape = (charge.size, 2 * sw + 2, 2 * sw + 2) fwork1 = np.empty(shape, dtype=numba.float64) fwork2 = np.empty(shape, dtype=numba.float64) iwork1 = np.empty(shape, dtype=numba.int64) iwork2 = np.empty(shape, dtype=numba.int64) bwork1 = np.zeros(shape, dtype=numba.boolean) N = source.shape[1] nx = xv.size ny = yv.size md = sw * h for i in numba.prange(N): sx = source[0, i] sy = source[1, i] ch = charge[i] indx = int((sx - xmin) // h) indy = int((sy - ymin) // h) lxi = indx - sw - 1 lyi = indy - sw - 1 hxi = indx + sw + 1 hyi = indy + sw + 1 for ixind, ix in enumerate(range(lxi, hxi)): xvh = xmin + ix * h for iyind, iy in enumerate(range(lyi, hyi)): yvh = ymin + iy * h d = np.hypot(xvh - sx, yvh - sy) if d <= md: fwork1[i, ixind, iyind] = _ex_gf(d) * ch fwork2[i, ixind, iyind] = _do_ufd(d) * ch iwork1[i, ixind, iyind] = ix + op_na iwork2[i, ixind, iyind] = iy + op_na bwork1[i, ixind, iyind] = True for i in range(N): for ixind in range(2 * sw + 2): for iyind in range(2 * sw + 2): if bwork1[i, ixind, iyind]: ix = iwork1[i, ixind, iyind] iy = iwork2[i, ixind, iyind] u[ix, iy] += fwork1[i, ixind, iyind] op[ix, iy] += fwork2[i, ixind, iyind] self.ewald_local_freespace = ewald_local_freespace def check_periodic(self, xv, yv): self.check_either(xv, yv) def check_freespace(self, xv, yv): self.check_either(xv, yv) if xv.size != yv.size: raise Exception('Square grid required for freespace evaluator') def check_either(self, xv, yv): xh = xv[1] - xv[0] if np.abs(xh - self.h) > 1e-15: raise Exception('h of input xv vector not same as backend') yh = yv[1] - yv[0] if np.abs(yh - self.h) > 1e-15: raise Exception('h of input yv vector not same as backend')
def experiment(seed, initial_num, max_iter, acq_name): # 定義域は[0, 1] でgrid_num分割して候補点を生成 grid_num = 200 X = np.c_[np.linspace(0, 1, grid_num)] y = np.c_[forrester(X)] # 乱数シード値の固定(重要: 実験が再現できるようにするため) np.random.seed(seed) random.seed(seed) # 訓練データの作成 index_list = range(grid_num) train_index = random.sample(index_list, initial_num) X_train = X[train_index] y_train = y[train_index] # カーネルの設定 ''' :param lentgh_scale: RBFカーネルのバンド幅 :param variance: 分散パラメータ :param noise_var: 観測誤差 ''' noise_var = 1.0e-4 # プロットや結果保存のためのディレクトリをつくる (実験結果をいつでも復元できるようにいろんなログはとっておいて損はない) result_dir_path = "./"+acq_name+"/seed_"+str(seed)+"/" _ = subprocess.check_call(["mkdir", "-p", result_dir_path]) # ベイズ最適化 for iter in range(max_iter): if iter % 5 == 0: # 5イテレーションごとにハイパラ更新 # ハイパラ最適化 hyper_grid = 100 length_scale, variance = opt(X_train, y_train, hyper_grid) kernel = RBFkernel(length_scale, variance, noise_var) pred_mean, pred_var = kernel.predict(kernel, X, X_train, y_train) # 結果のプロット #predict_plot(X, y, X_train, y_train, pred_mean, pred_var, result_dir_path + acq_name + "_iter" + str(iter) + ".pdf") if acq_name == 'ucb': alpha = ucb(X_train, pred_mean, pred_var) if acq_name == 'mes': F = FunctionGenerator(seed, length_scale, variance, noise_var, X) func_num = 5 f = F.gen(X_train, y_train, func_num=func_num) # RFMからサンプリングされた関数のプロット # rfm_fn_plot(X, y, f, pred_mean, pred_var, "rfm_plot_" + str(iter) + ".pdf") y_star = f.max() print(y_star) next_index = np.argmax(alpha) #データの保存 save_data_pass = result_dir_path+"iter_"+str(iter)+"/" _ = subprocess.check_call(["mkdir", "-p", save_data_pass]) save_data_lists = [X, y, pred_mean, pred_var, alpha] data_name_lists = ["X", "y", "pred_mean", "pred_var", "alpha"] for i in range(len(data_name_lists)): with open(save_data_pass+data_name_lists[i]+".pickle",'wb') as f: pickle.dump(save_data_lists[i], f) # 訓練データの更新 X_next = X[next_index] y_next = y[next_index] X_train = np.vstack((X_train, X_next)) y_train = np.vstack((y_train, y_next))
def setUp(self): self.generator = FunctionGenerator()
def getFunctions(self, num_func): generator = FunctionGenerator() func_list = [] for _ in range(num_func): func_list.append(generator.getFunction(1, randint(0, 20))) return func_list
def zeta(x): """ Returns I1(x)/I0(x), using standarad funcitons for small |x| And asymptotic expansions (see doc for __Iv) for |x| """ return __Iv(x, 1)/__Iv(x, 0) if np.abs(x) > 20 \ else sp.special.iv(1, x)/sp.special.iv(0, x) # construct vectorized version of zeta zetas = np.vectorize(zeta) # construct an approximation of zeta(x)/x using FunctionGenerator, good on [-1,1] # note the strange bounds: this just avoids the removable singularity at 0 _zeta_over_x = FunctionGenerator(lambda x: zetas(x) / x, -1.001, 1.0, tol=1e-14) # construct a function for zeta(x)/x, good on [-Inf, Inf] def zeta_over_x(x): if np.abs(x) > 1: return zeta(x) / x else: return _zeta_over_x(x) # returns the Bingham Function, Eq ... def bingham_function(x): return 0.5 * (1.0 + zeta(x))
cpu_num = int(os.cpu_count() / 2) numba.config.NUMBA_NUM_THREADS = cpu_num import mkl mkl.set_num_threads(cpu_num) # Greens Function def GF(x): Y = yn(1, x) S3 = struve(-3, x) S2 = struve(-2, x) return (x * (Y - S3) - 4 * S2) / x**2 # fast version of Greens Function gf = FunctionGenerator(GF, a=1e-30, b=1000, tol=1e-12) # extract compilable _gf = gf.get_base_function() # Kernel @numba.njit(fastmath=True) def Kernel(sx, sy, tx, ty): dx = tx - sx dy = ty - sy d = np.sqrt(dx**2 + dy**2) return _gf(d) N_source = 1000 * 10 N_target = 1000 * 10