InfHorz_TPath with d and two endogenous variables

I’ve run into a problem at the end of ValueFnIter_InfHorz_TPath_SingleStep_raw:

Policy2=zeros(2,N_a,N_z,'gpuArray'); %NOTE: this is not actually in Kron form
Policy2(1,:,:)=shiftdim(rem(Policy-1,N_d)+1,-1); % d
Policy2(2,:,:)=shiftdim(ceil(Policy/N_d),-1); % aprime

%% Policy in transition paths
Policy2=UnKronPolicyIndexes_Case1(Policy2,n_d,n_a,n_z,vfoptions);

I cannot understand what the comment about not being in Kron form is really trying to tell me, but this construction of Policy2 leaves it bereft of the 2nd endogenous variable.

I haven’t yet wired up my decision variable, so will try my luck with the _nod_ case and see if that gets me through.

1 Like

No luck with _nod_. The policy comes back reshaped with the n_a arrays in their original dimensions (in my case, 51x51 as part of a total shape of 2x51x51) but the policy indexes path variable is constructed with the product (N_a being 2601 = 51x51). So perhaps the problem is in Transitionpath_InfHorz_PType_singlepath here:

    [V, Policy]=ValueFnIter_InfHorz_TPath_SingleStep(Vnext,n_d,n_a,n_z,d_grid, a_grid, z_grid, pi_z, ReturnFn, Parameters, DiscountFactorParamNames, ReturnFnParamNames, vfoptions);
    % The VKron input is next period value fn, the VKron output is this period.
    % Policy is kept in the form where it is just a single-value in (d,a')

    if N_d>0
        PolicyIndexesPath(:,:,:,T-ttr)=Policy;
    else
        PolicyIndexesPath(:,:,T-ttr)=Policy;
    end

It is about what shape ‘Policy’ is done internally.

By the time Policy gets to the user the first dimension indexes the decisions for all the d,aprime, then there is [n_a,n_z] and any semiz and e as appropriate.

Many years ago, the approach to Policy internally was to create it as [N_a,N_z] and this used to internally get named PolicyKron (kron being short for kronecker, as in using kronecker product to put the multiple n_a dimensions together as one N_a dimension). Policy contains the joint-index for (d,aprime).

Nowadays, I just write Policy internally (there are likely a handful of codes internally where it is still called PolicyKron). And solving more complex models means that the old [N_a,N_z] shape for kron is no longer the best shape. For example, in models with a semi-exogenous state, it is worth distinguishing d1 from d2, and so Policy internally might be something like [3,N_a,N_z] where the first dimension indexes the choices for (d1,d2,aprime). To try and make it easier to remember these different internal shapes I sometimes called them Policy3 (or Policy2 if it was [2,N_a,N_z]) as a way to make it easier to know what was happening while reading the internal code. Similarly divide-and-conquer and grid interpolation layer mean more keeping the different endogenous states separate in the internal Policy.

The ‘not actually in Kron form’ comment would date back to when I was still only starting to change the shape of Policy2 used internally. Kron would have been [N_a,N_z] while this is [2,N_a,N_z] so it is not what Kron used to refer to.

The content of Policy2(2,:,:) is the joint-index for both endogenous states.

1 Like

Well I’m still stuck: after eliminated the decision variable, this PolicyKron is coming back not in Kronecker form (line 24 of ValueFnIter_InfHorz_TPath_SingleStep:

[VKron,PolicyKron]=ValueFnIter_InfHorz_TPath_SingleStep_nod_raw(VKron,n_a, n_z, a_grid, z_gridvals, pi_z, ReturnFn, Parameters, DiscountFactorParamNames, ReturnFnParamNames, vfoptions);

This should be no problem for (line 51 of TransitionPath_InfHorz_PType_singlepath), since it’s declared as a Policy:

[V, Policy]=ValueFnIter_InfHorz_TPath_SingleStep(Vnext,n_d,n_a,n_z,d_grid, a_grid, z_grid, pi_z, ReturnFn, Parameters, DiscountFactorParamNames, ReturnFnParamNames, vfoptions);

but for the construction (lines 12-20) of the PolicyIndexesPath:

% For this agent type, first go back through the value & policy fns.
% Then forwards through agent dist and agg vars.
if N_d>0
    l_d=length(n_d);
    PolicyIndexesPath=zeros(2,N_a,N_z,T-1,'gpuArray'); %Periods 1 to T-1
else
    l_d=0;
    PolicyIndexesPath=zeros(N_a,N_z,T-1,'gpuArray'); %Periods 1 to T-1
end

which is clearly expecting its policies to be strictly in Kronecker format.

Is this just old bad code from TransitionPath_InfHorz_PType_shooting that I mistakenly copied? I see that the FHorz shooting functions set up PolicyIndexesPath as things like:

if vfoptions.gridinterplayer==0
    PolicyIndexesPath=zeros(l_d+l_aprime,N_a,N_z,N_j,T-1,'gpuArray'); %Periods 1 to T-1
elseif vfoptions.gridinterplayer==1
    PolicyIndexesPath=zeros(l_d+l_aprime+1,N_a,N_z,N_j,T-1,'gpuArray'); %Periods 1 to T-1
end

If we drop the N_j for the InfHorz case, then we have a shape match where l_d is zero and l_aprime is 2, giving us the expected 2x51x51. I’m not using gridinterplayer for InfHorz.

What I think I am seeing is that the various ValueFnIter_InfHorz_TPath_SingleStep functions each do their own thing when it comes to returning things promised to be Policy, Policy2, and PolicyKron to variables all claiming to be PolicyKron receivers. I think that’s the source of the shape incompatibility. What I don’t know is whether to fix the problem by making them all return something consistent, or whether the fix should be a reshape in the hands of the receivers.