def Burglary(self, sample): if sample['Alarm']: if sample['Earthquake']: return probability(0.00327) else: return probability(0.485) else: if sample['Earthquake']: return probability(7.05e-05) else: return probability(6.01e-05)
def Earthquake(self, sample): if sample['Alarm']: if sample['Burglary']: return probability(0.0020212) else: return probability(0.36755) else: if sample['Burglary']: return probability(0.0016672) else: return probability(0.0014222)
def simulated_annealing1(problem: TSPAnnealingProblem, schedule=schedule_alpha()): current_state: Tuple[List[str], float] = problem.initial for t in range(max_iter): swapped: bool = False T: float = schedule(t) if T < np.exp(-800) or T == 0.0: return current_state[0], problem.calc_hamilton_path_len( current_state) next_state: Tuple[List[str], float] = problem.get_random_next_state(current_state) value_diff = current_state[1] - next_state[1] prob = np.exp(value_diff / T) if value_diff > 0.0 or probability(prob): current_state = next_state swapped = True hamiltonCircle = problem.calc_hamilton_path_len(current_state) print( "iteration: {iter}. Temp. = {T}. diff = {value_diff}. swapped= {swapped}. probability = {prob}. tsp length: {length}. hammCircle: {hamCir}" .format(iter=t, T=T, value_diff=value_diff, swapped=swapped, prob=prob, length=current_state[1], hamCir=hamiltonCircle)) return current_state[0], problem.calc_hamilton_path_len(current_state)
def simulated_annealing_full(graph, start, goal, rand, schedule=exp_schedule()): """ This version returns all the states encountered in reaching the goal state.""" states = [] start_node = Node(start, None) current = Node(start, None) for t in range(sys.maxsize): states.append(current.name) T = schedule(t) if T == 0: path = [] while current != start_node: path.append(current.name + ': ' + str(current.f)) current = current.parent path.append(start_node.name + ': ' + str(start_node.f)) # Return reversed path return path[::-1] #return states neighbors = graph.get(current.name) if not neighbors: return current.name next_choice = Node(choose(list(neighbors), rand), current) # Calculates path cost with realistic components current.f = components.componentAdjustments( rand, heuristicFunction(str(current.name), goal)) next_choice.f = components.componentAdjustments( rand, heuristicFunction(str(next_choice.name), goal)) # calcualtes delta e with the path costs delta_e = current.f - next_choice.f if delta_e > 0 or probability(np.exp(delta_e / T)): current = next_choice
def S_generator(n, m, k, q): """ :param n: the number of distinct propositional symbols in S :param m: the number of clauses in S :param k: the maximum number of literals in a clause in S :param q: 0.4 <= q <= 0.6, q is the probability that a literal in a clause in a negative literal :return: a random set of clauses """ if q < 0.4 or q > 0.6: raise ValueError("q should be between 0.4 and 0.6(inclusive)") letters = string.ascii_uppercase len_letters = len(letters) if n > len_letters: raise ValueError("n should be less than or equal to " + str(len_letters)) unique_symbols = list() for i in range(n): unique_symbols.append(Expr(letters[i])) S = list() for i in range(m): n_lt = random.randint(1, k) clause = None for j in range(n_lt): idx = random.randint(0, n - 1) sym = unique_symbols[idx] if probability(q): sym = sym.__invert__() if clause is None: clause = sym else: clause = clause.__or__(sym) S.append(clause) print("clauses S: " + str(S) + "\n") return S
def p_randomly(params, step, sL, s, **kwargs): commons = s["commons"] sentiment = s["sentiment"] ans = { "new_participant": False, "new_participant_investment": None, "new_participant_tokens": None } arrival_rate = (1 + sentiment) / 10 if probability(arrival_rate): ans["new_participant"] = True # Here we randomly generate each participant's post-Hatch # investment, in DAI/USD. # # expon.rvs() arguments: # # loc is the minimum number, so if loc=100, there will be no # investments < 100 # # scale is the standard deviation, so if scale=2, investments will # be around 0-12 DAI or even 15, if scale=100, the investments will be # around 0-600 DAI. ans["new_participant_investment"] = expon.rvs(loc=0.0, scale=100) ans["new_participant_tokens"] = commons.dai_to_tokens( ans["new_participant_investment"]) return ans
def WalkSAT(clauses, p=0.5, max_flips=10000): """Checks for satisfiability of all clauses by randomly flipping values of variables """ # Set of all symbols in all clauses symbols = set(sym for clause in clauses for sym in prop_symbols(clause)) # model is a random assignment of true/false to the symbols in clauses model = {s: random.choice([True, False]) for s in symbols} for i in range(max_flips): satisfied, unsatisfied = [], [] for clause in clauses: (satisfied if pl_true(clause, model) else unsatisfied).append(clause) if not unsatisfied: # if model satisfies all the clauses return model clause = random.choice(unsatisfied) if probability(p): sym = random.choice(prop_symbols(clause)) else: # Flip the symbol in clause that maximizes number of sat. clauses def sat_count(sym): # Return the the number of clauses satisfied after flipping the symbol. model[sym] = not model[sym] count = len([clause for clause in clauses if pl_true(clause, model)]) model[sym] = not model[sym] return count sym = argmax(prop_symbols(clause), key=sat_count) model[sym] = not model[sym] # If no solution is found within the flip limit, we return failure return None
def simulated_annealing_plot(problem, values_for_schedule): """[Figure 4.5] CAUTION: This differs from the pseudocode as it returns a state instead of a Node.""" schedule = exp_schedule(values_for_schedule[0], values_for_schedule[1], values_for_schedule[2]) x = list() y = list() current = Node(problem.initial) for t in range(sys.maxsize): T = schedule(t) if T == 0: plt.scatter(x, y) plt.show() return current.state neighbors = current.expand(problem) if not neighbors: plt.scatter(x, y) plt.show() return current.state next_choice = random.choice(neighbors) delta_e = problem.value(next_choice.state) - problem.value( current.state) y.append(problem.value(current.state)) x.append(t) if delta_e > 0 or probability(np.exp(delta_e / T)): current = next_choice
def WalkSAT(clauses, p=0.5, max_flips=10000): """Checks for satisfiability of all clauses by randomly flipping values of variables """ # Set of all symbols in all clauses symbols = {sym for clause in clauses for sym in prop_symbols(clause)} # model is a random assignment of true/false to the symbols in clauses model = {s: random.choice([True, False]) for s in symbols} for i in range(max_flips): satisfied, unsatisfied = [], [] for clause in clauses: (satisfied if pl_true(clause, model) else unsatisfied).append(clause) if not unsatisfied: # if model satisfies all the clauses return model clause = random.choice(unsatisfied) if probability(p): sym = random.choice(list(prop_symbols(clause))) else: # Flip the symbol in clause that maximizes number of sat. clauses def sat_count(sym): # Return the the number of clauses satisfied after flipping the symbol. model[sym] = not model[sym] count = len( [clause for clause in clauses if pl_true(clause, model)]) model[sym] = not model[sym] return count sym = argmax(prop_symbols(clause), key=sat_count) model[sym] = not model[sym] # If no solution is found within the flip limit, we return failure return None
def particle_filtering(e, N, HMM): """Particle filtering considering two states variables.""" dist = [0.5, 0.5] # Weight Initialization w = [0 for _ in range(N)] # STEP 1 # Propagate one step using transition model given prior state dist = vector_add(scalar_vector_product(dist[0], HMM.transition_model[0]), scalar_vector_product(dist[1], HMM.transition_model[1])) # Assign state according to probability s = ['A' if probability(dist[0]) else 'B' for _ in range(N)] w_tot = 0 # Calculate importance weight given evidence e for i in range(N): if s[i] == 'A': # P(U|A)*P(A) w_i = HMM.sensor_dist(e)[0] * dist[0] if s[i] == 'B': # P(U|B)*P(B) w_i = HMM.sensor_dist(e)[1] * dist[1] w[i] = w_i w_tot += w_i # Normalize all the weights for i in range(N): w[i] = w[i] / w_tot # Limit weights to 4 digits for i in range(N): w[i] = float("{0:.4f}".format(w[i])) # STEP 2 s = weighted_sample_with_replacement(N, s, w) return s
def simulated_annealing(problem, schedule=exp_schedule()): """[Figure 4.5] CAUTION: This differs from the pseudocode as it returns a state instead of a Node.""" current = Node(problem.initial) prev = None for t in range(sys.maxsize): T = schedule(t) if T == 0: log(simulated_annealing, "T == 0") return current.state if current is not prev: neighbors = current.expand(problem) if not neighbors: log(simulated_annealing, "no neighbors") return current.state next_choice = random.choice(neighbors) delta_e = problem.value(next_choice.state) - problem.value(current.state) log(simulated_annealing, "current state", current.state.state) log(simulated_annealing, "next_choice", next_choice.state.state) log(simulated_annealing, "delta_e", delta_e) log(simulated_annealing, "T", T) log(simulated_annealing, "t", t) prob = 1 if delta_e > T else math.exp(delta_e / T) log(simulated_annealing, "probability", prob) prev = current if delta_e > 0 or probability(prob): current = next_choice print('.', end='') # to show progress when running
def WalkSAT(clauses, p=0.5, max_flips=10000): symbols = set(sym for clause in clauses for sym in prop_symbols(clause)) model = {s: random.choice([True, False]) for s in symbols} for i in range(max_flips): satisfied, unsatisfied = [], [] for clause in clauses: (satisfied if pl_true(clause, model) else unsatisfied).append(clause) if not unsatisfied: return model clause = random.choice(unsatisfied) if probability(p): sym = random.choice(prop_symbols(clause)) else: def sat_count(sym): model[sym] = not model[sym] count = len( [clause for clause in clauses if pl_true(clause, model)]) model[sym] = not model[sym] return count sym = argmax(prop_symbols(clause), key=sat_count) model[sym] = not model[sym] return None
def simulated_annealing(self): T = 3.0 alpha = 0.99 epoch = 4000 cost_overtime = [] steps = [] combinations = list(self.squares_combinations()) for i in range(epoch): if T == 0: return self.state, cost_overtime, steps possible_states = [] for c in combinations: state = self.swap(c[0], c[1]) possible_states.append(state) next_state = random.choice(possible_states) delta_e = self.cost_function(next_state) - self.cost_function( self.state) # next state is accepted if is better than current state with respect # of cost function or probability if delta_e < 0 or probability(math.exp(-delta_e / T)): self.state = next_state cost_overtime.append(self.cost_function(self.state)) steps.append(i) T = alpha * T return self.state, cost_overtime, steps
def sample(self, event): """ Sample from the distribution for this variable conditioned on event's values for parent_variables. That is, return True/False at random according with the conditional probability given the parents. """ return probability(self.p(True, event))
def wants_to_exit(self): """ Returns True if the Participant wants to exit (if sentiment < 0.5, random chance of exiting), otherwise False """ if self.sentiment < 0.5: engagement_rate = 0.3 * self.sentiment return probability(1 - engagement_rate) return False
def p_influenced_by_grant_size(params, step, sL, s): base_failure_rate = 0.15 base_success_rate = 0.30 network = s["network"] active_proposals = get_proposals(network, status=ProposalStatus.ACTIVE) proposals_that_will_fail = [] proposals_that_will_succeed = [] for idx, proposal in active_proposals: r_failure = 1/(base_failure_rate + np.log(proposal.funds_requested)) r_success = 1/(base_success_rate + np.log(proposal.funds_requested)) if probability(r_failure): proposals_that_will_fail.append(idx) elif probability(r_success): proposals_that_will_succeed.append(idx) return {"failed": proposals_that_will_fail, "succeeded": proposals_that_will_succeed}
def markov_blanket_sample(X, e, bn): """Retornar uma amostra de P (X | mb) onde mb denota que a Variáveis no cobertor de Markov de X tomam seus valores do evento E (que deve atribuir um valor a cada). A manta de Markov de X é X pais, filhos e pais das crianças.""" Xnode = bn.variable_node(X) Q = ProbDist(X) for xi in bn.variable_values(X): ei = extend(e, X, xi) Q[xi] = Xnode.p(xi, e) * product( Yj.p(ei[Yj.variable], ei) for Yj in Xnode.children) return probability(Q.normalize()[True])
def actions(self, state): ''' Generate randomly flip one bit; do this twice to generate 2 neighbors Actions are just the genes ''' choices=[] for i in range(2): candidate = list(state.genes) c = random.randrange(len(candidate)) if probability(0.5): candidate[c] = 1 - candidate[c] choices.append(candidate) return choices
def markov_blanket_sample(X, e, bn): """Return a sample from P(X | mb) where mb denotes that the variables in the Markov blanket of X take their values from event e (which must assign a value to each). The Markov blanket of X is X's parents, children, and children's parents.""" Xnode = bn.variable_node(X) Q = ProbDist(X) for xi in bn.variable_values(X): ei = extend(e, X, xi) # [Equation 14.12] Q[xi] = Xnode.p(xi, e) * product(Yj.p(ei[Yj.variable], ei) for Yj in Xnode.children) # (assuming a Boolean variable here) return probability(Q.normalize()[True])
def simulated_annealing(problem, schedule=exp_schedule()): current = Node(problem.initial) for t in range(sys.maxsize): T = schedule(t) if T == 0: return current.state neighbors = current.expand(problem) if not neighbors: return current.state next = random.choice(neighbors) delta_e = problem.value(current.state) - problem.value(next.state) if delta_e > 0 or probability(math.exp(delta_e / T)): current = next
def simulated_annealing(problem, schedule=exp_schedule()): "[Fig. 4.5]" current = Node(problem.initial) for t in xrange(sys.maxint): T = schedule(t) if T == 0: return current neighbors = current.expand(problem) if not neighbors: return current next = random.choice(neighbors) delta_e = problem.value(next.state) - problem.value(current.state) if delta_e > 0 or probability(math.exp(delta_e/T)): current = next
def weighted_sample_with_replacement(N, s, w): """ Performs Weighted sampling over the paricles given weights of each particle. We keep on picking random states unitll we fill N number states in new distribution """ s_wtd = [] cnt = 0 while (cnt <= N): # Generate a random number from 0 to N-1 i = random.randint(0, N - 1) if (probability(w[i])): s_wtd.append(s[i]) cnt += 1 return s_wtd
def weighted_sample_with_replacement(N, s, w): """ Performs Weighted sampling over the paricles given weights of each particle. We keep on picking random states unitll we fill N number states in new distribution """ s_wtd = [] cnt = 0 while (cnt <= N): # Generate a random number from 0 to N-1 i = random.randint(0, N-1) if (probability(w[i])): s_wtd.append(s[i]) cnt += 1 return s_wtd
def markov_blanket_sample(X, e, bn): """Return a sample from P(X | mb) where mb denotes that the variables in the Markov blanket of X take their values from event e (which must assign a value to each). The Markov blanket of X is X's parents, children, and children's parents.""" Xnode = bn.variable_node(X) Q = ProbDist(X) for xi in bn.variable_values(X): ei = extend(e, X, xi) # [Equation 14.12:] Q[xi] = Xnode.p(xi, e) * product(Yj.p(ei[Yj.variable], ei) for Yj in Xnode.children) # (assuming a Boolean variable here) return probability(Q.normalize()[True])
def particle_filtering(e, N, HMM): """Particle filtering considering two states variables.""" s = [] dist = [0.5, 0.5] # State Initialization s = ['A' if probability(dist[0]) else 'B' for i in range(N)] # Weight Initialization w = [0 for i in range(N)] # STEP 1 # Propagate one step using transition model given prior state dist = vector_add(scalar_vector_product(dist[0], HMM.transition_model[0]), scalar_vector_product(dist[1], HMM.transition_model[1])) # Assign state according to probability s = ['A' if probability(dist[0]) else 'B' for i in range(N)] w_tot = 0 # Calculate importance weight given evidence e for i in range(N): if s[i] == 'A': # P(U|A)*P(A) w_i = HMM.sensor_dist(e)[0]*dist[0] if s[i] == 'B': # P(U|B)*P(B) w_i = HMM.sensor_dist(e)[1]*dist[1] w[i] = w_i w_tot += w_i # Normalize all the weights for i in range(N): w[i] = w[i]/w_tot # Limit weights to 4 digits for i in range(N): w[i] = float("{0:.4f}".format(w[i])) # STEP 2 s = weighted_sample_with_replacement(N, s, w) return s
def simulated_annealing(problem, schedule=exp_schedule()): current = Node(problem.initial) # The largest positive integer supported by the platform’s Py_ssize_t type for t in range(sys.maxsize): T = schedule(t) if T == 0: return current.state neighbors = current.expand(problem) if not neighbors: return current.state next = random.choice(neighbors) delta_e = problem.value(next.state) - problem.value(current.state) # return p > random.uniform(0.0, 1.0) if delta_e > 0 or probability(math.exp(delta_e / T)): current = next
def simulated_annealing(problem, schedule=exp_schedule()): """[Figure 4.5] CAUTION: This differs from the pseudocode as it returns a state instead of a Node.""" current = Node(problem.initial) for t in range(sys.maxsize): T = schedule(t) if T == 0: return current.state neighbors = current.expand(problem) if not neighbors: return current.state next = random.choice(neighbors) delta_e = problem.value(next.state) - problem.value(current.state) if delta_e > 0 or probability(math.exp(delta_e / T)): current = next
def particle_filtering(e, N, HMM): """Filtragem de partículas considerando duas variáveis de estados.""" s = [] dist = [0.5, 0.5] # Inicialização do estado s = ['A' if probability(dist[0]) else 'B' for i in range(N)] # Inicialização de peso w = [0 for i in range(N)] # PASSO 1 - Propagar um passo usando o modelo de transição dado estado anterior dist = vector_add(scalar_vector_product(dist[0], HMM.transition_model[0]), scalar_vector_product(dist[1], HMM.transition_model[1])) # Atribuir o estado de acordo com a probabilidade s = ['A' if probability(dist[0]) else 'B' for i in range(N)] w_tot = 0 # Calcular peso de importância dado evidência e for i in range(N): if s[i] == 'A': # P(U|A)*P(A) w_i = HMM.sensor_dist(e)[0] * dist[0] if s[i] == 'B': # P(U|B)*P(B) w_i = HMM.sensor_dist(e)[1] * dist[1] w[i] = w_i w_tot += w_i # Normalizar todos os pesos for i in range(N): w[i] = w[i] / w_tot # Limite pesos a 4 dígitos for i in range(N): w[i] = float("{0:.4f}".format(w[i])) # STEP 2 s = weighted_sample_with_replacement(s, w, N) return s
def buy(self) -> float: """ If the Participant decides to buy more tokens, returns the number of tokens. Otherwise, return 0. This method does not modify itself, it simply returns the answer so that cadCAD's state update functions will make the changes and maintain its functional-ness. """ engagement_rate = 0.3 * self.sentiment force = self.sentiment - config.sentiment_sensitivity if probability(engagement_rate) and force > 0: delta_holdings = np.random.rand() * force return delta_holdings return 0
def vote_on_candidate_proposals(self, candidate_proposals: dict) -> dict: """ Here the Participant decides which Candidate Proposals he will stake tokens on. This method does not decide how many tokens he will stake on them, because another function should decide how the tokens should be balanced across the newly supported proposals and the ones the Participant already supported. Copied from participants_buy_more_if_they_feel_good_and_vote_for_proposals() candidate dict format: { "proposalUUID": affinity, ... } NOTE: the original cadCAD policy returned {'delta_holdings': delta_holdings, 'proposals_supported': proposals_supported} proposals_supported seems to include proposals ALREADY supported by the participant, but I don't think it is needed. """ new_voted_proposals = {} engagement_rate = .3 * self.sentiment if probability(engagement_rate): # Put your tokens on your favourite Proposals, where favourite is # calculated as 0.75 * (the affinity for the Proposal you like the # most) e.g. if there are 2 Proposals that you have affinity 0.8, # 0.9, then 0.75*0.9 = 0.675, so you will end up voting for both of # these Proposals # # A Zargham work of art. for candidate in candidate_proposals: affinity = candidate_proposals[candidate] # Hardcoded 0.75 instead of a configurable sentiment_sensitivity # because modifying sentiment_sensitivity without changing the # hardcoded cutoff value of 0.5 may cause unintended behaviour. # Also, 0.75 is a reasonable number in this case. cutoff = 0.75 * np.max(list(candidate_proposals.values())) if cutoff < .5: cutoff = .5 if affinity > cutoff: new_voted_proposals[candidate] = affinity return new_voted_proposals
def simulated_annealing_full(problem, schedule=exp_schedule()): """ This version returns all the states encountered in reaching the goal state.""" states = [] current = Node(problem.initial) for t in range(sys.maxsize): states.append(current.state) T = schedule(t) if T == 0: return states neighbors = current.expand(problem) if not neighbors: return current.state next_choice = random.choice(neighbors) delta_e = problem.value(next_choice.state) - problem.value(current.state) if delta_e > 0 or probability(math.exp(delta_e / T)): current = next_choice
def actions(self, state): ''' Implement this method. Returns the neighbors of a given state. You must implement this so that the neighbors are from the "neighborhood" and are not an enormous set. ''' neighbor_changes = int(self.N/3) if 2 < int(self.N/3) else 2 neighbors=[] for i in range(neighbor_changes): candidate = list(state.genes) col = random.randrange(len(candidate)) if probability(0.7): candidate[col] = random.randrange(self.N) neighbors.append(candidate) return neighbors override
def WalkSAT(clauses, p=0.5, max_flips=10000): """Checks for satisfiability of all clauses by randomly flipping values of variables >>> WalkSAT([A & ~A], 0.5, 100) is None True """ # Set of all symbols in all clauses symbols = {} for clause in clauses: for literal in clause: symbols[abs(literal)] = literal # symbols = {sym for clause in clauses for sym in prop_symbols(clause)} # model is a random assignment of true/false to the symbols in clauses model = {s: random.choice([True, False]) for s in symbols} for i in range(max_flips): satisfied, unsatisfied = [], [] for clause in clauses: # if len(clause) == 0: # return None # print(clause, model) (satisfied if is_sat(clause, model) else unsatisfied).append(clause) # if not unsatisfied: # if model satisfies all the clauses # return model if len(unsatisfied) == 0: return model clause = random.choice(unsatisfied) if probability(p): sym = random.choice(list(model.keys())) # else: # # Flip the symbol in clause that maximizes number of sat. clauses # def sat_count(sym): # # Return the the number of clauses satisfied after flipping the symbol. # model[sym] = not model[sym] # count = len([clause for clause in clauses if pl_true(clause, model)]) # model[sym] = not model[sym] # return count # # sym = max(prop_symbols(clause), key=sat_count) # model[sym] = not model[sym] model[sym] = not model[sym] # If no solution is found within the flip limit, we return failure return None
def simulated_annealing(initial, successor, value, schedule=search.exp_schedule()): current = initial val_cur = value(current) try: for t in xrange(sys.maxint): T = schedule(t) print '%5d %0.4f %0.6f' % (t, T, val_cur) if T == 0: return current next = successor(current) val_next = value(next) delta_e = val_next - val_cur if delta_e < 0 or utils.probability(math.exp(-delta_e/T)): current = next val_cur = val_next except BaseException, e: traceback.print_exc() return current
def create_proposal(self, total_funds_requested, median_affinity, funding_pool) -> bool: """ Here the Participant will decide whether or not to create a new Proposal. This equation, originally from randomly_gen_new_proposal(), is a systems-type simulation. An individual Participant would likely think in a different way, and thus this equation should change. Nevertheless for simplicity's sake, we use this same equation for now. Explanation: If the median affinity is high, the Proposal Rate should be high. If total funds_requested in candidate proposals is much lower than the funding pool (i.e. the Commons has lots of spare money), then people are just going to pour in more Proposals. """ percent_of_funding_pool_being_requested = total_funds_requested/funding_pool proposal_rate = median_affinity / \ (1 + percent_of_funding_pool_being_requested) new_proposal = probability(proposal_rate) return new_proposal
def sample(self, event): """Sample from the distribution for this variable conditioned on event's values for parent_variables. That is, return True/False at random according with the conditional probability given the parents.""" return probability(self.p(True, event))
def feature_bagging(dataset, p=0.7): """Feature bagging with probability p to retain an attribute""" inputs = [i for i in dataset.inputs if probability(p)] return inputs or dataset.inputs
def run_simulation(p, a, c_l, c_h, b, d, w, pop, selection_strength, mutate_prob, generations, file_prefix=None, milestone=1000, silent=False, player1_seed='dwol', player2_seed='alle'): # if no file_prefix was provided, create a new folder at ./trials/ to store created files in if file_prefix is None: i = 0 while True: dir = os.path.dirname('./trials/trial{}/info.txt'.format(i)) if not os.path.exists(dir): file_prefix = './trials/trial{}/'.format(i) break i += 1 dir = os.path.dirname('{}/info.txt'.format(file_prefix)) if not os.path.exists(dir): os.makedirs(dir) # output a file with the setup parameters with open('{}setup_vars.json'.format(file_prefix), 'w+') as outfile: setup_vars = {'p': p, 'a': a, 'c_l': c_l, 'c_h': c_h, 'b': b, 'd': d, 'w': w, 'pop': pop, 'mutate_prob': mutate_prob, 'generations': generations, 'selection_strength': selection_strength, 'file_prefix': file_prefix, 'milestone': milestone, 'player1_seed': player1_seed, 'player2_seed': player2_seed} outfile.write(json.dumps(setup_vars)) player1_pop = [] player2_pop = [] coop_stats = [] mutations = ['alter_strategy', 'alter_action', 'add_state', 'delete_state'] time_started = prev_gen_time = calendar.timegm(datetime.datetime.now().utctimetuple()) finished_normally = True # create the initial population for _ in range(pop/2): player1 = fsm.Player1(player1_seed) player2 = fsm.Player2(player2_seed) player1_pop.append(player1) player2_pop.append(player2) # puts everything in a try block, so that if the user exits (with ctrl + c), # files may still be outputted at the end try: # outer loop for each generation for gen in range(generations): # statistics collected during the round continue_num = 0 cooperate_num = 0 cooperate_at_all_num = 0 continue_at_all_num = 0 moves = 0 ##### # # PLAY THE GAME # ##### # create tuples matching each Player 1 with each Player 2 only once pairs = itertools.product(player1_pop, player2_pop) # loop through the pairs and play the strategies against each other for player1, player2 in pairs: # make sure that the current state is set to the first state player1.reset() player2.reset() repeat = True continue_at_all = False cooperate_at_all = False while repeat: moves += 1 # choose temptation if utils.probability(p): temptation = 'low' else: temptation = 'high' # determine the player1's action first player1_action = player1.action(temptation) # calculate payoffs based on player1's action cooperate_defect = player1_action['move'] if cooperate_defect == 'defect' and temptation == 'high': player1.add_payoff(c_h) player2.add_payoff(d) elif cooperate_defect == 'defect' and temptation == 'low': player1.add_payoff(c_l) player2.add_payoff(d) elif cooperate_defect == 'cooperate': cooperate_num += 1 if not cooperate_at_all: cooperate_at_all = True cooperate_at_all_num += 1 player1.add_payoff(a) player2.add_payoff(b) # advance both players player1.advance_state() player2.advance_state(player1_action) # decide player2's action (in response to player1's) player2_action = player2.action(temptation) omega_repeat = utils.probability(w) cont = player2_action['action'] == 'continue' if cont: continue_num += 1 if not continue_at_all: continue_at_all = True continue_at_all_num += 1 # repeat if player2 played "continue," and the random dice roll chose to continue repeat = omega_repeat and cont coop_stats.append((continue_num, cooperate_num, continue_at_all_num, cooperate_at_all_num, moves)) ##### # # DETERMINE NEXT GENERATION # ##### # reproduction process: # segments the number line from 0 - 1 based on the players' relative fitness # then, creates new players by choosing random numbers between 0 and 1 # player1s dist = utils.create_distribution(player1_pop, selection_strength, games=pop/2) new_player1_pop = [] for _ in range(pop/2): rand = random.random() parent = utils.determine_player(dist, rand) new_player1_pop.append(utils.player_deep_copy(parent)) player1_pop = new_player1_pop # player2s dist = utils.create_distribution(player2_pop, selection_strength, games=pop/2) new_player2_pop = [] for _ in range(pop/2): rand = random.random() parent = utils.determine_player(dist, rand) new_player2_pop.append(utils.player_deep_copy(parent)) player2_pop = new_player2_pop ##### # # MUTATE # ##### # don't mutate on the last generation if gen < generations - 1: for player1 in player1_pop: if utils.probability(mutate_prob): mutation = random.choice(mutations) if mutation == 'alter_strategy': player1.alter_strategy() elif mutation == 'alter_action': player1.alter_action() elif mutation == 'delete_state': player1.delete_state() elif mutation == 'add_state': player1.add_state() for player2 in player2_pop: if utils.probability(mutate_prob): mutation = random.choice(mutations) if mutation == 'alter_strategy': player2.alter_strategy() elif mutation == 'alter_action': player2.alter_action() elif mutation == 'delete_state': player2.delete_state() elif mutation == 'add_state': player2.add_state() # if the generation is a milestone, save the populations and record some stats if gen % milestone == 0: now = calendar.timegm(datetime.datetime.now().utctimetuple()) gen_runtime = round(float(now - prev_gen_time)/60, 3) # save player 1 population with open('{}player1_pop_{}.json'.format(file_prefix, gen), 'w+') as outfile: # convert players to dictionaries player1_pop_json = [player1.to_dict() for player1 in player1_pop] outfile.write(json.dumps(player1_pop_json)) # save player 2 population with open('{}player2_pop_{}.json'.format(file_prefix, gen), 'w+') as outfile: # convert players to dictionaries player2_pop_json = [player2.to_dict() for player2 in player2_pop] outfile.write(json.dumps(player2_pop_json)) # save stats with open('{}cooperate_continue_stats_{}.json'.format(file_prefix, gen), 'w+') as outfile: rounds = [] labels = ['continue', 'cooperate', 'continue_at_all', 'cooperate_at_all', 'moves'] for rnd in coop_stats: rnd = {labels[i]:val for i, val in enumerate(rnd)} rounds.append(rnd) outfile.write(json.dumps(rounds)) with open('{}cooperate_continue_totals_{}.json'.format(file_prefix, gen), 'w+') as outfile: for rnd in coop_stats: rnd = {labels[i]:val for i, val in enumerate(rnd)} rounds.append(rnd) total_cooperated_at_all = sum([i['cooperate_at_all'] for i in rounds]) total_continued_at_all = sum([i['continue_at_all'] for i in rounds]) total_cooperated = sum([i['cooperate'] for i in rounds]) total_continued = sum([i['continue'] for i in rounds]) total_moves = sum([i['moves'] for i in rounds]) totals = { 'total_cooperated_at_all': total_cooperated_at_all, 'total_continued_at_all': total_continued_at_all, 'total_cooperated': total_cooperated, 'total_continued': total_continued, 'total_moves': total_moves, } outfile.write(json.dumps(totals)) coop_stats = [] if not silent: print 'Generation {} ({} mins.)'.format(gen, gen_runtime) prev_gen_time = calendar.timegm(datetime.datetime.now().utctimetuple()) except KeyboardInterrupt: finished_normally = False time_finished = calendar.timegm(datetime.datetime.now().utctimetuple()) setup_vars_str = '' for var in setup_vars: setup_vars_str += '\t{}: {}\n'.format(var, setup_vars[var]) runtime = round(float(time_finished - time_started)/60, 3) with open('{}cooperate_continue_stats.json'.format(file_prefix), 'w+') as outfile: rounds = [] labels = ['continue', 'cooperate', 'continue_at_all', 'cooperate_at_all', 'moves'] for rnd in coop_stats: rnd = {labels[i]:val for i, val in enumerate(rnd)} rounds.append(rnd) outfile.write(json.dumps(rounds)) total_cooperated_at_all = sum([i['cooperate_at_all'] for i in rounds]) total_continued_at_all = sum([i['continue_at_all'] for i in rounds]) total_cooperated = sum([i['cooperate'] for i in rounds]) total_continued = sum([i['continue'] for i in rounds]) total_moves = sum([i['moves'] for i in rounds]) total_games = (gen + 1) * (pop/2) with open('{}cooperate_continue_totals.json'.format(file_prefix), 'w+') as outfile: totals = { 'total_cooperated_at_all': total_cooperated_at_all, 'total_continued_at_all': total_continued_at_all, 'total_cooperated': total_cooperated, 'total_continued': total_continued, 'total_moves': total_moves } outfile.write(json.dumps(totals)) with open('{}info.txt'.format(file_prefix), 'w+') as outfile: string = """Finished Normally: {} Time Started: {} Time Finished: {} Runtime (minutes): {} Generations: {} Total Coop at All (since last milestone): {} Total Cont at All (since last milestone): {} Total Coop Moves (since last milestone): {} Total Cont Moves (since last milestone): {} Total moves (since last milestone): {} Setup Variables: {}""".format(finished_normally, time_started, time_finished, runtime, gen + 1, total_cooperated_at_all, total_continued_at_all, total_cooperated, total_continued, total_moves, setup_vars_str) outfile.write(string) with open('{}player1_pop.json'.format(file_prefix), 'w+') as outfile: player1_pop_json = [player1.to_dict() for player1 in player1_pop] outfile.write(json.dumps(player1_pop_json)) with open('{}player2_pop.json'.format(file_prefix), 'w+') as outfile: player2_pop_json = [player2.to_dict() for player2 in player2_pop] outfile.write(json.dumps(player2_pop_json)) return player1_pop, player2_pop
def JongCalls(self, sample): if sample['Alarm']: return probability(0.9) else: return probability(0.05)