¿Existe un límite para el valor inicial en pgfmathsetseed?

¿Existe un límite para el valor inicial en pgfmathsetseed?

Estoy usando pgf para crear algunos exámenes aleatorios. Para configurar la semilla, estoy usando pgfmathsetseed. Este sistema utiliza valores muy diferentes para la semilla, cuyo rango podría llegar a miles. El manual de pgf dice que pgfmathsetseed recibe un número entero, y no hay información sobre ningún límite. Pero obtengo exactamente los mismos resultados para diferentes semillas. El siguiente código ilustra el problema:

\documentclass[letterpaper,9pt]{article}
\usepackage{tikz} % also for pgfmathparse
\usepackage{pgfmath} % also for pgfmathparse
\usepackage{siunitx} % also for pgfmathparse
\usepgflibrary{fpu}
\pgfkeys{/pgf/fpu}
\pgfkeys{/pgf/fpu/output format=sci}
\pgfkeys{/pgf/number format/.cd, sci, sci e, sci zerofill, precision = 3}

\newcommand{\example}[1]{%
  \pgfmathsetseed{#1}
  \pgfmathsetmacro{\FACTOR}{0.90} % constrol the randomness span
  \pgfmathrandominteger{\NA}{1}{9}
  \pgfmathsetmacro{\LAA}{2.0*(1 + \FACTOR*rand)}
  \begin{tabular}{ccc}
    #1 & \Num{\NA} & \Num{\LAA}
  \end{tabular}
}

\newcommand{\Num}[1]{\pgfmathprintnumberto{#1}{\tmpnum}\ensuremath{\num{\tmpnum}}}

\begin{document}

\example{92}

\example{96}

\example{90}

\example{1}

\example{2}

\end{document}

y la salida es como

92 1.000 1.576
96 1.000 1.576
90 1.000 1.576
1 7.000 2.245
2 4.000 6.891 × 10−1

Como puedes ver, para varias semillas los valores son los mismos. ¿Existe un límite para el número entero que se puede poner dentro de pgfmathsetseed? ¿O cuál es el problema? Gracias.

Respuesta1

La producción de números aleatorios depende de algunos parámetros iniciales que se encuentran en pgfmathfunctions.random.code.tex:

\def\pgfmath@rnd@a{69621}
\def\pgfmath@rnd@r{23902}
\def\pgfmath@rnd@q{30845}

Según recuerdo (no lo he comprobado), los valores de los parámetros se obtuvieron de las referencias numéricas de Press et al. en C, segunda edición. Se sugieren alternativas (que también se enumeran en los comentarios de pgfmathfunctions.random.code.tex).

Estos parámetros se pueden cambiar, por ejemplo, a los mismos parámetros que los de Erich Janka.paquete lgg(en el que se basó el material aleatorio de pgf), lo que podría dar como resultado resultados más deseables (aunque aún pueden ocurrir repeticiones en secuencias de semillas consecutivas)

\documentclass{ltxdoc}
\usepackage{geometry}
\parindent=0pt
\usepackage{pgfmath,pgffor,lcg,xcolor,multicol}
\makeatletter
\def\pgfmath@rnd@a{16807}
\def\pgfmath@rnd@r{2836}
\def\pgfmath@rnd@q{127773}
\makeatother
\newcounter{lcgresult}
\newcommand{\example}[1]{%
  \pgfmathsetseed{#1}%
  \reinitrand[seed=#1, counter=lcgresult, first=1, last=9]
  \xdef\pgfseq{}%
  \xdef\lcgseq{}%
  \foreach\s in{0,...,10}{%
    \pgfmathrandominteger{\r}{1}{9}
    \xdef\pgfseq{\pgfseq\space\r}
    \rand
    \xdef\lcgseq{\lcgseq\space\thelcgresult}
  }%
  \begin{tabular}{p{0.5cm}p{4cm}}
    #1\hfil & \textcolor{blue}{\pgfseq} \newline \lcgseq
  \end{tabular}%
}
\begin{document}
\begin{multicols}{3}
\foreach \i in {1,...,60}{\example{\i}}
\end{multicols}
\end{document}

ingrese la descripción de la imagen aquí

Respuesta2

Parece que algo anda mal aquí: aparentemente sólo el primer dígito es significativo.

\documentclass{article}
\usepackage{geometry}
\usepackage{multicol}
\usepackage{tikz} % also for pgfmathparse
\usepackage{pgfmath} % also for pgfmathparse
\usepackage{siunitx} % also for pgfmathparse
\usepgflibrary{fpu}
\pgfkeys{/pgf/fpu}
\pgfkeys{/pgf/fpu/output format=sci}
\pgfkeys{/pgf/number format/.cd, sci, sci e, sci zerofill, precision = 3}

\newcommand{\example}[1]{%
  \pgfmathsetseed{#1}%
  \pgfmathsetmacro{\FACTOR}{0.90}% constrol the randomness span
  \pgfmathrandominteger{\NA}{1}{9}%
  \pgfmathsetmacro{\LAA}{2.0*(1 + \FACTOR*rand)}%
  #1\quad\Num{\NA}\quad\Num{\LAA}\par
}

\newcommand{\Num}[1]{\pgfmathprintnumberto{#1}{\tmpnum}\ensuremath{\num{\tmpnum}}}

\begin{document}

\begin{multicols}{3}

\count255=0
\loop\ifnum\count255<120
\expandafter\example{\the\count255}
\advance\count255 1
\repeat

\end{multicols}

\end{document}

ingrese la descripción de la imagen aquí

Si miramos la tabla, todas las llamadas con el argumento que comienza con 1producen el mismo resultado, lo mismo para 2y así sucesivamente.

Por otro lado, si comento las líneas relacionadas con fpu, el resultado se convierte en

ingrese la descripción de la imagen aquí

El número entero aleatorio en realidad no parece tan aleatorio, ya que sólo se eligen 1, 4 y 7.

Esto es lo que obtengo a expl3través de xfp:

\documentclass{article}
\usepackage{geometry}
\usepackage{multicol}
\usepackage{siunitx,xfp}

\sisetup{round-precision=5,round-mode=figures,scientific-notation=true}

\newcommand{\FACTOR}{0.9}

\newcommand{\example}[1]{%
  \pdfsetrandomseed #1\relax
  #1\quad\num{\fpeval{randint(1,9)}}\quad\num{\fpeval{2*(1+\FACTOR*rand())}}\par
}

\begin{document}

\begin{multicols}{3}

\count255=0
\loop\ifnum\count255<120
\expandafter\example{\the\count255}
\advance\count255 1
\repeat

\end{multicols}

\end{document}

ingrese la descripción de la imagen aquí

Respuesta3

Al usar la respuesta de @Mark Wibrow, pude mejorar el algoritmo aleatorio (usando los nuevos parámetros para el generador que en realidad provienen de la segunda edición de Numerical Recipies), pero también señalar la incompatibilidad con el fpu de pgf. y el cuajado de la semilla. NOTA: En mi aplicación necesito el fpu para calcular varias cantidades, estas mwe no lo muestra.

El siguiente ejemplo muestra que cuando se activa /pgf/fpu, el generador de números aleatorios funciona como se esperaba incluso después de usar los parámetros mejorados. Si lo desactivo localmente los resultados son mucho mejores. No sé exactamente cómo solucionar este problema, pero de alguna manera la función pgfmathsetseed se ve afectada y no produce los datos correctos. Aquí está el ejemplo

\documentclass{standalone}
\usepackage{tikz,pgfmath,pgffor,siunitx,multicol} 
\usepgflibrary{fpu}
\pgfkeys{/pgf/fpu/output format=sci}
\pgfkeys{/pgf/number format/.cd, sci, sci e, sci zerofill, precision = 3}

\pgfkeys{/pgf/fpu=true} % this breaks pgfmathsetseed

\makeatletter
\def\pgfmath@rnd@a{16807}
\def\pgfmath@rnd@r{2836}
\def\pgfmath@rnd@q{127773}
\makeatother

\newcommand{\pgfmathsetseednew}[1]{%
  \pgfkeys{/pgf/fpu=false}
  \pgfmathsetseed{#1}
  \pgfkeys{/pgf/fpu=true}
}

\newcommand{\exampleA}[1]{%
  \pgfmathsetseed{#1}%
  \pgfmathrandominteger{\r}{1}{9}
  \pgfmathsetmacro{\LAA}{2.0*(1 + 0.90*rand)}
  #1 \quad \r \quad \Num{\LAA}\par
}
\newcommand{\exampleB}[1]{%
  \pgfmathsetseednew{#1}
  \pgfmathrandominteger{\r}{1}{9}
  \pgfmathsetmacro{\LAA}{2.0*(1 + 0.90*rand)}
  #1 \quad \r \quad \Num{\LAA}\par
}
\newcommand{\Num}[1]{\pgfmathprintnumberto{#1}{\tmpnum}\ensuremath{\num{\tmpnum}}}

\begin{document}
\begin{tabular}{m{0.4\textwidth}m{0.4\textwidth}}
  /pgf/fpu globally activated & /pgf/fpu locally deactivated\\
  \foreach \i in {80,...,99}{\exampleA{\i}}
  &
    \foreach \i in {80,...,99}{\exampleB{\i}}
\end{tabular}
\end{document}

y la salida es

Comparación entre fpu activada y desactivada

Entonces, en mi caso, necesito desactivar localmente el fpu. Esta respuesta se basa completamente en la anterior, así que creo que marcaré la anterior como respuesta.

Respuesta4

Prefiero usar luaun generador de números aleatorios:

\documentclass[letterpaper,9pt]{article}
\usepackage{tikz} % also for pgfmathparse
\usepackage{pgfmath} % also for pgfmathparse
\usepackage{siunitx} % also for pgfmathparse
\usepackage{luacode,multicol}

\usepgflibrary{fpu}
\pgfkeys{/pgf/fpu}
\pgfkeys{/pgf/fpu/output format=sci}
\pgfkeys{/pgf/number format/.cd, sci, sci e, sci zerofill, precision = 3}


\NewDocumentCommand{\Seed}{O{os.time( )}}{%
        \directlua{math.randomseed ( #1 ) ;}%
}

\NewDocumentCommand{\Random}{oom}{%
    % no argument :  real number between 0 and 1
    % upper : integer numbers between 1 and upper (both inclusive).
    % lower and upper : integer numbers between lower and upper
    %                                             (both inclusive).
    \IfNoValueTF{#2}{% not 2 arguments
        \IfNoValueTF{#1}{% no arguments
            \luadirect{
                t = math.random ( ) ;
            }
        }{%
            \luadirect{
                t = math.random ( #1 ) ;
            }
        }
    }{%
        \luadirect{
            t = math.random ( #1 , #2 ) ;
        }
    }
    \bgroup
        \edef\foo{\luadirect{tex.print ( t )}}
        \global\let#3=\foo
    \egroup
}


\newcommand{\example}[1]{%
  \pgfmathsetseed{#1}
  \pgfmathsetmacro{\FACTOR}{0.90} % constrol the randomness span
%  \pgfmathrandominteger{\NA}{1}{9}
  \Random[9]{\NA}
  \Random{\Rand}
  \pgfmathsetmacro{\LAA}{2.0*(1 + \FACTOR*\Rand)}
  \begin{tabular}{ccc}
    #1 & \Num{\NA} & \Num{\LAA}
  \end{tabular}
}

\newcommand{\Num}[1]{\pgfmathprintnumberto{#1}{\tmpnum}\ensuremath{\num{\tmpnum}}}

\begin{document}

\begin{multicols}{3}

\count255=0
\loop\ifnum\count255<120
\expandafter\example{\the\count255}
\advance\count255 1
\repeat

\end{multicols}

\end{document}

ingrese la descripción de la imagen aquí

información relacionada