title | author | date | output | ||||
---|---|---|---|---|---|---|---|
Funz from Python |
Y. Richet |
30/07/2021 |
|
# requirements
import sys
import subprocess
import os
import json
libs = ["math","numpy","matplotlib"]
for l in libs:
if l not in sys.modules.keys():
subprocess.check_call([sys.executable, "-m", "pip", "install", l])
Just use the standard 'pip install Funz' command:
# install Funz if needed
if "Funz" not in sys.modules.keys():
subprocess.check_call([sys.executable, "-m", "pip", "install", "Funz"])
import Funz
Funz.installDesign("GradientDescent") # required for later example
Once installed, Funz Python module allows to access almost all features of Funz through command line.
It is mandatory to launch calculation back-end which will be used to perform parametric calculations, later.
Note: it is also possible to start this back-end on another computer/server/cluster, which will be usable by all computer which IP is declared in 'calculator.xml' file (by default, it just contains "127.0.0.1" local address).
# This will start 5 calculators, in background
calcs = Funz.startCalculators(5)
You can check all available calculators from your computer using:
Funz.Grid()
This main feature of Funz allows to evaluate a parametric model, built from parameterized files (like following ' branin.py' file including variables starting with a reserved character '?'):
with open(os.path.join(Funz.FUNZ_HOME,"samples","branin.py"), 'r') as f:
print(f.read())
Note: usually, a parametric model is based on heavy simulation software, not callable easily like a function. In practice, this example with a Python function may be easier to evaluate directly, of course.
Once calculators (eg. started from back-end) are available, you can launch this parametric model for given variables (x1 and x2) values:
import numpy
Funz.Run(model = "Python",
input_files = os.path.join(Funz.FUNZ_HOME,"samples","branin.py"),
input_variables = {'x1':numpy.arange(0,1,0.1),'x2':numpy.arange(0,1,0.1)},
all_combinations = True,
output_expressions = "z")
... get and display results (using the 'Funz._Last_run' global variable, if 'Run()' was not assigned):
r = Funz._Last_run()['results']
for s in r.keys(): print(s+": "+str(r[s][:10])+" ...") # print head
... or plot model response surface :
# Response surface of previous Run
import matplotlib.pyplot
fig = matplotlib.pyplot.figure()
import mpl_toolkits.mplot3d
ax = mpl_toolkits.mplot3d.Axes3D(fig)
fig.add_axes(ax)
ax.scatter(Funz._Last_run()['results']['x1'],Funz._Last_run()['results']['x2'],Funz._Last_run()['results']['z'])
matplotlib.pyplot.show()
The other main feature of Funz consists in applying an algorithm/analysis on a function:
import math
def branin(x):
x1 = numpy.array(x['x1'])*15-5
x2 = numpy.array(x['x2'])*15
return ((x2 - 5/(4*math.pi**2)*(x1**2) + 5/math.pi*x1 -6 )**2 + 10*(1-1/(8*math.pi))*numpy.cos(x1) +10).tolist()
Funz.Design(fun = branin,
design = "GradientDescent", options = {'max_iterations':15},
input_variables = {'x1':"[0,1]",'x2':"[0,1]"})
which solves the targeted issue (here an optimization):
x = numpy.arange(0,1.01,1/40)
xx = numpy.array([[x1, x2] for x1 in x for x2 in x]).reshape(-1,2)
xx = {'x1':xx[:,0].tolist(),'x2':xx[:,1].tolist()}
import matplotlib.pyplot
matplotlib.pyplot.contour(x,x,numpy.array(branin(xx)).reshape(-1,41))
d = Funz._Last_design()['results']
argmin = json.loads(d['analysis.argmin'])
matplotlib.pyplot.plot(argmin[0],argmin[1],color='red')
These two main features may also be coupled to apply an algorithm directly on the parametric model:
Funz.RunDesign(model = "Python",
input_files = os.path.join(Funz.FUNZ_HOME,"samples","branin.py"),
design = "GradientDescent", design_options = {'max_iterations':15},
input_variables = {'x1':"[0,1]",'x2':"[0,1]"},
output_expressions = "z")
... and returns the algorithm analysis:
x = numpy.arange(0,1.01,1/40)
xx = numpy.array([[x1, x2] for x1 in x for x2 in x]).reshape(-1,2)
xx = {'x1':xx[:,0].tolist(),'x2':xx[:,1].tolist()}
import matplotlib.pyplot
fig = matplotlib.pyplot.figure()
import mpl_toolkits.mplot3d
ax = mpl_toolkits.mplot3d.Axes3D(fig)
fig.add_axes(ax)
ax.scatter(xx['x1'],xx['x2'],numpy.array(branin(xx)),color='gray')
rd = Funz._Last_rundesign()['results']
# plot all evaluated points
ax.scatter(rd['x1'],rd['x2'],rd['z'],color='blue')
# plot min/argmin searched
argmin = json.loads(rd['analysis.argmin'][0])
min = json.loads(rd['analysis.min'][0])
ax.scatter([argmin[0]],[argmin[1]],[min],color='red')
matplotlib.pyplot.show()
Once finished, it is recommended to shutdown calculators in back-end:
# This will stop the 5 calculators started earlier
Funz.stopCalculators(calcs)
After a fresh install of Funz, is is commonplace to add useful models or algorithms. Such a plugin is a 'zip' file, which may be installed locally, or directly from GitHub Fuz repository.
Get already installed models:
Funz.installedModels()
Get available models from GitHub:
Funz.availableModels()
Install a new model from GitHub:
Funz.installModel("Modelica")
... or from a local file:
Funz.install_fileModel("plugin-Modelica.zip")
Get already installed models:
Funz.installedDesigns()
Get available models from GitHub:
Funz.availableDesigns()
Install a new model from GitHub:
Funz.installDesign("Brent")
... or from a local file:
Funz.install_fileDesign("algorthm-Brent.zip")