From 8c3b6412998970b6b15a11ffabb4b175f753b8d5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 14 Aug 2025 06:44:45 +0000 Subject: [PATCH 1/6] Initial plan From f763bfa3a85b2ad42b3612d8e7e8432c8adb3671 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 14 Aug 2025 06:57:04 +0000 Subject: [PATCH 2/6] Replace np.sum(a * b) with a @ b in linear_algebra, career, lake_model, and mccall_model_with_separation Co-authored-by: mmcky <8263752+mmcky@users.noreply.github.com> --- lectures/career.md | 4 ++-- lectures/lake_model.md | 6 +++--- lectures/linear_algebra.md | 12 +++++++++++- lectures/mccall_model_with_separation.md | 2 +- 4 files changed, 17 insertions(+), 7 deletions(-) diff --git a/lectures/career.md b/lectures/career.md index e2446cad1..c2f8ef252 100644 --- a/lectures/career.md +++ b/lectures/career.md @@ -206,8 +206,8 @@ class CareerWorkerProblem: self.F_probs = BetaBinomial(grid_size - 1, F_a, F_b).pdf() self.G_probs = BetaBinomial(grid_size - 1, G_a, G_b).pdf() - self.F_mean = np.sum(self.θ * self.F_probs) - self.G_mean = np.sum(self.ϵ * self.G_probs) + self.F_mean = self.θ @ self.F_probs + self.G_mean = self.ϵ @ self.G_probs # Store these parameters for str and repr methods self._F_a, self._F_b = F_a, F_b diff --git a/lectures/lake_model.md b/lectures/lake_model.md index dd801a1a5..0f61f62bc 100644 --- a/lectures/lake_model.md +++ b/lectures/lake_model.md @@ -699,7 +699,7 @@ def _update_bellman(α, β, γ, c, σ, w_vec, p_vec, V, V_new, U): V_new[w_idx] = u(w, σ) + β * ((1 - α) * V[w_idx] + α * U) U_new = u(c, σ) + β * (1 - γ) * U + \ - β * γ * np.sum(np.maximum(U, V) * p_vec) + β * γ * (np.maximum(U, V) @ p_vec) return U_new @@ -836,8 +836,8 @@ def compute_steady_state_quantities(c, τ): u, e = x # Compute steady state welfare - w = np.sum(V * p_vec * (w_vec - τ > w_bar)) / np.sum(p_vec * (w_vec - - τ > w_bar)) + mask = (w_vec - τ > w_bar) + w = (V * p_vec * mask) @ np.ones_like(p_vec) / (p_vec * mask) @ np.ones_like(p_vec) welfare = e * w + u * U return e, u, welfare diff --git a/lectures/linear_algebra.md b/lectures/linear_algebra.md index d7131dfc4..6ca14c01d 100644 --- a/lectures/linear_algebra.md +++ b/lectures/linear_algebra.md @@ -246,13 +246,23 @@ Continuing on from the previous example, the inner product and norm can be compu follows ```{code-cell} python3 -np.sum(x * y) # Inner product of x and y +np.sum(x * y) # Inner product of x and y, method 1 ``` +```{code-cell} python3 +x @ y # Inner product of x and y, method 2 (preferred) +``` + +The `@` operator is preferred because it uses optimized BLAS libraries that implement fused multiply-add operations, providing better performance and numerical accuracy compared to the separate multiply and sum operations. + ```{code-cell} python3 np.sqrt(np.sum(x**2)) # Norm of x, take one ``` +```{code-cell} python3 +np.sqrt(x @ x) # Norm of x, take two (preferred) +``` + ```{code-cell} python3 np.linalg.norm(x) # Norm of x, take two ``` diff --git a/lectures/mccall_model_with_separation.md b/lectures/mccall_model_with_separation.md index fe7d2c48a..677b11a09 100644 --- a/lectures/mccall_model_with_separation.md +++ b/lectures/mccall_model_with_separation.md @@ -345,7 +345,7 @@ def update(model, v, d): " One update on the Bellman equations. " α, β, c, w, q = model.α, model.β, model.c, model.w, model.q v_new = u(w) + β * ((1 - α) * v + α * d) - d_new = jnp.sum(jnp.maximum(v, u(c) + β * d) * q) + d_new = jnp.maximum(v, u(c) + β * d) @ q return v_new, d_new @jax.jit From 860c4eedf7879df36a022ff5a9a6f757adfd9aa2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 14 Aug 2025 07:00:56 +0000 Subject: [PATCH 3/6] Additional replacements: mix_model, kalman, and rand_resp files Co-authored-by: mmcky <8263752+mmcky@users.noreply.github.com> --- lectures/kalman.md | 6 ++++-- lectures/mix_model.md | 2 +- lectures/rand_resp.md | 6 ++++-- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/lectures/kalman.md b/lectures/kalman.md index fd24abbff..20c59cebc 100644 --- a/lectures/kalman.md +++ b/lectures/kalman.md @@ -783,8 +783,10 @@ e2 = np.empty(T-1) for t in range(1, T): kn.update(y[:,t]) - e1[t-1] = np.sum((x[:, t] - kn.x_hat.flatten())**2) - e2[t-1] = np.sum((x[:, t] - A @ x[:, t-1])**2) + diff1 = x[:, t] - kn.x_hat.flatten() + diff2 = x[:, t] - A @ x[:, t-1] + e1[t-1] = diff1 @ diff1 + e2[t-1] = diff2 @ diff2 fig, ax = plt.subplots(figsize=(9,6)) ax.plot(range(1, T), e1, 'k-', lw=2, alpha=0.6, diff --git a/lectures/mix_model.md b/lectures/mix_model.md index 635061a6d..31ca4d875 100644 --- a/lectures/mix_model.md +++ b/lectures/mix_model.md @@ -820,7 +820,7 @@ def learn_x_bayesian(observations, α0, β0, grid_size=2000): post = np.exp(log_post) post /= post.sum() - μ_path[t + 1] = np.sum(x_grid * post) + μ_path[t + 1] = x_grid @ post return μ_path diff --git a/lectures/rand_resp.md b/lectures/rand_resp.md index 1986812f2..a87f23422 100644 --- a/lectures/rand_resp.md +++ b/lectures/rand_resp.md @@ -235,14 +235,16 @@ class Comparison: rd_answer = sample * spinner + (1 - sample) * (1 - spinner) n1 = rd_answer.sum(axis=1) pi_hat = (p - 1) / (2 * p - 1) + n1 / n / (2 * p - 1) - mse_rd[p] = np.sum((pi_hat - A)**2) + diff_rd = pi_hat - A + mse_rd[p] = diff_rd @ diff_rd for inum, irow in df.iterrows(): truth_a = np.random.rand(size, self.n) <= irow.T_a truth_b = np.random.rand(size, self.n) <= irow.T_b trad_answer = sample * truth_a + (1 - sample) * (1 - truth_b) pi_trad = trad_answer.sum(axis=1) / n df.loc[inum, 'Bias'] = pi_trad.mean() - A - mse_trad = np.sum((pi_trad - A)**2) + diff_trad = pi_trad - A + mse_trad = diff_trad @ diff_trad for p in self.p_arr: df.loc[inum, p] = (mse_rd[p] / mse_trad).round(2) df = df.set_index(["T_a", "T_b", "Bias"]).rename(columns=self.p_map) From 9029534c9bdc69915b30ff4ccd4f46f0884d9a60 Mon Sep 17 00:00:00 2001 From: Humphrey Yang <39026988+HumphreyYang@users.noreply.github.com> Date: Sat, 16 Aug 2025 10:18:20 +1000 Subject: [PATCH 4/6] Update lectures/lake_model.md --- lectures/lake_model.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lectures/lake_model.md b/lectures/lake_model.md index 0f61f62bc..315a2e47e 100644 --- a/lectures/lake_model.md +++ b/lectures/lake_model.md @@ -837,7 +837,7 @@ def compute_steady_state_quantities(c, τ): # Compute steady state welfare mask = (w_vec - τ > w_bar) - w = (V * p_vec * mask) @ np.ones_like(p_vec) / (p_vec * mask) @ np.ones_like(p_vec) + w = ((V * p_vec * mask) @ np.ones_like(p_vec)) / ((p_vec * mask) @ np.ones_like(p_vec)) welfare = e * w + u * U return e, u, welfare From 238333273f27eb993870787fe99e784d96753d05 Mon Sep 17 00:00:00 2001 From: Humphrey Yang <39026988+HumphreyYang@users.noreply.github.com> Date: Sat, 16 Aug 2025 10:18:29 +1000 Subject: [PATCH 5/6] Update lectures/linear_algebra.md --- lectures/linear_algebra.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lectures/linear_algebra.md b/lectures/linear_algebra.md index 6ca14c01d..680dbf010 100644 --- a/lectures/linear_algebra.md +++ b/lectures/linear_algebra.md @@ -264,7 +264,7 @@ np.sqrt(x @ x) # Norm of x, take two (preferred) ``` ```{code-cell} python3 -np.linalg.norm(x) # Norm of x, take two +np.linalg.norm(x) # Norm of x, take three ``` ### Span From 36595e74728771ee5fa7ae6d8582c9ea90e4135d Mon Sep 17 00:00:00 2001 From: Humphrey Yang Date: Sat, 16 Aug 2025 10:20:06 +1000 Subject: [PATCH 6/6] revert change in rand_resp --- lectures/rand_resp.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lectures/rand_resp.md b/lectures/rand_resp.md index a87f23422..1986812f2 100644 --- a/lectures/rand_resp.md +++ b/lectures/rand_resp.md @@ -235,16 +235,14 @@ class Comparison: rd_answer = sample * spinner + (1 - sample) * (1 - spinner) n1 = rd_answer.sum(axis=1) pi_hat = (p - 1) / (2 * p - 1) + n1 / n / (2 * p - 1) - diff_rd = pi_hat - A - mse_rd[p] = diff_rd @ diff_rd + mse_rd[p] = np.sum((pi_hat - A)**2) for inum, irow in df.iterrows(): truth_a = np.random.rand(size, self.n) <= irow.T_a truth_b = np.random.rand(size, self.n) <= irow.T_b trad_answer = sample * truth_a + (1 - sample) * (1 - truth_b) pi_trad = trad_answer.sum(axis=1) / n df.loc[inum, 'Bias'] = pi_trad.mean() - A - diff_trad = pi_trad - A - mse_trad = diff_trad @ diff_trad + mse_trad = np.sum((pi_trad - A)**2) for p in self.p_arr: df.loc[inum, p] = (mse_rd[p] / mse_trad).round(2) df = df.set_index(["T_a", "T_b", "Bias"]).rename(columns=self.p_map)