def test_constant_simple_agent_basic(constant_agent_config): """ This test checks that a constant agent predicts and votes the configured [AB] and [vote] for different states in 100 timesteps. [AB] is a specified ActionBet [vote] is a specified float """ # for a list of random constant agent configurations: for AB, vote in constant_agent_config: print(f"constant: {AB.bet} and {AB.prediction}, {vote}") agent = fac.AgentFactory.create( fac.AgentFactorySpec(fac.AgentsEnum.constant, vote, bet=AB.bet, prediction=AB.prediction)) env = fac.EnvFactory.create( fac.EnvsFactorySpec(fac.EnvsEnum.default, n_actions=2)) for _ in range(100): state = env.state() assert (agent.vote(state) == vote) for j in env.actions(): action_bet = agent.bet(state, j, 1) assert (len(action_bet.bet) == len(AB.bet)) assert (len(action_bet.prediction) == len(AB.prediction)) for k in range(len(action_bet.bet)): assert (floatIsEqual(action_bet.bet[k], AB.bet[k])) for k in range(len(action_bet.prediction)): assert (floatIsEqual(action_bet.prediction[k], AB.prediction[k])) env.step(random.choice(env.actions()))
def test_vote_config(aggFun, VR, vals, gen_vote_conf, spec_enum): """ Checks that votes are aggregated correctly in voting config that are validated using [aggFun] with the specific [VR] specified [aggFun] function that aggregates votes that is defined in this file. [VR] voting range specified [vals] votes to be aggregated [spec_enum] voting configuration specifier The other parameter is a test fixture to help create objects easier. """ vc: project_types.VotingConfiguration = gen_vote_conf(spec_enum, VR) assert (vc.n_agents == 0) vc.set_n_agents(len(vals)) assert (vc.n_agents == len(vals)) if np.isfinite(vc.max_possible_vote_total()): assert floatIsEqual(vc.max_possible_vote_total(), aggFun([VR.maxVote()] * len(vals), VR)) else: assert not np.isfinite(VR.maxVote()) if np.isfinite(vc.min_possible_vote_total()): assert floatIsEqual(vc.min_possible_vote_total(), aggFun([VR.minVote()] * len(vals), VR)) else: assert not np.isfinite(VR.minVote()) assert vc.min_possible_vote_total() <= vc.max_possible_vote_total() assert (floatIsEqual(vc.aggregate_votes(vals), aggFun(vals, VR)))
def test_suggested_policy_config_single_action( bets,predictions, moneys,expectedVals,expectedProbs, gen_policy_conf,gen_weighted_bet): """ This test checks that aggregate bets in policy config satsifies our definition of suggested aggregation for at most a 3 agent system [bets] is the bet percentage of each agent in a certain timestep [predictions] is the corresponding prediction for each bet [moneys] is a list of the agents money at that time-step, [expectedVals] are the probablity keys of the object returned by aggregate bets [expectedProbs] are the probabilties of each key of the object returned by aggregate bets The other two parameters are test fixtures to help create objects easier. """ policyConf = gen_policy_conf(fac.PolicyConfigEnum.suggested) weightedBets : List[P.WeightedBet] = [] for i in range(len(bets)): print(bets[i],predictions[i],moneys[i]) weightedBets.append( gen_weighted_bet(bets[i],predictions[i],money=moneys[i]) ) dic = {'a':weightedBets} res = policyConf.aggregate_bets(dic)['a'] assert(len(res.values) == len(expectedVals)) assert(len(res.probabilities) == len(expectedProbs)) for k in range(len(res.probabilities)): assert(floatIsEqual(res.values[k], expectedVals[k])) assert(floatIsEqual(res.probabilities[k], expectedProbs[k]))
def test_suggested_policy_config_action_probs(arr,vals,expected,gen_policy_conf): """ This test checks that action probs in policy config satsifies our definition of suggested action probabilities which is identical to select action but gives out probabilities. [arr] is the list of actions available [vals] is the list of values for each action in [arr] The other parameter is a test fixture to help create objects easier. """ policyConf = gen_policy_conf(fac.PolicyConfigEnum.suggested) aggregate_bets : Dict[float,List[DiscreteDistribution]] = {} for k in range(len(arr)): aggregate_bets[arr[k]]= constantDistribution(vals[k]) if expected is not None: res = policyConf.action_probabilities(aggregate_bets) for i in arr: if (i == expected): assert(floatIsEqual(res[i],1)) continue assert(floatIsEqual(res[i],0)) else: with pytest.raises(Exception): policyConf.action_probabilities(aggregate_bets)
def test_simple_policy_config_multiple_actions(bets, predictions, moneys, expected, gen_policy_conf, gen_weighted_bet): """ This test checks that aggregate bets in policy config satsifies our definition of simple aggregation for a 3 agent system where the agents have multiple IDENTICAL actions [bets] is the bet percentage of each agent in a certain timestep [predictions] is the corresponding prediction for each bet [moneys] is a list of the agents money at that time-step The other two parameters are test fixtures to help create objects easier. """ policyConf = gen_policy_conf(fac.PolicyConfigEnum.simple) weightedBets: List[P.WeightedBet] = [] for i in range(len(bets)): print(bets[i], predictions[i], moneys[i]) weightedBets.append( gen_weighted_bet(bets[i], predictions[i], money=moneys[i])) dic = {i: weightedBets for i in range(100)} res = policyConf.aggregate_bets(dic) for i in res.keys(): assert (floatIsEqual(res[i], sum(expected)))
def check_same_behaviour(agent1, agent2, state, action, money=1.): for _ in range(5): assert floatIsEqual(agent1.vote(state), agent2.vote(state)),\ "Should be able to call vote any number of times without changing" b1 = agent1.bet(state, action, money) b2 = agent2.bet(state, action, money) assert sequenceEqual(b1.bet, b2.bet), \ "Should be able to call bet any number of times without changing" assert sequenceEqual(b1.prediction, b2.prediction), \ "Should be able to call bet any number of times without changing"
def test_simple_policy_config_action_probs(arr, vals, expected, gen_policy_conf): """ This test checks that action probs in policy config satsifies our definition of simple action probabilities which is identical to select action but gives out probabilities. [arr] is the list of actions available [vals] is the list of values for each action in [arr] The other parameter is a test fixture to help create objects easier. """ policyConf = gen_policy_conf(fac.PolicyConfigEnum.simple) res = policyConf.action_probabilities( {key: val for key, val in zip(arr, vals)}) try: for i in arr: if (i == expected): assert (floatIsEqual(res[i], 1)) continue assert (floatIsEqual(res[i], 0)) except: assert expected is None
def test_payout_config_calculate_all_payouts( enum, # factory spec variable welfare_score, selectedA, t_current, # history weightedBets, expected, gen_payout_conf, gen_weighted_bet, gen_history_item # fixtures ): """ This test checks that calculate all payouts for a given history item in payout config satisfies our definition of simple and suggested payouts for one agent is not affected by setting the new upperbound [enum] is the specifier for which payout config to use, given to the factory [welfare_score] is the total happiness for all agents at [t_current]. [selectedA] is the action selected by all agents at [t_current] [weightedBets] is what the agents bet at [t_current] The other three parameters are test fixtures to help create objects easier. """ pf: P.PayoutConfiguration = gen_payout_conf(enum, UBCE.quartile95) predsDict: Dict[A, List[WeightedBet[A, S]]] = {} # creating list of weighted bets at t1 for bet, pred, action, money, castby in weightedBets: if (action not in predsDict.keys()): predsDict[action] = [] predsDict[action].append( gen_weighted_bet(bet, pred, action, money, castby)) # TODO: doesn't hit t_cast_on != 0 # creating history item that's created at t0 = 0 record: HistoryItem[A, S] = gen_history_item(selectedA, predsDict, 0) # calculting payouts for history item payouts = pf.calculate_all_payouts( record, welfare_score, t_current, ) for agent in payouts: assert (floatIsEqual(payouts[agent], expected[agent]))
def test_payout_config_calculate_loss(enum, pred, t1, t0, R, expected, gen_payout_conf, gen_weighted_bet): """ This test checks that calculate loss in payout config satisfies our definition of simple and suggested payouts for one agent is not affected by setting the new upperbound [enum] is the specifier for which payout config to use, given to the factory [wb] is the weighted bet the agent created at [t0] generated from [pred]. The loss should be calculated for the [t1] weightedbet [R] is the welfare score. The other two parameters are test fixtures to help create objects easier. """ pf: P.PayoutConfiguration = gen_payout_conf(enum, UBCE.quartile95) bet: List[float] = [1 if t1 == (i + 1) else 0 for i in range(len(pred))] wb: P.WeightedBet = gen_weighted_bet(bet, pred) assert (floatIsEqual(pf.calculate_loss(wb, t0, t1, R), expected))
def test_suggested_policy_config_action_probs_uniform(arr,vals,expected,gen_policy_conf): """ This test checks that action probs in policy config satsifies our definition of suggested action probabilities which is identical to select action but gives out probabilities. [arr] is the list of actions available [vals] is the list of values for each action in [arr] The other parameter is a test fixture to help create objects easier. """ policyConf = gen_policy_conf(fac.PolicyConfigEnum.suggested) aggregate_bets : Dict[float,List[DiscreteDistribution]] = {} for k in range(len(arr)): aggregate_bets[arr[k]]= OneGoodOneBadDistribution(vals[k]) res = policyConf.action_probabilities(aggregate_bets) for i in arr: assert floatIsEqual(res[i],expected,0.05) # NOTE: this is a pretty big tolerance
def test_random_simple_agent_basic(random_agent_config): """ This test checks that a random agent predicts and votes using the configured [seed] and [vote] for different states in 100 timesteps. [seed] is a specified seed for bets and predictions where they both have different generators [vote] is a specified float """ for vote, seed in random_agent_config: print(f"random: {vote} , {seed}") votingConf = fac.VotingConfigFactory.create( fac.VotingConfigFactorySpec(fac.VotingConfigEnum.simple, vote_range.BinaryVoteRange)) agent = fac.AgentFactory.create( fac.AgentFactorySpec( fac.AgentsEnum.random, vote, bet=0.5, N=1, seed=seed, totalVotesBound=(votingConf.min_possible_vote_total, votingConf.max_possible_vote_total))) env = fac.EnvFactory.create( fac.EnvsFactorySpec(fac.EnvsEnum.default, n_actions=2)) genPred = np.random.default_rng(seed=seed) for _ in range(100): state = env.state() assert (agent.vote(state) == vote) for j in env.actions(): action_bet = agent.bet(state, j, 1) assert sum(action_bet.bet) <= 0.5 for k in range(len(action_bet.prediction)): min: float = votingConf.min_possible_vote_total() max: float = votingConf.max_possible_vote_total() if not np.isfinite(min): min = -100. if not np.isfinite(max): max = 100 assert (floatIsEqual(action_bet.prediction[k], genPred.uniform(min, max))) env.step(random.choice(env.actions()))
def test_random_simple_agent_forward_prediction(N): """ This test checks that a random agent predicts [N] timesteps using the configured seed = 0 and vote = 5 for different states in 100 timesteps. [N] is the length of the time-steps """ vote, seed = (5, 0) print(f"random: {vote} , {seed}") votingConf = fac.VotingConfigFactory.create( fac.VotingConfigFactorySpec(fac.VotingConfigEnum.simple, vote_range.BinaryVoteRange)) agent = fac.AgentFactory.create( fac.AgentFactorySpec( fac.AgentsEnum.random, vote, bet=0.5, N=N, seed=seed, totalVotesBound=(votingConf.min_possible_vote_total, votingConf.max_possible_vote_total))) env = fac.EnvFactory.create( fac.EnvsFactorySpec(fac.EnvsEnum.default, n_actions=5)) genBet = np.random.default_rng(seed=seed) genPred = np.random.default_rng(seed=seed) for _ in range(100): state = env.state() assert (agent.vote(state) == vote) for j in env.actions(): action_bet = agent.bet(state, j, 1) assert (len(action_bet.bet) == N) assert (len(action_bet.prediction) == N) assert sum(action_bet.bet) <= 0.5 for k in range(len(action_bet.prediction)): min: float = votingConf.min_possible_vote_total() max: float = votingConf.max_possible_vote_total() if not np.isfinite(min): min = -100. if not np.isfinite(max): max = 100 assert (floatIsEqual(action_bet.prediction[k], genPred.uniform(min, max)))
def test_weighted_mean(bets, predictions, moneys, expected, gen_weighted_bet): """ Checks that given a set of agent [bets] and [predictions], the weighted mean of them is equal to sum b_it p_it m_i / sum b_i m_i per time-step [bets] b_it [predictions] p_it [moneys] m_i The other parameter is a test fixture to help create objects easier. """ weightedBets: List[P.WeightedBet] = [] for i in range(len(bets)): print(bets[i], predictions[i], moneys[i]) weightedBets.append( gen_weighted_bet(bets[i], predictions[i], money=moneys[i])) res = U.weighted_mean_of_bets(weightedBets) assert (len(res) == len(expected)) for i in range(len(res)): assert (floatIsEqual(res[i], expected[i]))
def test_payout_config_calculate_payout_from_loss(enum, bet, t1, t0, loss, allLs, aj, ai, expected, gen_payout_conf, gen_weighted_bet): """ This test checks that calculate payout for a given loss in payout config satisfies our definition of simple and suggested payouts for one agent [enum] is the specifier for which payout config to use, given to the factory [bet] is the money the agent bet at [t1]. The [loss] is specified at [t1] for a certain agent. [allLs] are the weights and bet amounts of all agents at [t1] [aj] is the action that occured and [ai] is the action in question The other two parameters are test fixtures to help create objects easier. """ allLs: List[Weighted] = [P.Weighted(w, v) for w, v in allLs] pf: P.PayoutConfiguration = gen_payout_conf(enum) assert (floatIsEqual( pf.calculate_payout_from_loss(bet, loss, allLs, t0, t1, aj, ai), expected))
def test_add_dictionaries(dict1, dict2, expected): res: dict = U.add_dictionaries(dict1, dict2) assert (len(res.keys()) == len(expected.keys())) for i in res.keys(): assert (floatIsEqual(res[i], expected[i]))
def test_configured_bet(N,key,expected,gen_agent): """ Test that checks if look-up ActionBets work for a composite agent The tests inputs floats and expect a list of bets/predictions with length N. keyBet and keyPred have identical keys but values of keyPred are 10*values of keyBet to remove percent property. Expected is based on keyBet so we multiply by 10 to compare keyPred. N: int length of bet/prediction key: Tuple(S,A,money) what happens when an agent sees key expected: float value of bet at key and value/10 of prediction at key gen_agent: fn factory fixture """ keyBet: Dict = { (None,None,None):0.0, ('a',None,None):0.1, ('a',1,None):0.2, ('a',1,4):0.3, (None,2,5):0.4, (None,None,10):0.5, (None,2,10):0.6, ('a',1,1):0.7, } keyPred: Dict = { (None,None,None):0, ('a',None,None):1, ('a',1,None):2, ('a',1,4):3, (None,2,5):4, (None,None,10):5, (None,2,10):6, ('a',1,1):7, } a: Agent = gen_agent( AgentsEnum.composite, 20, bet_lookup=keyBet, prediction_lookup=keyPred, N=N ) assert len(a.bet(key[0],key[1],key[2]).bet) == N assert len(a.bet(key[0],key[1],key[2]).prediction) == N assert floatIsEqual(sum(a.bet(key[0],key[1],key[2]).bet), expected) assert floatIsEqual(sum(a.bet(key[0],key[1],key[2]).prediction), expected*N*10) # @pytest.mark.parametrize("keys,lookup,expected", [ # ([()],{},[0.0]) # ]) # def test_configured_prediction(keys,lookup,expected,gen_agent): # pass # @pytest.mark.parametrize("keys,lookup,expected", [ # ([()],{},0.0) # ]) # def test_should_fail_vote(keys,lookup,expected,gen_agent): # pass # @pytest.mark.parametrize("keys,lookup,expected", [ # ([()],{},[0.0]), # (('d',3,'f'),None), # ]) # def test_should_fail_bet(keys,lookup,expected,gen_agent): # pass # @pytest.mark.parametrize("keys,lookup,expected", [ # ([()],{},[0.0]) # ]) # def test_should_fail_prediction(keys,lookup,expected,gen_agent): # pass