Resources

How can I use variables created by varput in a loop for other operations?

0

Suppose that I have this code, and I want to automate some operations:

rho=5;
names=("a" $~ "b" $~ "d");
nums=(1 ~ 2 ~3);
lambda_1=8;
lambda_2=9;
lambda_3=10;

for i (1,3,1);
   varput(nums[i],"VE"$+names[i] );
   //I now need to sum rho+"VE"$+names[i] (VEa, VEb, VEd)
   //I Also now need to sum rho+"VE"$+names[i]+lambda"i"
endfor;

// To do this operations know I need to do something like that, how can a I do this into a loop?
res1=rho+VEa+lambda_1;
res2=rho+VEb+lambda_2;
res3=rho+VEd+lambda_3;
print res1 res2 res3;

   1.0000000
   1.0000000
   1.0000000
   14.000000 16.000000 18.000000

How can I do that?

Thank you for your help!

 

Tags: asked August 27, 2013

5 Answers

0

The problem
I am assuming that you are getting the error “Undefined symbols”. What is happening is that GAUSS is checking your program at compile-time (when it turns the text on page into something that the computer can execute) to make sure that all of the symbols are defined. However, the variables created by varput are not actually created until run-time (when the compiled program is actually executed).

You can see this for yourself by commenting out these lines below from your program.

res1=rho+VEa+lambda_1;
res2=rho+VEb+lambda_2;
res3=rho+VEd+lambda_3;
print res1 res2 res3;

Now run your program with them commented out. It will run successfully and it will create the variables VEa, VEb, etc. So, you can now uncomment those 4 lines above and re-run your program and it will succeed.

The Solution
If you are going to do this one time, commenting out the code or just running the loop by itself is fine. If this is part of a program that will be run over and over many times, however, you will want to be able to just run one file.

To do this you will want to declare your new variables before they are created by varput. You can do this in a number of ways. The simplest would be to add the statements VEa = 0; VEb = 0; VEd = 0; to the top of your program.

A more advanced method would be to create a declaration file. For this example, we will make a file called myvars.dec. Its contents will be:

declare VEa ?= 0;
declare VEb ?= 0;
declare VEd ?= 0;

Explanation of the declare statement
The declare command creates a variable at compile time which will prevent the “Undefined symbol” errors. You can add a declare statement before any constant numerical assignment. For example, these are legal:

declare a = 5;
declare b = { 6, 7 }; 

However, these are not legal:

declare a = rndn(1,1);
declare a = b;

If you add a question mark before the equals sign:

declare a ?= 0;

That tells GAUSS to first check to see if that variable already exists. If it DOES already exist, then GAUSS will leave it alone. However, if it DOES NOT exist, then GAUSS will create it and assign it a value of zero.

Automating the creation of a declare file
You can have GAUSS create a declare file for you like this:

output file=myvars.dec reset;
for i(1, 3, 1);
	print "declare VE"$+names[i]$+" ?= 0;";
endfor;
output off;

Then you can add this declaration file, myvars.dec, to your user library or by adding a #include statement to the top of your program.

aptech
227
0

Thank you for your answer.

Actually my code doesn´t have any mistake.

res1=rho+VEa+lambda_1;
res2=rho+VEb+lambda_2;
res3=rho+VEd+lambda_3;
print res1 res2 res3;

Those lines generate the last print on the answer that i sent before (14.000000 16.000000 18.000000). What I need to do is to automatice this process, something like:

for i (1,3,1);
   res"i"=rho+VE$+names[i]+lambda_"i";
endfor;

I dont know how can I do this into the Gauss language, said that I want to do this loop 1000 times, it would be very expensive to do

res1=rho+VEa+lambda_1;
.   =   .
.   =   .
.   =   .
res1000=rho+VEawq+lambda_1000;

This is my quesion, how can I do that?

0

I think you want to avoid creating all of those individual variables. Instead keep the data as vectors like this:

rho = 5;
nums = { 1 2 3 };
lambda = { 8, 9, 10 };

res = rho + nums' + lambda;

This will be much, much faster and the code is simpler. Then instead of:

print res1 res2 res3;

You would say either:

print res;

or

print res';

or if you needed to:

print res[1] res[2] res[3];
aptech
227
0

Hi in vectors this work very well my problem is the next(This is my code):

N_Theta = 5 ;
theta_grid = ( 0 | 0.3 | 0.5 | 0.7 | 1 ) ;
P_theta = (0.2 | 0.2 | 0.2 | 0.2 | 0.2) ;

N_Wage = 9 ;
Wage_Truncation = 100 ;
w_0 = 2 ;
w_grid = seqa(w_0,(Wage_Truncation-w_0)/(N_Wage-1),N_Wage)' ;
w_grid_W = w_grid' ; w_grid_M = w_grid' ;

E_Wage_W_hs = 50 ; V_Wage_W_hs = 30 ;
E_Wage_W_ls = 0.85*E_Wage_W_hs ; V_Wage_W_ls = 0.85*V_Wage_W_hs ;
E_Wage_M_hs = 68 ; V_Wage_M_hs = 100 ;
E_Wage_M_ls = 0.85*E_Wage_M_hs ; V_Wage_M_ls = 0.85*V_Wage_M_hs ;

sigma_wage_W_ls = sqrt(log(V_Wage_W_ls/E_Wage_W_ls+1)) ;
mu_wage_W_ls = log(E_Wage_W_ls)-sigma_wage_W_ls^2/2 ;
sigma_wage_W_hs = sqrt(log(V_Wage_W_hs/E_Wage_W_hs+1)) ;
mu_wage_W_hs = log(E_Wage_W_hs)-sigma_wage_W_hs^2/2 ;
sigma_wage_M_ls = sqrt(log(V_Wage_M_ls/E_Wage_M_ls+1)) ;
mu_wage_M_ls = log(E_Wage_M_ls)-sigma_wage_M_ls^2/2 ;
sigma_wage_M_hs = sqrt(log(V_Wage_M_hs/E_Wage_M_hs+1)) ;
mu_wage_M_hs = log(E_Wage_M_hs)-sigma_wage_M_hs^2/2 ;

P_W_ls = cdfn((ln(w_grid_W)-mu_wage_W_ls)./sigma_wage_W_ls)/cdfn((ln(Wage_Truncation)-mu_wage_W_ls)./sigma_wage_W_ls) ;
P_W_ls = P_W_ls - (0 | P_W_ls[1:rows(P_W_ls)-1]) ;
P_M_ls = cdfn((ln(w_grid_M)-mu_wage_M_ls)./sigma_wage_M_ls)/cdfn((ln(Wage_Truncation)-mu_wage_M_ls)./sigma_wage_M_ls) ;
P_M_ls = P_M_ls - (0 | P_M_ls[1:rows(P_M_ls)-1]) ;

P_W_hs = cdfn((ln(w_grid_W)-mu_wage_W_hs)./sigma_wage_W_hs)/cdfn((ln(Wage_Truncation)-mu_wage_W_hs)./sigma_wage_W_hs) ;
P_W_hs = P_W_hs - (0 | P_W_hs[1:rows(P_W_hs)-1]) ;
P_M_hs = cdfn((ln(w_grid_M)-mu_wage_M_hs)./sigma_wage_M_hs)/cdfn((ln(Wage_Truncation)-mu_wage_M_hs)./sigma_wage_M_hs) ;
P_M_hs = P_M_hs - (0 | P_M_hs[1:rows(P_M_hs)-1]) ;

//// Model Parameters
// Shocks
lambda_W_ls = 0.7*0.35 ;
lambda_W_hs = 0.35 ;
lambda_M_ls = 0.7*0.3 ;
lambda_M_hs = 0.35 ;
gama_W = 0.05 ;
gama_M = 0.05 ;
eta_W_ls = 0.7*0.025;
eta_W_hs = 0.025 ;
eta_M_ls = 0.7*1/(0.03) ;
eta_M_hs = 1/(0.03) ;
delta = 0.001 ;

// Utility
rho = 0.02 ;
sigma_W = 0.25 ;
sigma_M = 0.25 ;

// Hours
h_ft = 8*5 ;
h_pt = 4*5 ;
// Endowment
T = 16*5 ;
Y_W = (118.15/2) ;
Y_M = (118.15/2) ;

// Women
U_W_su = sigma_W*ln(T) + (1-sigma_W)*ln(Y_W) ;
U_W_se = sigma_W*ln(T-h_ft) + (1-sigma_W)*ln(w_grid_W*h_ft+Y_W) ;
U_W_muu = areshape(sigma_W*ln(T) + (1-sigma_W)*ln(Y_W+Y_M) ,N_Theta|1|1) + areshape(theta_grid,N_Theta|1|1) ;
U_W_mue = areshape(sigma_W*ln(T) + (1-sigma_W)*ln(w_grid_M*h_ft+Y_W+Y_M),N_Theta|N_Wage|1) + atranspose( areshape(theta_grid,1|N_wage|N_Theta), 3|2|1 ) ;
U_W_meu = areshape(sigma_W*ln(T-h_ft) + (1-sigma_W)*ln(w_grid_W*h_ft+Y_W+Y_M),N_Theta|N_Wage|1) + atranspose( areshape(theta_grid,1|N_wage|N_Theta), 3|2|1 ) ;
U_W_mee = areshape(sigma_W*ln(T-h_ft) + (1-sigma_W)*ln(w_grid_W.*.ones(1,N_Wage)*h_ft+(w_grid_M.*.ones(1,N_Wage))'*h_ft+Y_W+Y_M) ,N_Theta|N_wage|N_wage) +
atranspose( areshape(theta_grid,1|N_wage|N_Theta), 3|2|1 ) ;

// Men
U_M_su = sigma_M*ln(T) + (1-sigma_M)*ln(Y_M) ;
U_M_se = sigma_M*ln(T-h_ft) + (1-sigma_M)*ln(w_grid_M*h_ft+Y_M) ;
U_M_muu = areshape(sigma_M*ln(T) + (1-sigma_M)*ln(Y_M+Y_W) ,N_Theta|1|1) + areshape(theta_grid,N_Theta|1|1) ;
U_M_mue = areshape(sigma_M*ln(T) + (1-sigma_M)*ln(w_grid_W*h_ft+Y_M+Y_W),N_Theta|N_Wage|1) + atranspose( areshape(theta_grid,1|N_Wage|N_Theta), 3|2|1 ) ;
U_M_meu = areshape(sigma_M*ln(T-h_ft) + (1-sigma_M)*ln(w_grid_M*h_ft+Y_M+Y_W),N_Theta|N_Wage|1) + atranspose( areshape(theta_grid,1|N_Wage|N_Theta), 3|2|1 ) ;
U_M_mee = areshape(sigma_M*ln(T-h_ft) + (1-   sigma_M)*ln(w_grid_M.*.ones(1,N_Wage)*h_ft+(w_grid_W.*.ones(1,N_Wage))'*h_ft+Y_M+Y_W) ,N_Theta|N_Wage|N_Wage) +
atranspose( areshape(theta_grid,1|N_Wage|N_Theta), 3|2|1 ) ;

The code is running but I want to do loops as in SAS or STATA where you can declare  diferents variables that depends on diferents inputs.  Sometimes the names that I want to automatize are vectors, martices and arrays. I have Men and Women, and persons with high schooling and low schooling. For example, I want to put the part with  sigma_wage_¨gender¨_¨schooling¨ or  the  U_¨gender¨_mee into a loop.

I think that with the varput I can declare the variables but I don´t know how to call those variables in order to use them in another processes (inside or outside the same loop).

Thank you.

0

OK, I think I am understanding what you are trying to do. You can use the GAUSS function varget like this:

rho = 5;
string names = { "a" "b" "d" };
nums = { 1 2 3 };
lambda_1 = 8;
lambda_2 = 9;
lambda_3 = 10;


for i(1, 3, 1);
	varput(nums[i],"VE"$+names[i] );
endfor;

for i(1, 3, 1);
	string_counter = ftos(i, "%*.*lf", 0, 0);
	VEtmp = varget("VE"$+names[i]);
	lambdatmp = varget("lambda_" $+ string_counter);
	varput(rho + VEtmp + lambdatmp, "res" $+ string_counter);
endfor;

for i(1, 3, 1);
	print varget("res"$+ftos(i, "%*.*lf", 0, 0));
endfor;

However, I would strongly suggest that you use some combination of vectors, matrices or arrays to hold your data. Using matrices, all of the code above can be reduced to:

rho = 5;
string names = { "a" "b" "d" };
nums = { 1 2 3 };
lambda = seqa(8, 1, 3);

res = rho + nums' + lambda;
print res;

If you need to reference elements of res or lambda, you can index into the vector or matrix in a loop. The rest of your program can be shortened dramatically this way and it will also run much faster.

aptech
227