TwoQuarks commited on
Commit
b442b8c
·
verified ·
1 Parent(s): b5285b3

Update Down/AntiDown/exp/plot_corrupted_valley_results.py

Browse files
Down/AntiDown/exp/plot_corrupted_valley_results.py CHANGED
@@ -1,10 +1,17 @@
1
  """
2
- Plot results for the Corrupted Valley tabular experiment.
3
 
4
- Expects a CSV file created by `exp/run_corrupted_valley_tabular.py` with columns:
5
  phase, phase_tag, episode, agent, total_reward, valley_visits
 
 
 
 
 
6
  """
7
 
 
 
8
  # --- twoquarks bootstrap (path-stable imports) ---
9
  import sys
10
  from pathlib import Path
@@ -13,32 +20,48 @@ if str(_ROOT) not in sys.path:
13
  sys.path.insert(0, str(_ROOT))
14
  # -------------------------------------------------
15
 
16
-
17
  import csv
18
  import os
19
  from collections import defaultdict
20
  from typing import Dict, List, Tuple
21
 
 
 
22
  import matplotlib.pyplot as plt
23
 
24
 
25
- RESULTS_DIR = Path(os.environ.get("TWOQUARKS_RESULTS_DIR", (Path(__file__).resolve().parent.parent / "results").as_posix()))
26
- RESULTS_CSV = str(RESULTS_DIR / "antidown_corrupted_valley_tabular.csv")
27
- OUT_DIR = Path(os.environ.get("TWOQUARKS_GRAPHICS_DIR", (Path(__file__).resolve().parent.parent / "graphics").as_posix()))
28
- OUT_DIR.mkdir(parents=True, exist_ok=True)
29
- OUT_PREFIX = str(OUT_DIR / "antidown_corrupted_valley_")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
 
31
 
32
- def load_results(path: str) -> List[Dict[str, str]]:
33
- rows: List[Dict[str, str]] = []
34
- with open(path, mode="r", newline="") as f:
35
- reader = csv.DictReader(f)
36
- for row in reader:
37
- rows.append(row)
38
- return rows
39
 
40
 
41
- def build_global_index(rows: List[Dict[str, str]]) -> Tuple[Dict[int, int], Dict[int, Dict[str, List[Tuple[int, float, float]]]]]:
 
 
42
  """
43
  Returns:
44
  phase_to_max_ep: phase -> max episode index
@@ -64,8 +87,10 @@ def build_global_index(rows: List[Dict[str, str]]) -> Tuple[Dict[int, int], Dict
64
  ep = int(r["episode"])
65
  total_reward = float(r["total_reward"])
66
  valley_visits = float(r["valley_visits"])
 
67
  max_ep = phase_to_max_ep[phase]
68
  global_ep = (phase - 1) * max_ep + ep
 
69
  data[phase][agent].append((global_ep, total_reward, valley_visits))
70
 
71
  return phase_to_max_ep, data
@@ -75,14 +100,14 @@ def plot_metric(
75
  data: Dict[int, Dict[str, List[Tuple[int, float, float]]]],
76
  metric_index: int,
77
  ylabel: str,
78
- out_path: str,
79
  ) -> None:
80
  """
81
- metric_index: 1 for total_reward, 2 for valley_visits.
 
82
  """
83
  plt.figure()
84
 
85
- # merge across phases, keeping breaks in the global index
86
  agent_to_xy: Dict[str, Tuple[List[int], List[float]]] = {}
87
 
88
  for phase, agents in sorted(data.items()):
@@ -95,7 +120,6 @@ def plot_metric(
95
  agent_to_xy[agent][1].extend(ys)
96
 
97
  for agent, (xs, ys) in agent_to_xy.items():
98
- # sort by x
99
  pairs = sorted(zip(xs, ys), key=lambda p: p[0])
100
  xs_sorted = [p[0] for p in pairs]
101
  ys_sorted = [p[1] for p in pairs]
@@ -105,31 +129,56 @@ def plot_metric(
105
  plt.ylabel(ylabel)
106
  plt.legend()
107
  plt.tight_layout()
108
- plt.savefig(out_path)
109
  plt.close()
110
 
111
 
112
  def main() -> None:
113
- if not os.path.exists(RESULTS_CSV):
114
- raise FileNotFoundError(f"Results file not found: {RESULTS_CSV}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115
 
116
- rows = load_results(RESULTS_CSV)
117
  _, data = build_global_index(rows)
118
 
 
 
119
  plot_metric(
120
  data,
121
  metric_index=1,
122
  ylabel="total reward per episode",
123
- out_path=OUT_PREFIX + "reward.png",
124
  )
125
 
126
  plot_metric(
127
  data,
128
  metric_index=2,
129
  ylabel="valley visits per episode",
130
- out_path=OUT_PREFIX + "valley_visits.png",
131
  )
132
 
 
 
133
 
134
  if __name__ == "__main__":
135
- main()
 
1
  """
2
+ Plot results for the Corrupted Valley tabular experiment (AntiDown).
3
 
4
+ Expects a CSV created by exp/run_corrupted_valley_tabular.py with columns:
5
  phase, phase_tag, episode, agent, total_reward, valley_visits
6
+
7
+ Supports:
8
+ --csv path to CSV file
9
+ --out output directory for PNGs
10
+ --prefix filename prefix
11
  """
12
 
13
+ from __future__ import annotations
14
+
15
  # --- twoquarks bootstrap (path-stable imports) ---
16
  import sys
17
  from pathlib import Path
 
20
  sys.path.insert(0, str(_ROOT))
21
  # -------------------------------------------------
22
 
23
+ import argparse
24
  import csv
25
  import os
26
  from collections import defaultdict
27
  from typing import Dict, List, Tuple
28
 
29
+ import matplotlib
30
+ matplotlib.use("Agg")
31
  import matplotlib.pyplot as plt
32
 
33
 
34
+ def _build_parser() -> argparse.ArgumentParser:
35
+ p = argparse.ArgumentParser(description="Plot AntiDown corrupted valley tabular results.")
36
+ p.add_argument(
37
+ "--csv",
38
+ type=str,
39
+ default="",
40
+ help="Path to results CSV. If omitted, uses TWOQUARKS_RESULTS_DIR/antidown_corrupted_valley_tabular.csv",
41
+ )
42
+ p.add_argument(
43
+ "--out",
44
+ type=str,
45
+ default="",
46
+ help="Output directory for PNGs. If omitted, uses TWOQUARKS_GRAPHICS_DIR",
47
+ )
48
+ p.add_argument(
49
+ "--prefix",
50
+ type=str,
51
+ default="AntiDown",
52
+ help="Prefix for output filenames.",
53
+ )
54
+ return p
55
 
56
 
57
+ def load_results(path: Path) -> List[Dict[str, str]]:
58
+ with path.open("r", newline="") as f:
59
+ return list(csv.DictReader(f))
 
 
 
 
60
 
61
 
62
+ def build_global_index(
63
+ rows: List[Dict[str, str]],
64
+ ) -> Tuple[Dict[int, int], Dict[int, Dict[str, List[Tuple[int, float, float]]]]]:
65
  """
66
  Returns:
67
  phase_to_max_ep: phase -> max episode index
 
87
  ep = int(r["episode"])
88
  total_reward = float(r["total_reward"])
89
  valley_visits = float(r["valley_visits"])
90
+
91
  max_ep = phase_to_max_ep[phase]
92
  global_ep = (phase - 1) * max_ep + ep
93
+
94
  data[phase][agent].append((global_ep, total_reward, valley_visits))
95
 
96
  return phase_to_max_ep, data
 
100
  data: Dict[int, Dict[str, List[Tuple[int, float, float]]]],
101
  metric_index: int,
102
  ylabel: str,
103
+ out_path: Path,
104
  ) -> None:
105
  """
106
+ metric_index: 1 -> total_reward
107
+ 2 -> valley_visits
108
  """
109
  plt.figure()
110
 
 
111
  agent_to_xy: Dict[str, Tuple[List[int], List[float]]] = {}
112
 
113
  for phase, agents in sorted(data.items()):
 
120
  agent_to_xy[agent][1].extend(ys)
121
 
122
  for agent, (xs, ys) in agent_to_xy.items():
 
123
  pairs = sorted(zip(xs, ys), key=lambda p: p[0])
124
  xs_sorted = [p[0] for p in pairs]
125
  ys_sorted = [p[1] for p in pairs]
 
129
  plt.ylabel(ylabel)
130
  plt.legend()
131
  plt.tight_layout()
132
+ plt.savefig(out_path, dpi=160)
133
  plt.close()
134
 
135
 
136
  def main() -> None:
137
+ args = _build_parser().parse_args()
138
+
139
+ quark_dir = Path(__file__).resolve().parents[1] # .../AntiDown
140
+
141
+ # Defaults via env
142
+ results_dir = Path(os.environ.get("TWOQUARKS_RESULTS_DIR", (quark_dir / "results").as_posix()))
143
+ graphics_dir = Path(os.environ.get("TWOQUARKS_GRAPHICS_DIR", (quark_dir / "graphics").as_posix()))
144
+
145
+ if args.out.strip():
146
+ graphics_dir = Path(args.out)
147
+ graphics_dir.mkdir(parents=True, exist_ok=True)
148
+
149
+ if args.csv.strip():
150
+ results_csv = Path(args.csv)
151
+ else:
152
+ results_dir.mkdir(parents=True, exist_ok=True)
153
+ results_csv = results_dir / "antidown_corrupted_valley_tabular.csv"
154
+
155
+ if not results_csv.exists():
156
+ raise FileNotFoundError(f"Results file not found: {results_csv}")
157
+
158
+ rows = load_results(results_csv)
159
+ if not rows:
160
+ raise RuntimeError(f"CSV is empty: {results_csv}")
161
 
 
162
  _, data = build_global_index(rows)
163
 
164
+ prefix = args.prefix.strip() or "AntiDown"
165
+
166
  plot_metric(
167
  data,
168
  metric_index=1,
169
  ylabel="total reward per episode",
170
+ out_path=graphics_dir / f"{prefix}_corrupted_valley_reward.png",
171
  )
172
 
173
  plot_metric(
174
  data,
175
  metric_index=2,
176
  ylabel="valley visits per episode",
177
+ out_path=graphics_dir / f"{prefix}_corrupted_valley_valley_visits.png",
178
  )
179
 
180
+ print(f"Saved plots to {graphics_dir}")
181
+
182
 
183
  if __name__ == "__main__":
184
+ main()