mirror of https://gitlab.com/pamhyr/pamhyr2
doc: dev: Add note about scenarios.
parent
40d90424a3
commit
5598464081
|
|
@ -0,0 +1,661 @@
|
||||||
|
# senario.org -- Pamhyr developers documentation
|
||||||
|
# Copyright (C) 2023-2024 INRAE
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
#+STARTUP: indent show2levels
|
||||||
|
|
||||||
|
#+INCLUDE: ../tools/macro.org
|
||||||
|
#+INCLUDE: ../tools/latex.org
|
||||||
|
|
||||||
|
#+TITLE: Scenario implementation in Pamhyr2: \textbf{Preparatory work}
|
||||||
|
#+SUBTITLE: Version: {{{version}}}
|
||||||
|
#+AUTHOR: {{{INRAE}}}
|
||||||
|
|
||||||
|
#+OPTIONS: toc:t
|
||||||
|
#+LANGUAGE: UKenglish
|
||||||
|
|
||||||
|
#+latex: \newpage
|
||||||
|
|
||||||
|
* COMMENT tools
|
||||||
|
|
||||||
|
#+begin_src emacs-lisp :export none
|
||||||
|
(add-to-list 'org-structure-template-alist
|
||||||
|
'("p" "#+begin_src python :python python3 :results output\n\n#+end_src"))
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
#+RESULTS:
|
||||||
|
#+begin_example
|
||||||
|
((p #+begin_src python :python python3 :results output
|
||||||
|
|
||||||
|
,#+end_src) (d . #+name: graph-XXX
|
||||||
|
,#+header: :results drawer
|
||||||
|
,#+header: :exports results
|
||||||
|
,#+header: :post attr_wrap(width="12cm", data=*this*, name="graph-XXX", caption="Graph XXX", float="t")
|
||||||
|
,#+begin_src dot :file "images/graph-XXX.png" :cache no
|
||||||
|
digraph {
|
||||||
|
bgcolor="transparent";
|
||||||
|
node[colorscheme=set19,shape=box,style="filled",fillcolor=9];
|
||||||
|
}
|
||||||
|
,#+end_src) (p . src python :python python3 :results output :noweb yes
|
||||||
|
|
||||||
|
src) (t . EXPORT latex
|
||||||
|
\begin{table}
|
||||||
|
\centering
|
||||||
|
\resizebox{0.6\linewidth}{!}{
|
||||||
|
|
||||||
|
}
|
||||||
|
%\vspace{0.5pt}
|
||||||
|
%\caption{Number of tests by errors types}
|
||||||
|
\end{table}
|
||||||
|
,#+E) (B . src shell :session *shell* :results output :exports both) (a . export ascii) (c . center) (C . comment) (e . example) (E . export) (h . export html) (l . export latex) (q . quote) (s . src) (v . verse))
|
||||||
|
#+end_example
|
||||||
|
|
||||||
|
#+name: dbg-execute
|
||||||
|
#+begin_src python :python python3 :results output :noweb yes
|
||||||
|
def execute(db, query):
|
||||||
|
print(query)
|
||||||
|
return db.execute(query)
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
#+RESULTS: dbg-execute
|
||||||
|
|
||||||
|
#+name: execute
|
||||||
|
#+begin_src python :python python3 :results output :noweb yes
|
||||||
|
def execute(db, query):
|
||||||
|
return db.execute(query)
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
#+RESULTS: execute
|
||||||
|
|
||||||
|
* Principe
|
||||||
|
|
||||||
|
** Scenario
|
||||||
|
|
||||||
|
A scenario is defined by a name, a description and a parent
|
||||||
|
scenario. If a scenario as no parent, parent value is =None=. So, in
|
||||||
|
Pamhyr2 the list of scenario must by a tree with a root defined by a
|
||||||
|
default scenarios with no parent.
|
||||||
|
|
||||||
|
#+begin_src sql
|
||||||
|
CREATE TABLE scenario(
|
||||||
|
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||||
|
name TEXT NOT NULL, -- Name of the scenario
|
||||||
|
description TEXT NOT NULL, -- Rich text description
|
||||||
|
parent_id INTEGER REFERENCES scenario(id) -- Recursive references
|
||||||
|
-- for parent scenario
|
||||||
|
)
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
** Data
|
||||||
|
|
||||||
|
Each data is associated with one and only one scenario. This senario
|
||||||
|
is defined by the =id=. So, each data structure who can saved in DB
|
||||||
|
must add the following lines in table définition:
|
||||||
|
|
||||||
|
#+begin_src sql
|
||||||
|
scenario_id INTEGER NOT NULL,
|
||||||
|
FOREIGN KEY(scenario_id) REFERENCES scenario(id)
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
To avoid, at least, memory usage exploitation, by default, a scenario
|
||||||
|
must saved only the modified data from its parent. This contrains
|
||||||
|
require to wrap any data modification to update the data scenario id
|
||||||
|
to current scenario id in source code. In addition, we need to modify
|
||||||
|
the data loading méthode to take in considération this recursive
|
||||||
|
dependencies.
|
||||||
|
|
||||||
|
#+CAPTION: Recursive loading method
|
||||||
|
#+begin_src python :python python3 :results output :noweb yes
|
||||||
|
def rec_load(cls, db, current_scenario):
|
||||||
|
# Default case, end of recursion
|
||||||
|
if current_scenario is None:
|
||||||
|
return [] # Default value
|
||||||
|
|
||||||
|
table = db.execute(f"<MY SELECT> WHERE scenario_id = {current_scenario}")
|
||||||
|
|
||||||
|
# If no data for this scenario, recursion
|
||||||
|
if len(table) == 0:
|
||||||
|
parent_id = db.get_parent_id(current_scenario)
|
||||||
|
return cls.rec_load(db, parent_id)
|
||||||
|
|
||||||
|
# Otherelse, parse data and return...
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
With this method, modify a data in parent scenario, modify this data
|
||||||
|
in child scenario too. Unless is value has been previously modified in
|
||||||
|
the child scenario. Deny tree node modification, except for leaf.
|
||||||
|
|
||||||
|
This method work, but it dont allow to delete data un child scenarios,
|
||||||
|
because if we dont found data for this scenario we search for parent
|
||||||
|
scenario. So, we need a condition to stop recursion in case of data
|
||||||
|
deletion in child scenario. To stop the recurtion, we can use a dummy
|
||||||
|
data flag. By default, this flags is =false=, but if this flags is
|
||||||
|
=true= the data is ignored at loading.
|
||||||
|
|
||||||
|
So, we can use this flags for each data structure who can saved in DB:
|
||||||
|
|
||||||
|
#+begin_src sql
|
||||||
|
is_dummy BOOLEAN, -- True if this data as been deleted
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
Modify the loading method:
|
||||||
|
|
||||||
|
#+CAPTION: Recursive loading method with possible dummy data
|
||||||
|
#+begin_src python :python python3 :results output :noweb yes
|
||||||
|
def rec_load_2(cls, db, current_scenario):
|
||||||
|
# Default case, end of recursion
|
||||||
|
if current_scenario is None:
|
||||||
|
return [] # Default value
|
||||||
|
|
||||||
|
table = db.execute(f"<MY SELECT> WHERE scenario_id = {current_scenario}")
|
||||||
|
|
||||||
|
# If no data for this scenario, recursion
|
||||||
|
if len(table) == 0:
|
||||||
|
parent_id = db.get_parent_id(current_scenario)
|
||||||
|
return cls.rec_load(db, parent_id)
|
||||||
|
|
||||||
|
for data in table:
|
||||||
|
if is_dummy(data):
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Otherelse, parse data ...
|
||||||
|
|
||||||
|
# return ...
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
#+RESULTS:
|
||||||
|
|
||||||
|
And add a data reduction method:
|
||||||
|
|
||||||
|
#+caption: Data reduction method for data subtree
|
||||||
|
#+begin_src python :python python3 :results output :noweb yes
|
||||||
|
def reduce_change(self):
|
||||||
|
# Get the greater scenario
|
||||||
|
scenar = reduce(
|
||||||
|
lambda acc, x: max(acc, x._scenario),
|
||||||
|
self._values,
|
||||||
|
self._scenario
|
||||||
|
)
|
||||||
|
|
||||||
|
# Apply change on this subtree
|
||||||
|
self._scenario = scenar
|
||||||
|
|
||||||
|
if is_dummy(self): # There are no more subtree
|
||||||
|
self.values = []
|
||||||
|
else: # Update data subtree scenario id
|
||||||
|
for value in self._values:
|
||||||
|
value.set_scenario(self._scenario)
|
||||||
|
# Dummy data is no more necessary in this subtree
|
||||||
|
self._values = list(
|
||||||
|
filter(
|
||||||
|
lambda v: not is_dummy(v),
|
||||||
|
self._values
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Keep data id unique for all subtree
|
||||||
|
self.get_new_db_id()
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
#+RESULTS:
|
||||||
|
|
||||||
|
#+latex: \newpage
|
||||||
|
|
||||||
|
* Prototype
|
||||||
|
|
||||||
|
** Scenario
|
||||||
|
|
||||||
|
#+name: scenario
|
||||||
|
#+begin_src python :python python3 :results output :noweb yes
|
||||||
|
class Scenario():
|
||||||
|
def __init__(self, id, name, parent):
|
||||||
|
self._id = id
|
||||||
|
self._name = name
|
||||||
|
self._parent = parent
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def create_db(cls, db):
|
||||||
|
execute(
|
||||||
|
db, """
|
||||||
|
CREATE TABLE scenario(
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
parent_id INTEGER REFERENCES scenario(id)
|
||||||
|
)
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def load_db(cls, db):
|
||||||
|
cur = execute(
|
||||||
|
db, f"SELECT * FROM scenario"
|
||||||
|
)
|
||||||
|
table = cur.fetchall()
|
||||||
|
|
||||||
|
new = []
|
||||||
|
for values in table:
|
||||||
|
new.append(
|
||||||
|
cls(
|
||||||
|
values[0], values[1], values[2],
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
return new
|
||||||
|
|
||||||
|
def save(self, db):
|
||||||
|
sid = 'NULL' if self._parent is None else self._parent
|
||||||
|
|
||||||
|
execute(
|
||||||
|
db,
|
||||||
|
"INSERT INTO scenario (id, name, parent_id) " +
|
||||||
|
f"VALUES ({self._id}, '{self._name}', {sid})"
|
||||||
|
)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"Scenario {{ {self._id}, {self._name}, parent {self._parent} }}"
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"{self._name}({self._id})"
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
#+RESULTS: scenario
|
||||||
|
|
||||||
|
** Data
|
||||||
|
|
||||||
|
#+name: data-b
|
||||||
|
#+begin_src python :python python3 :results output :noweb yes
|
||||||
|
class B():
|
||||||
|
def __init__(self, value, scenario):
|
||||||
|
self._value = value
|
||||||
|
self._scenario = scenario
|
||||||
|
self._dummy = False
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def create_db(cls, db):
|
||||||
|
execute(db, """
|
||||||
|
CREATE TABLE b(
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
dummy_data BOOLEAN,
|
||||||
|
x INTEGER,
|
||||||
|
a_id INTEGER NOT NULL,
|
||||||
|
scenario_id INTEGER NOT NULL,
|
||||||
|
FOREIGN KEY(a_id) REFERENCES a(id),
|
||||||
|
FOREIGN KEY(scenario_id) REFERENCES scenario(id)
|
||||||
|
)
|
||||||
|
""")
|
||||||
|
|
||||||
|
def save(self, db, a_id):
|
||||||
|
execute(
|
||||||
|
db,
|
||||||
|
"INSERT INTO b (x, dummy_data, a_id, scenario_id) " +
|
||||||
|
f"VALUES ({self._value}, {self._dummy}, {a_id}, {self._scenario})"
|
||||||
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def load_db(cls, db, a_id, senar):
|
||||||
|
if senar is None:
|
||||||
|
return []
|
||||||
|
|
||||||
|
cur = execute(
|
||||||
|
db,
|
||||||
|
"SELECT x, scenario_id, dummy_data FROM b " +
|
||||||
|
f"WHERE scenario_id = {senar} AND a_id = {a_id}"
|
||||||
|
)
|
||||||
|
table = cur.fetchall()
|
||||||
|
|
||||||
|
if len(table) == 0:
|
||||||
|
parent = execute(
|
||||||
|
db,
|
||||||
|
f"SELECT parent_id FROM scenario WHERE id = {senar}"
|
||||||
|
).fetchone()
|
||||||
|
|
||||||
|
return cls.load_db(db, parent[0])
|
||||||
|
|
||||||
|
new = []
|
||||||
|
for values in table:
|
||||||
|
if values[2]: # Is dummy
|
||||||
|
continue
|
||||||
|
|
||||||
|
new.append(cls(values[0], values[1]))
|
||||||
|
|
||||||
|
return new
|
||||||
|
|
||||||
|
def set_value(self, value, scenario):
|
||||||
|
self._value = value
|
||||||
|
self._scenario = scenario
|
||||||
|
|
||||||
|
def set_dummy(self, scenario):
|
||||||
|
self._scenario = scenario
|
||||||
|
self._dummy = True
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
if self._dummy:
|
||||||
|
return ""
|
||||||
|
return f"{self._value}"
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
if self._dummy:
|
||||||
|
return ""
|
||||||
|
return f"{self._value}"
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
#+RESULTS: data-b
|
||||||
|
|
||||||
|
#+name: data-a
|
||||||
|
#+begin_src python :python python3 :results output :noweb yes
|
||||||
|
class A():
|
||||||
|
def __init__(self, id, values, scenario):
|
||||||
|
self._id = id
|
||||||
|
self._values = values
|
||||||
|
self._scenario = scenario
|
||||||
|
self._dummy = False
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def create_db(cls, db):
|
||||||
|
execute(db, """
|
||||||
|
CREATE TABLE a(
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
dummy_data BOOLEAN,
|
||||||
|
scenario_id INTEGER,
|
||||||
|
FOREIGN KEY(scenario_id) REFERENCES scenario(id)
|
||||||
|
)
|
||||||
|
""")
|
||||||
|
|
||||||
|
def save(self, db):
|
||||||
|
self.reduce_change()
|
||||||
|
|
||||||
|
execute(db, f"DELETE FROM a WHERE scenario_id = {self._scenario}")
|
||||||
|
execute(
|
||||||
|
db,
|
||||||
|
"INSERT INTO a (id, dummy_data, scenario_id) " +
|
||||||
|
f"VALUES ({self._id}, {self._dummy}, {self._scenario})"
|
||||||
|
)
|
||||||
|
|
||||||
|
execute(
|
||||||
|
db,
|
||||||
|
"DELETE FROM b " +
|
||||||
|
f"WHERE scenario_id = {self._scenario} " +
|
||||||
|
f"AND a_id = {self._id}"
|
||||||
|
)
|
||||||
|
|
||||||
|
for value in self._values:
|
||||||
|
value.save(db, self._id)
|
||||||
|
|
||||||
|
def reduce_change(self):
|
||||||
|
diff_scenar = reduce(
|
||||||
|
lambda acc, x: max(acc, x._scenario),
|
||||||
|
self._values,
|
||||||
|
self._scenario
|
||||||
|
)
|
||||||
|
print(f" ~> Reduce: {self._scenario} to {diff_scenar}")
|
||||||
|
self._scenario = diff_scenar
|
||||||
|
|
||||||
|
# Reduce new scenario value on each value
|
||||||
|
for value in self._values:
|
||||||
|
value._scenario = self._scenario
|
||||||
|
|
||||||
|
# Delete useless dummy data
|
||||||
|
self._values = list(
|
||||||
|
filter(
|
||||||
|
lambda v: not v._dummy,
|
||||||
|
self._values
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# HACK: keep id unique
|
||||||
|
self._id = self._id * 100 + diff_scenar
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def load_db(cls, db, senar):
|
||||||
|
if senar is None:
|
||||||
|
return []
|
||||||
|
|
||||||
|
cur = execute(
|
||||||
|
db,
|
||||||
|
f"SELECT id, scenario_id, dummy_data FROM a WHERE scenario_id = {senar}"
|
||||||
|
)
|
||||||
|
table = cur.fetchall()
|
||||||
|
|
||||||
|
if len(table) == 0:
|
||||||
|
parent = execute(
|
||||||
|
db,
|
||||||
|
f"SELECT parent_id FROM scenario WHERE id = {senar}"
|
||||||
|
).fetchone()
|
||||||
|
|
||||||
|
return cls.load_db(db, parent[0])
|
||||||
|
|
||||||
|
new = []
|
||||||
|
for values in table:
|
||||||
|
if values[2]:
|
||||||
|
continue
|
||||||
|
|
||||||
|
bb = B.load_db(db, values[0], senar)
|
||||||
|
new.append(cls(values[0], bb, values[1]))
|
||||||
|
|
||||||
|
return new
|
||||||
|
|
||||||
|
def set_dummy(self, scenario):
|
||||||
|
self._scenario = scenario
|
||||||
|
self._dummy = True
|
||||||
|
|
||||||
|
def add(self, b):
|
||||||
|
self._values.append(b)
|
||||||
|
|
||||||
|
def delete(self, index, scenario):
|
||||||
|
self._values[index].set_dummy(scenario)
|
||||||
|
self._scenario = scenario
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
if self._dummy:
|
||||||
|
return "{ }"
|
||||||
|
return f"{{ {self._values}, ({self._scenario}) }}"
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
if self._dummy:
|
||||||
|
return "{ }"
|
||||||
|
return f"{{ {list(map(str, self._values))}, ({self._scenario}) }}"
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
#+RESULTS: data-a
|
||||||
|
|
||||||
|
** Full prototype
|
||||||
|
|
||||||
|
#+begin_src python :python python3 :results output :exports both :noweb yes :cache yes
|
||||||
|
from functools import reduce
|
||||||
|
|
||||||
|
def execute(db, query):
|
||||||
|
# print(query)
|
||||||
|
return db.execute(query)
|
||||||
|
|
||||||
|
def get_tree(db):
|
||||||
|
from treelib import Node, Tree
|
||||||
|
|
||||||
|
tree = Tree()
|
||||||
|
|
||||||
|
for senar in db.execute("SELECT * FROM scenario").fetchall():
|
||||||
|
if senar[1] is None:
|
||||||
|
tree.create_node(
|
||||||
|
str(Scenario(senar[0], senar[1], senar[2])) +
|
||||||
|
" : " + str(A.load_db(db, senar[0])[0]),
|
||||||
|
senar[0]
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
tree.create_node(
|
||||||
|
str(Scenario(senar[0], senar[1], senar[2])) +
|
||||||
|
" : " + str(A.load_db(db, senar[0])[0]),
|
||||||
|
senar[0],
|
||||||
|
parent=senar[2]
|
||||||
|
)
|
||||||
|
|
||||||
|
return tree
|
||||||
|
|
||||||
|
### --- Scenario ---
|
||||||
|
<<scenario>>
|
||||||
|
|
||||||
|
### --- class B ---
|
||||||
|
<<data-b>>
|
||||||
|
|
||||||
|
### --- class A ---
|
||||||
|
<<data-a>>
|
||||||
|
|
||||||
|
### --- Script ---
|
||||||
|
import sqlite3
|
||||||
|
import pprint
|
||||||
|
|
||||||
|
pp = pprint.PrettyPrinter(width=79, compact=True, depth=6)
|
||||||
|
|
||||||
|
with sqlite3.connect(":memory:") as db:
|
||||||
|
cur = db.cursor()
|
||||||
|
|
||||||
|
Scenario.create_db(cur)
|
||||||
|
A.create_db(cur)
|
||||||
|
B.create_db(cur)
|
||||||
|
|
||||||
|
print("--- Default scenario (s0) ---")
|
||||||
|
|
||||||
|
# One scenario
|
||||||
|
|
||||||
|
s0 = Scenario(0, "s0", None)
|
||||||
|
a0 = A(
|
||||||
|
1,
|
||||||
|
[
|
||||||
|
B(0, s0._id),
|
||||||
|
B(1, s0._id),
|
||||||
|
B(2, s0._id),
|
||||||
|
],
|
||||||
|
s0._id
|
||||||
|
)
|
||||||
|
|
||||||
|
s0.save(cur)
|
||||||
|
a0.save(cur)
|
||||||
|
|
||||||
|
print("--- New scenario (s1) -- copy without modification ---")
|
||||||
|
|
||||||
|
# New scenario
|
||||||
|
|
||||||
|
s1 = Scenario(1, "s1", s0._id)
|
||||||
|
s1.save(cur)
|
||||||
|
|
||||||
|
print("--- New scenario (s2) -- data modification ---")
|
||||||
|
|
||||||
|
# New scenario 2 with data
|
||||||
|
|
||||||
|
s2 = Scenario(2, "s2", s0._id)
|
||||||
|
s2.save(cur)
|
||||||
|
|
||||||
|
a2 = a0
|
||||||
|
bb = list(map(
|
||||||
|
lambda b: b.set_value(b._value + 1, s2._id),
|
||||||
|
a2._values
|
||||||
|
))
|
||||||
|
|
||||||
|
a2.save(cur)
|
||||||
|
|
||||||
|
print("--- New scenario (s3) -- delete data ---")
|
||||||
|
|
||||||
|
# New scenario 3 with data
|
||||||
|
|
||||||
|
s3 = Scenario(3, "s3", s0._id)
|
||||||
|
s3.save(cur)
|
||||||
|
|
||||||
|
a3 = A.load_db(cur, s3._id)[0]
|
||||||
|
a3._values[0].set_dummy(s3._id)
|
||||||
|
a3.save(cur)
|
||||||
|
|
||||||
|
print("--- New scenario (s4) -- new data ---")
|
||||||
|
|
||||||
|
s4 = Scenario(4, "s4", s3._id)
|
||||||
|
s4.save(cur)
|
||||||
|
|
||||||
|
a4 = A.load_db(cur, s3._id)[0]
|
||||||
|
a4.add(B(666, s4._id))
|
||||||
|
a4.save(cur)
|
||||||
|
|
||||||
|
print("--- Scenario tree ---")
|
||||||
|
|
||||||
|
tree = get_tree(db)
|
||||||
|
print(tree)
|
||||||
|
|
||||||
|
print("--- Modify s0 data ---")
|
||||||
|
|
||||||
|
aa = A.load_db(db, s0._id)[0]
|
||||||
|
bb = list(map(
|
||||||
|
lambda b: b.set_value(b._value * 100 - 1, s0._id),
|
||||||
|
aa._values
|
||||||
|
))
|
||||||
|
aa.save(db)
|
||||||
|
|
||||||
|
print("--- Scenario tree ---")
|
||||||
|
|
||||||
|
tree = get_tree(db)
|
||||||
|
print(tree)
|
||||||
|
|
||||||
|
print("--- DB ---")
|
||||||
|
|
||||||
|
ss = db.execute("SELECT * FROM scenario").fetchall()
|
||||||
|
print(f"+ scenario ({len(ss)}):")
|
||||||
|
pp.pprint(ss)
|
||||||
|
|
||||||
|
aa = db.execute("SELECT * FROM a").fetchall()
|
||||||
|
print(f"+ a ({len(aa)}):")
|
||||||
|
pp.pprint(aa)
|
||||||
|
|
||||||
|
bb = db.execute("SELECT * FROM b").fetchall()
|
||||||
|
print(f"+ b ({len(bb)}):")
|
||||||
|
pp.pprint(bb)
|
||||||
|
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
#+RESULTS[96c84f23be557425ae2822ef7f174175ef69f9b9]:
|
||||||
|
#+begin_example
|
||||||
|
--- Default scenario (s0) ---
|
||||||
|
~> Reduce: 0 to 0
|
||||||
|
--- New scenario (s1) -- copy without modification ---
|
||||||
|
--- New scenario (s2) -- data modification ---
|
||||||
|
~> Reduce: 0 to 2
|
||||||
|
--- New scenario (s3) -- delete data ---
|
||||||
|
~> Reduce: 0 to 3
|
||||||
|
--- New scenario (s4) -- new data ---
|
||||||
|
~> Reduce: 3 to 4
|
||||||
|
--- Scenario tree ---
|
||||||
|
s0(0) : { ['0', '1', '2'], (0) }
|
||||||
|
├── s1(1) : { ['0', '1', '2'], (0) }
|
||||||
|
├── s2(2) : { ['1', '2', '3'], (2) }
|
||||||
|
└── s3(3) : { ['1', '2'], (3) }
|
||||||
|
└── s4(4) : { ['1', '2', '666'], (4) }
|
||||||
|
|
||||||
|
--- Modify s0 data ---
|
||||||
|
~> Reduce: 0 to 0
|
||||||
|
--- Scenario tree ---
|
||||||
|
s0(0) : { ['-1', '99', '199'], (0) }
|
||||||
|
├── s1(1) : { ['-1', '99', '199'], (0) }
|
||||||
|
├── s2(2) : { ['1', '2', '3'], (2) }
|
||||||
|
└── s3(3) : { ['1', '2'], (3) }
|
||||||
|
└── s4(4) : { ['1', '2', '666'], (4) }
|
||||||
|
|
||||||
|
--- DB ---
|
||||||
|
+ scenario (5):
|
||||||
|
[(0, 's0', None), (1, 's1', 0), (2, 's2', 0), (3, 's3', 0), (4, 's4', 3)]
|
||||||
|
+ a (4):
|
||||||
|
[(10000, 0, 0), (10002, 0, 2), (10003, 0, 3), (1000304, 0, 4)]
|
||||||
|
+ b (14):
|
||||||
|
[(1, 0, 0, 100, 0), (2, 0, 1, 100, 0), (3, 0, 2, 100, 0), (4, 0, 1, 10002, 2),
|
||||||
|
(5, 0, 2, 10002, 2), (6, 0, 3, 10002, 2), (7, 0, 1, 10003, 3),
|
||||||
|
(8, 0, 2, 10003, 3), (9, 0, 1, 1000304, 4), (10, 0, 2, 1000304, 4),
|
||||||
|
(11, 0, 666, 1000304, 4), (12, 0, -1, 10000, 0), (13, 0, 99, 10000, 0),
|
||||||
|
(14, 0, 199, 10000, 0)]
|
||||||
|
#+end_example
|
||||||
|
|
@ -0,0 +1,525 @@
|
||||||
|
# presentation.org -- Pamhyr
|
||||||
|
# Copyright (C) 2023 INRAE
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
#+STARTUP: indent hideblocks content beamer
|
||||||
|
|
||||||
|
#+TITLE: \textbf{Pamhyr2}
|
||||||
|
#+SUBTITLE: Scenarios managements
|
||||||
|
|
||||||
|
# #+AUTHOR: Pierre-Antoine Rouby
|
||||||
|
#+LATEX_HEADER: \author[Pierre-Antoine Rouby]{\textbf{Pierre-Antoine Rouby}}
|
||||||
|
#+EMAIL: pierre-antoine.rouby@inrae.fr
|
||||||
|
#+INSTITUTE: INRAE Lyon-Villerbanne, teams River Hydraulics
|
||||||
|
#+LATEX_HEADER: \institute{INRAE Lyon-Villerbanne, River Hydraulics team}
|
||||||
|
#+DATE: 9th November
|
||||||
|
|
||||||
|
#+KEYWORDS: g ui, hydraulics, sedimentary, hydro-sedimentary, 1D modelling, freesoftware, foss
|
||||||
|
|
||||||
|
#+OPTIONS: H:2 toc:t num:t author:nil
|
||||||
|
#+LATEX_CLASS: beamer
|
||||||
|
#+LATEX_CLASS_OPTIONS: [slideopt,A4,showboxes,svgnames,aspectratio=169]
|
||||||
|
# #+LATEX_CLASS_OPTIONS: [presentation]
|
||||||
|
#+BEAMER_THEME: default
|
||||||
|
#+COLUMNS: %45ITEM %10BEAMER_ENV(Env) %10BEAMER_ACT(Act) %4BEAMER_COL(Col)
|
||||||
|
|
||||||
|
#+LANGUAGE: fr
|
||||||
|
#+LATEX_HEADER: \usepackage[frenchb]{babel}
|
||||||
|
|
||||||
|
#+BEGIN_SRC emacs-lisp :results silent :exports none
|
||||||
|
(setq org-latex-pdf-process (list
|
||||||
|
"latexmk -pdflatex='lualatex -shell-escape -interaction nonstopmode' -pdf -f %f"))
|
||||||
|
|
||||||
|
(add-to-list 'org-latex-packages-alist '("" "minted"))
|
||||||
|
(setq org-latex-listings 'minted)
|
||||||
|
(setq org-src-fontify-natively t)
|
||||||
|
|
||||||
|
(org-add-link-type
|
||||||
|
"cite" 'ebib
|
||||||
|
(lambda (path desc format)
|
||||||
|
(cond
|
||||||
|
((eq format 'html)
|
||||||
|
(format "(<cite>%s</cite>)" path))
|
||||||
|
((eq format 'text)
|
||||||
|
(format "[%s]" path))
|
||||||
|
((eq format 'latex)
|
||||||
|
(if (or (not desc) (equal 0 (search "cite:" desc)))
|
||||||
|
(format "\\cite{%s}" path)
|
||||||
|
(format "\\cite[%s][%s]{%s}"
|
||||||
|
(cadr (split-string desc ";"))
|
||||||
|
(car (split-string desc ";")) path))))))
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
# Wrapper
|
||||||
|
#+NAME: attr_wrap
|
||||||
|
#+HEADER: :var width="\\textwidth"
|
||||||
|
#+HEADER: :var caption=""
|
||||||
|
#+HEADER: :var smallcaption=""
|
||||||
|
#+HEADER: :var name=""
|
||||||
|
#+HEADER: :var data=""
|
||||||
|
#+HEADER: :var float="nil"
|
||||||
|
#+BEGIN_SRC sh :results output :exports none
|
||||||
|
echo "#+CAPTION[$smallcaption]: $caption"
|
||||||
|
echo "#+NAME: $name"
|
||||||
|
echo "#+ATTR_LATEX: :width $width :float $float"
|
||||||
|
echo "$data"
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
#+LATEX_HEADER: \setbeamertemplate{footline}[frame number]
|
||||||
|
#+LATEX_HEADER: \setbeamertemplate{headline}{}
|
||||||
|
#+LATEX_HEADER: \usepackage{multirow}
|
||||||
|
#+LATEX_HEADER: \usepackage{fontawesome5}
|
||||||
|
#+LATEX_HEADER: \usepackage{tcolorbox}
|
||||||
|
#+LATEX_HEADER: \usepackage{tikz}
|
||||||
|
|
||||||
|
#+LATEX_HEADER: \logo{\includegraphics[width=.1\textwidth]{../../../src/View/ui/ressources/Logo-INRAE.png}}
|
||||||
|
|
||||||
|
#+LATEX_HEADER: \newcommand{\R}[1]{\rotatebox[origin=c]{90}{#1}}
|
||||||
|
|
||||||
|
# Beamer colors
|
||||||
|
#+LATEX_HEADER: \setbeamersize{text margin left=0.5cm,text margin right=0.5cm}
|
||||||
|
#+LATEX_HEADER: \setbeamerfont{alerted text}{series=\bfseries}
|
||||||
|
#+LATEX_HEADER: \setbeamerfont{example text}{series=\bfseries}
|
||||||
|
|
||||||
|
#+LATEX_HEADER: \definecolor{inrae_1}{RGB}{102,193,191}
|
||||||
|
#+LATEX_HEADER: \definecolor{inrae_2}{RGB}{0,150,152}
|
||||||
|
#+LATEX_HEADER: \definecolor{inrae_3}{RGB}{39,86,98}
|
||||||
|
|
||||||
|
#+LATEX_HEADER: \setbeamercolor{alerted text}{fg=inrae_1}
|
||||||
|
#+LATEX_HEADER: \setbeamercolor{structure}{fg=inrae_2}
|
||||||
|
#+LATEX_HEADER: \setbeamercolor{normal text}{fg=inrae_3}
|
||||||
|
#+LATEX_HEADER: \setbeamercolor*{author}{fg=inrae_3}
|
||||||
|
|
||||||
|
#+LATEX_HEADER: \usepackage[absolute,showboxes,overlay]{textpos}
|
||||||
|
|
||||||
|
#+LATEX_HEADER: \TPshowboxesfalse
|
||||||
|
#+LATEX_HEADER: \textblockorigin{5mm}{0mm}
|
||||||
|
|
||||||
|
# Biblio
|
||||||
|
#+LATEX_HEADER: \usepackage{natbib}
|
||||||
|
# #+LATEX_HEADER: \bibliographystyle{apalike}
|
||||||
|
#+LATEX_HEADER: \setbeamertemplate{bibliography item}{}
|
||||||
|
#+LATEX_HEADER: \renewcommand\bibfont{\scriptsize}
|
||||||
|
#+LATEX_HEADER: \setbeamertemplate{frametitle continuation}[from second]
|
||||||
|
#+LATEX_HEADER: \setbeamercolor*{bibliography entry title}{fg=inrae_3}
|
||||||
|
#+LATEX_HEADER: \setbeamercolor*{bibliography entry author}{fg=inrae_3}
|
||||||
|
#+LATEX_HEADER: \setbeamercolor*{bibliography entry location}{fg=inrae_3}
|
||||||
|
|
||||||
|
#+LATEX_HEADER: \usepackage{bbding}
|
||||||
|
#+LATEX_HEADER: \usepackage{pdfpages}
|
||||||
|
|
||||||
|
# Renew title page
|
||||||
|
#+LATEX_HEADER: \defbeamertemplate*{title page}{customized}[1][]
|
||||||
|
#+LATEX_HEADER: {
|
||||||
|
# #+LATEX_HEADER: {
|
||||||
|
# #+LATEX_HEADER: \usebeamerfont{date}\usebeamercolor[fg]{date}
|
||||||
|
# #+LATEX_HEADER: \tikz[overlay,remember picture]
|
||||||
|
# #+LATEX_HEADER: \node[xshift=-1cm,yshift=-1cm,text width=10cm] at (current page.north east) {
|
||||||
|
# #+LATEX_HEADER: 7$^{th}$ International Conference\\
|
||||||
|
# #+LATEX_HEADER: 8TH-10TH November\\
|
||||||
|
# #+LATEX_HEADER: EDF Lab - CHATOU, FRANCE
|
||||||
|
# #+LATEX_HEADER: }
|
||||||
|
# #+LATEX_HEADER: }
|
||||||
|
#+LATEX_HEADER: {
|
||||||
|
#+LATEX_HEADER: \usebeamerfont{title}\inserttitle\par
|
||||||
|
#+LATEX_HEADER: \usebeamerfont{title}\usebeamercolor[fg]{title}
|
||||||
|
#+LATEX_HEADER: }
|
||||||
|
#+LATEX_HEADER: \bigskip
|
||||||
|
#+LATEX_HEADER: \begin{center}
|
||||||
|
#+LATEX_HEADER: \usebeamerfont{subtitle}\usebeamercolor[fg]{subtitle}
|
||||||
|
#+LATEX_HEADER: {
|
||||||
|
#+LATEX_HEADER: \LARGE\insertsubtitle\par
|
||||||
|
#+LATEX_HEADER: }
|
||||||
|
#+LATEX_HEADER: \bigskip
|
||||||
|
#+LATEX_HEADER: \usebeamerfont{author}\usebeamercolor[fg]{author}\insertauthor\par
|
||||||
|
#+LATEX_HEADER: \bigskip
|
||||||
|
#+LATEX_HEADER: \usebeamerfont{institute}\usebeamercolor[fg]{institute}\insertinstitute\par
|
||||||
|
#+LATEX_HEADER: \bigskip
|
||||||
|
#+LATEX_HEADER: \usebeamerfont{date}\usebeamercolor[fg]{date}\insertdate\par
|
||||||
|
#+LATEX_HEADER: \usebeamercolor[fg]{titlegraphic}\inserttitlegraphic
|
||||||
|
#+LATEX_HEADER: \end{center}
|
||||||
|
#+LATEX_HEADER: }
|
||||||
|
|
||||||
|
# #+LATEX_HEADER: \newcommand{\tred}[1]{\textcolor{rouge_inrae}{#1}}
|
||||||
|
|
||||||
|
#+TODO: TODO WIP TOREVIEW | DONE
|
||||||
|
|
||||||
|
#+MACRO: pamhyr \textsc{PAMHyR}
|
||||||
|
#+MACRO: pamhyr2 \textsc{Pamhyr2}
|
||||||
|
|
||||||
|
#+MACRO: pause \pause
|
||||||
|
#+MACRO: framebreak \framebreak
|
||||||
|
#+MACRO: no
|
||||||
|
# #+MACRO: OK \checkmark
|
||||||
|
#+MACRO: OK \faIcon{check}
|
||||||
|
#+MACRO: bf \textbf{$1}
|
||||||
|
|
||||||
|
# #+latex: \frame{\tocpage}
|
||||||
|
|
||||||
|
* Problématique
|
||||||
|
|
||||||
|
** Problématique
|
||||||
|
|
||||||
|
*** Utilisateur
|
||||||
|
|
||||||
|
- Définire une version modifier de l'étude (changement dans les
|
||||||
|
données)
|
||||||
|
- Comparé des résultats entre une variante et l'étude
|
||||||
|
|
||||||
|
{{{pause}}}
|
||||||
|
|
||||||
|
**** COMMENT Développeur
|
||||||
|
:PROPERTIES:
|
||||||
|
:BEAMER_COL: 0.5
|
||||||
|
:BEAMER_ENV: block
|
||||||
|
:END:
|
||||||
|
|
||||||
|
- Un unique fichier
|
||||||
|
- Limité la duplication de donnée à sauvegarder
|
||||||
|
- Garder une bonne cohérence entre données et résultats
|
||||||
|
|
||||||
|
{{{pause}}}
|
||||||
|
|
||||||
|
*** Scénarios
|
||||||
|
:PROPERTIES:
|
||||||
|
:BEAMER_COL: 1
|
||||||
|
:BEAMER_ENV: definition
|
||||||
|
:END:
|
||||||
|
|
||||||
|
Un scénario est une variate d'une étude.
|
||||||
|
|
||||||
|
** Problématique -- Avancer
|
||||||
|
|
||||||
|
*** Utilisateur
|
||||||
|
|
||||||
|
- Définire une version modifier d'un senarios
|
||||||
|
- Comparé des résultats entre plusieurs senarios
|
||||||
|
|
||||||
|
{{{pause}}}
|
||||||
|
|
||||||
|
**** COMMENT Développeur
|
||||||
|
:PROPERTIES:
|
||||||
|
:BEAMER_COL: 0.5
|
||||||
|
:BEAMER_ENV: block
|
||||||
|
:END:
|
||||||
|
|
||||||
|
- Un unique fichier
|
||||||
|
- Limité la duplication de donnée à sauvegarder
|
||||||
|
- Garder une bonne cohérence entre données et résultats
|
||||||
|
|
||||||
|
{{{pause}}}
|
||||||
|
|
||||||
|
*** Scénarios
|
||||||
|
:PROPERTIES:
|
||||||
|
:BEAMER_COL: 1
|
||||||
|
:BEAMER_ENV: definition
|
||||||
|
:END:
|
||||||
|
|
||||||
|
Un scénario peut être l'étude ou une variate d'un autre scénario.
|
||||||
|
|
||||||
|
** Problématique -- Encore plus avancer
|
||||||
|
|
||||||
|
*** Utilisateur
|
||||||
|
|
||||||
|
- Définire un ensemble fini de variante correspondant a un ensemble de
|
||||||
|
valeur pour un(des) paramètre(s) et executer un solveur sur
|
||||||
|
l'ensemble des variantes
|
||||||
|
- Pouvoir comparé des metrics sur un ensemble de résultats trop grand
|
||||||
|
pour une comparaisont à la mains
|
||||||
|
|
||||||
|
{{{pause}}}
|
||||||
|
|
||||||
|
**** COMMENT Développeur
|
||||||
|
:PROPERTIES:
|
||||||
|
:BEAMER_COL: 0.5
|
||||||
|
:BEAMER_ENV: block
|
||||||
|
:END:
|
||||||
|
|
||||||
|
- Un unique fichier
|
||||||
|
- Limité la duplication de donnée à sauvegarder
|
||||||
|
- Garder une bonne cohérence entre données et résultats
|
||||||
|
|
||||||
|
{{{pause}}}
|
||||||
|
|
||||||
|
*** Scénarios
|
||||||
|
:PROPERTIES:
|
||||||
|
:BEAMER_COL: 1
|
||||||
|
:BEAMER_ENV: definition
|
||||||
|
:END:
|
||||||
|
|
||||||
|
Un scénario peut être l'étude, une variate d'un scénarios ou un
|
||||||
|
ensemble fini de variantes d'un scénarios.
|
||||||
|
|
||||||
|
** Problématique -- Encore plus plus avancer
|
||||||
|
|
||||||
|
*** Utilisateur
|
||||||
|
|
||||||
|
- Définire un ensemble fini de variante correspondant a un ensemble de
|
||||||
|
valeur pour un(des) paramètre(s) et faire un nombre fini de tirage
|
||||||
|
aléatoire dans ces paramètre pour executer un solveur ces paramètres
|
||||||
|
- Pouvoir comparé des metrics sur un ensemble de résultats trop grand
|
||||||
|
pour une comparaisont à la mains
|
||||||
|
|
||||||
|
{{{pause}}}
|
||||||
|
|
||||||
|
*** Scénarios
|
||||||
|
:PROPERTIES:
|
||||||
|
:BEAMER_COL: 1
|
||||||
|
:BEAMER_ENV: definition
|
||||||
|
:END:
|
||||||
|
|
||||||
|
Un scénario peut être l'étude, une variate d'un scénarios ou un
|
||||||
|
ensemble fini ou un tirage aléatoire dans un ensemble de variantes
|
||||||
|
d'un scénarios.
|
||||||
|
|
||||||
|
** Problématique -- Développeur
|
||||||
|
|
||||||
|
*** Développeur
|
||||||
|
|
||||||
|
- Permetre a l'utilisateur de *garder une bonne cohérence entre
|
||||||
|
données et résultats* de façon claire
|
||||||
|
- Permetre a l'utilisateur de *géré les scénarios* de façon claire
|
||||||
|
(représentation graphique)
|
||||||
|
- Garder *un unique fichier* (=.pamhyr=)
|
||||||
|
- *Limité la duplication* de donnée à sauvegarder
|
||||||
|
- Permetre à l'utilisateur de garder les *résultats pertinant* sans
|
||||||
|
exploser la mémoire de l'ordinateur
|
||||||
|
|
||||||
|
* Proposition
|
||||||
|
|
||||||
|
** Proposition -- Concept
|
||||||
|
|
||||||
|
*** {{{no}}}
|
||||||
|
\vspace{-1.2cm}
|
||||||
|
**** Deux type de scénarios
|
||||||
|
:PROPERTIES:
|
||||||
|
:BEAMER_COL: 0.5
|
||||||
|
:BEAMER_ENV: block
|
||||||
|
:END:
|
||||||
|
|
||||||
|
- Scénarios simple
|
||||||
|
- Scénarios d'éxecution d'ensemble
|
||||||
|
|
||||||
|
{{{pause}}}
|
||||||
|
|
||||||
|
**** Scénarios simple
|
||||||
|
:PROPERTIES:
|
||||||
|
:BEAMER_COL: 0.5
|
||||||
|
:BEAMER_ENV: block
|
||||||
|
:END:
|
||||||
|
|
||||||
|
Est composer:
|
||||||
|
- d'un identifiant unique
|
||||||
|
- d'un nom (définie par l'utilisateur)
|
||||||
|
- d'une description (définie par l'utilisateur)
|
||||||
|
- d'un parent (définie par l'utilisateur)
|
||||||
|
|
||||||
|
{{{pause}}}
|
||||||
|
|
||||||
|
\vspace{-0.5cm}
|
||||||
|
|
||||||
|
*** Scénarios d'ensembles
|
||||||
|
|
||||||
|
**** {{{no}}}
|
||||||
|
:PROPERTIES:
|
||||||
|
:BEAMER_COL: 0.5
|
||||||
|
:BEAMER_ENV: block
|
||||||
|
:END:
|
||||||
|
\vspace{-1cm}
|
||||||
|
Est composer:
|
||||||
|
- d'un identifiant unique
|
||||||
|
- d'un nom (définie par l'utilisateur)
|
||||||
|
- d'une description (définie par l'utilisateur)
|
||||||
|
- d'un parent (définie par l'utilisateur)
|
||||||
|
- d'un ou plusieurs ensemble de valeur
|
||||||
|
|
||||||
|
**** {{{no}}}
|
||||||
|
:PROPERTIES:
|
||||||
|
:BEAMER_COL: 0.5
|
||||||
|
:BEAMER_ENV: block
|
||||||
|
:END:
|
||||||
|
\vspace{-0.5cm}
|
||||||
|
Un ensemble de valeurs est definie par:
|
||||||
|
- une valeurs de départ
|
||||||
|
- une valeurs de fin
|
||||||
|
- un pas de valeur
|
||||||
|
- un élément d'origine (élément définie dans l'étude)
|
||||||
|
- une fonctions (modification de l'élément à l'aide d'une valeur de
|
||||||
|
l'ensemble)
|
||||||
|
|
||||||
|
** Proposition -- Limitation
|
||||||
|
|
||||||
|
*** Scénarios simple
|
||||||
|
:PROPERTIES:
|
||||||
|
:BEAMER_COL: 0.5
|
||||||
|
:BEAMER_ENV: block
|
||||||
|
:END:
|
||||||
|
|
||||||
|
Si le scénarios est le *parent d'un autre scénarios*, il ne *peut plus
|
||||||
|
être modifier* sans risquer des comportement difficilement
|
||||||
|
comprehensible pour l'utilisateur.
|
||||||
|
|
||||||
|
{{{pause}}}
|
||||||
|
|
||||||
|
*** Scénarios d'ensembles
|
||||||
|
:PROPERTIES:
|
||||||
|
:BEAMER_COL: 0.5
|
||||||
|
:BEAMER_ENV: block
|
||||||
|
:END:
|
||||||
|
|
||||||
|
- Un scénarios d'ensemble *ne peut pas être parent* d'un autre
|
||||||
|
scénarios
|
||||||
|
- Le nombre d'exécution peut très rapidement grossir
|
||||||
|
|
||||||
|
** Proposition -- Affichage
|
||||||
|
|
||||||
|
#+name: graph-scenarios
|
||||||
|
#+header: :results drawer
|
||||||
|
#+header: :exports results
|
||||||
|
#+header: :post attr_wrap(width="7cm", data=*this*, name="graph-scenarios", caption="Exemple of scenarios graph", float="t")
|
||||||
|
#+begin_src dot :file "images/graph-scenarios.png" :cache no
|
||||||
|
digraph {
|
||||||
|
bgcolor="transparent";
|
||||||
|
node[colorscheme=pastel19,shape=ellipse,style="filled",fillcolor=9];
|
||||||
|
|
||||||
|
b[fillcolor=2];
|
||||||
|
|
||||||
|
aa[shape=box,fillcolor=2];
|
||||||
|
aa2[label="aa'", shape=box, fillcolor=2];
|
||||||
|
ad[shape=box, fillcolor=2];
|
||||||
|
re[shape=box, fillcolor=2];
|
||||||
|
rf[shape=box, fillcolor=2];
|
||||||
|
|
||||||
|
default -> a;
|
||||||
|
default -> b;
|
||||||
|
default -> c;
|
||||||
|
|
||||||
|
a -> aa;
|
||||||
|
a -> aa2;
|
||||||
|
a -> f -> rf;
|
||||||
|
c -> d -> ad;
|
||||||
|
c -> e -> re;
|
||||||
|
}
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
#+RESULTS[80ed2484b9cc71143f800ff23c10846fd04697c3]: graph-scenarios
|
||||||
|
:results:
|
||||||
|
#+CAPTION[]: Exemple of scenarios graph
|
||||||
|
#+NAME: graph-scenarios
|
||||||
|
#+ATTR_LATEX: :width 7cm :float t
|
||||||
|
[[file:images/graph-scenarios.png]]
|
||||||
|
:end:
|
||||||
|
|
||||||
|
* Solution technique
|
||||||
|
|
||||||
|
** Technique -- scénarios
|
||||||
|
|
||||||
|
#+begin_src sql
|
||||||
|
CREATE TABLE scenario(
|
||||||
|
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||||
|
name TEXT NOT NULL, -- Name of the scenario
|
||||||
|
description TEXT NOT NULL, -- Rich text description
|
||||||
|
parent_id INTEGER REFERENCES scenario(id) -- Recursive references
|
||||||
|
-- for parent scenario
|
||||||
|
)
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
** Technique -- Données -- Enregistrement
|
||||||
|
|
||||||
|
#+begin_src sql
|
||||||
|
-- Unique ID (Must be unused, to delete)
|
||||||
|
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||||
|
-- New ID (not unique)
|
||||||
|
pamhyr_id INTEGER NOT NULL,
|
||||||
|
-- (Optional) Flag for set there is no data in this scenario and
|
||||||
|
-- ignore parent scenario
|
||||||
|
dummy BOOLEAN NOT NULL,
|
||||||
|
-- Corresponding scenario
|
||||||
|
scenario_id INTEGER NOT NULL,
|
||||||
|
PRIMARY KEY(pamhyr_id, scenario_id),
|
||||||
|
FOREIGN KEY(scenario_id) REFERENCES scenario(id),
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
** Technique -- Données -- Chargement
|
||||||
|
|
||||||
|
#+begin_src python :python python3 :results output :noweb yes
|
||||||
|
def load(cls, db, current_scenario):
|
||||||
|
# Default case, end of recursion
|
||||||
|
if current_scenario is None:
|
||||||
|
return [] # Default value
|
||||||
|
|
||||||
|
table = db.execute(f"<MY SELECT> WHERE scenario_id = {current_scenario}")
|
||||||
|
|
||||||
|
# If no data for this scenario, recursion
|
||||||
|
if len(table) == 0:
|
||||||
|
parent_id = db.get_parent_id(current_scenario)
|
||||||
|
return cls.load(db, parent_id)
|
||||||
|
|
||||||
|
# Otherelse, parse data and return...
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
** Technique -- Données -- Modification
|
||||||
|
|
||||||
|
#+begin_src python :python python3 :results output :noweb yes
|
||||||
|
def set_modified(self, current_scenario):
|
||||||
|
self.scenario = current_scenario
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
#+begin_src python :python python3 :results output :noweb yes
|
||||||
|
def delete(self, current_scenario):
|
||||||
|
self.deleted = True
|
||||||
|
self.set_modified(current_scenario)
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
** Technique -- Exécution d'ensemble
|
||||||
|
|
||||||
|
#+begin_src sql
|
||||||
|
CREATE TABLE range_set(
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
start REAL NOT NULL, -- Range start
|
||||||
|
end REAL NOT NULL, -- Range end
|
||||||
|
step REAL NOT NULL, -- Range step
|
||||||
|
generator_name TEXT NOT NULL, -- Generator function name (ex:
|
||||||
|
-- 'minor_strickler')
|
||||||
|
original_data_id INTEGER, -- (optional) Ref to data who apply
|
||||||
|
-- this range (ex: a strickler id)
|
||||||
|
scenario_id INTEGER NOT NULL,
|
||||||
|
FOREIGN KEY(scenario_id) REFERENCES scenario(id)
|
||||||
|
)
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
* Sauvegarde des résultats
|
||||||
|
|
||||||
|
** Sauvegarde des résultats
|
||||||
|
|
||||||
|
*** Scénarios simple
|
||||||
|
|
||||||
|
Sauvegarde d'un seul résultats complet par scénarios (et par solver).
|
||||||
|
|
||||||
|
*** Scénarios d'ensemble
|
||||||
|
|
||||||
|
Sauvegarde de metrics récupéré sur un ensemble de résultats (pas de
|
||||||
|
sauvegarde de tous les résultats) ou certain résultats particuliers.
|
||||||
|
|
||||||
|
* Question & remarque
|
||||||
|
|
||||||
|
** Question & remarque
|
||||||
|
|
||||||
|
- Solution satisfaisante ?
|
||||||
|
- Cas d'usage intéressent non couvert ?
|
||||||
|
- Contre exemple ?
|
||||||
|
- Meilleur solution ?
|
||||||
Loading…
Reference in New Issue