diff --git a/mesa/examples/advanced/alliance_formation/app.py b/mesa/examples/advanced/alliance_formation/app.py index 147efb672ad..3dd25c47a9b 100644 --- a/mesa/examples/advanced/alliance_formation/app.py +++ b/mesa/examples/advanced/alliance_formation/app.py @@ -24,6 +24,14 @@ "max": 100, "step": 1, }, + "std_dev": { + "type": "SliderFloat", + "value": 0.1, + "label": "Attribute variation:", + "min": 0.01, + "max": 0.4, + "step": 0.01, + }, } # Create visualization elements. The visualization elements are solara components @@ -37,12 +45,12 @@ def plot_network(model): update_counter.get() g = model.network - pos = nx.fruchterman_reingold_layout(g) + pos = nx.multipartite_layout(g, subset_key="level", align="horizontal") fig = Figure() ax = fig.subplots() labels = {agent.unique_id: agent.unique_id for agent in model.agents} node_sizes = [g.nodes[node]["size"] for node in g.nodes] - node_colors = [g.nodes[node]["size"] for node in g.nodes()] + node_colors = [g.nodes[node]["level"] for node in g.nodes()] nx.draw( g, @@ -53,6 +61,7 @@ def plot_network(model): labels=labels, ax=ax, ) + ax.set_axis_off() solara.FigureMatplotlib(fig) diff --git a/mesa/examples/advanced/alliance_formation/model.py b/mesa/examples/advanced/alliance_formation/model.py index b9defe2d576..8d0caa655cd 100644 --- a/mesa/examples/advanced/alliance_formation/model.py +++ b/mesa/examples/advanced/alliance_formation/model.py @@ -162,12 +162,14 @@ def step(self): """ Execute one step of the model. """ - # Get all other agents of the same type - agent_types = list(self.agents_by_type.keys()) - - for agent_type in agent_types: - similar_agents = self.agents_by_type[agent_type] - + # Agents at the same hierarchy level can form an alliance. Meta-agents + # use dynamically generated classes, so grouping by concrete type would + # isolate every meta-agent and prevent higher-level alliances. + agents_by_level = {} + for agent in self.agents: + agents_by_level.setdefault(agent.level, []).append(agent) + + for similar_agents in agents_by_level.values(): # Find the best combinations using find_combinations if ( len(similar_agents) > 1 diff --git a/tests/examples/test_alliance_formation_model.py b/tests/examples/test_alliance_formation_model.py index 3b49269db4c..06860eb881b 100644 --- a/tests/examples/test_alliance_formation_model.py +++ b/tests/examples/test_alliance_formation_model.py @@ -43,3 +43,16 @@ def fake_find_combinations(*args, **kwargs): assert backend.as_triplets() == expected_triplets backend.assert_invariants() + + +def test_alliance_model_forms_higher_level_alliances(): + """Meta-agents at one level can form an alliance at the next level.""" + model = MultiLevelAllianceModel( + scenario=AllianceScenario(n=4, mean=0.5, std_dev=0.0, rng=42) + ) + + model.step() + assert sum(agent.level == 1 for agent in model.agents) == 2 + + model.step() + assert sum(agent.level == 2 for agent in model.agents) == 1