Commit 054051ce authored by Matthieu Boileau's avatar Matthieu Boileau

Update tp6/exercice2

plot moved to external function
parent 1fb66d71
Pipeline #4003 passed with stages
in 1 minute and 59 seconds
CC = g++
CC_FLAGS = -std=c++11 -Wall
EXEC_NAME = main
OBJ_FILES = main.o modele.o modele_sir.o modele_seir.o solveur_temps.o euler_ex.o rk2.o graphe.o
all: $(EXEC_NAME)
clean:
rm -f $(EXEC_NAME) $(OBJ_FILES)
$(EXEC_NAME) : $(OBJ_FILES)
$(CC) $(CC_FLAGS) -o $(EXEC_NAME) $(OBJ_FILES)
%.o: %.cpp %.hpp
$(CC) $(CC_FLAGS) -o $@ -c $<
main.o : main.cpp modele_graphe.hpp
......@@ -39,15 +39,23 @@ public:
template< class T > class noeud{
T val;
int number;
string name;
vector<voisin> voisins;
public:
noeud(){
val = T();
number = 0;
name = "";
};
noeud(string n){
val = T();
number = 0;
name = n;
};
noeud(const noeud & n){
val = n.val;
number = n.number;
name = n.name;
voisins = n.voisins;
};
~noeud (){
......@@ -59,7 +67,9 @@ public:
void ajout_num(int n){
number = n;
}
void ajout_nom(string n){
name = n;
}
vector<voisin> get_voisins() {
return voisins;
}
......@@ -68,6 +78,10 @@ public:
return val;
}
string get_nom() {
return name;
}
int num(){
return number;
}
......@@ -90,15 +104,16 @@ public:
noeud & operator = (const noeud & n){
if(this != &n){
voisins.clear();
val = n.val;
voisins = n.voisins;
number = n.number;
val = n.val;
voisins = n.voisins;
number = n.number;
name = n.name;
}
return *this;
}
bool operator == (const noeud & n){
bool res = false;
res = (val == n.val) && (n.number == number);
res = (val == n.val) && (n.number == number) && (n.name == name);
return res;
}
......@@ -156,7 +171,7 @@ template <class T> ostream & operator<<(ostream & out, noeud<T> & x){
vector<voisin>::iterator ii;
int nvoisins=0;
out<<" noeuf numero: "<<x.number<<" de valeur "<<x.val<<endl;
out<<" noeud "<<x.name<<" numero: "<<x.number<<" de valeur "<<x.val<<endl;
if(x.voisins.size() != 0){
out<<">>>>> liste des voisins:"<<endl;
for(ii = x.voisins.begin(); ii != x.voisins.end(); ii++){
......
......@@ -12,9 +12,10 @@ class ModeleGraphe : public Modele {
// Graphe sur lequel le modèle d'épidémie sera appliqué
graphe<T> *m_graphe;
public:
ModeleGraphe();
ModeleGraphe();
ModeleGraphe(graphe<T> *g);
~ModeleGraphe();
~ModeleGraphe();
graphe<T> *get_graphe();
// Calcule les conditions initiales du modèle en fonction des conditions initiales
// du modèle associé à chaque noeud du graphe.
void setInitialValue();
......@@ -43,6 +44,11 @@ template<class T>
ModeleGraphe<T>::~ModeleGraphe() {
}
template<class T>
graphe<T> * ModeleGraphe<T>::get_graphe() {
return m_graphe;
}
template<class T>
void ModeleGraphe<T>::setInitialValue() {
// création du vecteur contenant les conditions initiale :
......
......@@ -7,7 +7,7 @@
class ModeleSeir : public Modele {
private:
double m_beta;
double m_gamma;
double m_gamma;
double m_alpha;
double m_nu;
double m_mu;
......@@ -16,7 +16,7 @@ class ModeleSeir : public Modele {
ModeleSeir();
ModeleSeir(double beta, double gamma, double alpha, double nu, double mu, double g);
~ModeleSeir() {}
double g();
double g();
std::vector<double> flux(std::vector<double>);
};
......
#ifndef PLOT_HPP
#define PLOT_HPP
#include "solveur_temps.hpp"
#include "matplotlibcpp.h"
void plotSolutionNoeud(const int, const std::string&, SolveurTemps*);
#endif
......@@ -4,7 +4,6 @@
#include <vector>
#include "modele.hpp"
#include "matplotlibcpp.h"
class SolveurTemps {
protected:
......@@ -25,10 +24,13 @@ class SolveurTemps {
// Calcule la valeur initiale du vecteur solution
void setInitialValue();
// Renvoie le temps correspondant au dernier vecteur de m_variablesTemps
double getCurrentTime();
double getCurrentTime();
// Renvoie le pas de temps
double get_dt();
// Renvoie la dernière solution calculée
std::vector<double> getSolutionCurrentTime();
void plotSolution(const int inoeud, const std::string&);
std::vector<double> getSolutionCurrentTime();
// Renvoie les solutions pour chaque pas de temps
std::vector< std::vector<double> > getVariablesTime();
};
#endif
#pragma once
#include <vector>
#include <map>
#include <array>
#include <numeric>
#include <algorithm>
#include <stdexcept>
#include <iostream>
#include <cstdint> // <cstdint> requires c++11 support
#include <functional>
#include <Python.h>
#ifndef WITHOUT_NUMPY
# define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
# include <numpy/arrayobject.h>
#endif // WITHOUT_NUMPY
#if PY_MAJOR_VERSION >= 3
# define PyString_FromString PyUnicode_FromString
# define PyInt_FromLong PyLong_FromLong
# define PyString_FromString PyUnicode_FromString
#endif
namespace matplotlibcpp {
namespace detail {
static std::string s_backend;
struct _interpreter {
PyObject *s_python_function_show;
PyObject *s_python_function_close;
PyObject *s_python_function_draw;
PyObject *s_python_function_pause;
PyObject *s_python_function_save;
PyObject *s_python_function_figure;
PyObject *s_python_function_fignum_exists;
PyObject *s_python_function_plot;
PyObject *s_python_function_quiver;
PyObject *s_python_function_semilogx;
PyObject *s_python_function_semilogy;
PyObject *s_python_function_loglog;
PyObject *s_python_function_fill;
PyObject *s_python_function_fill_between;
PyObject *s_python_function_hist;
PyObject *s_python_function_scatter;
PyObject *s_python_function_subplot;
PyObject *s_python_function_legend;
PyObject *s_python_function_xlim;
PyObject *s_python_function_ion;
PyObject *s_python_function_ginput;
PyObject *s_python_function_ylim;
PyObject *s_python_function_title;
PyObject *s_python_function_axis;
PyObject *s_python_function_xlabel;
PyObject *s_python_function_ylabel;
PyObject *s_python_function_xticks;
PyObject *s_python_function_yticks;
PyObject *s_python_function_grid;
PyObject *s_python_function_clf;
PyObject *s_python_function_errorbar;
PyObject *s_python_function_annotate;
PyObject *s_python_function_tight_layout;
PyObject *s_python_colormap;
PyObject *s_python_empty_tuple;
PyObject *s_python_function_stem;
PyObject *s_python_function_xkcd;
PyObject *s_python_function_text;
PyObject *s_python_function_suptitle;
PyObject *s_python_function_bar;
PyObject *s_python_function_subplots_adjust;
/* For now, _interpreter is implemented as a singleton since its currently not possible to have
multiple independent embedded python interpreters without patching the python source code
or starting a separate process for each.
http://bytes.com/topic/python/answers/793370-multiple-independent-python-interpreters-c-c-program
*/
static _interpreter& get() {
static _interpreter ctx;
return ctx;
}
private:
#ifndef WITHOUT_NUMPY
# if PY_MAJOR_VERSION >= 3
void *import_numpy() {
import_array(); // initialize C-API
return NULL;
}
# else
void import_numpy() {
import_array(); // initialize C-API
}
# endif
#endif
_interpreter() {
// optional but recommended
#if PY_MAJOR_VERSION >= 3
wchar_t name[] = L"plotting";
#else
char name[] = "plotting";
#endif
Py_SetProgramName(name);
Py_Initialize();
#ifndef WITHOUT_NUMPY
import_numpy(); // initialize numpy C-API
#endif
PyObject* matplotlibname = PyString_FromString("matplotlib");
PyObject* pyplotname = PyString_FromString("matplotlib.pyplot");
PyObject* cmname = PyString_FromString("matplotlib.cm");
PyObject* pylabname = PyString_FromString("pylab");
if (!pyplotname || !pylabname || !matplotlibname || !cmname) {
throw std::runtime_error("couldnt create string");
}
PyObject* matplotlib = PyImport_Import(matplotlibname);
Py_DECREF(matplotlibname);
if (!matplotlib) {
PyErr_Print();
throw std::runtime_error("Error loading module matplotlib!");
}
// matplotlib.use() must be called *before* pylab, matplotlib.pyplot,
// or matplotlib.backends is imported for the first time
if (!s_backend.empty()) {
PyObject_CallMethod(matplotlib, const_cast<char*>("use"), const_cast<char*>("s"), s_backend.c_str());
}
PyObject* pymod = PyImport_Import(pyplotname);
Py_DECREF(pyplotname);
if (!pymod) { throw std::runtime_error("Error loading module matplotlib.pyplot!"); }
s_python_colormap = PyImport_Import(cmname);
Py_DECREF(cmname);
if (!s_python_colormap) { throw std::runtime_error("Error loading module matplotlib.cm!"); }
PyObject* pylabmod = PyImport_Import(pylabname);
Py_DECREF(pylabname);
if (!pylabmod) { throw std::runtime_error("Error loading module pylab!"); }
s_python_function_show = PyObject_GetAttrString(pymod, "show");
s_python_function_close = PyObject_GetAttrString(pymod, "close");
s_python_function_draw = PyObject_GetAttrString(pymod, "draw");
s_python_function_pause = PyObject_GetAttrString(pymod, "pause");
s_python_function_figure = PyObject_GetAttrString(pymod, "figure");
s_python_function_fignum_exists = PyObject_GetAttrString(pymod, "fignum_exists");
s_python_function_plot = PyObject_GetAttrString(pymod, "plot");
s_python_function_quiver = PyObject_GetAttrString(pymod, "quiver");
s_python_function_semilogx = PyObject_GetAttrString(pymod, "semilogx");
s_python_function_semilogy = PyObject_GetAttrString(pymod, "semilogy");
s_python_function_loglog = PyObject_GetAttrString(pymod, "loglog");
s_python_function_fill = PyObject_GetAttrString(pymod, "fill");
s_python_function_fill_between = PyObject_GetAttrString(pymod, "fill_between");
s_python_function_hist = PyObject_GetAttrString(pymod,"hist");
s_python_function_scatter = PyObject_GetAttrString(pymod,"scatter");
s_python_function_subplot = PyObject_GetAttrString(pymod, "subplot");
s_python_function_legend = PyObject_GetAttrString(pymod, "legend");
s_python_function_ylim = PyObject_GetAttrString(pymod, "ylim");
s_python_function_title = PyObject_GetAttrString(pymod, "title");
s_python_function_axis = PyObject_GetAttrString(pymod, "axis");
s_python_function_xlabel = PyObject_GetAttrString(pymod, "xlabel");
s_python_function_ylabel = PyObject_GetAttrString(pymod, "ylabel");
s_python_function_xticks = PyObject_GetAttrString(pymod, "xticks");
s_python_function_yticks = PyObject_GetAttrString(pymod, "yticks");
s_python_function_grid = PyObject_GetAttrString(pymod, "grid");
s_python_function_xlim = PyObject_GetAttrString(pymod, "xlim");
s_python_function_ion = PyObject_GetAttrString(pymod, "ion");
s_python_function_ginput = PyObject_GetAttrString(pymod, "ginput");
s_python_function_save = PyObject_GetAttrString(pylabmod, "savefig");
s_python_function_annotate = PyObject_GetAttrString(pymod,"annotate");
s_python_function_clf = PyObject_GetAttrString(pymod, "clf");
s_python_function_errorbar = PyObject_GetAttrString(pymod, "errorbar");
s_python_function_tight_layout = PyObject_GetAttrString(pymod, "tight_layout");
s_python_function_stem = PyObject_GetAttrString(pymod, "stem");
s_python_function_xkcd = PyObject_GetAttrString(pymod, "xkcd");
s_python_function_text = PyObject_GetAttrString(pymod, "text");
s_python_function_suptitle = PyObject_GetAttrString(pymod, "suptitle");
s_python_function_bar = PyObject_GetAttrString(pymod,"bar");
s_python_function_subplots_adjust = PyObject_GetAttrString(pymod,"subplots_adjust");
if( !s_python_function_show
|| !s_python_function_close
|| !s_python_function_draw
|| !s_python_function_pause
|| !s_python_function_figure
|| !s_python_function_fignum_exists
|| !s_python_function_plot
|| !s_python_function_quiver
|| !s_python_function_semilogx
|| !s_python_function_semilogy
|| !s_python_function_loglog
|| !s_python_function_fill
|| !s_python_function_fill_between
|| !s_python_function_subplot
|| !s_python_function_legend
|| !s_python_function_ylim
|| !s_python_function_title
|| !s_python_function_axis
|| !s_python_function_xlabel
|| !s_python_function_ylabel
|| !s_python_function_grid
|| !s_python_function_xlim
|| !s_python_function_ion
|| !s_python_function_ginput
|| !s_python_function_save
|| !s_python_function_clf
|| !s_python_function_annotate
|| !s_python_function_errorbar
|| !s_python_function_errorbar
|| !s_python_function_tight_layout
|| !s_python_function_stem
|| !s_python_function_xkcd
|| !s_python_function_text
|| !s_python_function_suptitle
|| !s_python_function_bar
|| !s_python_function_subplots_adjust
) { throw std::runtime_error("Couldn't find required function!"); }
if ( !PyFunction_Check(s_python_function_show)
|| !PyFunction_Check(s_python_function_close)
|| !PyFunction_Check(s_python_function_draw)
|| !PyFunction_Check(s_python_function_pause)
|| !PyFunction_Check(s_python_function_figure)
|| !PyFunction_Check(s_python_function_fignum_exists)
|| !PyFunction_Check(s_python_function_plot)
|| !PyFunction_Check(s_python_function_quiver)
|| !PyFunction_Check(s_python_function_semilogx)
|| !PyFunction_Check(s_python_function_semilogy)
|| !PyFunction_Check(s_python_function_loglog)
|| !PyFunction_Check(s_python_function_fill)
|| !PyFunction_Check(s_python_function_fill_between)
|| !PyFunction_Check(s_python_function_subplot)
|| !PyFunction_Check(s_python_function_legend)
|| !PyFunction_Check(s_python_function_annotate)
|| !PyFunction_Check(s_python_function_ylim)
|| !PyFunction_Check(s_python_function_title)
|| !PyFunction_Check(s_python_function_axis)
|| !PyFunction_Check(s_python_function_xlabel)
|| !PyFunction_Check(s_python_function_ylabel)
|| !PyFunction_Check(s_python_function_grid)
|| !PyFunction_Check(s_python_function_xlim)
|| !PyFunction_Check(s_python_function_ion)
|| !PyFunction_Check(s_python_function_ginput)
|| !PyFunction_Check(s_python_function_save)
|| !PyFunction_Check(s_python_function_clf)
|| !PyFunction_Check(s_python_function_tight_layout)
|| !PyFunction_Check(s_python_function_errorbar)
|| !PyFunction_Check(s_python_function_stem)
|| !PyFunction_Check(s_python_function_xkcd)
|| !PyFunction_Check(s_python_function_text)
|| !PyFunction_Check(s_python_function_suptitle)
|| !PyFunction_Check(s_python_function_bar)
|| !PyFunction_Check(s_python_function_subplots_adjust)
) { throw std::runtime_error("Python object is unexpectedly not a PyFunction."); }
s_python_empty_tuple = PyTuple_New(0);
}
~_interpreter() {
Py_Finalize();
}
};
} // end namespace detail
// must be called before the first regular call to matplotlib to have any effect
inline void backend(const std::string& name)
{
detail::s_backend = name;
}
inline bool annotate(std::string annotation, double x, double y)
{
PyObject * xy = PyTuple_New(2);
PyObject * str = PyString_FromString(annotation.c_str());
PyTuple_SetItem(xy,0,PyFloat_FromDouble(x));
PyTuple_SetItem(xy,1,PyFloat_FromDouble(y));
PyObject* kwargs = PyDict_New();
PyDict_SetItemString(kwargs, "xy", xy);
PyObject* args = PyTuple_New(1);
PyTuple_SetItem(args, 0, str);
PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_annotate, args, kwargs);
Py_DECREF(args);
Py_DECREF(kwargs);
if(res) Py_DECREF(res);
return res;
}
#ifndef WITHOUT_NUMPY
// Type selector for numpy array conversion
template <typename T> struct select_npy_type { const static NPY_TYPES type = NPY_NOTYPE; }; //Default
template <> struct select_npy_type<double> { const static NPY_TYPES type = NPY_DOUBLE; };
template <> struct select_npy_type<float> { const static NPY_TYPES type = NPY_FLOAT; };
template <> struct select_npy_type<bool> { const static NPY_TYPES type = NPY_BOOL; };
template <> struct select_npy_type<int8_t> { const static NPY_TYPES type = NPY_INT8; };
template <> struct select_npy_type<int16_t> { const static NPY_TYPES type = NPY_SHORT; };
template <> struct select_npy_type<int32_t> { const static NPY_TYPES type = NPY_INT; };
template <> struct select_npy_type<int64_t> { const static NPY_TYPES type = NPY_INT64; };
template <> struct select_npy_type<uint8_t> { const static NPY_TYPES type = NPY_UINT8; };
template <> struct select_npy_type<uint16_t> { const static NPY_TYPES type = NPY_USHORT; };
template <> struct select_npy_type<uint32_t> { const static NPY_TYPES type = NPY_ULONG; };
template <> struct select_npy_type<uint64_t> { const static NPY_TYPES type = NPY_UINT64; };
template<typename Numeric>
PyObject* get_array(const std::vector<Numeric>& v)
{
detail::_interpreter::get(); //interpreter needs to be initialized for the numpy commands to work
NPY_TYPES type = select_npy_type<Numeric>::type;
if (type == NPY_NOTYPE)
{
std::vector<double> vd(v.size());
npy_intp vsize = v.size();
std::copy(v.begin(),v.end(),vd.begin());
PyObject* varray = PyArray_SimpleNewFromData(1, &vsize, NPY_DOUBLE, (void*)(vd.data()));
return varray;
}
npy_intp vsize = v.size();
PyObject* varray = PyArray_SimpleNewFromData(1, &vsize, type, (void*)(v.data()));
return varray;
}
template<typename Numeric>
PyObject* get_2darray(const std::vector<::std::vector<Numeric>>& v)
{
detail::_interpreter::get(); //interpreter needs to be initialized for the numpy commands to work
if (v.size() < 1) throw std::runtime_error("get_2d_array v too small");
npy_intp vsize[2] = {static_cast<npy_intp>(v.size()),
static_cast<npy_intp>(v[0].size())};
PyArrayObject *varray =
(PyArrayObject *)PyArray_SimpleNew(2, vsize, NPY_DOUBLE);
double *vd_begin = static_cast<double *>(PyArray_DATA(varray));
for (const ::std::vector<Numeric> &v_row : v) {
if (v_row.size() != static_cast<size_t>(vsize[1]))
throw std::runtime_error("Missmatched array size");
std::copy(v_row.begin(), v_row.end(), vd_begin);
vd_begin += vsize[1];
}
return reinterpret_cast<PyObject *>(varray);
}
#else // fallback if we don't have numpy: copy every element of the given vector
template<typename Numeric>
PyObject* get_array(const std::vector<Numeric>& v)
{
PyObject* list = PyList_New(v.size());
for(size_t i = 0; i < v.size(); ++i) {
PyList_SetItem(list, i, PyFloat_FromDouble(v.at(i)));
}
return list;
}
#endif // WITHOUT_NUMPY
template<typename Numeric>
bool plot(const std::vector<Numeric> &x, const std::vector<Numeric> &y, const std::map<std::string, std::string>& keywords)
{
assert(x.size() == y.size());
// using numpy arrays
PyObject* xarray = get_array(x);
PyObject* yarray = get_array(y);
// construct positional args
PyObject* args = PyTuple_New(2);
PyTuple_SetItem(args, 0, xarray);
PyTuple_SetItem(args, 1, yarray);
// construct keyword args
PyObject* kwargs = PyDict_New();
for(std::map<std::string, std::string>::const_iterator it = keywords.begin(); it != keywords.end(); ++it)
{
PyDict_SetItemString(kwargs, it->first.c_str(), PyString_FromString(it->second.c_str()));
}
PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_plot, args, kwargs);
Py_DECREF(args);
Py_DECREF(kwargs);
if(res) Py_DECREF(res);
return res;
}
template <typename Numeric>
void plot_surface(const std::vector<::std::vector<Numeric>> &x,
const std::vector<::std::vector<Numeric>> &y,
const std::vector<::std::vector<Numeric>> &z,
const std::map<std::string, std::string> &keywords =
std::map<std::string, std::string>())
{
// We lazily load the modules here the first time this function is called
// because I'm not sure that we can assume "matplotlib installed" implies
// "mpl_toolkits installed" on all platforms, and we don't want to require
// it for people who don't need 3d plots.
static PyObject *mpl_toolkitsmod = nullptr, *axis3dmod = nullptr;
if (!mpl_toolkitsmod) {
detail::_interpreter::get();
PyObject* mpl_toolkits = PyString_FromString("mpl_toolkits");
PyObject* axis3d = PyString_FromString("mpl_toolkits.mplot3d");
if (!mpl_toolkits || !axis3d) { throw std::runtime_error("couldnt create string"); }
mpl_toolkitsmod = PyImport_Import(mpl_toolkits);
Py_DECREF(mpl_toolkits);
if (!mpl_toolkitsmod) { throw std::runtime_error("Error loading module mpl_toolkits!"); }
axis3dmod = PyImport_Import(axis3d);
Py_DECREF(axis3d);
if (!axis3dmod) { throw std::runtime_error("Error loading module mpl_toolkits.mplot3d!"); }
}
assert(x.size() == y.size());
assert(y.size() == z.size());
// using numpy arrays
PyObject *xarray = get_2darray(x);
PyObject *yarray = get_2darray(y);
PyObject *zarray = get_2darray(z);
// construct positional args
PyObject *args = PyTuple_New(3);
PyTuple_SetItem(args, 0, xarray);
PyTuple_SetItem(args, 1, yarray);