pgfmathsetseedのシード値に制限はありますか?

pgfmathsetseedのシード値に制限はありますか?

私は pgf を使用してランダムな試験をいくつか作成しています。シードを設定するために、pgfmathsetseed を使用しています。このシステムでは、シードに非常に異なる値を使用します。その範囲は数千に及ぶ可能性があります。pgf のマニュアルには、pgfmathsetseed は整数を受け取ると記載されていますが、制限については何も記載されていません。しかし、シードが異なってもまったく同じ結果が得られます。次のコードは、この問題を示しています。

\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}

出力は次のようになります

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

ご覧のとおり、複数のシードで値は同じです。pgfmathsetseed 内に入れることができる整数に制限はありますか? それとも、何が問題なのでしょうか? ありがとうございます。

答え1

乱数の生成は、以下の初期パラメータに依存しますpgfmathfunctions.random.code.tex

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

私の記憶では (確認はしていませんが)、パラメータ値は Press らの Numerical references in C, 2nd edition から収集したものです。代替案も提案されています ( のコメントにも記載されていますpgfmathfunctions.random.code.tex)。

これらのパラメータは、例えば、Erich Jankaのパラメータと同じものに変更することができます。LCG パッケージ(pgf のランダム要素のベース) より望ましい結果が得られる可能性があります (ただし、連続するシードのシーケンス全体で繰り返しが発生する可能性はあります)

\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}

ここに画像の説明を入力してください

答え2

何かが間違っているようです。どうやら最初の数字だけが重要なようです。

\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}

ここに画像の説明を入力してください

表を見ると、 で始まる引数を持つすべての呼び出しは1同じ出力を生成し、2などについても同様です。

一方、に関連する行をコメントアウトするとfpu、出力は次のようになります。

ここに画像の説明を入力してください

ランダムな整数は、1、4、7 のみが選択されるため、実際にはそれほどランダムではないようです。

expl3以下は、経由して得られるものです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}

ここに画像の説明を入力してください

答え3

@Mark Wibrow からの返信を使用することで、ランダム アルゴリズム (Numerical Recipies の第 2 版から実際に取得されたジェネレーターの新しいパラメーターを使用することで) を改善することができましたが、pgf の fpu とシードの設定との互換性の問題も指摘されました。注: 私のアプリケーションでは、いくつかの量を計算するために fpu が必要ですが、これらの mwe はそれを表示しません。

次の例は、/pgf/fpu が有効化されているときに、改良されたパラメータを使用した後でも乱数ジェネレータが期待通りに動作することを示しています。ローカルで無効化すると、結果ははるかに良くなります。これを正確に修正する方法はわかりませんが、何らかの理由で関数 pgfmathsetseed が影響を受け、正しいデータを生成しません。これが例です。

\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}

そして出力は

FPU の有効化と無効化の比較

したがって、私の場合は、FPU をローカルで非アクティブ化する必要があります。この回答は完全に前の回答に基づいているため、前の回答を回答としてマークするつもりです。

答え4

私はlua乱数ジェネレータを使用することを好みます:

\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}

ここに画像の説明を入力してください

関連情報