Initial gnuplot mechanism working

Using GNUPLOT on a simulation output file will produce a gnuplot
command and a datafile to generate a graph for a given simulation run.
This commit is contained in:
Mark Evenson 2022-09-04 08:36:20 +02:00
parent 650b26d495
commit 7effa57921
4 changed files with 83 additions and 24 deletions

View File

@ -1,7 +1,7 @@
(defsystem glacier
:version "0.0.1"
:version "0.0.2"
:depends-on (alexandria
drakma
do-urlencode
jsown
split-sequence)
:components ((:module source

View File

@ -50,9 +50,13 @@
(loop for (key . value) :in key-values
:collecting (format nil "~a=~a" key value))))))
(values
(drakma:url-encode string :utf8)
(do-urlencode:urlencode string :queryp t)
string)))
(defun decode-parameters (filename)
(let ((name (pathname-name (pathname filename))))
(do-urlencode:urldecode name :queryp t)))
(defun run (trials
&key
parameters
@ -129,8 +133,6 @@
($.distribution.yes ,(coerce yes 'single-float))
($.distribution.no ,(coerce no 'single-float))))))
;;; unused
(defun json-parameters ()
`($.consensus_settings.glacier.evidence_alpha

View File

@ -29,7 +29,56 @@
(dolist (file files)
(format *standard-output* "~&~a~&~a~%" file (summarize file)))
(format *standard-output* "~&Summarized ~d files." (length files))))
(defun gnuplot (file)
"Generate gnuplot command and data for FILE"
(let ((data
(make-pathname :defaults file
:type "data"))
(plot
(make-pathname :defaults file
:type "gnuplot"))
(summary
(summarize file)))
(with-open-file (out data :direction :output :if-exists :supersede)
(loop :for (undecided no yes) :in summary
:doing (format out "~a ~a ~a~%" undecided no yes)))
(with-open-file (out plot :direction :output :if-exists :supersede)
(format out "source = '~a'~%" data)
(format out "set xlabel 'rounds'~%")
(format out "set ylabel 'node opinions'~%")
(format out "plot ~
source using 1 with linespoints pointnumber 3 title 'none', ~
source using 2 with linespoints pointnumber 7 title 'no', ~
source using 3 with linespoints pointnumber 11 title 'yes', ~
1/0 title '~a'~%" (gnuplot-legend file)))
(values
plot
data)))
(defun gnuplot-legend (filename)
(let* ((name
(do-urlencode:urldecode (pathname-name filename) :queryp t))
(all-pairs
(second ;; not going to work for negative integer values
(split-sequence:split-sequence #\- name)))
(pairs
(split-sequence:split-sequence #\space all-pairs))
(assoc-pairs
(loop :for pair :in pairs
:collecting (let ((key-value (split-sequence:split-sequence #\= pair)))
`(,(first key-value) . ,(second key-value))))))
(flet
((get-value (key)
(alexandria:assoc-value assoc-pairs key :test 'equal)))
(values
(format nil "l=~a α_1=~a α_2=~a k=~a"
(get-value "look_ahead")
(get-value "evidence_alpha")
(get-value "evidence_alpha_2")
(get-value "initial_query_size"))
assoc-pairs))))

View File

@ -24,47 +24,55 @@ to produce a plot of total yes, no, and undecided per round.
Simulate up to 10^4 nodes adding 10, 100, 1000?
#+caption: run Glauber simulator
#+caption: run Glacier simulator
#+begin_src bash
./target/release-opt/consensus-simulations --input-settings etc/glacier.json --output-file=./var/glauber.output
#+end_src
** TODO Grind out parametrized settings with existing code
#+caption: use these on a base templateo
| a1 | $.consensus_settings.glacier.evidence_alpha |
| a2 | $.consensus_settings.glacier.evidence_alpha_2 |
| l | $.consensus_settings.glacier.look_ahead |
| k | $.consensus_settings.query.initial_query_size |
| k_multiplier | $.consensus_settings.query_multiplier |
| k_multiplier_max | $.consensus_settings.max_multiplier |
| n | $.byzantine_settings.total_size |
| n_honest | $.byzantine_settings.honest |
| initial yes | $.distribution.yes |
| intial no | $.distribution.no |
| | |
#+caption: use these on a base template
| name | JSON path | Notes |
|------------------+-----------------------------------------------+-------|
| a1 | $.consensus_settings.glacier.evidence_alpha | |
| a2 | $.consensus_settings.glacier.evidence_alpha_2 | |
| l | $.consensus_settings.glacier.look_ahead | |
| k | $.consensus_settings.query.initial_query_size | |
| k_query_size | $.consensus_settings.query.query_size | ??? |
| k_multiplier | $.consensus_settings.query_multiplier | |
| k_multiplier_max | $.consensus_settings.max_multiplier | |
| n | $.byzantine_settings.total_size | |
| honest | $.byzantine_settings.honest | |
| yes | $.distribution.yes | |
| no | $.distribution.no | |
| | | |
** TODO Double check that this is all we need.
opinion votes can be derived…
* TODO Make parameters depend on network size
* <2022-09-02 Fri> Initial implementation
** TODO encode/decode parameters in simulation input/outout filenames
** TODO encode/decode parameters in simulation input/output filenames
All are encoded except for =query-size=. What is the difference between this and =initial_query_size=?
*** TODO record random seed used for execution
Probably should be able to be specified in configuration as otherwise
it needs to be parsed from =consensus-simulations= stdout.
** TODO write basic execution pipeline
** DONE write basic execution pipeline
CLOSED: [2022-09-04 Sun 08:35]
- CLOSING NOTE [2022-09-04 Sun 08:35]
** TODO benchmark
Along machine, architecture, and async/sync axes
** TODO setup/run batch jobs
*** For @AlexanderM's parameter choices
*** For RFC 38
** TODO instrument simulation to emit line data
** TODO Produce graphs
** DONE Produce graphs
CLOSED: [2022-09-04 Sun 08:35]
- CLOSING NOTE [2022-09-04 Sun 08:35]
For given parameter choices show YES, NO, NONE opinion evolution over rounds
* Colophon
#+begin_example
@easye <mark.evenson@status.im>
Created: 01-SEP-2022
Revised: <2022-09-03 Sat 03:58>
Revised: <2022-09-04 Sun 08:35>
#+end_example