def create_variants(self, n, desc, category, constructor): def assign_2nd_alg(archipelago, algo): if category == 'rings': for island in archipelago.topology.every_other_island(): island.algorithm = algo elif hasattr(archipelago.topology, 'endpoints'): for island in archipelago.topology.endpoints: island.algorithm = algo elif isinstance(archipelago.topology, FullyConnectedTopology): for island in islice(archipelago.topology.islands, None, None, 2): island.algorithm = algo return archipelago def assign_algs(archipelago, algos): ''' Evenly partitions and assigns algorithms to islands. ''' for island,algo in zip(archipelago.topology.islands, cycle(algos)): island.algorithm = algo g = self.generations self.new_topology( desc='{}, de'.format(desc), category=category, algorithms=['de'], archipelago=Archipelago(constructor(de(gen=g),n))) self.new_topology( desc='{}, de1220'.format(desc), category=category, algorithms=['de1220'], archipelago=Archipelago(constructor(de1220(gen=g),n))) self.new_topology( desc='{}, sade'.format(desc), category=category, algorithms=['sade'], archipelago=Archipelago(constructor(sade(gen=g),n))) self.new_topology( desc='{}, bee_colony'.format(desc), category=category, algorithms=['bee_colony'], archipelago=Archipelago(constructor(bee_colony(gen=g),n))) # de + nelder mead combo self.new_topology( desc='{}, de+nelder mead'.format(desc), category=category, algorithms=['de','neldermead'], archipelago=assign_2nd_alg(Archipelago(constructor(de(gen=g),n)), self.make_nelder_mead())) # de + praxis combo self.new_topology( desc='{}, de+praxis'.format(desc), category=category, algorithms=['de','praxis'], archipelago=assign_2nd_alg(Archipelago(constructor(de(gen=g),n)), self.make_praxis())) # de + sade combo self.new_topology( desc='{}, de+sade'.format(desc), category=category, algorithms=['de','sade'], archipelago=assign_2nd_alg(Archipelago(constructor(de(gen=g),n)), sade(gen=g)))
def user_defined_problem(): prob = pg.problem(sphere_function(3)) print(prob) algo = pg.algorithm(pg.bee_colony(gen = 200, limit = 20)) pop = pg.population(prob, 10) pop = algo.evolve(pop) print(pop.champion_f) print(pop)
def user_defined_problem(): prob = pg.problem(sphere_function(3)) print(prob) algo = pg.algorithm(pg.bee_colony(gen=200, limit=20)) pop = pg.population(prob, 10) pop = algo.evolve(pop) print(pop.champion_f) print(pop)
def test_pagmo(joint_likelihood_bn090217206_nai): pagmo = GlobalMinimization("PAGMO") minuit = LocalMinimization("minuit") algo = pygmo.algorithm(pygmo.bee_colony(gen=100)) pagmo.setup(islands=4, population_size=20, evolution_cycles=1, second_minimization=minuit, algorithm=algo) do_analysis(joint_likelihood_bn090217206_nai, pagmo)
archi.wait_check() print(archi) import pygmo as pg # The user-defined problem udp = pg.schwefel(dim=20) # The pygmo problem prob = pg.problem(udp) # For a number of generation based algorithms we can use a similar script to run and average over 25 runs. udas = [ pg.sade(gen=500), pg.de(gen=500), pg.de1220(gen=500), pg.pso(gen=500), pg.bee_colony(gen=250, limit=20) ] for uda in udas: logs = [] for i in range(25): algo = pg.algorithm(uda) algo.set_verbosity(1) # regulates both screen and log verbosity pop = pg.population(prob, 20) pop = algo.evolve(pop) logs.append(algo.extract(type(uda)).get_log()) logs = np.array(logs) avg_log = np.average(logs, 0) plt.plot(avg_log[:, 1], avg_log[:, 2] - 418.9829 * 20, label=algo.get_name())
def chi_optimize(method='pso', parallel=False, N_ind=100, N_gen=30, iset=0, show_results=False, dir='../data/', file_name='chi_fit'): # Load experimental data N_set = 2 ca_data = svu.loaddata('../data/herzog_data.pkl')[0] po_data = svu.loaddata('../data/fit_po.pkl')[0] lr_data = svu.loaddata('../data/fit_lra.pkl')[0] # Get boundary dictionary bounds_dict = models.model_bounds(model='chi') # Save effective bounds and scaling bounds, scaling = bounds_for_exploration(bounds_dict, normalized=False) # Prepare model parameters c0 = 5.0 # c0 = 15.0 params = np.asarray(np.r_[po_data[[0, 1, 0, 2, 3]], lr_data[[0, 1]], c0, iset]) args = (params, ca_data) #----------------------------------------------------------------------------------------------------------- # Effective evolution #----------------------------------------------------------------------------------------------------------- # Size parameters # N_var = problem_dimension(model='lra') N_individuals = N_ind N_var = problem_dimension(model='chi') N_generations = N_gen * N_var # Tolerances FTOL = 1e-6 XTOL = 1e-6 # prob = pg.problem(fit_problem('lra',args)) prob = pg.problem(fit_problem('chi', args)) # Optimization # NOTE: We keep each algorithm self contained here because different setting of parameters for evolution are # needed depending on the chose algorithm if method == 'pso': algo = pg.algorithm( pg.pso(gen=N_generations, variant=5, neighb_type=4, max_vel=0.8)) elif method == 'bee': algo = pg.algorithm(pg.bee_colony(gen=N_generations, limit=2)) elif method == 'de': algo = pg.algorithm(pg.de(gen=N_generations, ftol=FTOL, tol=XTOL)) # Single-node optimation to run on local machine / laptop # N_individuals = 100 # N_generations = 40 * N_var # verbosity = 20 if not parallel: verbosity = 20 algo.set_verbosity(verbosity) pop = pg.population(prob, size=N_individuals) pop = algo.evolve(pop) best_fitness = pop.get_f()[pop.best_idx()] print(best_fitness) x_rescaled = rescale_vector(pop.champion_x, model='chi', normalized=True, bounds=bounds, scaling=scaling) # Show results of fit if show_results: astro = models.Astrocyte( model='chi', d1=po_data[0], d2=po_data[1], d3=po_data[0], d5=po_data[2], a2=po_data[3], c0=c0, c1=0.5, rl=0.1, Ker=0.1, rc=lr_data[0], ver=lr_data[1], vbeta=x_rescaled[0], vdelta=x_rescaled[1], v3k=x_rescaled[2], r5p=x_rescaled[3], ICs=np.asarray([x_rescaled[6], x_rescaled[4], x_rescaled[5]])) options = su.solver_opts(t0=ca_data['time'][iset][0], tfin=ca_data['time'][iset][-1], dt=1e-4, atol=1e-8, rtol=1e-6, method="gsl_msadams") astro.integrate(algparams=options, normalized=True) ca_trace = ca_data['smoothed'][iset] plt.plot(ca_data['time'][0], ca_trace, 'k-', astro.sol['ts'], astro.sol['ca'], 'r-') plt.show() else: # Parallel version to run on cluster N_evolutions = 100 N_islands = 10 # Initiate optimization algo = pg.algorithm( pg.pso(gen=N_generations, variant=5, neighb_type=4, max_vel=0.8)) archi = pg.archipelago(n=N_islands, algo=algo, prob=prob, pop_size=N_individuals) archi.evolve(N_evolutions) archi.wait() imin = np.argmin(archi.get_champions_f()) x_rescaled = rescale_vector(archi.get_champions_x()[imin], model='chi', normalized=True, bounds=bounds, scaling=scaling) print archi.get_champions_f()[imin] print x_rescaled svu.savedata([x_rescaled], dir + file_name + '.pkl')
def popen_optimize(method='de-simple'): # Load experimental data p_open = svu.loaddata('../data/p_open.pkl')[0] # Get boundary dictionary # bounds_dict = models.model_bounds(model='lra') bounds_dict = models.model_bounds(model='lra2') # Save effective bounds and scaling bounds, scaling = bounds_for_exploration(bounds_dict, normalized=False) args = (p_open['ca'], p_open['ip3']) #----------------------------------------------------------------------------------------------------------- # Effective evolution #----------------------------------------------------------------------------------------------------------- # Size parameters # N_var = problem_dimension(model='lra') N_var = problem_dimension(model='lra2') N_individuals = 100 N_generations = 500 * N_var N_evolutions = 50 # Tolerances FTOL = 1e-3 XTOL = 1e-3 # prob = pg.problem(fit_problem('lra',args)) prob = pg.problem(fit_problem('lra2', args)) # Optimization # NOTE: We keep each algorithm self contained here because different setting of parameters for evolution are # needed depending on the chose algorithm if method == 'de-simple': ##----------------- # # Single node ##----------------- # algo = pg.algorithm(pg.de(gen=N_generations,F=0.75,CR=0.9,variant=6,ftol=FTOL,xtol=XTOL)) # algo = pg.algorithm(pg.de(gen=N_generations, ftol=1e-12, tol=1e-6)) # algo = pg.algorithm(pg.pso(gen=N_generations)) algo = pg.algorithm(pg.bee_colony(gen=N_generations)) algo.set_verbosity(100) pop = pg.population(prob, size=N_individuals) pop = algo.evolve(pop) best_fitness = pop.get_f()[pop.best_idx()] print(best_fitness) x_rescaled = rescale_vector(pop.champion_x, model='lra2', normalized=True, bounds=bounds, scaling=scaling) astro = models.Astrocyte(model='lra2', d1=x_rescaled[0], d2=x_rescaled[1], d5=x_rescaled[2], a2=x_rescaled[3]) astro.popen(p_open['ca'][0], 1.0) po_ca = astro.po astro.popen(0.25, p_open['ip3'][0]) po_ip3 = astro.po print x_rescaled svu.savedata([x_rescaled], '../data/fit_po.pkl') plt.semilogx(p_open['ca'][0], p_open['ca'][1], 'k-', p_open['ca'][0], po_ca, 'ro', p_open['ip3'][0], p_open['ip3'][1], 'm-', p_open['ip3'][0], po_ip3, 'bo') plt.show()
n_grad - 1, str(grad_res[-1, :]), expr_eval(f, grad_res[-1, :]))) #%% Применяем Pygmo с covariance Matrix Evolutionary Strategy (CMA-ES) class Ackley_function: def fitness(self, x): return [expr_eval(f, x)] def get_bounds(self): return ([x[0], y[0]], [x[-1], y[-1]]) prob = pg.problem(Ackley_function()) algo = pg.algorithm(pg.bee_colony(gen=gen, seed=42)) algo.set_verbosity(100) pop = pg.population(prob, n_pop) pop = algo.evolve(pop) n_pygmo = pop.get_x().shape[0] print(pop) #%% Визуализация для функции двух аргументов через линии уровня print("Градиентный Спуск: {:f}, Pygmo: {:f}".format( expr_eval(f, grad_res[-1, :]), pop.champion_f[0])) n_levels = 15 # число линий уровня markersize = 5
def __call__(self, function): scanner_options = { 'sade': dict(gen=self.gen, variant=self.variant, variant_adptv=self.variant_adptv, ftol=self.ftol, xtol=self.xtol, memory=self.memory, seed=self.seed), 'gaco': dict(gen=self.gen, ker=self.ker, q=self.q, oracle=self.oracle, acc=self.acc, threshold=self.threshold, n_gen_mark=self.n_gen_mark, impstop=self.impstop, evalstop=self.evalstop, focus=self.focus, memory=self.memory, seed=self.seed), 'maco': dict(gen=self.gen, ker=self.ker, q=self.q, threshold=self.threshold, n_gen_mark=self.n_gen_mark, evalstop=self.evalstop, focus=self.focus, memory=self.memory, seed=self.seed), 'gwo': dict(gen=self.gen, seed=self.seed), 'bee_colony': dict(gen=self.gen, limit=self.limit, seed=self.seed), 'de': dict(gen=self.gen, F=self.F, CR=self.CR, variant=self.variant, ftol=self.ftol, xtol=self.xtol, seed=self.seed), 'sea': dict(gen=self.gen, seed=self.seed), 'sga': dict(gen=self.gen, cr=self.cr, eta_c=self.eta_c, m=self.m, param_m=self.param_m, param_s=self.param_s, crossover=self.crossover, mutation=self.mutation, selection=self.selection, seed=self.seed), 'de1220': dict(gen=self.gen, allowed_variants=self.allowed_variants, variant_adptv=self.variant_adptv, ftol=self.ftol, xtol=self.xtol, memory=self.memory, seed=self.seed), 'cmaes': dict(gen=self.gen, cc=self.cc, cs=self.cs, c1=self.c1, cmu=self.cmu, sigma0=self.sigma0, ftol=self.ftol, xtol=self.xtol, memory=self.memory, force_bounds=self.force_bounds, seed=self.seed), 'moead': dict(gen=self.gen, weight_generation=self.weight_generation, decomposition=self.decomposition, neighbours=self.neighbours, CR=self.CR, F=self.F, eta_m=self.eta_m, realb=self.realb, limit=self.limit, preserve_diversity=self.preserve_diversity, seed=self.seed), 'compass_search': dict(max_fevals=self.max_fevals, start_range=self.start_range, stop_range=self.stop_range, reduction_coeff=self.reduction_coeff), 'simulated_annealing': dict(Ts=self.Ts, Tf=self.Tf, n_T_adj=self.n_T_adj, n_range_adj=self.n_range_adj, bin_size=self.bin_size, start_range=self.start_range, seed=self.seed), 'pso': dict(gen=self.gen, omega=self.omega, eta1=self.eta1, eta2=self.eta2, max_vel=self.max_vel, variant=self.variant, neighb_type=self.neighb_type, neighb_param=self.neighb_param, memory=self.memory, seed=self.seed), 'pso_gen': dict(gen=self.gen, omega=self.omega, eta1=self.eta1, eta2=self.eta2, max_vel=self.max_vel, variant=self.variant, neighb_type=self.neighb_type, neighb_param=self.neighb_param, memory=self.memory, seed=self.seed), 'nsga2': dict(gen=self.gen, cr=self.cr, eta_c=self.eta_c, m=self.m, eta_m=self.eta_m, seed=self.seed), 'nspso': dict(gen=self.gen, omega=self.omega, c1=self.c1, c2=self.c2, chi=self.chi, v_coeff=self.v_coeff, leader_selection_range=self.leader_selection_range, diversity_mechanism=self.diversity_mechanism, memory=self.memory, seed=self.seed), 'mbh': dict(algo=self.algo, stop=self.stop, perturb=self.perturb, seed=self.seed), 'cstrs_self_adaptive': dict(iters=self.iters, algo=self.algo, seed=self.seed), 'ihs': dict(gen=self.gen, phmcr=self.phmcr, ppar_min=self.ppar_min, ppar_max=self.ppar_max, bw_min=self.bw_min, bw_max=self.bw_max, seed=self.seed), 'xnes': dict(gen=self.gen, eta_mu=self.eta_mu, eta_sigma=self.eta_sigma, eta_b=self.eta_b, sigma0=self.sigma0, ftol=self.ftol, xtol=self.xtol, memory=self.memory, force_bounds=self.force_bounds, seed=self.seed) } if self.log_data: xl = [] yl = [] log_data = self.log_data # class interf_function: def __init__(self, dim): self.dim = dim def fitness(self, x): x = np.expand_dims(x, axis=0) y = function(x) # x = x[0] y = y.tolist() if log_data: xl.append(x) yl.append(y) # print (x, y[0]) return y[0] if function.is_differentiable(): def gradient(self, x): x = np.expand_dims(x, axis=0) g = function(x) g = g.tolist() return g[0] def get_bounds(self): lb = [] ub = [] bounds = function.get_ranges() # warning # check for infinities for i in range(len(bounds)): lb.append(bounds[i, 0]) ub.append(bounds[i, 1]) r = (np.array(lb), np.array(ub)) return r # I need to call pygmo functions directly prob = pg.problem(interf_function(function)) # print (prob.get_thread_safety()) if self.scanner == "sade": # I need a dictionary with algorithms and options algo = pg.algorithm(pg.sade(**scanner_options[self.scanner])) elif self.scanner == "gaco": algo = pg.algorithm(pg.gaco(**scanner_options[self.scanner])) # elif self.scanner == "maco": # is not implemented though in webpage # looks it is # algo = pg.algorithm(pg.maco(**scanner_options[self.scanner])) elif self.scanner == "gwo": algo = pg.algorithm(pg.gwo(**scanner_options[self.scanner])) elif self.scanner == "bee_colony": algo = pg.algorithm(pg.bee_colony(**scanner_options[self.scanner])) elif self.scanner == "de": algo = pg.algorithm(pg.de(**scanner_options[self.scanner])) elif self.scanner == "sea": algo = pg.algorithm(pg.sea(**scanner_options[self.scanner])) elif self.scanner == "sga": algo = pg.algorithm(pg.sga(**scanner_options[self.scanner])) elif self.scanner == "de1220": algo = pg.algorithm(pg.de1220(**scanner_options[self.scanner])) elif self.scanner == "cmaes": algo = pg.algorithm(pg.cmaes(**scanner_options[self.scanner])) # elif self.scanner == "moead": #multiobjective algorithm # algo = pg.algorithm(pg.moead(**scanner_options[self.scanner])) elif self.scanner == "compass_search": algo = pg.algorithm( pg.compass_search(**scanner_options[self.scanner])) elif self.scanner == 'simulated_annealing': algo = pg.algorithm( pg.simulated_annealing(**scanner_options[self.scanner])) elif self.scanner == 'pso': algo = pg.algorithm(pg.pso(**scanner_options[self.scanner])) elif self.scanner == 'pso_gen': algo = pg.algorithm(pg.pso_gen(**scanner_options[self.scanner])) # elif self.scanner == 'nsga2': #multiobjective algorithm # algo = pg.algorithm(pg.nsga2(**scanner_options[self.scanner])) # elif self.scanner == 'nspso': is not implemented though in webpage # looks it is # algo = pg.algorithm(pg.nspso(**scanner_options[self.scanner])) elif self.scanner == 'mbh': if scanner_options[self.scanner]['algo'] == 'de': algo = pg.algorithm( pg.mbh(pg.algorithm(pg.de(**scanner_options['de'])))) # elif self.scanner == 'ihs': #does not work # algo = pg.algorithm(ihs(**scanner_options[self.scanner])) # elif self.scanner == 'xnes': #does not work # algo = pg.algorithm(xnes(**scanner_options[self.scanner])) # uda = algo.extract(xnes) else: print( 'The ' + self.scanner + ' algorithm is not implemented. The ' 'list of algorithms available is', algorithms) sys.exit() # add verbosing flag if self.verbose > 1: algo.set_verbosity(self.verbose) pop = pg.population(prob, self.size) if self.verbose > 9: print('prob', prob) opt = algo.evolve(pop) if self.verbose > 9: print('algo', algo) # best_x = np.expand_dims(opt.champion_x, axis=0) # best_fitness = np.expand_dims(opt.get_f()[opt.best_idx()], axis=0) best_x = np.expand_dims(opt.champion_x, axis=0) best_fitness = np.expand_dims(opt.champion_f, axis=0) if self.verbose > 0: print('best fit:', best_x, best_fitness) if self.log_data: x = np.squeeze(xl, axis=(1, )) y = np.squeeze(yl, axis=(2, )) if self.log_data: return (x, y) else: return (best_x, best_fitness)
# !/usr/bin/env python # -*- coding:utf-8 -*- # Author: [email protected] import pygmo as pg class UdpFunction: def __init__(self, dim): self.dim = dim def fitness(self, x): return [sum(x * x)] def get_bounds(self): return ([-1] * self.dim, [1] * self.dim) def get_name(self): return "Udp Function!" algo = pg.algorithm(pg.bee_colony(gen=20, limit=20)) prob = pg.problem(UdpFunction(3)) pop = pg.population(prob, 10) pop = algo.evolve(pop) print(prob) print(pop.champion_f) print(pop.champion_x)
def create_variants(self, n, desc, category, constructor): def assign_2nd_alg(archipelago, algo): if category == 'rings': for island in archipelago.topology.every_other_island(): island.algorithm = algo elif hasattr(archipelago.topology, 'endpoints'): for island in archipelago.topology.endpoints: island.algorithm = algo elif isinstance(archipelago.topology, FullyConnectedTopology): for island in islice(archipelago.topology.islands, None, None, 2): island.algorithm = algo return archipelago def assign_algs(archipelago, algos): ''' Evenly partitions and assigns algorithms to islands. ''' for island,algo in zip(archipelago.topology.islands, cycle(algos)): island.algorithm = algo g = self.generations self.new_topology( desc='{}, de'.format(desc), category=category, algorithms=['de'], archipelago=Archipelago(constructor(de(gen=g),n))) self.new_topology( desc='{}, de1220'.format(desc), category=category, algorithms=['de1220'], archipelago=Archipelago(constructor(de1220(gen=g),n))) self.new_topology( desc='{}, sade'.format(desc), category=category, algorithms=['sade'], archipelago=Archipelago(constructor(sade(gen=g),n))) self.new_topology( desc='{}, ihs'.format(desc), category=category, algorithms=['ihs'], archipelago=Archipelago(constructor(ihs(gen=g),n))) self.new_topology( desc='{}, pso'.format(desc), category=category, algorithms=['pso'], archipelago=Archipelago(constructor(pso(gen=g),n))) self.new_topology( desc='{}, pso_gen'.format(desc), category=category, algorithms=['pso_gen'], archipelago=Archipelago(constructor(pso_gen(gen=g),n))) # self.new_topology( # desc='{}, simulated_annealing'.format(desc), # category=category, # algorithms=['simulated_annealing'], # archipelago=Archipelago(constructor(simulated_annealing(),n))) self.new_topology( desc='{}, bee_colony'.format(desc), category=category, algorithms=['bee_colony'], archipelago=Archipelago(constructor(bee_colony(gen=g),n))) self.new_topology( desc='{}, cmaes'.format(desc), category=category, algorithms=['cmaes'], archipelago=Archipelago(constructor(cmaes(gen=g),n))) self.new_topology( desc='{}, nsga2'.format(desc), category=category, algorithms=['nsga2'], archipelago=Archipelago(constructor(nsga2(gen=g),n))) self.new_topology( desc='{}, xnes'.format(desc), category=category, algorithms=['xnes'], archipelago=Archipelago(constructor(xnes(gen=g),n))) # de + nelder mead combo self.new_topology( desc='{}, de+nelder mead'.format(desc), category=category, algorithms=['de','neldermead'], archipelago=assign_2nd_alg(Archipelago(constructor(de(gen=g),n)), self.make_nelder_mead())) # de + praxis combo self.new_topology( desc='{}, de+praxis'.format(desc), category=category, algorithms=['de','praxis'], archipelago=assign_2nd_alg(Archipelago(constructor(de(gen=g),n)), self.make_praxis())) # de + nsga2 combo self.new_topology( desc='{}, de+nsga2'.format(desc), category=category, algorithms=['de','nsga2'], archipelago=assign_2nd_alg(Archipelago(constructor(de(gen=g),n)), nsga2(gen=g))) # de + de1220 combo self.new_topology( desc='{}, de+de1220'.format(desc), category=category, algorithms=['de','de1220'], archipelago=assign_2nd_alg(Archipelago(constructor(de(gen=g),n)), de1220(gen=g))) # de + sade combo self.new_topology( desc='{}, de+sade'.format(desc), category=category, algorithms=['de','sade'], archipelago=assign_2nd_alg(Archipelago(constructor(de(gen=g),n)), sade(gen=g))) # de + pso combo self.new_topology( desc='{}, de+pso'.format(desc), category=category, algorithms=['de','pso'], archipelago=assign_2nd_alg(Archipelago(constructor(de(gen=g),n)), pso(gen=g))) # extra configurations for fully connected topology if constructor is self.factory.createFullyConnected: self.new_topology( desc='{}, de+pso+praxis'.format(desc), category=category, algorithms=['de','pso','praxis'], archipelago=assign_algs(Archipelago(constructor(de(gen=g),n)), (de(gen=g), pso(gen=g), self.make_praxis()))) self.new_topology( desc='{}, de+pso+praxis+nsga2'.format(desc), category=category, algorithms=['de','pso','praxis','nsga2'], archipelago=assign_algs(Archipelago(constructor(de(gen=g),n)), (de(gen=g), pso(gen=g), self.make_praxis(), nsga2(gen=g)))) self.new_topology( desc='{}, de+pso+praxis+cmaes'.format(desc), category=category, algorithms=['de','pso','praxis','cmaes'], archipelago=assign_algs(Archipelago(constructor(de(gen=g),n)), (de(gen=g), pso(gen=g), self.make_praxis(), cmaes(gen=g)))) self.new_topology( desc='{}, de+pso+praxis+xnes'.format(desc), category=category, algorithms=['de','pso','praxis','xnes'], archipelago=assign_algs(Archipelago(constructor(de(gen=g),n)), (de(gen=g), pso(gen=g), self.make_praxis(), xnes(gen=g))))