Diagnostics and Debugging |
PROC MODEL provides several features to aid in finding errors in the model program. These debugging features are not usually needed; most models can be developed without them.
The example model program that follows is used in the following sections to illustrate the diagnostic and debugging capabilities. This example is the estimation of a segmented model.
/*--- Diagnostics and Debugging ---*/ *---------Fitting a Segmented Model using MODEL----* | | | | y | quadratic plateau | | | y=a+b*x+c*x*x y=p | | | ..................... | | | . : | | | . : | | | . : | | | . : | | | . : | | +-----------------------------------------X | | x0 | | | | continuity restriction: p=a+b*x0+c*x0**2 | | smoothness restriction: 0=b+2*c*x0 so x0=-b/(2*c)| *--------------------------------------------------*; title 'QUADRATIC MODEL WITH PLATEAU'; data a; input y x @@; datalines; .46 1 .47 2 .57 3 .61 4 .62 5 .68 6 .69 7 .78 8 .70 9 .74 10 .77 11 .78 12 .74 13 .80 13 .80 15 .78 16 ; proc model data=a list xref listcode; parms a 0.45 b 0.5 c -0.0025; x0 = -.5*b / c; /* join point */ if x < x0 then /* Quadratic part of model */ y = a + b*x + c*x*x; else /* Plateau part of model */ y = a + b*x0 + c*x0*x0; fit y; run;
The LIST option produces a listing of the model program. The statements are printed one per line with the original line number and column position of the statement.
The program listing from the example program is shown in Figure 19.85.
QUADRATIC MODEL WITH PLATEAU |
Listing of Compiled Program Code | ||
---|---|---|
Stmt | Line:Col | Statement as Parsed |
1 | 4043:4 | x0 = (-0.5 * b) / c; |
2 | 4044:4 | if x < x0 then |
3 | 4045:7 | PRED.y = a + b * x + c * x * x; |
3 | 4045:7 | RESID.y = PRED.y - ACTUAL.y; |
3 | 4045:7 | ERROR.y = PRED.y - y; |
4 | 4046:4 | else |
5 | 4047:7 | PRED.y = a + b * x0 + c * x0 * x0; |
5 | 4047:7 | RESID.y = PRED.y - ACTUAL.y; |
5 | 4047:7 | ERROR.y = PRED.y - y; |
The LIST option also shows the model translations that PROC MODEL performs. LIST output is useful for understanding the code generated by the %AR and the %MA macros.
The XREF option produces a cross-reference listing of the variables in the model program. The XREF listing is usually used in conjunction with the LIST option. The XREF listing does not include derivative (@-prefixed) variables. The XREF listing does not include generated assignments to equation variables, PRED., RESID., and ERROR.-prefixed variables, unless the DETAILS option is used.
The cross-reference from the example program is shown in Figure 19.86.
QUADRATIC MODEL WITH PLATEAU |
Cross Reference Listing For Program | |||
---|---|---|---|
Symbol----------- | Kind | Type | References (statement)/(line):(col) |
a | Var | Num | Used: 3/57202:13 5/57204:13 |
b | Var | Num | Used: 1/57200:12 3/57202:16 5/57204:16 |
c | Var | Num | Used: 1/57200:15 3/57202:22 5/57204:23 |
x0 | Var | Num | Assigned: 1/57200:15 |
Used: 2/57201:11 5/57204:16 5/57204:23 5/57204:26 | |||
x | Var | Num | Used: 2/57201:11 3/57202:16 3/57202:22 3/57202:24 |
PRED.y | Var | Num | Assigned: 3/57202:19 5/57204:20 |
The LISTCODE option lists the model code and derivatives tables produced by the compiler. This listing is useful only for debugging and should not normally be needed.
LISTCODE prints the operator and operands of each operation generated by the compiler for each model program statement. Many of the operands are temporary variables generated by the compiler and given names such as #temp1. When derivatives are taken, the code listing includes the operations generated for the derivatives calculations. The derivatives tables are also listed.
A LISTCODE option prints the transformed equations from the example shown in Figure 19.87 and Figure 19.88.
Derivatives | ||
---|---|---|
WRT-Variable | Object-Variable | Derivative-Variable |
a | RESID.y | @RESID.y/@a |
b | RESID.y | @RESID.y/@b |
c | RESID.y | @RESID.y/@c |
Listing of Compiled Program Code | ||
---|---|---|
Stmt | Line:Col | Statement as Parsed |
1 | 4043:4 | x0 = (-0.5 * b) / c; |
1 | 4043:4 | @x0/@b = -0.5 / c; |
1 | 4043:4 | @x0/@c = - x0 / c; |
2 | 4044:4 | if x < x0 then |
3 | 4045:7 | PRED.y = a + b * x + c * x * x; |
3 | 4045:7 | @PRED.y/@a = 1; |
3 | 4045:7 | @PRED.y/@b = x; |
3 | 4045:7 | @PRED.y/@c = x * x; |
3 | 4045:7 | RESID.y = PRED.y - ACTUAL.y; |
3 | 4045:7 | @RESID.y/@a = @PRED.y/@a; |
3 | 4045:7 | @RESID.y/@b = @PRED.y/@b; |
3 | 4045:7 | @RESID.y/@c = @PRED.y/@c; |
3 | 4045:7 | ERROR.y = PRED.y - y; |
4 | 4046:4 | else |
5 | 4047:7 | PRED.y = a + b * x0 + c * x0 * x0; |
5 | 4047:7 | @PRED.y/@a = 1; |
5 | 4047:7 | @PRED.y/@b = x0 + b * @x0/@b + (c * @x0/@b * x0 + c * x0 * @x0/@b); |
5 | 4047:7 | @PRED.y/@c = b * @x0/@c + ((x0 + c * @x0/@c) * x0 + c * x0 * @x0/@c); |
5 | 4047:7 | RESID.y = PRED.y - ACTUAL.y; |
5 | 4047:7 | @RESID.y/@a = @PRED.y/@a; |
5 | 4047:7 | @RESID.y/@b = @PRED.y/@b; |
5 | 4047:7 | @RESID.y/@c = @PRED.y/@c; |
5 | 4047:7 | ERROR.y = PRED.y - y; |
1 Stmt ASSIGN | line 4043 column 4. (1) arg=x0 argsave=x0 | |
Source Text: | x0 = -.5*b / c; | |
Oper * | at 4043:12 (30,0,2). | * : _temp1 <- -0.5 b |
Oper / | at 4043:15 (31,0,2). | / : x0 <- _temp1 c |
Oper eeocf | at 4043:15 (18,0,1). | eeocf : _DER_ <- _DER_ |
Oper / | at 4043:15 (31,0,2). | / : @x0/@b <- -0.5 c |
Oper - | at 4043:15 (24,0,1). | - : @1dt1_2 <- x0 |
Oper / | at 4043:15 (31,0,2). | / : @x0/@c <- @1dt1_2 c |
2 Stmt IF | line 4044 column 4. (2) arg=_temp1 argsave=_temp1 | ref.st=ASSIGN stmt number 5 at 4047:7 |
Source Text: | if x < x0 then | |
Oper < | at 4044:11 (36,0,2). | < : _temp1 <- x x0 |
3 Stmt ASSIGN | line 4045 column 7. (1) arg=PRED.y argsave=y | |
Source Text: | /* Quadratic part of model */ y = a + b*x + c*x*x; | |
Oper * | at 4045:16 (30,0,2). | * : _temp1 <- b x |
Oper + | at 4045:13 (32,0,2). | + : _temp2 <- a _temp1 |
Oper * | at 4045:22 (30,0,2). | * : _temp3 <- c x |
Oper * | at 4045:24 (30,0,2). | * : _temp4 <- _temp3 x |
Oper + | at 4045:19 (32,0,2). | + : PRED.y <- _temp2 _temp4 |
Oper eeocf | at 4045:19 (18,0,1). | eeocf : _DER_ <- _DER_ |
Oper = | at 4045:19 (1,0,1). | = : @PRED.y/@a <- 1 |
Oper = | at 4045:19 (1,0,1). | = : @PRED.y/@b <- x |
Oper * | at 4045:24 (30,0,2). | * : @1dt1_1 <- x x |
Oper = | at 4045:19 (1,0,1). | = : @PRED.y/@c <- @1dt1_1 |
3 Stmt Assign | line 4045 column 7. (1) arg=RESID.y argsave=y | |
Oper - | at 4045:7 (33,0,2). | - : RESID.y <- PRED.y ACTUAL.y |
Oper eeocf | at 4045:7 (18,0,1). | eeocf : _DER_ <- _DER_ |
Oper = | at 4045:7 (1,0,1). | = : @RESID.y/@a <- @PRED.y/@a |
Oper = | at 4045:7 (1,0,1). | = : @RESID.y/@b <- @PRED.y/@b |
Oper = | at 4045:7 (1,0,1). | = : @RESID.y/@c <- @PRED.y/@c |
3 Stmt Assign | line 4045 column 7. (1) arg=ERROR.y argsave=y | |
Oper - | at 4045:7 (33,0,2). | - : ERROR.y <- PRED.y y |
4 Stmt ELSE | line 4046 column 4. (9) | ref.st=FIT stmt number 5 at 4049:4 |
Source Text: | else | |
5 Stmt ASSIGN | line 4047 column 7. (1) arg=PRED.y argsave=y | |
Source Text: | /* Plateau part of model */ y = a + b*x0 + c*x0*x0; | |
Oper * | at 4047:16 (30,0,2). | * : _temp1 <- b x0 |
Oper + | at 4047:13 (32,0,2). | + : _temp2 <- a _temp1 |
Oper * | at 4047:23 (30,0,2). | * : _temp3 <- c x0 |
Oper * | at 4047:26 (30,0,2). | * : _temp4 <- _temp3 x0 |
Oper + | at 4047:20 (32,0,2). | + : PRED.y <- _temp2 _temp4 |
Oper eeocf | at 4047:20 (18,0,1). | eeocf : _DER_ <- _DER_ |
Oper = | at 4047:20 (1,0,1). | = : @PRED.y/@a <- 1 |
Oper * | at 4047:16 (30,0,2). | * : @1dt1_1 <- b @x0/@b |
Oper + | at 4047:16 (32,0,2). | + : @1dt1_2 <- x0 @1dt1_1 |
Oper * | at 4047:23 (30,0,2). | * : @1dt1_3 <- c @x0/@b |
Oper * | at 4047:26 (30,0,2). | * : @1dt1_4 <- @1dt1_3 x0 |
Oper * | at 4047:26 (30,0,2). | * : @1dt1_5 <- _temp3 @x0/@b |
Oper + | at 4047:26 (32,0,2). | + : @1dt1_6 <- @1dt1_4 @1dt1_5 |
Oper + | at 4047:20 (32,0,2). | + : @PRED.y/@b <- @1dt1_2 @1dt1_6 |
Oper * | at 4047:16 (30,0,2). | * : @1dt1_8 <- b @x0/@c |
Oper * | at 4047:23 (30,0,2). | * : @1dt1_9 <- c @x0/@c |
Oper + | at 4047:23 (32,0,2). | + : @1dt1_10 <- x0 @1dt1_9 |
Oper * | at 4047:26 (30,0,2). | * : @1dt1_11 <- @1dt1_10 x0 |
Oper * | at 4047:26 (30,0,2). | * : @1dt1_12 <- _temp3 @x0/@c |
Oper + | at 4047:26 (32,0,2). | + : @1dt1_13 <- @1dt1_11 @1dt1_12 |
Oper + | at 4047:20 (32,0,2). | + : @PRED.y/@c <- @1dt1_8 @1dt1_13 |
5 Stmt Assign | line 4047 column 7. (1) arg=RESID.y argsave=y | |
Oper - | at 4047:7 (33,0,2). | - : RESID.y <- PRED.y ACTUAL.y |
Oper eeocf | at 4047:7 (18,0,1). | eeocf : _DER_ <- _DER_ |
Oper = | at 4047:7 (1,0,1). | = : @RESID.y/@a <- @PRED.y/@a |
Oper = | at 4047:7 (1,0,1). | = : @RESID.y/@b <- @PRED.y/@b |
Oper = | at 4047:7 (1,0,1). | = : @RESID.y/@c <- @PRED.y/@c |
5 Stmt Assign | line 4047 column 7. (1) arg=ERROR.y argsave=y | |
Oper - | at 4047:7 (33,0,2). | - : ERROR.y <- PRED.y y |