CAUSALDISCOVERY Procedure

Getting Started: CAUSALDISCOVERY Procedure

This example illustrates how the CAUSALDISCOVERY procedure estimates the DAG from which the data are generated, in order to solve a seven-variable DAG structure learning problem.

The following DATA step produces the simulated data set to be used in the example:

   data one;
      input x1 - x7;
   datalines;
    0.6712068564    -0.2826079580    -0.5349256450    -0.8261341320
    -3.0394109400    -1.8825135390    5.2510795861
    -0.7107886740    -2.4798707050    1.2698001196    -6.2078732110
    -14.3827270100    -11.0299665000    20.9643672460

   ... more lines ...   

    -0.5282917840    0.4435880321    -0.6905104940    0.4259155417
    -0.1943036260    0.6881816788    -0.6409083280
    -0.3955187900    -0.5117192740    -1.0742776010    0.7085965238
    2.1642802138    1.5589762381    -2.7343111790
    ;

What is the relationship among these seven variables? That is the question that the DAG structure learning is trying to answer. Note that as the number of variables increases, the number of DAGs increases superexponentially. When the number of variables is seven, there are more than one billion seven-variable DAGs. Finding the one true DAG from which the data are generated is not easy. However, PROC CAUSALDISCOVERY might help you find that DAG in seconds or even less than a second.

The following DATA step loads the data set one into the data table one in your session that is associated with the mylib libref. The DATA step assumes that your libref is named mylib, but you can substitute any appropriately defined libref.

data mylib.one; set one; run;

The following code inputs the data set, specifies the variables, and names the output data table. The INITMETHOD=DATA option in the LEARN statement shows whether there is any difference between the topological order of the final estimated DAG and the order that is specified in the VAR statement.

proc causaldiscovery;
   var x1 - x7;
   learn data=mylib.one / initmethod=data out=mylib.oest;
run;

The number of observations is shown in Figure 1.

Figure 1: Number of Observations

The CAUSALDISCOVERY Procedure

Number of Observations Read10000
Number of Observations Used10000


The algorithm information is shown in Figure 2.

Figure 2: Algorithm Information

The CAUSALDISCOVERY Procedure

Algorithm Information
AlgorithmTopological Order Permutation
Initialization MethodData
Maximum Iterations200
ParallelYes
Seed1


The topological orders are shown in Figure 3. This table shows that there is a difference between the topological order of the final estimated DAG and the order that is specified in the VAR statement.

Figure 3: Initial and Final Topological Orders

Topological Orders
VariableInitial OrderFinal Order
x111
x223
x332
x444
x556
x665
x777


The estimated full DAG that is expressed as the adjacency matrix is shown in Figure 4. In an adjacency matrix , element is either 0 or 1. If , this means that there is no edge from variable i to variable j; otherwise, there is an edge from variable i to variable j (that is, variable i is a parent of variable j, or variable j is a child of variable i).

Figure 4: Estimated Full Adjacency Matrix

Estimated Full
Adjacency Matrix
Variablex1x2x3x4x5x6x7
x10111111
x20001111
x30101111
x40000111
x50000001
x60000101
x70000000


The estimated DAG based on the significance level 0.0001% is shown in Figure 5.

Figure 5: Estimated Adjacency Matrices Based on the Significance Level 0.0001%

Estimated Adjacency Matrices
AlphaVariablex1x2x3x4x5x6x7
1E-6x10100000
 x20001100
 x30101010
 x40000010
 x50000000
 x60000101
 x70000000


As shown in the adjacency matrix in Figure 5, X1 and X3 have no parents; X2’s parents are X1 and X3; X4’s parents are X2 and X3; X5’s parents are X2 and X6; X6’s parents are X3 and X4; and X7’s parent is X6. Figure 6 shows this seven-variable DAG.

Figure 6: Estimated DAG

Estimated DAG


In fact, this estimated DAG is the true DAG for the data generating process, as shown in the following SAS code:

data one;
   call streaminit('pcg', 12345);
   x1 = 0; x2 = 0; x3 = 0; x4 = 0;
   x5 = 0; x6 = 0; x7 = 0;
   do i = 1 to 10000;
      x1 = rand('Normal');
      x3 = rand('Normal');
      x2 = x1 - 0.5*x3 + rand('Normal');
      x4 = 1.5*x2 - x3 + rand('Normal');
      x6 = 0.5*x3 + 2*x4 + rand('Normal');
      x5 = -x2 + 1.5*x6 + rand('Normal');
      x7 = -2*x6 + rand('Normal');
      output;
   end;
   drop i;
run;
Last updated: July 09, 2026