1"""Deals with creating the random number generator.
2
3Copyright (C) 2013, Joshua More and Michele Ceriotti
4
5This program is free software: you can redistribute it and/or modify
6it under the terms of the GNU General Public License as published by
7the Free Software Foundation, either version 3 of the License, or
8(at your option) any later version.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program. If not, see <http.//www.gnu.org/licenses/>.
17
18
19Generates a random number generator either from a seed number, or from a
20state vector.
21
22Classes:
23   InputRandom: Deals with creating the Random object from a file, and
24      writing the checkpoints.
25"""
26
27__all__ = ['InputRandom']
28
29import numpy as np
30from ipi.utils.prng import *
31from ipi.utils.inputvalue import *
32
33class InputRandom(Input):
34   """Random input class.
35
36   Handles generating the appropriate random number class from the xml
37   input file, and generating the xml checkpoint tags and data from an
38   instance of the object.
39
40   Attributes:
41      seed: An optional integer giving a seed to initialize the random number
42         generator from. Defaults to 123456.
43      state: An optional array giving the state of the random number generator.
44         Defaults to an empty array.
45      has_gauss: An optional integer giving whether there is a stored
46         Gaussian number or not. Defaults to 0.
47      gauss: An optional float giving the stored Gaussian number. Defaults to
48         0.0.
49      set_pos: An optional integer giving the position in the state array
50         that is being read from. Defaults to 0.
51   """
52
53   fields = {"seed"      : (InputValue, {"dtype"   : int,
54                                         "default" : 123456,
55                                         "help"    : "This is the seed number used to generate the initial state of the random number generator."}),
56             "state"     : (InputArray, {"dtype"   : np.uint,
57                                         "default" : input_default(factory=np.zeros, kwargs={'shape': (0,), 'dtype': np.uint}),
58                                         "help"    : "Gives the state vector for the random number generator. Avoid directly modifying this unless you are very familiar with the inner workings of the algorithm used."}),
59             "has_gauss" : (InputValue, {"dtype"   : int,
60                                         "default" : 0,
61                                         "help"    : "Determines whether there is a stored gaussian number or not. A value of 0 means there is none stored."}),
62             "gauss"     : (InputValue, {"dtype"   : float,
63                                         "default" : 0.00,
64                                         "help"    : "The stored Gaussian number." }),
65             "set_pos"   : (InputValue, {"dtype"   : int,
66                                         "default" : 0,
67                                         "help"    : "Gives the position in the state array that the random number generator is reading from."})}
68
69   default_help = "Deals with the pseudo-random number generator."
70   default_label = "PRNG"
71
72   def store(self, prng):
73      """Takes a random number instance and stores a minimal
74      representation of it.
75
76      Args:
77         prng: A random number object from which to initialize from.
78      """
79
80      super(InputRandom,self).store(prng)
81      self.seed.store(prng.seed)
82      gstate = prng.state
83      self.state.store(gstate[1])
84      self.set_pos.store(gstate[2])
85      self.has_gauss.store(gstate[3])
86      self.gauss.store(gstate[4])
87
88   def fetch(self):
89      """Creates a random number object.
90
91      Returns:
92         An random number object of the appropriate type and with the
93         appropriate properties given the attributes of the InputRandom
94         object.
95      """
96
97      super(InputRandom,self).fetch()
98      if not self.state._explicit:
99         return Random(seed=self.seed.fetch())
100      else:
101         return Random(state=('MT19937',self.state.fetch(), self.set_pos.fetch(), self.has_gauss.fetch(), self.gauss.fetch() ))
102