Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Large calculation time difference between r-causal and causal-cmd v1.5.0 #83

Closed
yasu-sh opened this issue Feb 1, 2023 · 70 comments
Closed

Comments

@yasu-sh
Copy link
Contributor

yasu-sh commented Feb 1, 2023

I am wondering why the calculation time has big difference between as of 2019 and as of 2023.
Could you tell me why this big difference happens? algorithms is different?
I have used profiling tool at IntelliJ IDEA at causal-cmd v.1.5.0. but the process looks normal and test consumes log-gamma calculation a lot.

r-causal based on causal-cmd ver. 1.2.0-SNAPSHOT

image
image

[1] "INFO No prior knowledge for TETRAD."
[1] "r-causal used Parameters: numberResampling = 0 / samplePrior = 10 / structurePrior = 1 / faithfulnessAssumed = false / verbose = false / maxDegree = 6 / symmetricFirstStep = true / printStream = "
[1] "INFO structure learning completed. user/sys/elapsed duraton: 3.03 / 0.01 / 3.33"
Actual turn around time: 3.33 secs.

causal-cmd based on the @kvb2univpitt 's release

[1] "INFO Causal structure learning started. Recipe: 5 | Algorithm: fges"
[1] "INFO structure learning with causal-cmd started."
[1] "INFO No prior knowledge for TETRAD."
[1] "javaw -Xmx3G -Xss4096k -jar causal-cmd-1.5.0-jar-with-dependencies.jar --data-type discrete --delimiter comma --score bdeu-score --json-graph --maxDegree 6 --algorithm fges --dataset dt.tetrad.csv --prefix c-tetrad --knowledge prior.txt --priorEquivalentSampleSize 10 --numberResampling 0 --parallelized --symmetricFirstStep"
[1] "INFO structure learning completed. user/sys/elapsed duraton: 0.19 / 0.64 / 100.25"
Actual turn around time: 100 secs.

no prior (no information at prior.txt)
dataset: hailfinder (https://github.com/bd2kccd/causal-cmd/files/10555256/dt.tetrad.csv)

condition is same as below, including dataset.:
#80 (comment)

The process aborted since the profiling makes much longer.

image

@kvb2univpitt
Copy link
Contributor

@yasu-sh One of the issue has to do with default parameters. If you don't provide a specific parameter, it will use the default value set by Java (boolean type) and by Tetrad (int type and double type). Each Tetrad algorithms has its own default parameter values that is optimized for it. Use the --default flag would make all the parameters, including boolean type, to use the algorithm specific default parameter values. This may improve your run time.

You can still override the default values set by the --default flag if you specify the value for a specific parameter.

Of course, there are other factors that also affect the runtime.

@jdramsey
Copy link
Contributor

jdramsey commented Feb 1, 2023

@yasu-sh Also, from 2019 to this year is a lot of time--we've made a number of optimizations to the code since then, even in the FGES class. Though I'm sure Kevin is right about parameter choices and how the parameters get used.

@yasu-sh
Copy link
Contributor Author

yasu-sh commented Feb 2, 2023

@jdramsey @jdramsey Thanks for your views and opinion. I tried the argument as you recommended.
The duration is not so changed. I will check at simple arguments later.

[1] "INFO No prior knowledge for TETRAD."
[1] "java -Xmx512m -jar causal-cmd-1.5.0-jar-with-dependencies.jar --data-type discrete --delimiter comma --score bdeu-score --json-graph --maxDegree 6 --algorithm fges --dataset dt.tetrad.csv --prefix c-tetrad --seed 42 --default --priorEquivalentSampleSize 10 --numberResampling 0 --parallelized --symmetricFirstStep"

  1. INSERT trcol41 --> trcol27 [] 46651.56856485745 degree = 1 indegree = 1 cond = 1
  2. INSERT trcol27 --> trcol32 [] 29804.224330255773 degree = 2 indegree = 1 cond = 1
  3. INSERT trcol27 --> trcol37 [] 28490.912815049505 degree = 3 indegree = 1 cond = 1
    (omit)
  4. DELETE trcol13 --> trcol25 H = [] NaYX = [trcol15] degree = 6 indegree = 3 diff = [trcol15] (37.74207135744655) cond = 1
  5. INSERT trcol13 --> trcol14 [] 639.8455362967507 degree = 6 indegree = 3 cond = 2
  6. DELETE trcol13 --> trcol14 H = [trcol15] NaYX = [trcol15] degree = 6 indegree = 3 diff = [] (23.54686309976387) cond = 0
    --- Directing trcol15 --- trcol14 to trcol14 --> trcol15
    Elapsed time = 90.791 s
    [1] "INFO structure learning completed. user/sys/elapsed duraton: 0.11 / 0.15 / 94.17"

@jdramsey
Copy link
Contributor

jdramsey commented Feb 2, 2023

Thanks!

@yasu-sh
Copy link
Contributor Author

yasu-sh commented Feb 3, 2023

As I mentioned yesterday, I compared 3 conditions:

  1. causal-cmd v1.5.0 latest version from sonartype
  2. causal-cmd v.1.2.0-SNAPSHOT Downloaded from r-causal repos.
  3. causal-cmd v1.2.0-SNAPSHOT Build at my machine from git, revision 1776706 (committed on Nov 2, 2019)
    dataset:
    dt.hailfinder.csv
    condition: v1.5.0 - default / v1.2.0 - verbose used since the '--default' arg. does not exists

basic execution at powershell

v 1.5.0
PS E:\Tetrad> java -jar "causal-cmd-1.5.0-jar-with-dependencies.jar" --data-type discrete --delimiter comma --score bdeu-score --json-graph --algorithm fges --dataset dt.hailfinder.csv --default
Elapsed time = 4843.091 s

v. 1.2.0
PS E:\Tetrad> Measure-Command {java -jar "causal-cmd-1.2.0-SNAPSHOT-jar-with-dep-selfbuild.jar" --data-type discrete --delimiter comma --score bdeu-score --json-graph --algorithm fges --dataset dt.hailfinder.csv --verbose}
TotalSeconds : 11.9347421

I have notices several points as below:

  • the search process steps is not so different between v1.2.0 and v1.5.0.
  • But causal-cmd v.1.5.0 takes much longer time , espcially at over degree = 7. (v1.5.0: 4843 secs / v1.2.0 12secs)
  • r-causal's causal-cmd would have been modified by @chirayukong and verbose does not work, no intermediate information available. I needed to build the jar at similar timing of upload of r-causal's jar to compare.

How come,,,? I feel like seeing v.1.2.0 by profiling, but it might not work for getting new ideas.
@kvb2univpitt @jdramsey I would appreciate if you could make comments or views?

Surely hailfinder dataset has many degrees as ground truth. it would make time-consuming.
(Lowering maxDegrees is easy way, but it does not mean good result for many-degree strucure.)

Logs

  1. causal-cmd-v1.5.0-default-hailfinder.txt
  2. causal-cmd-v.1.2.0-rcausal-hailfinder.txt
  3. causal-cmd-v1.2.0-Build-AsofDec2019-hailfinder.txt

PS E:\Tetrad> java -version
openjdk version "11.0.18" 2023-01-17
OpenJDK Runtime Environment Temurin-11.0.18+10 (build 11.0.18+10)
OpenJDK 64-Bit Server VM Temurin-11.0.18+10 (build 11.0.18+10, mixed mode)

@jdramsey
Copy link
Contributor

jdramsey commented Feb 3, 2023

Well, one comment I can make is that the R version is very out of date; the person working on that left the group some time ago, and there's been some difficulty updating that, though a number of people are interested, so I may try my hand at it myself (though I am not skilled at R progrmming). It it's just a matter of changing the causal command version and updating the calls made, perhaps I can. but it's not usign 1.5.0 but some much older version.

@jdramsey
Copy link
Contributor

jdramsey commented Feb 3, 2023

Much work has been done since 1.2.0 in any case; I would rely more on 1.5.0. BTW we will soon some out with a new version; enough changes have accrued I think, even in this short time.

@yasu-sh
Copy link
Contributor Author

yasu-sh commented Feb 3, 2023

Thanks. Okay, I rely on ver. 1.5.0 and use different settings on the latest version, as you recommended.
I just thought newer version could make faster search time.

Surely accuracy and speed has trade-off.
Let me know when you notice some ideas coming up.

@jdramsey
Copy link
Contributor

jdramsey commented Feb 3, 2023

Hold on, for 1.5.0, could you add the "--defaults" flag?

@jdramsey
Copy link
Contributor

jdramsey commented Feb 3, 2023 via email

@jdramsey
Copy link
Contributor

jdramsey commented Feb 3, 2023 via email

@jdramsey
Copy link
Contributor

jdramsey commented Feb 3, 2023 via email

@jdramsey
Copy link
Contributor

jdramsey commented Feb 3, 2023

Yeah, I switched to the Apache Gamma.loggamma method in the 7.1.3-1 release--item 52 here:

https://github.com/cmu-phil/tetrad/releases

@jdramsey
Copy link
Contributor

jdramsey commented Feb 3, 2023

...and the BDeu score makes extensive use of this function:

   double score = 0.0;

    score += getPriorForStructure(parents.length, N);

    double cellPrior = getSamplePrior() / (c * r);
    double rowPrior = getSamplePrior() / r;

    for (int j = 0; j < r; j++) {
        score -= Gamma.logGamma(rowPrior + n_j[j]);

        for (int k = 0; k < c; k++) {
            score += Gamma.logGamma(cellPrior + n_jk[j][k]);
        }
    }

    score += r * Gamma.logGamma(rowPrior);
    score -= c * r * Gamma.logGamma(cellPrior);

@jdramsey
Copy link
Contributor

jdramsey commented Feb 3, 2023

Holy crap, I never did the comparison--out to 6 decimal places they'r the same!!

Log gamma values

x	ProUtils	Apache
10.0	12.801827	12.801827
20.0	39.339884	39.339884
30.0	71.257039	71.257039
40.0	106.631760	106.631760
50.0	144.565744	144.565744
60.0	184.533829	184.533829
70.0	226.190548	226.190548
80.0	269.291098	269.291098
90.0	313.652830	313.652830
100.0	359.134205	359.134205

Here's the code:

   public static void compareLogGammas() {
        NumberFormat nf = new DecimalFormat("0.000000");

        System.out.println("Log gamma values");
        System.out.println();

        System.out.println("x\tProUtils\tApache");

        for (int i = 10; i <= 100; i += 10) {
            double x = i / 1d;

            double g1 = ProbUtils.lngamma(x);
            double g2 = Gamma.logGamma(x);

            System.out.println(x + "\t" + nf.format(g1) + "\t" + nf.format(g2));
        }
    }

@jdramsey
Copy link
Contributor

jdramsey commented Feb 3, 2023

So which is faster?

Here's my code:

    public static void compareLogGammas2() {
        NumberFormat nf = new DecimalFormat("0.000000");

        long start = ManagementFactory.getThreadMXBean().getCurrentThreadCpuTime();

        int numIter = 10000000;
        double nano = 1000000000d;

        for (int i = 0; i < numIter; i++) {
            ProbUtils.lngamma(1000.0);
        }

        long stop = ManagementFactory.getThreadMXBean().getCurrentThreadCpuTime();

        System.out.println("Elapsed ProbUtils.lngamma = " + (stop - start) / nano + "s");

        long start2 = ManagementFactory.getThreadMXBean().getCurrentThreadCpuTime();

        for (int i = 0; i < numIter; i++) {
            Gamma.logGamma(1000.0);
        }

        long stop2 = ManagementFactory.getThreadMXBean().getCurrentThreadCpuTime();

        System.out.println("Elapsed Gamma.logGamma = " + (stop2 - start2) / nano + "s");
    }

Here's the result:

Elapsed ProbUtils.lngamma = 1.630955s
Elapsed Gamma.logGamma = 0.26709s

Gamma.logGamma is significantly faster in CPU time. Hmm... so that' s not the reason.

@jdramsey
Copy link
Contributor

jdramsey commented Feb 3, 2023

Hold on, there was also a change in whether FGES was parallelized or not. @yasu-sh what size machine are you using? Parallelization for FGES was turned off by default for 7.1.3-1 (I'll add that to the release notes). To turn it on, I think you need to add the flag "--parallelized". Could you try that?

    private boolean parallelized = false;

This is a new field in FGES that was added in April, 2022. We added this so that we could run FGES in the algcomparison API and compare it to other algorithms, where the multithreading was done across algorithm runs instead of inside FGES.

@jdramsey
Copy link
Contributor

jdramsey commented Feb 3, 2023

Added this note to the release notes for 7.1.3-1 (sorry for leaving it out--that was a major release; there are probably a few other defaults I left out as well:

Set FGES to be single-thread by default; to to multithreading, the flag "parallelized" needs to be set to true (in causal cmd, "--parallelized".

@yasu-sh
Copy link
Contributor Author

yasu-sh commented Feb 6, 2023

@jdramsey Thanks a lot for telling your analysis and consideration!
I read the code of R's library(dll) for combination size calclulation about a year ago.
I knew the gamma function was used and the calclulation time was much faster than my colleague's code in C++.
So I think the gamma function of log is a key to make efficient search.

I have checked different cofiguration at v.1.5.0 already, and I set the similar option settings including --parallelized as long as I could.
(I noticed v.1.2.0 have parallelize enabled always and I also thought FGES needed to enable to make native optimized search.)

Hold on, there was also a change in whether FGES was parallelized or not. @yasu-sh what size machine are you using?

OS: Microsoft Windows 10 Pro x64 21H2 / 10.0.19044 N/A Build 19044
System Model: HP ZBook Studio G4
Processor(s): 1 Processor(s) Installed.
Intel(R) Core(TM) i7-7820HQ CPU @ 2.90GHz、2904 Mhz、4 Cores, 8 logical processors
[01]: Intel64 Family 6 Model 158 Stepping 9 GenuineIntel ~2904 Mhz
System Locale: ja;Japanese
Total Physical Memory: 32,381 MB

I would like to add some later on. See you then.

@jdramsey
Copy link
Contributor

jdramsey commented Feb 8, 2023

@yasu-sh Have you discovered any new information about this? Your machine should certainly be large enough to do parallel processing. When you run java, it's possible the heap size is too emall--that would slow things down a lot. You can increase the heap size by adding a flag to the Java command like -Xmx10g for 10 Gigabytes.

@yasu-sh
Copy link
Contributor Author

yasu-sh commented Feb 9, 2023

@jdramsey Unfortunately, no information so far. I noticed this phenomena on this issue at -Xmx4G flag for java.
So I thought the heap memory size would be enough to get the process functional....

I am afraid I need to help my colleagues at another projects for 2 weeks, therefore I have little time to check about this topic.
Today, I tried at the statement as below and took so many minues(already 30min.) Not ended now.

Win10 Not fully occupied by process,,, windows specific???
image
image

java -Xmx10G -jar "causal-cmd-1.5.0-jar-with-dependencies.jar" --data-type discrete --delimiter comma --score bdeu-score --json-graph --algorithm fges --dataset dt.hailfinder.csv --parallelized

datafile(posted the same above): https://github.com/bd2kccd/causal-cmd/files/10575729/dt.hailfinder.csv

@yasu-sh
Copy link
Contributor Author

yasu-sh commented Feb 9, 2023

This time (just added parallelized & expanded 10GB heap memory), out of memory error came up.
Finally saturated at 10GB memory consumption and made these as below.

PS E:\Tetrad> java -Xmx10G -jar "causal-cmd-1.5.0-jar-with-dependencies.jar" --data-type discrete --delimiter comma --score bdeu-score --json-graph --algorithm fges --dataset dt.hailfinder.csv --parallelized
java.util.concurrent.ExecutionException: java.lang.OutOfMemoryError
at java.base/java.util.concurrent.ForkJoinTask.get(ForkJoinTask.java:1006)
at edu.cmu.tetrad.search.Fges.calculateArrowsForward(Fges.java:718)
at edu.cmu.tetrad.search.Fges.access$500(Fges.java:61)
at edu.cmu.tetrad.search.Fges$1AdjTask.call(Fges.java:593)
at edu.cmu.tetrad.search.Fges$1AdjTask.call(Fges.java:541)
at java.base/java.util.concurrent.ForkJoinTask$AdaptedCallable.exec(ForkJoinTask.java:1448)
at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:290)
at java.base/java.util.concurrent.ForkJoinTask.tryExternalHelp(ForkJoinTask.java:381)
at java.base/java.util.concurrent.ForkJoinTask.externalAwaitDone(ForkJoinTask.java:323)
at java.base/java.util.concurrent.ForkJoinTask.doJoin(ForkJoinTask.java:398)
at java.base/java.util.concurrent.ForkJoinTask.quietlyJoin(ForkJoinTask.java:1078)
at java.base/java.util.concurrent.ForkJoinPool.invokeAll(ForkJoinPool.java:2519)
at edu.cmu.tetrad.search.Fges.reevaluateForward(Fges.java:616)
at edu.cmu.tetrad.search.Fges.fes(Fges.java:522)
at edu.cmu.tetrad.search.Fges.search(Fges.java:207)
at edu.cmu.tetrad.algcomparison.algorithm.oracle.cpdag.Fges.search(Fges.java:79)
at edu.pitt.dbmi.causal.cmd.tetrad.TetradRunner.lambda$runSearch$3(TetradRunner.java:203)
at java.base/java.lang.Iterable.forEach(Iterable.java:75)
at edu.pitt.dbmi.causal.cmd.tetrad.TetradRunner.runSearch(TetradRunner.java:202)
at edu.pitt.dbmi.causal.cmd.tetrad.TetradRunner.runAlgorithm(TetradRunner.java:119)
at edu.pitt.dbmi.causal.cmd.CausalCmdApplication.runTetrad(CausalCmdApplication.java:149)
at edu.pitt.dbmi.causal.cmd.CausalCmdApplication.main(CausalCmdApplication.java:113)
Caused by: java.lang.OutOfMemoryError
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
at java.base/java.util.concurrent.ForkJoinTask.getThrowableException(ForkJoinTask.java:603)
... 22 more
Caused by: java.lang.OutOfMemoryError: Java heap space
at edu.cmu.tetrad.search.BDeuScore.localScore(BDeuScore.java:112)
at edu.cmu.tetrad.search.BDeuScore.localScoreDiff(BDeuScore.java:179)
at edu.cmu.tetrad.search.Fges.scoreGraphChange(Fges.java:1078)
at edu.cmu.tetrad.search.Fges.insertEval(Fges.java:776)
at edu.cmu.tetrad.search.Fges.access$600(Fges.java:61)
at edu.cmu.tetrad.search.Fges$1EvalTask.call(Fges.java:679)
at edu.cmu.tetrad.search.Fges$1EvalTask.call(Fges.java:660)
at java.base/java.util.concurrent.ForkJoinTask$AdaptedCallable.exec(ForkJoinTask.java:1448)
at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:290)
at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1020)
at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1656)
at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1594)
at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:183)

@yasu-sh
Copy link
Contributor Author

yasu-sh commented Feb 9, 2023

@jdramsey even at 10GB, the max memory size might not be enough. Let me try 25GB..

@yasu-sh
Copy link
Contributor Author

yasu-sh commented Feb 9, 2023

Sometime explosive memory consumption happens like saws(for woods).
I hope to use conventional calcluration since the calculation is more effecient than newer table model of apache commons math lib.
Could @jdramsey try the same data(hailfinder) at same options at your computer as below(memory can be changed)?
I saw your past comments had Mac window, operation systems could be related to this phenomena.

java -Xmx25G -jar "causal-cmd-1.5.0-jar-with-dependencies.jar" --data-type discrete --delimiter comma --score bdeu-score --json-graph --algorithm fges --dataset dt.hailfinder.csv --parallelized

I have checked by myself at Mac machine.
Mac(Unix based), Win & Unix have different features and I have read that windows system cannot fork the memory so many memory copies via TCP/IP in R environment whereas unix system can just copies the memory of the running enviromnet in the same computer.

image
image

jconsole's manual page

@yasu-sh
Copy link
Contributor Author

yasu-sh commented Feb 13, 2023

@jdramsey The other day I have purchased a Mac mini M2(new model) with minimum spec for my private.
I have tried at the condition as below and the result / conclusion is the similar.
The new scoring algorithm at parallel computing does not suit for many-degree causal network??

parallelized setting Yes No
duration Stopped over 2h 1937.134 secs
Out of memory error Occurred Not Occurred
Verbose's progress 2x -3x slower than the other Slow, but progress
Mac-mini Tetrad % java -version
openjdk version "11.0.18" 2023-01-17
OpenJDK Runtime Environment Temurin-11.0.18+10 (build 11.0.18+10)
OpenJDK 64-Bit Server VM Temurin-11.0.18+10 (build 11.0.18+10, mixed mode)

Tetrad % /usr/sbin/system_profiler -detailLevel mini 
Hardware:
    Hardware Overview:
      Model Name: Mac mini
      Model Identifier: Mac14,3
      Model Number: MMFJ3J/A
      Chip: Apple M2
      Total Number of Cores: 8 (4 performance and 4 efficiency)
      Memory: 8 GB
      System Firmware Version: 8419.80.7
      OS Loader Version: 8419.80.7

Memory:
      Memory: 8 GB
      Type: LPDDR5
      Manufacturer: Micron
Mac-mini Tetrad % java -Xmx5G -jar "causal-cmd-1.5.0-jar-with-dependencies.jar" --data-type discrete --delimiter comma --score bdeu-score --json-graph --algorithm fges --dataset dt.hailfinder.csv --parallelized --verbose
1. INSERT ScnRelPlFcst --> Scenario [] 46651.56856485745 degree = 1 indegree = 1 cond = 1
2. INSERT ScnRelPlFcst --> ScenRelAMIns [] 29804.224330255773 degree = 2 indegree = 0 cond = 1
3. INSERT Scenario --> ScenRel34 [] 28490.912815049505 degree = 2 indegree = 0 cond = 1
4. INSERT AreaMesoALS --> CombVerMo [] 25244.402367736307 degree = 2 indegree = 0 cond = 1
5. INSERT CapChange --> CompPlFcst [] 21347.6368234152 degree = 2 indegree = 0 cond = 1
6. INSERT PlainsFcst --> N34StarFcst [] 13651.483290013432 degree = 2 indegree = 1 cond = 1
7. INSERT Scenario --> WindFieldPln [] 10240.609710882767 degree = 3 indegree = 1 cond = 1
8. INSERT Scenario --> SfcWndShfDis [] 9896.183754378471 degree = 4 indegree = 1 cond = 1
9. INSERT MountainFcst --> R5Fcst [] 9841.66758822378 degree = 4 indegree = 1 cond = 1
10. INSERT N34StarFcst --> R5Fcst [MountainFcst] 11481.578596648274 degree = 4 indegree = 1 cond = 2
--- Directing MountainFcst --> R5Fcst
11. INSERT Scenario --> ScenRelAMCIN [] 9827.080206968974 degree = 5 indegree = 2 cond = 1
12. INSERT AMInstabMt --> InsInMt [] 9200.035720480517 degree = 5 indegree = 2 cond = 1
13. INSERT CombMoisture --> AreaMoDryAir [] 8697.303519154746 degree = 5 indegree = 2 cond = 1
14. INSERT Scenario --> Dewpoints [] 8060.360232083614 degree = 6 indegree = 2 cond = 1
15. INSERT Scenario --> WindAloft [] 7691.486439166631 degree = 7 indegree = 2 cond = 1
16. INSERT CombClouds --> CldShadeOth [] 7582.724420807997 degree = 7 indegree = 2 cond = 1
17. INSERT InsInMt --> CldShadeConv [] 6951.145041866659 degree = 7 indegree = 2 cond = 1
18. INSERT Scenario --> MvmtFeatures [] 6064.721401109418 degree = 8 indegree = 2 cond = 1
19. INSERT InsInMt --> OutflowFrMt [] 5861.459915747448 degree = 8 indegree = 2 cond = 1
20. INSERT AMCINInScen --> MorningCIN [] 5744.261326911303 degree = 8 indegree = 2 cond = 1
21. INSERT VISCloudCov --> CombClouds [] 5505.233648352496 degree = 8 indegree = 2 cond = 1
22. INSERT InsInMt --> MountainFcst [] 5471.96694397506 degree = 8 indegree = 2 cond = 1
23. INSERT InsSclInScen --> AMInsWliScen [] 5389.565668086932 degree = 8 indegree = 2 cond = 1
24. INSERT InsChange --> LoLevMoistAd [] 5314.347428221692 degree = 8 indegree = 2 cond = 1
25. INSERT Scenario --> TempDis [] 5268.570835127262 degree = 9 indegree = 2 cond = 1
26. INSERT AMCINInScen --> CapInScen [] 5161.809906832612 degree = 9 indegree = 2 cond = 1
27. INSERT CapChange --> CapInScen [AMCINInScen] 7935.477957001622 degree = 9 indegree = 2 cond = 2
--- Directing AMCINInScen --> CapInScen
28. INSERT InsChange --> InsSclInScen [AMInsWliScen] 5100.860672891173 degree = 9 indegree = 2 cond = 2
--- Directing AMInsWliScen --> InsSclInScen
29. INSERT Scenario --> RHRatio [] 5024.198470412222 degree = 10 indegree = 2 cond = 1
30. INSERT Scenario --> LowLLapse [] 4395.0530244349575 degree = 11 indegree = 2 cond = 1
^[OP^[OP11java.util.concurrent.ExecutionException: java.lang.OutOfMemoryError
	at java.base/java.util.concurrent.ForkJoinTask.get(ForkJoinTask.java:1006)
	at edu.cmu.tetrad.search.Fges.calculateArrowsForward(Fges.java:718)
	at edu.cmu.tetrad.search.Fges.access$500(Fges.java:61)
	at edu.cmu.tetrad.search.Fges$1AdjTask.call(Fges.java:593)
	at edu.cmu.tetrad.search.Fges$1AdjTask.call(Fges.java:541)
	at java.base/java.util.concurrent.ForkJoinTask$AdaptedCallable.exec(ForkJoinTask.java:1448)
	at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:290)
	at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1020)
	at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1656)
	at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1594)
	at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:183)
Caused by: java.lang.OutOfMemoryError
	at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
	at java.base/java.util.concurrent.ForkJoinTask.getThrowableException(ForkJoinTask.java:603)
	... 11 more
Caused by: java.lang.OutOfMemoryError: Java heap space
	at edu.cmu.tetrad.search.BDeuScore.localScore(BDeuScore.java:111)
	at edu.cmu.tetrad.search.BDeuScore.localScoreDiff(BDeuScore.java:179)
	at edu.cmu.tetrad.search.Fges.scoreGraphChange(Fges.java:1078)
	at edu.cmu.tetrad.search.Fges.insertEval(Fges.java:776)
	at edu.cmu.tetrad.search.Fges.access$600(Fges.java:61)
	at edu.cmu.tetrad.search.Fges$1EvalTask.call(Fges.java:679)
	at edu.cmu.tetrad.search.Fges$1EvalTask.call(Fges.java:660)
	... 6 more
java.util.concurrent.ExecutionException: java.lang.OutOfMemoryError
	at java.base/java.util.concurrent.ForkJoinTask.get(ForkJoinTask.java:1006)
	at edu.cmu.tetrad.search.Fges.calculateArrowsForward(Fges.java:718)
	at edu.cmu.tetrad.search.Fges.access$500(Fges.java:61)
	at edu.cmu.tetrad.search.Fges$1AdjTask.call(Fges.java:593)
	at edu.cmu.tetrad.search.Fges$1AdjTask.call(Fges.java:541)
	at java.base/java.util.concurrent.ForkJoinTask$AdaptedCallable.exec(ForkJoinTask.java:1448)
	at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:290)
	at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1020)
	at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1656)
	at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1594)
	at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:183)
Caused by: java.lang.OutOfMemoryError
	at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
	at java.base/java.util.concurrent.ForkJoinTask.getThrowableException(ForkJoinTask.java:603)
	... 11 more
Caused by: java.lang.OutOfMemoryError: Java heap space
java.util.concurrent.ExecutionException: java.lang.OutOfMemoryError
	at java.base/java.util.concurrent.ForkJoinTask.get(ForkJoinTask.java:1006)
	at edu.cmu.tetrad.search.Fges.calculateArrowsForward(Fges.java:718)
	at edu.cmu.tetrad.search.Fges.access$500(Fges.java:61)
	at edu.cmu.tetrad.search.Fges$1AdjTask.call(Fges.java:593)
	at edu.cmu.tetrad.search.Fges$1AdjTask.call(Fges.java:541)
	at java.base/java.util.concurrent.ForkJoinTask$AdaptedCallable.exec(ForkJoinTask.java:1448)
	at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:290)
	at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1020)
	at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1656)
	at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1594)
	at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:183)
Caused by: java.lang.OutOfMemoryError
	at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
	at java.base/java.util.concurrent.ForkJoinTask.getThrowableException(ForkJoinTask.java:603)
	... 11 more
Caused by: java.lang.OutOfMemoryError: Java heap space
java.util.concurrent.ExecutionException: java.lang.OutOfMemoryError
	at java.base/java.util.concurrent.ForkJoinTask.get(ForkJoinTask.java:1006)
	at edu.cmu.tetrad.search.Fges.calculateArrowsForward(Fges.java:718)
	at edu.cmu.tetrad.search.Fges.access$500(Fges.java:61)
	at edu.cmu.tetrad.search.Fges$1AdjTask.call(Fges.java:593)
	at edu.cmu.tetrad.search.Fges$1AdjTask.call(Fges.java:541)
	at java.base/java.util.concurrent.ForkJoinTask$AdaptedCallable.exec(ForkJoinTask.java:1448)
	at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:290)
	at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1020)
	at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1656)
	at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1594)
	at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:183)
Caused by: java.lang.OutOfMemoryError
	at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
	at java.base/java.util.concurrent.ForkJoinTask.getThrowableException(ForkJoinTask.java:603)
	... 11 more
Caused by: java.lang.OutOfMemoryError: Java heap space
java.util.concurrent.ExecutionException: java.lang.OutOfMemoryError
	at java.base/java.util.concurrent.ForkJoinTask.get(ForkJoinTask.java:1006)
	at edu.cmu.tetrad.search.Fges.calculateArrowsForward(Fges.java:718)
	at edu.cmu.tetrad.search.Fges.access$500(Fges.java:61)
	at edu.cmu.tetrad.search.Fges$1AdjTask.call(Fges.java:593)
	at edu.cmu.tetrad.search.Fges$1AdjTask.call(Fges.java:541)
	at java.base/java.util.concurrent.ForkJoinTask$AdaptedCallable.exec(ForkJoinTask.java:1448)
	at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:290)
	at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1020)
	at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1656)
	at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1594)
	at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:183)
Caused by: java.lang.OutOfMemoryError
	at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
	at java.base/java.util.concurrent.ForkJoinTask.getThrowableException(ForkJoinTask.java:603)
	... 11 more
Caused by: java.lang.OutOfMemoryError: Java heap space
(manually stopped)

Mac-mini Tetrad % java -Xmx5G -jar "causal-cmd-1.5.0-jar-with-dependencies.jar" --data-type discrete --delimiter comma --score bdeu-score --json-graph --algorithm fges --dataset dt.hailfinder.csv --verbose  
1. INSERT ScnRelPlFcst --> Scenario [] 46651.56856485745 degree = 1 indegree = 1 cond = 1
2. INSERT ScnRelPlFcst --> ScenRelAMIns [] 29804.224330255773 degree = 2 indegree = 0 cond = 1
3. INSERT Scenario --> ScenRel34 [] 28490.912815049505 degree = 2 indegree = 0 cond = 1
4. INSERT AreaMesoALS --> CombVerMo [] 25244.402367736307 degree = 2 indegree = 0 cond = 1
5. INSERT CapChange --> CompPlFcst [] 21347.6368234152 degree = 2 indegree = 0 cond = 1
6. INSERT PlainsFcst --> N34StarFcst [] 13651.483290013432 degree = 2 indegree = 1 cond = 1
7. INSERT ScnRelPlFcst --> WindFieldPln [] 10240.609710882767 degree = 3 indegree = 1 cond = 1
8. INSERT Scenario --> SfcWndShfDis [] 9896.183754378471 degree = 3 indegree = 1 cond = 1
9. INSERT MountainFcst --> R5Fcst [] 9841.66758822378 degree = 3 indegree = 1 cond = 1
10. INSERT N34StarFcst --> R5Fcst [MountainFcst] 11481.578596648274 degree = 3 indegree = 1 cond = 2
--- Directing MountainFcst --> R5Fcst
11. INSERT Scenario --> ScenRelAMCIN [] 9827.080206968974 degree = 4 indegree = 2 cond = 1
12. INSERT AMInstabMt --> InsInMt [] 9200.035720480517 degree = 4 indegree = 2 cond = 1
13. INSERT CombMoisture --> AreaMoDryAir [] 8697.303519154746 degree = 4 indegree = 2 cond = 1
14. INSERT Scenario --> Dewpoints [] 8060.360232083614 degree = 5 indegree = 2 cond = 1
15. INSERT ScnRelPlFcst --> WindAloft [] 7691.486439166631 degree = 5 indegree = 2 cond = 1
16. INSERT CombClouds --> CldShadeOth [] 7582.724420807997 degree = 5 indegree = 2 cond = 1
17. INSERT InsInMt --> CldShadeConv [] 6951.145041866659 degree = 5 indegree = 2 cond = 1
18. INSERT ScnRelPlFcst --> MvmtFeatures [] 6064.721401109418 degree = 5 indegree = 2 cond = 1
19. INSERT InsInMt --> OutflowFrMt [] 5861.459915747448 degree = 5 indegree = 2 cond = 1
20. INSERT AMCINInScen --> MorningCIN [] 5744.261326911303 degree = 5 indegree = 2 cond = 1
21. INSERT VISCloudCov --> CombClouds [] 5505.233648352496 degree = 5 indegree = 2 cond = 1
22. INSERT InsInMt --> MountainFcst [] 5471.96694397506 degree = 5 indegree = 2 cond = 1
23. INSERT InsSclInScen --> AMInsWliScen [] 5389.565668086932 degree = 5 indegree = 2 cond = 1
24. INSERT InsChange --> LoLevMoistAd [] 5314.347428221692 degree = 5 indegree = 2 cond = 1
25. INSERT Scenario --> TempDis [] 5268.570835127262 degree = 6 indegree = 2 cond = 1
26. INSERT AMCINInScen --> CapInScen [] 5161.809906832612 degree = 6 indegree = 2 cond = 1
27. INSERT CompPlFcst --> CapInScen [AMCINInScen] 7935.477957001622 degree = 6 indegree = 2 cond = 2
--- Directing AMCINInScen --> CapInScen
28. INSERT InsChange --> InsSclInScen [AMInsWliScen] 5100.860672891173 degree = 6 indegree = 2 cond = 2
--- Directing AMInsWliScen --> InsSclInScen
29. INSERT Scenario --> RHRatio [] 5024.198470412222 degree = 7 indegree = 2 cond = 1
30. INSERT Scenario --> LowLLapse [] 4395.0530244349575 degree = 8 indegree = 2 cond = 1
31. INSERT ScnRelPlFcst --> SynForcng [] 4258.72156103166 degree = 8 indegree = 2 cond = 1
32. INSERT ScnRelPlFcst --> MeanRH [] 4160.4474252851105 degree = 8 indegree = 2 cond = 1
33. INSERT CurPropConv --> LLIW [] 4155.38932550736 degree = 8 indegree = 2 cond = 1
34. INSERT LatestCIN --> CurPropConv [LLIW] 4051.9878197565013 degree = 8 indegree = 2 cond = 2
--- Directing LLIW --> CurPropConv
35. INSERT Scenario --> MidLLapse [] 3463.0283821636185 degree = 9 indegree = 2 cond = 1
36. INSERT OutflowFrMt --> Boundaries [] 3411.097146228003 degree = 9 indegree = 2 cond = 1
37. INSERT AreaMesoALS --> AreaMoDryAir [CombMoisture] 3155.7691316592245 degree = 9 indegree = 2 cond = 2
--- Directing CombMoisture --> AreaMoDryAir
38. INSERT WndHodograph --> OutflowFrMt [InsInMt] 3152.94192621985 degree = 9 indegree = 2 cond = 2
--- Directing InsInMt --> OutflowFrMt
39. INSERT WndHodograph --> CldShadeConv [InsInMt] 3053.342200996385 degree = 9 indegree = 2 cond = 2
--- Directing InsInMt --> CldShadeConv
40. INSERT ScnRelPlFcst --> WindFieldMt [] 2789.047194566061 degree = 9 indegree = 2 cond = 1
41. INSERT CombVerMo --> N07muVerMo [] 2731.467407400931 degree = 9 indegree = 2 cond = 1
42. INSERT SubjVertMo --> CombVerMo [N07muVerMo] 2655.020437775369 degree = 9 indegree = 2 cond = 2
--- Directing N07muVerMo --> CombVerMo
43. INSERT QGVertMotion --> CombVerMo [] 4117.928027072281 degree = 9 indegree = 2 cond = 3
44. INSERT IRCloudCover --> CombClouds [VISCloudCov] 2458.094871995503 degree = 9 indegree = 2 cond = 2
--- Directing VISCloudCov --> CombClouds
45. INSERT AreaMesoALS --> CldShadeOth [] 2191.0516760104747 degree = 9 indegree = 2 cond = 2
46. INSERT CombMoisture --> SatContMoist [] 2126.1178240752342 degree = 9 indegree = 2 cond = 1
47. INSERT RaoContMoist --> CombMoisture [SatContMoist] 2532.7527230040578 degree = 9 indegree = 2 cond = 2
--- Directing SatContMoist --> CombMoisture
48. INSERT MorningBound --> Boundaries [] 1895.3523960106195 degree = 9 indegree = 2 cond = 2
49. INSERT AMDewptCalPl --> AMInsWliScen [] 1726.9878538675002 degree = 9 indegree = 2 cond = 1
50. INSERT LIfr12ZDENSd --> AMInsWliScen [AMDewptCalPl] 1422.3951010527926 degree = 9 indegree = 2 cond = 2
--- Directing AMDewptCalPl --> AMInsWliScen
51. INSERT CapChange --> InsChange [LoLevMoistAd] 1196.3283128400344 degree = 9 indegree = 2 cond = 2
--- Directing LoLevMoistAd --> InsChange
52. INSERT CurPropConv --> PlainsFcst [] 849.0071934315165 degree = 9 indegree = 2 cond = 1
53. INSERT ScenRelAMCIN --> AMCINInScen [MorningCIN] 778.5394196887337 degree = 9 indegree = 2 cond = 2
--- Directing MorningCIN --> AMCINInScen
54. INSERT Date --> Scenario [] 727.7999368397141 degree = 10 indegree = 2 cond = 1
55. INSERT AreaMoDryAir --> CldShadeOth [] 703.1535649705329 degree = 10 indegree = 2 cond = 3
56. INSERT AreaMesoALS --> CapChange [] 700.5598957238835 degree = 10 indegree = 2 cond = 1
57. INSERT PlainsFcst --> ScnRelPlFcst [] 570.1579930226726 degree = 10 indegree = 2 cond = 1
58. INSERT InsSclInScen --> PlainsFcst [] 570.0031714512916 degree = 10 indegree = 2 cond = 2
59. INSERT CldShadeOth --> CapChange [] 479.3933521717736 degree = 10 indegree = 2 cond = 2
60. INSERT AMInsWliScen --> ScnRelPlFcst [] 416.7982150651951 degree = 10 indegree = 2 cond = 2
61. INSERT WndHodograph --> Boundaries [] 354.91872928021985 degree = 10 indegree = 2 cond = 3
62. INSERT ScenRel34 --> N34StarFcst [] 121.17752072456369 degree = 10 indegree = 2 cond = 2
63. INSERT CldShadeOth --> MountainFcst [] 63.76639495397103 degree = 10 indegree = 2 cond = 1
64. INSERT CldShadeOth --> InsInMt [] 148.14735435118564 degree = 10 indegree = 2 cond = 2
65. INSERT CldShadeConv --> CapChange [] 59.48265800724039 degree = 10 indegree = 2 cond = 3
66. INSERT ScenRelAMIns --> Scenario [] 45.67621526152453 degree = 11 indegree = 2 cond = 2
67. INSERT ScnRelPlFcst --> ScenRel34 [] 43.32892665240189 degree = 11 indegree = 2 cond = 2
68. INSERT ScnRelPlFcst --> ScenRelAMCIN [] 22.7365392031544 degree = 12 indegree = 2 cond = 2
67. DELETE CldShadeOth --> MountainFcst H = [] NaYX = [InsInMt] degree = 12 indegree = 2 diff = [InsInMt] (37.74207135744655)  cond = 1
68. INSERT CldShadeOth --> AMInstabMt [] 639.8455362967507 degree = 12 indegree = 2 cond = 2
67. DELETE CldShadeOth --> AMInstabMt H = [InsInMt] NaYX = [InsInMt] degree = 12 indegree = 2 diff = [] (23.54686309976387)  cond = 0
--- Directing InsInMt --- AMInstabMt to AMInstabMt --> InsInMt
Elapsed time = 1937.134 s

@jdramsey
Copy link
Contributor

@yasu-sh I will give it a shot. Sorry, we've been focused lately on getting a new release of Tetrad and causal-cmd out the door so I haven't had a lot of time to think (other than that). I don't think the new release will solve this problem. However, I've got 64 GB of RAM on my laptop so maybe I can get further than you, I don't know. Anyway, we're supposed to get the new release out by today or maybe tomorrow so maybe after that, I'll have a little bit of time to address this.

@jdramsey
Copy link
Contributor

@yasu-sh Could you zip and attach this file for me--would speed things up for me:

dt.hailfinder.csv

Thanks, or give me the link to download this. You may have given this to me before but I can't find it immediately.

@jdramsey
Copy link
Contributor

Never mind, I found it in the thread. I've got a few minutes right now; let me try loading it up in the interface and searching...

@jdramsey
Copy link
Contributor

Actually, I would remove columns 27 and 41 from the data; they have too many categories. That might be the problem. Are they needed? Without them, fGES finishes quite quickly.

@jdramsey
Copy link
Contributor

Here's the dataset without these variables (tab-delimited)--see if causal-cmd can deal with this instead.

dt.hailfinder.subset.txt

My theory is that the problem is that these 11-category variables were causing the algorithm to make cross-classification tables that were just too big.

@yasu-sh yasu-sh reopened this Mar 1, 2023
@jdramsey
Copy link
Contributor

jdramsey commented Mar 1, 2023

What happened was that we had spent so much time fixing issues in Tetrad and finally had a version (7.2.2) that seemed to have fixed all outstanding reported bugs...so then we stopped and had a meeting and decided the next thing to do was to make it easier to deal with Tetrad from Python... so Bryan Andrews and I started looking around at recent methods for doing this and found JPype, which is just beautiful.

@yasu-sh
Copy link
Contributor Author

yasu-sh commented Mar 1, 2023

@jdramsey I appreciate your proposals and I will check the instruction of py-tetrad.
I thought it looked nice since tetrad itself can be wrapped.

@jdramsey
Copy link
Contributor

jdramsey commented Mar 1, 2023

I agree--there is really no separation between Python and java using this method. You just have to get used to writing Java "in Python" using Python syntax; JPype handles all of the details for you. It "marries" the Python and Java virtual machines to make this happen.

There are few details. You have to start the JVM from Python as before, and you can only do it once per session. Also, like I said you need to use >= 3.7 version for Python (since all underlying reference to Python 2 needs to be eliminated from the underlying code). A few other things.

@yasu-sh
Copy link
Contributor Author

yasu-sh commented Mar 1, 2023

My experience on analytics is mainly on R. But some years ago I used Python more often.
Tetrad software has useful GUI. I need to make not R interface but Python, it would be possible and need consideration. Anyway, thanks for your offer.
Most of my colleagues are using Python. No problem I can ask them.

@jdramsey
Copy link
Contributor

jdramsey commented Mar 1, 2023

Thanks!

@jdramsey
Copy link
Contributor

jdramsey commented Mar 1, 2023

I'd like to revisit R as well at some point, and see if there aren't more up-to-date ways of connecting R to Java. The main impediment is I would have to find time to do that myself; there's no one else in our group that does R. But I will try to get to it.

@jdramsey
Copy link
Contributor

jdramsey commented Mar 1, 2023

One thing that may be nice from your point of view for R is that we wrote a method to save out graphs in the "endpoint matrix" format of PCALG--it's returned as a numpy array, though I may change that to a pandas data frame so the variable names can be returned as well; you can always get a numpy array from the data frame if you don't need the variable names. But that might be the beginning of a way to interface Java with R in a more up-to-date way.

@jdramsey
Copy link
Contributor

jdramsey commented Mar 1, 2023

Anyway, first things first; we'd like to make it very easy to use Tetrad from Python, much easier than currently, and py-tetrad seems to promise that.

@yasu-sh
Copy link
Contributor Author

yasu-sh commented Mar 6, 2023

@jdramsey I have confirmed working py-tetrad at my windows machine.
It looks working well as long as python environment only.

  1. JVM: ver. 11
    OpenJDK Runtime Environment Temurin-11.0.18+10 (build 11.0.18+10)
  2. JAVA_HOME is set as above
    JAVA_HOME=C:\Program Files\Eclipse Adoptium\jdk-11.0.18.10-hotspot\
  3. Installed Python version 3.10
    Python 3.10.10 (tags/v3.10.10:aad5f6a, Feb 7 2023, 17:20:36) [MSC v.1929 64 bit (AMD64)] on win32
  4. Installed causal-learn(0.1.3.3) by pip
    pip install causal-learn
  5. Installed JPype(1.4.1) by pip
    pip install JPype1
  6. Cloned the github of py-tetrad

The location of 'file' is here.
E:\PyProjects\py-tetrad\examples..
E:\PyProjects\py-tetrad\examples\run_searches_on_discrete_data.py

@jdramsey
Copy link
Contributor

jdramsey commented Mar 6, 2023

Huh, interesting! OK, I learned something. Feel free to let me know if you find any valuable tweaks. But the Java version and the Python version are good, based on what I was expecting.

I think I know what you mean by "python environment only"--it would be nice if I could figure out how to publish the project in PyPl. I'll have to figure out how to fix the paths, but I can look at other projects.

And I promise I will start thinking about R again.

@yasu-sh
Copy link
Contributor Author

yasu-sh commented Mar 6, 2023

This was cross-comment on "python environment"... Sorry. (this was added later)

--
I notice that there are different way to call py-tetrad from my exisitng R codes.
Which do you recommend? I think the simplest way is the same as causal-cmd. ie 1.

Possible ways from R:

  1. Calls py-tetrad from command prompt, like causal-cmd
  2. Calls by using reticulate I/F (https://rstudio.github.io/reticulate/).
    it result in an error due to file's discrepancy,
 __file__ returns:
> case1: virtualenv - current virtualenv's activate_this.py. 
> case2: plain python.exe - not defined.

Questions:

  1. How to provide prior knowledge information for py-tetrad?
  2. How to output json-graph file after search?

@yasu-sh
Copy link
Contributor Author

yasu-sh commented Mar 6, 2023

py-tetrad ran with PyCharm CE on Win10 at Japanese locale! @jdramsey Thank you for your help!
image

@jdramsey
Copy link
Contributor

jdramsey commented Mar 6, 2023

That's great! :-D I'm glad it worked!

It's good to know there are some options for R; I'll try them out when I can. Our old project, https://github.com/bd2kccd/r-causal, used the command line option, but I still need to look closely at it. (Unfortunately, the guy who was maintaining that code left us, and we haven't had a chance to work through what he did, but I will.) The current problem is that it uses an old version of Tetrad, and a lot of the code needs to be updated; in that sense accessing Tetrad through Python would be a great option if it could work, though that does involve coordinating three languages.

Also, I am curious to know whether your problems are Windows-specific yet. Maybe I could get it to work on my Mac.

@jdramsey
Copy link
Contributor

jdramsey commented Mar 6, 2023

Looking briefly at the Reticulate docs, it seems I could solve the file path problem by figuring out how to publish py-tetrad to PyPl. I've never done that before, but maybe I can figure it out. Then you can just.

import pytetrad,

and then continue using the functionality in your project from there. I'm still learning how to do these sorts of things in Python.

@yasu-sh
Copy link
Contributor Author

yasu-sh commented Mar 6, 2023

@jdramsey Thank you for your investigation and document check.
I feel that the package-reticulate could require more time than simple call from console when breaking down issues.

For example, the latest version of reticulate(v.1.28-compiled on my PC) makes bombing error when calling python.
But stable version(v 1.24-cran binary) works fine when calling python at my PC.

ex. rstudio/reticulate#1258
I guess there are many similar incompatiblities. ex. my case:

R console
> sys$executable
[1] "C:\\Program Files\\RStudio\\resources\\app\\bin\\rsession.exe"

IPython
>>>  sys.executable
'C:\\Python\\venv\\pytetrad\\Scripts\\python.exe'

command prompt at R console

> library(reticulate)
> setwd("E:/PyProjects/py-tetrad")
> py_run_file("./examples/run_searches_on_discrete_data.py")
Error in py_run_file_impl(file, local, convert) : 
  FileNotFoundError: [Errno 2] No such file or directory: 'C:/Python/venv/pytetrad/Scripts\\../examples/resources/bridges.data.version211_rev.txt'

Detailed traceback:
  File "<string>", line 30, in <module>
  File "C:\Python\venv\pytetrad\lib\site-packages\pandas\io

This is return value of file

C:/Python/venv/pytetrad/Scripts..
C:/Python/venv/pytetrad/Scripts/activate_this.py

R environment information:

> sessionInfo()
R version 4.0.2 (2020-06-22)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 10 x64 (build 19044)

Matrix products: default

locale:
[1] LC_COLLATE=Japanese_Japan.932  LC_CTYPE=Japanese_Japan.932    LC_MONETARY=Japanese_Japan.932 LC_NUMERIC=C                   LC_TIME=Japanese_Japan.932    

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] reticulate_1.24

loaded via a namespace (and not attached):
[1] compiler_4.0.2  Matrix_1.2-18   tools_4.0.2     Rcpp_1.0.7      grid_4.0.2      jsonlite_1.7.2  png_0.1-7       lattice_0.20-41

Python environment information

> py_config()
python:         C:/Python/venv/pytetrad/Scripts/python.exe
libpython:      E:/Program Files/Python310/python310.dll
pythonhome:     C:/Python/venv/pytetrad
virtualenv:     C:/Python/venv/pytetrad/Scripts/activate_this.py
version:        3.10.10 (tags/v3.10.10:aad5f6a, Feb  7 2023, 17:20:36) [MSC v.1929 64 bit (AMD64)]
Architecture:   64bit
numpy:          C:/Python/venv/pytetrad/Lib/site-packages/numpy
numpy_version:  1.24.2

NOTE: Python version was forced by RETICULATE_PYTHON

@yasu-sh
Copy link
Contributor Author

yasu-sh commented Mar 7, 2023

@jdramsey This is my understanding on several ways to use tetrad at console / other packages in Python/R.
This information may be beneficial for you or not. But I thought it contributes reducing time from your side.

Project Calling place jar file I/F Package I/F Library Concerns / Notices
r-causal R causal-cmd rJava JNI Reflection needs to be avoid in for-loops.
py-tetrad R tetrad reticulate/JPype JNI needs to care about reticulate's incompatibility
py-tetrad Python tetrad JPype JNI NA
py-causal Python causal-cmd Javabridge JNA NA
causal-cmd Console causal-cmd None None Need file access / for general usage

r-causal: Need to avoid reflection(over 100x slow), possible for tetrad's java developers to choose methods without $ accessors.
https://www.rforge.net/rJava/#:~:text=You%20simply%20use,issues%20with%20it.

For my understanding, rJava is current golden standard I/F between Java and R.

@jdramsey
Copy link
Contributor

jdramsey commented Mar 7, 2023

@yasu-sh This is wonderful--thank you so much for doing this! Yes, this will most certainly help me. I will spend some time in the next few days studying these options. I am interested in your observation, first of all, that causal-cmd needs file access; I hadn't thought of that as a limitation for some people, but it might be; you're right. And the remark on r-causal is beneficial as well. Could reticulate's incompatibility be overcome? Anyway, this is food for thought.

Today I also started another project, which I plan to proceed slowly with. We have a command-line tool for making algorithm comparisons that is quite nice, algcomparison. The procedure is based in Tetrad and has been heavily used, so it is well-tested. Still, Kevin Bui added a facility to allow external search results to be added to the comparison tables from other platforms like Python, R, or Matlab. I decided to code up a Python wrapper for it to do Tetrad and causal-learn algorithms, but I'd like to extend that to R algorithms in, say, PCALG or bnlearn. So at some point, I need to reverse what you're suggesting, i.e., run R algorithms from Python, not just Python algorithms from R. I'll have to think of how to do that as well. But this could be a real contribution to the literature, showing how algorithms from different projects compare to one another on standard statistics so that you can pick the best algorithms (across platforms) for a task you have in mind. I do have to solve that technical challenge, though.

@jdramsey
Copy link
Contributor

jdramsey commented Mar 7, 2023

@yasu-sh I wonder if the slowness of reflection in for loops might be because the java jar needs to be loaded each time? This was one of the clever things about JPype, I thought--their insistence that the Java jar is loaded only once per session. It doesn't seem to me that reflection itself should take very much time.

@yasu-sh
Copy link
Contributor Author

yasu-sh commented Mar 7, 2023

@jdramsey Thanks for your quick reply.

file access on causal-cmd

I am interested in your observation, first of all, that causal-cmd needs file access; I hadn't thought of that as a limitation for some people, but it might be; you're right.

Regarding the file access, file-aceess is not limitation. I just thought it could become the limitation if you wants to hand over big-data(>2G). causa-cmd from console is basic and reliable. I like to use if there are no performance issues. (So far I use small data)

Reflection on R Java

No, it does not mean java jar's multi-calling. Java Reflection API need to find correct methods from many possibilities.
This is the code of r-causal I improved last year.

cate_list$add(as.character(cate[j])) is much slower than .jcall(cate_list, "Z", "add", .jcast(.jnew("java/lang/String", as.character(cate[j])), "java/lang/Object")).
There are two-for-loops on all rows and all columns. The code need time as follows: reflection * columns * rows.
I guess this must be avoided on JPype case also as long as dynamic method access is not be suppressed.
Definitely more efficient ways exist to make this. At that time I tried it to manupulate minimum.

https://github.com/bd2kccd/r-causal/blob/fc370245e938d5a2cb6e6abd4548bf7107fdd1dc/R/tetrad_utils.R#L326

loadDiscreteData <- function(df){
(cut)
	for (i in 1:length(node_names)){
(cut)
		for(j in 1:length(cate)){
#			cate_list$add(as.character(cate[j]))
		  .jcall(cate_list, "Z", "add", .jcast(.jnew("java/lang/String", as.character(cate[j])), "java/lang/Object"))
		}

R from Python

I have heard that a colleague uses RPY2. It seems to work without fatal issues.
https://rpy2.github.io/

@jdramsey
Copy link
Contributor

jdramsey commented Mar 7, 2023

@yasu-sh On reflection--I see. That is a real limitation. We tested the data translation methods in JPype with some rather large datasets, and they didn't slow down like that. I need to think about it.

I did notice that the Tetrad data loading routine implemented by Kevin was much faster than the one in Python for continuous data; I should test that with discrete data as well.

Let me add a discrete simulation to py_tetrad, do a save and load in Python, and transfer it back to Java, and see where there is a slowdown.

@jdramsey
Copy link
Contributor

jdramsey commented Mar 7, 2023

@yasu-sh It's fast enough in py-tetrad; I made a 500-variable dataset with N = 500 using this method:

https://github.com/cmu-phil/py-tetrad/blob/main/examples/simulating_data_discrete.py

Then I converted it from Tetrad to pandas in Python and back again and added print statements to see how long each step took. Loading the JVM took a few seconds, and the simulation itself also took a few seconds, but the conversion to pandas and the conversion from pandas to Tetrad each took about one second, which I thought was OK.

So the question is whether there's a method to transfer a dataset to R that's about the same speed.

@jdramsey
Copy link
Contributor

jdramsey commented Mar 7, 2023

@yasu-sh I spent some time today turning py-tetrad into a Python package. This may solve the file path problem. It's not done by any means, but it's going in the right direction. All of the hard-coded paths are gone.

It's not much of a package yet, just two files plus several examples, but it will grow. Also, it must be installed by checking it out from GitHub and then using pip to install the package, so the instructions have changed. But perhaps now in R you can import the package and run the examples? I'll have to try it.

@yasu-sh
Copy link
Contributor Author

yasu-sh commented Mar 8, 2023

@jdramsey package runs successfully on python

1. (pytetrad) PS E:\PyProjects> $env:JAVA_HOME
C:\Program Files\Eclipse Adoptium\jdk-11.0.18.10-hotspot\

2. Install via pip
Successfully built py-tetrad
Installing collected packages: py-tetrad
Successfully installed py-tetrad-0.1

3.
(pytetrad) PS E:\PyProjects> cd py-tetrad/examples                    

4.
(pytetrad) PS E:\PyProjects\py-tetrad\examples> python run_searches_on_continuous_data.py > output.txt

 #### inside output.txt ####
Elapsed initializeForwardEdgesFromEmptyGraph = 0 ms
1. INSERT Attack --> Displacement [] 623.1587215188538 degree = 1 indegree = 1 cond = 1
2. INSERT Chord --> Attack [Displacement] 238.25923654533153 degree = 2 indegree = 1 cond = 2
--- Directing Displacement --> Attack
3. INSERT Frequency --> Pressure [] 117.16912428882142 degree = 2 indegree = 2 cond = 1
4. INSERT Displacement --> Pressure [Frequency] 162.33668553267944 degree = 2 indegree = 2 cond = 2
--- Directing Frequency --> Pressure
5. INSERT Chord --> Pressure [] 134.30338539976947 degree = 3 indegree = 3 cond = 3
6. INSERT Attack --> Frequency [] 50.785978197867735 degree = 3 indegree = 3 cond = 1
7. INSERT Velocity --> Pressure [] 45.056623591369316 degree = 4 indegree = 4 cond = 4
8. INSERT Attack --> Pressure [] 49.445992425935856 degree = 5 indegree = 5 cond = 5
9. INSERT Displacement --> Chord [] 30.227695613430114 degree = 5 indegree = 5 cond = 1
10. INSERT Velocity --> Frequency [Attack] 11.166001339552167 degree = 5 indegree = 5 cond = 2
--- Directing Attack --> Frequency
11. INSERT Chord --> Frequency [] 17.04597303328046 degree = 5 indegree = 5 cond = 3
12. INSERT Velocity --> Attack [Chord, Displacement] 2.2857250149374977 degree = 5 indegree = 5 cond = 3
--- Directing Chord --> Attack
--- Directing Displacement --> Attack
Elapsed time = 0.125 s

FGES

Graph Nodes:
Frequency;Attack;Chord;Velocity;Displacement;Pressure
...

I'll check at R next.

@yasu-sh
Copy link
Contributor Author

yasu-sh commented Mar 8, 2023

@jdramsey By the way, shall we move to py-tetrad issue from here? I think this issue can be closed and the matter is for py-tetrad now.

@yasu-sh
Copy link
Contributor Author

yasu-sh commented Mar 8, 2023

@yasu-sh yasu-sh closed this as completed Mar 8, 2023
@jdramsey
Copy link
Contributor

jdramsey commented Mar 8, 2023

Sounds good.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants