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;

Program Listing

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.

Figure 19.85 LIST Output for Segmented Model
QUADRATIC MODEL WITH PLATEAU

The MODEL Procedure

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.

Cross-Reference

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.

Figure 19.86 XREF Output for Segmented Model
QUADRATIC MODEL WITH PLATEAU

The MODEL Procedure

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

Compiler Listing

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.

Figure 19.87 LISTCODE Output for Segmented Model—Statements as Parsed
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;

Figure 19.88 LISTCODE Output for Segmented Model—Compiled Code
     
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