@@ -57,28 +57,6 @@ def __call__(self, hidden, obs, dones):
5757
5858 return hidden , embedding
5959
60- class RewardRNN (nn .Module ):
61- # homogenous agent for parameters sharing, assumes all agents have same obs and action dim
62-
63- hidden_dim : int
64- init_scale : float
65-
66- @nn .compact
67- def __call__ (self , hidden , obs , dones ):
68-
69- embedding = nn .Dense (self .hidden_dim , kernel_init = orthogonal (self .init_scale ), bias_init = constant (0.1 ))(obs )
70- embedding = nn .relu (embedding )
71-
72- rnn_in = (embedding , dones )
73- hidden , embedding = ScannedRNN ()(hidden , rnn_in )
74- # output reward
75- rew = nn .Dense (1 , kernel_init = orthogonal (self .init_scale ), bias_init = constant (0.1 ))(embedding )
76-
77- rew = nn .tanh (rew )
78-
79- return hidden , rew
80-
81-
8260class IQLAgent (nn .Module ):
8361 action_dim : int
8462 hidden_dim : int
@@ -188,149 +166,4 @@ def __call__(self, agent_hidden, obs, dones, _):
188166
189167
190168
191- def test_iql_agent ():
192- """
193- Test the IQLAgent with actual implementations and verify output shapes and masking.
194- """
195- # Define test parameters
196- num_agents = 4
197- timesteps = 5
198- batch_size = 2
199- obs_dim = 14 # Updated from 20 to 14
200- action_dim = 3
201- hidden_dim = 16
202- num_proxy_agents = 2
203- pre_policy_output_dim = 2
204- pre_policy_hidden_dim = 12
205- gnn_embedding_dim = 14
206- init_scale = 1.0
207-
208- config = {'GNN_EMBEDDING_DIM' : gnn_embedding_dim }
209-
210- # Initialize the agent
211- agent = IQLAgent (
212- action_dim = action_dim ,
213- hidden_dim = hidden_dim ,
214- num_agents = num_agents ,
215- num_proxy_agents = num_proxy_agents ,
216- init_scale = init_scale ,
217- pre_policy_output_dim = pre_policy_output_dim ,
218- pre_policy_hidden_dim = pre_policy_hidden_dim ,
219- config = config
220- )
221-
222- # Initialize parameters with a random key
223- rng = jax .random .PRNGKey (0 )
224-
225- # Define the input shapes
226- # agent_hidden: [num_agents, batch_size, hidden_dim]
227- agent_hidden = jnp .zeros ((num_agents , batch_size , hidden_dim ))
228- # obs: [num_agents, timesteps, batch_size, obs_dim=14]
229- obs = jnp .ones ((num_agents , timesteps , batch_size , obs_dim ))
230- # dones: [num_agents, timesteps, batch_size]
231- dones = jnp .zeros ((num_agents , timesteps , batch_size ))
232- # pre_policy_hidden: [num_agents, batch_size, pre_policy_hidden_dim]
233- pre_policy_hidden = jnp .zeros ((num_agents , batch_size , pre_policy_hidden_dim ))
234-
235- # Initialize the parameters using dummy inputs
236- variables = agent .init (rng , agent_hidden , obs , dones , pre_policy_hidden )
237- # Apply the agent
238- agent_hidden_out , q_vals , pre_policy_hidden_out = agent .apply (
239- variables , agent_hidden , obs , dones , pre_policy_hidden
240- )
241-
242- # Assertions to verify output shapes
243- assert agent_hidden_out .shape == (num_agents , batch_size , hidden_dim ), (
244- f"agent_hidden_out shape mismatch: expected { (num_agents , batch_size , hidden_dim )} , "
245- f"got { agent_hidden_out .shape } "
246- )
247- # assert q_vals.shape == (num_agents, batch_size, action_dim), (
248- # f"q_vals shape mismatch: expected {(num_agents, batch_size, action_dim)}, "
249- # f"got {q_vals.shape}"
250- # )
251- assert pre_policy_hidden_out .shape == (num_agents , batch_size , pre_policy_hidden_dim ), (
252- f"pre_policy_hidden_out shape mismatch: expected { (num_agents , batch_size , pre_policy_hidden_dim )} , "
253- f"got { pre_policy_hidden_out .shape } "
254- )
255-
256- # To verify the masking, create a subclass that returns pre_policy_embedding
257- class TestableIQLAgent (IQLAgent ):
258- def __call__ (self , agent_hidden , obs , dones , pre_policy_hidden ):
259- agent_hidden , agent_embedding = jax .vmap (self .agent_rnn , in_axes = 0 )(
260- agent_hidden , obs , dones
261- )
262-
263- pre_policy_hidden , pre_policy_embedding = jax .vmap (self .pre_policy_network , in_axes = 0 )(
264- pre_policy_hidden , obs , dones
265- )
266-
267- # Create a mask for pre_policy_embedding
268- mask = jnp .arange (self .num_agents ) < self .num_proxy_agents
269- mask = mask [:, None , None , None ] # Reshape for broadcasting
270-
271- # Non-proxy agents receive all-zero pre-policy embeddings
272- pre_policy_embedding = pre_policy_embedding * mask
273- print (pre_policy_embedding )
274- # Apply MLP to agent embeddings before GNN
275- gnn_input = jax .vmap (self .mlp_gnn , in_axes = 0 )(agent_embedding )
276- print (f'gnn input: { gnn_input .shape } ' ) # Expected: (num_agents, timesteps, batch_size, 14)
277-
278- # Apply GNN to the processed agent embeddings
279- gnn_features = jax .vmap (self .gnn , in_axes = 0 )(gnn_input )
280- print (f'gnn features shape: { gnn_features .shape } ' ) # Expected: (num_agents, timesteps, batch_size, out_embedding_dim)
281-
282- # Concatenate embeddings for Q-value computation
283- q_value_input = jnp .concatenate (
284- [agent_embedding , gnn_features , pre_policy_embedding ], axis = - 1
285- )
286- q_vals = jax .vmap (self .q_value_mlp , in_axes = 0 )(q_value_input )
287-
288- return agent_hidden , q_vals , pre_policy_hidden , pre_policy_embedding
289-
290- # Initialize the testable agent
291- testable_agent = TestableIQLAgent (
292- action_dim = action_dim ,
293- hidden_dim = hidden_dim ,
294- num_agents = num_agents ,
295- num_proxy_agents = num_proxy_agents ,
296- init_scale = init_scale ,
297- pre_policy_output_dim = pre_policy_output_dim ,
298- pre_policy_hidden_dim = pre_policy_hidden_dim ,
299- config = config
300- )
301-
302- # Initialize parameters for the testable agent
303- testable_variables = testable_agent .init (rng , agent_hidden , obs , dones , pre_policy_hidden )
304-
305- # Apply the testable agent
306- _ , _ , _ , pre_policy_embedding_out = testable_agent .apply (
307- testable_variables , agent_hidden , obs , dones , pre_policy_hidden
308- )
309-
310- # Create the expected mask
311- expected_mask = jnp .arange (num_agents ) < num_proxy_agents
312- expected_mask = expected_mask [:, None , None , None ] # Shape: [num_agents, 1, 1, 1]
313-
314- # Check that pre_policy_embedding is zero for non-proxy agents
315- non_proxy_agents = ~ (jnp .arange (num_agents ) < num_proxy_agents )
316- non_proxy_agents = non_proxy_agents [:, None , None , None ] # Reshape for broadcasting
317-
318- # Extract pre_policy_embedding for non-proxy agents
319- masked_pre_policy = pre_policy_embedding_out * non_proxy_agents
320-
321- # Assert that the masked pre_policy_embedding is all zeros
322- assert jnp .all (masked_pre_policy == 0 ), "pre_policy_embedding is not zero for non-proxy agents"
323-
324- print ("All tests passed successfully." )
325-
326-
327- if __name__ == "__main__" :
328- test_iql_agent ()
329-
330-
331-
332-
333-
334-
335-
336169
0 commit comments