Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
Specifies whether the models specified are root models.
Returns
-------
list
A list containing two entries. The first entry corresponds to the mapping of the root models, including their parents. The second entry corresponds to the next index to be considered in a parameter list.
"""
if(models is None):
models = self.model
mapping = []
for model in models:
# If this model corresponds to an unvisited free parameter, add it to the mapping
if(is_not_root and not(model.visited) and not(isinstance(model, Hyperparameter)) and not(isinstance(model, ModelResultingFromOperation))):
mapping.append((model, index))
index+= 1 #model.get_output_dimension()
# Add all parents to the mapping, if applicable
for parent in model.get_input_models():
parent_mapping, index = self._get_mapping([parent], index=index, is_not_root=True)
parent.visited=True
for mappings in parent_mapping:
mapping.append(mappings)
model.visited=True
# At the end of the algorithm, reset all flags such that another method can act on the graph freely.
if(not(is_not_root)):
self._reset_flags()
return [mapping, index]
model_output_dim = [0, 0]
for i, model in enumerate(parameters):
if isinstance(model, ProbabilisticModel):
model_output_dim[i] = model.get_output_dimension()
elif isinstance(model, Number):
model_output_dim[i] = 1
else:
raise TypeError('Unsupported type.')
# here, model_output_dim contains the dim of both input models
if model_output_dim[0] != model_output_dim[1]:
raise ValueError('The provided models are not of equal dimension.')
self._dimension = 1
input_parameters = InputConnector.from_list(parameters)
super(ModelResultingFromOperation, self).__init__(input_parameters, name)
for j in range(0, self.get_input_dimension()):
model = self.get_input_connector().get_model(j)
parameter_values[j] = model_samples[model][i]
# add the corresponding parameter_values
sample_value = []
for j in range(self.get_output_dimension()):
sample_value.append(parameter_values[j]+parameter_values[j+self.get_output_dimension()])
if(len(sample_value)==1):
sample_value=sample_value[0]
return_value.append(sample_value)
return return_value
class SubtractionModel(ModelResultingFromOperation):
"""This class represents all probabilistic models resulting from an subtraction of two probabilistic models"""
def forward_simulate(self, input_values, k, rng=np.random.RandomState(), mpi_comm=None):
"""Adds the sampled values of both parent distributions.
Parameters
----------
input_values: list
List of input values
k: integer
The number of samples that should be sampled
rng: random number generator
The random number generator to be used.
mpi_comm: MPI communicator object
Defines the MPI communicator object for MPI parallelization. The default value is None,
meaning the forward simulation is not MPI-parallelized.
Returns
-------
list
The first entry corresponds to the mapping of the root model, as well as all its parents. The second entry corresponds to the next index in depth-first search.
"""
# Implement a dfs to discover all nodes of the model
mapping = []
for model in models:
if(not(model.visited) and not(isinstance(model, Hyperparameter))):
model.visited = True
# Only parameters that are neither root nor Hyperparameters are included in the mapping
if(not(is_root) and not(isinstance(model, ModelResultingFromOperation))):
for i in range(model.get_output_dimension()):
mapping.append((model, index))
index+=1
for parent in model.get_input_models():
parent_mapping, index = self.get_mapping([parent], is_root= False, index=index)
for element in parent_mapping:
mapping.append(element)
# Reset the flags of all models
if(is_root):
self._reset_flags()
return [mapping, index]
for j in range(0, self.get_input_dimension()):
model = self.get_input_connector().get_model(j)
parameter_values[j] = model_samples[model][i]
# subtract the corresponding parameter_values
sample_value = []
for j in range(self.get_output_dimension()):
sample_value.append(parameter_values[j] - parameter_values[j + self.get_output_dimension()])
if(len(sample_value)==1):
sample_value=sample_value[0]
return_value.append(sample_value)
return return_value
class MultiplicationModel(ModelResultingFromOperation):
"""This class represents all probabilistic models resulting from a multiplication of two probabilistic models"""
def forward_simulate(self, input_values, k, rng=np.random.RandomState(), mpi_comm=None):
"""Multiplies the sampled values of both parent distributions element wise.
Parameters
----------
input_values: list
List of input values
k: integer
The number of samples that should be sampled
rng: random number generator
The random number generator to be used.
mpi_comm: MPI communicator object
Defines the MPI communicator object for MPI parallelization. The default value is None,
meaning the forward simulation is not MPI-parallelized.
model = self.get_input_connector().get_model(j)
parameter_values[j] = model_samples[model][i]
# multiply the corresponding parameter_values
sample_value = []
for j in range(self.get_output_dimension()):
sample_value.append(parameter_values[j] * parameter_values[j+self.get_output_dimension()])
if (len(sample_value) == 1):
sample_value = sample_value[0]
return_value.append(sample_value)
return return_value
class DivisionModel(ModelResultingFromOperation):
"""This class represents all probabilistic models resulting from a division of two probabilistic models"""
def forward_simulate(self, input_valus, k, rng=np.random.RandomState(), mpi_comm=None):
"""Divides the sampled values of both parent distributions.
Parameters
----------
input_values: list
List of input values
k: integer
The number of samples that should be sampled
rng: random number generator
The random number generator to be used.
mpi_comm: MPI communicator object
Defines the MPI communicator object for MPI parallelization. The default value is None,
meaning the forward simulation is not MPI-parallelized.
is_root: boolean
Defines whether the current models are at the root. This ensures that only values corresponding to random variables will be set.
Returns
-------
list: [boolean, integer]
Returns whether it was possible to set all parameters and the next index to be considered in the parameters list.
"""
# If we are at the root, we set models to the model attribute of the inference method
if is_root:
models = self.model
for model in models:
# New parameters should only be set in case we are not at the root
if not is_root and not isinstance(model, ModelResultingFromOperation):
#new_output_values = np.array(parameters[index:index + model.get_output_dimension()])
new_output_values = np.array(parameters[index]).reshape(-1,)
if not model.set_output_values(new_output_values):
return [False, index]
index += 1 #model.get_output_dimension()
model.visited = True
# New parameters for all parents are set using a depth-first search
for parent in model.get_input_models():
if not parent.visited and not isinstance(parent, Hyperparameter):
is_set, index = self.set_parameters(parameters, models=[parent], index=index, is_root=False)
if not is_set:
# At the end of the algorithm, are flags are reset such that new methods can act on the graph freely
if is_root:
self._reset_flags()
return [False, index]
parameter_values = [0 for i in range(self.get_input_dimension())]
for j in range(0, self.get_input_dimension()):
model = self.get_input_connector().get_model(j)
parameter_values[j] = model_samples[model][i]
# divide the corresponding parameter_values
sample_value = []
for j in range(self.get_output_dimension()):
sample_value.append(parameter_values[j]/parameter_values[j + self.get_output_dimension()])
return_value += sample_value
return return_value
class ExponentialModel(ModelResultingFromOperation):
"""This class represents all probabilistic models resulting from an exponentiation of two probabilistic models"""
def __init__(self, parameters, name=''):
"""
Specific initializer for exponential models that does additional checks.
Parameters
----------
parameters: list
List of probabilistic models that should be added together.
"""
exp = parameters[1]
if isinstance(exp, ProbabilisticModel):
if exp.get_output_dimension() != 1:
raise ValueError('The exponent can only be 1 dimensional.')
if not model.visited:
model_has_valid_parameters = model._check_input(model.get_input_values())
if model_has_valid_parameters:
model_samples[model] = model.forward_simulate(model.get_input_values(), k, rng=rng)
model.visited = True
else:
raise ValueError('Model %s has invalid input parameters.' % parent.name)
# Restore the visited state of all input models
for i in range(0, self.get_input_dimension()):
self.get_input_connector().get_model(i).visited = visited_state[i]
return model_samples
class SummationModel(ModelResultingFromOperation):
"""This class represents all probabilistic models resulting from an addition of two probabilistic models"""
def forward_simulate(self, input_values, k, rng=np.random.RandomState(), mpi_comm=None):
"""Adds the sampled values of both parent distributions.
Parameters
----------
input_values: list
List of input values
k: integer
The number of samples that should be sampled
rng: random number generator
The random number generator to be used.
mpi_comm: MPI communicator object
Defines the MPI communicator object for MPI parallelization. The default value is None,
meaning the forward simulation is not MPI-parallelized.
for j in range(0, self.get_input_dimension()):
model = self.get_input_connector().get_model(j)
parameter_values[j] = model_samples[model][i]
power = parameter_values[-1]
sample_value = []
for j in range(self.get_output_dimension()):
sample_value.append(parameter_values[j]**power)
result.append(np.array(sample_value))
return result
class RExponentialModel(ModelResultingFromOperation):
"""This class represents all probabilistic models resulting from an exponentiation of a Hyperparameter by another probabilistic model."""
def __init__(self, parameters, name=''):
"""
Specific initializer for exponential models that does additional checks.
Parameters
----------
parameters: list
List of probabilistic models that should be added together.
"""
exp = parameters[1]
if isinstance(exp, ProbabilisticModel):
if exp.get_output_dimension() != 1:
raise ValueError('The exponent can only be 1 dimensional.')