Computing constraint on capital and corresponding optimal labor

This function computes the constraint on borrowing of capital and corresponding optimal labor for all combinations of state of assets and productivity based on degree of imperfect enforcement of contracts. Uses 3 methods- Numerical, Vectorized, Taylor Series

Back to full code page https://kritikhanna.github.io/BKS-modified/

Function Inputs : Meshed-vectorised asset grid (size = it_agridnoxit_zgridno x 1) and entrepreneurial productivity grid (size : it_agridnoxit_zgridnox1), relevant model parameters required to compute the constraint on capital and labor based on the degree of contract enforceability.

Function Outputs : Returns an array of k and l (meshed-vectorized, size = it_agridnoxit_zgridno x 1 ), which are constrained k and l for each combination of assets and and entrepreneurial productivity. Also generates and prints matrix of constrained k and l.

Contents

function [ar_k_con,ar_l_con]=con_kl(varargin)
close all;
bl_profile = false;      % Switch off profile if running a tester/calling from another function
if(bl_profile)
profile off;
profile on;
end

addpath(genpath('/Users/sidhantkhanna/Documents/GitHub/BKS modified/'));

if ~isempty(varargin)

    [ar_a_v,ar_z_v,ar_a,ar_z ...
        fl_ahi,fl_zhi, fl_phi,fl_theta,fl_alpha,fl_w,fl_r,fl_delta,...
        fl_kappa,it_agridno,it_zgridno, ...
        ] = varargin{:};
   % Display matrix and graphs of constrained k and l (for every combination of a and z)

    % if testing the index below, print out graph, and also show each
    % iteration of the first order taylor approximation. if bl_state_test
    % is true, then test specific state iteration to arrive at \bar{k}.
    bl_print           = false;
    bl_state_test      = false;
    it_test_a_idx      = 1;
    it_test_z_idx      = 1;
    bl_saveimg         = false;  % True if images are to be saved, false if you want to publish them
    it_k_n             = 20000;                            % capital grid points to create capital grid and search for

else
    fl_ahi             = 50;
    fl_zhi             = 7;
    it_agridno         = 5;
    it_zgridno         = 6;
    ar_a               = linspace(0,fl_ahi,it_agridno);    % Sample asset grid
    ar_z               = linspace(0.2,fl_zhi,it_zgridno);  % Sample entrepreneurial productivity grid
    %ar_a              = 50;                               % for testing single a value
    %ar_z              = 1;                                % for testing single z value
    [a_m,z_m]          = meshgrid(ar_a,ar_z);              % Meshed matrix of assets and entrepreneurial productivity
                                                           % grid (size for a_m = it_zgridnoxit_agridno, z_m =it_zgridnoxit_agridno)

    ar_a_v             = a_m(:);                           % Meshed-vectorised asset grid
    ar_z_v             = z_m(:);                           % Meshed-vectorised entrepreneurial productivity grid
    it_k_n             = 20000;                            % capital grid points to create capital grid and search for
                                                           % constrained k
    fl_phi             = 0.5;

    fl_alpha = 0.4;
    fl_theta = 0.79 - fl_alpha;
    fl_delta = 0.06;
    fl_kappa = 2;
    [fl_r,fl_w,fl_ahi] = ...
        deal(0.04,1.8,100);

Testing Controls

    bl_print           = true;                             % Print matrix of optimal k with graphs
    bl_state_test      = true;                             % Plotting taylor method graphs for root finding
    it_test_a_idx      = 2;                                % a index for drawing graph or root search of k using TS approx
    it_test_z_idx      = 4;                                % z index for drawing graph or root search of k using TS approx
    bl_saveimg         = false;
end

Parameter controls

it_max_iter_taylor     = 7;                 % No of iterations for taylor series approximation for constraint function

Initialize Matrices

fl_R              = fl_r + fl_delta;
mt_k_con          = ones(it_agridno,it_zgridno);    % Matrix for storing constrained k , for each combination on a and z
mt_l_con          = ones(it_agridno,it_zgridno);

fl_version    = 3;
% version 1 = numerical method, version 2 = vectorised, version 3 = taylor
% series approximation for loop - has both vectorised and unvectorised
% versions
fl_vectorised = false; % for version 3- loop or vectorised

Version 1 - Numerical Method

if(fl_version == 1)
    for i = 1:it_agridno*it_zgridno
        fl_a    = ar_a_v(i);
        fl_z    = ar_z_v(i);
        [ar_k_con(i),ar_l_con(i)] = conkl_numerical(fl_a,fl_z,fl_r,fl_w,fl_alpha,fl_theta,fl_kappa,fl_delta,fl_phi,fl_R);
    end

    ar_k_con = ar_k_con';                 % transposing to get same order as input vector (it_agridnoxit_zgridno x 1)
    ar_l_con = ar_l_con';                 % transposing to get same order as input vector (it_agridnoxit_zgridno x 1)

    mt_k_con = reshape(ar_k_con, [it_zgridno,it_agridno]);
    mt_l_con = reshape(ar_l_con, [it_zgridno,it_agridno]);

    mt_k_con = mt_k_con';                   % getting to matrix of dimension it_agridnoxit_zgridno
    mt_l_con = mt_l_con';                   % getting to matrix of dimension it_agridnoxit_zgridno

Version 2 - Vectorised solution

elseif (fl_version == 2)
    ar_ks1 = linspace(0, 5*fl_ahi, it_k_n);  % Grid of capital to search for roots of constraint equation (order = 1 X it_k_n)
    ar_ks  = fliplr(ar_ks1);                   % flipping array to pick up the second root (non-zero root)

    f_lmax = @(z,k) (fl_w./((k.^fl_alpha).*fl_theta.*z)).^(1/(fl_theta - 1)); % max l for a given constrained k

    f_con_concave = @(a,z,k) fl_phi.*((k.^fl_alpha).*z.*(f_lmax(z,k)).^fl_theta - fl_w.*(f_lmax(z,k)))-(1+fl_r)*fl_kappa.*ones(numel(a),it_k_n)+(1+fl_r).*(a).*ones(1,it_k_n);
    % concave part of the constraint function

    f_con_straight = @(a,z,k) (1-fl_phi).*(1-fl_delta).*ones(numel(a),1).*k+fl_R.*ones(numel(a),1).*k;
    % straight line part of the constraint function

    f_con = @(a,z,k) f_con_concave(a,z,k) - f_con_straight(a,z,k); % constraint function

    f1 = f_con(ar_a_v, ar_z_v, ar_ks);
    % f1 evaulates the constraint for each combination of a,z and k. Order of f1 = ((it_agridnoxit_zgridno) X it_k_n)


    % for i=1:it_agridno*it_zgridno
    %    f1(i,it_k_n)=-1000;
    % end

    f1(:,it_k_n)  = -1000;  % assigning a large absolute value to the constraint at k=0 so as to
                           % remove the root k=0


    [val, idx]    = min(abs((f1)'));
   % for each combi of a,z, root of the constraint equation is the k for
   % which the value of the constraint function is closest to zero.
   % min function on a matrix minimizes over each column, min (NXM) is of
   % order (1XM). As f1 is of the order ((it_agridnoxit_zgridno) X it_k_n),
   % dimension of val and idx = (1 X (it_agridnoXit_zgridno)). Since we need to minimize f1 over
   % k for each combination of a and z, and dim f1=((it_agridnoxit_zgridno) X it_k_n),
   % dim f1' = (it_k_n x (it_agridnoxit_zgridno)), dim min(abs((f1)'))= 1 X (it_agridnoxit_zgridno),
   % dim val , idx = 1 X (it_agridnoxit_zgridno)

   [val2,idx2]    = max(((f1)'));     % store the max value of f1(k) for each combination of a,z
    ar_k_con      = ar_ks(idx);    %  storing constrained k values, dim = 1 X (it_agridnoxit_zgridno)

    % Analysing cases where the only root of constraint equation is k=0 in
    % the range of k's we are checking
    % There are 2 subcases:

    % 1) k = 0 is the only root and max of f is obtained at k = 0 ( all other
    % f's are negative in the range of k's )

    % 2) k = 0 is not the only root, but only root in the given range of k's
    % we are checking. The actual constrained k is very high in this case,
    % so assuming the optimal would surely be less than the constrained k

    for i=1:it_agridno*it_zgridno
        if (ar_k_con(i)==ar_ks1(2))
            if (val2(i)<=0)
                ar_k_con(i)=0;  % Case 1)
            else
                ar_k_con(i)=1000000; % Case 2)
            end
        end
    end

    % Limitation of this method is for case 2), if optimal k was greater than
    % constrained k, those cases you are not sure about (not sure if those
    % cases exist)

    ar_k_con = ar_k_con'; % transposing to get same order as input vector (it_agridnoxit_zgridno x 1)

    ar_l_con = (fl_w./(fl_theta.*ar_z_v.*ar_k_con.^(fl_alpha))).^(1/(fl_theta-1));

    mt_k_con = reshape(ar_k_con, [it_zgridno,it_agridno]);
    mt_l_con = reshape(ar_l_con, [it_zgridno,it_agridno]);

    mt_k_con = mt_k_con';           % getting to matrix of dimension it_agridnoxit_zgridno
    mt_l_con = mt_l_con';            % getting to matrix of dimension it_agridnoxit_zgridno

Version 3 - Taylor Series Method - For loop

elseif (fl_version == 3)
    if(~fl_vectorised)
        % Solving constraint k for each combination of a and z one by one.
        % The constraint function has a linear part and a curved part.
        % Starting at any point, the the curved part is approximated to a straight line with a taylor series expansion
        % The intersection of the first approximation and the linear part
        % is the first guess of k. At the first guess of k, approximate the
        % curve part again as a stright line, then find its intersection
        % with a straight line for the next guess of k. Continue doing that
        % until it_max_iter_taylor iterations (you converge to the correct k in less than those no. of iterations


        syms k w alph theta kappa r phi delta R
        for i = 1:it_agridno
            for j = 1:it_zgridno

                % Defining the functions using symbols only

                f_lmax             = (w/((k^alph)*theta*ar_z(j)))^(1/(theta - 1));  % optimal l to constrained k
                f_con_concave      = phi*((k^alph)*ar_z(j)*(f_lmax)^theta - w*(f_lmax))-(1+r)*kappa+(1+r)*(ar_a(i));
                % Concave part of constraint function of k
                f_con_straight     = (1-phi)*(1-delta)*k+R*k;
                % Straight line part of constraint function of k

                % Substituting parameters in the constraint function
                f_con_straight_sub = subs(f_con_straight,{w,alph,theta,kappa,r,phi,delta,R},{fl_w,fl_alpha fl_theta,fl_kappa,fl_r,fl_phi,fl_delta, fl_R});
                f_con_concavej_k   = subs(f_con_concave, {w,alph,theta,kappa,r,phi,delta,R}, {fl_w,fl_alpha fl_theta,fl_kappa,fl_r,fl_phi,fl_delta, fl_R});

                m  = 1;   % no if iteration for guess of k
                kj = 1;   % First guess of k

                % * a = constant term in taylor approximate of the concave part of constraint function
                % * b = coefficient of k in taylor approximate of the concave part of constraint function
                % * c = 0 (constant term of straight line part of constraint - staight line function chosen that way)
                % * d = coefficient of k of straight line part of constraint

                if (bl_state_test)
                    ar_k_store = zeros(1, it_max_iter_taylor);
                    % Store all values of guesses of k
                end

                if (fl_phi == 0) % assuming kappa = 0, id a = 0 and phi = 0, opti k = 0
                mt_k_con(i,j) = (1+fl_r)*(ar_a(i)- fl_kappa);
                mt_l_con(i,j) = (fl_w/((mt_k_con(i,j)^fl_alpha)*fl_theta*ar_z(j)))^(1/(fl_theta - 1));

                    else
                % bl_solution_exits = false;
                s=0; % s increases value when a<0, case where there is no intersection of the 2 straight lines

                while (m < it_max_iter_taylor)

                    f_con_concavej        = double(subs(f_con_concavej_k, {k}, {kj})); % substituting first guess of k
                    % computing coefficients a and b of taylor series approximate
                    f_con_concave_diff_k  = diff(f_con_concave,k);
                    f_con_concave_diff_kj = double(subs(f_con_concave_diff_k, {k,w,alph,theta,kappa,r,phi,delta,R}, {kj,fl_w,fl_alpha fl_theta,fl_kappa,fl_r,fl_phi,fl_delta, fl_R}));

                    d = (1-fl_phi)*(1-fl_delta)+ fl_R;
                    a = double(f_con_concavej-f_con_concave_diff_kj*kj);
                    b = double(f_con_concave_diff_kj);
                    if (b>d) % Case where slope of tangent to curve greater
                        % than that of straight line), first guess needs to
                        % a large no.
                        k_jplus1=kj*100;

                    elseif (a<0)   %case where there is no intersection of the 2 straight lines
                        k_jplus1 = kj;
                        s=s+1;
                    else
                    k_jplus1 = (a/(d-b)); % intersection of taylor approximate and straight line part of the constraint

                    end

              % Displaying coefficients of straight line and tangent to
              % curved part of the constraint, and each guess of k

                    if (i == it_test_a_idx && j == it_test_z_idx && bl_state_test)
                        st_test_iter_info_one = ['iter:', num2str(m), ', kj:', num2str(kj)];
                        st_test_iter_info_two = ['y-interp for lin approx of concave:', num2str(a)];
                        st_test_iter_info_thr = ['slope for lin approx of concave:', num2str(b)];
                        st_test_iter_info_fou = ['slope for origin linear line:', num2str(d)];
                        disp(st_test_iter_info_one);
                        disp(st_test_iter_info_two);
                        disp(st_test_iter_info_thr);
                        disp(st_test_iter_info_fou);
                        ar_k_store(m) = kj; % storing all k's which were guessed until convergence to root
                    end

                    % updating
                    kj = k_jplus1; % next guess of k
                    m  = m+1; % updating iteration for next guess of k
                end

                %if(~bl_solution_exits)
                 %   display ('constraint equation has no positive solution for capital');
                %return;
                %else

                mt_k_con(i,j) = kj; % updating constrained k for each a and z
                mt_l_con(i,j) = (fl_w/((kj^fl_alpha)*fl_theta*ar_z(j)))^(1/(fl_theta - 1));
                if (s>0)
                    mt_k_con(i,j)=0;
                    mt_l_con(i,j)=0;

                end
                % updating optimal l to correponding constrained k for each a and z

                bl_state_test = true;
iter:1, kj:1
y-interp for lin approx of concave:11.3482
slope for lin approx of concave:0.81569
slope for origin linear line:0.57
iter:2, kj:100
y-interp for lin approx of concave:19.6933
slope for lin approx of concave:0.16711
slope for origin linear line:0.57
iter:3, kj:48.8799
y-interp for lin approx of concave:16.4067
slope for lin approx of concave:0.21381
slope for origin linear line:0.57
iter:4, kj:46.0613
y-interp for lin approx of concave:16.1971
slope for lin approx of concave:0.21822
slope for origin linear line:0.57
iter:5, kj:46.0439
y-interp for lin approx of concave:16.1958
slope for lin approx of concave:0.21825
slope for origin linear line:0.57
iter:6, kj:46.0439
y-interp for lin approx of concave:16.1958
slope for lin approx of concave:0.21825
slope for origin linear line:0.57

Graph Curve and line Intersection

                if (i== it_test_a_idx && j == it_test_z_idx && bl_state_test)
                    figure(1);
                    hold on;
                    %fl_k_max = min(0.001, kj + kj/10);
                    fl_k_max = 120;
                    fplot(f_con_concavej_k, [0, fl_k_max]);
                    fplot(f_con_straight_sub, [0, fl_k_max]);

                    for it_m = 1:1:it_max_iter_taylor
                        fl_kj_cur = ar_k_store(it_m);
                        line([real(fl_kj_cur) real(fl_kj_cur)],[0 fl_kj_cur+1], 'LineStyle', '--');
                        % -- lines are guesses of k
                    end

                    line([real(kj) real(kj)],[0 kj+1]);
                    % final solution k
                    grid on;
                    grid minor;
                    if(bl_saveimg)
                    saveas(gcf, '/Users/sidhantkhanna/Documents/GitHub/BKS modified/code/Firms/figures/con_kl/taylor.png')
                    end
                end
            end

            end

        end

        mt_k_con1 = mt_k_con';
        mt_l_con1 = mt_l_con';

        ar_k_con = mt_k_con1(:);                    % matrix unlayered one column under another
        ar_l_con = mt_l_con1(:);                    % matrix unlayered one column under another

Version 3 - Taylor Series Method - Vectorised Version

    elseif(fl_phi==0)
         ar_k_con =(1+fl_r).*(ar_a_v- fl_kappa.*ones(numel(ar_a_v),1));
         ar_l_con =(fl_w./(fl_theta.*ar_z_v.*ar_k_con.^(fl_alpha))).^(1/(fl_theta-1));
         ar_k_con(ar_k_con<0) = 0;
         ar_l_con(ar_l_con<0) = 0;

          mt_k_con=reshape(ar_k_con, [it_zgridno,it_agridno]);
    mt_l_con=reshape(ar_l_con, [it_zgridno,it_agridno]);

    mt_k_con=mt_k_con';
    mt_l_con=mt_l_con';



         else


        ar_kj = ones(it_agridno*it_zgridno, 1); % initial guess of k
        m     = 1;
        s = zeros(it_agridno*it_zgridno, 1);
        s1 = zeros(it_agridno*it_zgridno, 1);
        while (m < it_max_iter_taylor)
        f_lmax = (fl_w./((ar_kj.^fl_alpha)*fl_theta.*ar_z_v)).^(1/(fl_theta - 1));
        f_con_concave = fl_phi*((ar_kj.^fl_alpha).*ar_z_v.*(f_lmax).^fl_theta - fl_w.*(f_lmax))-(1+fl_r)*fl_kappa.*ones(it_agridno*it_zgridno,1)+(1+fl_r).*(ar_a_v);
        f_con_concave_diff = fl_phi.*(fl_alpha.*ar_kj.^(fl_alpha - 1).*ar_z_v.*((fl_w./(ar_kj.^fl_alpha.*fl_theta.*ar_z_v)).^(1/(fl_theta - 1))).^fl_theta - (fl_alpha.*ar_kj.^fl_alpha.*fl_w.*((fl_w./(ar_kj.^fl_alpha.*fl_theta.*ar_z_v)).^(1/(fl_theta - 1))).^(fl_theta - 1).*(fl_w./(ar_kj.^fl_alpha.*fl_theta.*ar_z_v)).^(1/(fl_theta - 1) - 1))./(ar_kj.^(fl_alpha + 1).*(fl_theta - 1)) + (fl_alpha.*fl_w^2.*(fl_w./(ar_kj.^fl_alpha.*fl_theta.*ar_z_v)).^(1/(fl_theta - 1) - 1))./(ar_kj.^(fl_alpha + 1).*fl_theta.*ar_z_v.*(fl_theta - 1)));
        d = ((1-fl_phi)*(1-fl_delta)+ fl_R).*ones(it_agridno*it_zgridno, 1);
        a = (f_con_concave-f_con_concave_diff.*ar_kj);
        b = f_con_concave_diff;

        % find k_{j+1} for everyone
        ar_k_jplus1 = (a./(d-b));
        % ar_k_jplus1_dup = ar_k_jplus1;

        % replace if lin approximate for slope is greater than linear slope
        ar_k_jplus1((b>d)) = ar_kj(b>d)*100;
  %     s1(b>d) = s1(b>d)+1;
        ar_k_jplus1((a<0) & (b<d)) = ar_kj(a<0 & b<d);
        s(a<0 & b<d) = s(a<0 & b<d)+1;
        ar_kj = ar_k_jplus1;
        m = m+1;
        end

        ar_k_con = ar_kj;
        ar_l_con = (fl_w./(fl_theta.*ar_z_v.*ar_k_con.^(fl_alpha))).^(1/(fl_theta-1));
        ar_l_con1 = ar_l_con;
        ar_k_con(s>0) = 0;
        ar_l_con(s>0) = 0;
 %      ar_k_con(s1>0) = ar_kj(s1>0);
 %      ar_l_con(s1>0) = ar_l_con1(s1>0);

    mt_k_con=reshape(ar_k_con, [it_zgridno,it_agridno]);
    mt_l_con=reshape(ar_l_con, [it_zgridno,it_agridno]);

    mt_k_con=mt_k_con';
    mt_l_con=mt_l_con';


    end

end

Print matrix for constrained k and l

if(bl_print)

    disp('mt_k_con');
    disp(mt_k_con);
    disp('mt_l_con');
    disp(mt_l_con);

figure (2)
surf(ar_z, ar_a, mt_k_con);
title('K constraint given a and z');
xlabel('a');
ylabel('z');
zlabel('K constraint');
view(125,35);
if(bl_saveimg)
saveas(gcf, '/Users/sidhantkhanna/Documents/GitHub/BKS modified/code/Firms/figures/con_kl/Kconst_az.png')
end

figure (3)
surf(ar_z, ar_a, mt_l_con);
title('L constraint given a and z');
xlabel('a');
ylabel('z');
zlabel('L with K constrained');
view(125,35);
if(bl_saveimg)
saveas(gcf, '/Users/sidhantkhanna/Documents/GitHub/BKS modified/code/Firms/figures/con_kl/Lconst_az.png')
end
end

if(bl_profile)
profile off;
profile viewer;
st_file_name = '/Users/sidhantkhanna/Documents/GitHub/BKS modified/code/Profile/Firms/con_kl';
profsave(profile('info'), st_file_name);
end
mt_k_con
         0         0         0    6.0551   23.6750   89.4185
   19.2580   22.3586   30.0059   46.0439   79.7481  149.5586
   42.1321   47.1884   58.8345   80.8599  122.0637  199.4670
   64.9941   71.6404   86.4906  113.2944  160.6981  245.0144
   87.8497   95.8947  113.5405  144.4921  197.3334  287.9551

mt_l_con
         0         0         0    2.8784   11.0640   37.6848
    0.0405    1.2960    4.3926   10.8866   24.5341   52.8016
    0.0677    2.1151    6.8308   15.7493   32.4335   63.7754
    0.0900    2.7812    8.7943   19.6476   38.8422   72.9834
    0.1096    3.3672   10.5123   23.0451   44.4416   81.1359