def _compute_eps(lam): session = WolframLanguageSession(wlpath) session.evaluate( wlexpr(''' randomgamma[alpha_, beta_, gamma_, samples_] := RandomVariate[GammaDistribution[alpha, beta, gamma, 0], samples]; ''')) random_gamma = session.function(wlexpr('randomgamma')) session.evaluate( wlexpr(''' integrant[exponents_, beta_, dimension_, clippingbound_, lam_, r_, q_] := Mean[NIntegrate[ (Sin[x]^(dimension-2)*Gamma[dimension/2]/(Sqrt[Pi]*Gamma[(dimension-1)/2]))*(((1-q)*(1-q+ q*Exp[(r^exponents-(r^2+clippingbound^2-2*r*clippingbound*Cos[x])^(exponents/2))/beta])^(lam)) +(q*(1-q+q*Exp[((r^2+clippingbound^2+2*r*clippingbound*Cos[x])^(exponents/2)-r^exponents)/beta])^(lam))),{x,0,Pi} ]]; ''')) integrant_moment = session.function(wlexpr('integrant')) samples = random_gamma(FLAGS.dimension / FLAGS.exponents, beta**(1 / FLAGS.exponents), FLAGS.exponents, FLAGS.num_samples) moment = integrant_moment(FLAGS.exponents, beta, FLAGS.dimension, FLAGS.clippingbound, lam, samples, FLAGS.q) eps = (FLAGS.T * mp.log(moment) + mp.log(1 / FLAGS.delta)) / lam session.terminate() return eps
def compute_dp(lam): session = WolframLanguageSession(wlpath) session.evaluate( wlexpr(''' randomgamma[alpha_, beta_, gamma_, samples_] := RandomVariate[GammaDistribution[alpha, beta, gamma, 0], samples]; ''')) random_gamma = session.function(wlexpr('randomgamma')) session.evaluate( wlexpr(''' integrant[p_, beta_, d_, Delta_, lam_, r_] := Mean[NIntegrate[ Sin[x]^(d-2)*Gamma[d/2]/(Sqrt[Pi]*Gamma[(d-1)/2])*(0.99+0.01*Exp[(r^p-(r^2+Delta^2+2*r*Delta*Cos[x])^(p/2))/beta])^(-lam),{x,0,Pi} ]]; ''')) integrant_moment = session.function(wlexpr('integrant')) samples = random_gamma(d / p, beta**(1 / p), p, num_samples) # print(samples) moment = integrant_moment(p, beta, d, Delta, lam, samples) # print(moment) eps = (T * mp.log(moment) + mp.log(1 / delta)) / lam session.terminate() return eps
class Engine: def __init__(self): config = get_config() wolfram_path = config.get("DEFAULT", "WOLFRAM_PATH") self.image_path = os.path.join(os.getcwd(), 'static', 'city') atexit.register(self.cleanup) if wolfram_path is None or len(wolfram_path) == 0: self.session = WolframLanguageSession() print("Wolfram Engine session opened on default path.") else: self.session = WolframLanguageSession(wolfram_path) print(f"Wolfram Engine session opened on '{wolfram_path}'.") self._define_wolfram_functions() def _define_wolfram_functions(self): self.get_weather = self.session.function(wlexpr('<|"Temperature" -> WeatherData[#, "Temperature"], "WindSpeed" ->WeatherData[#, "WindSpeed"],"Pressure"-> WeatherData[#,"Pressure"]|>&')) self.get_city = self.session.function(wlexpr('Module[{cities}, cities = TextCases[#, "City"];If[Length[cities] > 0, First[cities], ""]]&')) def test(self): self.check_session() return self.session.evaluate(wlexpr('NIntegrate[Sin[Sin[x]], {x, 0, 2}]')) def get_city_image(self, name): # search existing images if present lname = str.lower(name) for file in os.listdir(self.image_path): if file.endswith(".png"): if file == f"{lname}.png": print(f"Found image for '{name}' in cache.") return # get the image via websearch graphic = self.session.evaluate(wlexpr(f'WebImageSearch["{name}", "Images", MaxItems -> 1][[1]]')) path = os.path.join(self.image_path, f"{lname}.png") png_export = wl.Export(path, graphic, "PNG") return self.session.evaluate(png_export) def get_weather_info(self, text) -> dict: """ Returns a dictionary with some weather info for the first city found in the given (natural language) text. :param text: any text """ self.check_session() if text is None or len(text) == 0: return {} city = self.get_city(text) if city is None or len(city) == 0: return {} print(f"Found city: {city}") found = self.get_weather(city) if isinstance(found, dict) and found["Temperature"].args[0] != "NotAvailable": self.get_city_image(city) return { "Input": text, "City": city, "Temperature": found["Temperature"].args[0], "WindSpeed": found["WindSpeed"].args[0], "Pressure": found["Pressure"].args[0], "Info": self.session.evaluate(wlexpr(f'TextSentences[WikipediaData["{city}"]][[;; 5]]'))[0] } else: return {} def check_session(self): if self.session is None: raise Exception("The Engine is not present.") # noinspection PyBroadException def cleanup(self): """ Note that there is no way to catch the SIGKILL and stop the engine gracefully if this happens. :return: """ try: if self.session is not None: self.session.stop() print("Wolfram Engine stopped.") except Exception: pass
class WolframSampler: def __init__(self): """A wrapper to generateExperiments.wls Written as a class so the Wolfram session is only once at __init__ time. """ self.session = WolframLanguageSession(kernel=wolfram_kernel_path) self.session.evaluate('<<./capture/generate/randomSampling.wls') self.session.evaluate('<<./capture/generate/enumerativeSampling.wls') self._randomlySample = self.session.function('generateExperiments') self._enumerativelySample = self.session.function( 'generateEnumerations') def randomlySample(self, reagentVectors, oldReagents=None, nExpt=96, maxMolarity=9., finalVolume=500.): """Randomly sample possible experiments in the convex hull of concentration space defined by the reagentVectors Runs Josh's Mathematica function called `generateExperiments` defined in `randomSampling.wls` Shadows default arguments set at Wolfram level. Currently does not expose processVaules argument. :param reagentVectors: a dictionary of vector representations of reagents living in species-concentration space :param nExpt: the number of samples to draw :param maxMolarity: the maximum concentration of any species: defines a hypercube bounding the convex hull :param finalVolume: a scalar to act on the concentrations to convert to desired volume :return: a dictionary mapping: {reagents => list(volumes)} where list(volumes) has length nExpt :raises TypeError: since Mathematica will fail silently on incorrect types """ ## Easy mathematica debugging (get an error, uncomment here for vectors) #print("new", reagentVectors, '\n') #print('to be removed', oldReagents, '\n') if not isinstance(reagentVectors, dict): raise TypeError('reagentVectors must be dict, got {}'.format( type(reagentVectors))) if not isinstance(nExpt, int): raise TypeError('nExpt must be int, got {}'.format(type(nExpt))) if not isinstance(maxMolarity, float): raise TypeError('maxMolarity must be float, got {}'.format( type(maxMolarity))) if not isinstance(finalVolume, float): raise TypeError('finalVolume must be float, got {}'.format( type(finalVolume))) if oldReagents: if not isinstance(oldReagents, dict): raise TypeError('oldReagents must be dict, got {}'.format( type(oldReagents))) if oldReagents: result = self._randomlySample(reagentVectors, oldReagents, nExpt, maxMolarity, finalVolume) # result = self._randomlySample(oldReagents, reagentVectors, nExpt, maxMolarity, finalVolume) if "Volume of remaining space is zero" in result: raise ValueError( 'New reagents define a convex hull that is covered by that of old reagents.' ) else: result = self._randomlySample(reagentVectors, nExpt, maxMolarity, finalVolume) return result def enumerativelySample(self, reagentVectors, uniqueChemNames, deltaV=10., maxMolarity=9., finalVolume=500.): """Enumeratively sample possible experiments in the convex hull of concentration space defined by the reagentVectors Runs Josh's Mathematica function called `achievableGrid` defined in `enumerativeSampling.wls` Shadows default arguments set at Wolfram level. :param reagentVectors: a dictionary of vector representations of reagents living in species-concentration space :param uniqueChemNames: list of chemicals making up the reagents :param maxMolarity: the maximum concentration of any species: defines a hypercube bounding the convex hull :param deltaV: the spacing of reagent volumes that define the spacing of the grid in concentration space :param finalVolume: a scalar to act on the concentration points to convert to desired volume :return: a dictionary mapping: {reagents => list(volumes)} :raises TypeError: since Mathematica will fail silently on incorrect types """ if not isinstance(reagentVectors, dict): raise TypeError('reagentVectors must be dict, got {}'.format( type(reagentVectors))) if not isinstance(uniqueChemNames, list): raise TypeError('uniqueChemNames must be a list, got {}'.format( type(uniqueChemNames))) if not isinstance(maxMolarity, float): raise TypeError('maxMolarity must be float, got {}'.format( type(maxMolarity))) if not isinstance(deltaV, float): raise TypeError('deltaV must be float, got {}'.format( type(deltaV))) if not isinstance(finalVolume, float): raise TypeError('finalVolume must be float, got {}'.format( type(finalVolume))) return self._enumerativelySample(reagentVectors, uniqueChemNames, deltaV, maxMolarity, finalVolume) def terminate(self): """Kill the session thread""" self.session.terminate()