Vladimiros Minasidis
$$\begin{aligned}
& \underset{x\in R^n}{\text{minimize}}& &f(x;p) \\
& \text{subject to :}& & c_i(x;p) \leq 0, \, i \in \mathcal{I}\\
& & & c_i(x;p) = 0, \, i \in \mathcal{E}
\end{aligned}$$
more information on http://ipython.org/
e.g. to run any command at the system shell, simply prefix it with ! :
!ping www.ntnu.no
Pinging semper26.itea.ntnu.no [129.241.56.116] with 32 bytes of data: Reply from 129.241.56.116: bytes=32 time=35ms TTL=52 Reply from 129.241.56.116: bytes=32 time=39ms TTL=52 Reply from 129.241.56.116: bytes=32 time=27ms TTL=52 Reply from 129.241.56.116: bytes=32 time=58ms TTL=52 Ping statistics for 129.241.56.116: Packets: Sent = 4, Received = 4, Lost = 0 (0% loss), Approximate round trip times in milli-seconds: Minimum = 27ms, Maximum = 58ms, Average = 39ms
A very nice cheatsheet with IPython commands can be found on http://damontallen.github.io/IPython-quick-ref-sheets/
Cell containing Python code:
%pylab inline
from IPython.core.display import HTML
# Generate a HTML5 compatible wav player
def wavPlayer(filepath):
src = """
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Simple Test</title>
</head>
<body>
<audio controls="controls" style="width:600px" >
<source src="%s" type="audio/wav" />
Your browser does not support the audio element.
</audio>
</body>
"""%(filepath)
display(HTML(src))
# Play the file
wavPlayer("files/arribba.wav")
Populating the interactive namespace from numpy and matplotlib
Cell containing text and mathematical expressions:
An illustration of the Discrete Fourier Transform using windowing, to reveal the frequency content of a sound signal.
$$ X_k = \sum_{n=0}^{N-1} x_n e^{-\frac{2 \pi i}{N} k n} \quad \quad k = 0, \dots, N-1 $$
We begin by loading a datafile using SciPy's audio file support:
Let's plot the spectrogramm of the arribba.wav
file:
%matplotlib inline
from scipy.io import wavfile
rate, x = wavfile.read('files/arribba.wav')
from matplotlib import pyplot as plt
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 4))
ax1.plot(x); ax1.set_title('Raw audio signal')
ax2.specgram(x); ax2.set_title('Spectrogram');
import plotly.plotly as py
from plotly.graph_objs import *
py.sign_in("BananaJoe","flye8ny912")
trace1 = Scatter(
x=[1,2,3],
y=[5,6,7],
mode='markers',
marker=Marker(
color=['blue','red','yellow'],
size=[10,20,30]
)
)
data = Data([trace1])
# Make Figure object
fig = Figure(data=data)
# Send to Plotly and show in notebook
py.iplot(fig, filename='random_stuff')
# Importing the neccessary libraries
from numpy import arange
from matplotlib.pyplot import plot
from IPython.html.widgets import interact
# Some IPython magic
%matplotlib inline
%load_ext fortranmagic
Fortran code cell
%%fortran
subroutine f1(x, z)
real, intent(in) :: x
real, intent(out) :: z
z = sin(x)
end subroutine f1
Building module "_fortran_magic_9abff170f71a193b94ebb99b75d11139"... Constructing wrapper function "f1"... z = f1(x) Wrote C/API module "_fortran_magic_9abff170f71a193b94ebb99b75d11139" to file "c:\users\banana~1\appdata\local\temp\tmp_zgrvd\src.win32-2.7\_fortran_magic_9abff170f71a193b94ebb99b75d11139module.c" running build running config_cc unifing config_cc, config, build_clib, build_ext, build commands --compiler options running config_fc unifing config_fc, config, build_clib, build_ext, build commands --fcompiler options running build_src build_src building extension "_fortran_magic_9abff170f71a193b94ebb99b75d11139" sources f2py options: [] f2py:> c:\users\banana~1\appdata\local\temp\tmp_zgrvd\src.win32-2.7\_fortran_magic_9abff170f71a193b94ebb99b75d11139module.c creating c:\users\banana~1\appdata\local\temp\tmp_zgrvd\src.win32-2.7 Reading fortran codes... Reading file 'C:\\Users\\BananaBob\\.ipython\\fortran\\_fortran_magic_9abff170f71a193b94ebb99b75d11139.f90' (format:free) Post-processing... Block: _fortran_magic_9abff170f71a193b94ebb99b75d11139 Block: f1 Post-processing (stage 2)... Building modules... adding 'c:\users\banana~1\appdata\local\temp\tmp_zgrvd\src.win32-2.7\fortranobject.c' to sources. adding 'c:\users\banana~1\appdata\local\temp\tmp_zgrvd\src.win32-2.7' to include_dirs. copying C:\Python27\lib\site-packages\numpy\f2py\src\fortranobject.c -> c:\users\banana~1\appdata\local\temp\tmp_zgrvd\src.win32-2.7 copying C:\Python27\lib\site-packages\numpy\f2py\src\fortranobject.h -> c:\users\banana~1\appdata\local\temp\tmp_zgrvd\src.win32-2.7 build_src: building npy-pkg config files running build_ext No module named msvccompiler in numpy.distutils; trying from distutils customize MSVCCompiler customize MSVCCompiler using build_ext customize GnuFCompiler Could not locate executable g77 Could not locate executable f77 customize IntelVisualFCompiler Could not locate executable ifort Could not locate executable ifl customize AbsoftFCompiler Could not locate executable f90 customize CompaqVisualFCompiler Could not locate executable DF customize IntelItaniumVisualFCompiler Could not locate executable efl customize Gnu95FCompiler Found executable C:\MinGW32-xy\bin\gfortran.exe Found executable C:\MinGW32-xy\bin\gfortran.exe customize G95FCompiler Could not locate executable g95 customize IntelEM64VisualFCompiler customize IntelEM64TFCompiler Could not locate executable efort Could not locate executable efc don't know how to compile Fortran code on platform 'nt' warning: build_ext: f77_compiler=None is not available. building '_fortran_magic_9abff170f71a193b94ebb99b75d11139' extension
UsageError: error: extension '_fortran_magic_9abff170f71a193b94ebb99b75d11139' has Fortran sources but no Fortran compiler found
If you have a F90 compiler you might see some IPython magic interaction:) )
@interact
def ifort(w=5):
xx = arange(0,10,0.1)
yy = [f1(w*x) for x in xx]
plot(xx,yy)
--------------------------------------------------------------------------- NameError Traceback (most recent call last) <ipython-input-26-0e8f2eb39409> in ifort(w) 2 def ifort(w=5): 3 xx = arange(0,10,0.1) ----> 4 yy = [f1(w*x) for x in xx] 5 plot(xx,yy) NameError: global name 'f1' is not defined
Dont get too confident with those or they might bite :)
from IPython.display import YouTubeVideo
YouTubeVideo("ZbspVpA-Ezk")
NBconvert
-- a tool which allows you to convert an .ipynb notebook document file into various static formats.
The currently supported export formats are:
HTML
- renders a full static HTML page.LaTeX
- generates .tex
Latex file. Can automatically generate PDF files from the .tex
.Python
- convert a notebook to an executable Python scriptsAnd the best one is saved for the last
Reveal.js
- generates a Reveal.js HTML slideshow which must be served by an HTTP server.IPython is a suite of tools whose goal it is to cover the whole scientific workflow, from interactive data analysis to publication.
It’s main focus is Python, but people behind the project are ambitious about including other languages. IPython can already magically whizz data back and forth between Python, R, Octave and Julia.
A low-level open-source tool, written in self-contained C++ code, for efficient implementation of algorithms for nonlinear numerical optimization
CasADi efficiently calculates the relevant derivative or ODE/DAE sensitivity information as needed by the NLP solver
Full-featured Python front end, as well as back ends to state-of-the-art codes such as Sundials (CVODES, IDAS and KINSOL), IPOPT, WORHP, SNOPT and KNITRO
Developed by Joel Andersson and Joris Gillis at the Optimization in Engineering Center, OPTEC of the K.U. Leuven
under supervision of Moritz Diehl
CasADi: can evaluate exact (up to machine precision) derivatives very efficiently using Algorithmic Differentiation
Say that we want to obtain the $\nabla_x{F(x)}$ where $F: R^n \rightarrow R^m$
The idea is quite simple:
$F(x)$ is decomposed into sequence of elementary operations (EO). Typical EOs in computer software are $x+y$, $x*y$, $sin(x)$ and $x^y$ .
Create a computational graph (aka information flow diagramm) for those elementary operations
Automatic Differentiation tools then follow the graphs and apply
the chain rule
to these elementary operations and evaluate the derivatives.
For example :
Let's say we want to calculate $\frac{\partial{f}}{\partial{x_1}}$ where $f(x_1,x_2) = x_1x_2 + sin(x_1)$. $f$ can be decomposed into the following elementary operations and those can be differentiated using chain rule:
Elem. operations (EO) | Differentiated EO |
---|---|
$w_1 = x_1$ | $w'_1$ |
$w_2 = x_2$ | $w'_2$ |
$w_3 = w_1 w_2$ | $w'_3 = w'_1 w_2 + w_1 w'_2$ |
$w_4 = \sin(w_1)$ | $w'_4 = \cos(w_1)w'_1$ |
$w_5 = w_3 + w_4$ | $w'_5 = w'_3 + w'_4 $ |
This is how the computational graph looks like:
source http://en.wikipedia.org/wiki/Automatic_differentiation
Since we are interested only in $\frac{\partial{f}}{\partial{x_1}}$ we can start the evaluation of the differentiated elementary operations by setting $w'_1 = 1$ and $w'_2 = 0$
Elem.operations (EO) | Differentiated EO |
---|---|
$w_1 = x_1$ | $w'_1 = 1$ |
$w_2 = x_2$ | $w'_2 = 0$ |
$w_3 = w_1 w_2$ | $w'_3 = w'_1 w_2 + w_1 w'_2 = 1 x_2 + x_1 0 =x_2$ |
$w_4 = \sin(w_1)$ | $w'_4 = \cos(w_1)w'_1 = \cos(x_1) 1$ |
$w_5 = w_3 + w_4$ | $w'_5 = w'_3 + w'_4 = x_2 + \cos(x_1)$ |
The Wikipedia page doesn't have the computational graph for the $\nabla_x{f(x)}$ but these can be generated also from CasADi.
# Load pregenerated images since we haven't seen any CasADi code yet
display(Image(filename='files/fgraph.png'))
display(Image(filename='files/jgraph.png'))
Two different methods for Algorithmic Differentiation:
Both methods have approximately the same computational cost as the one for evaluating $f$
CasADi allows you to create symbolic expressions using syntax similar to e.g.
Symbolic Math Toolbox for MATLAB
or SymPy
Let's look at an example:
# Import CasADi and numpy libraries
import casadi.casadi as cd
import numpy as np
# Declare a symbolic NxM x variable
N = 3
M = 2
x = cd.SX.sym("x",N,M)
print x
[[x_0, x_3], [x_1, x_4], [x_2, x_5]]
# Create a symbolic function y = f(x)
y = x**2 - 2*x
print y
[[(sq(x_0)-(2*x_0)), (sq(x_3)-(2*x_3))], [(sq(x_1)-(2*x_1)), (sq(x_4)-(2*x_4))], [(sq(x_2)-(2*x_2)), (sq(x_5)-(2*x_5))]]
We can get the jacobian of an expression quite easily:
# Get the Jacobian of y w.r.t x
jac = cd.jacobian(y,x)
print jac
[[((x_0+x_0)+-2), 00, 00, 00, 00, 00], [00, ((x_1+x_1)+-2), 00, 00, 00, 00], [00, 00, ((x_2+x_2)+-2), 00, 00, 00], [00, 00, 00, ((x_3+x_3)+-2), 00, 00], [00, 00, 00, 00, ((x_4+x_4)+-2), 00], [00, 00, 00, 00, 00, ((x_5+x_5)+-2)]]
We can perform various scalar operations between symbolic variables and numerical varibles:
# Declare a new symbolic variable and operate on y
z = cd.SX.sym("z",N,M)
print y*cd.sin(z)
[[((sq(x_0)-(2*x_0))*sin(z_0)), ((sq(x_3)-(2*x_3))*sin(z_3))], [((sq(x_1)-(2*x_1))*sin(z_1)), ((sq(x_4)-(2*x_4))*sin(z_4))], [((sq(x_2)-(2*x_2))*sin(z_2)), ((sq(x_5)-(2*x_5))*sin(z_5))]]
# Add a number to the expression y
B3 = cd.DMatrix.ones(N,M)*4 # a dense N-by-M matrix with all numerical fours
print B3
print y + B3
[[4, 4], [4, 4], [4, 4]] [[((sq(x_0)-(2*x_0))+4), ((sq(x_3)-(2*x_3))+4)], [((sq(x_1)-(2*x_1))+4), ((sq(x_4)-(2*x_4))+4)], [((sq(x_2)-(2*x_2))+4), ((sq(x_5)-(2*x_5))+4)]]
# We can also repeat an expression NxM number of times
y_rep = cd.SX.repmat(y + z,2,1)
print y_rep
[[((sq(x_0)-(2*x_0))+z_0), ((sq(x_3)-(2*x_3))+z_3)], [((sq(x_1)-(2*x_1))+z_1), ((sq(x_4)-(2*x_4))+z_4)], [((sq(x_2)-(2*x_2))+z_2), ((sq(x_5)-(2*x_5))+z_5)], [((sq(x_0)-(2*x_0))+z_0), ((sq(x_3)-(2*x_3))+z_3)], [((sq(x_1)-(2*x_1))+z_1), ((sq(x_4)-(2*x_4))+z_4)], [((sq(x_2)-(2*x_2))+z_2), ((sq(x_5)-(2*x_5))+z_5)]]
The symbolic instance SX has a small overhead and it's ideal for scalar operations but it's also limited to just scalar operations:
In order to do matrix operation, need to change the symbolic class SX
to MX
:
e.g. $\sum{x_i^2+x_i}$ will be declared using MX symbolics
n = 6s
m = 1
# MX symbolics
X = cd.MX.sym("X",n,m)
Y = cd.sumAll(X**2 + X)
print Y
(0+mul(ones(6x1, dense)', (sq(X)+X)))
MX symbolics have a large overhead but are more generic. SX
and MX
can be mixed to construct functions that are both fast and generic.
In order to access the full power of CasADi symbolic functions, these need to be declared using "SXFunction" or "MXFunction classes" e.g. :
# Declare MX symbolics
X = cd.MX.sym("X",n,m)
Y = cd.sumAll(X**2 + X)
print "Y = ", Y
Y = (0+mul(ones(6x1, dense)', (sq(X)+X)))
# Declare an MX function using MXFunction class
F = cd.MXFunction(cd.nlpIn(x=X),cd.nlpOut(f=Y))
F.init()
# Define the evaluating point
X0 = 2*cd.DMatrix.ones(n,m)
# Evaluate MX function
print "F[{0}] = ".format(X0), F([X0])
F[[2, 2, 2, 2, 2, 2]] = [DMatrix(36), DMatrix([])]
# Get the jacobian of y wrt x using MX Function object
J = F.jacobian("x","f")
J.init()
# Evaluate the jacobian at x0
J_num = J([X0])
print "J_num = ", J_num
J_num = [DMatrix([[5, 5, 5, 5, 5, 5]]), DMatrix(36), DMatrix([])]
# Calculate the Hessian
H = F.hessian("x","f")
H.init()
print "H = ", H([X0])
H = [DMatrix( [[2, 00, 00, 00, 00, 00], [00, 2, 00, 00, 00, 00], [00, 00, 2, 00, 00, 00], [00, 00, 00, 2, 00, 00], [00, 00, 00, 00, 2, 00], [00, 00, 00, 00, 00, 2]]), DMatrix([5, 5, 5, 5, 5, 5]), DMatrix(36), DMatrix([])]
CasADi features, among others, a backend to a very popular large scale NPL solver IPOPT
.
Parametric NLPs in a CasADi are formulated as follows:
$$\begin{aligned} & \underset{x}{\text{minimize}}& &f(x;p) \\ & \text{subject to :}& & x_{lb} \leq x \leq x_{ub}\\ & & & g_{lb}[i] \leq g_i(x;p) \leq g_{ub}[i], \, \forall i \in \{1,...,k\} \end{aligned}$$ where:
CasADi automatically generates exact Jacobian and exact Hessian information and provides them to the NLP solve if required information.
Lets look at a toy example on how to use CasADi and IPOPT
:
Mathematical problem formulation:
$$\begin{aligned} & \underset{x}{\text{min}}& &f(x;p) = x_1^2 + x_2^2 + x_3^2 \\ & \text{subject to :}& & x_1, x_2, x_3 \geq 0\\ & & & 6x_1 + 3x_2 + 2x_3 - p_1 = 0\\ & & & p_2x_1 + x_2 - x_3 - 1 = 0 \end{aligned}$$
IPython
code:
# Import libraries
import casadi as cd
import numpy as np
import matplotlib.pyplot as plt
# Decision variables
x = cd.SX.sym("x",3)
# Parameters
p = [5.00,1.00]
# Objective function
f = x[0]*x[0] + x[1]*x[1] + x[2]*x[2]
# Concatenate nonlinear constraints
g = cd.vertcat(( \
6*x[0] + 3*x[1] + 2*x[2] - p[0],
p[1]*x[0] + x[1] - x[2] - 1))
# Nonlinear bounds
lbg = [0.00, 0.00]
ubg = [0.00, 0.00]
# Input bounds for the optimization variables
lbx = [0.00, 0.00, 0.00]
ubx = [ cd.inf, cd.inf, cd.inf]
# Initial guess for the decision variables
x0 = [0.15, 0.15, 0.00]
# Create NLP solver
nlp = cd.SXFunction(cd.nlpIn(x=x),cd.nlpOut(f=f, g=g))
solver = cd.NlpSolver("ipopt", nlp)
# Initialize solver
solver.init()
# Pass the bounds and the initial values
solver.setInput( x0, "x0")
solver.setInput(lbx, "lbx")
solver.setInput(ubx, "ubx")
solver.setInput(lbg, "lbg")
solver.setInput(ubg, "ubg")
# Solve NLP
solver.evaluate()
The problem is solved ! Lets retract the information:
# Print the solution
print "----"
print "Minimal cost " , solver.getOutput("f")
print "----"
print "Optimal solution"
print "x = " , solver.output("x").data()
print "----"
---- Minimal cost 0.55102 ---- Optimal solution x = [0.6326530575201198, 0.3877551079678083, 0.020408165487927975] ----
$$\begin{equation} min_u\,J = E\,(\,\textbf{x}(t_0),t_0,\textbf{x}(t_f),t_f\,) + \int_{t_0}^{t_f} \mathcal{L}\,(\,\textbf{x}(t),\textbf{u}(t),t\,)\operatorname{dt} \end{equation}$$ $\textit{subject to }:$ $$\begin{align} \dot{\textbf{x}}(t) = &\, \textbf{f}\,(\textbf{x}(t),\textbf{u}(t),t) &\textit{Dynamic constraints}\\ &\textbf{g}(\textbf{x}(t),\textbf{u}(t),t) \geq \textbf{0} &\textit{Algerbaic path constraints}\\ &\boldsymbol{\phi}\,[\,\textbf{x}(t_0),t_0,\textbf{x}(t_f),t_f\,] = 0& \textit{Boundary conditions} \end{align}$$
In order to access the full power of CasADi symbolic functions, these need to be declared using "SXFunction" or "MXFunction classes" e.g. :