From d7d210ec740f5972f130f0182f15f96929dfd434 Mon Sep 17 00:00:00 2001 From: kraken_laptop Date: Sat, 17 Jun 2023 10:08:14 +0200 Subject: [PATCH] seed for random model --- jajapy/base/Base_MC.py | 10 ++++++---- jajapy/base/tools.py | 3 ++- jajapy/ctmc/CTMC.py | 18 ++++++++++++++---- jajapy/gohmm/GoHMM.py | 17 ++++++++++++----- jajapy/hmm/HMM.py | 10 +++++++++- jajapy/mc/MC.py | 10 ++++++++-- jajapy/mdp/MDP.py | 20 +++++++++++++++----- jajapy/pctmc/PCTMC.py | 18 ++++++++++++------ 8 files changed, 78 insertions(+), 28 deletions(-) diff --git a/jajapy/base/Base_MC.py b/jajapy/base/Base_MC.py index 7cf0518..55d58a9 100644 --- a/jajapy/base/Base_MC.py +++ b/jajapy/base/Base_MC.py @@ -1,6 +1,6 @@ from .Model import Model, MC_ID, MDP_ID, CTMC_ID from numpy import ndarray, where -from random import choices +from random import choices, seed class Base_MC(Model): """ @@ -123,7 +123,7 @@ def toStormpy(self): except ModuleNotFoundError: raise RuntimeError("Stormpy is not installed on this machine.") -def labelsForRandomModel(nb_states: int, labelling: list) -> list: +def labelsForRandomModel(nb_states: int, labelling: list, sseed:int=None) -> list: if 'init' in labelling: msg = "The label 'init' cannot be used: it is reserved for initial states." raise SyntaxError(msg) @@ -133,12 +133,14 @@ def labelsForRandomModel(nb_states: int, labelling: list) -> list: print("number of states. The last labels will not be assigned to",end=" ") print("any states.") - if nb_states > len(labelling): print("WARNING: the size of the labelling is lower than the",end=" ") print("number of states. The labels for the last states will",end=" ") print("be chosen randomly.") - + + if sseed != None: + seed(sseed) labelling = labelling[:min(len(labelling),nb_states)] + choices(labelling,k=nb_states-len(labelling)) labelling.append("init") + seed() return labelling diff --git a/jajapy/base/tools.py b/jajapy/base/tools.py index b0358be..f39a944 100644 --- a/jajapy/base/tools.py +++ b/jajapy/base/tools.py @@ -114,7 +114,8 @@ def randomProbabilities(size: int) -> ndarray: raise ValueError("The size parameter should be higher than 0.") if type(size) != int: raise TypeError("The size parameter should be an int.") - return normalize(randint(1,11,size)) + res = normalize(randint(1,11,size)) + return res def checkProbabilities(l: ndarray) -> bool: """ diff --git a/jajapy/ctmc/CTMC.py b/jajapy/ctmc/CTMC.py index 1189e77..872e9b4 100644 --- a/jajapy/ctmc/CTMC.py +++ b/jajapy/ctmc/CTMC.py @@ -1,4 +1,4 @@ -from numpy.random import exponential +import numpy.random from ast import literal_eval from ..base.tools import resolveRandom, randomProbabilities from ..base.Set import Set @@ -7,7 +7,7 @@ from ..base.Base_MC import * from math import exp, log from random import randint -from numpy import array, zeros, dot, ndarray, vstack, hstack, newaxis, append, delete, where, insert +from numpy import array, zeros, dot, vstack, hstack, newaxis, delete, insert from sys import platform from multiprocessing import cpu_count, Pool from sympy import sympify @@ -175,7 +175,7 @@ def next(self,state: int) -> tuple: if exp_lambda <= 0.0: exps.append(1024) else: - exps.append(exponential(1/exp_lambda)) + exps.append(numpy.random.exponential(1/exp_lambda)) next_state= exps.index(min(exps)) next_obs = self.labelling[state] return (next_obs, next_state, min(exps)) @@ -346,7 +346,8 @@ def loadCTMC(file_path: str) -> CTMC: def CTMC_random(nb_states: int, labelling: list, min_exit_rate_time : int, max_exit_rate_time: int, self_loop: bool = True, - random_initial_state: bool=True) -> CTMC: + random_initial_state: bool=True, + sseed:int=None) -> CTMC: """ Generates a random CTMC. All the rates will be between 0 and 1. All the exit rates will be integers. @@ -367,6 +368,8 @@ def CTMC_random(nb_states: int, labelling: list, min_exit_rate_time : int, random_initial_state: bool, optional If set to True we will start in each state with a random probability, otherwise we will always start in state 0. Default is True. + sseed : int, optional + the seed value. Returns ------- @@ -392,6 +395,10 @@ def CTMC_random(nb_states: int, labelling: list, min_exit_rate_time : int, s2 -> s0 : lambda = 0.2 s2 -> s1 : lambda = 0.8 """ + if sseed != None: + seed(sseed) + numpy.random.seed(sseed) + matrix = zeros((nb_states+1,nb_states)) for i in range(nb_states): if self_loop: @@ -411,6 +418,9 @@ def CTMC_random(nb_states: int, labelling: list, min_exit_rate_time : int, matrix = hstack((matrix,zeros(len(matrix))[:,newaxis])) labelling = labelsForRandomModel(nb_states,labelling) + + seed() + numpy.random.seed() return CTMC(matrix, labelling,"CTMC_random_"+str(nb_states)+"_states") def createCTMC(transitions: list, labelling: list, initial_state, diff --git a/jajapy/gohmm/GoHMM.py b/jajapy/gohmm/GoHMM.py index c8ab99b..b2e18ba 100644 --- a/jajapy/gohmm/GoHMM.py +++ b/jajapy/gohmm/GoHMM.py @@ -1,10 +1,10 @@ -from numpy.random import normal +import numpy.random +import random from numpy import array, zeros, ndarray from ast import literal_eval from ..base.tools import randomProbabilities from ..base.Base_HMM import Base_HMM, GOHMM_ID from math import sqrt, exp, pi -from random import uniform class GoHMM(Base_HMM): """ @@ -141,7 +141,7 @@ def next_obs(self, s:int) -> list: output : str An observation. """ - return [normal(parameter[0],parameter[1],1)[0] for parameter in self.output[s]] + return [numpy.random.normal(parameter[0],parameter[1],1)[0] for parameter in self.output[s]] def tau(self,s1:int,s2:int,obs: list) -> float: """ @@ -219,7 +219,7 @@ def loadGoHMM(file_path: str) -> GoHMM: def GoHMM_random(nb_states:int,nb_distributions:int, random_initial_state:bool=False, min_mu: float=0.0,max_mu: float=2.0, - min_sigma: float=0.5,max_sigma: float=2.0) -> GoHMM: + min_sigma: float=0.5,max_sigma: float=2.0, sseed: int = None) -> GoHMM: """ Generates a random GoHMM. @@ -243,6 +243,8 @@ def GoHMM_random(nb_states:int,nb_distributions:int, lower bound for sigma. By default 0.5 max_sigma : float, optional upper bound for sigma. By default 2.0 + sseed : int, optional + the seed value. Returns ------- @@ -251,10 +253,13 @@ def GoHMM_random(nb_states:int,nb_distributions:int, """ matrix = [] output = [] + if sseed != None: + random.seed(sseed) + numpy.random.seed(sseed) for s in range(nb_states): p1 = array(randomProbabilities(nb_states)) matrix.append(p1) - p2 = [[round(uniform(min_mu,max_mu),3),round(uniform(min_sigma,max_sigma),3)] for i in range(nb_distributions)] + p2 = [[round(random.uniform(min_mu,max_mu),3),round(random.uniform(min_sigma,max_sigma),3)] for i in range(nb_distributions)] p2 = array(p2) output.append(p2) matrix = array(matrix) @@ -264,6 +269,8 @@ def GoHMM_random(nb_states:int,nb_distributions:int, init = randomProbabilities(nb_states) else: init = 0 + numpy.random.seed() + random.seed() return GoHMM(matrix, output, init,"GoHMM_random_"+str(nb_states)+"_states") diff --git a/jajapy/hmm/HMM.py b/jajapy/hmm/HMM.py index ba56fed..2b40bff 100644 --- a/jajapy/hmm/HMM.py +++ b/jajapy/hmm/HMM.py @@ -2,6 +2,7 @@ from ..base.Base_HMM import Base_HMM,HMM_ID from ast import literal_eval from numpy import array, where, zeros +from numpy.random import seed class HMM(Base_HMM): @@ -180,7 +181,9 @@ def loadHMM(file_path: str) -> HMM: return HMM(matrix, output, alphabet, initial_state, name) -def HMM_random(nb_states: int, alphabet: list, random_initial_state: bool = False) -> HMM: +def HMM_random(nb_states: int, alphabet: list, + random_initial_state: bool = False, + sseed: int = None) -> HMM: """ Generates a random HMM. @@ -193,6 +196,8 @@ def HMM_random(nb_states: int, alphabet: list, random_initial_state: bool = Fals random_initial_state: bool, optional If set to True we will start in each state with a random probability, otherwise we will always start in state 0. Default is False. + sseed : int, optional + the seed value. Returns ------- @@ -205,6 +210,8 @@ def HMM_random(nb_states: int, alphabet: list, random_initial_state: bool = Fals """ matrix = [] output = [] + if sseed != None: + seed(sseed) for s in range(nb_states): p1 = array(randomProbabilities(nb_states)) matrix.append(p1) @@ -217,6 +224,7 @@ def HMM_random(nb_states: int, alphabet: list, random_initial_state: bool = Fals init = randomProbabilities(nb_states) else: init = 0 + seed() return HMM(matrix, output, alphabet, init,"HMM_random_"+str(nb_states)+"_states") diff --git a/jajapy/mc/MC.py b/jajapy/mc/MC.py index adbc1c9..a7834b0 100644 --- a/jajapy/mc/MC.py +++ b/jajapy/mc/MC.py @@ -2,6 +2,7 @@ from ..base.Base_MC import * from ast import literal_eval from numpy import ndarray, array, zeros, vstack, hstack, newaxis, append, where +from numpy.random import seed class MC(Base_MC): def __init__(self, matrix: ndarray, labelling: list, name: str ="unknown_MC") -> None: @@ -225,7 +226,7 @@ def loadMC(file_path: str) -> MC: f.close() return MC(matrix, labelling, name) -def MC_random(nb_states: int, labelling: list, random_initial_state: bool=True) -> MC: +def MC_random(nb_states: int, labelling: list, random_initial_state: bool=True, sseed:int=None) -> MC: """ Generate a random MC. @@ -239,6 +240,8 @@ def MC_random(nb_states: int, labelling: list, random_initial_state: bool=True) If set to True we will start in each state with a random probability, otherwise we will always start in state 0. Default is True. + sseed : int, optional + the seed value. Returns ------- @@ -260,6 +263,8 @@ def MC_random(nb_states: int, labelling: list, random_initial_state: bool=True) ----STATE 2--init---- s2 -> s0 : 1.0 """ + if sseed != None: + seed(sseed) matrix = [] for _ in range(nb_states): matrix.append(append(randomProbabilities(nb_states),0.0)) @@ -269,7 +274,8 @@ def MC_random(nb_states: int, labelling: list, random_initial_state: bool=True) else: matrix.append(array([1.0]+[0.0 for i in range(nb_states)])) matrix = array(matrix) - labelling = labelsForRandomModel(nb_states,labelling) + labelling = labelsForRandomModel(nb_states,labelling,sseed) + seed() return MC(matrix, labelling,"MC_random_"+str(nb_states)+"_states") def createMC(transitions: list, labelling: list, initial_state, name: str ="unknown_MC") -> MC: diff --git a/jajapy/mdp/MDP.py b/jajapy/mdp/MDP.py index ece5150..551def5 100644 --- a/jajapy/mdp/MDP.py +++ b/jajapy/mdp/MDP.py @@ -3,11 +3,10 @@ from ..base.Base_MC import * from ..base.Set import Set from .Scheduler import Scheduler -from numpy.random import geometric -from numpy import array, append, dot, zeros, vsplit, ndarray, where, reshape, vstack, append, concatenate +import numpy.random +from numpy import array, append, dot, zeros, vsplit, reshape, vstack, append, concatenate from ast import literal_eval from multiprocessing import cpu_count, Pool -from random import choices class MDP(Base_MC): """ @@ -253,7 +252,7 @@ def generateSet(self, set_size: int, param, scheduler: Scheduler, distribution=N val = [] for i in range(set_size): if distribution == 'geo': - curr_size = min_size + int(geometric(param)) + curr_size = min_size + int(numpy.random.geometric(param)) else: if type(param) == list: curr_size = param[i] @@ -473,7 +472,9 @@ def loadMDP(file_path: str) -> MDP: return MDP(matrix, labelling, actions, name) -def MDP_random(nb_states: int,labelling: list, actions: list,random_initial_state: bool = True, deterministic: bool = False) -> MDP: +def MDP_random(nb_states: int,labelling: list, actions: list, + random_initial_state: bool = True, deterministic: bool = False, + sseed: int = None) -> MDP: """ Generate a random MDP. @@ -492,12 +493,17 @@ def MDP_random(nb_states: int,labelling: list, actions: list,random_initial_stat If True, the model will be determinstic: in state `s`, with action `a`, for all label `o`, there is at most one transition to a state labelled with `o`. Default is False. + sseed : int, optional + the seed value. Returns ------- MDP A pseudo-randomly generated MDP. """ + if sseed != None: + seed(sseed) + numpy.random.seed(sseed) alphabet = list(set(labelling)) matrix = [] for s in range(nb_states): @@ -523,6 +529,10 @@ def MDP_random(nb_states: int,labelling: list, actions: list,random_initial_stat matrix = array(matrix) labelling = labelsForRandomModel(nb_states,labelling) + + seed() + numpy.random.seed() + return MDP(matrix, labelling, actions, "MDP_random_"+str(nb_states)+"_states") diff --git a/jajapy/pctmc/PCTMC.py b/jajapy/pctmc/PCTMC.py index 0422352..a90d86c 100644 --- a/jajapy/pctmc/PCTMC.py +++ b/jajapy/pctmc/PCTMC.py @@ -1,12 +1,10 @@ from ..base.tools import resolveRandom from ..base.Parametric_Model import * -from ..base.Set import Set -from numpy import ndarray, array, zeros, dot, newaxis, hstack, inf, vstack, delete -from numpy.random import exponential, rand +from numpy import zeros, dot, newaxis, hstack, inf, vstack, delete +from numpy.random import exponential, rand, seed from math import exp, log from multiprocessing import cpu_count, Pool from sys import platform -from sympy import sympify class PCTMC(Parametric_Model): """ @@ -207,7 +205,8 @@ def instantiate(self, parameters: list, values: list) -> bool: return True return False - def randomInstantiation(self, parameters: list = None,min_val:float = None,max_val:float = None) -> None: + def randomInstantiation(self, parameters: list = None,min_val:float = None, + max_val:float = None, sseed: int = None) -> None: """ Randomly instantiated the parameters given in `parameters`. If `parameters` is not set it instantiates all the non-instantiated @@ -229,6 +228,8 @@ def randomInstantiation(self, parameters: list = None,min_val:float = None,max_v this value is equal to the parameters with the highest instantiation. If not set and if the model has less than two instantiated parameters, this value is equal to 5.0. + sseed : int, optional + the seed value. """ if parameters == None: parameters = [] @@ -247,10 +248,15 @@ def randomInstantiation(self, parameters: list = None,min_val:float = None,max_v max_val = max(self.parameter_values.values()) else: max_val = 0.3 + + if sseed != None: + seed(sseed) val = rand(len(parameters))*(max_val-min_val)+min_val while not self.instantiate(parameters,val): val = rand(len(parameters))*(max_val-min_val)+min_val - + + seed() + def _stateToString(self,state:int) -> str: res = "----STATE "+str(state)+"--"+self.labelling[state]+"----\n" if self.isInstantiated(state):