def build_problem(self): """ Build the linear programming problem """ for trans in self.smap: rv = self.smap[trans] if rv.get_transition_type() == "IMMEDIATE": new_rv = Exponential() new_rv.scale = DEFAULT_REPLACEMENT_IMMEDIATE self.smap[trans] = new_rv aeq_1, beq_1, aub_1, bub_1 = self.build_1_throughput() aeq_2, beq_2, aub_2, bub_2 = self.build_2_flowbalance() aeq_3, beq_3, aub_3, bub_3 = self.build_3_secondmoment() aeq_4, beq_4, aub_4, bub_4 = self.build_4_populationcovariance() aeq_5, beq_5, aub_5, bub_5 = self.build_5_liveness() aeq_6, beq_6, aub_6, bub_6 = self.build_6_liveness() aeq_18, beq_18, aub_18, bub_18 = self.build_18_samplepath() aeq_19, beq_19, aub_19, bub_19 = self.build_19_samplepath() aeq_21, beq_21, aub_21, bub_21 = self.build_21_samplepath() aeq_22, beq_22, aub_22, bub_22 = self.build_22_samplepath() aeq_26, beq_26, aub_26, bub_26 = self.build_26_littlelaw() aeq_general, beq_general, aub_general, bub_general = self.build_general_cond() self.Aeq = np.vstack( (aeq_1, aeq_2, aeq_3, aeq_4, aeq_5, aeq_6, aeq_18, aeq_19, aeq_21, aeq_22, aeq_26, aeq_general)) self.beq = np.vstack( (beq_1, beq_2, beq_3, beq_4, beq_5, beq_6, beq_18, beq_19, beq_21, beq_22, beq_26, beq_general)) self.Aub = np.vstack( (aub_1, aub_2, aub_3, aub_4, aub_5, aub_6, aub_18, aub_19, aub_21, aub_22, aub_26, aub_general)) self.bub = np.vstack( (bub_1, bub_2, bub_3, bub_4, bub_5, bub_6, bub_18, bub_19, bub_21, bub_22, bub_26, bub_general)) self.Aeq, self.beq = aeq_redundant_fix.remove_redundant_rows(self.Aeq, self.beq) if DEFAULT_LP_SOLVER_VARIANT == lp_solver.CVXOPT: self.Aeq = np.transpose(self.Aeq.astype(np.float64)).tolist() self.beq = np.transpose(self.beq.astype(np.float64)).tolist() self.Aub = np.transpose(self.Aub.astype(np.float64)).tolist() self.bub = np.transpose(self.bub.astype(np.float64)).tolist()
def read_from_string(self, distribution_type, distribution_parameters): """ Read the random variable from string Parameters ----------- distribution_type Distribution type distribution_parameters Distribution parameters splitted by ; """ if distribution_type == "NORMAL": self.random_variable = Normal() self.random_variable.read_from_string(distribution_parameters) elif distribution_type == "UNIFORM": self.random_variable = Uniform() self.random_variable.read_from_string(distribution_parameters) elif distribution_type == "EXPONENTIAL": self.random_variable = Exponential() self.random_variable.read_from_string(distribution_parameters) elif distribution_type == "IMMEDIATE": self.random_variable = Constant0()
def transform_net(self, net0, initial_marking0, final_marking0, s_map, avg_time_starts): """ Transform the source Petri net removing the initial and final marking, and connecting to each "initial" place a hidden timed transition mimicking the case start Parameters ------------- net0 Initial Petri net provided to the object initial_marking0 Initial marking of the Petri net provided to the object final_marking0 Final marking of the Petri net provided to the object s_map Stochastic map of transitions (EXPONENTIAL distribution since we assume a Markovian process) avg_time_starts Average time interlapsed between case starts Returns ------------- net Petri net that will be simulated initial_marking Initial marking of the Petri net that will be simulated (empty) final_marking Final marking of the Petri net that will be simulated (empty) s_map Stochastic map of transitions enriched by new hidden case-generator transitions """ # copy the Petri net object (assure that we do not change the original Petri net) [net1, initial_marking1, final_marking1] = copy([net0, initial_marking0, final_marking0]) # on the copied Petri net, add a sucking transition for the final marking for index, place in enumerate(final_marking1): suck_transition = PetriNet.Transition( "SUCK_TRANSITION" + str(index), None) net1.transitions.add(suck_transition) add_arc_from_to(place, suck_transition, net1) hidden_generator_distr = Exponential() hidden_generator_distr.scale = avg_time_starts s_map[suck_transition] = hidden_generator_distr # on the copied Petri net, remove both the place(s) in the initial marking and # the immediate transitions that are connected to it. target_places = [] for place in initial_marking1: out_arcs = list(place.out_arcs) for target_arc in out_arcs: target_trans = target_arc.target if len(target_trans.in_arcs) == 1: out_arcs_lev2 = list(target_trans.out_arcs) for arc in out_arcs_lev2: target_place = arc.target target_places.append(target_place) net1 = remove_transition(net1, target_trans) net1 = remove_place(net1, place) # add hidden case-generation transitions to the model. # all places that are left orphan by the previous operation are targeted. for index, place in enumerate(target_places): hidden_generator_trans = PetriNet.Transition( "HIDDEN_GENERATOR_TRANS" + str(index), None) net1.transitions.add(hidden_generator_trans) add_arc_from_to(hidden_generator_trans, place, net1) hidden_generator_distr = Exponential() hidden_generator_distr.scale = avg_time_starts s_map[hidden_generator_trans] = hidden_generator_distr # the simulated Petri net is assumed to start from an empty initial and final marking initial_marking = Marking() final_marking = Marking() return net1, initial_marking, final_marking, s_map
def calculate_parameters(self, values, parameters=None, force_distribution=None): """ Calculate parameters of the current distribution Parameters ----------- values Empirical values to work on parameters Possible parameters of the algorithm force_distribution If provided, distribution to force usage (e.g. EXPONENTIAL) """ if parameters is None: parameters = {} debug_mode = parameters["debug"] if "debug" in parameters else False if self.random_variable is not None: self.random_variable.calculate_parameters(values) else: norm = Normal() unif = Uniform() expon = Exponential() constant = Constant0() if not force_distribution or not force_distribution == "EXPONENTIAL": likelihoods = list() likelihoods.append( [constant, constant.calculate_loglikelihood(values)]) if force_distribution == "NORMAL" or force_distribution is None: norm.calculate_parameters(values) likelihoods.append( [norm, norm.calculate_loglikelihood(values)]) if force_distribution == "UNIFORM" or force_distribution is None: unif.calculate_parameters(values) likelihoods.append( [unif, unif.calculate_loglikelihood(values)]) if force_distribution == "EXPONENTIAL" or force_distribution is None: expon.calculate_parameters(values) likelihoods.append( [expon, expon.calculate_loglikelihood(values)]) likelihoods = [x for x in likelihoods if str(x[1]) != 'nan'] likelihoods = sorted(likelihoods, key=lambda x: x[1], reverse=True) if debug_mode: print("likelihoods = ", likelihoods) self.random_variable = likelihoods[0][0] else: avg_values = np.average(values) if values and avg_values > 0.00000: expon.scale = avg_values self.random_variable = expon else: self.random_variable = constant
class RandomVariable(object): def __init__(self): self.random_variable = None def read_from_string(self, distribution_type, distribution_parameters): """ Read the random variable from string Parameters ----------- distribution_type Distribution type distribution_parameters Distribution parameters splitted by ; """ if distribution_type == "NORMAL": self.random_variable = Normal() self.random_variable.read_from_string(distribution_parameters) elif distribution_type == "UNIFORM": self.random_variable = Uniform() self.random_variable.read_from_string(distribution_parameters) elif distribution_type == "EXPONENTIAL": self.random_variable = Exponential() self.random_variable.read_from_string(distribution_parameters) elif distribution_type == "IMMEDIATE": self.random_variable = Constant0() def get_distribution_type(self): """ Get current distribution type Returns ----------- distribution_type String representing the distribution type """ if self.random_variable is not None: return self.random_variable.get_distribution_type() def get_transition_type(self): """ Get the type of transition associated to the current distribution Returns ----------- transition_type String representing the type of the transition """ if self.random_variable is not None: return self.random_variable.get_transition_type() def get_distribution_parameters(self): """ Get a string representing distribution parameters Returns ----------- distribution_parameters String representing distribution parameters """ if self.random_variable is not None: return self.random_variable.get_distribution_parameters() def calculate_loglikelihood(self, values): """ Calculate log likelihood Parameters ------------ values Empirical values to work on Returns ------------ likelihood Log likelihood that the values follows the distribution """ if self.random_variable is not None: return self.random_variable.calculate_loglikelihood(values) def calculate_parameters(self, values, parameters=None, force_distribution=None): """ Calculate parameters of the current distribution Parameters ----------- values Empirical values to work on parameters Possible parameters of the algorithm force_distribution If provided, distribution to force usage (e.g. EXPONENTIAL) """ if parameters is None: parameters = {} debug_mode = parameters["debug"] if "debug" in parameters else False if self.random_variable is not None: self.random_variable.calculate_parameters(values) else: norm = Normal() unif = Uniform() expon = Exponential() constant = Constant0() if not force_distribution or not force_distribution == "EXPONENTIAL": likelihoods = list() likelihoods.append( [constant, constant.calculate_loglikelihood(values)]) if force_distribution == "NORMAL" or force_distribution is None: norm.calculate_parameters(values) likelihoods.append( [norm, norm.calculate_loglikelihood(values)]) if force_distribution == "UNIFORM" or force_distribution is None: unif.calculate_parameters(values) likelihoods.append( [unif, unif.calculate_loglikelihood(values)]) if force_distribution == "EXPONENTIAL" or force_distribution is None: expon.calculate_parameters(values) likelihoods.append( [expon, expon.calculate_loglikelihood(values)]) likelihoods = [x for x in likelihoods if str(x[1]) != 'nan'] likelihoods = sorted(likelihoods, key=lambda x: x[1], reverse=True) if debug_mode: print("likelihoods = ", likelihoods) self.random_variable = likelihoods[0][0] else: avg_values = np.average(values) if values and avg_values > 0.00000: expon.scale = avg_values self.random_variable = expon else: self.random_variable = constant def get_value(self): """ Get a random value following the distribution Returns ----------- value Value obtained following the distribution """ if self.random_variable is not None: return self.random_variable.get_value() def get_values(self, no_values=400): """ Get some random values following the distribution Parameters ----------- no_values Number of values to return Returns ---------- values Values extracted according to the probability distribution """ if self.random_variable is not None: return self.random_variable.get_values(no_values=no_values) def get_weight(self): """ Getter of weight Returns ---------- weight Weight of the transition """ if self.random_variable is not None: return self.random_variable.get_weight() def set_weight(self, weight): """ Setter of the weight Parameters ----------- weight Weight of the transition """ if self.random_variable is not None: self.random_variable.set_weight(weight) def get_priority(self): """ Getter of the priority Returns ----------- priority Priority of the transition """ if self.random_variable is not None: return self.random_variable.get_priority() def set_priority(self, priority): """ Setter of the priority variable Parameters ------------ priority Priority of the transition """ if self.random_variable is not None: self.random_variable.set_priority(priority) def __str__(self): """ Returns a representation of the current object Returns ---------- repr Representation of the current object """ if self.random_variable is not None: return str(self.random_variable) else: return "UNINITIALIZED" def __repr__(self): """ Returns a representation of the current object Returns ---------- repr Representation of the current object """ if self.random_variable is not None: return repr(self.random_variable) else: return "UNINITIALIZED"