Topologically Order Tool Calls with Argument Dependencies
Problem Statement
A set of tool calls reference each other's outputs. Produce a valid execution order (dependencies first), or detect a cycle. Break ties deterministically by step id.
Background
Each call has an integer id and a list of deps (ids it must run after). This is a topological sort. Use Kahn's algorithm: repeatedly emit the ready node (in-degree 0) with the smallest id. If not all nodes are emitted, there is a cycle.
Your Task
Implement:
def order_calls(calls):
- calls: list of {"id": int, "deps": [int, ...]}.
- Return the ordered list of ids, or the string "CYCLE" if no valid order exists.
Input Format
- calls (list of dicts).
Output Format
- A list of ints, or "CYCLE".
Sample
print(order_calls([{"id":1,"deps":[2]},{"id":2,"deps":[]}]))
Output:
[2, 1]
Example
print(order_calls([{"id":1,"deps":[2]},{"id":2,"deps":[]}]))[2, 1]
- Initialize dependency tracking: Node 1 depends on Node 2, so Node 1's in-degree is 1 and Node 2's in-degree is 0. The adjacency list records that Node 2 must execute before Node 1.
- Identify ready nodes: Only Node 2 has an in-degree of 0, so it is the sole candidate for the first execution step.
- Process Node 2: Emit Node 2 to the result list. Decrement the in-degree of its dependent, Node 1, from 1 to 0, making Node 1 ready for execution.
- Process Node 1: With Node 1 now having an in-degree of 0, it is emitted next. No further nodes remain in the queue.
- Verify completion: The result list contains both nodes (length 2), matching the total number of input calls, confirming no cycle exists.
- The final output is [2, 1]
Constraints
- Ids are unique ints; deps reference existing ids.
- Among ready nodes, always emit the smallest id (deterministic).
- Return
"CYCLE"if a topological order does not exist.