Skip to content

ExpAsset improvements#77

Draft
MichaelTiemann wants to merge 103 commits into
vfitoolkit:masterfrom
MichaelTiemann:mixed-horizon-tpath
Draft

ExpAsset improvements#77
MichaelTiemann wants to merge 103 commits into
vfitoolkit:masterfrom
MichaelTiemann:mixed-horizon-tpath

Conversation

@MichaelTiemann
Copy link
Copy Markdown
Contributor

@MichaelTiemann MichaelTiemann commented Mar 24, 2026

These are the changes to ExpAssets to enable a large model to use ExpAssets in a wider range of circumstances.

This is also a branch from which additional PType changes (and other changes) will be cherry-picked out for separate merging. When all those pre-requisites have been merged, this pull request should consist entirely of ExpAsset changes.

NOTE: Files such as VFIToolkit-matlab\EvaluateFnOnAgentDist\TransPathFHorz\SubCodes\ExpAsset\EvalFnOnAgentDist_AggVars_FHorz_ExpAsset_fastOLG.m which come from code generators need to be modified to add the ExpAsset argument to the arrayfun function calls. I have manually fixed up thew few cases I have tested, but every call must be adjusted to use the ExpAsset.

NOTE ALSO: I'm virtually certain I'm not calculating Policy3 correctly in VFIToolkit-matlab\TransitionPaths\FHorz\subcodes\ValueFnSingleStep\slowOLG\ExpAsset\ValueFnIter_FHorz_TPath_ExpAsset_SingleStep_raw.m (and similar). I could use help with my mod/ceil math at the end of the file. The calculations I do provide the correct shapes, but not the correct answers.

@MichaelTiemann MichaelTiemann marked this pull request as draft March 24, 2026 20:35
@MichaelTiemann
Copy link
Copy Markdown
Contributor Author

Converting to draft, because it really depends on the PType/TPath pull request being accepted first. Once that is merged, I'll merge those changes into this, and it should reduce the changed file count from 58 to 38.

@robertdkirkby
Copy link
Copy Markdown
Contributor

In the PolicyInd2Val commands you write

if n_d(1)==0
        n_d=n_d(2:end);
    end

I get what you are doing, but this is wrong. n_d should not contain zeros (unless is simply is equal to a scalar zero). I assume it is something about you setting n_d incorrectly?

@robertdkirkby
Copy link
Copy Markdown
Contributor

robertdkirkby commented Apr 12, 2026

I've done a push to modify setupGEnewprice3_shooting.m, EvalFnOnAgentDist_Grid.m‎ and EvalFnOnAgentDist_Grid_J.m‎ to adopt what you are doing here.

37234c1

made a typo in that, cleaned it up

f545bd2

@robertdkirkby
Copy link
Copy Markdown
Contributor

ExpAsset does not need its own Kron and UnKron commands.

@MichaelTiemann
Copy link
Copy Markdown
Contributor Author

I'm no longer creating an n_d with a zero in the first position. I'll look through my commits to see what I was thinking when I did that. I will resolve the conflicts newly created by your adoption. Thanks!

@robertdkirkby
Copy link
Copy Markdown
Contributor

Comment in
AgentDist_InfHorz_TPath_SingleStep.m
is incorrect, this is handled before passing as input, hence why input is called Policy_aprime and not Policy.

@robertdkirkby
Copy link
Copy Markdown
Contributor

the change to
ValueFnIter_Case1.m
can be dropped

@MichaelTiemann
Copy link
Copy Markdown
Contributor Author

In the PolicyInd2Val commands you write

if n_d(1)==0
        n_d=n_d(2:end);
    end

I get what you are doing, but this is wrong. n_d should not contain zeros (unless is simply is equal to a scalar zero). I assume it is something about you setting n_d incorrectly?

My history tells me that I hit this because I was setting n_d to scalar zero, and I was trying to make it robust in the case where zero might be an entry in a string of entries. I'll revert this (if you haven't already).

@MichaelTiemann
Copy link
Copy Markdown
Contributor Author

ExpAsset does not need its own Kron and UnKron commands.

Does this mean we need to modify the existing commands to overridethe l_a that n_a gives us with the l_aprime that the policy in PolicyPath will tell us?

@robertdkirkby
Copy link
Copy Markdown
Contributor

Do you want to revert (and so remove) the change to
[EvaluateFnOnAgentDist/FHorz/LifeCycleProfiles_FHorz_Case1.m
as part of this pull request. Unless I am mistaken it is just deleting a 'space' at end of line.

[will help reduce size of the pull request so I can make further progress on it]

@robertdkirkby
Copy link
Copy Markdown
Contributor

ExpAsset does not need its own Kron and UnKron commands.

Does this mean we need to modify the existing commands to overridethe l_a that n_a gives us with the l_aprime that the policy in PolicyPath will tell us?

Anything that is not the 'standard Case 1' uses 'Case 2' for Kron and UnKron. All the various different 'not standard' setups just involve slightly different inputs to the Case 2 Kron and UnKron.

@robertdkirkby
Copy link
Copy Markdown
Contributor

I just pushed
08a2a39

which implements a lot of the experienceasset in FHorz TPath setup.

It now works for
ValueFnOnTransPath_Case1_FHorz
AgentDistOnTransPath_Case1_FHorz
EvalFnOnTransPath_AggVars_Case1_FHorz

It does not yet work for
TransitionPath_Case1_FHorz

I did both simoptions.fastOLG=0 and simoptions.fastOLG=1 [you never want to use simoptions.fastOLG=0, it is really just there so the thing is coded twice as a way to check solutions are correct]

I only did vfoptions.fastOLG=0, and did not do divide-and-conquer nor grid-interpolation-layer (nor the combo of both).

I plan to do the fastOLG (including with DC and GI). And to do the TransitionPath_Case1_FHorz. But I figure there is enough progress there to push now.

@robertdkirkby
Copy link
Copy Markdown
Contributor

robertdkirkby commented Apr 13, 2026

PS. The only test I ran so far was solving a 'nothing happens' transition path. That worked just fine (no d1, with z, no e).

@MichaelTiemann
Copy link
Copy Markdown
Contributor Author

Excellent! I will take a deep breath and dive in. I see your UnKron Case2 patterns and will take guidance from them.

@MichaelTiemann
Copy link
Copy Markdown
Contributor Author

Do you want to revert (and so remove) the change to [EvaluateFnOnAgentDist/FHorz/LifeCycleProfiles_FHorz_Case1.m as part of this pull request. Unless I am mistaken it is just deleting a 'space' at end of line.

[will help reduce size of the pull request so I can make further progress on it]

Done.

@robertdkirkby
Copy link
Copy Markdown
Contributor

oops, missed a file, just added now
c4b6003

@MichaelTiemann
Copy link
Copy Markdown
Contributor Author

In the PolicyInd2Val commands you write

if n_d(1)==0
        n_d=n_d(2:end);
    end

I get what you are doing, but this is wrong. n_d should not contain zeros (unless is simply is equal to a scalar zero). I assume it is something about you setting n_d incorrectly?

New info:

In TransitionPath_InfHorz_PType_ExpAsset_singlepath.m there's this call at line 84:

PolicyValuesPath=PolicyInd2Val_InfHorz_TPath(PolicyIndexesPath,[n_d1,n_d2],[n_a1,n_a2],n_z,T-1,d_gridvals,a_gridvals,vfoptions,1);

As you can see, it creates an n_d that has n_d(1)==0 and n_d(2:end) of not zero. What is the proper way to construct PolicyValuesPath in this case?

@robertdkirkby
Copy link
Copy Markdown
Contributor

robertdkirkby commented Apr 14, 2026

If I understand the question correctly the trick is to do

if N_d1==0
PolicyValuesPath=PolicyInd2Val_InfHorz_TPath(PolicyIndexesPath,n_d2 [n_a1,n_a2],n_z,T-1,d_gridvals,a_gridvals,vfoptions,1);
else
PolicyValuesPath=PolicyInd2Val_InfHorz_TPath(PolicyIndexesPath,[n_d1,n_d2], [n_a1,n_a2],n_z,T-1,d_gridvals,a_gridvals,vfoptions,1);
end

@MichaelTiemann
Copy link
Copy Markdown
Contributor Author

MichaelTiemann commented Apr 14, 2026

ExpAsset does not need its own Kron and UnKron commands.

Does this mean we need to modify the existing commands to overridethe l_a that n_a gives us with the l_aprime that the policy in PolicyPath will tell us?

Anything that is not the 'standard Case 1' uses 'Case 2' for Kron and UnKron. All the various different 'not standard' setups just involve slightly different inputs to the Case 2 Kron and UnKron.

The UnKornPolicyIndexes_Case2_FHorz function is defined with this signature:

function Policy=UnKronPolicyIndexes_Case2_FHorz(PolicyKron, n_d, n_a, n_z,N_j, vfoptions)

but called like this:

PolicyKron=UnKronPolicyIndexes_Case2_FHorz(PolicyKron,[n_d1,n_d2,n_a1],N_a,N_z,N_j,vfoptions);

You did say that the FHorz_TPath stuff is not yet working. This seems to be the first major sticking point my code has noticed, and it's far enough out of round that I'll await your guidance as to when I should proceed.

I've commited the small change fixing calls to PolicyInd2Val_InfHorz_TPath.

@robertdkirkby
Copy link
Copy Markdown
Contributor

Bit of cheating. Using a function for things that were not it's original intent but which it does a nice job of.

The UnKron Case2 was designed to take inputs (n_d,n_a,n_z,N_j) and then create output a Policy of size [length(n_d),n_a,n_z,N_j]

I later realised this could be reused for all sorts of other things.

For example in a model with any combo of d,a and complicated endo states, you can put an input in place of n_d that captures the actual things that can be chosen in that model.

The other example is I realised if I input (n_d,N_a,N_z,N_j) then it essentially only unpacks the first dimension and leaves the rest in 'kron' form.

The ones you are referring to are doing both those examples as once. Is a trick I picked up along the way that saved defining a new function.

@robertdkirkby
Copy link
Copy Markdown
Contributor

I've added a comment to the Case2 UnKron commands that mentions the second example. Will be included in my next push. Hopefully helps someone in future.

@robertdkirkby
Copy link
Copy Markdown
Contributor

got my first fastOLG case for VFI with experienceasset in FHorz TPath running
aa91aeb
lots of cases left to go, but the first case is always the hardest

also adds those comments I mentioned

@MichaelTiemann
Copy link
Copy Markdown
Contributor Author

My problems trace back to this known problem I created for myself (in ValueFnIter_FHorz_TPath_SingleStep_ExpAsset_raw):

if N_d1==0
    Policy3=zeros(2,N_a,N_z,N_j,'gpuArray'); % first dim indexes the optimal choice for d2 and aprime rest of dimensions a,z
    Policy3(1,:,:,:)=1; % is meaningless anyway
    Policy3(2,:,:,:)=shiftdim(rem(Policy-1,N_d2)+1,-1);
    Policy3(3,:,:,:)=shiftdim(ceil(Policy/N_d2),-1);
else
    Policy3=zeros(3,N_a,N_z,N_j,'gpuArray'); % first dim indexes the optimal choice for (d1,d2,aprime) rest of dimensions a,z
                                                 % second dim indexes the optimal choice for (d2,aprime) rest of dimensions a,z
    Policy3(1,:,:,:)=shiftdim(rem(Policy-1,N_d1)+1,-1); % one of these is wrong
    Policy3(2,:,:,:)=shiftdim(ceil(Policy/N_d1),-1);    % one of these is wrong
    Policy3(3,:,:,:)=shiftdim(ceil(Policy/N_d),-1);     % this may be wrong
end

I'll see whether the new comments help me solve this on my own, but I think I need your help handling the rem/ceil scissors.

@robertdkirkby
Copy link
Copy Markdown
Contributor

robertdkirkby commented Apr 14, 2026

My guess as to what is going on.

You have Policy as a joint-index, say for (d1,d2,a1prime) [this last is a guess]
So doing
rem(Policy-1,N_d1)+1
separates d1 from 'the rest'
ceil(Policy/N_d1)
is 'the rest', after you separate out d1.

Likely what you are wanting to do is
temp=ceil(Policy/N_d1)
which contains 'the rest' (given my guess this is d2,a1prime) and then you can get
rem(temp-1,N_d2)+1
which separates our d2, and
ceil(temp/N_d2)
which would be a1prime

You would then set Policy3(1,:) to d1, Policy3(2,:) to d2, and Policy3(3,:) to a1prime.

@MichaelTiemann
Copy link
Copy Markdown
Contributor Author

MichaelTiemann commented Apr 14, 2026

Thanks! I'll give it a go (after confirming that the joint index hypothesis is valid...I think it is but will check).

@MichaelTiemann
Copy link
Copy Markdown
Contributor Author

MichaelTiemann commented Apr 14, 2026

It appears that UnKronPolicyIndexes_Case2_FHorz is not prepared to deal with a Policy3 in Kron format. In this cases it looks like UnKronPolicyIndexes_Case1_FHorz is suited to do the job (at the end of ValueFnIter_FHorz_TPath_SingleStep_ExpAsset), so I'll go down that path...

Almost. My Policy has a first dimension of 7, but PolicyIndexesPath has a first dimension of 6. I'll see where the discrepancy is coming in. At least now I don't have the wrong number of dimensions.

@robertdkirkby
Copy link
Copy Markdown
Contributor

robertdkirkby commented Apr 14, 2026

It appears that UnKronPolicyIndexes_Case2_FHorz is not prepared to deal with a Policy3 in Kron format. In this cases it looks like UnKronPolicyIndexes_Case1_FHorz is suited to do the job

UnKron Case2 is only designed to handle when the index is joint. UnKron Case1 handles that it is one index for d (if any), one index for aprime, one index for L2index (if using grid interp layer).

More likely, just don't covert joint index to Policy3, and instead pass to UnKron Case2.

@MichaelTiemann
Copy link
Copy Markdown
Contributor Author

MichaelTiemann commented Apr 14, 2026

Looks like Policy was already in Kron format in ValueFnIter_FHorz_TPath_SingleStep_ExpAsset and so no need to further shape it. With that change, and a few others, I made it to the undefined function ValueFnOnTransPath_Case1_FHorz_ExpAsset, caused by funky MATLAB path/function caching. Once I did an addpath, it revealed some other inconsistencies, and now I'm chasing some things that seemed to be working hours ago. I'll stay on it...

@MichaelTiemann
Copy link
Copy Markdown
Contributor Author

I made it to the end of my script in fast mode. First time in a while. Please see comments in latest commit (1201627). I will run larger test cases overnight.

@robertdkirkby
Copy link
Copy Markdown
Contributor

I adopted changes to
aprimeFnMatrix/CreateaprimePolicyExperienceAsset_J.m
EvaluateFnOnAgentDist/TransPathFHorz/SubCodes/EvalFnOnAgentDist_AggVars_FHorz_fastOLG.m
SubCodes/ExoShocks/ExogShockSetup_FHorz_TPath.m (was already adopted elsewhere as is a typo)

you can revert
EvaluateFnOnAgentDist/TransPath/EvalFnOnTransPath_AggVars_InfHorz.m

changes are all part of
45a8718

@robertdkirkby
Copy link
Copy Markdown
Contributor

TransitionPaths/InfHorz/subcodes/EvalFnOnAgentDist_TPath_SingleStep/EvalFnOnAgentDist_InfHorz_TPath_SingleStep_AggVars.m
should be reverted, if there is a problem here is should be being solved in terms of the inputs

@MichaelTiemann
Copy link
Copy Markdown
Contributor Author

This is great--thanks! I'll be back on the tools Wednesday evening. Looking forward to it 😁

@robertdkirkby
Copy link
Copy Markdown
Contributor

robertdkirkby commented May 18, 2026

you can revert
PolicyInd2Val/PolicyInd2Val_FHorz_TPath.m

you can move all the
ValueFnIter/FHorz/ExperienceAssetu/ValueFnIter_FHorz_ExpAssetu_nod1_noa1_e_raw.m
variations to the current toolkit repo versions, I did a bunch of work on these

@robertdkirkby
Copy link
Copy Markdown
Contributor

I adopted a lot of the
replace .(Names_i{ii});
with .(iistr);
in all the PType commands

@robertdkirkby
Copy link
Copy Markdown
Contributor

once you do a bunch of those, we can take a look at what is left

The fixes I needed are now in master.
If there's a problem (such as `temp` being sparse), it's the caller's fault.
We now complete end-to-end for small model, small_z_no_e (with AgentDistOnTransPath_MixHorz_PType change coming).
We test Scenario=3 because Scenario=4 is too large for fastOLG.
Address some of these issues.  Not out of the woods yet.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants