Compare commits

..

7 Commits

Author SHA1 Message Date
Jean Sirmai b2bccc8da4
src/fsm/log/oper.c fsm_add_log_event() fixing a bug
The bug was caused by pointers to local variables sended to fsm_add_log().
malloc() are now realized in fsm_add_log_event().

+ cleaning (checking that the sentence "This file is part of Gem-graph."
is systematicaly added to legal mentions.)
2024-11-13 17:17:36 +01:00
Jean Sirmai faba304ba4
src/widget/main_window/design First visible window (with memory leaks)
To display this minimal window, three files and two functions must be
added simultaneously:

- include/widget/h
- src/manager.c
- src/main_window/design.c

main() now contains: g_signal_connect (on_windows_activation);
on_windows_activation () is in src/manager.c and calls
widget_main_window () which is in src/main_window/design.c

NB  The iconic image of E coli drawn by David S. Goodsell in 2009
is reproduced here with permission.

One goal of Gem-graph is to animate such static representations
i.e. use the best anatomy to try to achieve good physiology.
2024-11-12 17:15:12 +01:00
Jean Sirmai dc74605850
docs/rtfm/intro writing + cleaning details in src/ 2024-11-11 23:44:02 +01:00
Jean Sirmai de9b28520a
rtfm/intro (writing the manual) + cleaning doc 2024-11-11 23:36:02 +01:00
Jean Sirmai 7b51248aa5
* modifies several names:
* - in fsm_trigger_log_init(), fsm_trigger_log_close() the word **trigger** is
 * replaced by **relay**
 * - fsm_log_struct_unit is replaced by: fsm_log_unit_struct
 *
 * docs/rtfm/intro (previously 'Once upon a time'... 🙃️) is also renamed and
 * extended.
 *
2024-11-11 16:39:47 +01:00
Jean Sirmai 74894b5253
rtfm/intro Manual Introduction - a first version.
The same text is presented in two formats: for an external text editor (.txt)
or with lines limited to 80 characters.

The links are prepared but not functionnal.
2024-11-10 19:55:24 +01:00
Jean Sirmai 4d97b5328e
src/fsm/control.c fsm_init() and fsm_close() can be now triggered from main().
These two functions (defined in control.c) initiate the log and print it just
before the end of the program.
It is now possible to send messages that reports the events occuring during a
session: the creation of the log, then of the application and their closure in
the reverse order.
As previously,there is no g signal connect (activate) and no window is created.
This triggers the same error message in the console.
What is new, in this commit, is that a first log is printed in the console.
2024-11-09 08:03:55 +01:00
13 changed files with 667 additions and 659 deletions

342
docs/readme Normal file
View File

@ -0,0 +1,342 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Gem-graph client *
* What the documentation contains and how to use it *
* Docstring content: rationale and usage *
* Alphabetic Index 2024 of functions names *
* *
* Copyright © 2021 Libre en Communs <contact@a-lec.org> *
* Copyright © 2024 Jean Sirmai <jean@a-lec.org> *
* *
* This file is part of Gem-graph. *
* *
* This program is free software: you can redistribute it and/or modify it *
* under the terms of the GNU Affero General Public License *
* as publishedby 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 Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
This file gives you information on how best to use the doc and a few tips for
personalising it.
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Attention
Let's repeat that, because it is often overlooked:
to document global objects (functions, typedefs, enum, macros, etc),
you must document the file in which they are defined.
In other words, there must at least be a
/** \file */
(or /*! \file */)
line in this file.
---------------------------------------------------------------------------
*
* docstrings
* ----------
*
* @brief
* @details
* @date
* @author
* @callgraph
* @see (liste des fonctions appelées par cette fonction)
* @callergraph
* @see (liste des fonctions qui appellent cette fonction)
* @param (liste des paramètres)
* @return
---------------------------------------------------------------------------
* TODO : valgrind bin/gem-graph-client
* sanitize
*
/* * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* C O N V E N T I O N S E T R È G L E S D E N O M M A G E - 2 0 2 4
*
* Le nom d'une fonction doit permettre d'identifier facilement:
* - le lieu (le fichier) où elle est définie,
* - le type d'action qu'elle exécute et
* - les objets modifiés par son action.
*
* - - -
*
* Ces trois informations sont encodées au moyen de trois "préfixes"
* associés et concaténés dans cet ordre pour former le nom.
*
* - - -
*
* En octobre 2024, la première version de cet:
* "index alphabétique des fonctiond du client gem-graph"
* classe en trois listes l'ensemble des préfixes utilisés.
*
* Ces listes sont en cours d'élaboration.
* Elles ne sont ni limitatives ni exhaustives ni ordonnées.
* TODO
*
* - - -
*
* Le premier préfixe est l'adresse du fichier dans la hiérarchie "src":
* ex: graphics_draw_
* fsm_measures_manager_
* util_draw_gl_
* widget_one_rule_algebra_assign_
*
* Le deuxième préfixe est choisi dans une liste de fonctions types:
* get, set, reset, read, write, print, edit, concat, design,
* init, create, add, remove, erase, restore, trigger, draw, push
* setup, shutdown, update, list, sort, seek, select, fix, debug,
* render, realize, unrealize, activate, exec, stop, signal,
*
* Le troisième préfixe est choisi dans une liste d'objets ou d'états
* qui sont modifiés par les fonctions.
* Ce préfixe peut être composé de deux, trois ou quatre items
* appartenant à cette liste et d'une conjonction si besoin.
* ex: axis_slider, stack_slot_size, user_tree_model_child,
* grids_on_space_faces_lines, current_model_before_editing, etc.
*
* number, string, view, image, window, list, tree, stack,
* file, buffer, callback, signal,
* widget, button, slider, color, glarea, shader,
* point, line, plan, space_unit, site, arrow, slot, vertex, ridge, axis
* state, rules, data, results, stock,
*
*
*
* Le 2024-10-05, seules trois fonctions ne sont pas nommées selon ces règles:
* > create_axis_slider, free_stack_slot, free_stack_slot_size <
*
* et les noms de cinq autres pourraient être améliorés.
* graphics_shutdown_graphics_stack > graphics_shutdown_stack < ex.
* * * * * * * * * * * * * * * * * * * * * * * * * * */
create_axis_slider util/draw/gl 223 << to rename
free_stack_slot graphics/init 36 << to rename
free_stack_slot_size graphics/init 37 << to rename
get_user_tree_model util/tree 66 static
get_user_tree_model_child util/tree 49 static
graphics_create_shader 187 ?
graphics_debug_callback graphics/init 53 static
graphics_draw graphics/draw 150
graphics_draw_color graphics/draw 74
graphics_draw_grids_on_space_faces_lines graphics/grid 129
graphics_draw_grids_on_space_faces_vertex graphics/grid 75
graphics_draw_line graphics/draw 100
graphics_draw_one_arrow_line 365 ?
graphics_draw_one_arrow_vertex 355 ?
graphics_draw_plan graphics/draw 124
graphics_draw_space_ridges_lines graphics/grid 62
graphics_draw_space_ridges_vertex graphics/grid 30
graphics_draw_vertex graphics/draw 40
graphics_init graphics/init 108
graphics_init_buffers graphics/init 326
graphics_init_graphics_stack 127 ?
graphics_init_shaders graphics/init 370
graphics_model_setup graphics/init 228
graphics_print_stack 221 ?
graphics_render_stack 87 ?
graphics_set_arrow 401 ?
graphics_setup_glarea 89 ?
graphics_shutdown graphics/init 169
graphics_shutdown_graphics_stack 128 << to rename
graphics_stack graphics/init 34
graphics_stack_size graphics/init 35
graphics_stack_t graphics.h
graphics_update_axis_stack 129 ?
fsm_add_data fsm/measures/data_list
fsm_add_displayable fsm/preferences/manager
fsm_add_measure fsm/measures/manager
fsm_add_result fsm/results/manager
fsm_disp_add_chart fsm/measures/disp_list
fsm_disp_get_chart fsm/measures/disp_list
fsm_disp_remove_chart fsm/measures/disp_list
fsm_enum_exec_edit fsm.h
fsm_enum_journal_severity fsm.h
fsm_enum_journal_source fsm.h
fsm_enum_measure_type fsm.h
fsm_enum_state_rules_data fsm.h
fsm_enum_store_restore_reset fsm.h
fsm_get_data fsm/measures/data_list
fsm_get_exec_edit fsm/dispatch
fsm_get_preferences_state fsm/dispatch
fsm_get_state_rules_data fsm/dispatch
fsm_init fsm/dispatch
fsm_journal_clear src/journal
fsm_journal_event fsm/dispatch
fsm_journal_init src/journal
fsm_journal_length src/journal
fsm_journal_pop_back src/journal
fsm_journal_publication_request fsm/dispatch
fsm_journal_publish src/journal
fsm_journal_push_front src/journal
fsm_journal_seek src/journal
fsm_list_init_displayables fsm/prefer
fsm_list_init_measures fsm/measures/manager
fsm_list_init_preferences fsm/preferences/manager
fsm_list_init_results fsm/results/manager
fsm_list_tools_clear fsm/measures/tools_list
fsm_list_tools_insert fsm/measures/tools_list
fsm_list_tools_length fsm/measures/tools_list
fsm_list_tools_pop fsm/measures/tools_list
fsm_list_tools_test fsm/measures/tools_list
fsm_list_tools_view fsm/measures/tools_list
fsm_remove_data fsm/measures/data_list
fsm_reset_all_situations_values fsm/preferences/manager
fsm_rule_trig_measure fsm/measures/manager
fsm_set_exec_edit fsm/dispatch
fsm_set_preferences_modified fsm/dispatch
fsm_set_state_rules_data fsm/dispatch
fsm_set_store_restore_reset fsm/dispatch
fsm_struct_journal fsm.h
fsm_struct_journal_unit fsm.h
fsm_struct_list_data fsm.h
fsm_struct_list_disp fsm.h
fsm_struct_list_tool fsm.h
on_auto_notification signal 37 static
on_axis_value_change signal 181
on_bind_user_tree_factory signal 81
on_clicked_topbar_right_home signal 373 << to rename
on_clicked_topbar_right_search signal 364 << to rename
on_discard_current_model_before_editing signal 228
on_entry_name_delete_after signal 547
on_entry_name_insert_after signal 542
on_glarea_realize signal 132
on_glarea_render signal 112
on_glarea_unrealize signal 158
on_measure_ ... signal 453 sqq.
on_realize_debug util/draw/gl 335 static
on_render_debug util/draw/gl 345 static
on_resetting_XYZ_in_state_page signal 404
on_save_current_model_before_editing signal 220
on_select_rules_first signal 446
on_setup_user_tree_factory signal 73
on_situations_box_do_reset signal 412
on_start_new_measure signal 439
on_toggle_exec_edit signal 254 << to rename
on_toggle_state_rules_data signal 286 << to rename
on_topbar_right_measure_clicked signal 426
on_updating_objects_transparencies signal 389
on_user_tree_expander_toggled signal 64 static
on_windows_activation widget/dispatch 67
on_windows_startup widget/dispatch 61
on_write_current_model signal 236
parse_model_get_dim util/parse 231
parse_model_get_dim_value util/parse 244
parse_model_get_multiplicity util/parse 255
parse_model_get_next_arrow util/parse 346
parse_model_get_next_state util/parse 269
parse_model_get_state_arrows_count util/parse 295
parse_model_init 29 (not used)
parse_model_shutdown util/parse 88
parse_parse_model_init util/parse 46
shader frag graphics/shader
shader vert graphics/shader
stack_index stack_index 38
stack_index_size stack_index 39
stack_index_t util/draw/gl.c 32
switch_state_rules_data signal 305 static
TreeNode_t widget.h (rename ?)
util_concat util/strings_op
util_gl_clean_stack_index util/draw/gl.c 150
util_gl_get_stack util/draw/gl.c 66
util_gl_init_stack util/draw/gl.c 102
util_gl_is_ready util/draw/gl.c 84
util_gl_is_util_ready 92 TODO
util_gl_render_stack util/draw/gl.c 166
util_gl_set_arrow util/draw/gl.c 42
util_gl_setup_glarea util/draw/gl.c 364
util_gl_shutdown_all_stacks util/draw/gl.c 207
util_gl_shutdown_stack util/draw/gl.c 133
util_gl_update_axis util/draw/gl.c 187
util_list_2x2_ ^c^v (8 fonctions) util/list_2x2
util_pile_ ^c^v (5 fonctions) util/pile
util_read_file util/io
util_sorted_list_ ^c^v (5 fonctions) util/sorted_list
util_test_double_list util/tests
util_test_pile util/tests
util_test_sorted_list util/tests
util_trigger_test util/tests
widget_add_tree_child_node util/tree 32
widget_create_user_rules_tree_node util/tree 41
widget_design_dialog_window widget/dispatch
widget_design_main_window widget/dispatch
widget_design_text_window widget/dispatch
widget_measure_do_select_rules_first widget/measure/dispatch
widget_measure_do_ ... 295 sqq.
widget_measure_event_occurences_dates widget/measure/dispatch
widget_measure_event_occurences_nb widget/measure/dispatch
widget_measure_event_occurences_situations widget/measure/dispatch
widget_measure_other_events_between_the_two widget/measure/dispatch
widget_measure_time_elapsed_between_two_events widget/measure/dispatch
widget_get_address_text_theory widget/topbar/dispatch
widget_get_address_text_practice widget/topbar/dispatch
widget_get_btt_label_data widget/topbar/left
widget_get_btt_label_rules widget/topbar/left
widget_get_btt_label_state widget/topbar/left
widget_get_btt_label_synth widget/topbar/left
widget_get_dialog_window widget/dispatch
widget_get_graph_view_control widget/state/middle
widget_get_main_window widget/dispatch
widget_get_non_time_dependent widget/synth/dispatch
widget_get_object_transparency widget/state/top
widget_get_page_data widget/results/dispatch
widget_get_page_engine 104 TODO
widget_get_page_measure widget/measure/dispatch
widget_get_page_state widget/state/dispatch
widget_get_page_synth widget/synth/dispatch
widget_get_pane_all_rules_left widget/all_rules/dispatch
widget_get_pane_selected_rule_right widget/one_rule/dispatch
widget_get_results_box_display widget/results/display
widget_get_results_box_organize widget/results/organize
widget_get_results_box_time widget/results/display
widget_get_rule_edition_tools widget/one_rule/geometry/edit
widget_get_rule_investigation_tools widget/one_rule/geometry/investigate
widget_get_rule_geometry_and_algebra 187 TODO (not yet used)
widget_get_rules_pilot_box widget/all_rules/tree/pilot_box
widget_get_rules_tree_tools widget/all_rules/tree/pilot_box
widget_get_rules_use widget/all_rules/tree/freq
widget_get_selected_rule widget/one_rule/dispatch
widget_get_selected_rule_algebra widget/one_rule/algebra/dispatch
widget_get_selected_rule_assignations_list_btt widget/one_rule/algebra/assign
widget_get_selected_rule_before_after widget/one_rule/geometry/geometry
widget_get_selected_rule_camera widget/one_rule/geometry/camera
widget_get_selected_rule_conditions_list_btt widget/one_rule/algebra/conditions
widget_get_selected_rule_geometry widget/one_rule/geometry/dispatch
widget_get_selected_rule_identity_btt widget/one_rule/algebra/identity
widget_get_sequence_control widget/state/bottom
widget_get_space_edit_control widget/state/bottom
widget_get_space_view widget/state/middle
widget_get_space_vs_non_time_dependent widget/synth/dispatch
widget_get_text_from_address widget/topbar/modal
widget_get_text_window widget/dispatch
widget_get_time_dependent widget/synth/time
widget_get_user_rules_tree util/tree 88
widget_reset_XYZ_in_state_pane widget/state/middle TODO (dispatch)
widget_reset_XYZ_scrollbars_rule 166 TODO
widget_reset_XYZ_scrollbars_state 167 TODO
widget_reset_XYZ_scrollbars_synth 168 TODO
widget_set_item_text widget/one_rule/algebra/dispatch
widget_set_objects_value widget/state/top
widget_set_situations_value widget/state/top
window_design_topbar_left widget/dispatch
window_design_topbar_right widget/dispatch

163
docs/rtfm/intro 80 char Normal file
View File

@ -0,0 +1,163 @@
Welcome to Gem-graph !
Gem-graph lets you move and transform drawn objects using an automaton. It's an
ideal tool for describing the evolution of a situation through drawing. Would
you like to see your drawings evolve automatically to represent a phenomenon?
Gem-graph lets you transform your drawings as you wish. You can draw whatever
you want. It's your drawing and you decide how it evolves! You can use gem-graph
to make a game. You can use it to make a model of a phenomenon that interests you.
You can represent what you want simply or in more realistic detail.
Simple parts and more detailed parts can coexist in the same design. You can
watch what you have created evolve without interfering or guiding it towards what
you want to achieve. You can mix several drawings and animations. You can observe
them in detail, modify them, go back, start again, measure, compare and keep the
results that interest you so that you can play them again.
However, a certain amount of effort will be required to achieve this. A complicated
model will require more work than a simpler one, but it is possible to start with
something simple and develop it step by step. In any case, you must draw what you
want to see and say how you want it to be transformed. Gem-graph cannot do that
for you. Gem-graph can only help you to draw up and develop your idea. However,
it can give you powerful tools to do so. The strength of gem-graph - short for
'geometric graph' - lies in the fact that it deals only with very simple drawing
elements, all of which are similar, and that the rules it uses to manipulate these
elements are equally simple and similar. As a result, these rules can be combined
and processed automatically, no matter how many there are. The tools provided by
gem-graph give you access to the power of the automaton it uses to draw and animate
your drawings, and this manual is here to help you to learn how to master them.
One way of doing this is to reproduce a very simple example, such as when a word
processing program asks you to write "Hello world". For gem-graph, the equivalent
of "Hello world" will be to move a small line on your screen. Once you have done
this simple example, you will know enough to quickly build and animate much more
complex drawings that suit your desires. If you like learning this way, this
example is explained (here). If you prefer to learn by reading what the commands
you see on the screen are doing, they have been detailed (here). The table of
contents goes from the simplest to the most complicated. How to set up a simple
model, observe it and measure what it does, then transform it by changing what
you see and how it reacts.
------------
Our "Hello world" is the simplest program that gem-graph can execute. It consists
of a single short arrow, which moves in a straight line in a single direction.
To do this, we first had to draw this little arrow and then make it move. The
result is certainly not very exciting, but this example is enough to show how a
drawing is made and how it is animated. One state and one rule are enough. The
rule only says: if an arrow is drawn here, I erase it and redraw it on the next
square. For the moment, you don't need to know in detail how the rule works
(it's described here). All that gem-graph needs to know is written in the
"Hello world" file (here). If you open this file, you'll find a description of
the arrow (here) and its movement (there).
------------
To improve this model, it is possible to give the arrow the ability to move in
two directions: forwards or backwards. To do this, we need to add a second rule.
This second rule says: if an arrow is drawn here, I erase it and redraw it on the
previous square. A random draw (described here) is also necessary to determine
whether the first or second rule applies. With these two rules and the random
draw, the arrow now sometimes goes forwards, sometimes backwards. We can call
this second model a "random walk".
------------
The second model (the random walk) had one state (the arrow) and two rules
(forward/backward). Now here's a model with two states and two rules:
the "pendulum". This time, the arrow can be drawn either tilted forwards or tilted
backwards (these are the two possible states) and the two rules switch the drawn
arrow from one state to the other or vice versa. In the file, the states are (here)
and the rules (here). The pendulum does not change place, but alternates between
left and right. Like the previous ones, you can slow down the programme so that
you can observe the movements.
------------
Once you know how to write a state and a rule, you can write thousands of them:
they will always be combinations of the same elementary form. However, it is also
possible to combine programs: for example, you can combine the reports and rules
from the two previous models to create a new model that shows both phenomena
simultaneously. Once again, in the file, the states are (here) and the rules
(here).
------------
The next example shows how the same rule can be applied to a multitude of states.
The rule is the same as that used in the first model: an arrow can only be moved
one square forward, but this time you have to check that the square forward is
free. If it isn't, the arrow won't move. Once the rule has been modified in this
way (see how), it can be applied to a multitude of arrows distributed randomly in space
(see more details here).
When you set the model in motion, you will see all these small lines moving from
left to right. A single rule is responsible for all these movements.
For a small fee, we can apply the two rules of the 'random walk' model to all the
arrows distributed in this space, and they will then all behave in the same way,
sometimes moving forwards, sometimes backwards.
------------
In the next example, we first build a model similar to the previous one: a
multitude of arrows are randomly distributed in space, but this time they are
vertical and the movements are up and down instead of right and left. Then, we
add this model to the previous state and set the final model in motion. We see
then little lines moving from left to right or reverse if they are horizontal,
and up and down or reverse if they are vertical. Their number is constant. They
don't change shape or direction. There seems to be no accident when they cross.
Nothing else happens.
------------
The last example in this series, because it shows a multitude of diverse and
simultaneous movements, perhaps gives the impression of a more complex system.
It would be easy to make it even more complex, but it's much more interesting
to show how gem-graph can be used to analyse and control that complexity (here). At
this point, it's time to compare gem-graph to other classes of automata that do
quite similar things, and to look at what it can actually do and what its
limitations are.
------------
The main difference between gem-graph models and agent-based models is that
gem-graph deals with situations, not agents. In a situation where several agents
are interacting and each agent could apply a different rule, gem-graph considers
and processes the situation. Not the agents. Whatever the new situation that
results from his action, his decision-making process will have been simple and
straightforward. It will therefore be easy to modify and control. And the
diversity of possible new situations will be far greater than that offered by
agent-based models.
------------
The comparison between gem-graphs and cellular automata first comes up against
a question of vocabulary. What is commonly called a 'rule' in one and the other
is not the same thing. Gem-graphs and cellular automata have the same power:
anything that can be done by one can be done by the other, but their writing is
not the same (details of this comparison here).
------------
How can gem-graph be used to analyse and control the complexity of what it
represents and sets in motion? This chapter introduces the gem-graph mechanism.
------------
Gem-graph can reproduce the behavior of any cellular automata. Whatever the state
of the cellular automaton space at a given time (n), this state can be considered
as a gem-graph state and a rule can be written to transform it into the next
state (n+1).
The difference with the cellular automaton is that this rule is not generated by
a "micro-rule" applied cell by cell to the entire state (n). This rule must be
written by hand and its writing requires knowledge of state (n+1).
Writing all the rules that describe all the transformations that have occurred
when a cellular automaton describes a trajectory (a story) is certainly tedious,
but it is always possible. And the number of possible histories that gem-graph
rules can describe is limited only by the size of the space and the number of
symbols it contains.
If a set of "micro-rules", each applied cell by cell to the entire state (n) of
a cellular automaton, can produce all the possible states that the gem-graph can
describe, the two representations can be considered to be equivalent in power.

60
docs/rtfm/intro.txt Normal file
View File

@ -0,0 +1,60 @@
Welcome to Gem-graph !
Gem-graph lets you move and transform drawn objects using an automaton. It's an ideal tool for describing the evolution of a situation through drawing. Would you like to see your drawings evolve automatically to represent a phenomenon? Gem-graph lets you transform your drawings as you wish. You can draw whatever you want. It's your drawing and you decide how it evolves! You can use gem-graph to make a game. You can use it to make a model of a phenomenon that interests you. You can represent what you want simply or in more realistic detail. Simple parts and more detailed parts can coexist in the same design. You can watch what you have created evolve without interfering or guiding it towards what you want to achieve. You can mix several drawings and animations. You can observe them in detail, modify them, go back, start again, measure, compare and keep the results that interest you so that you can play them again.
However, a certain amount of effort will be required to achieve this. A complicated model will require more work than a simpler one, but it is possible to start with something simple and develop it step by step. In any case, you must draw what you want to see and say how you want it to be transformed. Gem-graph cannot do that for you. Gem-graph can only help you to draw up and develop your idea. However, it can give you powerful tools to do so. The strength of gem-graph - short for 'geometric graph' - lies in the fact that it deals only with very simple drawing elements, all of which are similar, and that the rules it uses to manipulate these elements are equally simple and similar. As a result, these rules can be combined and processed automatically, no matter how many there are. The tools provided by gem-graph give you access to the power of the automaton it uses to draw and animate your drawings, and this manual is here to help you to learn how to master them.
One way of doing this is to reproduce a very simple example, such as when a word processing program asks you to write "Hello world". For gem-graph, the equivalent of "Hello world" will be to move a small line on your screen. Once you have done this simple example, you will know enough to quickly build and animate much more complex drawings that suit your desires. If you like learning this way, this example is explained (here). If you prefer to learn by reading what the commands you see on the screen are doing, they have been detailed (here). The table of contents goes from the simplest to the most complicated. How to set up a simple model, observe it and measure what it does, then transform it by changing what you see and how it reacts.
------------
Our "Hello world" is the simplest program that gem-graph can execute. It consists of a single short arrow, which moves in a straight line in a single direction. To do this, we first had to draw this little arrow and then make it move. The result is certainly not very exciting, but this example is enough to show how a drawing is made and how it is animated. One state and one rule are enough. The rule only says: if an arrow is drawn here, I erase it and redraw it on the next square. For the moment, you don't need to know in detail how the rule works (it's described here). All that gem-graph needs to know is written in the "Hello world" file (here). If you open this file, you'll find a description of the arrow (here) and its movement (there).
------------
To improve this model, it is possible to give the arrow the ability to move in two directions: forwards or backwards. To do this, we need to add a second rule. This second rule says: if an arrow is drawn here, I erase it and redraw it on the previous square. A random draw (described here) is also necessary to determine whether the first or second rule applies. With these two rules and the random draw, the arrow now sometimes goes forwards, sometimes backwards. We can call this second model a "random walk".
------------
The second model (the random walk) had one state (the arrow) and two rules (forward/backward). Now here's a model with two states and two rules: the "pendulum". This time, the arrow can be drawn either tilted forwards or tilted backwards (these are the two possible states) and the two rules switch the drawn arrow from one state to the other or vice versa. In the file, the states are (here) and the rules (here). The pendulum does not change place, but alternates between left and right. Like the previous ones, you can slow down the programme so that you can observe the movements.
------------
Once you know how to write a state and a rule, you can write thousands of them: they will always be combinations of the same elementary form. However, it is also possible to combine programs: for example, you can combine the reports and rules from the two previous models to create a new model that shows both phenomena simultaneously. Once again, in the file, the states are (here) and the rules (here).
------------
The next example shows how the same rule can be applied to a multitude of states. The rule is the same as that used in the first model: an arrow can only be moved one square forward, but this time you have to check that the square forward is free. If it isn't, the arrow won't move. Once the rule has been modified in this way (see how), it can be applied to a multitude of arrows distributed randomly in space (see more details here).
When you set the model in motion, you will see all these small lines moving from left to right. A single rule is responsible for all these movements.
For a small fee, we can apply the two rules of the 'random walk' model to all the arrows distributed in this space, and they will then all behave in the same way, sometimes moving forwards, sometimes backwards.
------------
In the next example, we first, we build a model similar to the previous one: a multitude of arrows are randomly distributed in space, but this time they are vertical and the movements are up and down instead of right and left. Then, we add this model to the previous state and set the final model in motion. We see then little lines moving from left to right or reverse if they are horizontal, and up and down or reverse if they are vertical. Their number is constant. They don't change shape or direction. There seems to be no accident when they cross. Nothing else happens.
------------
The last example in this series, because it shows a multitude of diverse and simultaneous movements, perhaps gives the impression of a more complex system. It would be easy to make it even more complex, but it's much more interesting to show how gem-graph can be used to analyse and control that complexity. At this point, it's time to compare gem-graph to other classes of automata that do quite similar things, and to look at what it can actually do and what its limitations are.
------------
The main difference between gem-graph models and agent-based models is that gem-graph deals with situations, not agents. In a situation where several agents are interacting and each agent could apply a different rule, gem-graph considers and processes the situation. Not the agents. Whatever the new situation that results from his action, his decision-making process will have been simple and straightforward. It will therefore be easy to modify and control. And the diversity of possible new situations will be far greater than that offered by agent-based models.
------------
The comparison between gem-graphs and cellular automata first comes up against a question of vocabulary. What is commonly called a 'rule' in one and the other is not the same thing. Gem-graphs and cellular automata have the same power: anything that can be done by one can be done by the other, but their writing is not the same (details of this comparison here).
------------
How can gem-graph be used to analyse and control the complexity of what it represents and sets in motion? This chapter introduces the gem-graph mechanism.
------------
Gem-graph can reproduce the behavior of any cellular automata. Whatever the state of the cellular automaton space at a given time (n), this state can be considered as a gem-graph state and a rule can be written to transform it into the next state (n+1).
The difference with the cellular automaton is that this rule is not generated by a "micro-rule" applied cell by cell to the entire state (n). This rule must be written by hand and its writing requires knowledge of state (n+1).
Writing all the rules that describe all the transformations that have occurred when a cellular automaton describes a trajectory (a story) is certainly tedious, but it is always possible. And the number of possible histories that gem-graph rules can describe is limited only by the size of the space and the number of symbols it contains.
If a set of "micro-rules", each applied cell by cell to the entire state (n) of a cellular automaton, can produce all the possible states that the gem-graph can describe, the two representations can be considered to be equivalent in power.

View File

@ -1,155 +0,0 @@
Welcome to Gem-graph !
Gem-graph lets you move and transform drawn objects using an automaton. It's an ideal tool for describing the evolution of a situation through drawing. Would you like to see your drawings evolve automatically to represent a phenomenon? Gem-graph lets you transform your drawings as you wish. You can draw whatever you want. It's your drawing and you decide how it evolves! You can use gem-graph to make a game. You can use it to make a model of a phenomenon that interests you. You can represent what you want simply or in more realistic detail. You can draw in one, two or three dimensions. Simple parts and more detailed parts can coexist in the same design. You can watch what you have created evolve without interfering or guiding it towards what you want to achieve. You can mix several drawings and animations. You can observe them in detail, modify them, go back, start again, measure, compare and keep the results that interest you so that you can play them again.
However, a certain amount of effort will be required to achieve this. A complicated model will require more work than a simpler one, but it is possible to start with something simple and develop it step by step. In any case, you must draw what you want to see and say how you want it to be transformed. Gem-graph cannot do that for you. Gem-graph can only help you to draw up and develop your idea. However, it can give you powerful tools to do so. The strength of gem-graph - short for 'geometric graph' - lies in the fact that it deals only with very simple drawing elements, all of which are similar, and that the rules it uses to manipulate these elements are equally simple and similar. As a result, these rules can be combined and processed automatically, no matter how many there are. The tools provided by gem-graph give you access to the power of the automaton it uses to draw and animate your drawings, and this manual is here to help you to learn how to master them.
One way of doing this is to reproduce very simple examples, such as when a programming language asks you to write "Hello world". For gem-graph, the equivalent of "Hello world" will be to move a small line on your screen. This example and other simple ones that follows will progressively give you an approach of what gem-graph can do and enable you to build and animate much more complex drawings that suit your desires. If you like learning this way, start here (@see 1). If you prefer to learn by reading what the commands you see on the screen are doing, they have been detailed here (@see 2). The table of contents is another way to learn. It goes from the simplest to the most complicated. How to set up a simple model (@see 3), observe it and measure what it does (@see 4), then transform it by changing what you see and how it reacts (@see 5) or directly deal in with the details of gem-graph mechanism itself (@see 6). You may also whish to compare gem-graph to other classes of automata that do quite similar things, and look at what it can actually do and what its limitations are (@see 7).
------------
[@ 1] Our "Hello world" is the simplest program that gem-graph can execute. It consists of a single short arrow, which moves in a straight line in a single direction. To do this, we first had to draw this little arrow (@see 8) and then make it move (@see 9). The result is certainly not very exciting, but this example is enough to show how a drawing is made and how it is animated. One state and one rule are enough. The rule only says: if an arrow is drawn here, I erase it and redraw it on the next square. For the moment, you don't need to know in detail how the rule works (it's described here: @see 6). Like in all the examples demonstrated in this manual, the model is assumed to evolve in a flat space (@see 8). All that gem-graph needs to know to execute such models is written in the "Hello world" file (@see 10).
To improve this model, it is possible to give the arrow the ability to move in two directions: forwards or backwards. We can call this second model a "random walk" (@see 11). To do this, we need to add a second rule. This second rule says: if an arrow is drawn here, I erase it and redraw it on the previous square. A random draw (@see 12) is also necessary to determine whether the first or second rule applies. With these two rules and the random draw, the arrow now sometimes goes forwards, sometimes backwards.
The second model (the random walk) had one state (the arrow) and two rules (forward/backward). Now here's a model with two states and two rules: the "pendulum" (@see 13). This time, the arrow can be drawn either tilted forwards or tilted backwards (these are its two possible states) and the two rules switch the drawn arrow from one state to the other or vice versa. In the file, the states are here (@see 14) and the rules here (@see 15). The pendulum does not change place, but alternates between left and right. Like the previous ones, you can slow down the programme so that you can observe the movements (@see ~).
Once you know how to write a state and a rule, you can write thousands of them: they will always be combinations of the same elementary form. However, it is also possible to combine programs: for example, you can combine the reports and rules from the two previous models to create a new model that shows both phenomena simultaneously. Once again, in the file, the states are here (@see 16) and the rules here (@see 17).
The next example shows how the same rule can be applied to a multitude of states. The rule is the same as that used in the second model: an arrow can only be moved one square forward or backward, but this time you have to check that this square is free. If it isn't, the arrow won't move. Once the rules has been modified in this way (@see how), it can be applied to a multitude of arrows distributed randomly in space (@see more details here ~).
When you set the model in motion, you will see all these small lines moving at random towards left or right. The same two rules only are responsible for all these movements.
In the next example, we first build a model similar to the previous one: a multitude of arrows are randomly distributed in space, but this time they are vertical and the movements are up and down instead of right and left (@see ~). Then, we add this model to the previous state and set the final model in motion. We see then little lines moving from left to right or reverse if they are horizontal, and up and down or reverse if they are vertical. Their number is constant. They don't change shape or direction. There seems to be no accident when they cross. Nothing else happens.
The last example in this series, because it shows a multitude of diverse and simultaneous movements, perhaps gives the impression of a more complex system. It would be easy to make it even more complex, but it's much more interesting to show how gem-graph can be used to analyse and control that complexity. At this point, it's time to have a look to the gem-graph mechanism (@see 6) and to compare gem-graph to other classes of automata that do quite similar things to better understand what it can actually do and what its limitations are (@see 7).
------------
[@ 8] This is where the heart of the "Hello world" model lies and where it's worth starting to learn it. The model consists of a single state and a single rule.
The state is a 30 x 20 flat space (NB The number of rows and columns are counted from zero inclusive. @see 10: line 21). All the examples demonstrated in this manual will evolve in the same space. In the "Hello world" model, the arrow is initially located in the middle of this space in square (@see 10: the values (14, 9) are line 34). After applying the rule, it will have been moved to (15, 9). If the same rule were applied again, it would be moved to (16, 9) and so on, always to the right (The x coordinates increase from left to right).
[@ 9] Note that the rule (@see 10: lines 38-47) does not specify which square in the space it should apply to. The automaton guarantees that the rule will apply everywhere in space (@see ~). It simply states that if an arrow is at this point, it should be moved one square to the right. It is made up of two parts: a condition (@see 10 line 39) and a transition. The transition is made of two actions (@see 10 lines 44-45). The condition says: "If there is an arrow at the address (0,0,0), then the rule applies". The address is given by the address of the box (x, y) plus the number of the site in this box. There are "sites" in each box of the space. Each site harbours the arrows oriented towards a neighbouring cell or itself. A weight of 1 indicates that there is an arrow at this address. A weight of 0 indicates that there is no arrow at this address. The two actions to be performed in this case are each described by a line: the first one (@see 10: line 44) indicates that the existing arrow at address (0,0,0) should be deleted; the second one (@see 10: line 45) indicates that a new arrow should be written to address (0,0,1), i.e. the next cell. The rule can be summarizedas follows:
<condition x="0" y="0" site="0" weight="1"/>
<transition>
<arrow x="0" y="0" site="0" weight="0"/>
<arrow x="1" y="0" site="0" weight="1"/>
</transition>
Note that, for this model to be complete, a parameter called "loop_on_space_size_x" must be specified. If it is set to: loop_on_space_size_x="true", anything moved beyond x_max returns to x_zero space. If it is set to: loop_on_space_size_x="false", anything moved beyond x_max is lost. In case of vertical movements, a similar loop_on_space_size_y parameter would be required (for a complete space description @see ~).
------------
[@ 11] The "random walk" model consists of one state and two rules. As these two rules apply to the same state which is the same as in the "Hello world" model, they differ only in their transitions. Again, each transition is made of two actions, each described by a line. The first line is identical in both cases. It indicates that the existing arrow at address (0,0,0) should be deleted. The second line differs: in one case it indicates that a new arrow should be written to address (0,0,1), i.e. the next cell, while in the other case it indicates that a new arrow should be written to address (0,0,-1), i.e. the previous cell.
[@ 12] A random draw is necessary to determine whether the first or second rule applies. It consists in a probability that is associated to each of them. This probability can be set to 0.5 for each or any other value. The sum of all probabilities must be 1. You must also indicate that they share the same parent condition and have separate identities. The complete writing becomes:
<condition x="0" y="0" site="0" weight="1" id="move_west_or_east"/>
<transition probability="0.5" parent="move_west_or_east" id="move_the_arrow_to_east">
<arrow x="0" y="0" site="0" weight="0"/>
<arrow x="1" y="0" site="0" weight="1"/>
</transition>
<transition probability="0.5" parent="move_west_or_east" id="move_the_arrow_to_west">
<arrow x="0" y="0" site="0" weight="0"/>
<arrow x="-1" y="0" site="0" weight="1"/>
</transition>
Initially, the arrow is located in the middle of planar space. Since each of the two transitions can be applied with a probability of 0.5, the arrow can be moved either towards (15, 9) or towards (13, 9). If the same rule were applied again and again, the movement of the arrow would be a random walk with an increasing probability of moving away from the starting point in either direction. Once again, the rule does not specify which square in space it should apply to. It simply states that if an arrow is at this point, it should be moved one square to the right or left. Note also that, for this model to be complete, another parameter called "loop_on_zero_x" must be specified. If it is set to: loop_on_zero_x="true", anything moved beyond zero returns to the maximum space. If it is set to: loop_on_zero_x="false", anything moved beyond zero is lost. In this example, each transition has an identifier. This makes it easier to manage each rule when there are many of them.
------------
[@ 10] All that gem-graph needs to run the "Hello world" file is detailed in this file. The most interesting part concerns the description of the arrow (@see 8 and line 34) and its movement (@see 9 and lines 44, 45).
A full Gem-graph XML model includes also information that is not interesting for understanding how Gem-graph works. These informations are detailed in the following example of a typical gem-graph model file. They include: date (line 8), author identity (lines 6, 7), model identity and parameters (lines 5, 10), rules identities and parameters, objects definitions, current measurements and results.
In all the examples demonstrated in this manual, the model is assumed to evolve in a flat space of 30 x 20 squares. As the number of rows and columns is counted from zero inclusive, this size of space is noted: 29 x 19 (line 21) and its middle 14 x 9. The x coordinates increase from left to right; the y coordinates increase from bottom to top. To simplify, z values have been omitted. Two parameters named "loop_on_zero_x" and "loop_on_space_size_x" can be set to true or false. If loop_on_zero_x="true", anything moved before zero reenters at the end of space else it is lost. If loop_on_space_size_x="true", anything moved beyond the space size x reenters at the zero of space else it is lost (lines 19, 20). These parameters must be defined at least for x and (in case) for y and z. Site_multiplicity = number of sites in a space unit (line 22). Each site points towards a neighbouring space unit. Site 0 points towards the current space unit itself. Several arrows can be stacked in the same site.
line 1 <?xml version="1.0" encoding="UTF-8"?>
line 2 <gem-graph-model version="0.1.0">
line 3
line 4 <identity>
line 5 <name>Hello World</name>
line 6 <owner>owner</owner>
line 7 <owner_id>owner_id</owner_id>
line 8 <date>date</date>
line 9 <version>1.0</version>
line 10 <g_ref id="id" date="date" author="author" lang="en">En</g_ref>
line 11 </identity>
line 12
line 13 <parameters id="id" date="0" author="author">
line 14 <simulation>
line 15 <max_thread>0</max_thread>
line 16 <max_cycles>0</max_cycles>
line 17 </simulation>
line 18 <space-param>
line 19 <loop_on_zero_x="true"/>
line 20 <loop_on_space_size_x="true"/>
line 21 <dimension x="29" y="19"/>
line 22 <site_multiplicity="1"/>
line 23 </space-param>
line 24 </parameters>
line 25
line 26 <objects>
line 27 <object id="one_arrow" date="date" author="author">
line 28 <arrow site="0" weight="1" x="0" y="0"/>
line 29 </object>
line 30 </objects>
line 31
line 32 <savedstates>
line 33 <state id="initial" date="date" author="author">
line 34 <arrow site="0" weight="1" x="14" y="9"/>
line 35 </state>
line 36 </savedstates>
line 37
line 38 <conditions>
line 39 <condition site="0" weight="1" node_id="1" parent="0" x="0" y="0"/>
line 40 </conditions>
line 41
line 42 <transitions>
line 43 <transition id="move_one_arrow_to_east" probability="1" date="date" author="author">
line 44 <arrow site="0" weight="0" x="0" y="0"/>
line 45 <arrow site="0" weight="1" x="1" y="0"/>
line 46 </transition>
line 47 </transitions>
line 48
line 49 </gem-graph-model>
------------
[@ 13] The "pendulum" model consists of two states and two rules. Suppose the pendulum is in the middle square (x="14", y="9") and the states describe an arrow as being inclined backwards (site="6") or forwards (site = "7"). Each rule detects one of these two positions by means of a condition and modifies the inclination of the arrow by means of two actions: one that deletes and the other that rewrites. Here again, conditions and transitions are written separately and must be identifiable so that they can be linked. Here are the two rules:
<condition x="0" y="0" site="6" weight="1" id="inclined_backwards"/>
<condition x="0" y="0" site="7" weight="1" id="inclined_forwards"/>
<transition parent="inclined_backwards" id="incline_forwards">
<arrow x="0" y="0" site="6" weight="0"/>
<arrow x="0" y="0" site="7" weight="1"/>
</transition>
<transition parent="inclined_forwards" id="incline_backwards">
<arrow x="0" y="0" site="7" weight="0"/>
<arrow x="0" y="0" site="6" weight="1"/>
</transition>
The pendulum does not change place. Lorsque nous avons décrit l'espace dans son ensemble, nous l'avons placé au milieu (14,9). Pour la règle, il se trouve en (0,0). C'est l'automate de gem-graph qui cherche dans tout l'espace s'il y a une case où cette règle peut s'appliquer. Lorsqu'il atteint la case (14,9), l'une ou l'autre des deux règles s'applique. La probabilité d'application de chaque règle est de "1" et n'a pas été indiquée. Comme les deux règles s'appliquent alternativement, le pendule oscille. Il serait facile, en utilisant plus d'états et de règles, de décrire son mouvement de manière plus fine.
------------
[@ 6] Details about how the rule works (how the automaton searches everywhere in the whole space a place where the rule could apply and how the rules are evaluated)
This chapter introduces the gem-graph mechanism.
------------
[@ 7] The main difference between gem-graph models and agent-based models is that gem-graph deals with situations, not agents. In a situation where several agents are interacting and each agent could apply a different rule, gem-graph considers and processes the situation. Not the agents. Whatever the new situation that results from his action, his decision-making process will have been simple and straightforward. It will therefore be easy to modify and control. And the diversity of possible new situations will be far greater than that offered by agent-based models.
The comparison between gem-graphs and cellular automata first comes up against a question of vocabulary. What is commonly called a 'rule' in one and the other is not the same thing. Gem-graphs and cellular automata have the same power: anything that can be done by one can be done by the other, but their writing is not the same (details of this comparison here).
How can gem-graph be used to analyse and control the complexity of what it represents and sets in motion? This chapter introduces the gem-graph mechanism.
Gem-graph can reproduce the behavior of any cellular automata. Whatever the state of the cellular automaton space at a given time (n), this state can be considered as a gem-graph state and a rule can be written to transform it into the next state (n+1).
The difference with the cellular automaton is that this rule is not generated by a "micro-rule" applied cell by cell to the entire state (n). This rule must be written by hand and its writing requires knowledge of state (n+1).
Writing all the rules that describe all the transformations that have occurred when a cellular automaton describes a trajectory (a story) is certainly tedious, but it is always possible. And the number of possible histories that gem-graph rules can describe is limited only by the size of the space and the number of symbols it contains.
If a set of "micro-rules", each applied cell by cell to the entire state (n) of a cellular automaton, can produce all the possible states that the gem-graph can describe, the two representations can be considered to be equivalent in power.

View File

@ -1,345 +0,0 @@
Welcome to Gem-graph !
Gem-graph lets you move and transform drawn objects using an automaton. It's an
ideal tool for describing the evolution of a situation through drawing. Would you
like to see your drawings evolve automatically to represent a phenomenon?
Gem-graph lets you transform your drawings as you wish. You can draw whatever you
want. It's your drawing and you decide how it evolves! You can use gem-graph to
make a game. You can use it to make a model of a phenomenon that interests you.
You can represent what you want simply or in more realistic detail. You can draw
in one, two or three dimensions. Simple parts and more detailed parts can coexist
in the same design. You can watch what you have created evolve without interfering
or guiding it towards what you want to achieve. You can mix several drawings and
animations. You can observe them in detail, modify them, go back, start again,
measure, compare and keep the results that interest you so that you can play them
again.
However, a certain amount of effort will be required to achieve this.
A complicated model will require more work than a simpler one, but it is possible
to start with something simple and develop it step by step. In any case, you must
draw what you want to see and say how you want it to be transformed. Gem-graph
cannot do that for you. Gem-graph can only help you to draw up and develop your
idea. However, it can give you powerful tools to do so. The strength of gem-graph
- short for 'geometric graph' - lies in the fact that it deals only with very
simple drawing elements, all of which are similar, and that the rules it uses to
manipulate these elements are equally simple and similar. As a result, these rules
can be combined and processed automatically, no matter how many there are. The
tools provided by gem-graph give you access to the power of the automaton it uses
to draw and animate your drawings, and this manual is here to help you to learn
how to master them.
One way of doing this is to reproduce very simple examples, such as when a
programming language asks you to write "Hello world". For gem-graph, the
equivalent of "Hello world" will be to move a small line on your screen. This
example and other simple ones that follows will progressively give you an approach
of what gem-graph can do and enable you to build and animate much more complex
drawings that suit your desires. If you like learning this way, start here (@see 1).
If you prefer to learn by reading what the commands you see on the screen are
doing, they have been detailed here (@see 2). The table of contents is another
way to learn. It goes from the simplest to the most complicated. How to set up a
simple model (@see 3), observe it and measure what it does (@see 4), then
transform it by changing what you see and how it reacts (@see 5) or directly deal
in with the details of gem-graph mechanism itself (@see 6). You may also whish to
compare gem-graph to other classes of automata that do quite similar things, and
look at what it can actually do and what its limitations are (@see 7).
------------
[@ 1] Our "Hello world" is the simplest program that gem-graph can execute. It
consists of a single short arrow, which moves in a straight line in a single
direction. To do this, we first had to draw this little arrow (@see 8) and then
make it move (@see 9). The result is certainly not very exciting, but this example
is enough to show how a drawing is made and how it is animated. One state and one
rule are enough. The rule only says: if an arrow is drawn here, I erase it and
redraw it on the next square. For the moment, you don't need to know in detail
how the rule works (it's described here: @see 6). Like in all the examples
demonstrated in this manual, the model is assumed to evolve in a flat space (@see 8).
All that gem-graph needs to know to execute such models is written in the "Hello
world" file (@see 10).
To improve this model, it is possible to give the arrow the ability to move in
two directions: forwards or backwards. We can call this second model a "random
walk" (@see 11). To do this, we need to add a second rule. This second rule says:
if an arrow is drawn here, I erase it and redraw it on the previous square.
A random draw (@see 12) is also necessary to determine whether the first or second
rule applies. With these two rules and the random draw, the arrow now sometimes
goes forwards, sometimes backwards.
The second model (the random walk) had one state (the arrow) and two rules
(forward/backward). Now here's a model with two states and two rules: the "pendulum"
(@see 13). This time, the arrow can be drawn either tilted forwards or tilted
backwards (these are its two possible states) and the two rules switch the drawn
arrow from one state to the other or vice versa. In the file, the states are here
(@see 14) and the rules here (@see 15). The pendulum does not change place, but
alternates between left and right. Like the previous ones, you can slow down the
programme so that you can observe the movements (@see ~).
Once you know how to write a state and a rule, you can write thousands of them:
they will always be combinations of the same elementary form. However, it is also
possible to combine programs: for example, you can combine the reports and rules
from the two previous models to create a new model that shows both phenomena
simultaneously. Once again, in the file, the states are here (@see 16) and the
rules here (@see 17).
The next example shows how the same rule can be applied to a multitude of states.
The rule is the same as that used in the second model: an arrow can only be moved
one square forward or backward, but this time you have to check that this square
is free. If it isn't, the arrow won't move. Once the rules has been modified in
this way (@see how), it can be applied to a multitude of arrows distributed
randomly in space (@see more details here ~).
When you set the model in motion, you will see all these small lines moving at
random towards left or right. The same two rules only are responsible for all
these movements.
In the next example, we first build a model similar to the previous one: a
multitude of arrows are randomly distributed in space, but this time they are
vertical and the movements are up and down instead of right and left (@see ~).
Then, we add this model to the previous state and set the final model in motion.
We see then little lines moving from left to right or reverse if they are
horizontal, and up and down or reverse if they are vertical. Their number is
constant. They don't change shape or direction. There seems to be no accident when
they cross. Nothing else happens.
The last example in this series, because it shows a multitude of diverse and
simultaneous movements, perhaps gives the impression of a more complex system.
It would be easy to make it even more complex, but it's much more interesting to
show how gem-graph can be used to analyse and control that complexity. At this
point, it's time to have a look to the gem-graph mechanism (@see 6) and to compare
gem-graph to other classes of automata that do quite similar things to better
understand what it can actually do and what its limitations are (@see 7).
------------
[@ 8] This is where the heart of the "Hello world" model lies and where it's worth
starting to learn it. The model consists of a single state and a single rule.
The state is a 30 x 20 flat space (NB The number of rows and columns are counted
from zero inclusive. @see 10: line 21). All the examples demonstrated in this
manual will evolve in the same space. In the "Hello world" model, the arrow is
initially located in the middle of this space in square (@see 10: the values (14, 9)
are line 34). After applying the rule, it will have been moved to (15, 9). If the
same rule were applied again, it would be moved to (16, 9) and so on, always to
the right (The x coordinates increase from left to right).
[@ 9] Note that the rule (@see 10: lines 38-47) does not specify which square in
the space it should apply to. The automaton guarantees that the rule will apply
everywhere in space (@see ~). It simply states that if an arrow is at this point,
it should be moved one square to the right. It is made up of two parts: a condition
(@see 10 line 39) and a transition. The transition is made of two actions (@see 10
lines 44-45). The condition says: "If there is an arrow at the address (0,0,0),
then the rule applies". The address is given by the address of the box (x, y)
plus the number of the site in this box. There are "sites" in each box of the space.
Each site harbours the arrows oriented towards a neighbouring cell or itself.
A weight of 1 indicates that there is an arrow at this address. A weight of 0
indicates that there is no arrow at this address. The two actions to be performed
in this case are each described by a line: the first one (@see 10: line 44)
indicates that the existing arrow at address (0,0,0) should be deleted; the second
one (@see 10: line 45) indicates that a new arrow should be written to address
(0,0,1), i.e. the next cell. The rule can be summarizedas follows:
<condition x="0" y="0" site="0" weight="1"/>
<transition>
<arrow x="0" y="0" site="0" weight="0"/>
<arrow x="1" y="0" site="0" weight="1"/>
</transition>
Note that, for this model to be complete, a parameter called "loop_on_space_size_x"
must be specified. If it is set to: loop_on_space_size_x="true", anything moved
beyond x_max returns to x_zero space. If it is set to: loop_on_space_size_x="false",
anything moved beyond x_max is lost. In case of vertical movements, a similar
loop_on_space_size_y parameter would be required (for a complete space description
@see ~).
------------
[@ 11] The "random walk" model consists of one state and two rules. As these two
rules apply to the same state which is the same as in the "Hello world" model,
they differ only in their transitions. Again, each transition is made of two actions,
each described by a line. The first line is identical in both cases. It indicates
that the existing arrow at address (0,0,0) should be deleted. The second line
differs: in one case it indicates that a new arrow should be written to address
(0,0,1), i.e. the next cell, while in the other case it indicates that a new arrow
should be written to address (0,0,-1), i.e. the previous cell.
[@ 12] A random draw is necessary to determine whether the first or second rule
applies. It consists in a probability that is associated to each of them. This
probability can be set to 0.5 for each or any other value. The sum of all
probabilities must be 1. You must also indicate that they share the same parent
condition and have separate identities. The complete writing becomes:
<condition x="0" y="0" site="0" weight="1" id="move_west_or_east"/>
<transition probability="0.5" parent="move_west_or_east"
id="move_the_arrow_to_east">
<arrow x="0" y="0" site="0" weight="0"/>
<arrow x="1" y="0" site="0" weight="1"/>
</transition>
<transition probability="0.5" parent="move_west_or_east"
id="move_the_arrow_to_west">
<arrow x="0" y="0" site="0" weight="0"/>
<arrow x="-1" y="0" site="0" weight="1"/>
</transition>
Initially, the arrow is located in the middle of planar space. Since each of the
two transitions can be applied with a probability of 0.5, the arrow can be moved
either towards (15, 9) or towards (13, 9). If the same rule were applied again
and again, the movement of the arrow would be a random walk with an increasing
probability of moving away from the starting point in either direction. Once again,
the rule does not specify which square in space it should apply to. It simply
states that if an arrow is at this point, it should be moved one square to the
right or left. Note also that, for this model to be complete, another parameter
called "loop_on_zero_x" must be specified. If it is set to: loop_on_zero_x="true",
anything moved beyond zero returns to the maximum space. If it is set to:
loop_on_zero_x="false", anything moved beyond zero is lost. In this example, each
transition has an identifier. This makes it easier to manage each rule when there
are many of them.
------------
[@ 10] All that gem-graph needs to run the "Hello world" file is detailed in this
file. The most interesting part concerns the description of the arrow (@see 8
and line 34) and its movement (@see 9 and lines 44, 45).
A full Gem-graph XML model includes also information that is not interesting for
understanding how Gem-graph works. These informations are detailed in the following
example of a typical gem-graph model file. They include: date (line 8), author
identity (lines 6, 7), model identity and parameters (lines 5, 10), rules identities
and parameters, objects definitions, current measurements and results.
In all the examples demonstrated in this manual, the model is assumed to evolve in
a flat space of 30 x 20 squares. As the number of rows and columns is counted from
zero inclusive, this size of space is noted: 29 x 19 (line 21) and its middle 14 x 9.
The x coordinates increase from left to right; the y coordinates increase from bottom
to top. To simplify, z values have been omitted. Two parameters named "loop_on_zero_x"
and "loop_on_space_size_x" can be set to true or false. If loop_on_zero_x="true",
anything moved before zero reenters at the end of space else it is lost. If
loop_on_space_size_x="true", anything moved beyond the space size x reenters at
the zero of space else it is lost (lines 19, 20). These parameters must be defined
at least for x and (in case) for y and z. Site_multiplicity = number of sites in
a space unit (line 22). Each site points towards a neighbouring space unit.
Site 0 points towards the current space unit itself. Several arrows can be stacked
in the same site.
line 1 <?xml version="1.0" encoding="UTF-8"?>
line 2 <gem-graph-model version="0.1.0">
line 3
line 4 <identity>
line 5 <name>Hello World</name>
line 6 <owner>owner</owner>
line 7 <owner_id>owner_id</owner_id>
line 8 <date>date</date>
line 9 <version>1.0</version>
line 10 <g_ref id="id" date="date" author="author" lang="en">En</g_ref>
line 11 </identity>
line 12
line 13 <parameters id="id" date="0" author="author">
line 14 <simulation>
line 15 <max_thread>0</max_thread>
line 16 <max_cycles>0</max_cycles>
line 17 </simulation>
line 18 <space-param>
line 19 <loop_on_zero_x="true"/>
line 20 <loop_on_space_size_x="true"/>
line 21 <dimension x="29" y="19"/>
line 22 <site_multiplicity="1"/>
line 23 </space-param>
line 24 </parameters>
line 25
line 26 <objects>
line 27 <object id="one_arrow" date="date" author="author">
line 28 <arrow site="0" weight="1" x="0" y="0"/>
line 29 </object>
line 30 </objects>
line 31
line 32 <savedstates>
line 33 <state id="initial" date="date" author="author">
line 34 <arrow site="0" weight="1" x="14" y="9"/>
line 35 </state>
line 36 </savedstates>
line 37
line 38 <conditions>
line 39 <condition site="0" weight="1" node_id="1" parent="0" x="0" y="0"/>
line 40 </conditions>
line 41
line 42 <transitions>
line 43 <transition id="move_one_arrow_to_east" probability="1">
line 44 <arrow site="0" weight="0" x="0" y="0"/>
line 45 <arrow site="0" weight="1" x="1" y="0"/>
line 46 </transition>
line 47 </transitions>
line 48
line 49 </gem-graph-model>
------------
[@ 13] The "pendulum" model consists of two states and two rules. Suppose the
pendulum is in the middle square (x="14", y="9") and the states describe an arrow
as being inclined backwards (site="6") or forwards (site = "7"). Each rule detects
one of these two positions by means of a condition and modifies the inclination
of the arrow by means of two actions: one that deletes and the other that rewrites.
Here again, conditions and transitions are written separately and must be
identifiable so that they can be linked. Here are the two rules:
<condition x="0" y="0" site="6" weight="1" id="inclined_backwards"/>
<condition x="0" y="0" site="7" weight="1" id="inclined_forwards"/>
<transition parent="inclined_backwards" id="incline_forwards">
<arrow x="0" y="0" site="6" weight="0"/>
<arrow x="0" y="0" site="7" weight="1"/>
</transition>
<transition parent="inclined_forwards" id="incline_backwards">
<arrow x="0" y="0" site="7" weight="0"/>
<arrow x="0" y="0" site="6" weight="1"/>
</transition>
The pendulum does not change place. Lorsque nous avons décrit l'espace dans son
ensemble, nous l'avons placé au milieu (14,9). Pour la règle, il se trouve en (0,0).
C'est l'automate de gem-graph qui cherche dans tout l'espace s'il y a une case où
cette règle peut s'appliquer. Lorsqu'il atteint la case (14,9), l'une ou l'autre
des deux règles s'applique. La probabilité d'application de chaque règle est de
"1" et n'a pas été indiquée. Comme les deux règles s'appliquent alternativement,
le pendule oscille. Il serait facile, en utilisant plus d'états et de règles,
de décrire son mouvement de manière plus fine.
------------
[@ 6] Details about how the rule works (how the automaton searches everywhere in
the whole space a place where the rule could apply and how the rules are evaluated)
This chapter introduces the gem-graph mechanism.
------------
[@ 7] The main difference between gem-graph models and agent-based models is that
gem-graph deals with situations, not agents. In a situation where several agents
are interacting and each agent could apply a different rule, gem-graph considers
and processes the situation. Not the agents. Whatever the new situation that
results from his action, his decision-making process will have been simple and
straightforward. It will therefore be easy to modify and control. And the diversity
of possible new situations will be far greater than that offered by agent-based models.
The comparison between gem-graphs and cellular automata first comes up against a
question of vocabulary. What is commonly called a 'rule' in one and the other is
not the same thing. Gem-graphs and cellular automata have the same power: anything
that can be done by one can be done by the other, but their writing is not the
same (details of this comparison here).
How can gem-graph be used to analyse and control the complexity of what it
represents and sets in motion? This chapter introduces the gem-graph mechanism.
Gem-graph can reproduce the behavior of any cellular automata. Whatever the state
of the cellular automaton space at a given time (n), this state can be considered
as a gem-graph state and a rule can be written to transform it into the next state
(n+1).
The difference with the cellular automaton is that this rule is not generated by a
"micro-rule" applied cell by cell to the entire state (n). This rule must be written
by hand and its writing requires knowledge of state (n+1).
Writing all the rules that describe all the transformations that have occurred
when a cellular automaton describes a trajectory (a story) is certainly tedious,
but it is always possible. And the number of possible histories that gem-graph
rules can describe is limited only by the size of the space and the number of
symbols it contains.
If a set of "micro-rules", each applied cell by cell to the entire state (n) of
a cellular automaton, can produce all the possible states that the gem-graph can
describe, the two representations can be considered to be equivalent in power.

View File

@ -178,18 +178,19 @@ enum fsm_enum_log_source {
* A log unit must include the followings: * A log unit must include the followings:
* *
* @callergraph * @callergraph
* @see fsm_log_t * @see fsm_log_struct
*/ */
struct fsm_log_unit_t typedef struct fsm_log_unit_struct
{ {
long yy_dd_mm; /**< * date of the event reported in the log */ long yy_dd_mm; /**< * date of the event reported in the log */
long usec; /**< * with microseconds precision */ long usec; /**< * with microseconds precision */
char *file_source; /**< * emitter file */ char *file_source; /**< * emitter file */
char *function_source; /**< * emitter function */ char *function_source; /**< * emitter function */
char *string_value; /**< * any event descriptors */ char *string_value; /**< * any event descriptors */
struct fsm_log_unit_t *prev; /**< * chained list */ struct fsm_log_unit_struct *prev; /**< * chained list */
struct fsm_log_unit_t *next; /**< * chained list */ struct fsm_log_unit_struct *next; /**< * chained list */
}; }
fsm_log_unit_struct;
/** /**
@ -197,7 +198,7 @@ struct fsm_log_unit_t
* are required to initialize and manage it. * are required to initialize and manage it.
* *
* @callgraph * @callgraph
* @see fsm_log_t_unit * @see fsm_log_struct_unit
* *
* @callergraph * @callergraph
* @see fsm_init_log() * @see fsm_init_log()
@ -208,31 +209,30 @@ struct fsm_log_unit_t
* @see fsm_seek_log() * @see fsm_seek_log()
* @see fsm_remove_log() * @see fsm_remove_log()
*/ */
struct fsm_log_t typedef struct {
{ fsm_log_unit_struct *first; /**< * required */
struct fsm_log_unit_t *oldest; /**< * required */ fsm_log_unit_struct *last; /**< * required */
struct fsm_log_unit_t *latest; /**< * required */ }
}; fsm_log_struct;
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void fsm_init_log (struct fsm_log_t *); void fsm_init_log (fsm_log_struct *jj);
void fsm_publish_log (struct fsm_log_t *); void fsm_publish_log (fsm_log_struct jj);
void fsm_clear_log (struct fsm_log_t *); void fsm_clear_log (fsm_log_struct *jj);
void fsm_clear_log_unit (struct fsm_log_unit_t *);
void fsm_add_log_event (struct fsm_log_t *gg_logs, void fsm_add_log_event (fsm_log_struct *jj,
char *file_source, char *file_source,
char *function_source, char *function_source,
char *string_value); char *string_value);
int fsm_get_log_length(struct fsm_log_t *); int fsm_get_log_length(fsm_log_struct jj);
void fsm_seek_log (struct fsm_log_t *gg_logs, void fsm_seek_log (fsm_log_struct jj,
long usec, long usec,
char *file_source, char *file_source,
char *function_source, char *function_source,
char *string_value); char *string_value);
long fsm_remove_log (struct fsm_log_t *gg_logs, long fsm_remove_log (fsm_log_struct *jj,
char *file_source, char *file_source,
char *function_source, char *function_source,
char *string_value); char *string_value);
@ -248,3 +248,5 @@ void fsm_relay_close_log();
void fsm_init (char *initial_message_from_main); void fsm_init (char *initial_message_from_main);
void fsm_close (char *final_message_from_main); void fsm_close (char *final_message_from_main);

View File

@ -28,6 +28,6 @@
#pragma once #pragma once
#include <gtk-4.0/gtk/gtk.h> #include <gtk-4.0/gtk/gtk.h>
void on_app_activation (GtkApplication *app); void on_windows_activation (GtkApplication *app);
void widget_design_main_window (GtkWindow *main_window, GtkApplication *app); void widget_get_main_window (GtkWindow *main_window, GtkApplication *app);
gboolean on_window_close_request (GtkWindow *main_window, gpointer user_data);

View File

@ -39,35 +39,26 @@
* *
* @since 2024-09 * @since 2024-09
* *
* @param *gg_logs * @param *jj
* @param *file_source * @param *file_source
* @param *function_source * @param *function_source
* @param *string_value * @param *string_value
* *
* @returns the removed event date microseconds * @returns the removed event date microseconds
*/ */
long fsm_remove_log (struct fsm_log_t *gg_logs, long fsm_remove_log (fsm_log_struct *jj,
char *file_source, char *file_source,
char *function_source, char *function_source,
char *string_value) char *string_value)
{ {
// save latest log ref in tmp long usec;
struct fsm_log_unit_t *tmp = gg_logs->latest; fsm_log_unit_struct *tmp = jj->last;
long usec = tmp->usec; if (! tmp) return -1;
usec = tmp->usec;
// if there is no log, get out jj->last = tmp->prev;
if (! tmp) if (jj->last) jj->last->next = NULL;
return 0; else jj->first = NULL;
free (tmp);
// remove the log from history
gg_logs->latest = tmp->prev;
// update gg_logs references if needed
if (gg_logs->latest) gg_logs->latest->next = NULL;
else gg_logs->latest = NULL;
// free the unit memory
fsm_clear_log_unit(tmp);
return usec; return usec;
} }
@ -78,12 +69,12 @@ long fsm_remove_log (struct fsm_log_t *gg_logs,
* *
* @since 2024-09 * @since 2024-09
* *
* @param *gg_logs * @param *jj
* @returns log length * @returns log length
*/ */
int fsm_get_log_length (struct fsm_log_t *gg_logs) int fsm_get_log_length (fsm_log_struct jj)
{ {
struct fsm_log_unit_t *a_unit = gg_logs->oldest; fsm_log_unit_struct *a_unit = jj.first;
int nb = 0; int nb = 0;
while (a_unit) while (a_unit)
{ {
@ -99,19 +90,19 @@ int fsm_get_log_length (struct fsm_log_t *gg_logs)
* *
* @since 2024-09 * @since 2024-09
* *
* @param *gg_logs * @param *jj
* @param usec * @param usec
* @param *file_source * @param *file_source
* @param *function_source * @param *function_source
* @param *string_value * @param *string_value
*/ */
void fsm_seek_log (struct fsm_log_t *gg_logs, void fsm_seek_log (fsm_log_struct jj,
long usec, long usec,
char *file_source, char *file_source,
char *function_source, char *function_source,
char *string_value) char *string_value)
{ {
struct fsm_log_unit_t *a_unit = gg_logs->oldest; fsm_log_unit_struct *a_unit = jj.first;
int nb = 0; int nb = 0;
while (a_unit) while (a_unit)
{ {

View File

@ -47,7 +47,7 @@
* *
* Limiting the access to gg_logs helps to avoid uncontrolled operations on it. * Limiting the access to gg_logs helps to avoid uncontrolled operations on it.
*/ */
static struct fsm_log_t gg_logs = { 0 }; static fsm_log_struct gg_logs;
/** /**
@ -148,7 +148,7 @@ void fsm_relay_init_log()
*/ */
void fsm_relay_close_log() void fsm_relay_close_log()
{ {
fsm_publish_log (&gg_logs); fsm_publish_log (gg_logs);
fsm_clear_log (&gg_logs); fsm_clear_log (&gg_logs);
} }

View File

@ -45,7 +45,7 @@
static int string_1_size = 40; static int string_1_size = 40;
static int string_2_size = 40; static int string_2_size = 40;
static int string_3_size = 50; static int string_3_size = 40;
/** /**
* Inits the log: a double chained list. * Inits the log: a double chained list.
@ -54,12 +54,12 @@ static int string_3_size = 50;
* *
* @since 2024-09 * @since 2024-09
* *
* @param *gg_logs * @param *jj
*/ */
void fsm_init_log (struct fsm_log_t *gg_logs) void fsm_init_log (fsm_log_struct *jj)
{ {
gg_logs->oldest = NULL; jj->first = NULL;
gg_logs->latest = NULL; jj->last = NULL;
} }
@ -68,38 +68,22 @@ void fsm_init_log (struct fsm_log_t *gg_logs)
* *
* @since 2024-09 * @since 2024-09
* *
* @param *gg_logs * @param *jj
*/ */
void fsm_clear_log (struct fsm_log_t *gg_logs) void fsm_clear_log (fsm_log_struct *jj)
{ {
struct fsm_log_unit_t *tmp; fsm_log_unit_struct *tmp;
struct fsm_log_unit_t *a_unit = gg_logs->oldest; fsm_log_unit_struct *a_unit = jj->first;
while(a_unit) while(a_unit)
{ {
tmp = a_unit; tmp = a_unit;
a_unit = a_unit->next; a_unit = a_unit->next;
fsm_clear_log_unit(tmp); free (tmp);
} }
gg_logs->oldest = NULL; jj->first = NULL;
gg_logs->latest = NULL; jj->last = NULL;
} }
/**
* Deletes all the contents of a log unit and takes care
* of freeing it.
*
* @since 2024-11
*
* @param *unit
*/
void fsm_clear_log_unit (struct fsm_log_unit_t *unit)
{
g_free(unit->file_source);
g_free(unit->function_source);
g_free(unit->string_value);
g_free(unit);
}
/** /**
* Adds a log unit (an event) to the log list. * Adds a log unit (an event) to the log list.
@ -110,12 +94,12 @@ void fsm_clear_log_unit (struct fsm_log_unit_t *unit)
* *
* @since 2024-09 * @since 2024-09
* *
* @param *gg_logs * @param *jj
* @param *file_source * @param *file_source
* @param *function_source * @param *function_source
* @param *string_value * @param *string_value
*/ */
void fsm_add_log_event (struct fsm_log_t *gg_logs, void fsm_add_log_event (fsm_log_struct *jj,
char *file_source, char *file_source,
char *function_source, char *function_source,
char *string_value) char *string_value)
@ -123,7 +107,7 @@ void fsm_add_log_event (struct fsm_log_t *gg_logs,
struct timeval tv; struct timeval tv;
gettimeofday (&tv, NULL); gettimeofday (&tv, NULL);
struct fsm_log_unit_t *new_unit = g_malloc0 (sizeof(struct fsm_log_unit_t)); fsm_log_unit_struct *new_unit = malloc (sizeof(fsm_log_unit_struct));
if (! new_unit) exit (EXIT_FAILURE); if (! new_unit) exit (EXIT_FAILURE);
new_unit->yy_dd_mm = tv.tv_sec; new_unit->yy_dd_mm = tv.tv_sec;
@ -137,17 +121,13 @@ void fsm_add_log_event (struct fsm_log_t *gg_logs,
strncpy (new_unit->function_source, function_source, string_2_size - 1); strncpy (new_unit->function_source, function_source, string_2_size - 1);
strncpy (new_unit->string_value, string_value, string_3_size - 1); strncpy (new_unit->string_value, string_value, string_3_size - 1);
// first time we log something (don't touch new_unit->prev) new_unit->next = jj->first;
if (gg_logs->oldest == NULL) new_unit->prev = NULL;
gg_logs->oldest = new_unit; // record the first reference (once)
// not the first time, just update
else {
new_unit->prev = gg_logs->latest;
new_unit->prev->next = new_unit;
}
// in any case, update the latest reference if (jj->first) jj->first->prev = new_unit;
gg_logs->latest = new_unit; else jj->last = new_unit;
jj->first = new_unit;
} }
@ -161,43 +141,27 @@ void fsm_add_log_event (struct fsm_log_t *gg_logs,
* *
* @since 2024-09 * @since 2024-09
* *
* @param *gg_logs * @param *jj
*/ */
void fsm_publish_log (struct fsm_log_t *gg_logs) void fsm_publish_log (fsm_log_struct jj)
{ {
struct fsm_log_unit_t *a_unit = gg_logs->oldest; fsm_log_unit_struct *a_unit = jj.last;
char *timestamp = g_malloc0 (LOG_MAX_LENGTH * sizeof(char)); char buf [LOG_MAX_LENGTH];
int nb = 0; int nb = 0;
while (a_unit) while (a_unit)
{ {
strftime(timestamp, LOG_MAX_LENGTH * sizeof(char), strftime(buf, sizeof(buf), "%D %T", localtime(&a_unit->yy_dd_mm));
"%D %T", localtime(&a_unit->yy_dd_mm)); g_message ("%s + %-6ld %6d %-28s %-32s %-40s",
buf,
g_message ("%s + %-6ld %6d %-28s %-32s %-45s",
timestamp,
a_unit->usec, a_unit->usec,
nb, nb,
a_unit->file_source, a_unit->file_source,
a_unit->function_source, a_unit->function_source,
a_unit->string_value); a_unit->string_value);
free (a_unit->string_value);
a_unit = a_unit->next; a_unit = a_unit->prev;
nb ++; nb ++;
} }
g_free(timestamp);
} }
/*
* LEAK SUMMARY:
*
* g_message (+) or printf
* definitely lost: 5,008 bytes in 54 blocks
* indirectly lost: 16,151 bytes in 673 blocks
*
* g_message (-)
* definitely lost: 5,776 bytes in 55 blocks
* indirectly lost: 17,703 bytes in 728 blocks
*/

View File

@ -63,19 +63,18 @@ int main (int argc, char **argv)
GtkApplication *app; GtkApplication *app;
int status; int status;
app = gtk_application_new ("org.gem-graph", G_APPLICATION_DEFAULT_FLAGS);
fsm_init ("first instruction / first log"); fsm_init ("first instruction / first log");
fsm_add_log (INFO, MAIN, "main", fsm_add_log (INFO, MAIN, "main", "*app = gtk_application_new()",
"*app = gtk_application_new()",
"| 👉️ trigger app initialization"); "| 👉️ trigger app initialization");
app = gtk_application_new ("org.gem-graph", G_APPLICATION_DEFAULT_FLAGS);
fsm_add_log (INFO, MAIN, "main", fsm_add_log (INFO, MAIN, "main",
"g signal connect (activate)", "g signal connect (activate)",
"| 👉️ windows creation requested"); "| 👉️ windows creation requested");
// g_signal_connect (app, "startup", G_CALLBACK (on_windows_startup), NULL); // g_signal_connect (app, "startup", G_CALLBACK (on_windows_startup), NULL);
g_signal_connect (app, "activate", G_CALLBACK (on_app_activation), NULL); g_signal_connect (app, "activate", G_CALLBACK (on_windows_activation), NULL);
status = g_application_run (G_APPLICATION (app), argc, argv); status = g_application_run (G_APPLICATION (app), argc, argv);
g_object_unref (app); g_object_unref (app);

View File

@ -39,16 +39,16 @@
* @param *main_window * @param *main_window
* @param *app * @param *app
*/ */
void widget_design_main_window (GtkWindow *main_window, GtkApplication *app) void widget_get_main_window (GtkWindow *main_window, GtkApplication *app)
{ {
fsm_add_log (INFO, TOPBAR, "widget/main_window/design", fsm_add_log (INFO, TOPBAR, "widget/main_window/design",
"main window", "start of design"); "main window", "start of design");
/* GtkWidget *topbar = GTK_WIDGET (gtk_header_bar_new ()); */ GtkWidget *topbar = GTK_WIDGET (gtk_header_bar_new ());
/* char *title = "E coli (with permission from David S. Goodsell, 2009)"; */ char *title = "E coli (with permission from David S. Goodsell, 2009)";
/* gtk_header_bar_set_title_widget (GTK_HEADER_BAR (topbar), */ gtk_header_bar_set_title_widget (GTK_HEADER_BAR (topbar),
/* gtk_label_new (title)); */ gtk_label_new (title));
GtkWidget *e_coli = GTK_WIDGET (gtk_picture_new_for_filename GtkWidget *e_coli = GTK_WIDGET (gtk_picture_new_for_filename
("./docs/showcase/E coli (Goodsell).png")); ("./docs/showcase/E coli (Goodsell).png"));
@ -60,3 +60,4 @@ void widget_design_main_window (GtkWindow *main_window, GtkApplication *app)
fsm_add_log (INFO, TOPBAR, "widget/main_window/design", fsm_add_log (INFO, TOPBAR, "widget/main_window/design",
"main window", "ready for presentation"); "main window", "ready for presentation");
} }

View File

@ -35,18 +35,20 @@
#include <stdio.h> #include <stdio.h>
static GtkWindow *window; static GtkWindow *main_window;
/** /**
* @brief 1) creates a new main window 2) presents this window * @brief 1) creates a new main window 2) presents this window
* *
* NB > on_app_activation() is in: widget/manager NOT in: src/signal * NB > on_windows_activation() is in: widget/manager NOT in: src/signal
* *
* @since 2024-06 * @since 2024-06
* *
* @callgraph * @callgraph
* @see widget_design_main_window() * @see widget_design_main_window()
* @see widget_design_dialog_window()
* @see widget_design_text_window()
* @see util_trigger_test() * @see util_trigger_test()
* @see fsm_add_log() * @see fsm_add_log()
* *
@ -55,9 +57,9 @@ static GtkWindow *window;
* *
* @param *app * @param *app
*/ */
void on_app_activation (GtkApplication *app) void on_windows_activation (GtkApplication *app)
{ {
fsm_add_log (INFO, WIDGETS, "widget/manager", "app activation()", "has began"); fsm_add_log (INFO, WIDGETS, "widget/manager", "windows activation()", "has began");
// on_windows_activation() is in: widget/manager NOT in: src/signal // on_windows_activation() is in: widget/manager NOT in: src/signal
// g_application_activate (G_APPLICATION (app)); < how ? > in main is // g_application_activate (G_APPLICATION (app)); < how ? > in main is
@ -74,14 +76,12 @@ void on_app_activation (GtkApplication *app)
//gtk_widget_destroy(widget); //gtk_widget_destroy(widget);
window = GTK_WINDOW (gtk_application_window_new (app)); main_window = GTK_WINDOW (gtk_application_window_new (app));
int window_int_id = gtk_application_window_get_id (GTK_APPLICATION_WINDOW (window)); int window_int_id = gtk_application_window_get_id (GTK_APPLICATION_WINDOW (main_window));
char window_char_id[40]; char window_char_id[40];
sprintf(window_char_id, "%d", window_int_id); sprintf(window_char_id, "%d", window_int_id);
g_signal_connect(window, "close-request", G_CALLBACK (on_window_close_request), (void *)(long long)window_int_id);
//printf ("gtk_application_window_id = %s = %d\n", window_char_id, window_int_id); //printf ("gtk_application_window_id = %s = %d\n", window_char_id, window_int_id);
fsm_add_log (INFO, WIDGETS, "widget/manager", "gtk_application_window_get_id", fsm_add_log (INFO, WIDGETS, "widget/manager", "gtk_application_window_get_id",
@ -90,9 +90,9 @@ void on_app_activation (GtkApplication *app)
//printf ("gtk_application_window_get_id (main_window) = %d\n", //printf ("gtk_application_window_get_id (main_window) = %d\n",
//gtk_application_window_get_id (GTK_APPLICATION_WINDOW (main_window))); //gtk_application_window_get_id (GTK_APPLICATION_WINDOW (main_window)));
widget_design_main_window (window, app); widget_get_main_window (main_window, app);
gtk_window_present (GTK_WINDOW (window)); gtk_window_present (GTK_WINDOW (main_window));
// g_object_unref (main_window); TODO get the closing signal of the main window // g_object_unref (main_window); TODO get the closing signal of the main window
@ -117,21 +117,7 @@ void on_app_activation (GtkApplication *app)
g_action_map_add_action (G_ACTION_MAP (app), G_ACTION (act_b)); g_action_map_add_action (G_ACTION_MAP (app), G_ACTION (act_b));
g_signal_connect (act_b, "activate", G_CALLBACK (action_b), app2);*/ g_signal_connect (act_b, "activate", G_CALLBACK (action_b), app2);*/
fsm_add_log (INFO, WIDGETS, "widget/manager", "app activation()", fsm_add_log (INFO, WIDGETS, "widget/manager", "windows activation()",
"has ended 🧐️ | 👉️ a new session starts"); "has ended 🧐️ | 👉️ a new session starts");
} }
gboolean on_window_close_request (GtkWindow *window, gpointer user_data)
{
fsm_add_log (INFO, WIDGETS, "widget/manager", "window close request()",
"freeing all ressources !");
// free the only child
gtk_window_set_child (window, NULL); // deleting the child from window
// drop window's reference
gtk_window_destroy (window);
return false; // the default handler takes care of g_object_unref for window
}