Posted on Jun 14, 2025
Sheesh… this applied Mathematics project is going to take forever! I’m just dumping into it everything I find useful to organise my mind. It is what it is.
I think I’ve reached milestone one in using the package TikZ under LaTeX to draw function graphs. The result is in the example embedded document below.
I’m not going to explain here the full project management stuff I use (it works for me, but it’s ugly); but below is the chunk of Makefile that I use to generate pictures; it is meant to be used by gnu Make. The TikZ code itself is embedded in the ‘.tex’ document, but the data is generated by a C language program and written to a comma–separated values ‘.csv’ file; it uses the gnu Scientific Library to generate the random numbers.
.PHONY: figures builddir = . FIGURE_SOURCES = figura--sezione--processi-stocastici--esempio-passeggiata-aleatoria-01.c FIGURE_TARGETS = $(patsubst %.c,%.csv,$(FIGURE_SOURCES)) MMUX_CC_TYPES_LIBS = $(shell pkg-config mmux-cc-types --libs) MMUX_CC_TYPES_CFLAGS = $(shell pkg-config mmux-cc-types --cflags) MMUX_CC_LIBC_LIBS = $(shell pkg-config mmux-cc-libc --libs) MMUX_CC_LIBC_CFLAGS = $(shell pkg-config mmux-cc-libc --cflags) GSL_LIBS = $(shell pkg-config gsl --libs) GSL_CFLAGS = $(shell pkg-config gsl --cflags) GCC = gcc GCC_CFLAGS = -std=c11 -Wall $(MMUX_CC_TYPES_CFLAGS) $(MMUX_CC_LIBC_CFLAGS) $(GSL_CFLAGS) GCC_LIBS = $(MMUX_CC_TYPES_LIBS) $(MMUX_CC_LIBC_LIBS) $(GSL_LIBS) SUBSOURCES += $(FIGURE_TARGETS) $(DOCUMENTS): $(FIGURE_TARGETS) figures: $(FIGURE_TARGETS) figura--%.exe: figura--%.c $(GCC) $(GCC_CFLAGS) $(CFLAGS) $(GCC_LIBS) -o $(@) $(^) figura--%.csv: figura--%.exe $(builddir)/$(<) >$(@)
I use the Makefile variable SUBSOURCES
to list all the files that are needed to build
the ‘.dvi’ file; there is a master document.tex file and multiple sezione--*.tex
and appendice--*.tex files that are included in the master; all the files to include are
listed in the SUBSOURCES
variable to be registered as prerequisites for the generation of the
device–independent ‘.dvi’ output file.
TikZ can compute values using its embedded facilities, but I find that getting used to implement a C separate language program makes the task easier when doing both simple and complex computations: there is less new stuff to learn, and there is the risk of starting to use TikZ only to realise later that it is not enough, and switch to a C program. Once a template file for the C program is done: it is easy to reuse it. Below is the C source itself:
/* figura--sezione--processi-stocastici--esempio-passeggiata-aleatoria-01.c -- * * Date: Jun 14, 2025 * * Abstract * * Generatore di file comma-separated values (.csv) utilizzato nel documento per * comporre una figura con esempi di passeggiate aleatorie. S'intende che il * codice LaTeX sia simile a: * * \begin{figure}[htbp] * \centering * \begin{tikzpicture} * \begin{axis}[...] * \addplot[blue, thick] table [x=ascissa, y=ordinataUno, col sep=comma] * {figura--sezione--processi-stocastici--esempio-passeggiata-aleatoria-01.csv}; * \addplot[red, thick] table [x=ascissa, y=ordinataDue, col sep=comma] * {figura--sezione--processi-stocastici--esempio-passeggiata-aleatoria-01.csv}; * \addplot[green, thick] table [x=ascissa, y=ordinataTre, col sep=comma] * {figura--sezione--processi-stocastici--esempio-passeggiata-aleatoria-01.csv}; * \addplot[brown, thick] table [x=ascissa, y=ordinataQuattro, col sep=comma] * {figura--sezione--processi-stocastici--esempio-passeggiata-aleatoria-01.csv}; * \addplot[PureGold, thick] table [x=ascissa, y=ordinataCinque, col sep=comma] * {figura--sezione--processi-stocastici--esempio-passeggiata-aleatoria-01.csv}; * \end{axis} * \end{tikzpicture} * \caption{Passeggiata aleatoria.} * \end{figure} * * Le passeggiate sono generte sommando al valore iniziale U(0)=100.0 delle * variazioni \Delta U generate con una distribuzione gaussiana, come * implementata dalla GNU Scientific Library. * * This program is free software: you can redistribute it and/or modify it under the * terms of the GNU General Public License as published by the Free Software * Foundation, either version 3 of the License, or (at your option) any later * version. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * PARTICULAR PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with this * program. If not, see <http://www.gnu.org/licenses/>. */ /** -------------------------------------------------------------------- ** Headers. ** ----------------------------------------------------------------- */ #include <mmux-cc-types.h> #include <mmux-cc-libc.h> #include <gsl/gsl_rng.h> #include <gsl/gsl_randist.h> /** -------------------------------------------------------------------- ** Type definitions. ** ----------------------------------------------------------------- */ struct ascissa_t { mmux_double_t start; mmux_double_t end; mmux_double_t step; mmux_usize_t number_of_ticks; mmux_double_t * values; }; typedef struct ascissa_t ascissa_t; struct ordinata_t { ascissa_t const * ascissa; mmux_double_t initial_value; mmux_double_t * values; }; typedef struct ordinata_t ordinata_t; /** -------------------------------------------------------------------- ** Global variables. ** ----------------------------------------------------------------- */ static mmux_libc_fd_t oufd, erfd; static gsl_rng * random_numbers_generator_p; /* ------------------------------------------------------------------ */ #undef NUMBER_OF_ORDINATA #define NUMBER_OF_ORDINATA 5 /* We want 12 variations vor each unit of ascissa. */ #undef NUMBER_OF_TICKS #define NUMBER_OF_TICKS (12 * 10) #undef ASCISSA_START #define ASCISSA_START 0.0 #undef ASCISSA_END #define ASCISSA_END 10.0 #undef ASCISSA_STEP #define ASCISSA_STEP (((ASCISSA_END) - (ASCISSA_START)) / (mmux_double_t)(NUMBER_OF_TICKS)) static mmux_double_t values_ascissa[NUMBER_OF_TICKS]; static mmux_double_t values_ordinata[NUMBER_OF_ORDINATA][NUMBER_OF_TICKS]; static ascissa_t ascissa = { .number_of_ticks = NUMBER_OF_TICKS, .start = ASCISSA_START, .end = ASCISSA_END, .step = ASCISSA_STEP, .values = values_ascissa, }; static ordinata_t ordinata[NUMBER_OF_ORDINATA] = { { .ascissa = &ascissa, .initial_value = 100.0, .values = values_ordinata[0], }, { .ascissa = &ascissa, .initial_value = 100.0, .values = values_ordinata[1], }, { .ascissa = &ascissa, .initial_value = 100.0, .values = values_ordinata[2], }, { .ascissa = &ascissa, .initial_value = 100.0, .values = values_ordinata[3], }, { .ascissa = &ascissa, .initial_value = 100.0, .values = values_ordinata[4], }, }; /** -------------------------------------------------------------------- ** Tuple generation functions. ** ----------------------------------------------------------------- */ static void ascissa_compute_values (ascissa_t * ascissa) { for (mmux_usize_t idx = 0; idx < ascissa->number_of_ticks; ++idx) { ascissa->values[idx] = ascissa->start + ((mmux_double_t)idx) * ascissa->step; } } static void ordinata_compute_values (ordinata_t * ordinata) { static mmux_double_t const standard_deviation = 3.0; ordinata->values[0] = ordinata->initial_value; for (mmux_usize_t idx = 1; idx < ordinata->ascissa->number_of_ticks; ++idx) { ordinata->values[idx] = ordinata->values[idx-1] + gsl_ran_gaussian(random_numbers_generator_p, standard_deviation); } } /** -------------------------------------------------------------------- ** Let's go. ** ----------------------------------------------------------------- */ int main (int argc, const char *const argv[]) { mmux_libc_stdou(&oufd); mmux_libc_stder(&erfd); /* Let's accept the default seed for this random-numbers generator. */ random_numbers_generator_p = gsl_rng_alloc(gsl_rng_random_glibc2); { /* compute values */ { ascissa_compute_values(&ascissa); for (mmux_usize_t ordinata_idx; ordinata_idx < NUMBER_OF_ORDINATA; ++ordinata_idx) { ordinata_compute_values(&ordinata[ordinata_idx]); } } /* print CSV data to stdout */ { mmux_libc_dprintf(oufd, "ascissa, ordinataUno, ordinataDue, ordinataTre, ordinataQuattro, ordinataCinque\n"); for (mmux_usize_t idx = 0; idx < ascissa.number_of_ticks; ++idx) { mmux_libc_dprintf(oufd, "%f, %f, %f, %f, %f, %f\n", ascissa.values[idx], ordinata[0].values[idx], ordinata[1].values[idx], ordinata[2].values[idx], ordinata[3].values[idx], ordinata[4].values[idx]); } } } gsl_rng_free(random_numbers_generator_p); mmux_libc_exit(MMUX_LIBC_EXIT_SUCCESS); } /* end of file */
Finally, below is the standalone LaTeX document I have extracted from the original source to generate the example ‘.pdf’ embedded above.
% documento.tex -*- coding: utf-8-unix -*- \documentclass[12pt,a4paper]{article} \renewcommand{\rmdefault}{ptm} % Times Roman font, for PDF output \usepackage[left=2cm, right=2cm, top=2cm, bottom=2cm]{geometry} \usepackage[italian]{babel} \usepackage[utf8]{inputenc} \usepackage[T1]{fontenc} \usepackage{tikz} \usepackage{pgfplots} \pgfplotsset{compat=1.18} \definecolor{PureGold}{RGB}{255,215,0} \begin{document} \author{Marco Maggi} \title{Esempio TikZ} \maketitle \section{Esempio di passeggiata aleatoria} % L'argomento "htbp" stabilisce con quale precedenza si sceglie il piazzamento della figura nella % pagina: here, top, bottom, standalone page. \begin{figure}[h] \centering \begin{tikzpicture} \begin{axis}[ % Seleziona il dominio del grafico per il calcolo. domain=0:10, % Seleziona il numero di campioni da calcolare e connettere con la linea spezzata. samples=120, % Seleziona l'etichetta dell'ascissa. xlabel=$t$, % Seleziona l'etichetta dell'ordinata. ylabel=$\mathcal{U}$, % Seleziona i valori minimo e massimo del dominio dell'ascissa da visualizzare nel grafico. xmin=0, xmax=10, % Seleziona i valori minimo e massimo del codominio dell'ordinata da visualizzare nel grafico. ymin=40, ymax=160, % Disegna gli assi dell'ascissa e dell'ordinata in modo che s'incrocino nell'origine (0,0). axis lines=middle, % Visualizza una griglia con linee sia per l'ascissa che per l'ordinata; le linee verticali % per l'ascissa sono disegnate nei valori scelti dopo con "xtick". grid=both, % Seleziona la larghezza e l'altezza della figura nella pagina LaTeX. width=17cm, height=8cm, ] % Disegna il grafico del sostegno della funzione. \addplot[blue, thick] table [x=ascissa, y=ordinataUno, col sep=comma] {figura--sezione--processi-stocastici--esempio-passeggiata-aleatoria-01.csv}; \addplot[red, thick] table [x=ascissa, y=ordinataDue, col sep=comma] {figura--sezione--processi-stocastici--esempio-passeggiata-aleatoria-01.csv}; \addplot[green, thick] table [x=ascissa, y=ordinataTre, col sep=comma] {figura--sezione--processi-stocastici--esempio-passeggiata-aleatoria-01.csv}; \addplot[brown, thick] table [x=ascissa, y=ordinataQuattro, col sep=comma] {figura--sezione--processi-stocastici--esempio-passeggiata-aleatoria-01.csv}; \addplot[PureGold, thick] table [x=ascissa, y=ordinataCinque, col sep=comma] {figura--sezione--processi-stocastici--esempio-passeggiata-aleatoria-01.csv}; \end{axis} \end{tikzpicture} \caption{Esempi di passeggiate aleatorie ottenute sommando al valore iniziale \(\mathcal{U}(t_0) = 100\), variazioni successive \(\mathcal{U}(t_{k}) - \mathcal{U}(t_{k-1})\) generate da una distribuzione gaussiana con valore atteso \(\mu = 0\) e deviazione standard \(\sigma = 3\). L'unità di misura del tempo \(t\) può essere fissata a piacere; in ogni caso: le passeggiate sono state generate con \(12\) variazioni per ogni unità di tempo.} \end{figure} \end{document} %%% Local Variables: %%% mode: latex %%% TeX-master: t %%% End:
I still have to experiment to find a way to put a Dirac’s unit impulse and non–unit impulse arrow in a graph. Do I want it with scaled length? Do I want all the arrows with the same length? it should not be difficult, but I have to dive in the documentation. Never stop fighting…