From f7cf6a559a0a9274b7b5c5aad0fd60e7cb9edeba Mon Sep 17 00:00:00 2001 From: "Pedro H. Chaves Maia" <68562195+phchavesmaia@users.noreply.github.com> Date: Sat, 7 Mar 2026 12:50:40 -0300 Subject: [PATCH 1/6] Fixing what I believe is a typo Equation S.31 states that: phi = LD ./ (K .^ (1-mu)) This would imply: Vout = LD ./ (K.^0.25) --- matlab/section6/exogcftual/cdensityE.m | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/matlab/section6/exogcftual/cdensityE.m b/matlab/section6/exogcftual/cdensityE.m index 08c26d4..ed829a0 100644 --- a/matlab/section6/exogcftual/cdensityE.m +++ b/matlab/section6/exogcftual/cdensityE.m @@ -58,5 +58,6 @@ % Total floor space demand; LD=LM+LR; % Total floor space demand is simply the sum of commercial and residential floor space demand -Vout=LD./(K.^0.75); % We solve for density of development varphi using Eq. S31 +Vout=LD./(K.^0.25); % We solve for density of development varphi using Eq. S31 thetaout=LM./LD; % Share of commercial floor space theta is residential floor space + From 89634c2ce7c15ce0633c0736df7c2b450eca28e3 Mon Sep 17 00:00:00 2001 From: "Pedro H. Chaves Maia" <68562195+phchavesmaia@users.noreply.github.com> Date: Mon, 9 Mar 2026 12:03:46 -0300 Subject: [PATCH 2/6] Rescaled CMA to conform to new wages --- matlab/section6/calibration/calcal_adj_TD.m | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/matlab/section6/calibration/calcal_adj_TD.m b/matlab/section6/calibration/calcal_adj_TD.m index 8defec9..584d310 100644 --- a/matlab/section6/calibration/calcal_adj_TD.m +++ b/matlab/section6/calibration/calcal_adj_TD.m @@ -24,7 +24,7 @@ %%% rescaled wages, we amenities so that we match the city population in %%% the model (Phi = city population) -function [Aout,Bout,wageout] = calcal_adj_TD(obsdata,distvar,noj,A,B) +function [Aout,Bout,wageout,CMA] = calcal_adj_TD(obsdata,distvar,noj,A,B) % This program uses the following inputs % obsdata refers to an n by 4 object that contains a vector of four variables, % floor space prices, worplace employment, residence employment, and area @@ -85,6 +85,11 @@ % Adjust amenities to match the right population EB=((HH./Ephi).^(1./epsilon)).*EB; % If the ratio of the total population in the data over the population in the model is positive, we inflate amenities % From normalization of U_bar explained on page 18 in the supplement we have that H = Phi (the term in Brackets in the H equation). This equation reveals that we can move a multiplicative component Badjustment^epsilon in B_i out of the summation and use it to reach any population level H. +% Adjust CMA to conform to new wages; +ECMA=d_ij_eps*(Ewage.^epsilon); % We recreate residential commuter market access since we have normalized it before +CMA=zeros(noj,1); % We create a column vector of length n +CMA(Irsd)=ECMA; % Map commuter market access from the vector containing locations with postive residence employment into the vector containing all observations. Observations with zero residence employment receive a theory-consistent zero value. + % If we have H = "adjustment factor"^epsilon * Phi, the it follows that "adjustment factor" = (H/Phi)^(1/epsilon) % Compute recaled productivities and amenities for all blocks Aout=zeros(noj,1); @@ -96,4 +101,5 @@ display('>>>> Productivities and amenities updated <<<<'); - \ No newline at end of file + + From aa48e9a17c1eebcebb498fce21bd8903fa59e475 Mon Sep 17 00:00:00 2001 From: "Pedro H. Chaves Maia" <68562195+phchavesmaia@users.noreply.github.com> Date: Mon, 9 Mar 2026 12:04:23 -0300 Subject: [PATCH 3/6] Add CMA06 to productivities and amenities update --- matlab/section6/calibration/calcal_TD.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/matlab/section6/calibration/calcal_TD.m b/matlab/section6/calibration/calcal_TD.m index 910b350..0233124 100644 --- a/matlab/section6/calibration/calcal_TD.m +++ b/matlab/section6/calibration/calcal_TD.m @@ -177,7 +177,7 @@ %%% input into the smodexpg.m solver % Update productivities and amenities -[A06,B06,wage06] = calcal_adj_TD(obsvar06,tt06,nobs06,A06,B06); +[A06,B06,wage06,CMA06] = calcal_adj_TD(obsvar06,tt06,nobs06,A06,B06); % *****************************; % **** TOTAL WORKER INCOME ****; From 7068bddce63553eb9fb645d5f839ee4c17fbf9f9 Mon Sep 17 00:00:00 2001 From: "Pedro H. Chaves Maia" <68562195+phchavesmaia@users.noreply.github.com> Date: Mon, 16 Mar 2026 13:05:00 -0300 Subject: [PATCH 4/6] Fixing Edistvar indexing Looking at comegaoptC.m and comegaoptO.m, one understands that tt86rw and tt06, by extension, are indexed as (workplace, residence) matrices. This appears to be the case for tt86rw, since the estimated epsilon is 6.83, consistent with the paper. In camen.m and calcal_adj_TD.m (and all other functions in the repository), the indexing of the travel time matrices changes to (residence, workplace), suggesting that tt06 and ttpub06 are indexed differently from tt86rw. To my knowledge, that implies that either: 1) The indexing in comegaoptC.m is wrong, or 2) The indexing in all functions from the application of camen.m onward are wrong. Since the first option is more probable, I am adding this commit here. --- matlab/section6/calibration/comegaoptC.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/matlab/section6/calibration/comegaoptC.m b/matlab/section6/calibration/comegaoptC.m index 27d8c08..3cf4195 100644 --- a/matlab/section6/calibration/comegaoptC.m +++ b/matlab/section6/calibration/comegaoptC.m @@ -66,7 +66,7 @@ EHMT = HMT(Iwpl); % Generates a vector of workplace employment only containing observations with positive workplace emplyoment (it has nto observations) EHRT = HRT(Irsd); % Generates a vector of residence employment only containing observations with positive residence emplyoment (it has nfrom observations) Eomega = omega(Iwpl); % Generates a vector of guesses of transformed wages for observations with positive workplace employment (it has nto observations) -Edistvar=distvar(Iwpl,Irsd); % Generates a smaller travel time matrix that connects only observations with positive workplace employment to observations with residence emplyoment (it has nto by nfrom osbervations) +Edistvar=distvar(Irsd,Iwpl); % Generates a smaller travel time matrix that connects only observations with positive workplace employment to observations with residence emplyoment (it has nto by nfrom osbervations) % Notice that in this matrix, workplaces are rows and residences are columns clear distvar % clear variable to save memory From 8083cde9ee02ca746621168e0e2e33339f90d3dc Mon Sep 17 00:00:00 2001 From: "Pedro H. Chaves Maia" <68562195+phchavesmaia@users.noreply.github.com> Date: Tue, 17 Mar 2026 12:31:06 -0300 Subject: [PATCH 5/6] EQQ updates As written, EQQ is not updating across iterations. I believe this should not be the case; thus, I propose changing QT for Q_i in its computing. --- matlab/section6/exogcftual/smodexog.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/matlab/section6/exogcftual/smodexog.m b/matlab/section6/exogcftual/smodexog.m index 539a370..b7a1709 100644 --- a/matlab/section6/exogcftual/smodexog.m +++ b/matlab/section6/exogcftual/smodexog.m @@ -149,7 +149,7 @@ % We compute residence and workplace employment via commuting probabilities using guesses of wages and floor space prices and fundamental amenity; % In the below matrices, we have living in i (rows) and working in j (cols); % Notice that _i subscripts may indicate guesses (not residence locations, e.g. for wages) -EQQ=repmat(QT(Irsd),1,nwpl); % We assign guesses of residence floor space prices to all bilaterals. We take the vector of floor space prices, generate a new vector only for observations with positive residence employment, and replicates it nwpl times to generate a nrsd x nwpl matrix +EQQ=repmat(Q_i(Irsd),1,nwpl); % We assign guesses of residence floor space prices to all bilaterals. We take the vector of floor space prices, generate a new vector only for observations with positive residence employment, and replicates it nwpl times to generate a nrsd x nwpl matrix EQQ=EQQ.^(-(1-beta).*epsilon); % Generate the first component of bilateral commuting probabilities in Eq. 4: floor space prices to the power of (1-beta) x -epsilon EBB=repmat(EB,1,nwpl); % We assign residence amenities to all bilaterals. Takes the vector of amenities for observations with positive residence emplyoment and replicates it to generate an nrds x nwpl matrix EBB=EBB.^epsilon; % Generates the next component of bilateral commuting probabilities: B to the power of epsilon From 7cfb4c61d3a7900e5d91668e27e95de6052e7487 Mon Sep 17 00:00:00 2001 From: "Pedro H. Chaves Maia" <68562195+phchavesmaia@users.noreply.github.com> Date: Wed, 18 Mar 2026 19:49:28 -0300 Subject: [PATCH 6/6] change theta update rule The current update rule for theta uses the estimated prices of commercial buildings rather than the guessed prices. Although this substantially improves the convergence rate, it is unusual because theta is then the only endogenous variable defined differently from the others. I therefore propose updating theta using its guessed value instead. --- matlab/section6/exogcftual/smodexog.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/matlab/section6/exogcftual/smodexog.m b/matlab/section6/exogcftual/smodexog.m index b7a1709..c60414d 100644 --- a/matlab/section6/exogcftual/smodexog.m +++ b/matlab/section6/exogcftual/smodexog.m @@ -217,7 +217,7 @@ % Solve for theta for which the land market clears; theta_e=theta_i; % Completely specialized blocks never change since amenity or productivity are zero, so predicted theta correponds guesses (initial values). We only update mixed use shares in the next line -theta_e(Iis)=((1-alpha).*Y(Iis))./(q_e(Iis).*LD(Iis)); % We use the facotr input demand function derived from Eq. (10). Commercial floor space input LM is (1-alpha)*Y / q. Theta is LM/LD. Combining the two we can predict the commerical floor space share for imperfectly specialized blocks using predicted outputs and rents +theta_e(Iis)=((1-alpha).*Y(Iis))./(q_i(Iis).*LD(Iis)); % We use the facotr input demand function derived from Eq. (10). Commercial floor space input LM is (1-alpha)*Y / q. Theta is LM/LD. Combining the two we can predict the commerical floor space share for imperfectly specialized blocks using predicted outputs and rents %%% Now we have closed to loop from guesses to predicted values of the %%% target variables wage, floor space price and floor space share;