|
1 |
| -function [VKron, Policy]=ValueFnIter_Case1_NoD_Par2_raw(VKron, n_a, n_z, pi_z, DiscountFactorParamsVec, ReturnMatrix, Howards,Howards2,Tolerance,maxiter) % Verbose, a_grid, z_grid, |
2 |
| -%Does pretty much exactly the same as ValueFnIter_Case1, only without any decision variable (n_d=0) |
| 1 | +function [VKron, Policy]=ValueFnIter_DC1_nod_raw(V0, n_a, n_z, a_grid, z_gridvals, pi_z, ReturnFn, DiscountFactorParamsVec, ReturnFnParamsVec, vfoptions) |
3 | 2 |
|
4 | 3 | N_a=prod(n_a);
|
5 | 4 | N_z=prod(n_z);
|
6 | 5 |
|
7 |
| -% PolicyIndexes=zeros(N_a,N_z,'gpuArray'); |
8 |
| -% Ftemp=zeros(N_a,N_z,'gpuArray'); |
| 6 | +% n-Monotonicity |
| 7 | +% vfoptions.level1n=11; |
| 8 | +level1ii=round(linspace(1,n_a,vfoptions.level1n)); |
| 9 | +level1iidiff=level1ii(2:end)-level1ii(1:end-1)-1; |
9 | 10 |
|
| 11 | +%% Start by setting up ReturnFn for the first-level (as we can reuse this every iteration) |
| 12 | +ReturnMatrixLvl1=CreateReturnFnMatrix_Case1_Disc_DC1_nod_Par2(ReturnFn, n_z, a_grid, a_grid(level1ii), z_gridvals, ReturnFnParamsVec, 1); |
| 13 | + |
| 14 | +V=reshape(V0,[N_a,N_z]); |
| 15 | +Policy=zeros(N_a,N_z,'gpuArray'); |
| 16 | + |
| 17 | +% for Howards, preallocate |
| 18 | +Ftemp=zeros(N_a,N_z,'gpuArray'); |
| 19 | +% and we need |
10 | 20 | bbb=reshape(shiftdim(pi_z,-1),[1,N_z*N_z]);
|
11 | 21 | ccc=kron(ones(N_a,1,'gpuArray'),bbb);
|
12 | 22 | aaa=reshape(ccc,[N_a*N_z,N_z]);
|
13 | 23 |
|
14 |
| -addindexforaz=gpuArray(N_a*(0:1:N_a-1)'+N_a*N_a*(0:1:N_z-1)); |
| 24 | +% precompute |
| 25 | +Epi_z=shiftdim(pi_z',-1); % pi_z in the form we need it to compute the expectations |
| 26 | + |
| 27 | +% I want the print that tells you distance to have number of decimal points corresponding to vfoptions.tolerance |
| 28 | +distvstolstr=['ValueFnIter: after %i iterations the dist is %4.',num2str(-round(log10(vfoptions.tolerance))),'f \n']; |
15 | 29 |
|
16 | 30 | %%
|
17 |
| -tempcounter=1; |
18 | 31 | currdist=Inf;
|
19 |
| -while currdist>Tolerance && tempcounter<=maxiter |
20 |
| - VKronold=VKron; |
| 32 | +tempcounter=1; |
| 33 | +while currdist>vfoptions.tolerance && tempcounter<=vfoptions.maxiter |
| 34 | + |
| 35 | + Vold=V; |
21 | 36 |
|
22 | 37 | %Calc the condl expectation term (except beta), which depends on z but not on control variables
|
23 |
| - EV=VKronold.*shiftdim(pi_z',-1); %kron(ones(N_a,1),pi_z(z_c,:)); |
| 38 | + EV=Vold.*Epi_z; |
24 | 39 | EV(isnan(EV))=0; %multilications of -Inf with 0 gives NaN, this replaces them with zeros (as the zeros come from the transition probabilites)
|
25 | 40 | EV=sum(EV,2); % sum over z', leaving a singular second dimension
|
26 | 41 |
|
27 |
| - entireRHS=ReturnMatrix+DiscountFactorParamsVec*EV; %aprime by a by z |
| 42 | + DiscountedEV=DiscountFactorParamsVec*reshape(EV,[N_a,1,N_z]); |
| 43 | + |
| 44 | + %% Level 1 |
| 45 | + % We can just reuse ReturnMatrixLvl1 |
| 46 | + entireRHS_ii=ReturnMatrixLvl1+DiscountedEV; |
| 47 | + |
| 48 | + % First, we want aprime conditional on (1,a,z) |
| 49 | + [Vtempii,maxindex1]=max(entireRHS_ii,[],2); |
| 50 | + |
| 51 | + % Store |
| 52 | + % curraindex=level1ii'; |
| 53 | + V(level1ii,:)=shiftdim(Vtempii,1); |
| 54 | + Policy(level1ii,:)=shiftdim(maxindex1,1); |
| 55 | + |
| 56 | + % Need to keep Ftemp for Howards policy iteration improvement |
| 57 | + Ftemp(level1ii,:)=ReturnMatrixLvl1(shiftdim(maxindex1,1)+N_a*(0:1:vfoptions.level1n-1)'+N_a*vfoptions.level1n*(0:1:N_z-1)); |
| 58 | + |
| 59 | + % Attempt for improved version |
| 60 | + maxgap=squeeze(max(maxindex1(1,2:end,:)-maxindex1(1,1:end-1,:),[],3)); |
| 61 | + for ii=1:(vfoptions.level1n-1) |
| 62 | + curraindex=(level1ii(ii)+1:1:level1ii(ii+1)-1)'; |
| 63 | + if maxgap(ii)>0 |
| 64 | + loweredge=min(maxindex1(1,ii,:),N_a-maxgap(ii)); % maxindex(ii,:), but avoid going off top of grid when we add maxgap(ii) points |
| 65 | + % loweredge is 1-by-1-by-n_z |
| 66 | + aprimeindexes=loweredge+(0:1:maxgap(ii)); |
| 67 | + % aprime possibilities are maxgap(ii)+1-by-1-by-n_z |
| 68 | + ReturnMatrix_ii=CreateReturnFnMatrix_Case1_Disc_DC1_nod_Par2(ReturnFn, n_z, a_grid(aprimeindexes), a_grid(level1ii(ii)+1:level1ii(ii+1)-1), z_gridvals, ReturnFnParamsVec,2); |
| 69 | + aprimez=repelem(aprimeindexes-1,1,level1iidiff(ii),1)+N_a*shiftdim((0:1:N_z-1),-1); % the current aprimeii(ii):aprimeii(ii+1) |
| 70 | + entireRHS_ii=ReturnMatrix_ii+DiscountedentireEV(reshape(aprimez,[(maxgap(ii)+1),level1iidiff(ii),N_z])); |
| 71 | + [Vtempii,maxindex]=max(entireRHS_ii,[],1); |
| 72 | + V(curraindex,:)=shiftdim(Vtempii,1); |
| 73 | + % the a1prime is relative to loweredge(allind), need to 'add' the loweredge |
| 74 | + zind=shiftdim((0:1:N_z-1),-1); % already includes -1 |
| 75 | + Policy(curraindex,:)=shiftdim(maxindex+N_d*(loweredge(zind)-1),1); |
| 76 | + |
| 77 | + % Need to keep Ftemp for Howards policy iteration improvement |
| 78 | + Ftemp(curraindex,:)=ReturnMatrix_ii(shiftdim(maxindex,1)+(maxgap(ii)+1)*(0:1:level1iidiff(ii)-1)'+(maxgap(ii)+1)*level1iidiff(ii)*(0:1:N_z-1)); |
| 79 | + |
| 80 | + else |
| 81 | + loweredge=maxindex1(:,1,ii,:); |
| 82 | + % Just use aprime(ii) for everything |
| 83 | + ReturnMatrix_ii=CreateReturnFnMatrix_Case1_Disc_DC1_nod_Par2(ReturnFn, n_z, a_grid(loweredge), a_grid(level1ii(ii)+1:level1ii(ii+1)-1), z_gridvals, ReturnFnParamsVec,2); |
| 84 | + aprimez=repelem(loweredge-1,1,level1iidiff(ii),1)+N_a*shiftdim((0:1:N_z-1),-1); % the current aprimeii(ii):aprimeii(ii+1) |
| 85 | + entireRHS_ii=ReturnMatrix_ii+DiscountedentireEV(reshape(aprimez,[1,level1iidiff(ii),N_z])); |
| 86 | + [Vtempii,maxindex]=max(entireRHS_ii,[],1); |
| 87 | + V(curraindex,:)=shiftdim(Vtempii,1); |
| 88 | + % the aprime is relative to loweredge(allind), need to 'add' the loweredge |
| 89 | + zind=shiftdim((0:1:N_z-1),-1); % already includes -1 |
| 90 | + Policy(curraindex,:)=shiftdim(maxindex+N_d*(loweredge(zind)-1),1); |
| 91 | + |
| 92 | + % Need to keep Ftemp for Howards policy iteration improvement |
| 93 | + Ftemp(curraindex,:)=ReturnMatrix_ii(shiftdim(maxindex,1)+(0:1:level1iidiff(ii)-1)'+level1iidiff(ii)*(0:1:N_z-1)); |
28 | 94 |
|
29 |
| - %Calc the max and it's index |
30 |
| - [VKron,PolicyIndexes]=max(entireRHS,[],1); |
31 |
| - |
32 |
| - tempmaxindex=shiftdim(PolicyIndexes,1)+addindexforaz; % aprime index, add the index for a and z |
33 |
| - |
34 |
| - Ftemp=reshape(ReturnMatrix(tempmaxindex),[N_a,N_z]); % keep return function of optimal policy for using in Howards |
| 95 | + end |
| 96 | + end |
35 | 97 |
|
36 |
| - PolicyIndexes=PolicyIndexes(:); % a by z (this shape is just convenient for Howards) |
37 |
| - VKron=shiftdim(VKron,1); % a by z |
| 98 | + %% Finish up |
| 99 | + % Update currdist |
| 100 | + Vdist=V(:)-Vold(:); |
| 101 | + Vdist(isnan(Vdist))=0; |
| 102 | + currdist=max(abs(Vdist)); |
38 | 103 |
|
39 |
| - VKrondist=VKron(:)-VKronold(:); |
40 |
| - VKrondist(isnan(VKrondist))=0; |
41 |
| - currdist=max(abs(VKrondist)); |
42 |
| - |
43 |
| - % Use Howards Policy Fn Iteration Improvement (except for first few and last few iterations, as it is not a good idea there) |
44 |
| - if isfinite(currdist) && currdist/Tolerance>10 && tempcounter<Howards2 |
45 |
| - for Howards_counter=1:Howards |
46 |
| - EVKrontemp=VKron(PolicyIndexes,:); |
| 104 | + if isfinite(currdist) && currdist/vfoptions.tolerance>10 && tempcounter<vfoptions.maxhowards % Use Howards Policy Fn Iteration Improvement |
| 105 | + Policy_Vind=Policy(:); |
| 106 | + for Howards_counter=1:vfoptions.howards |
| 107 | + EVKrontemp=V(Policy_Vind,:); |
47 | 108 | EVKrontemp=EVKrontemp.*aaa;
|
48 | 109 | EVKrontemp(isnan(EVKrontemp))=0;
|
49 |
| - EVKrontemp=reshape(sum(EVKrontemp,2),[N_a,N_z]); |
50 |
| - VKron=Ftemp+DiscountFactorParamsVec*EVKrontemp; |
| 110 | + EVKrontemp=sum(EVKrontemp,2); |
| 111 | + V=Ftemp+DiscountFactorParamsVec*reshape(EVKrontemp,[N_a,N_z]); |
| 112 | + end |
| 113 | + end |
| 114 | + |
| 115 | + if vfoptions.verbose==1 |
| 116 | + if rem(tempcounter,10)==0 % Every 10 iterations |
| 117 | + fprintf(distvstolstr, tempcounter,currdist) % use enough decimal points to be able to see countdown of currdist to 0 |
51 | 118 | end
|
52 | 119 | end
|
53 | 120 |
|
54 | 121 | tempcounter=tempcounter+1;
|
| 122 | +end |
| 123 | + |
55 | 124 |
|
| 125 | + |
| 126 | + |
| 127 | +%% Cleaning up the output |
| 128 | +if vfoptions.outputkron==0 |
| 129 | + V=reshape(V,[n_a,n_z]); |
| 130 | + Policy=UnKronPolicyIndexes_Case1(Policy, 0, n_a, n_z,vfoptions); |
| 131 | +else |
| 132 | + return |
56 | 133 | end
|
57 | 134 |
|
58 |
| -Policy=reshape(PolicyIndexes,[N_a,N_z]); |
| 135 | +if vfoptions.polindorval==2 |
| 136 | + Policy=PolicyInd2Val_Case1(Policy,0,n_a,n_z,d_grid, a_grid); |
| 137 | +end |
| 138 | + |
| 139 | +% Sometimes numerical rounding errors (of the order of 10^(-16) can mean |
| 140 | +% that Policy is not integer valued. The following corrects this by converting to int64 and then |
| 141 | +% makes the output back into double as Matlab otherwise cannot use it in |
| 142 | +% any arithmetical expressions. |
| 143 | +if vfoptions.policy_forceintegertype==1 |
| 144 | + Policy=uint64(Policy); |
| 145 | + Policy=double(Policy); |
| 146 | +end |
59 | 147 |
|
60 | 148 |
|
61 | 149 |
|
|
0 commit comments