以 ASCII 树形式打印节点树
(nodes: Dict[str, NodeInfo], root_id: str, max_depth: int = 10)
| 144 | |
| 145 | |
| 146 | def print_tree_ascii(nodes: Dict[str, NodeInfo], root_id: str, max_depth: int = 10): |
| 147 | """ |
| 148 | 以 ASCII 树形式打印节点树 |
| 149 | """ |
| 150 | if root_id not in nodes: |
| 151 | print("Error: Root node not found") |
| 152 | return |
| 153 | |
| 154 | print("\n" + "="*80) |
| 155 | print("MCTS Search Tree Visualization") |
| 156 | print("="*80) |
| 157 | print(f"Legend: ✓=OK ✗=FAIL ?=unknown, [r/d/i]=root/draft/improve, m=metric, [T]=terminal") |
| 158 | print("="*80 + "\n") |
| 159 | |
| 160 | def dfs_print(node_id: str, prefix: str, is_last: bool, depth: int): |
| 161 | if depth > max_depth: |
| 162 | return |
| 163 | |
| 164 | node = nodes[node_id] |
| 165 | |
| 166 | # 打印当前节点 |
| 167 | current_prefix = "└── " if is_last else "├── " |
| 168 | print(prefix + current_prefix + str(node)) |
| 169 | |
| 170 | # 更新前缀 |
| 171 | extension = " " if is_last else "│ " |
| 172 | new_prefix = prefix + extension |
| 173 | |
| 174 | # 递归打印子节点 |
| 175 | children = node.children_ids |
| 176 | for i, child_id in enumerate(children): |
| 177 | is_last_child = (i == len(children) - 1) |
| 178 | dfs_print(child_id, new_prefix, is_last_child, depth + 1) |
| 179 | |
| 180 | # 打印根节点 |
| 181 | dfs_print(root_id, "", True, 0) |
| 182 | |
| 183 | print("\n" + "="*80) |
| 184 | print("Statistics:") |
| 185 | print("="*80) |
| 186 | |
| 187 | # 统计信息 |
| 188 | stats = { |
| 189 | 'root': 0, 'draft': 0, 'improve': 0, 'debug': 0, |
| 190 | 'OK': 0, 'FAIL': 0, 'unknown': 0, |
| 191 | 'terminal': 0, |
| 192 | 'with_metric': 0 |
| 193 | } |
| 194 | |
| 195 | for node in nodes.values(): |
| 196 | stats[node.stage] = stats.get(node.stage, 0) + 1 |
| 197 | stats[node.run_status] = stats.get(node.run_status, 0) + 1 |
| 198 | if node.is_terminal: |
| 199 | stats['terminal'] += 1 |
| 200 | if node.metric is not None: |
| 201 | stats['with_metric'] += 1 |
| 202 | |
| 203 | print(f"Total nodes: {len(nodes)}") |
no test coverage detected