0.5.0 release card: temporal causal discovery#
Release card
Temporal causal discovery
0.5.0
We compare Andrey’s time-series methods with the packages that implement them: PCMCI, PCMCI+, and LPCMCI with tigramite, lasso Granger causality with causal-learn, and VARMA-LiNGAM and LongitudinalLiNGAM with lingam. PCMCI+ runs more than 50x faster than tigramite at every size, and more than 100x at 80 variables and 2,000 time steps. PCMCI runs more than 20x faster at 10 variables, where it has fewer errors than the empty graph. Both return the same graph as tigramite on every dataset. LPCMCI runs more than 8x faster at every size, and LongitudinalLiNGAM more than 1.3x faster than lingam. We support these methods from 0.5.0.
Speed is not accuracy. On the larger graphs, both packages’ PCMCI results have more errors than the empty graph (see Known limits). You can find speedups and accuracy in the summary, and measurement and scoring definitions in how to read the results. These results apply to the measured workloads. Speed and accuracy depend on the data, settings, and hardware.
Summary#
tigramite, causal-learn, and lingam are the baselines, each for the methods it implements. We report every paired speed ratio, regardless of accuracy.
Speed.
Method |
Compared with |
Variables ( |
Length ( |
Cores per fit |
Andrey speedup |
|---|---|---|---|---|---|
PCMCI |
tigramite |
10-160 |
500-2,000 |
4 |
23.2-166x |
PCMCI+ |
tigramite |
10-80 |
500-2,000 |
4 |
52.0-116x |
LPCMCI |
tigramite |
5-20 |
500-2,000 |
4 |
8.56-18.7x |
Granger |
causal-learn |
10-160 |
1,000 |
4 |
1.59-3.34x |
VARMA-LiNGAM |
lingam |
3-20 |
100-1,000 |
4 |
0.962-1.13x |
LongitudinalLiNGAM |
lingam |
2-5 |
20-50 |
4 |
1.33-2.24x |
Each bar is the median, over the datasets of that size, of the other package's time divided by Andrey's on the same dataset. Each method's bars share its own scale.
Accuracy.
Method |
Compared with |
Datasets |
Same graph |
Andrey ahead |
Other ahead |
|---|---|---|---|---|---|
PCMCI |
tigramite |
125 |
125 of 125 |
0 |
0 |
PCMCI+ |
tigramite |
110 |
110 of 110 |
0 |
0 |
LPCMCI |
tigramite |
90 |
73 of 90 |
12 |
5 |
Granger |
causal-learn |
50 |
50 of 50 |
0 |
0 |
VARMA-LiNGAM |
lingam |
105 |
51 of 105 |
18 |
18 |
LongitudinalLiNGAM |
lingam |
240 |
231 of 240 |
8 |
1 |
“Ahead” counts the datasets on which that package’s graph has fewer errors than the other’s, and “Other” is the compared package. On the rest, the two have the same number of errors.
How to read the results#
Data. We run each method on its paper’s simulation, with one dataset per seed. PCMCI runs on
pcmci_paper (Runge et al., 2019): linear-Gaussian series in which every variable depends on its
own previous step, with one cross-link per variable at lag 1 or 2 and no same-step links. PCMCI+
runs on pcmciplus_paper (Runge, 2020), with strong autocorrelation and 1.5 cross-links per
variable, 30% of them within a time step and the rest at lags 1 to 5. LPCMCI runs on lpcmci_paper
(Gerhardus and Runge, 2020), like PCMCI+’s simulation, with lags up to 3 and 30% of the series
unobserved. Granger runs on var2_lagged: linear-Gaussian VAR(2) series with no same-step links and
each variable z-scored. VARMA-LiNGAM runs on varma_lingam_paper (Hyvarinen et al., 2010): a linear
series with non-Gaussian noise, a same-step DAG, a lag-1 matrix, and a moving-average matrix.
LongitudinalLiNGAM runs on longitudinal_lingam_paper (Kadowaki et al., 2013): M units observed
at n time points, with a same-step DAG and a lag-1 matrix drawn anew at every time point and a
hidden common cause at the first. d is the number of variables (series), and n is the number of
time steps. There are 10 datasets per rung, except 5 for PCMCI at 160 variables and VARMA-LiNGAM at
20 variables.
Accuracy. We count each method’s errors in its own unit, defined in its section below. Lower is
better. The empty graph’s errors are the true links it misses. F1 measures the window causal graph’s
cross-links: links between two different variables, at a lag or within a time step. It leaves out
each variable’s links from its own past (Assaad et al., 2022, Sect. 9.1). LPCMCI’s adjacency F1 is
defined in its section. Errors are medians over a rung’s datasets, and F1 is reported per rung.
“Same graph” means equal structure_hash values: the same links at every lag, with the same marks
or weights.
Timing. Times are seconds per fit, the median over a rung’s datasets; each dataset is fitted once. For each dataset, we divide the other package’s time by Andrey’s, then report the median of these paired ratios. This need not equal the ratio of the displayed median times. No fit reached its time limit. Times and ratios have three significant figures, as in the summary.
Hardware. Every fit ran on an Intel Core i7-7820X with 4 cores per fit.
Benchmark results#
Comparison |
d |
Andrey build |
Measured package versions |
|---|---|---|---|
PCMCI |
10-160 |
Pre-release 0.5.0, October 13, 2026 |
tigramite 5.2.10.1 |
PCMCI+ |
10-80 |
Pre-release 0.5.0, October 13, 2026 |
tigramite 5.2.10.1 |
LPCMCI |
5-20 |
Pre-release 0.5.0, October 13, 2026 |
tigramite 5.2.10.1 |
Granger |
10-160 |
Pre-release 0.5.0, October 13, 2026 |
causal-learn 0.1.4.8 |
VARMA-LiNGAM |
3-20 |
Pre-release 0.5.0, October 15, 2026 |
lingam 1.13.0 |
LongitudinalLiNGAM |
2-5 |
Pre-release 0.5.0, October 15, 2026 |
lingam 1.13.0 |
We measured pre-release Andrey 0.5.0 builds with the dates shown in the table. VARMA-LiNGAM ran in
lingam’s own environment (Python 3.12.3, NumPy 2.2.6, SciPy 1.13.1, statsmodels 0.15.0), so both
packages fit the model with the same numerical libraries. The
summary contains one
row per method and rung. Each row gives median seconds, the paired ratio, the datasets both packages
finished (paired), and those with the same graph (same_graph). It also gives each package’s
errors beside the empty graph’s, the datasets on which each has fewer errors, and F1. fits,
andrey_ok, and comparator_ok count the fits and those that finished.
Time-series methods#
These methods learn causal links in data ordered in time, from a variable’s past to another’s present. PCMCI+, LPCMCI, and the two LiNGAM methods also learn links within a time step.
PCMCI#
PCMCI finds the lagged links of a multivariate series in two steps. Its condition-selection step
keeps, for each variable, the past values its own tests cannot remove. It then runs a momentary
conditional independence test for each lagged pair, conditioned on the parents kept at both ends.
Both packages test with Student-t partial correlation at lags 1 to 2, with pc_alpha 0.2 and
alpha_level 0.05. The output is one directed graph per lag. Errors are the lag-resolved SHD: we
count the links that differ from the true links at each lag, with a reversed link counting 2, then
sum over the lags.
d |
n |
Andrey (s) |
tigramite (s) |
Speedup |
|---|---|---|---|---|
10 |
500 |
0.0316 |
0.688 |
23.2x |
10 |
1,000 |
0.0308 |
0.816 |
24.0x |
10 |
2,000 |
0.0354 |
0.988 |
27.4x |
20 |
500 |
0.0481 |
2.56 |
51.4x |
20 |
1,000 |
0.0573 |
3.19 |
58.8x |
20 |
2,000 |
0.0518 |
3.95 |
69.5x |
40 |
500 |
0.127 |
11.2 |
86.6x |
40 |
1,000 |
0.131 |
13.9 |
104x |
40 |
2,000 |
0.140 |
17.6 |
125x |
80 |
500 |
0.626 |
57.7 |
88.6x |
80 |
1,000 |
0.549 |
69.9 |
132x |
80 |
2,000 |
0.608 |
103 |
166x |
160 |
1,000 |
5.35 |
477 |
91.6x |
d |
n |
Datasets |
Same graph |
Errors, Andrey |
Errors, tigramite |
Errors, empty graph |
Cross-link F1, Andrey |
Cross-link F1, tigramite |
|---|---|---|---|---|---|---|---|---|
10 |
500 |
10 |
10 of 10 |
8 |
8 |
20 |
0.717 |
0.717 |
10 |
1,000 |
10 |
10 of 10 |
9.5 |
9.5 |
20 |
0.704 |
0.704 |
10 |
2,000 |
10 |
10 of 10 |
8 |
8 |
20 |
0.728 |
0.728 |
20 |
500 |
10 |
10 of 10 |
35 |
35 |
39 |
0.526 |
0.526 |
20 |
1,000 |
10 |
10 of 10 |
38.5 |
38.5 |
39 |
0.519 |
0.519 |
20 |
2,000 |
10 |
10 of 10 |
37.5 |
37.5 |
39 |
0.523 |
0.523 |
40 |
500 |
10 |
10 of 10 |
160 |
160 |
78 |
0.332 |
0.332 |
40 |
1,000 |
10 |
10 of 10 |
161.5 |
161.5 |
78 |
0.333 |
0.333 |
40 |
2,000 |
10 |
10 of 10 |
157.5 |
157.5 |
78 |
0.340 |
0.340 |
80 |
500 |
10 |
10 of 10 |
644.5 |
644.5 |
155.5 |
0.195 |
0.195 |
80 |
1,000 |
10 |
10 of 10 |
634 |
634 |
155.5 |
0.203 |
0.203 |
80 |
2,000 |
10 |
10 of 10 |
634 |
634 |
155.5 |
0.203 |
0.203 |
160 |
1,000 |
5 |
5 of 5 |
2,605 |
2,605 |
300 |
0.110 |
0.110 |
PCMCI returns the same graph as tigramite on every dataset, so their error and F1 columns are equal.
PCMCI+#
PCMCI+ adds links within a time step. It runs PCMCI’s tests over lags 0 to 5, then orients the
same-step links as PC does, with the majority collider rule. Both packages test with Student-t
partial correlation at pc_alpha 0.01. The output is a CPDAG of the same-step links and a directed
graph for each lag. Errors are the endpoint SHD over lags 0 to 5: two for a missing or extra link
and one per wrong end. An unoriented same-step link counts as an error at its open end.
d |
n |
Andrey (s) |
tigramite (s) |
Speedup |
|---|---|---|---|---|
10 |
500 |
0.0243 |
1.21 |
52.0x |
10 |
1,000 |
0.0269 |
1.50 |
54.8x |
10 |
2,000 |
0.0282 |
1.95 |
67.8x |
20 |
500 |
0.0575 |
4.22 |
72.9x |
20 |
1,000 |
0.0655 |
5.59 |
82.9x |
20 |
2,000 |
0.0735 |
7.01 |
96.6x |
40 |
500 |
0.241 |
15.3 |
64.7x |
40 |
1,000 |
0.267 |
18.8 |
69.4x |
40 |
2,000 |
0.270 |
25.1 |
84.3x |
80 |
1,000 |
0.772 |
75.9 |
96.4x |
80 |
2,000 |
0.852 |
98.7 |
116x |
d |
n |
Datasets |
Same graph |
Errors, Andrey |
Errors, tigramite |
Errors, empty graph |
Cross-link F1, Andrey |
Cross-link F1, tigramite |
|---|---|---|---|---|---|---|---|---|
10 |
500 |
10 |
10 of 10 |
12 |
12 |
50 |
0.786 |
0.786 |
10 |
1,000 |
10 |
10 of 10 |
8 |
8 |
50 |
0.873 |
0.873 |
10 |
2,000 |
10 |
10 of 10 |
5 |
5 |
50 |
0.916 |
0.916 |
20 |
500 |
10 |
10 of 10 |
34 |
34 |
100 |
0.697 |
0.697 |
20 |
1,000 |
10 |
10 of 10 |
26 |
26 |
100 |
0.807 |
0.807 |
20 |
2,000 |
10 |
10 of 10 |
19.5 |
19.5 |
100 |
0.842 |
0.842 |
40 |
500 |
10 |
10 of 10 |
71.5 |
71.5 |
200 |
0.695 |
0.695 |
40 |
1,000 |
10 |
10 of 10 |
56 |
56 |
200 |
0.773 |
0.773 |
40 |
2,000 |
10 |
10 of 10 |
60.5 |
60.5 |
200 |
0.777 |
0.777 |
80 |
1,000 |
10 |
10 of 10 |
179.5 |
179.5 |
400 |
0.668 |
0.668 |
80 |
2,000 |
10 |
10 of 10 |
167 |
167 |
400 |
0.715 |
0.715 |
PCMCI+ returns the same graph as tigramite on every dataset, so their error and F1 columns are equal.
LPCMCI#
LPCMCI allows for unobserved series. It returns a time-series PAG over lags 0 to 3, with a tail, an
arrowhead, or a circle at each end of each link. Both packages test with Student-t partial
correlation at pc_alpha 0.05 with one preliminary round. In this regime, 30% of the series are
unobserved, so we score each fit against the true PAG over the observed series (Gerhardus and Runge,
2020, Sect. 2.3). Errors are the endpoint SHD against that PAG; a circle in both counts as a match.
F1 counts links regardless of their marks, including autodependencies.
d |
Observed |
n |
Andrey (s) |
tigramite (s) |
Speedup |
|---|---|---|---|---|---|
5 |
4 |
500 |
0.0746 |
0.647 |
8.56x |
5 |
4 |
1,000 |
0.0841 |
0.928 |
12.0x |
5 |
4 |
2,000 |
0.0920 |
1.33 |
15.9x |
10 |
7 |
500 |
0.195 |
2.32 |
10.4x |
10 |
7 |
1,000 |
0.276 |
3.56 |
12.6x |
10 |
7 |
2,000 |
0.255 |
4.59 |
18.7x |
20 |
14 |
500 |
1.04 |
10.6 |
10.8x |
20 |
14 |
1,000 |
0.940 |
11.2 |
12.2x |
20 |
14 |
2,000 |
1.06 |
16.2 |
16.5x |
d |
Observed |
n |
Datasets |
Same graph |
Errors, Andrey |
Errors, tigramite |
Errors, empty graph |
Adjacency F1, Andrey |
Adjacency F1, tigramite |
|---|---|---|---|---|---|---|---|---|---|
5 |
4 |
500 |
10 |
9 of 10 |
4.5 |
4.5 |
16 |
0.883 |
0.883 |
5 |
4 |
1,000 |
10 |
9 of 10 |
14.5 |
15.5 |
28 |
0.791 |
0.775 |
5 |
4 |
2,000 |
10 |
8 of 10 |
16 |
16 |
29 |
0.827 |
0.827 |
10 |
7 |
500 |
10 |
6 of 10 |
55 |
56 |
78 |
0.554 |
0.577 |
10 |
7 |
1,000 |
10 |
9 of 10 |
41.5 |
41.5 |
62 |
0.644 |
0.644 |
10 |
7 |
2,000 |
10 |
8 of 10 |
45 |
45 |
74 |
0.653 |
0.653 |
20 |
14 |
500 |
10 |
9 of 10 |
181.5 |
181 |
221 |
0.422 |
0.422 |
20 |
14 |
1,000 |
10 |
9 of 10 |
146.5 |
146.5 |
182 |
0.486 |
0.486 |
20 |
14 |
2,000 |
10 |
6 of 10 |
131 |
131 |
170 |
0.555 |
0.555 |
The two return different graphs on 17 of 90 datasets: Andrey’s has fewer errors on 12 of them and tigramite’s on 5.
Granger#
Lasso Granger causality fits each variable on every variable’s past at lags 1 to 2, using a lasso
with 5-fold cross-validation. It keeps lagged edges with nonzero coefficients. Both packages fit the
same lasso on the same z-scored series. Errors are the lagged edges missed plus those added. We also
ran Andrey’s per-variable fits on threads across its 4 cores (andrey.granger.numpy.parallel),
shown in the parallel columns. This returns the same coefficients.
d |
n |
Andrey (s) |
causal-learn (s) |
Speedup |
Andrey, parallel (s) |
Speedup, parallel |
|---|---|---|---|---|---|---|
10 |
1,000 |
0.149 |
0.480 |
3.34x |
0.434 |
1.11x |
20 |
1,000 |
0.327 |
0.995 |
3.09x |
0.984 |
1.04x |
40 |
1,000 |
0.836 |
2.38 |
2.83x |
1.88 |
1.27x |
80 |
1,000 |
2.98 |
6.52 |
2.15x |
2.50 |
2.64x |
160 |
1,000 |
21.6 |
33.8 |
1.59x |
7.00 |
4.85x |
d |
n |
Datasets |
Same graph |
Errors, Andrey |
Errors, causal-learn |
Errors, empty graph |
Cross-link F1, Andrey |
Cross-link F1, causal-learn |
|---|---|---|---|---|---|---|---|---|
10 |
1,000 |
10 |
10 of 10 |
59 |
59 |
56.5 |
0.559 |
0.559 |
20 |
1,000 |
10 |
10 of 10 |
166 |
166 |
124 |
0.448 |
0.448 |
40 |
1,000 |
10 |
10 of 10 |
447 |
447 |
246.5 |
0.358 |
0.358 |
80 |
1,000 |
10 |
10 of 10 |
1,027.5 |
1,027.5 |
494 |
0.315 |
0.315 |
160 |
1,000 |
10 |
10 of 10 |
2,444 |
2,444 |
973 |
0.284 |
0.284 |
VARMA-LiNGAM#
VARMA-LiNGAM fits a vector autoregressive moving-average model of order (1, 1), with no order search. It then estimates the same-step DAG from the residuals using LiNGAM and prunes the lag blocks using adaptive lasso. It returns weighted same-step, lag-1, and moving-average matrices. Errors are the cross-links that differ from the true ones: missing plus extra. We count a lagged link with its direction and a same-step link by adjacency.
d |
n |
Andrey (s) |
lingam (s) |
Speedup |
|---|---|---|---|---|
3 |
100 |
2.14 |
2.27 |
1.05x |
3 |
300 |
3.23 |
3.16 |
1.00x |
3 |
1,000 |
5.04 |
5.14 |
1.02x |
5 |
100 |
6.64 |
6.90 |
1.06x |
5 |
300 |
12.4 |
11.7 |
0.962x |
5 |
1,000 |
29.5 |
30.4 |
1.03x |
10 |
100 |
20.2 |
20.6 |
1.03x |
10 |
300 |
36.1 |
36.1 |
1.01x |
10 |
1,000 |
96.6 |
99.4 |
1.04x |
20 |
100 |
43.0 |
47.4 |
1.11x |
20 |
300 |
85.7 |
97.2 |
1.13x |
20 |
1,000 |
241 |
270 |
1.12x |
d |
n |
Datasets |
Same graph |
Errors, Andrey |
Errors, lingam |
Errors, empty graph |
Cross-link F1, Andrey |
Cross-link F1, lingam |
|---|---|---|---|---|---|---|---|---|
3 |
100 |
10 |
9 of 10 |
3 |
3 |
7 |
0.748 |
0.748 |
3 |
300 |
10 |
9 of 10 |
2 |
2 |
7 |
0.833 |
0.833 |
3 |
1,000 |
10 |
9 of 10 |
1 |
1 |
7 |
0.916 |
0.916 |
5 |
100 |
10 |
4 of 10 |
9 |
8.5 |
12 |
0.653 |
0.667 |
5 |
300 |
10 |
6 of 10 |
5 |
5 |
12 |
0.781 |
0.781 |
5 |
1,000 |
10 |
7 of 10 |
4 |
3.5 |
12 |
0.840 |
0.863 |
10 |
100 |
10 |
0 of 10 |
29 |
27.5 |
26 |
0.556 |
0.565 |
10 |
300 |
10 |
0 of 10 |
16 |
17 |
26 |
0.684 |
0.686 |
10 |
1,000 |
10 |
5 of 10 |
9 |
9 |
26 |
0.834 |
0.834 |
20 |
100 |
5 |
0 of 5 |
78 |
77 |
55 |
0.466 |
0.469 |
20 |
300 |
5 |
0 of 5 |
39 |
37 |
55 |
0.650 |
0.646 |
20 |
1,000 |
5 |
2 of 5 |
33 |
34 |
55 |
0.741 |
0.741 |
The two return different graphs on 54 of 105 datasets: Andrey’s has fewer errors on 18 of them and lingam’s on 18.
LongitudinalLiNGAM#
LongitudinalLiNGAM takes M units observed at n time points. It estimates a same-step DAG and a
lag-1 matrix at every time point but the first, using one lag and the pairwise likelihood-ratio
measure. As for VARMA-LiNGAM, errors count the cross-links that differ from the true ones, pooled
over the time points.
d |
n |
M |
Andrey (s) |
lingam (s) |
Speedup |
|---|---|---|---|---|---|
2 |
20 |
1,000 |
0.0716 |
0.101 |
1.37x |
2 |
50 |
100 |
0.151 |
0.263 |
1.60x |
2 |
50 |
200 |
0.153 |
0.217 |
1.42x |
2 |
50 |
500 |
0.166 |
0.225 |
1.34x |
2 |
50 |
1,000 |
0.174 |
0.225 |
1.33x |
3 |
20 |
100 |
0.116 |
0.184 |
1.55x |
3 |
20 |
200 |
0.120 |
0.179 |
1.47x |
3 |
20 |
500 |
0.125 |
0.193 |
1.52x |
3 |
20 |
1,000 |
0.131 |
0.218 |
1.66x |
3 |
50 |
100 |
0.288 |
0.442 |
1.52x |
3 |
50 |
200 |
0.304 |
0.455 |
1.54x |
3 |
50 |
500 |
0.314 |
0.508 |
1.59x |
3 |
50 |
1,000 |
0.334 |
0.516 |
1.55x |
5 |
20 |
100 |
0.238 |
0.460 |
1.90x |
5 |
20 |
200 |
0.249 |
0.503 |
2.02x |
5 |
20 |
500 |
0.277 |
0.619 |
2.24x |
5 |
20 |
1,000 |
0.300 |
0.539 |
1.77x |
5 |
50 |
100 |
0.622 |
1.17 |
1.87x |
5 |
50 |
200 |
0.628 |
1.23 |
1.95x |
5 |
50 |
500 |
0.682 |
1.33 |
1.96x |
5 |
50 |
1,000 |
0.766 |
1.41 |
1.84x |
d |
n |
M |
Datasets |
Same graph |
Errors, Andrey |
Errors, lingam |
Errors, empty graph |
Cross-link F1, Andrey |
Cross-link F1, lingam |
|---|---|---|---|---|---|---|---|---|---|
2 |
20 |
100 |
10 |
10 of 10 |
0 |
0 |
57 |
1.00 |
1.00 |
2 |
20 |
200 |
10 |
10 of 10 |
0 |
0 |
57 |
1.00 |
1.00 |
2 |
20 |
500 |
10 |
10 of 10 |
0 |
0 |
57 |
1.00 |
1.00 |
2 |
20 |
1,000 |
10 |
10 of 10 |
0 |
0 |
57 |
1.00 |
1.00 |
2 |
50 |
100 |
10 |
10 of 10 |
0 |
0 |
147 |
1.00 |
1.00 |
2 |
50 |
200 |
10 |
10 of 10 |
0 |
0 |
147 |
1.00 |
1.00 |
2 |
50 |
500 |
10 |
10 of 10 |
0 |
0 |
147 |
1.00 |
1.00 |
2 |
50 |
1,000 |
10 |
10 of 10 |
0 |
0 |
147 |
1.00 |
1.00 |
3 |
20 |
100 |
10 |
10 of 10 |
2 |
2 |
171 |
0.994 |
0.994 |
3 |
20 |
200 |
10 |
10 of 10 |
0 |
0 |
171 |
1.00 |
1.00 |
3 |
20 |
500 |
10 |
10 of 10 |
0 |
0 |
171 |
1.00 |
1.00 |
3 |
20 |
1,000 |
10 |
10 of 10 |
0 |
0 |
171 |
1.00 |
1.00 |
3 |
50 |
100 |
10 |
10 of 10 |
4.5 |
4.5 |
441 |
0.995 |
0.995 |
3 |
50 |
200 |
10 |
10 of 10 |
1 |
1 |
441 |
0.999 |
0.999 |
3 |
50 |
500 |
10 |
10 of 10 |
1 |
1 |
441 |
0.999 |
0.999 |
3 |
50 |
1,000 |
10 |
10 of 10 |
0.5 |
0.5 |
441 |
0.999 |
0.999 |
5 |
20 |
100 |
10 |
10 of 10 |
15 |
15 |
570 |
0.987 |
0.987 |
5 |
20 |
200 |
10 |
10 of 10 |
5.5 |
5.5 |
570 |
0.995 |
0.995 |
5 |
20 |
500 |
10 |
10 of 10 |
3 |
3 |
570 |
0.997 |
0.997 |
5 |
20 |
1,000 |
10 |
10 of 10 |
1.5 |
1.5 |
570 |
0.999 |
0.999 |
5 |
50 |
100 |
10 |
7 of 10 |
31.5 |
31.5 |
1,470 |
0.989 |
0.989 |
5 |
50 |
200 |
10 |
7 of 10 |
12.5 |
15 |
1,470 |
0.996 |
0.995 |
5 |
50 |
500 |
10 |
9 of 10 |
3 |
3 |
1,470 |
0.999 |
0.999 |
5 |
50 |
1,000 |
10 |
8 of 10 |
2 |
2 |
1,470 |
0.999 |
0.999 |
The two return different graphs on 9 of 240 datasets: Andrey’s has fewer errors on 8 of them and lingam’s on 1.
The panels of 2 variables at 20 time points with 100, 200, and 500 units report accuracy only. We omit speed because both fits take under 0.1 s.
Known limits#
Data coverage. We measure one simulated regime per method. These results do not establish performance on measured series or on other mechanisms, noise, or lags.
PCMCI accuracy. At 40 and 80 variables, at every length, and at 160, both packages return more errors than the empty graph on every dataset. At 20 variables, Andrey does so on 4 or 5 of 10 datasets, as tigramite does.
Granger accuracy. At 1,000 time steps, both packages return more errors than the empty graph on every dataset from 20 variables. At 10 variables, Andrey does so on 5 of 10, as causal-learn does.
VARMA-LiNGAM. Andrey’s VARMA-LiNGAM gains little speed over lingam: its ratios range from 0.962x, slower than lingam, to 1.13x. At 100 time steps from 10 variables, both packages return more errors than the empty graph on most datasets. lingam has fewer errors on more datasets at two rungs: 10 variables at 100 steps (5 against 4) and 20 at 300 (4 against 1). This comes from a defect in lingam: its pruning builds the lagged columns with
np.roll, so its first regression row pairs the first step with values from the end of the series. Andrey starts the regressions at the first step with a full lag.LPCMCI agreement. On series with unobserved variables, the two LPCMCI implementations return the same PAG on 6 to 9 of 10 datasets per rung. At 20 variables with 14 observed and 500 steps, tigramite has fewer errors on 1 dataset and Andrey on 0. This comes from the order of candidate separating sets: tigramite follows the variable indices, and Andrey’s order does not depend on the column order.
LongitudinalLiNGAM agreement. The two implementations return different graphs on 9 of 240 datasets, from a defect in lingam: its lag regression uses scikit-learn’s LinearRegression, whose default tolerance zeroes singular values below 1e-6 of the largest, so on the fast-growing panels it drops to rank 1 of 5. With an exact lag regression, lingam returns the same graph as Andrey on all 240 datasets.
LongitudinalLiNGAM timing. The smallest panels, 2 variables at 20 time points with 100, 200, and 500 units, are not timed: both fits take under 0.1 s.
Hardware. Ratios are specific to the measured hardware, core budget, and settings.
Reproduce#
The benchmark harness guide documents environment setup, the campaign drivers, and the
scores. tigramite and lingam run in their own environments (benchmarks/start_tigramite.sh,
benchmarks/start_lingam_ts.sh), listed in the guide. To rerun the comparisons, install Andrey
0.5.0 (andrey-core), tigramite 5.2.10.1, causal-learn 0.1.4.8, and lingam 1.13.0, then run the
drivers with the settings below. Times will differ with the hardware and build; graphs should match
closely.
Comparison |
Driver |
d |
n |
Datasets x repeats |
Wall cap (s) |
Cores |
|---|---|---|---|---|---|---|
PCMCI |
|
10, 20, 40, and 80 |
500, 1,000, and 2,000 |
10 x 1 |
3,600 |
4 |
PCMCI |
|
160 |
1,000 |
5 x 1 |
3,600 |
4 |
PCMCI+ |
|
10, 20, and 40 |
500, 1,000, and 2,000 |
10 x 1 |
3,600 |
4 |
PCMCI+ |
|
80 |
1,000 and 2,000 |
10 x 1 |
3,600 |
4 |
LPCMCI |
|
5, 10, and 20 |
500, 1,000, and 2,000 |
10 x 1 |
3,600 |
4 |
Granger |
|
10, 20, 40, 80, and 160 |
1,000 |
10 x 1 |
3,600 |
4 |
VARMA-LiNGAM |
|
3, 5, and 10 |
100, 300, and 1,000 |
10 x 1 |
3,600 |
4 |
VARMA-LiNGAM |
|
20 |
100, 300, and 1,000 |
5 x 1 |
3,600 |
4 |
LongitudinalLiNGAM |
|
2, 3, and 5 |
20 and 50 |
10 x 1 |
3,600 |
4 |
$ANDREY_BENCH_PYTHON benchmarks/pcmci_cpu.py --method pcmci --out outputs/pcmci \
--ladder 10 20 40 80 --lengths 500 1000 2000 --tau-max 2 --seeds 10 --repeats 1 \
--cap-wall-s 3600 --cores 4
$ANDREY_BENCH_PYTHON benchmarks/pcmci_cpu.py --method pcmci --out outputs/pcmci-160 --ladder 160 \
--lengths 1000 --tau-max 2 --seeds 5 --repeats 1 --cap-wall-s 3600 --cores 4
$ANDREY_BENCH_PYTHON benchmarks/pcmci_cpu.py --method pcmciplus --out outputs/pcmciplus \
--ladder 10 20 40 --lengths 500 1000 2000 --tau-max 5 --seeds 10 --repeats 1 --cap-wall-s 3600 \
--cores 4
$ANDREY_BENCH_PYTHON benchmarks/pcmci_cpu.py --method pcmciplus --out outputs/pcmciplus-80 \
--ladder 80 --lengths 1000 2000 --tau-max 5 --seeds 10 --repeats 1 --cap-wall-s 3600 --cores 4
$ANDREY_BENCH_PYTHON benchmarks/pcmci_cpu.py --method lpcmci --out outputs/lpcmci --ladder 5 10 20 \
--lengths 500 1000 2000 --tau-max 3 --seeds 10 --repeats 1 --cap-wall-s 3600 --cores 4
$ANDREY_BENCH_PYTHON benchmarks/granger_var.py --out outputs/granger --ladder 10 20 40 80 160 \
--n 1000 --maxlag 2 --cv 5 --seeds 10 --repeats 1 --cap-wall-s 3600 --cores 4
$ANDREY_BENCH_PYTHON benchmarks/lingam_ts.py --method varma --out outputs/varma --ladder 3 5 10 \
--lengths 100 300 1000 --seeds 10 --repeats 1 --cap-wall-s 3600 --cores 4
$ANDREY_BENCH_PYTHON benchmarks/lingam_ts.py --method varma --out outputs/varma-20 --ladder 20 \
--lengths 100 300 1000 --seeds 5 --repeats 1 --cap-wall-s 3600 --cores 4
$ANDREY_BENCH_PYTHON benchmarks/lingam_ts.py --method longitudinal --out outputs/longitudinal \
--ladder 2 3 5 --lengths 20 50 --samples 100 200 500 1000 --seeds 10 --repeats 1 \
--cap-wall-s 3600 --cores 4