Draken1606 commited on
Commit
867d483
·
1 Parent(s): 47438e4

Update README to match Container Yard behavior

Browse files
Files changed (1) hide show
  1. README.md +41 -21
README.md CHANGED
@@ -24,7 +24,7 @@ Port container yards are critical logistics infrastructure where thousands of co
24
 
25
  ### How It Works
26
  1. **Containers Arrive**: Containers arrive sequentially, each with a retrieval priority (1=earliest, 3=latest)
27
- 2. **Placement Decision**: Agent must choose which stack (0-9) to place the current container
28
  3. **Rehandle Penalty**: If a high-priority container is placed below a low-priority container, it must be rehandled during retrieval
29
  4. **Reward Signal**: Agent receives immediate feedback based on placement efficiency
30
 
@@ -232,22 +232,31 @@ The deployed space includes:
232
  ## Environment Details
233
 
234
  ### Action
235
- **ContainerYardAction**: Contains a single field
236
- - `message` (str) - The message to echo back
237
 
238
  ### Observation
239
- **ContainerYardObservation**: Contains the echo response and metadata
240
- - `echoed_message` (str) - The message echoed back
241
- - `message_length` (int) - Length of the message
242
- - `reward` (float) - Reward based on message length (length × 0.1)
243
- - `done` (bool) - Always False for echo environment
244
- - `metadata` (dict) - Additional info like step count
 
 
 
 
 
 
245
 
246
  ### Reward
247
- The reward is calculated as: `message_length × 0.1`
248
- - "Hi" reward: 0.2
249
- - "Hello, World!" reward: 1.3
250
- - Empty message reward: 0.0
 
 
 
251
 
252
  ## Advanced Usage
253
 
@@ -257,13 +266,14 @@ If you already have a Container Yard environment server running, you can connect
257
 
258
  ```python
259
  from Container_Yard import ContainerYardEnv
 
260
 
261
  # Connect to existing server
262
  Container_Yardenv = ContainerYardEnv(base_url="<ENV_HTTP_URL_HERE>")
263
 
264
  # Use as normal
265
  result = Container_Yardenv.reset()
266
- result = Container_Yardenv.step(ContainerYardAction(message="Hello!"))
267
  ```
268
 
269
  Note: When connecting to an existing server, `Container_Yardenv.close()` will NOT stop the server.
@@ -278,11 +288,15 @@ from Container_Yard import ContainerYardAction, ContainerYardEnv
278
  # Connect with context manager (auto-connects and closes)
279
  with ContainerYardEnv(base_url="http://localhost:8000") as env:
280
  result = env.reset()
281
- print(f"Reset: {result.observation.echoed_message}")
282
  # Multiple steps with low latency
283
- for msg in ["Hello", "World", "!"]:
284
- result = env.step(ContainerYardAction(message=msg))
285
- print(f"Echoed: {result.observation.echoed_message}")
 
 
 
 
286
  ```
287
 
288
  The client uses WebSocket connections for:
@@ -314,9 +328,15 @@ from concurrent.futures import ThreadPoolExecutor
314
  def run_episode(client_id: int):
315
  with ContainerYardEnv(base_url="http://localhost:8000") as env:
316
  result = env.reset()
317
- for i in range(10):
318
- result = env.step(ContainerYardAction(message=f"Client {client_id}, step {i}"))
319
- return client_id, result.observation.message_length
 
 
 
 
 
 
320
 
321
  # Run 4 episodes concurrently
322
  with ThreadPoolExecutor(max_workers=4) as executor:
 
24
 
25
  ### How It Works
26
  1. **Containers Arrive**: Containers arrive sequentially, each with a retrieval priority (1=earliest, 3=latest)
27
+ 2. **Placement Decision**: Agent must choose a valid stack index (0 to num_stacks-1) for the current task
28
  3. **Rehandle Penalty**: If a high-priority container is placed below a low-priority container, it must be rehandled during retrieval
29
  4. **Reward Signal**: Agent receives immediate feedback based on placement efficiency
30
 
 
232
  ## Environment Details
233
 
234
  ### Action
235
+ **ContainerYardAction**: Contains a single required field
236
+ - `stack_index` (int) - Index of the stack to place the current container into
237
 
238
  ### Observation
239
+ **ContainerYardObservation**:
240
+ - `stacks` (List[List[int]]) - Current stack states as container IDs
241
+ - `containers_placed` (int) - Number of placed containers
242
+ - `total_containers` (int) - Episode container count
243
+ - `current_container_id` (int) - Next container to place, `-1` if done
244
+ - `current_container_priority` (int) - Priority in range `1..3`
245
+ - `rehandles_so_far` (int) - Accumulated rehandles
246
+ - `num_stacks` (int) - Number of stacks in the current task
247
+ - `max_stack_height` (int) - Capacity per stack
248
+ - `action_error` (Optional[str]) - Validation error for invalid/full stack actions
249
+ - `reward` (float) - Step reward
250
+ - `done` (bool) - Whether episode is complete
251
 
252
  ### Reward
253
+ The reward is calculated per valid placement:
254
+ - `+0.1` base reward for a valid placement
255
+ - `-0.5 * rehandles_caused` penalty for new rehandles introduced by this move
256
+ - `+0.3` bonus when placement causes zero rehandles
257
+ - `+0.2` bonus when the container is stacked on same-priority container
258
+
259
+ Invalid actions (out-of-range index or full stack) return `reward=0.0` and set `action_error`.
260
 
261
  ## Advanced Usage
262
 
 
266
 
267
  ```python
268
  from Container_Yard import ContainerYardEnv
269
+ from models import ContainerYardAction
270
 
271
  # Connect to existing server
272
  Container_Yardenv = ContainerYardEnv(base_url="<ENV_HTTP_URL_HERE>")
273
 
274
  # Use as normal
275
  result = Container_Yardenv.reset()
276
+ result = Container_Yardenv.step(ContainerYardAction(stack_index=0))
277
  ```
278
 
279
  Note: When connecting to an existing server, `Container_Yardenv.close()` will NOT stop the server.
 
288
  # Connect with context manager (auto-connects and closes)
289
  with ContainerYardEnv(base_url="http://localhost:8000") as env:
290
  result = env.reset()
291
+ print(f"Current container: {result.observation.current_container_id}")
292
  # Multiple steps with low latency
293
+ for _ in range(3):
294
+ result = env.step(ContainerYardAction(stack_index=0))
295
+ print(
296
+ f"Placed={result.observation.containers_placed} "
297
+ f"rehandles={result.observation.rehandles_so_far} "
298
+ f"reward={result.reward:.2f}"
299
+ )
300
  ```
301
 
302
  The client uses WebSocket connections for:
 
328
  def run_episode(client_id: int):
329
  with ContainerYardEnv(base_url="http://localhost:8000") as env:
330
  result = env.reset()
331
+ while not result.done:
332
+ # Simple policy: choose first non-full stack
333
+ obs = result.observation
334
+ next_stack = next(
335
+ idx for idx, stack in enumerate(obs.stacks)
336
+ if len(stack) < obs.max_stack_height
337
+ )
338
+ result = env.step(ContainerYardAction(stack_index=next_stack))
339
+ return client_id, result.observation.rehandles_so_far
340
 
341
  # Run 4 episodes concurrently
342
  with ThreadPoolExecutor(max_workers=4) as executor: