Skip to content

Commit 1cf26c3

Browse files
committed
chore: fix formatting issues to satisfy CI
1 parent 5a1e3af commit 1cf26c3

11 files changed

Lines changed: 126 additions & 90 deletions

scripts/check_ldc_bias.py

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,59 +8,63 @@
88

99
from src.portfolio.moead import MOEADOptimizer
1010

11+
1112
def map_to_2d(weights):
1213
w2 = weights[:, 1]
1314
w3 = weights[:, 2]
1415
x = w2 + 0.5 * w3
1516
y = (np.sqrt(3.0) / 2.0) * w3
1617
return x, y
1718

19+
1820
def verify_ldc():
19-
np.random.seed(1337) # Different seed
20-
N_points = 5000 # More points
21-
N_iterations = 200 # More iterations
21+
np.random.seed(1337) # Different seed
22+
N_points = 5000 # More points
23+
N_iterations = 200 # More iterations
2224
optimizer = MOEADOptimizer(problem=None)
23-
25+
2426
# Start with uniform Dirichlet
2527
points = np.random.dirichlet(np.ones(3), N_points)
26-
28+
2729
# Evolution loop for LDC
2830
for _ in range(N_iterations):
2931
indices = np.random.permutation(len(points))
3032
p1_idx = indices[: len(points) // 2]
3133
p2_idx = indices[len(points) // 2 :]
32-
34+
3335
new_points = np.empty_like(points)
3436
for j in range(len(p1_idx)):
3537
p1 = points[p1_idx[j]]
3638
p2 = points[p2_idx[j]]
3739
c1 = optimizer._ldc_crossover(p1, p2)
3840
c2 = optimizer._ldc_crossover(p1, p2)
39-
new_points[2*j] = c1
40-
new_points[2*j+1] = c2
41+
new_points[2 * j] = c1
42+
new_points[2 * j + 1] = c2
4143
points = new_points
4244

4345
# Plotting
4446
fig, ax = plt.subplots(figsize=(10, 8))
4547
h = np.sqrt(3) / 2
4648
ax.plot([0, 1, 0.5, 0], [0, 0, h, 0], "k-")
47-
49+
4850
x, y = map_to_2d(points)
4951
hb = ax.hexbin(x, y, gridsize=40, cmap="magma", mincnt=0, extent=(0, 1, 0, h))
50-
52+
5153
# Clipping
5254
from matplotlib.patches import Polygon
55+
5356
vertices = np.array([[0, 0], [1, 0], [0.5, h]])
5457
clip_poly = Polygon(vertices, transform=ax.transData)
5558
hb.set_clip_path(clip_poly)
56-
59+
5760
plt.title("High-Fidelity LDC Verification (N=5000, Iter=200)")
5861
plt.colorbar(hb)
59-
62+
6063
output_path = "artifacts/ldc_high_fidelity.png"
6164
os.makedirs("artifacts", exist_ok=True)
6265
plt.savefig(output_path)
6366
print(f"Plot saved to {output_path}")
6467

68+
6569
if __name__ == "__main__":
6670
verify_ldc()

scripts/experiment_evolution.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,9 @@ def run_evolution_demo():
4444
run_folder = os.path.join(OUTPUT_FOLDER, run_id)
4545
os.makedirs(run_folder, exist_ok=True)
4646

47-
print(f"Starting Multi-Variant Evolution Demo. Results will be saved to {run_folder}")
47+
print(
48+
f"Starting Multi-Variant Evolution Demo. Results will be saved to {run_folder}"
49+
)
4850

4951
# 1. Load data and calculate expected returns/cov
5052
raw_data_dict = load_data(DATA_FOLDER, ASSET_NAMES, verbose=False)

scripts/experiment_operator_bias.py

Lines changed: 32 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
from src.portfolio.moead import MOEADOptimizer
1010

11+
1112
def map_to_2d(weights):
1213
"""Maps 3-simplex weights to 2D for triangular plotting."""
1314
w2 = weights[:, 1]
@@ -16,6 +17,7 @@ def map_to_2d(weights):
1617
y = (np.sqrt(3.0) / 2.0) * w3
1718
return x, y
1819

20+
1921
def plot_triangle(ax):
2022
"""Plots the boundary of the 3-simplex and returns its vertices."""
2123
h = np.sqrt(3) / 2
@@ -26,48 +28,46 @@ def plot_triangle(ax):
2628
ax.axis("off")
2729
return vertices
2830

31+
2932
def run_simulation():
3033
np.random.seed(42)
31-
N_points = 2000
34+
N_points = 2000
3235
N_iterations = 100
3336
N_runs = 5
3437
h = np.sqrt(3) / 2
35-
38+
3639
optimizer = MOEADOptimizer(problem=None)
37-
40+
3841
combinations = [
3942
# (Crossover, Mutation, Repair, Title)
4043
("sbx", "none", "simple", "SBX + Simple Norm"),
4144
("none", "polynomial", "simple", "PolyMut + Simple Norm"),
4245
("sbx", "polynomial", "simple", "SBX + PolyMut + Simple Norm"),
43-
4446
("sbx", "none", "euclidean", "SBX + Euclidean"),
4547
("none", "polynomial", "euclidean", "PolyMut + Euclidean"),
4648
("sbx", "polynomial", "euclidean", "SBX + PolyMut + Euclidean"),
47-
4849
("simplex", "none", "none", "Simplex Crossover Only"),
4950
("none", "simplex", "none", "Simplex Mutation Only"),
5051
("simplex", "simplex", "none", "Simplex Crossover + Mutation"),
51-
5252
("ldc", "none", "none", "LDC (Latent) Crossover Only"),
5353
("none", "simplex", "none", "Simplex Mutation Only (Ref)"),
5454
("ldc", "simplex", "none", "LDC Crossover + Mutation"),
5555
]
56-
56+
5757
fig, axes = plt.subplots(4, 3, figsize=(18, 24))
5858
axes = axes.flatten()
59-
59+
6060
cmap = plt.cm.magma # Dark background colormap
61-
61+
6262
for idx, (cross, mut, repair_meth, title) in enumerate(combinations):
6363
print(f"Simulating: {title} ({N_runs} runs)...")
64-
64+
6565
ensemble_points = []
66-
66+
6767
for run_idx in range(N_runs):
6868
# 1. Start with a fresh uniform distribution per run
6969
points = np.random.dirichlet(np.ones(3), N_points)
70-
70+
7171
def apply_repair(w):
7272
if repair_meth == "euclidean":
7373
return optimizer._repair(w)
@@ -79,13 +79,13 @@ def apply_repair(w):
7979
indices = np.random.permutation(len(points))
8080
p1_idx = indices[: len(points) // 2]
8181
p2_idx = indices[len(points) // 2 :]
82-
82+
8383
new_points = np.empty_like(points)
84-
84+
8585
for j in range(len(p1_idx)):
8686
p1 = points[p1_idx[j]]
8787
p2 = points[p2_idx[j]]
88-
88+
8989
if cross == "sbx":
9090
c1 = optimizer._sbx_crossover(p1, p2)
9191
c2 = optimizer._sbx_crossover(p1, p2)
@@ -99,7 +99,7 @@ def apply_repair(w):
9999
c2 = optimizer._ldc_crossover(p1, p2)
100100
else:
101101
c1, c2 = p1.copy(), p2.copy()
102-
102+
103103
if mut == "polynomial":
104104
c1 = optimizer._polynomial_mutation(c1)
105105
c2 = optimizer._polynomial_mutation(c2)
@@ -108,48 +108,44 @@ def apply_repair(w):
108108
elif mut == "simplex":
109109
c1 = optimizer._simplex_mutation(c1, eta=0.1)
110110
c2 = optimizer._simplex_mutation(c2, eta=0.1)
111-
112-
new_points[2*j] = c1
113-
new_points[2*j+1] = c2
114-
111+
112+
new_points[2 * j] = c1
113+
new_points[2 * j + 1] = c2
114+
115115
points = new_points
116-
116+
117117
ensemble_points.append(points)
118-
118+
119119
aggregate_points = np.vstack(ensemble_points)
120-
120+
121121
# Plotting
122122
ax = axes[idx]
123-
123+
124124
# Clip to the triangle specifically
125125
vertices = plot_triangle(ax)
126126
x, y = map_to_2d(aggregate_points)
127-
127+
128128
# Use mincnt=0 to draw ALL hexagons in the extent, then clip to triangle
129-
hb = ax.hexbin(
130-
x, y,
131-
gridsize=30,
132-
cmap=cmap,
133-
mincnt=0,
134-
extent=(0, 1, 0, h)
135-
)
136-
129+
hb = ax.hexbin(x, y, gridsize=30, cmap=cmap, mincnt=0, extent=(0, 1, 0, h))
130+
137131
# Clipping: create a polygon path from vertices
138132
from matplotlib.patches import Polygon
133+
139134
clip_poly = Polygon(vertices, transform=ax.transData)
140135
hb.set_clip_path(clip_poly)
141-
136+
142137
# Add colorbar (legend) per subplot
143138
cb = fig.colorbar(hb, ax=ax, shrink=0.6, pad=0.05)
144139
cb.set_label("Solution Count", fontsize=8)
145-
140+
146141
ax.set_title(title, fontsize=12, fontweight="bold")
147-
142+
148143
plt.tight_layout()
149144
output_path = os.path.join("plots", "operator_bias_comparison.png")
150145
os.makedirs("plots", exist_ok=True)
151146
plt.savefig(output_path, dpi=150, bbox_inches="tight")
152147
print(f"\nResult saved to {output_path}")
153148

149+
154150
if __name__ == "__main__":
155151
run_simulation()

scripts/find_optimal_beta.py

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,44 @@
11
import numpy as np
22
import matplotlib.pyplot as plt
33

4+
45
def simplex_crossover(p1, p2, beta_val):
56
diff = p1 - p2
67
pos_mask = diff > 1e-9
78
neg_mask = diff < -1e-9
8-
9+
910
alpha_min = np.max(-p2[pos_mask] / diff[pos_mask]) if np.any(pos_mask) else 0.0
1011
alpha_max = np.min(-p2[neg_mask] / diff[neg_mask]) if np.any(neg_mask) else 1.0
11-
12+
1213
u = np.random.beta(beta_val, beta_val)
1314
alpha = alpha_min + u * (alpha_max - alpha_min)
14-
15+
1516
offspring = alpha * p1 + (1.0 - alpha) * p2
1617
return offspring / np.sum(offspring)
1718

19+
1820
def check_uniformity(points, D):
1921
# For a uniform distribution on the simplex, each weight w_i ~ Beta(1, D-1)
2022
# The mean is 1/D, variance is (D-1)/(D^2 * (D+1))
2123
# We can check the empirical CDF against the theoretical Beta(1, D-1)
22-
w = points[:, 0] # Check first dimension
24+
w = points[:, 0] # Check first dimension
2325
w_sorted = np.sort(w)
2426
n = len(w)
25-
emp_cdf = np.arange(1, n+1) / n
26-
theo_cdf = 1 - (1 - w_sorted)**(D-1) # CDF of Beta(1, D-1)
27-
27+
emp_cdf = np.arange(1, n + 1) / n
28+
theo_cdf = 1 - (1 - w_sorted) ** (D - 1) # CDF of Beta(1, D-1)
29+
2830
# Kolmogorov-Smirnov-like statistic
2931
return np.max(np.abs(emp_cdf - theo_cdf))
3032

33+
3134
def run_parameter_search():
3235
Ds = [2, 3, 4, 10]
3336
betas = np.linspace(0.4, 1.0, 7)
3437
n_points = 2000
3538
iterations = 100
36-
39+
3740
results = {}
38-
41+
3942
for D in Ds:
4043
print(f"Testing D={D}...")
4144
results[D] = []
@@ -45,18 +48,18 @@ def run_parameter_search():
4548
for _ in range(iterations):
4649
idx = np.random.permutation(n_points)
4750
for i in range(0, n_points, 2):
48-
p1, p2 = points[idx[i]], points[idx[i+1]]
51+
p1, p2 = points[idx[i]], points[idx[i + 1]]
4952
points[idx[i]] = simplex_crossover(p1, p2, b)
50-
points[idx[i+1]] = simplex_crossover(p1, p2, b)
51-
53+
points[idx[i + 1]] = simplex_crossover(p1, p2, b)
54+
5255
error = check_uniformity(points, D)
5356
results[D].append(error)
5457
print(f" beta={b:.2f}, error={error:.4f}")
5558

5659
# Plot
5760
plt.figure(figsize=(10, 6))
5861
for D in Ds:
59-
plt.plot(betas, results[D], 'o-', label=f"D={D}")
62+
plt.plot(betas, results[D], "o-", label=f"D={D}")
6063
plt.xlabel("Beta parameter")
6164
plt.ylabel("K-S Error (lower is better)")
6265
plt.title("Search for Optimal Beta to Preserve Uniformity")
@@ -65,5 +68,6 @@ def run_parameter_search():
6568
plt.savefig("scripts/optimal_beta_search.png")
6669
print("Optimization results saved to scripts/optimal_beta_search.png")
6770

71+
6872
if __name__ == "__main__":
6973
run_parameter_search()

0 commit comments

Comments
 (0)