diff --git a/examples/modular/environment/haggling.py b/examples/modular/environment/haggling.py index 708e3ae2..532dc190 100644 --- a/examples/modular/environment/haggling.py +++ b/examples/modular/environment/haggling.py @@ -165,6 +165,11 @@ def configure_player( f'Would {name} accept the offer?:': 'accept', f'What price would {name} propose?:': '3 coins', } + extras['specific_memories'] = [ + f'{name} does not care about the price. {name} will accept any offer!' + ' They are very vocal about it and will not haggle and will praise any' + ' offer.' + ] return formative_memories.AgentConfig( name=name, @@ -549,10 +554,6 @@ def __init__( resident_visitor_modules: Sequence[types.ModuleType] | None = None, supporting_agent_module: types.ModuleType | None = None, time_and_place_module: str | None = None, - num_supporting_player: int = 0, - only_match_with_support: bool = False, - num_games: int = 2, - num_main_players: int = 3, seed: int | None = None, ): """Initialize the simulation object. @@ -577,11 +578,7 @@ def __init__( time_and_place_module: optionally, specify a module containing settings that create a sense of setting in a specific time and place. If not specified, a random module will be chosen from the default options. - num_supporting_player: the number of supporting players. - only_match_with_support: whether to only match main players with - supporting players. - num_games: the number of games to play. - num_main_players: the number of main players. + seed: the random seed to use. """ # Support for these parameters will be added in a future addition coming @@ -595,11 +592,6 @@ def __init__( seed=seed, ) ) - sampled_settings.num_supporting_players = num_supporting_player - sampled_settings.only_match_with_support = only_match_with_support - sampled_settings.num_main_players = num_main_players - sampled_settings.num_games = num_games - self._rng = random.Random(sampled_settings.random_seed) start_time = datetime.datetime( @@ -699,10 +691,10 @@ def __init__( ), ) explicit_preference = agent_components.constant.Constant( - pre_act_key='explicit preference', + pre_act_key='Explicit preference', state=( f'{player_config.name} will accept any offer! They are very vocal' - ' about it.' + ' about it and will not haggle and will praise any offer.' ), ) player = self._build_supporting_agent( diff --git a/examples/modular/environment/haggling_gullible.py b/examples/modular/environment/haggling_gullible.py deleted file mode 100644 index f58a9730..00000000 --- a/examples/modular/environment/haggling_gullible.py +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright 2024 DeepMind Technologies Limited. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""A Concordia Environment Configuration.""" - -from examples.modular.environment import haggling - - -class Simulation(haggling.Simulation): - """Simulation with pub closures.""" - - def __init__( - self, - **kwargs, - ): - """Initialize the simulation object. - - The launch script assumes this API object has a run() method. - - Args: - **kwargs: arguments to pass to the base class. - """ - - super().__init__( - num_supporting_player=1, - only_match_with_support=True, - **kwargs, - ) diff --git a/examples/modular/environment/haggling_multi_item.py b/examples/modular/environment/haggling_multi_item.py index f052936e..67c674d6 100644 --- a/examples/modular/environment/haggling_multi_item.py +++ b/examples/modular/environment/haggling_multi_item.py @@ -100,7 +100,7 @@ class WorldConfig: buyer_base_reward_min: int = 5 seller_base_reward_max: int = 2 num_games: int = 2 - num_main_players: int = 3 + num_main_players: int = 2 prices: Sequence[int] = (1, 2, 3, 4, 5, 6) items_for_sale: Sequence[str] = ('apple', 'banana', 'pear') random_seed: int = 42 @@ -169,6 +169,11 @@ def configure_player( f'Would {name} accept the offer?:': 'accept', f'What price would {name} propose?:': '3 coins', } + extras['specific_memories'] = [ + f'{name} does not care about the price. {name} will accept any offer!' + ' They are very vocal about it and will not haggle and will praise any' + ' offer.' + ] return formative_memories.AgentConfig( name=name, @@ -579,10 +584,6 @@ def __init__( resident_visitor_modules: Sequence[types.ModuleType] | None = None, supporting_agent_module: types.ModuleType | None = None, time_and_place_module: str | None = None, - num_supporting_player: int = 0, - only_match_with_support: bool = False, - num_games: int = 2, - num_main_players: int = 3, seed: int | None = None, ): """Initialize the simulation object. @@ -607,11 +608,6 @@ def __init__( time_and_place_module: optionally, specify a module containing settings that create a sense of setting in a specific time and place. If not specified, a random module will be chosen from the default options. - num_supporting_player: the number of supporting players. - only_match_with_support: whether to only match main players with - supporting players. - num_games: the number of games to play. - num_main_players: the number of main players. seed: the random seed to use. """ # Support for these parameters will be added in a future addition coming @@ -625,10 +621,10 @@ def __init__( seed=seed, ) ) - sampled_settings.num_supporting_players = num_supporting_player - sampled_settings.only_match_with_support = only_match_with_support - sampled_settings.num_main_players = num_main_players - sampled_settings.num_games = num_games + # sampled_settings.num_supporting_players = num_supporting_player + # sampled_settings.only_match_with_support = only_match_with_support + # sampled_settings.num_main_players = num_main_players + # sampled_settings.num_games = num_games self._rng = random.Random(sampled_settings.random_seed) start_time = datetime.datetime( @@ -728,10 +724,10 @@ def __init__( ), ) explicit_preference = agent_components.constant.Constant( - pre_act_key='explicit preference', + pre_act_key='Explicit preference', state=( f'{player_config.name} will accept any offer! They are very vocal' - ' about it.' + ' about it and will not haggle and will praise any offer.' ), ) player = self._build_supporting_agent( diff --git a/examples/modular/environment/modules/fruitville_haggling_gullible.py b/examples/modular/environment/modules/fruitville_haggling_gullible.py new file mode 100644 index 00000000..85b8ab06 --- /dev/null +++ b/examples/modular/environment/modules/fruitville_haggling_gullible.py @@ -0,0 +1,137 @@ +# Copyright 2024 DeepMind Technologies Limited. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""World configuration for the Fruitville haggling scenario.""" + +import random +from examples.modular.environment import haggling + +YEAR = 1895 +MONTH = 9 +DAY = 12 + +FEMALE_NAMES = [ + "Anya Blossomwood", + "Brynn Orchardheart", + "Clara Applebrook", + "Della Plumstone", + "Elara Berryvine", + "Faye Honeydew", + "Gaia Willowbrook", + "Hazel Nutgrove", + "Ivy Pearblossom", + "Juniper Quincewood", + "Kira Citronbloom", + "Lila Figleaf", + "Maeve Mulberry", + "Nova Peachwood", + "Opal Apricot", + "Sasha Grapevine", + "Quinn Cherryblossom", + "Rowan Cranberry", + "Sage Honeycomb", + "Willow Blackberry", +] + +MALE_NAMES = [ + "Aiden Riversong", + "Blaise Windwillow", + "Cedric Meadowbrook", + "Dorian Sunstone", + "Elias Berryfield", + "Flynn Honeycomb", + "Garen Willowshade", + "Hunter Nutwood", + "Ivor Pearbrook", + "Jasper Quincehill", + "Kieran Citronbrook", + "Lennon Figtree", + "Magnus Mulberrylane", + "Nolan Peachgrove", + "Orion Apricotwood", + "Peregrine Grapehill", + "Quentin Cherrybrook", + "Rowan Cranberryfield", + "Silas Honeybrook", + "Tristan Blackberrylane", +] + +SCENARIO_PREMISE = ( + "In the realm of Ouroboros, there is a quiet village of" + " Fruitville, which is famous for its fruit market. Traders from" + " all over the realm come to Fruitville to buy and sell produce." +) + +VISUAL_SCENE_OPENINGS = [ + ( + "The first rays of dawn painted the sky above Fruitville in hues of" + " orange and gold, casting a warm glow over the bustling market. Stalls" + " overflowed with vibrant fruits, their aromas mingling in the crisp" + " morning air." + ), + ( + "As the sun peeked over the horizon, the market of Fruitville stirred" + " to life. Merchants, their voices a cheerful symphony, arranged their" + " wares: glistening berries, plump melons, and exotic fruits from" + " distant lands." + ), + ( + "Dewdrops clung to the colorful fruits displayed in the market of" + " Fruitville, reflecting the soft morning light. The air buzzed with" + " anticipation as traders and customers alike gathered for the day's" + " trade." + ), + ( + "The cobblestone streets of Fruitville echoed with the clatter of" + " hooves and the rumble of carts as the market awoke. Underneath" + " colorful awnings, merchants proudly presented their bountiful" + " harvests, their voices a chorus of greetings and bartering." + ), + ( + "In the heart of Fruitville, the market square transformed into a" + " kaleidoscope of colors as the sun rose. Fruits of every imaginable" + " shape and size adorned the stalls, a feast for the eyes and a promise" + " of delightful flavors." + ), +] + + +def sample_parameters(seed: int | None = None): + """Samples a set of parameters for the world configuration.""" + seed = seed if seed is not None else random.getrandbits(63) + + config = haggling.WorldConfig( + year=YEAR, + location="Fruitville", + premise=SCENARIO_PREMISE, + scene_visuals=VISUAL_SCENE_OPENINGS, + random_seed=seed, + num_supporting_players=1, + num_main_players=1, + num_games=3, + buyer_base_reward_min=6, + seller_base_reward_max=1, + only_match_with_support=True, + ) + all_names = list(MALE_NAMES) + list(FEMALE_NAMES) + rng = random.Random(config.random_seed) + rng.shuffle(all_names) + config.people = all_names + + for _, name in enumerate(MALE_NAMES): + config.person_data[name] = {"gender": "male"} + for _, name in enumerate(FEMALE_NAMES): + config.person_data[name] = {"gender": "female"} + + return config diff --git a/examples/modular/environment/modules/fruitville_haggling_multi_fruit.py b/examples/modular/environment/modules/fruitville_haggling_multi_fruit_gullible.py similarity index 97% rename from examples/modular/environment/modules/fruitville_haggling_multi_fruit.py rename to examples/modular/environment/modules/fruitville_haggling_multi_fruit_gullible.py index ab6caf43..8259f317 100644 --- a/examples/modular/environment/modules/fruitville_haggling_multi_fruit.py +++ b/examples/modular/environment/modules/fruitville_haggling_multi_fruit_gullible.py @@ -117,6 +117,10 @@ def sample_parameters(seed: int | None = None): premise=SCENARIO_PREMISE, scene_visuals=VISUAL_SCENE_OPENINGS, random_seed=seed, + num_supporting_players=1, + num_main_players=1, + num_games=3, + only_match_with_support=True, ) all_names = list(MALE_NAMES) + list(FEMALE_NAMES) diff --git a/examples/modular/environment/modules/pub_coordination_london_follow.py b/examples/modular/environment/modules/pub_coordination_london_follow.py new file mode 100644 index 00000000..ff607a00 --- /dev/null +++ b/examples/modular/environment/modules/pub_coordination_london_follow.py @@ -0,0 +1,67 @@ +# Copyright 2024 DeepMind Technologies Limited. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""A set of pub names and reasons to like them.""" + +import random +from examples.modular.environment import pub_coordination +from examples.modular.environment.modules import pub_coordination_london + +YEAR = pub_coordination_london.YEAR +MONTH = pub_coordination_london.MONTH +DAY = pub_coordination_london.DAY + +NUM_PUBS = pub_coordination_london.NUM_PUBS + + +def sample_parameters(seed: int | None = None): + """Samples a set of parameters for the world configuration.""" + seed = seed if seed is not None else random.getrandbits(63) + rng = random.Random(seed) + + pubs = rng.sample( + list(pub_coordination_london.PUB_PREFERENCES.keys()), + pub_coordination_london.NUM_PUBS, + ) + pub_preferences = { + k: pub_coordination_london.PUB_PREFERENCES[k] for k in pubs + } + + config = pub_coordination.WorldConfig( + year=pub_coordination_london.YEAR, + location="London", + event="European football cup", + game_countries=pub_coordination_london.EURO_CUP_COUNTRIES, + venues=pubs, + venue_preferences=pub_preferences, + social_context=pub_coordination_london.SOCIAL_CONTEXT, + random_seed=seed, + num_main_players=2, + num_supporting_players=4, + num_games=5, + ) + + all_names = list(pub_coordination_london.MALE_NAMES) + list( + pub_coordination_london.FEMALE_NAMES + ) + + rng.shuffle(all_names) + config.people = all_names + + for _, name in enumerate(pub_coordination_london.MALE_NAMES): + config.person_data[name] = {"gender": "male"} + for _, name in enumerate(pub_coordination_london.FEMALE_NAMES): + config.person_data[name] = {"gender": "female"} + + return config diff --git a/examples/modular/environment/modules/pub_coordination_london_mini.py b/examples/modular/environment/modules/pub_coordination_london_mini.py new file mode 100644 index 00000000..343db548 --- /dev/null +++ b/examples/modular/environment/modules/pub_coordination_london_mini.py @@ -0,0 +1,67 @@ +# Copyright 2024 DeepMind Technologies Limited. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""A set of pub names and reasons to like them.""" + +import random +from examples.modular.environment import pub_coordination +from examples.modular.environment.modules import pub_coordination_london + +YEAR = pub_coordination_london.YEAR +MONTH = pub_coordination_london.MONTH +DAY = pub_coordination_london.DAY + +NUM_PUBS = pub_coordination_london.NUM_PUBS + + +def sample_parameters(seed: int | None = None): + """Samples a set of parameters for the world configuration.""" + seed = seed if seed is not None else random.getrandbits(63) + rng = random.Random(seed) + + pubs = rng.sample( + list(pub_coordination_london.PUB_PREFERENCES.keys()), + pub_coordination_london.NUM_PUBS, + ) + pub_preferences = { + k: pub_coordination_london.PUB_PREFERENCES[k] for k in pubs + } + + config = pub_coordination.WorldConfig( + year=pub_coordination_london.YEAR, + location="London", + event="European football cup", + game_countries=pub_coordination_london.EURO_CUP_COUNTRIES, + venues=pubs, + venue_preferences=pub_preferences, + social_context=pub_coordination_london.SOCIAL_CONTEXT, + random_seed=seed, + num_main_players=2, + num_supporting_players=0, + num_games=3, + ) + + all_names = list(pub_coordination_london.MALE_NAMES) + list( + pub_coordination_london.FEMALE_NAMES + ) + + rng.shuffle(all_names) + config.people = all_names + + for _, name in enumerate(pub_coordination_london.MALE_NAMES): + config.person_data[name] = {"gender": "male"} + for _, name in enumerate(pub_coordination_london.FEMALE_NAMES): + config.person_data[name] = {"gender": "female"} + + return config diff --git a/examples/modular/environment/pub_coordination.py b/examples/modular/environment/pub_coordination.py index f2d69d0d..dd1c1d30 100644 --- a/examples/modular/environment/pub_coordination.py +++ b/examples/modular/environment/pub_coordination.py @@ -687,9 +687,6 @@ def __init__( time_and_place_module: str | None = None, pub_closed_probability: float = 0.0, use_relational_matrix: bool = False, - num_games: int = 3, - num_main_players: int = 4, - num_supporting_players: int = 1, seed: int | None = None, ): """Initialize the simulation object. @@ -717,9 +714,6 @@ def __init__( pub_closed_probability: the probability that a pub is closed. Zero by default. use_relational_matrix: whether to use relational matrix or not. - num_games: the number of games to play. - num_main_players: the number of main players. - num_supporting_players: the number of supporting players. seed: the random seed to use. """ # Support for these parameters will be added in a future addition coming @@ -755,9 +749,6 @@ def __init__( ) ) self._rng = random.Random(sampled_settings.random_seed) - sampled_settings.num_main_players = num_main_players - sampled_settings.num_supporting_players = num_supporting_players - sampled_settings.num_games = num_games start_time = datetime.datetime( year=time_and_place_params.YEAR, @@ -799,7 +790,6 @@ def __init__( main_player_configs, supporting_player_configs = configure_players( sampled_settings, self._rng ) - self._rng.shuffle(main_player_configs) tasks = { config.name: functools.partial( @@ -996,6 +986,7 @@ def __call__(self) -> tuple[logging_lib.SimulationOutcome, str]: ) player_scores = self._coordination_payoffs() + print(player_scores) simulation_outcome = logging_lib.SimulationOutcome( resident_scores=immutabledict.immutabledict( {name: player_scores[name] for name in self._resident_names} diff --git a/examples/modular/environment/pub_coordination_mini.py b/examples/modular/environment/pub_coordination_mini.py deleted file mode 100644 index 3a16449b..00000000 --- a/examples/modular/environment/pub_coordination_mini.py +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright 2024 DeepMind Technologies Limited. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""A Concordia Environment Configuration.""" - - -from examples.modular.environment import pub_coordination - - -class Simulation(pub_coordination.Simulation): - """Simulation with pub closures.""" - - def __init__( - self, - **kwargs, - ): - """Initialize the simulation object. - - The launch script assumes this API object has a run() method. - - Args: - **kwargs: arguments to pass to the base class. - """ - - super().__init__( - pub_closed_probability=0.0, - num_games=3, - num_main_players=2, - num_supporting_players=0, - **kwargs, - ) diff --git a/examples/modular/scenario/scenarios.py b/examples/modular/scenario/scenarios.py index fb617385..bea6da75 100644 --- a/examples/modular/scenario/scenarios.py +++ b/examples/modular/scenario/scenarios.py @@ -102,14 +102,6 @@ class ScenarioConfig: environment='pub_coordination', supporting_agent_module='basic_puppet_agent', ), - pub_coordination_mini=SubstrateConfig( - description=( - 'pub attendance coordination with supporting agent being stubborn' - ' and always choosing their preference.' - ), - environment='pub_coordination_mini', - supporting_agent_module='basic_puppet_agent', - ), pub_coordination_closures=SubstrateConfig( description=( 'pub attendance coordination with one pub sometimes being closed' @@ -127,7 +119,7 @@ class ScenarioConfig: environment='haggling', supporting_agent_module='basic_puppet_agent', ), - haggling_multi_item=SubstrateConfig( + haggling_multi_item_gullible=SubstrateConfig( description='haggling over a price with multiple items', environment='haggling_multi_item', supporting_agent_module='basic_puppet_agent', @@ -200,22 +192,23 @@ class ScenarioConfig: 'a mini scenario with one focal and one rational visitor and no' ' supporting agents. Intended for fast testing.' ), - substrate_config=SUBSTRATE_CONFIGS['pub_coordination_mini'], + substrate_config=SUBSTRATE_CONFIGS['pub_coordination'], background_agent_module='rational_agent', - time_and_place_module='pub_coordination_london', + time_and_place_module='pub_coordination_london_mini', focal_is_resident=True, tags=('coordination', 'persuasion'), ), pub_coordination_0=ScenarioConfig( description=( - 'resident population of focal agents in a pub coordination scenario' - ' with a supporting agent who is stubborn and a' - ' rational visitor agent' + 'visitor population of focal agents in a pub coordination scenario' + ' with a supporting agents who are stubborn and have an opposite ' + 'preference and a rational resident agent who has opposite ' + 'preferences as well.' ), substrate_config=SUBSTRATE_CONFIGS['pub_coordination'], background_agent_module='rational_agent', - time_and_place_module='pub_coordination_london', - focal_is_resident=True, + time_and_place_module='pub_coordination_london_follow', + focal_is_resident=False, tags=('coordination', 'persuasion'), ), pub_coordination_friendships_0=ScenarioConfig( @@ -243,24 +236,24 @@ class ScenarioConfig: ), haggling_1=ScenarioConfig( description=( - 'visitor focal agent in a haggling scenario with no supporting' - ' agents and a rational visitor agent' + 'visitor focal agent in a haggling scenario with a supporting' + ' agents who will accept any price and a rational visitor agent' ), - substrate_config=SUBSTRATE_CONFIGS['haggling_gullible'], + substrate_config=SUBSTRATE_CONFIGS['haggling'], background_agent_module='rational_agent', - time_and_place_module='fruitville_haggling', - focal_is_resident=True, + time_and_place_module='fruitville_haggling_gullible', + focal_is_resident=False, tags=('negotiation',), ), haggling_multi_item_0=ScenarioConfig( description=( - 'resident population of focal agents in a haggling scenario with no' - ' supporting agents and rational residents' + 'visitor focal agent in a haggling scenario with a supporting' + ' agents who will accept any price and a rational visitor agent' ), - substrate_config=SUBSTRATE_CONFIGS['haggling_multi_item'], + substrate_config=SUBSTRATE_CONFIGS['haggling_multi_item_gullible'], background_agent_module='rational_agent', - time_and_place_module='fruitville_haggling_multi_fruit', - focal_is_resident=True, + time_and_place_module='fruitville_haggling_multi_fruit_gullible', + focal_is_resident=False, tags=('negotiation', 'hidden information'), ), reality_show_circa_2003_prisoners_dilemma_0=ScenarioConfig(