fix: dates

This commit is contained in:
Barrett Ruth 2025-05-22 18:40:46 -05:00
parent b81f0fa3c4
commit ffc8ce9a4c
8 changed files with 1132 additions and 18535 deletions

18507
public/d3.js vendored

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,693 @@
import { getTopicColor } from "../../src/utils/colors.js";
function urlToTopic() {
const path = window.location.pathname;
const pathParts = path.split("/");
return pathParts[2];
}
function setUpParameters(render, parameters, modelPrefix) {
parameters.forEach((param) => {
const slider = document.getElementById(`slider${modelPrefix}${param}`);
slider.oninput = function () {
slider.previousElementSibling.innerText = this.value;
render();
};
});
return parameters.map((param) => {
return parseFloat(
document.getElementById(`output${modelPrefix}${param}`).textContent,
);
});
}
function drawSolowGraph() {
const L = 150,
K_MAX = 500,
margin = { top: 20, right: 30, bottom: 20, left: 50 };
const [A, d, s, alpha] = setUpParameters(
drawSolowGraph,
["A", "d", "s", "alpha"],
"S",
);
const solowOutput = (K) => A * Math.pow(K, alpha) * Math.pow(L, 1 - alpha);
const solowDepreciation = (K) => d * K;
const solowInvestment = (Y) => s * Y;
const container = document.getElementById("solow-visualization");
const width = container.clientWidth - margin.left - margin.right;
const height = container.clientHeight - margin.top - margin.bottom;
console.log(width, height);
container.innerHTML = "";
const svg = d3
.select("#solow-visualization")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", `translate(${margin.left}, ${margin.top})`);
const x = d3.scaleLinear().domain([0, K_MAX]).range([0, width]);
svg
.append("g")
.attr("transform", `translate(0, ${height})`)
.call(d3.axisBottom(x))
.append("text")
.attr("fill", "#000")
.attr("x", width + 10)
.attr("y", -10)
.style("text-anchor", "end")
.style("font-size", "1.5em")
.text("K");
const Y_MAX = solowOutput(K_MAX) + K_MAX / 10;
const y = d3.scaleLinear().domain([0, Y_MAX]).range([height, 0]);
svg
.append("g")
.call(d3.axisLeft(y))
.append("text")
.attr("fill", "#000")
.attr("x", 0)
.attr("y", -10)
.style("text-anchor", "start")
.style("font-size", "1.5em")
.text("Y");
const outputData = Array.from({ length: K_MAX }, (_, k) => ({
K: k,
Y: solowOutput(k),
}));
svg
.append("path")
.datum(outputData)
.attr("fill", "none")
.attr("stroke", getTopicColor(urlToTopic()))
.attr("stroke-width", 2)
.attr(
"d",
d3
.line()
.x((d) => x(d.K))
.y((d) => y(d.Y)),
);
svg
.append("foreignObject")
.attr("width", "2em")
.attr("height", "2em")
.attr("x", x(K_MAX))
.attr("y", y(outputData[K_MAX - 1].Y))
.append("xhtml:body")
.style("font-size", "0.75em")
.html(`\\(Y\\)`);
const depreciationData = Array.from({ length: K_MAX }, (_, k) => ({
K: k,
Y: solowDepreciation(k),
}));
svg
.append("path")
.datum(depreciationData)
.attr("fill", "none")
.attr("stroke", "red")
.attr("stroke-width", 2)
.attr(
"d",
d3
.line()
.x((d) => x(d.K))
.y((d) => y(d.Y)),
);
svg
.append("foreignObject")
.attr("width", "2em")
.attr("height", "2em")
.attr("x", x(K_MAX))
.attr("y", y(depreciationData[K_MAX - 1].Y))
.append("xhtml:body")
.style("font-size", "0.75em")
.append("xhtml:div")
.html("\\(\\bar{d}K\\)");
const investmentData = outputData.map((d) => ({
K: d.K,
Y: solowInvestment(d.Y),
}));
svg
.append("path")
.datum(investmentData)
.attr("fill", "none")
.attr("stroke", "purple")
.attr("stroke-width", 2)
.attr(
"d",
d3
.line()
.x((d) => x(d.K))
.y((d) => y(d.Y)),
);
const labelFO = svg
.append("foreignObject")
.attr("width", 16)
.attr("height", 20)
.attr("x", x(K_MAX))
.attr("y", y(investmentData[K_MAX - 1].Y))
.append("xhtml:span")
.attr("class", "latex-label");
function renderLabel() {
katex.render("I", labelFO.node(), {
displayMode: false,
throwOnError: false,
});
}
renderLabel();
// svg
// .append("foreignObject")
// .attr("width", "1em")
// .attr("height", "2em")
// .attr("x", x(K_MAX))
// .attr("y", y(investmentData[K_MAX - 1].Y))
// .append("xhtml:body")
// .style("font-size", "0.75em")
// .html("\\(I\\)");
const k_star = L * Math.pow((s * A) / d, 1 / (1 - alpha));
svg
.append("line")
.attr("x1", x(k_star))
.attr("y1", y((d * k_star) / s))
.attr("x2", x(k_star))
.attr("y2", y(0))
.attr("stroke", "black")
.attr("stroke-width", 1)
.attr("stroke-dasharray", "5,5");
const y_star = solowOutput(k_star);
svg
.append("foreignObject")
.attr("width", "20em")
.attr("height", "2em")
.attr("x", x(k_star) - 40)
.attr("y", y(y_star) - 40)
.append("xhtml:body")
.style("font-size", "0.75em")
.html(`(${k_star.toFixed(0)}, ${y_star.toFixed(0)})`);
}
const formatNumber = (num) => {
return `~${num.toExponential(0)}`;
};
const normalFont = `style="font-weight: normal"`;
const updateRomerTable = (romerData) => {
const tableHeader = document.getElementById("romer-table-header");
const rowA_t = document.getElementById("row-A_t");
const rowY_t = document.getElementById("row-Y_t");
tableHeader.innerHTML = `<th ${normalFont}>t</th>`;
rowA_t.innerHTML = `<td class="romer-table-at">A_t</td>`;
rowY_t.innerHTML = `<td class="romer-table-yt">Y_t</td>`;
romerData.forEach((d) => {
if (d.year % 20 === 0 || d.year === 1) {
tableHeader.innerHTML += `<th ${normalFont}>${d.year}</th>`;
rowA_t.innerHTML += `<td>${formatNumber(d.A)}</td>`;
rowY_t.innerHTML += `<td>${formatNumber(d.Y)}</td>`;
}
});
};
function drawRomerGraph() {
const T_MAX = 100,
margin = { top: 20, right: 100, bottom: 20, left: 50 };
const [z, L, l, A0] = setUpParameters(
drawRomerGraph,
["z", "L", "l", "A0"],
"R",
);
const container = document.getElementById("romer-visualization");
const width = container.clientWidth - margin.left - margin.right;
const height = container.clientHeight - margin.top - margin.bottom;
container.innerHTML = "";
const svg = d3
.select("#romer-visualization")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", `translate(${margin.left}, ${margin.top})`);
let A = A0;
const romerData = [];
for (let t = 1; t <= T_MAX; ++t) {
const A_t = A * (1 + z * l * L);
const Y_t = A_t * (1 - l) * L;
romerData.push({ year: t, A: A_t, Y: Math.log10(Y_t) });
A = A_t;
}
const x = d3.scaleLinear().domain([1, T_MAX]).range([0, width]);
svg
.append("g")
.attr("transform", `translate(0, ${height})`)
.call(d3.axisBottom(x))
.append("text")
.attr("fill", "#000")
.attr("x", width + 10)
.attr("y", -10)
.style("text-anchor", "end")
.style("font-size", "1.5em")
.text("t");
const y = d3
.scaleLinear()
.domain([0, romerData[romerData.length - 1].Y])
.range([height, 0]);
svg
.append("g")
.call(d3.axisLeft(y).ticks(10, d3.format(".1s")))
.append("text")
.attr("fill", "#000")
.attr("x", 0)
.attr("y", -10)
.style("text-anchor", "start")
.style("font-size", "1.5em")
.text("log(Y)");
svg
.append("path")
.datum(romerData)
.attr("fill", "none")
.attr("stroke", getTopicColor(urlToTopic()))
.attr("stroke-width", 2)
.attr(
"d",
d3
.line()
.x((d) => x(d.year))
.y((d) => y(d.Y)),
);
svg
.append("foreignObject")
.attr("width", "4em")
.attr("height", "2em")
.attr("x", x(T_MAX))
.attr("y", y(romerData[T_MAX - 1].Y))
.append("xhtml:body")
.style("font-size", "0.75em")
.html(`\\(log_{10}Y\\)`);
updateRomerTable(romerData);
}
function drawRomerlGraph() {
const T_MAX = 100,
z = 0.01,
L = 50,
A0 = 50,
margin = { top: 20, right: 100, bottom: 20, left: 50 };
const [l, t0] = setUpParameters(drawRomerlGraph, ["lChange", "t0"], "");
const container = document.getElementById("romer-lchange-visualization");
const width = container.clientWidth - margin.left - margin.right;
const height = container.clientHeight - margin.top - margin.bottom;
container.innerHTML = "";
const svg = d3
.select("#romer-lchange-visualization")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", `translate(${margin.left}, ${margin.top})`);
let A = A0,
l_ = 0.1;
const romerData = [];
for (let t = 1; t <= t0; ++t) {
const A_t = A * (1 + z * l_ * L);
const Y_t = A_t * (1 - l_) * L;
romerData.push({ year: t, A: A_t, Y: Math.log10(Y_t) });
A = A_t;
}
for (let t = t0 + 1; t <= T_MAX; ++t) {
const A_t = A * (1 + z * l * L);
const Y_t = A_t * (1 - l) * L;
romerData.push({ year: t, A: A_t, Y: Math.log10(Y_t) });
A = A_t;
}
const x = d3.scaleLinear().domain([1, T_MAX]).range([0, width]);
svg
.append("g")
.attr("transform", `translate(0, ${height})`)
.call(d3.axisBottom(x))
.append("text")
.attr("fill", "#000")
.attr("x", width + 10)
.attr("y", -10)
.style("text-anchor", "end")
.style("font-size", "1.5em")
.text("t");
const y = d3
.scaleLinear()
.domain([0, romerData[romerData.length - 1].Y])
.range([height, 0]);
svg
.append("g")
.call(d3.axisLeft(y).ticks(10, d3.format(".1s")))
.append("text")
.attr("fill", "#000")
.attr("x", 0)
.attr("y", -10)
.style("text-anchor", "start")
.style("font-size", "1.5em")
.text("log(Y)");
svg
.append("path")
.datum(romerData)
.attr("fill", "none")
.attr("stroke", getTopicColor(urlToTopic()))
.attr("stroke-width", 2)
.attr(
"d",
d3
.line()
.x((d) => x(d.year))
.y((d) => y(d.Y)),
);
svg
.append("line")
.attr("x1", x(t0))
.attr("y1", y(romerData[T_MAX - 1].Y))
.attr("x2", x(t0))
.attr("y2", height)
.attr("stroke", "black")
.attr("stroke-width", 1)
.attr("stroke-dasharray", "4");
svg
.append("foreignObject")
.attr("width", "5em")
.attr("height", "2em")
.attr("x", x(0) + 15)
.attr("y", y(romerData[0].Y))
.append("xhtml:body")
.style("font-size", "0.6em")
.html(`\\(\\bar{l}_0=${l_}\\)`);
svg
.append("foreignObject")
.attr("width", "5em")
.attr("height", "2em")
.attr("x", x(t0) + 15)
.attr("y", y(romerData[t0].Y))
.append("xhtml:body")
.style("font-size", "0.6em")
.html(`\\(\\bar{l}_1=${l}\\)`);
svg
.append("foreignObject")
.attr("width", "4em")
.attr("height", "2em")
.attr("x", x(T_MAX))
.attr("y", y(romerData[T_MAX - 1].Y))
.append("xhtml:body")
.style("font-size", "0.75em")
.html(`\\(log_{10}Y\\)`);
}
function calculateRomerSolowData(
T_MAX,
L,
l,
A0,
alpha,
s,
d,
z,
t0 = Infinity,
L0,
l0,
alpha0,
z0,
) {
let A = A0,
K_t = 1,
romerSolowData = [];
for (let t = 1; t <= T_MAX; ++t) {
if (t > t0) {
alpha = alpha0;
z = z0;
l = l0;
L = L0;
}
const Y_t = A * Math.pow(K_t, alpha) * Math.pow((1 - l) * L, 1 - alpha);
const A_t = A * (1 + z * l * L);
K_t = K_t + s * Y_t - d * K_t;
romerSolowData.push({ year: t, A: A_t, K: K_t, Y: Math.log10(Y_t) });
A = A_t;
}
return romerSolowData;
}
function drawRomerSolowGraph() {
const T_MAX = 100,
margin = { top: 20, right: 100, bottom: 20, left: 50 };
const [z, l, L, A0, s, d, alpha] = setUpParameters(
drawRomerSolowGraph,
["z", "l", "L", "A0", "s", "d", "alpha"],
"RS",
);
const container = document.getElementById("romer-solow-visualization");
const width = container.clientWidth - margin.left - margin.right;
const height = container.clientHeight - margin.top - margin.bottom;
container.innerHTML = "";
const svg = d3
.select("#romer-solow-visualization")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", `translate(${margin.left}, ${margin.top})`);
const romerSolowData = calculateRomerSolowData(
T_MAX,
L,
l,
A0,
alpha,
s,
d,
z,
);
const x = d3.scaleLinear().domain([1, T_MAX]).range([0, width]);
svg
.append("g")
.attr("transform", `translate(0, ${height})`)
.call(d3.axisBottom(x))
.append("text")
.attr("fill", "#000")
.attr("x", width + 10)
.attr("y", -10)
.style("text-anchor", "end")
.style("font-size", "1.5em")
.text("t");
const y = d3
.scaleLinear()
.domain([0, romerSolowData[romerSolowData.length - 1].Y])
.range([height, 0]);
svg
.append("g")
.call(d3.axisLeft(y).ticks(10, d3.format(".1s")))
.append("text")
.attr("fill", "#000")
.attr("x", 0)
.attr("y", -10)
.style("text-anchor", "start")
.style("font-size", "1.5em")
.text("log(Y)");
svg
.append("path")
.datum(romerSolowData)
.attr("fill", "none")
.attr("stroke", getTopicColor(urlToTopic()))
.attr("stroke-width", 2)
.attr(
"d",
d3
.line()
.x((d) => x(d.year))
.y((d) => y(d.Y)),
);
svg
.append("foreignObject")
.attr("width", "4em")
.attr("height", "2em")
.attr("x", x(T_MAX))
.attr("y", y(romerSolowData[T_MAX - 1].Y))
.append("xhtml:body")
.style("font-size", "0.75em")
.html(`\\(log_{10}Y\\)`);
}
function drawRomerSolowChangeGraph() {
const T_MAX = 100,
margin = { top: 20, right: 100, bottom: 20, left: 50 },
s = 0.2,
d = 0.2,
A0 = 50,
alpha = 0.33,
l = 0.5,
L = 100,
z = 0.5;
const [z0, l0, L0, alpha0, t0] = setUpParameters(
drawRomerSolowChangeGraph,
["z0", "l0", "L0", "alpha0", "t0"],
"RSC",
);
const container = document.getElementById("romer-solow-change-visualization");
const width = container.clientWidth - margin.left - margin.right;
const height = container.clientHeight - margin.top - margin.bottom;
container.innerHTML = "";
const svg = d3
.select("#romer-solow-change-visualization")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", `translate(${margin.left}, ${margin.top})`);
const romerSolowData = calculateRomerSolowData(
T_MAX,
L,
l,
A0,
alpha,
s,
d,
z,
t0,
L0,
l0,
alpha0,
z0,
);
const x = d3.scaleLinear().domain([1, T_MAX]).range([0, width]);
svg
.append("g")
.attr("transform", `translate(0, ${height})`)
.call(d3.axisBottom(x))
.append("text")
.attr("fill", "#000")
.attr("x", width + 10)
.attr("y", -10)
.style("text-anchor", "end")
.style("font-size", "1.5em")
.text("t");
const y = d3
.scaleLinear()
.domain([0, romerSolowData[romerSolowData.length - 1].Y])
.range([height, 0]);
svg
.append("g")
.call(d3.axisLeft(y).ticks(10, d3.format(".1s")))
.append("text")
.attr("fill", "#000")
.attr("x", 0)
.attr("y", -10)
.style("text-anchor", "start")
.style("font-size", "1.5em")
.text("log(Y)");
svg
.append("path")
.datum(romerSolowData)
.attr("fill", "none")
.attr("stroke", getTopicColor(urlToTopic()))
.attr("stroke-width", 2)
.attr(
"d",
d3
.line()
.x((d) => x(d.year))
.y((d) => y(d.Y)),
);
svg
.append("line")
.attr("x1", x(t0))
.attr("y1", y(romerSolowData[T_MAX - 1].Y))
.attr("x2", x(t0))
.attr("y2", height)
.attr("stroke", "black")
.attr("stroke-width", 1)
.attr("stroke-dasharray", "4");
svg
.append("foreignObject")
.attr("width", "4em")
.attr("height", "2em")
.attr("x", x(T_MAX))
.attr("y", y(romerSolowData[T_MAX - 1].Y))
.append("xhtml:body")
.style("font-size", "0.75em")
.html(`\\(log_{10}Y\\)`);
}
document.addEventListener("DOMContentLoaded", function () {
drawSolowGraph();
drawRomerGraph();
drawRomerlGraph();
drawRomerSolowGraph();
drawRomerSolowChangeGraph();
window.onresize = () => {
drawSolowGraph();
drawRomerGraph();
drawRomerlGraph();
drawRomerSolowGraph();
drawRomerSolowChangeGraph();
};
});

View file

@ -139,3 +139,14 @@ pre * {
.astro-code {
font-size: 0.8em !important;
}
.post-article h1:has(.date) {
display: flex;
justify-content: space-between;
align-items: baseline;
}
.post-article h1 .date {
font-weight: normal;
}

View file

@ -7,6 +7,8 @@ const postsCollection = defineCollection({
description: z.string().optional(),
date: z.string().optional(),
useKatex: z.boolean().optional().default(false),
useD3: z.boolean().optional().default(false),
scripts: z.array(z.string()).optional(),
}),
});

View file

@ -1,10 +1,10 @@
---
title: "leetcode daily"
date: "04/13/2024"
date: "11/9/2024"
useKatex: true
---
# [count good numbers](https://leetcode.com/problems/count-good-numbers/submissions/1605647445/?envType=daily-question&envId=2025-04-13) 04/13/2024
# [count good numbers](https://leetcode.com/problems/count-good-numbers) <span class="date">13/12/2024</span>
## understanding the problem
@ -12,7 +12,7 @@ This is a combinatoric problem at heart. You have some slots for evens and some
## doing it
So, what's the answer? If we know which slots we have and the number of choices for them, we're done. Since this is leetcode, they don't let you think—they just give you the answer. You have 2 types of slots (even and odd indices) with 5 (${0,2,4,6,8}$) and 4 (${2,3,5,7}$) choices respectively. Therefore, the answer is: $5^{\text{# even slots}}\cdot4^{\text{# odd slots}}$ By counting or with small cases, we have $\lceil\frac{n}{2}\rceil$ even slots and $\lfloor\frac{n}{2}\rfloor$ odd slots. Let's submit it!
So, what's the answer? If we know which slots we have and the number of choices for them, we're done. Since this is leetcode, they don't let you think—they just give you the answer. You have 2 types of slots (even and odd indices) with 5 (${0,2,4,6,8}$) and 4 (${2,3,5,7}$) choices respectively. Therefore, the answer is: $5^\text{\# even slots}\cdot 4^\text{\# odd slots}$. By counting or with small cases, we have $\lceil\frac{n}{2}\rceil$ even slots and $\lfloor\frac{n}{2}\rfloor$ odd slots. Let's submit it!
And.... TLE. Checking _everything_ when you submit your code—in this case, constraint $n\leq 10^{16}$ informs us of something suspect. In the worst case, $\frac{n}{2}\approx n^{14}$. This is far too many multiplications, so we can leverage binary exponentiation instead (and probably should've been the whole time!). Don't forget the mod.
@ -38,7 +38,7 @@ public:
};
```
# [minimum number of operations to make array distinct](https://leetcode.com/problems/minimum-number-of-operations-to-make-elements-in-array-distinc) 04/09/2024
# [minimum number of operations to make array distinct](https://leetcode.com/problems/minimum-number-of-operations-to-make-elements-in-array-distinc) <span class="date">04/10/2024</span>
## understanding the problem
@ -55,7 +55,7 @@ The solution is optimal, considering the least amount of elements possible in:
- <u>Time Complexity</u>: $O(n)$
- <u>Space Complexity</u>: $\Theta(1)$
# [count the number of fair pairs](https://leetcode.com/problems/count-the-number-of-fair-pairs/) 09/13/2024
# [count the number of fair pairs](https://leetcode.com/problems/count-the-number-of-fair-pairs/) <span class="date">10/12/2024</span>
## problem statement
@ -145,7 +145,7 @@ The second approach is _asymptotically_ equivalent. However, it's still worth co
respect to the second approach.
- <u>Space Complexity</u>: $\Theta(1)$ for both.
# [most beautiful item for each query](https://leetcode.com/problems/most-beautiful-item-for-each-query/description/) 09/12/2024
# [most beautiful item for each query](https://leetcode.com/problems/most-beautiful-item-for-each-query/description/) <span class="date">09/12/2024</span>
## problem statement
@ -212,7 +212,7 @@ Let `n=len(items)` and `m=len(queries)`. There may be more items than queries, o
allocated. If `queries`/`items` cannot be modified in-place, increase the
space complexity by $m$/$n$ respectively.
# [shortest subarray with or at least k ii](https://leetcode.com/problems/shortest-subarray-with-or-at-least-k-ii/description/) 09/11/2024
# [shortest subarray with or at least k ii](https://leetcode.com/problems/shortest-subarray-with-or-at-least-k-ii/description/) <span class="date">09/11/2024</span>
## problem statement
@ -285,7 +285,7 @@ Note that the size of the frequency map is bounded by $lg_{2}({10^9})\approx30$.
considered at least once and takes $O(1)$ work each to find the element-wise
bitwise OR.
# [minimum array end](https://leetcode.com/problems/minimum-array-end/) 09/10/2024
# [minimum array end](https://leetcode.com/problems/minimum-array-end/) <span class="date">09/10/2024</span>
## problem statement

View file

@ -2,6 +2,8 @@
title: "models of production"
date: "22/06/2024"
useKatex: true
useD3: true
scripts: ["/scripts/models-of-production.js"]
---
This post offers a basic introduction to the Solow, Romer, and Romer-Solow economic models, as taught by [Vladimir Smirnyagin](https://www.vladimirsmirnyagin.com/) and assisted by [Donghyun Suh](https://www.donghyunsuh.com/) in Intermediate Macroeconomics (ECON 3020) during the Spring semester of 2024 at the University of Virginia.
@ -43,7 +45,75 @@ $$Y_t=F(K_t,L_t)=\bar{A}K_t^{\frac{1}{3}} \bar{L}^{\frac{2}{3}}$$
Utilizing this simplification and its graphical representation below, output is clearly characterized by the cube root of capital:
$\bar{A}:$ 1.00 $\bar{d}:$ 0.50 $\bar{s}:$ 0.50 $\alpha:$ 0.33
<div class="graph">
<div id="solow-visualization"></div>
</div>
<div class="sliders">
<div style="padding-right: 20px">
<ul>
<li>
<div class="slider">
<label for="sliderSA">$\bar{A}:$</label>
<span id="outputSA">1.00</span>
<input
type="range"
id="sliderSA"
min="0.1"
max="2"
step="0.01"
value="1"
/>
</div>
</li>
<li>
<div class="slider">
<label for="sliderSd">$\bar{d}:$</label>
<span id="outputSd">0.50</span>
<input
type="range"
id="sliderSd"
min="0.01"
max="0.99"
step="0.01"
value="0.50"
/>
</div>
</li>
</ul>
</div>
<div style="padding-left: 20px">
<ul start="3">
<li>
<div class="slider">
<label for="sliderSs">$\bar{s}:$</label>
<span id="outputSs">0.50</span>
<input
type="range"
id="sliderSs"
min="0.01"
max="0.99"
step="0.01"
value="0.50"
/>
</div>
</li>
<li>
<div class="slider">
<label for="sliderSalpha">$\alpha:$</label>
<span id="outputSalpha">0.33</span>
<input
type="range"
id="sliderSalpha"
min="0.01"
max="0.99"
step="0.01"
value="0.33"
/>
</div>
</li>
</ul>
</div>
</div>
When investment is completely disincentivized by depreciation (in other words, $sY_t=\bar{d}K_t$), the economy equilibrates at a so-called "steady-state" with equilibrium $(K_t,Y_t)=(K_t^*,Y_t^*)$.
@ -122,10 +192,90 @@ Finally, we have a model:
A visualization of the Romer Model shows that the economy grows exponentially—production knows no bounds ([_ceteris paribus_](https://en.wikipedia.org/wiki/Ceteris_paribus), of course). A graph of $log_{10}(Y_t)$ can be seen below:
$\bar{z}:$ 0.50 $\bar{L}:$ 505 $\bar{l}:$ 0.50 $\bar{A}_0:$ 500
<div class="graph">
<div id="romer-visualization"></div>
</div>
<div class="sliders">
<div style="padding-right: 20px">
<ul>
<li>
<div class="slider">
<label for="sliderRz">$\bar{z}:$</label>
<span id="outputRz">0.50</span>
<input
type="range"
id="sliderRz"
min="0.1"
max="0.99"
step="0.01"
value="0.50"
/>
</div>
</li>
<li>
<div class="slider">
<label for="sliderRL">$\bar{L}:$</label>
<span id="outputRL">505</span>
<input
type="range"
id="sliderRL"
min="10"
max="1000"
step="19"
value="505"
/>
</div>
</li>
</ul>
</div>
<div style="padding-left: 20px">
<ul start="3">
<li>
<div class="slider">
<label for="sliderRl">$\bar{l}:$</label>
<span id="outputRl">0.50</span>
<input
type="range"
id="sliderRl"
min="0.01"
max="0.99"
step="0.01"
value="0.50"
/>
</div>
</li>
<li>
<div class="slider">
<label for="sliderRA0">$\bar{A}_0:$</label>
<span id="outputRA0">500</span>
<input
type="range"
id="sliderRA0"
min="0"
max="1000"
step="100"
value="500"
/>
</div>
</li>
</ul>
</div>
</div>
Playing with the sliders, this graph may seem underwhelming in comparison to the Solow Model. However, on a logarithmic scale, small changes in the parameters lead to massive changes in the growth rate of ideas and economices:
<div class="romer-table-container">
<table id="romer-table">
<thead>
<tr id="romer-table-header"></tr>
</thead>
<tbody>
<tr id="row-A_t"></tr>
<tr id="row-Y_t"></tr>
</tbody>
</table>
</div>
### solving the model
To find the output in terms of exogenous parameters, first note that
@ -152,7 +302,47 @@ Further, all economy continually and perpetually grow along a constant "Balanced
Changes in the growth rate of ideas, then, alter the growth rate of output itself—in this case, parameters $\bar{l}, \bar{z}$, and $\bar{L}$. This is best exemplified by comparing the growth rate before and and after a parameter changes. In the below example, a larger $\bar{l}$ initially drops output due to less workers being allocated to production. Soon after, though, output recovers along a "higher" Balanced Growth Path.
$\bar{l}_1:$ 0.50 $t_0:$ 50
<div class="graph">
<div id="romer-lchange-visualization"></div>
</div>
<div class="sliders">
<div style="padding-right: 20px">
<ul>
<li>
<div class="slider">
<label for="sliderlChange">$\bar{l}_1:$</label>
<span id="outputlChange">0.50</span>
<input
type="range"
id="sliderlChange"
min="0.1"
max="0.99"
step="0.01"
value="0.50"
/>
</div>
</li>
</ul>
</div>
<div style="padding-left: 20px">
<ul start="3">
<li>
<div class="slider">
<label for="slidert0">$t_0:$</label>
<span id="outputt0">50</span>
<input
type="range"
id="slidert0"
min="1"
max="99"
step="1"
value="50"
/>
</div>
</li>
</ul>
</div>
</div>
Notably, while both the Romer and Solow Models help to analyze growth across countries, they both are unable to resolve one question: why can and do investment rates and TFP differ across contries? This is a more fundamental economic question involving culture, institutions, and social dynamics—one day I hope we'll have an answer.
@ -169,11 +359,21 @@ would certainly be more pragmatic. The Solow Model's capital dynamics do, in som
Combining the dynamics of the Romer Model's ideas and the Solow Model's capital stock could yield the desired result. Intuitively, incorporating capital into output via the Solow Model's production function, as well as including the Law of Capital Motion seems like one way to legitimately create this so-called "Romer-Solow" model:
1. $Y_t=A_t K_t^\alpha L_{yt}^{1-\alpha}$
2. $\Delta K_{t+1}=\bar{s}Y_t-\bar{d}K_t$
3. $\Delta A_{t+1} = \bar{z}A_tL_{at}$
4. $L_{yt}+L_{at}=\bar{L}$
5. $L_{at}=\bar{l}\bar{L}$
<div style="display: flex; justify-content: center">
<div style="padding-right: 50px">
<ol>
<li>$Y_t=A_t K_t^\alpha L_{yt}^{1-\alpha}$</li>
<li>$\Delta K_{t+1}=\bar{s}Y_t-\bar{d}K_t$</li>
<li>$\Delta A_{t+1} = \bar{z}A_tL_{at}$</li>
</ol>
</div>
<div style="padding-left: 50px">
<ol start="4">
<li>$L_{yt}+L_{at}=\bar{L}$</li>
<li>$L_{at}=\bar{l}\bar{L}$</li>
</ol>
</div>
</div>
### solving the model
@ -222,7 +422,117 @@ Expectedly, output has a positive relationship with the savings rate and a negat
Using the visualization below, we see a growth pattern similar to that of the Romer Model. However, the Romer-Solow economy indeed grows at a faster rate than the Romer model—I had to cap $\bar{L}$ at $400$ and $\alpha$ at $0.4$ because output would be _too large_ for JavaScript to contain in a number (the graph would disappear).
$\bar{z}:$ 0.50 $A_0:$ 500 $\bar{d}:$ 0.50 $\bar{s}:$ 0.50 $\alpha:$ 0.33 $\bar{l}:$ 0.50 $\bar{L}:$ 200
<div class="graph">
<div id="romer-solow-visualization"></div>
</div>
<div class="sliders">
<div style="padding-right: 20px">
<ul>
<li>
<div class="slider">
<label for="sliderRSz">$\bar{z}:$</label>
<span id="outputRSz">0.50</span>
<input
type="range"
id="sliderRSz"
min="0.1"
max="0.99"
step="0.01"
value="0.50"
/>
</div>
</li>
<li>
<div class="slider">
<label for="sliderRSA0">$A_0:$</label>
<span id="outputRSA0">500</span>
<input
type="range"
id="sliderRSA0"
min="0"
max="1000"
step="10"
value="500"
/>
</div>
</li>
<li>
<div class="slider">
<label for="sliderRSd">$\bar{d}:$</label>
<span id="outputRSd">0.50</span>
<input
type="range"
id="sliderRSd"
min="0.01"
max="0.99"
step="0.01"
value="0.50"
/>
</div>
</li>
<li>
<div class="slider">
<label for="sliderRSs">$\bar{s}:$</label>
<span id="outputRSs">0.50</span>
<input
type="range"
id="sliderRSs"
min="0.01"
max="0.99"
step="0.01"
value="0.50"
/>
</div>
</li>
</ul>
</div>
<div style="padding-left: 20px">
<ul start="3">
<li>
<div class="slider">
<label for="sliderRSalpha">$\alpha:$</label>
<span id="outputRSalpha">0.33</span>
<input
type="range"
id="sliderRSalpha"
min="0.01"
max="0.40"
step="0.01"
value="0.33"
/>
</div>
</li>
<li>
<div class="slider">
<label for="sliderRSl">$\bar{l}:$</label>
<span id="outputRSl">0.50</span>
<input
type="range"
id="sliderRSl"
min="0.01"
max="0.99"
step="0.01"
value="0.50"
/>
</div>
</li>
<li>
<div class="slider">
<label for="sliderRSL">$\bar{L}:$</label>
<span id="outputRSL">200</span>
<input
type="range"
id="sliderRSL"
min="0"
max="400"
step="10"
value="200"
/>
</div>
</li>
</ul>
</div>
</div>
Playing with the parameters, the previous mathematical findings are validated. For example, because $g_Y^*=\frac{\bar{z}\bar{l}\bar{L}}{1-\alpha}$, only changes in parameters $\alpha,\bar{z},\bar{l}$, and $\bar{L}$ affect the growth rate of output, manifesting as the y-axis scaling up/down on a ratio scale.
@ -230,6 +540,88 @@ However, do economics grow _faster_/_slower_ the further _below_/_above_ they ar
The graph below illustrates the transition dynamics of Romer-Solow Model. Namely, $(\bar{z}, \bar{l}, \bar{L}, \alpha)=(0.5, 0.5, 100, 0.33)\forall t<t_0$, then update to the slider values when $t>t_0$.
$\bar{z}_0:$ 0.50 $\alpha_0:$ 0.33 $\bar{L}_0:$ 100 $\bar{l}_0:$ 0.50 $t_0:$ 50
<div class="graph">
<div id="romer-solow-change-visualization"></div>
</div>
<div class="sliders">
<div style="padding-right: 20px">
<ul>
<li>
<div class="slider">
<label for="sliderRSCz0">$\bar{z}_0:$</label>
<span id="outputRSCz0">0.50</span>
<input
type="range"
id="sliderRSCz0"
min="0.1"
max="0.99"
step="0.01"
value="0.50"
/>
</div>
</li>
<li>
<div class="slider">
<label for="sliderRSCalpha0">$\alpha_0:$</label>
<span id="outputRSCalpha0">0.33</span>
<input
type="range"
id="sliderRSCalpha0"
min="0.01"
max="0.54"
step="0.01"
value="0.33"
/>
</div>
</li>
<li>
<div class="slider">
<label for="sliderRSCL0">$\bar{L}_0:$</label>
<span id="outputRSCL0">100</span>
<input
type="range"
id="sliderRSCL0"
min="0"
max="200"
step="10"
value="100"
/>
</div>
</li>
</ul>
</div>
<div style="padding-left: 20px">
<ul start="3">
<li>
<div class="slider">
<label for="sliderRSCl0">$\bar{l}_0:$</label>
<span id="outputRSCl0">0.50</span>
<input
type="range"
id="sliderRSCl0"
min="0.01"
max="0.99"
step="0.01"
value="0.50"
/>
</div>
</li>
<li>
<div class="slider">
<label for="sliderRSCt0">$t_0:$</label>
<span id="outputRSCt0">50</span>
<input
type="range"
id="sliderRSCt0"
min="0"
max="100"
step="1"
value="50"
/>
</div>
</li>
</ul>
</div>
</div>
Finally, it is clear that economies converge to their Balanced Growth Path as desired—something slightly more convoluted to prove from the complex expression for $Y^*$ derived earlier. For example, with an increase in $\alpha_0$, output grows at an increasing rate after the change, then increases at a decreasing rate as it converges to the new higher Balanced Growth Path. Increasing parameters $\bar{z},\bar{l},\bar{L}$ yield similar results, although the changes are visually less obvious.

View file

@ -2,17 +2,9 @@
import Header from "../components/Header.astro";
import Footer from "../components/Footer.astro";
interface Props {
title: string;
description?: string;
useKatex?: boolean;
bodyClass?: string;
}
const {
title,
description = "Barrett Ruth's personal website",
useKatex = false,
bodyClass = "graph-background",
} = Astro.props;
---

View file

@ -8,21 +8,27 @@ interface Props {
description?: string;
date?: string;
useKatex?: boolean;
useD3?: boolean;
scripts?: string[];
};
}
const { frontmatter, post } = Astro.props;
const { title, description, useKatex = false } = frontmatter;
const { title, description, useKatex = false, useD3 = false } = frontmatter;
const filePath = post?.id || "";
const category = filePath.split("/")[0];
const topicColor = getTopicColor(category);
console.log(frontmatter)
---
<BaseLayout title={title} description={description} useKatex={useKatex}>
<BaseLayout title={title} description={description} useKatex={useKatex}, useD3={useD3}>
<slot name="head" slot="head">
<link rel="stylesheet" href="/styles/posts.css" />
<link rel="stylesheet" href="/styles/graph.css" />
{
useKatex && (
<link
@ -33,6 +39,11 @@ const topicColor = getTopicColor(category);
/>
)
}
{
useD3 && (
<script src="https://d3js.org/d3.v7.min.js"></script>
)
}
</slot>
<div class="post-container" style={`--topic-color: ${topicColor};`}>
@ -48,5 +59,8 @@ const topicColor = getTopicColor(category);
<slot name="scripts" slot="scripts">
<script src="/scripts/dateHeadings.js" is:inline></script>
{frontmatter.scripts?.map(script => (
<script src={script} type="module"></script>
))}
</slot>
</BaseLayout>