From e4e7588a6a26b84ddb0c55a3e709ff2e14e9b0ca Mon Sep 17 00:00:00 2001 From: jdramsey Date: Wed, 15 Nov 2023 18:03:47 -0500 Subject: [PATCH 001/163] Updating version to 7.6.2-SNAPSHOT. --- data-reader/pom.xml | 2 +- pom.xml | 2 +- tetrad-gui/pom.xml | 2 +- tetrad-lib/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/data-reader/pom.xml b/data-reader/pom.xml index b18df6845f..55a001ea55 100644 --- a/data-reader/pom.xml +++ b/data-reader/pom.xml @@ -5,7 +5,7 @@ io.github.cmu-phil tetrad - 7.6.1 + 7.6.2-SNAPSHOT data-reader diff --git a/pom.xml b/pom.xml index b03d15628e..6e02a473f9 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 io.github.cmu-phil tetrad - 7.6.1 + 7.6.2-SNAPSHOT pom Tetrad Project diff --git a/tetrad-gui/pom.xml b/tetrad-gui/pom.xml index 0483b1ab23..e2df09adae 100644 --- a/tetrad-gui/pom.xml +++ b/tetrad-gui/pom.xml @@ -6,7 +6,7 @@ io.github.cmu-phil tetrad - 7.6.1 + 7.6.2-SNAPSHOT tetrad-gui diff --git a/tetrad-lib/pom.xml b/tetrad-lib/pom.xml index b963ae99b4..682f91eae0 100644 --- a/tetrad-lib/pom.xml +++ b/tetrad-lib/pom.xml @@ -6,7 +6,7 @@ io.github.cmu-phil tetrad - 7.6.1 + 7.6.2-SNAPSHOT tetrad-lib From 39a79c480bbab42b207ff40b53bb254bb7feae3f Mon Sep 17 00:00:00 2001 From: Joseph Ramsey Date: Wed, 15 Nov 2023 18:11:16 -0500 Subject: [PATCH 002/163] Update INSTALL_APPLICATION.md --- INSTALL_APPLICATION.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/INSTALL_APPLICATION.md b/INSTALL_APPLICATION.md index 3158b22fd5..7db8efcdf6 100644 --- a/INSTALL_APPLICATION.md +++ b/INSTALL_APPLICATION.md @@ -6,7 +6,7 @@ Please use a recent Java JDK. See [Setting up Java for Tetrad](https://github.co To download the Tetrad jar, please click the following link (which will always be updated to the latest version): -https://s01.oss.sonatype.org/content/repositories/releases/io/github/cmu-phil/tetrad-gui/7.6.0/tetrad-gui-7.6.0-launch.jar +https://s01.oss.sonatype.org/content/repositories/releases/io/github/cmu-phil/tetrad-gui/7.6.1/tetrad-gui-7.6.1-launch.jar You may be able to launch this jar by double-clicking the jar file name. However, on a Mac, this presents some security challenges. On all platforms, the jar may be launched at the command line (with a specification of the amount of RAM you will allow it to use) using this command: From 8ded6357352f018d77e50af8ad3b25f57f7ff7f9 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Tue, 21 Nov 2023 06:46:46 -0500 Subject: [PATCH 003/163] Adding IMaGES-BOSS. --- .../algorithm/multi/ImagesBoss.java | 217 ++++++++++++++++++ 1 file changed, 217 insertions(+) create mode 100644 tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/multi/ImagesBoss.java diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/multi/ImagesBoss.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/multi/ImagesBoss.java new file mode 100644 index 0000000000..eca28c086e --- /dev/null +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/multi/ImagesBoss.java @@ -0,0 +1,217 @@ +package edu.cmu.tetrad.algcomparison.algorithm.multi; + +import edu.cmu.tetrad.algcomparison.algorithm.MultiDataSetAlgorithm; +import edu.cmu.tetrad.algcomparison.algorithm.oracle.cpdag.Fges; +import edu.cmu.tetrad.algcomparison.independence.IndependenceWrapper; +import edu.cmu.tetrad.algcomparison.score.ScoreWrapper; +import edu.cmu.tetrad.algcomparison.score.SemBicScore; +import edu.cmu.tetrad.algcomparison.utils.HasKnowledge; +import edu.cmu.tetrad.algcomparison.utils.UsesScoreWrapper; +import edu.cmu.tetrad.annotation.AlgType; +import edu.cmu.tetrad.annotation.Bootstrapping; +import edu.cmu.tetrad.data.*; +import edu.cmu.tetrad.graph.EdgeListGraph; +import edu.cmu.tetrad.graph.Graph; +import edu.cmu.tetrad.search.Boss; +import edu.cmu.tetrad.search.PermutationSearch; +import edu.cmu.tetrad.search.score.ImagesScore; +import edu.cmu.tetrad.search.score.Score; +import edu.cmu.tetrad.search.utils.TsUtils; +import edu.cmu.tetrad.util.Parameters; +import edu.cmu.tetrad.util.Params; +import edu.pitt.dbmi.algo.resampling.GeneralResamplingTest; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +/** + * Wraps the IMaGES algorithm for continuous variables. This version uses the BOSS algorithm in place of FGES. + *

+ * Requires that the parameter 'randomSelectionSize' be set to indicate how many datasets should be taken at a time + * (randomly). This cannot given multiple values. + * + * @author josephramsey + */ +@edu.cmu.tetrad.annotation.Algorithm( + name = "IMaGES-BOSS", + command = "images-boss", + algoType = AlgType.forbid_latent_common_causes, + dataType = DataType.All +) +@Bootstrapping +public class ImagesBoss implements MultiDataSetAlgorithm, HasKnowledge, UsesScoreWrapper { + + private static final long serialVersionUID = 23L; + private Knowledge knowledge = new Knowledge(); + + private ScoreWrapper score = new SemBicScore(); + + public ImagesBoss(ScoreWrapper score) { + this.score = score; + } + + public ImagesBoss() { + } + + @Override + public Graph search(List dataSets, Parameters parameters) { + int meta = parameters.getInt(Params.IMAGES_META_ALG); + + if (parameters.getInt(Params.NUMBER_RESAMPLING) < 1) { + List _dataSets = new ArrayList<>(); + + if (parameters.getInt(Params.TIME_LAG) > 0) { + for (DataModel dataSet : dataSets) { + DataSet timeSeries = TsUtils.createLagData((DataSet) dataSet, parameters.getInt(Params.TIME_LAG)); + if (dataSet.getName() != null) { + timeSeries.setName(dataSet.getName()); + } + _dataSets.add(timeSeries); + } + + dataSets = _dataSets; + } + + List scores = new ArrayList<>(); + + for (DataModel dataModel : dataSets) { + Score s = score.getScore(dataModel, parameters); + scores.add(s); + } + + ImagesScore score = new ImagesScore(scores); + + if (meta == 1) { + PermutationSearch search = new PermutationSearch(new Boss(score)); +// edu.cmu.tetrad.search.Fges search = new edu.cmu.tetrad.search.Fges(score); + search.setKnowledge(this.knowledge); +// search.setVerbose(parameters.getBoolean(Params.VERBOSE)); + return search.search(); + } else if (meta == 2) { + PermutationSearch search = new PermutationSearch(new Boss(score)); + search.setKnowledge(this.knowledge); + return search.search(); + } else { + throw new IllegalArgumentException("Unrecognized meta option: " + meta); + } + } else { + ImagesBoss imagesSemBic = new ImagesBoss(); + + List dataSets2 = new ArrayList<>(); + + for (DataModel dataModel : dataSets) { + dataSets2.add((DataSet) dataModel); + } + + List _dataSets = new ArrayList<>(); + + if (parameters.getInt(Params.TIME_LAG) > 0) { + for (DataSet dataSet : dataSets2) { + DataSet timeSeries = TsUtils.createLagData(dataSet, parameters.getInt(Params.TIME_LAG)); + if (dataSet.getName() != null) { + timeSeries.setName(dataSet.getName()); + } + _dataSets.add(timeSeries); + } + + dataSets2 = _dataSets; + } + + GeneralResamplingTest search = new GeneralResamplingTest( + dataSets2, + imagesSemBic, + parameters.getInt(Params.NUMBER_RESAMPLING), + parameters.getDouble(Params.PERCENT_RESAMPLE_SIZE), + parameters.getBoolean(Params.RESAMPLING_WITH_REPLACEMENT), parameters.getInt(Params.RESAMPLING_ENSEMBLE), parameters.getBoolean(Params.ADD_ORIGINAL_DATASET)); + search.setParameters(parameters); + search.setVerbose(parameters.getBoolean(Params.VERBOSE)); + search.setKnowledge(this.knowledge); + search.setScoreWrapper(score); + return search.search(); + } + } + + @Override + public Graph search(DataModel dataSet, Parameters parameters) { + if (parameters.getInt(Params.NUMBER_RESAMPLING) < 1) { + return search(Collections.singletonList(SimpleDataLoader.getMixedDataSet(dataSet)), parameters); + } else { + ImagesBoss images = new ImagesBoss(); + + List dataSets = Collections.singletonList(SimpleDataLoader.getMixedDataSet(dataSet)); + GeneralResamplingTest search = new GeneralResamplingTest(dataSets, + images, + parameters.getInt(Params.NUMBER_RESAMPLING), + parameters.getDouble(Params.PERCENT_RESAMPLE_SIZE), + parameters.getBoolean(Params.RESAMPLING_WITH_REPLACEMENT), + parameters.getInt(Params.RESAMPLING_ENSEMBLE), + parameters.getBoolean(Params.ADD_ORIGINAL_DATASET)); + + if (score == null) { + System.out.println(); + } + + search.setParameters(parameters); + search.setVerbose(parameters.getBoolean(Params.VERBOSE)); + search.setScoreWrapper(score); + return search.search(); + } + } + + @Override + public Graph getComparisonGraph(Graph graph) { + return new EdgeListGraph(graph); + } + + @Override + public String getDescription() { + return "IMaGES"; + } + + @Override + public DataType getDataType() { + return DataType.All; + } + + @Override + public List getParameters() { + List parameters = new LinkedList<>(); + parameters.addAll(new SemBicScore().getParameters()); + + parameters.addAll((new Fges()).getParameters()); + parameters.add(Params.RANDOM_SELECTION_SIZE); + parameters.add(Params.TIME_LAG); + parameters.add(Params.IMAGES_META_ALG); + + parameters.add(Params.VERBOSE); + + return parameters; + } + + @Override + public Knowledge getKnowledge() { + return this.knowledge; + } + + @Override + public void setKnowledge(Knowledge knowledge) { + this.knowledge = new Knowledge((Knowledge) knowledge); + } + + @Override + public ScoreWrapper getScoreWrapper() { + return this.score; + } + + @Override + public void setScoreWrapper(ScoreWrapper score) { + this.score = score; + } + + @Override + public void setIndTestWrapper(IndependenceWrapper test) { + // Not used. + } +} From 99b33951143bda36ee72b56e77e26265cd0105cc Mon Sep 17 00:00:00 2001 From: jdramsey Date: Fri, 24 Nov 2023 14:55:19 -0500 Subject: [PATCH 004/163] Added Bryan's Binomial check to the Markov Checker. --- .../main/java/edu/cmu/tetradapp/Tetrad.java | 13 +- .../tetradapp/editor/MarkovCheckEditor.java | 33 ++++- .../edu/cmu/tetrad/search/MarkovCheck.java | 116 ++++++++++++++++-- .../tetrad/search/test/IndTestFisherZ.java | 46 ++++++- .../cmu/tetrad/search/test/RowsSettable.java | 19 +++ .../edu/cmu/tetrad/util/UniformityTest.java | 4 +- 6 files changed, 204 insertions(+), 27 deletions(-) create mode 100644 tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/RowsSettable.java diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/Tetrad.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/Tetrad.java index 6e9d9fb2cd..6341e1a9c1 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/Tetrad.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/Tetrad.java @@ -158,13 +158,12 @@ private void launchFrame() { @Override public Dimension getPreferredSize() { - Dimension size = Toolkit.getDefaultToolkit().getScreenSize(); - double minLength = FastMath.min(size.getWidth(), size.getHeight()); - double height = minLength * 0.8; - double width = height * (4.0 / 3); - - return new Dimension((int) width, (int) height); - +// Dimension size = Toolkit.getDefaultToolkit().getScreenSize(); +// double minLength = FastMath.min(size.getWidth(), size.getHeight()); +// double height = minLength * 0.8; +// double width = height * (4.0 / 3); +// return new Dimension((int) width, (int) height); + return Toolkit.getDefaultToolkit().getScreenSize(); } }; diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java index 3e06f09bc4..a4ccaba79d 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java @@ -85,6 +85,8 @@ public class MarkovCheckEditor extends JPanel { private JLabel ksLabelIndep; private JLabel masLabelDep; private JLabel masLabelIndep; + private JLabel bernoulliPLabelDep; + private JLabel bernoulliPLabelIndep; private int sortDir; private int lastSortCol; private IndependenceWrapper independenceWrapper; @@ -533,6 +535,11 @@ public void mouseClicked(MouseEvent e) { b6.add(ksLabelDep); b0b1.add(b6); + Box b6a = Box.createHorizontalBox(); + b6a.add(Box.createHorizontalGlue()); + b6a.add(bernoulliPLabelDep); + b0b1.add(b6a); + Box b7 = Box.createHorizontalBox(); b7.add(Box.createHorizontalGlue()); b7.add(masLabelDep); @@ -726,6 +733,11 @@ public void mouseClicked(MouseEvent e) { b6.add(ksLabelIndep); b0b1.add(b6); + Box b6a = Box.createHorizontalBox(); + b6a.add(Box.createHorizontalGlue()); + b6a.add(bernoulliPLabelIndep); + b0b1.add(b6a); + Box b7 = Box.createHorizontalBox(); b7.add(Box.createHorizontalGlue()); b7.add(masLabelIndep); @@ -768,6 +780,14 @@ private void setLabelTexts() { ksLabelDep = new JLabel(); } + if (bernoulliPLabelIndep == null) { + bernoulliPLabelIndep = new JLabel(); + } + + if (bernoulliPLabelDep == null) { + bernoulliPLabelDep = new JLabel(); + } + if (fractionDepLabelIndep == null) { fractionDepLabelIndep = new JLabel(); } @@ -784,14 +804,23 @@ private void setLabelTexts() { masLabelDep = new JLabel(); } - ksLabelIndep.setText("P-value of Kolmogorov-Smirnov Uniformity Test = " + ksLabelIndep.setText("P-value of KS Uniformity Test = " + ((Double.isNaN(model.getMarkovCheck().getKsPValue(true)) ? "-" : NumberFormatUtil.getInstance().getNumberFormat().format(model.getMarkovCheck().getKsPValue(true))))); - ksLabelDep.setText("P-value of Kolmogorov-Smirnov Uniformity Test = " + ksLabelDep.setText("P-value of KS Uniformity Test = " + ((Double.isNaN(model.getMarkovCheck().getKsPValue(false)) ? "-" : NumberFormatUtil.getInstance().getNumberFormat().format(model.getMarkovCheck().getKsPValue(false))))); + + bernoulliPLabelIndep.setText("P-value of Bernoulli Test = " + + ((Double.isNaN(model.getMarkovCheck().getBernoulliPValue(true)) + ? "-" + : NumberFormatUtil.getInstance().getNumberFormat().format(model.getMarkovCheck().getBernoulliPValue(true))))); + bernoulliPLabelDep.setText("P-value of Bernoulli Test = " + + ((Double.isNaN(model.getMarkovCheck().getBernoulliPValue(false)) + ? "-" + : NumberFormatUtil.getInstance().getNumberFormat().format(model.getMarkovCheck().getBernoulliPValue(false))))); fractionDepLabelIndep.setText("% dependent = " + ((Double.isNaN(model.getMarkovCheck().getFractionDependent(true)) ? "-" diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java index bca58d5fcc..40488c9828 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java @@ -6,8 +6,11 @@ import edu.cmu.tetrad.graph.Node; import edu.cmu.tetrad.search.test.IndependenceResult; import edu.cmu.tetrad.search.test.MsepTest; +import edu.cmu.tetrad.search.test.RowsSettable; +import edu.cmu.tetrad.util.RandomUtil; import edu.cmu.tetrad.util.SublistGenerator; import edu.cmu.tetrad.util.UniformityTest; +import org.apache.commons.math3.distribution.BinomialDistribution; import org.apache.commons.math3.util.FastMath; import org.jetbrains.annotations.NotNull; @@ -50,6 +53,8 @@ public class MarkovCheck { private double fractionDependentDep = Double.NaN; private double ksPValueIndep = Double.NaN; private double ksPValueDep = Double.NaN; + private double bernoulliPIndep = Double.NaN; + private double bernoulliPDep = Double.NaN; /** * Constructor. Takes a graph and an independence test over the variables of the graph. @@ -304,6 +309,14 @@ public double getKsPValue(boolean indep) { } } + public double getBernoulliPValue(boolean indep) { + if (indep) { + return bernoulliPIndep; + } else { + return bernoulliPDep; + } + } + /** * Returns the Markov Adequacy Score for the graph. This is zero if the p-value of the KS test of Uniformity is less * than alpha, and the fraction of dependent pairs otherwise. This is only for continuous Gaussian data, as it @@ -389,21 +402,61 @@ public List call() { Node x = fact.getX(); Node y = fact.getY(); Set z = fact.getZ(); - boolean verbose = independenceTest.isVerbose(); - independenceTest.setVerbose(false); - IndependenceResult result; - try { - result = independenceTest.checkIndependence(x, y, z); - } catch (Exception e) { - throw new RuntimeException(e); - } - boolean indep = result.isIndependent(); - double pValue = result.getPValue(); - independenceTest.setVerbose(verbose); - if (!Double.isNaN(pValue)) { - results.add(new IndependenceResult(fact, indep, pValue, Double.NaN)); + if (independenceTest instanceof RowsSettable) { + for (int t = 0; t < 5; t++) { + List rows = getSubsampleRows(0.8); +// List rows = getBoostrapSample(1.0); + ((RowsSettable) independenceTest).setRows(rows); + + boolean verbose = independenceTest.isVerbose(); + independenceTest.setVerbose(false); + IndependenceResult result; + try { + result = independenceTest.checkIndependence(x, y, z); + } catch (Exception e) { + throw new RuntimeException(e); + } + boolean indep = result.isIndependent(); + double pValue = result.getPValue(); + independenceTest.setVerbose(verbose); + + if (!Double.isNaN(pValue)) { + results.add(new IndependenceResult(fact, indep, pValue, Double.NaN)); + } + } + } else { + boolean verbose = independenceTest.isVerbose(); + independenceTest.setVerbose(false); + IndependenceResult result; + try { + result = independenceTest.checkIndependence(x, y, z); + } catch (Exception e) { + throw new RuntimeException(e); + } + boolean indep = result.isIndependent(); + double pValue = result.getPValue(); + independenceTest.setVerbose(verbose); + + if (!Double.isNaN(pValue)) { + results.add(new IndependenceResult(fact, indep, pValue, Double.NaN)); + } } +// boolean verbose = independenceTest.isVerbose(); +// independenceTest.setVerbose(false); +// IndependenceResult result; +// try { +// result = independenceTest.checkIndependence(x, y, z); +// } catch (Exception e) { +// throw new RuntimeException(e); +// } +// boolean indep = result.isIndependent(); +// double pValue = result.getPValue(); +// independenceTest.setVerbose(verbose); +// +// if (!Double.isNaN(pValue)) { +// results.add(new IndependenceResult(fact, indep, pValue, Double.NaN)); +// } } return results; @@ -438,6 +491,27 @@ public List call() { } } + private List getSubsampleRows(double v) { + int sampleSize = independenceTest.getSampleSize(); + int subsampleSize = (int) FastMath.ceil(sampleSize * v); + List rows = new ArrayList<>(sampleSize); + for (int i = 0; i < sampleSize; i++) { + rows.add(i); + } + Collections.shuffle(rows); + return rows.subList(0, subsampleSize); + } + + private List getBoostrapSample(double v) { + int sampleSize = independenceTest.getSampleSize(); + int subsampleSize = (int) FastMath.floor(sampleSize * v); + List rows = new ArrayList<>(sampleSize); + for (int i = 0; i < subsampleSize; i++) { + rows.add(RandomUtil.getInstance().nextInt(sampleSize)); + } + return rows; + } + private void generateResultsAllSubsets(boolean indep, List msep, List mconn) { List facts = indep ? msep : mconn; @@ -534,18 +608,34 @@ private void calcStats(boolean indep) { if (indep) { if (pValues.size() < 2) { ksPValueIndep = Double.NaN; + bernoulliPIndep = Double.NaN; } else { ksPValueIndep = UniformityTest.getPValue(pValues); + bernoulliPIndep = getBernoulliP(pValues, independenceTest.getAlpha()); } } else { if (pValues.size() < 2) { ksPValueDep = Double.NaN; + bernoulliPDep = Double.NaN; } else { ksPValueDep = UniformityTest.getPValue(pValues); + bernoulliPDep = getBernoulliP(pValues, independenceTest.getAlpha()); } } } + private double getBernoulliP(List pValues, double alpha) { + int successes = 0; + + for (double pValue : pValues) { + if (pValue > alpha) successes++; + } + + int n = pValues.size(); + BinomialDistribution bd = new BinomialDistribution(n, 1.0 - alpha); + return (1.0 - bd.cumulativeProbability(successes)); + } + private int getChunkSize(int n) { int chunk = (int) FastMath.ceil((n / ((double) (5 * Runtime.getRuntime().availableProcessors())))); if (chunk < 1) chunk = 1; diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java index 729eda85e7..78559f28aa 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java @@ -25,7 +25,6 @@ import edu.cmu.tetrad.graph.IndependenceFact; import edu.cmu.tetrad.graph.Node; import edu.cmu.tetrad.search.IndependenceTest; -import edu.cmu.tetrad.search.utils.GraphSearchUtils; import edu.cmu.tetrad.search.utils.LogUtilsSearch; import edu.cmu.tetrad.util.Matrix; import edu.cmu.tetrad.util.MatrixUtils; @@ -55,6 +54,7 @@ public final class IndTestFisherZ implements IndependenceTest { private final Map nameMap; private final NormalDistribution normal = new NormalDistribution(0, 1, 1e-15); private final Map nodesHash; + private final int sampleSize; private ICovarianceMatrix cor = null; private List variables; private double alpha; @@ -62,6 +62,7 @@ public final class IndTestFisherZ implements IndependenceTest { private boolean verbose = true; // private double p = Double.NaN; private double r = Double.NaN; + private List rows = null; /** @@ -114,6 +115,8 @@ public IndTestFisherZ(DataSet dataSet, double alpha) { this.nodesHash = nodesHash; } + + this.sampleSize = dataSet.getNumRows(); } /** @@ -138,6 +141,8 @@ public IndTestFisherZ(Matrix data, List variables, double alpha) { } this.nodesHash = nodesHash; + this.sampleSize = dataSet.getNumRows(); + } /** @@ -161,6 +166,8 @@ public IndTestFisherZ(ICovarianceMatrix covMatrix, double alpha) { } this.nodesHash = nodesHash; + this.sampleSize = cor.getSampleSize(); + } @@ -357,7 +364,7 @@ public List getDataSets() { */ @Override public int getSampleSize() { - return this.cor.getSampleSize(); + return this.sampleSize(); } /** @@ -470,7 +477,7 @@ private double getR(Node x, Node y, Set z, List rows) { } private int sampleSize() { - return covMatrix().getSampleSize(); + return sampleSize; } private ICovarianceMatrix covMatrix() { @@ -498,6 +505,10 @@ private Map indexMap(List variables) { } private List getRows(List allVars, Map nodesHash) { + if (rows != null) { + return rows; + } + List rows = new ArrayList<>(); K: @@ -511,6 +522,35 @@ private List getRows(List allVars, Map nodesHash) return rows; } + + /** + * Gets the rows to use for the test. These rows over override testwise deletion + * if set. + * @return The rows to use for the test. Can be null. + */ + public List getRows() { + return rows; + } + + /** + * Sets the rows to use for the test. This will override testwise deletion. + * @param rows The rows to use for the test. Can be null. + */ + public void setRows(List rows) { + if (rows != null) { + for (int i = 0; i < rows.size(); i++) { + if (rows.get(i) < 0 || rows.get(i) > sampleSize()) { + throw new IllegalArgumentException("Row index = " + i + "=" + rows.get(i) + " is out of bounds."); + } + } + + this.cor = null; + } else { + this.cor = new CorrelationMatrix(dataSet); + } + + this.rows = rows; + } } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/RowsSettable.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/RowsSettable.java new file mode 100644 index 0000000000..e786ba36b8 --- /dev/null +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/RowsSettable.java @@ -0,0 +1,19 @@ +package edu.cmu.tetrad.search.test; + +import java.util.List; + +public interface RowsSettable { + + /** + * Gets the rows to use for the test. These rows over override testwise deletion + * if set. + * @return The rows to use for the test. Can be null. + */ + List getRows(); + + /** + * Sets the rows to use for the test. This will override testwise deletion. + * @param rows The rows to use for the test. Can be null. + */ + void setRows(List rows); +} diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/util/UniformityTest.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/util/UniformityTest.java index b3d9b402c6..7e113bc6a2 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/util/UniformityTest.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/util/UniformityTest.java @@ -14,8 +14,8 @@ public static double getPValue(List points) { double[] data = points.stream().mapToDouble(Double::doubleValue).toArray(); // Create a uniform distribution with the same range as the data - double min = points.stream().min(Double::compareTo).orElse(0.0); - double max = points.stream().max(Double::compareTo).orElse(1.0); + double min = 0.0;//points.stream().min(Double::compareTo).orElse(0.0); + double max = 1.0;//points.stream().max(Double::compareTo).orElse(1.0); UniformRealDistribution distribution; try { distribution = new UniformRealDistribution(min, max); From 2ab30ad4a78fbbca6ea536873d05eb2dea713a86 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Fri, 24 Nov 2023 16:31:26 -0500 Subject: [PATCH 005/163] Added Bryan's Binomial check to the Markov Checker. --- .../cmu/tetradapp/editor/MarkovCheckEditor.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java index a4ccaba79d..64cdb7dbba 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java @@ -540,10 +540,10 @@ public void mouseClicked(MouseEvent e) { b6a.add(bernoulliPLabelDep); b0b1.add(b6a); - Box b7 = Box.createHorizontalBox(); - b7.add(Box.createHorizontalGlue()); - b7.add(masLabelDep); - b0b1.add(b7); +// Box b7 = Box.createHorizontalBox(); +// b7.add(Box.createHorizontalGlue()); +// b7.add(masLabelDep); +// b0b1.add(b7); b0b1.add(Box.createVerticalGlue()); b0.add(b0b1); @@ -738,10 +738,10 @@ public void mouseClicked(MouseEvent e) { b6a.add(bernoulliPLabelIndep); b0b1.add(b6a); - Box b7 = Box.createHorizontalBox(); - b7.add(Box.createHorizontalGlue()); - b7.add(masLabelIndep); - b0b1.add(b7); +// Box b7 = Box.createHorizontalBox(); +// b7.add(Box.createHorizontalGlue()); +// b7.add(masLabelIndep); +// b0b1.add(b7); b0.add(b0b1); From 5655d2a9f558cc7a001c17df00f533c58e8fa552 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Sat, 25 Nov 2023 17:00:41 -0500 Subject: [PATCH 006/163] Fixed the bounds issue for the UniformityTest. --- .../edu/cmu/tetrad/search/MarkovCheck.java | 4 +-- .../edu/cmu/tetrad/util/UniformityTest.java | 25 ++++++++++++------- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java index 40488c9828..3bf4eb542e 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java @@ -610,7 +610,7 @@ private void calcStats(boolean indep) { ksPValueIndep = Double.NaN; bernoulliPIndep = Double.NaN; } else { - ksPValueIndep = UniformityTest.getPValue(pValues); + ksPValueIndep = UniformityTest.getPValue(pValues, 0.0, 1.0); bernoulliPIndep = getBernoulliP(pValues, independenceTest.getAlpha()); } } else { @@ -618,7 +618,7 @@ private void calcStats(boolean indep) { ksPValueDep = Double.NaN; bernoulliPDep = Double.NaN; } else { - ksPValueDep = UniformityTest.getPValue(pValues); + ksPValueDep = UniformityTest.getPValue(pValues, 0.0, 1.0); bernoulliPDep = getBernoulliP(pValues, independenceTest.getAlpha()); } } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/util/UniformityTest.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/util/UniformityTest.java index 7e113bc6a2..b41854f290 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/util/UniformityTest.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/util/UniformityTest.java @@ -10,23 +10,30 @@ public class UniformityTest { public static double getPValue(List points) { - // Convert the list to a primitive double array - double[] data = points.stream().mapToDouble(Double::doubleValue).toArray(); // Create a uniform distribution with the same range as the data - double min = 0.0;//points.stream().min(Double::compareTo).orElse(0.0); - double max = 1.0;//points.stream().max(Double::compareTo).orElse(1.0); - UniformRealDistribution distribution; + double min = points.stream().min(Double::compareTo).orElse(0.0); + double max = points.stream().max(Double::compareTo).orElse(1.0); + + return getPValue(points, min, max); + } + + public static double getPValue(List points, double min, double max) { + + // Create a uniform distribution with the same range as the data try { - distribution = new UniformRealDistribution(min, max); + double[] data = points.stream().mapToDouble(Double::doubleValue).toArray(); + + UniformRealDistribution distribution = new UniformRealDistribution(min, max); + + // Perform the Kolmogorov-Smirnov test + KolmogorovSmirnovTest test = new KolmogorovSmirnovTest(); + return test.kolmogorovSmirnovTest(distribution, data); } catch (NumberIsTooLargeException e) { e.printStackTrace(); return Double.NaN; } - // Perform the Kolmogorov-Smirnov test - KolmogorovSmirnovTest test = new KolmogorovSmirnovTest(); - return test.kolmogorovSmirnovTest(distribution, data); } public static void main(String[] args) { From b2bd0f672c38ce7b6d48d6e761f9d0dd82da1a0b Mon Sep 17 00:00:00 2001 From: jdramsey Date: Mon, 27 Nov 2023 11:22:17 -0500 Subject: [PATCH 007/163] Committing a few updates to Markov Check. --- .../tetradapp/editor/MarkovCheckEditor.java | 34 +-- .../statistic/MarkovAdequacyScore.java | 46 --- .../edu/cmu/tetrad/search/MarkovCheck.java | 279 ++++++++++-------- .../tetrad/search/test/IndTestFisherZ.java | 8 +- 4 files changed, 172 insertions(+), 195 deletions(-) delete mode 100644 tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/MarkovAdequacyScore.java diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java index 64cdb7dbba..7989c360dc 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java @@ -83,8 +83,8 @@ public class MarkovCheckEditor extends JPanel { private JLabel fractionDepLabelDep; private JLabel ksLabelDep; private JLabel ksLabelIndep; - private JLabel masLabelDep; - private JLabel masLabelIndep; +// private JLabel masLabelDep; +// private JLabel masLabelIndep; private JLabel bernoulliPLabelDep; private JLabel bernoulliPLabelIndep; private int sortDir; @@ -796,13 +796,13 @@ private void setLabelTexts() { fractionDepLabelDep = new JLabel(); } - if (masLabelIndep == null) { - masLabelIndep = new JLabel(); - } - - if (masLabelDep == null) { - masLabelDep = new JLabel(); - } +// if (masLabelIndep == null) { +// masLabelIndep = new JLabel(); +// } +// +// if (masLabelDep == null) { +// masLabelDep = new JLabel(); +// } ksLabelIndep.setText("P-value of KS Uniformity Test = " + ((Double.isNaN(model.getMarkovCheck().getKsPValue(true)) @@ -829,14 +829,14 @@ private void setLabelTexts() { + ((Double.isNaN(model.getMarkovCheck().getFractionDependent(false)) ? "-" : NumberFormatUtil.getInstance().getNumberFormat().format(model.getMarkovCheck().getFractionDependent(false))))); - masLabelIndep.setText("Markov Adequacy Score = " - + ((Double.isNaN(model.getMarkovCheck().getMarkovAdequacyScore(0.01)) - ? "-" - : NumberFormatUtil.getInstance().getNumberFormat().format(model.getMarkovCheck().getMarkovAdequacyScore(0.01))))); - masLabelDep.setText("Markov Adequacy Score = " - + ((Double.isNaN(model.getMarkovCheck().getMarkovAdequacyScore(0.01)) - ? "-" - : NumberFormatUtil.getInstance().getNumberFormat().format(model.getMarkovCheck().getMarkovAdequacyScore(0.01))))); +// masLabelIndep.setText("Markov Adequacy Score = " +// + ((Double.isNaN(model.getMarkovCheck().getMarkovAdequacyScore(0.01)) +// ? "-" +// : NumberFormatUtil.getInstance().getNumberFormat().format(model.getMarkovCheck().getMarkovAdequacyScore(0.01))))); +// masLabelDep.setText("Markov Adequacy Score = " +// + ((Double.isNaN(model.getMarkovCheck().getMarkovAdequacyScore(0.01)) +// ? "-" +// : NumberFormatUtil.getInstance().getNumberFormat().format(model.getMarkovCheck().getMarkovAdequacyScore(0.01))))); conditioningLabelIndep.setText("Tests graphical predictions of Indep(X, Y | " + conditioningSetTypeJComboBox.getSelectedItem() + ")"); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/MarkovAdequacyScore.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/MarkovAdequacyScore.java deleted file mode 100644 index 5bafefbb19..0000000000 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/MarkovAdequacyScore.java +++ /dev/null @@ -1,46 +0,0 @@ -package edu.cmu.tetrad.algcomparison.statistic; - -import edu.cmu.tetrad.data.DataModel; -import edu.cmu.tetrad.data.DataSet; -import edu.cmu.tetrad.graph.Graph; -import edu.cmu.tetrad.search.ConditioningSetType; -import edu.cmu.tetrad.search.MarkovCheck; -import edu.cmu.tetrad.search.test.IndTestFisherZ; - -/** - * Tests whether the p-values under the null distribution are distributed as Uniform, and if so, returns the proportion - * of judgements of dependence under the Alternative Hypothesis. If the p-values are not distributed as Uniform, zero is - * returned. - * - * @author josephramsey - */ -public class MarkovAdequacyScore implements Statistic { - private static final long serialVersionUID = 23L; - private double alpha = 0.05; - - @Override - public String getAbbreviation() { - return "MAS"; - } - - @Override - public String getDescription() { - return "Markov Adequacy Score (depends only on the estimated DAG and the data)"; - } - - @Override - public double getValue(Graph trueGraph, Graph estGraph, DataModel dataModel) { - MarkovCheck markovCheck = new MarkovCheck(estGraph, new IndTestFisherZ((DataSet) dataModel, 0.01), ConditioningSetType.LOCAL_MARKOV); - markovCheck.generateResults(); - return markovCheck.getMarkovAdequacyScore(alpha); - } - - @Override - public double getNormValue(double value) { - return value; - } - - public void setAlpha(double alpha) { - this.alpha = alpha; - } -} diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java index 3bf4eb542e..57bdfc7a78 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java @@ -33,11 +33,6 @@ * the p-values are tested for Uniformity using the Kolmogorov-Smirnov test; these should be dependent. Also, a fraction * of dependent judgments is returned, which should be maximal./p> * - *

A "Markov adequacy score" is also given, which simply returns zero if the Markov p-value Uniformity test - * fails and the fraction of dependent judgments for the local Faithfulness check otherwise. Maximizing this score picks - * out models for which Markov holds and faithfulness holds to the extend possible; these model should generally have - * good accuracy scores.

- * * @author josephramsey */ public class MarkovCheck { @@ -55,6 +50,7 @@ public class MarkovCheck { private double ksPValueDep = Double.NaN; private double bernoulliPIndep = Double.NaN; private double bernoulliPDep = Double.NaN; + private int numResamples = 1; /** * Constructor. Takes a graph and an independence test over the variables of the graph. @@ -69,6 +65,43 @@ public MarkovCheck(Graph graph, IndependenceTest independenceTest, ConditioningS this.setType = setType; } + @NotNull + public static AllSubsetsIndependenceFacts getAllSubsetsIndependenceFacts(Graph graph) { + List variables = new ArrayList<>(graph.getNodes()); + MsepTest msepTest = new MsepTest(graph); + + List nodes = new ArrayList<>(variables); + Collections.sort(nodes); + + List msep = new ArrayList<>(); + List mconn = new ArrayList<>(); + + for (Node x : nodes) { + List other = new ArrayList<>(variables); + Collections.sort(other); + other.remove(x); + + for (Node y : other) { + List _other = new ArrayList<>(other); + _other.remove(y); + + SublistGenerator generator = new SublistGenerator(_other.size(), _other.size()); + int[] list; + + while ((list = generator.next()) != null) { + Set z = GraphUtils.asSet(list, _other); + + if (msepTest.isMSeparated(x, y, z)) { + msep.add(new IndependenceFact(x, y, z)); + } else { + mconn.add(new IndependenceFact(x, y, z)); + } + } + } + } + return new AllSubsetsIndependenceFacts(msep, mconn); + } + /** * Generates all results, for both the local Markov and local Faithfulness checks, for each node in the graph given * the parents of that node. These results are stored in the resultsIndep and resultsDep lists. @@ -105,7 +138,7 @@ public void generateResults() { for (Node w : new ArrayList<>(z)) { int i1 = order.indexOf(x); int i2 = order.indexOf(w); - + if (i2 >= i1) { z.remove(w); } @@ -145,82 +178,6 @@ public void generateResults() { calcStats(false); } - @NotNull - public static AllSubsetsIndependenceFacts getAllSubsetsIndependenceFacts(Graph graph) { - List variables = new ArrayList<>(graph.getNodes()); - MsepTest msepTest = new MsepTest(graph); - - List nodes = new ArrayList<>(variables); - Collections.sort(nodes); - - List msep = new ArrayList<>(); - List mconn = new ArrayList<>(); - - for (Node x : nodes) { - List other = new ArrayList<>(variables); - Collections.sort(other); - other.remove(x); - - for (Node y : other) { - List _other = new ArrayList<>(other); - _other.remove(y); - - SublistGenerator generator = new SublistGenerator(_other.size(), _other.size()); - int[] list; - - while ((list = generator.next()) != null) { - Set z = GraphUtils.asSet(list, _other); - - if (msepTest.isMSeparated(x, y, z)) { - msep.add(new IndependenceFact(x, y, z)); - } else { - mconn.add(new IndependenceFact(x, y, z)); - } - } - } - } - return new AllSubsetsIndependenceFacts(msep, mconn); - } - - public static class AllSubsetsIndependenceFacts { - private final List msep; - private final List mconn; - - public AllSubsetsIndependenceFacts(List msep, List mconn) { - this.msep = msep; - this.mconn = mconn; - } - - public String toStringIndep() { - StringBuilder builder = new StringBuilder("All subsets independence facts:\n"); - - for (IndependenceFact fact : msep) { - builder.append(fact).append("\n"); - } - - return builder.toString(); - } - - - public String toStringDep() { - StringBuilder builder = new StringBuilder("All subsets independence facts:\n"); - - for (IndependenceFact fact : mconn) { - builder.append(fact).append("\n"); - } - - return builder.toString(); - } - - public List getMsep() { - return msep; - } - - public List getMconn() { - return mconn; - } - } - /** * Returns type of conditioning sets to use in the Markov check. * @@ -317,23 +274,6 @@ public double getBernoulliPValue(boolean indep) { } } - /** - * Returns the Markov Adequacy Score for the graph. This is zero if the p-value of the KS test of Uniformity is less - * than alpha, and the fraction of dependent pairs otherwise. This is only for continuous Gaussian data, as it - * hard-codes the Fisher Z test for the local Markov and Faithfulness check. - * - * @param alpha The alpha level for the KS test of Uniformity. An alpha level greater than this will be considered - * uniform. - * @return The Markov Adequacy Score for this graph given the data. - */ - public double getMarkovAdequacyScore(double alpha) { - if (getKsPValue(true) > alpha) { - return getFractionDependent(false); - } else { - return 0.0; - } - } - /** * Returns the variables of the independence test. * @@ -343,6 +283,23 @@ public List getVariables() { return new ArrayList<>(independenceTest.getVariables()); } +// /** +// * Returns the Markov Adequacy Score for the graph. This is zero if the p-value of the KS test of Uniformity is less +// * than alpha, and the fraction of dependent pairs otherwise. This is only for continuous Gaussian data, as it +// * hard-codes the Fisher Z test for the local Markov and Faithfulness check. +// * +// * @param alpha The alpha level for the KS test of Uniformity. An alpha level greater than this will be considered +// * uniform. +// * @return The Markov Adequacy Score for this graph given the data. +// */ +// public double getMarkovAdequacyScore(double alpha) { +// if (getKsPValue(true) > alpha) { +// return getFractionDependent(false); +// } else { +// return 0.0; +// } +// } + /** * Returns the variable with the given name. * @@ -403,29 +360,29 @@ public List call() { Node y = fact.getY(); Set z = fact.getZ(); - if (independenceTest instanceof RowsSettable) { - for (int t = 0; t < 5; t++) { - List rows = getSubsampleRows(0.8); -// List rows = getBoostrapSample(1.0); - ((RowsSettable) independenceTest).setRows(rows); - - boolean verbose = independenceTest.isVerbose(); - independenceTest.setVerbose(false); - IndependenceResult result; - try { - result = independenceTest.checkIndependence(x, y, z); - } catch (Exception e) { - throw new RuntimeException(e); - } - boolean indep = result.isIndependent(); - double pValue = result.getPValue(); - independenceTest.setVerbose(verbose); - - if (!Double.isNaN(pValue)) { - results.add(new IndependenceResult(fact, indep, pValue, Double.NaN)); - } - } - } else { +// if (independenceTest instanceof RowsSettable) { +// for (int t = 0; t < getNumResamples(); t++) { +// List rows = getSubsampleRows(0.8); +//// List r5ows = getBoostrapSample(1.0); +// ((RowsSettable) independenceTest).setRows(rows); +// +// boolean verbose = independenceTest.isVerbose(); +// independenceTest.setVerbose(false); +// IndependenceResult result; +// try { +// result = independenceTest.checkIndependence(x, y, z); +// } catch (Exception e) { +// throw new RuntimeException(e); +// } +// boolean indep = result.isIndependent(); +// double pValue = result.getPValue(); +// independenceTest.setVerbose(verbose); +// +// if (!Double.isNaN(pValue)) { +// results.add(new IndependenceResult(fact, indep, pValue, Double.NaN)); +// } +// } +// } else { boolean verbose = independenceTest.isVerbose(); independenceTest.setVerbose(false); IndependenceResult result; @@ -441,7 +398,7 @@ public List call() { if (!Double.isNaN(pValue)) { results.add(new IndependenceResult(fact, indep, pValue, Double.NaN)); } - } +// } // boolean verbose = independenceTest.isVerbose(); // independenceTest.setVerbose(false); // IndependenceResult result; @@ -589,7 +546,14 @@ public List call() { } private void calcStats(boolean indep) { - List results = getResultsLocal(indep); + List results = new ArrayList<>(getResultsLocal(indep)); + +// Collections.shuffle(_results); +// +// List results = new ArrayList<>(); +// for (int i = 0; i < _results.size() / getNumResamples(); i++) { +// results.add(_results.get(i)); +// } int dependent = 0; @@ -624,16 +588,28 @@ private void calcStats(boolean indep) { } } + /** + * Returns a Bernoulli p-value for the hypothesis that the distribution of p-values is not Uniform under the null + * hypothesis. Values less than alpha imply non-uniform distributions. + * @param pValues The p-values. + * @param alpha The alpha level. Rejections with p-values less than this are considered dependent. + * @return The Bernoulli p-value for non-uniformity. + */ private double getBernoulliP(List pValues, double alpha) { - int successes = 0; + int dependentJudgments = 0; for (double pValue : pValues) { - if (pValue > alpha) successes++; + if (pValue < alpha) dependentJudgments++; } int n = pValues.size(); - BinomialDistribution bd = new BinomialDistribution(n, 1.0 - alpha); - return (1.0 - bd.cumulativeProbability(successes)); + + // The left tail of this binomial distribution is a p-value for getting too few dependent judgments for + // the distribution to count as uniform. + BinomialDistribution bd = new BinomialDistribution(n, alpha); + + // We want the area to the right of this, so we subtract from 1. + return (1.0 - bd.cumulativeProbability(dependentJudgments)) / 2.0 + (bd.probability(n - dependentJudgments) / 2.0); } private int getChunkSize(int n) { @@ -650,5 +626,52 @@ private List getResultsLocal(boolean indep) { } } + public int getNumResamples() { + return numResamples; + } + + public void setNumResamples(int numResamples) { + this.numResamples = numResamples; + } + + public static class AllSubsetsIndependenceFacts { + private final List msep; + private final List mconn; + + public AllSubsetsIndependenceFacts(List msep, List mconn) { + this.msep = msep; + this.mconn = mconn; + } + + public String toStringIndep() { + StringBuilder builder = new StringBuilder("All subsets independence facts:\n"); + + for (IndependenceFact fact : msep) { + builder.append(fact).append("\n"); + } + + return builder.toString(); + } + + + public String toStringDep() { + StringBuilder builder = new StringBuilder("All subsets independence facts:\n"); + + for (IndependenceFact fact : mconn) { + builder.append(fact).append("\n"); + } + + return builder.toString(); + } + + public List getMsep() { + return msep; + } + + public List getMconn() { + return mconn; + } + } + } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java index 78559f28aa..b440f0d35b 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java @@ -49,7 +49,7 @@ * @author josephramsey * @author Frank Wimberly */ -public final class IndTestFisherZ implements IndependenceTest { +public final class IndTestFisherZ implements IndependenceTest, RowsSettable { private final Map indexMap; private final Map nameMap; private final NormalDistribution normal = new NormalDistribution(0, 1, 1e-15); @@ -73,7 +73,7 @@ public final class IndTestFisherZ implements IndependenceTest { * @param alpha The alpha level of the test. */ public IndTestFisherZ(DataSet dataSet, double alpha) { - this.dataSet = dataSet; + this.dataSet = dataSet.copy(); if (!(dataSet.isContinuous())) { throw new IllegalArgumentException("Data set must be continuous."); @@ -544,12 +544,12 @@ public void setRows(List rows) { } } + this.rows = rows; this.cor = null; } else { this.cor = new CorrelationMatrix(dataSet); + this.rows = null; } - - this.rows = rows; } } From a8bba556f6f04fc8bdb45c6bf0b2e85bd3750a71 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Tue, 28 Nov 2023 06:58:31 -0500 Subject: [PATCH 008/163] Committing a few updates to Markov Check. --- .../edu/cmu/tetrad/search/MarkovCheck.java | 78 +++++++++---------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java index 57bdfc7a78..80c94e0acf 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java @@ -360,29 +360,29 @@ public List call() { Node y = fact.getY(); Set z = fact.getZ(); -// if (independenceTest instanceof RowsSettable) { -// for (int t = 0; t < getNumResamples(); t++) { -// List rows = getSubsampleRows(0.8); -//// List r5ows = getBoostrapSample(1.0); -// ((RowsSettable) independenceTest).setRows(rows); -// -// boolean verbose = independenceTest.isVerbose(); -// independenceTest.setVerbose(false); -// IndependenceResult result; -// try { -// result = independenceTest.checkIndependence(x, y, z); -// } catch (Exception e) { -// throw new RuntimeException(e); -// } -// boolean indep = result.isIndependent(); -// double pValue = result.getPValue(); -// independenceTest.setVerbose(verbose); -// -// if (!Double.isNaN(pValue)) { -// results.add(new IndependenceResult(fact, indep, pValue, Double.NaN)); -// } -// } -// } else { + if (indep && independenceTest instanceof RowsSettable) { + for (int t = 0; t < getNumResamples(); t++) { + List rows = getSubsampleRows(0.5); +// List r5ows = getBoostrapSample(1.0); + ((RowsSettable) independenceTest).setRows(rows); + + boolean verbose = independenceTest.isVerbose(); + independenceTest.setVerbose(false); + IndependenceResult result; + try { + result = independenceTest.checkIndependence(x, y, z); + } catch (Exception e) { + throw new RuntimeException(e); + } + boolean indep = result.isIndependent(); + double pValue = result.getPValue(); + independenceTest.setVerbose(verbose); + + if (!Double.isNaN(pValue)) { + results.add(new IndependenceResult(fact, indep, pValue, Double.NaN)); + } + } + } else { boolean verbose = independenceTest.isVerbose(); independenceTest.setVerbose(false); IndependenceResult result; @@ -398,22 +398,22 @@ public List call() { if (!Double.isNaN(pValue)) { results.add(new IndependenceResult(fact, indep, pValue, Double.NaN)); } -// } -// boolean verbose = independenceTest.isVerbose(); -// independenceTest.setVerbose(false); -// IndependenceResult result; -// try { -// result = independenceTest.checkIndependence(x, y, z); -// } catch (Exception e) { -// throw new RuntimeException(e); -// } -// boolean indep = result.isIndependent(); -// double pValue = result.getPValue(); -// independenceTest.setVerbose(verbose); -// -// if (!Double.isNaN(pValue)) { -// results.add(new IndependenceResult(fact, indep, pValue, Double.NaN)); -// } + } + boolean verbose = independenceTest.isVerbose(); + independenceTest.setVerbose(false); + IndependenceResult result; + try { + result = independenceTest.checkIndependence(x, y, z); + } catch (Exception e) { + throw new RuntimeException(e); + } + boolean indep = result.isIndependent(); + double pValue = result.getPValue(); + independenceTest.setVerbose(verbose); + + if (!Double.isNaN(pValue)) { + results.add(new IndependenceResult(fact, indep, pValue, Double.NaN)); + } } return results; From f62e80bd5e69d3117080139b74346992b0d079cf Mon Sep 17 00:00:00 2001 From: jdramsey Date: Sat, 2 Dec 2023 10:12:03 -0500 Subject: [PATCH 009/163] Fixed the bounds issue for the UniformityTest. --- pom.xml | 2 +- .../tetradapp/editor/MarkovCheckEditor.java | 48 +++- .../cmu/tetradapp/util/WatchedProcess.java | 1 + .../edu/cmu/tetrad/search/MarkovCheck.java | 242 +++++++++--------- .../tetrad/search/utils/LogUtilsSearch.java | 7 +- 5 files changed, 160 insertions(+), 140 deletions(-) diff --git a/pom.xml b/pom.xml index 6e02a473f9..459e93e964 100644 --- a/pom.xml +++ b/pom.xml @@ -116,7 +116,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 2.9.1 + 3.6.2 /usr/bin/javadoc diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java index 7989c360dc..1680b784cb 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java @@ -48,6 +48,8 @@ import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.JTableHeader; import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.lang.reflect.InvocationTargetException; @@ -232,8 +234,23 @@ public void watch() { box1.add(indTestJComboBox); JButton params = new JButton("Params"); box1.add(params); + JButton refresh = new JButton("Refresh"); + box1.add(refresh); + DoubleTextField percent = new DoubleTextField(0.5, 4, new DecimalFormat("0.0")); + box1.add(new JLabel("% Sample:")); + box1.add(percent); box1.add(Box.createHorizontalGlue()); + refresh.addActionListener(e -> refreshResult(model, percent)); + + percent.setFilter((value, oldValue) -> { + if (value < 0.0 || value > 1.0) { + return oldValue; + } else { + return value; + } + }); + setLabelTexts(); params.addActionListener(e -> { @@ -244,19 +261,7 @@ class MyWatchedProcess2 extends WatchedProcess { @Override public void watch() { - setTest(); - model.getMarkovCheck().generateResults(); - tableModelIndep.fireTableDataChanged(); - tableModelDep.fireTableDataChanged(); - histogramPanelDep.removeAll(); - histogramPanelIndep.removeAll(); - histogramPanelDep.add(createHistogramPanel(false), BorderLayout.CENTER); - histogramPanelIndep.add(createHistogramPanel(true), BorderLayout.CENTER); - histogramPanelDep.validate(); - histogramPanelIndep.validate(); - histogramPanelDep.repaint(); - histogramPanelIndep.repaint(); - setLabelTexts(); + refreshResult(model, percent); } } @@ -314,6 +319,23 @@ public void watch() { add(box); } + private void refreshResult(MarkovCheckIndTestModel model, DoubleTextField percent) { + setTest(); + model.getMarkovCheck().setPercentResammple(percent.getValue()); + model.getMarkovCheck().generateResults(); + tableModelIndep.fireTableDataChanged(); + tableModelDep.fireTableDataChanged(); + histogramPanelDep.removeAll(); + histogramPanelIndep.removeAll(); + histogramPanelDep.add(createHistogramPanel(false), BorderLayout.CENTER); + histogramPanelIndep.add(createHistogramPanel(true), BorderLayout.CENTER); + histogramPanelDep.validate(); + histogramPanelIndep.validate(); + histogramPanelDep.repaint(); + histogramPanelIndep.repaint(); + setLabelTexts(); + } + @NotNull private static String getHelpMessage() { return "This tool lets you plot statistics for independence tests of a pair of variables given some conditioning calculated for one of those variables, for a given graph and dataset. Two tables are made, one in which the independence facts predicted by the graph using these conditioning sets are tested in the data and the other in which the graph's predicted dependence facts are tested. The first of these sets is a check for \"Markov\" (a check for implied independence facts) for the chosen conditioning sets; the is a check of the \"Dependent Distribution.\" (a check of implied dependence facts)”\n" + diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java index 97f6db77a7..72725b82e6 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java @@ -61,6 +61,7 @@ private void startLongRunningThread() { try { watch(); } catch (InterruptedException e) { + e.printStackTrace(); // Thread was interrupted while sleeping, so exit the loop and terminate System.out.println("Thread was interrupted while watching. Stopping..."); return; diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java index 80c94e0acf..204fc82252 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java @@ -12,6 +12,7 @@ import edu.cmu.tetrad.util.UniformityTest; import org.apache.commons.math3.distribution.BinomialDistribution; import org.apache.commons.math3.util.FastMath; +import org.apache.commons.math3.util.Pair; import org.jetbrains.annotations.NotNull; import java.util.*; @@ -51,6 +52,7 @@ public class MarkovCheck { private double bernoulliPIndep = Double.NaN; private double bernoulliPDep = Double.NaN; private int numResamples = 1; + private double percentResammple = 0.5; /** * Constructor. Takes a graph and an independence test over the variables of the graph. @@ -73,8 +75,8 @@ public static AllSubsetsIndependenceFacts getAllSubsetsIndependenceFacts(Graph g List nodes = new ArrayList<>(variables); Collections.sort(nodes); - List msep = new ArrayList<>(); - List mconn = new ArrayList<>(); + Set msep = new HashSet<>(); + Set mconn = new HashSet<>(); for (Node x : nodes) { List other = new ArrayList<>(variables); @@ -99,6 +101,7 @@ public static AllSubsetsIndependenceFacts getAllSubsetsIndependenceFacts(Graph g } } } + return new AllSubsetsIndependenceFacts(msep, mconn); } @@ -121,57 +124,71 @@ public void generateResults() { List nodes = new ArrayList<>(variables); Collections.sort(nodes); - List order = graph.paths().getValidOrder(graph.getNodes(), true); + List order = null; - for (Node x : nodes) { - Set z; + if (!graph.paths().existsDirectedCycle()) { + order = graph.paths().getValidOrder(graph.getNodes(), true); + } - switch (setType) { - case LOCAL_MARKOV: - z = new HashSet<>(graph.getParents(x)); - break; - case ORDERED_LOCAL_MARKOV: - if (order == null) throw new IllegalArgumentException("No valid order found."); - z = new HashSet<>(graph.getParents(x)); + Set msep = new HashSet<>(); + Set mconn = new HashSet<>(); - // Keep only the parents in Prefix(x). - for (Node w : new ArrayList<>(z)) { - int i1 = order.indexOf(x); - int i2 = order.indexOf(w); + for (int i = 0; i < nodes.size(); i++) { + for (int j = i + 1; j < nodes.size(); j++) { + Node x = nodes.get(i); + Node y = nodes.get(j); - if (i2 >= i1) { - z.remove(w); - } - } + if (graph.isAdjacentTo(x, y)) continue; - break; - case MARKOV_BLANKET: - z = GraphUtils.markovBlanket(x, graph); - break; - default: - throw new IllegalArgumentException("Unknown separation set type: " + setType); - } + Set z; - Set msep = new HashSet<>(); - Set mconn = new HashSet<>(); + switch (setType) { + case LOCAL_MARKOV: + z = new HashSet<>(graph.getParents(x)); + break; + case ORDERED_LOCAL_MARKOV: + if (order == null) throw new IllegalArgumentException("No valid order found."); + z = new HashSet<>(graph.getParents(x)); - List other = new ArrayList<>(graph.getNodes()); - Collections.sort(other); - other.removeAll(z); + // Keep only the parents in Prefix(x). + for (Node w : new ArrayList<>(z)) { + int i1 = order.indexOf(x); + int i2 = order.indexOf(w); - for (Node y : other) { - if (y == x) continue; - if (z.contains(x) || z.contains(y)) continue; - if (this.msep.isMSeparated(x, y, z)) { - msep.add(y); - } else { - mconn.add(y); + if (i2 >= i1) { + z.remove(w); + } + } + + break; + case MARKOV_BLANKET: + z = GraphUtils.markovBlanket(x, graph); + break; + default: + throw new IllegalArgumentException("Unknown separation set type: " + setType); } - } - generateResults(true, x, z, msep, mconn); - generateResults(false, x, z, msep, mconn); + List other = new ArrayList<>(graph.getNodes()); + Collections.sort(other); + other.removeAll(z); + + for (Node w : other) { + if (w == x || w == y) continue; + if (z.contains(x) || z.contains(y) || z.contains(w)) continue; + if (this.msep.isMSeparated(x, y, z)) { + if (!msep.contains(new IndependenceFact(y, x, z))) { + msep.add(new IndependenceFact(x, y, z)); + } + } else { + if (!mconn.contains(new IndependenceFact(y, x, z))) { + mconn.add(new IndependenceFact(x, y, z)); + } + } + } + } } + + generateResults(msep, mconn); } calcStats(true); @@ -319,23 +336,8 @@ public IndependenceTest getIndependenceTest() { return this.independenceTest; } - private void generateResults(boolean indep, Node x, Set z, Set msep, Set mconn) { - List facts = new ArrayList<>(); - - // Listing all facts before checking any (in preparation for parallelization). - if (indep) { - for (Node y : msep) { - if (z.contains(y)) continue; - facts.add(new IndependenceFact(x, y, z)); - } - } else { - for (Node y : mconn) { - if (z.contains(y)) continue; - facts.add(new IndependenceFact(x, y, z)); - } - } - - class IndCheckTask implements Callable> { + private void generateResults(Set msep, Set mconn) { + class IndCheckTask implements Callable, Set>> { private final int from; private final int to; private final List facts; @@ -349,8 +351,9 @@ class IndCheckTask implements Callable> { } @Override - public List call() { - List results = new ArrayList<>(); + public Pair, Set> call() { + Set resultsIndep = new HashSet<>(); + Set resultsDep = new HashSet<>(); for (int i = from; i < to; i++) { if (Thread.interrupted()) break; @@ -360,10 +363,9 @@ public List call() { Node y = fact.getY(); Set z = fact.getZ(); - if (indep && independenceTest instanceof RowsSettable) { - for (int t = 0; t < getNumResamples(); t++) { - List rows = getSubsampleRows(0.5); -// List r5ows = getBoostrapSample(1.0); + if (independenceTest instanceof RowsSettable) { +// for (int t = 0; t < getNumResamples(); t++) { + List rows = getSubsampleRows(percentResammple); ((RowsSettable) independenceTest).setRows(rows); boolean verbose = independenceTest.isVerbose(); @@ -379,9 +381,15 @@ public List call() { independenceTest.setVerbose(verbose); if (!Double.isNaN(pValue)) { - results.add(new IndependenceResult(fact, indep, pValue, Double.NaN)); + if (msep.contains(new IndependenceFact(x, y, z))) { + resultsIndep.add(new IndependenceResult(fact, indep, pValue, Double.NaN)); + } else if (mconn.contains(new IndependenceFact(x, y, z))) { + resultsDep.add(new IndependenceResult(fact, indep, pValue, Double.NaN)); + } else { + throw new IllegalArgumentException("Unknown separation set: " + z); + } } - } +// } } else { boolean verbose = independenceTest.isVerbose(); independenceTest.setVerbose(false); @@ -396,31 +404,28 @@ public List call() { independenceTest.setVerbose(verbose); if (!Double.isNaN(pValue)) { - results.add(new IndependenceResult(fact, indep, pValue, Double.NaN)); + if (msep.contains(new IndependenceFact(x, y, z))) { + resultsIndep.add(new IndependenceResult(fact, indep, pValue, Double.NaN)); + } else if (mconn.contains(new IndependenceFact(x, y, z))) { + resultsDep.add(new IndependenceResult(fact, indep, pValue, Double.NaN)); + } else { + throw new IllegalArgumentException("Unknown separation set: " + z); + } } } - boolean verbose = independenceTest.isVerbose(); - independenceTest.setVerbose(false); - IndependenceResult result; - try { - result = independenceTest.checkIndependence(x, y, z); - } catch (Exception e) { - throw new RuntimeException(e); - } - boolean indep = result.isIndependent(); - double pValue = result.getPValue(); - independenceTest.setVerbose(verbose); - - if (!Double.isNaN(pValue)) { - results.add(new IndependenceResult(fact, indep, pValue, Double.NaN)); - } } - return results; + return new Pair<>(resultsIndep, resultsDep); } } - List>> tasks = new ArrayList<>(); + List, Set>>> tasks = new ArrayList<>(); + + Set _facts = new HashSet<>(); + _facts.addAll(msep); + _facts.addAll(mconn); + + List facts = new ArrayList<>(_facts); int chunkSize = getChunkSize(facts.size()); @@ -428,19 +433,21 @@ public List call() { IndCheckTask task = new IndCheckTask(i, min(facts.size(), i + chunkSize), facts, independenceTest); if (!parallelized) { - List _results = task.call(); - getResultsLocal(indep).addAll(_results); + Pair, Set> _results = task.call(); + resultsIndep.addAll(_results.getFirst()); + resultsDep.addAll(_results.getSecond()); } else { tasks.add(task); } } if (parallelized) { - List>> theseResults = ForkJoinPool.commonPool().invokeAll(tasks); + List, Set>>> theseResults = ForkJoinPool.commonPool().invokeAll(tasks); - for (Future> future : theseResults) { + for (Future, Set>> future : theseResults) { try { - getResultsLocal(indep).addAll(future.get()); + resultsIndep.addAll(future.get().getFirst()); + resultsDep.addAll(future.get().getSecond()); } catch (InterruptedException | ExecutionException e) { throw new RuntimeException(e); } @@ -469,8 +476,8 @@ private List getBoostrapSample(double v) { return rows; } - private void generateResultsAllSubsets(boolean indep, List msep, List mconn) { - List facts = indep ? msep : mconn; + private void generateResultsAllSubsets(boolean indep, Set msep, Set mconn) { + Set facts = indep ? msep : mconn; class IndCheckTask implements Callable> { private final int from; @@ -517,32 +524,7 @@ public List call() { } } - List>> tasks = new ArrayList<>(); - - int chunkSize = getChunkSize(facts.size()); - - for (int i = 0; i < facts.size() && !Thread.currentThread().isInterrupted(); i += chunkSize) { - IndCheckTask task = new IndCheckTask(i, min(facts.size(), i + chunkSize), facts, independenceTest); - - if (!parallelized) { - List _results = task.call(); - getResultsLocal(indep).addAll(_results); - } else { - tasks.add(task); - } - } - - if (parallelized) { - List>> theseResults = ForkJoinPool.commonPool().invokeAll(tasks); - - for (Future> future : theseResults) { - try { - getResultsLocal(indep).addAll(future.get()); - } catch (InterruptedException | ExecutionException e) { - throw new RuntimeException(e); - } - } - } + generateResults(msep, mconn); } private void calcStats(boolean indep) { @@ -634,11 +616,19 @@ public void setNumResamples(int numResamples) { this.numResamples = numResamples; } + public double getPercentResammple() { + return percentResammple; + } + + public void setPercentResammple(double percentResammple) { + this.percentResammple = percentResammple; + } + public static class AllSubsetsIndependenceFacts { - private final List msep; - private final List mconn; + private final Set msep; + private final Set mconn; - public AllSubsetsIndependenceFacts(List msep, List mconn) { + public AllSubsetsIndependenceFacts(Set msep, Set mconn) { this.msep = msep; this.mconn = mconn; } @@ -665,13 +655,15 @@ public String toStringDep() { } public List getMsep() { - return msep; + List facts = new ArrayList<>(msep); + Collections.sort(facts); + return facts; } public List getMconn() { - return mconn; + List facts = new ArrayList<>(mconn); + Collections.sort(facts); + return facts; } } - - } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/LogUtilsSearch.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/LogUtilsSearch.java index 3bbd503f04..484cd1bc91 100755 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/LogUtilsSearch.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/LogUtilsSearch.java @@ -185,7 +185,12 @@ public static void stampWithScores(Graph graph, DataModel dataModel, Score score public static void stampWithBic(Graph graph, DataModel dataModel) { if (!graph.getAllAttributes().containsKey("BIC")) { - graph.addAttribute("BIC", new BicEst().getValue(null, graph, dataModel)); + try { + graph.addAttribute("BIC", new BicEst().getValue(null, graph, dataModel)); + } catch (Exception e) { + e.printStackTrace(); +// throw new RuntimeException(e); + } } } } From 4656be5097395e467cd6ea78254b185e4f61b780 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Wed, 6 Dec 2023 09:18:52 -0500 Subject: [PATCH 010/163] Switching to Anderson-Darling test for Markov Checker. --- .../tetradapp/editor/MarkovCheckEditor.java | 66 +++++++++++++++-- .../data/GeneralAndersonDarlingTest.java | 71 +++++++++++++++++-- .../edu/cmu/tetrad/search/MarkovCheck.java | 48 +++++++++++-- 3 files changed, 169 insertions(+), 16 deletions(-) diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java index 1680b784cb..0507eeeb50 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java @@ -48,8 +48,6 @@ import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.JTableHeader; import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.lang.reflect.InvocationTargetException; @@ -89,6 +87,10 @@ public class MarkovCheckEditor extends JPanel { // private JLabel masLabelIndep; private JLabel bernoulliPLabelDep; private JLabel bernoulliPLabelIndep; + private JLabel andersonDarlingA2LabelDep; + private JLabel andersonDarlingA2LabelIndep; + private JLabel andersonDarlingPLabelDep; + private JLabel andersonDarlingPLabelIndep; private int sortDir; private int lastSortCol; private IndependenceWrapper independenceWrapper; @@ -437,7 +439,7 @@ public Object getValueAt(int rowIndex, int columnIndex) { IndependenceFact fact = model.getResults(false).get(rowIndex).getFact(); List Z = new ArrayList<>(fact.getZ()); - Collections.sort(Z); +// Collections.sort(Z); String z = Z.stream().map(Node::getName).collect(Collectors.joining(", ")); @@ -562,6 +564,16 @@ public void mouseClicked(MouseEvent e) { b6a.add(bernoulliPLabelDep); b0b1.add(b6a); + Box b6b = Box.createHorizontalBox(); + b6b.add(Box.createHorizontalGlue()); + b6b.add(andersonDarlingA2LabelDep); + b0b1.add(b6b); + + Box b6c = Box.createHorizontalBox(); + b6c.add(Box.createHorizontalGlue()); + b6c.add(andersonDarlingPLabelDep); + b0b1.add(b6c); + // Box b7 = Box.createHorizontalBox(); // b7.add(Box.createHorizontalGlue()); // b7.add(masLabelDep); @@ -636,7 +648,7 @@ public Object getValueAt(int rowIndex, int columnIndex) { IndependenceFact fact = model.getResults(true).get(rowIndex).getFact(); List Z = new ArrayList<>(fact.getZ()); - Collections.sort(Z); +// Collections.sort(Z); String z = Z.stream().map(Node::getName).collect(Collectors.joining(", ")); @@ -760,6 +772,16 @@ public void mouseClicked(MouseEvent e) { b6a.add(bernoulliPLabelIndep); b0b1.add(b6a); + Box b6b = Box.createHorizontalBox(); + b6b.add(Box.createHorizontalGlue()); + b6b.add(andersonDarlingA2LabelIndep); + b0b1.add(b6b); + + Box b6c = Box.createHorizontalBox(); + b6c.add(Box.createHorizontalGlue()); + b6c.add(andersonDarlingPLabelIndep); + b0b1.add(b6c); + // Box b7 = Box.createHorizontalBox(); // b7.add(Box.createHorizontalGlue()); // b7.add(masLabelIndep); @@ -810,6 +832,22 @@ private void setLabelTexts() { bernoulliPLabelDep = new JLabel(); } + if (andersonDarlingA2LabelIndep == null) { + andersonDarlingA2LabelIndep = new JLabel(); + } + + if (andersonDarlingA2LabelDep == null) { + andersonDarlingA2LabelDep = new JLabel(); + } + + if (andersonDarlingPLabelIndep == null) { + andersonDarlingPLabelIndep = new JLabel(); + } + + if (andersonDarlingPLabelDep == null) { + andersonDarlingPLabelDep = new JLabel(); + } + if (fractionDepLabelIndep == null) { fractionDepLabelIndep = new JLabel(); } @@ -835,6 +873,26 @@ private void setLabelTexts() { ? "-" : NumberFormatUtil.getInstance().getNumberFormat().format(model.getMarkovCheck().getKsPValue(false))))); + andersonDarlingA2LabelIndep.setText("A^2 = " + + ((Double.isNaN(model.getMarkovCheck().getAndersonDarlingA2Star(true)) + ? "-" + : NumberFormatUtil.getInstance().getNumberFormat().format(model.getMarkovCheck().getAndersonDarlingA2Star(true))))); + andersonDarlingA2LabelDep.setText("A^2* = " + + ((Double.isNaN(model.getMarkovCheck().getAndersonDarlingA2Star(false)) + ? "-" + : NumberFormatUtil.getInstance().getNumberFormat().format(model.getMarkovCheck().getAndersonDarlingA2Star(false))))); + + andersonDarlingPLabelIndep.setText("P-value of the Anderson-Darling test = " + + ((Double.isNaN(model.getMarkovCheck().getAndersonDarlingP(true)) + ? "-" + : NumberFormatUtil.getInstance().getNumberFormat().format(model.getMarkovCheck().getAndersonDarlingP(true))))); + andersonDarlingPLabelDep.setText("P-value of the Anderson-Darling test = " + + ((Double.isNaN(model.getMarkovCheck().getAndersonDarlingP(false)) + ? "-" + : NumberFormatUtil.getInstance().getNumberFormat().format(model.getMarkovCheck().getAndersonDarlingP(false))))); + + + bernoulliPLabelIndep.setText("P-value of Bernoulli Test = " + ((Double.isNaN(model.getMarkovCheck().getBernoulliPValue(true)) ? "-" diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/data/GeneralAndersonDarlingTest.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/data/GeneralAndersonDarlingTest.java index a380fc86e4..76b101fa10 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/data/GeneralAndersonDarlingTest.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/data/GeneralAndersonDarlingTest.java @@ -21,12 +21,17 @@ package edu.cmu.tetrad.data; +import edu.cmu.tetrad.util.RandomUtil; import org.apache.commons.math3.distribution.RealDistribution; +import org.apache.commons.math3.distribution.UniformRealDistribution; import org.apache.commons.math3.util.FastMath; +import java.util.ArrayList; import java.util.Collections; import java.util.List; +import static org.apache.commons.math3.util.FastMath.*; + /** * Implements the Anderson-Darling test against the given CDF, with P values calculated as in R's ad.test method (in * package nortest). @@ -118,23 +123,79 @@ private void runTest() { } double a = -n - (1.0 / numSummed) * h; - double aa = (1 + 0.75 / numSummed + 2.25 / FastMath.pow(numSummed, 2)) * a; + double aa = (1 + 0.75 / numSummed + 2.25 / pow(numSummed, 2)) * a; double p; if (aa < 0.2) { - p = 1 - FastMath.exp(-13.436 + 101.14 * aa - 223.73 * aa * aa); + p = 1 - exp(-13.436 + 101.14 * aa - 223.73 * aa * aa); } else if (aa < 0.34) { - p = 1 - FastMath.exp(-8.318 + 42.796 * aa - 59.938 * aa * aa); + p = 1 - exp(-8.318 + 42.796 * aa - 59.938 * aa * aa); } else if (aa < 0.6) { - p = FastMath.exp(0.9177 - 4.279 * aa - 1.38 * aa * aa); + p = exp(0.9177 - 4.279 * aa - 1.38 * aa * aa); } else { - p = FastMath.exp(1.2937 - 5.709 * aa + 0.0186 * aa * aa); + p = exp(1.2937 - 5.709 * aa + 0.0186 * aa * aa); } this.aSquared = a; this.aSquaredStar = aa; this.p = p; } + + private double c(double n) { + return .01265 + .1757 / n; + } + + private double g1(double x) { + return sqrt(x) * (1 - x) * (49 * x - 102); + } + + private double g2(double x) { + return -.00022633 + (6.54034 - (14.6538 - (14.458 - (8.259 - 1.91864 * x) * x) * x) * x) * x; + } + + private double g3(double x) { + return -130.2137 + (745.2337 - (1705.091 - (1950.646 - (1116.360 - 255.7844 * x) * x) * x) * x) * x; + } + + private double errfix(double n, double x) { + if (x < c(n)) { + return (.0037 / pow(n, 3) + .00078 / pow(n, 2) + .00006 / n) * g1(x / c(n)); + } else if (x < .8) { + return (.04213 / n + .01365 / pow(n , 2)) * g2((x - c(n)) / (.8 - c(n))); + } else { + return g3(x) / n; + } + } + + private double adinf(double z) { + if (0 < z && z < 2) { + return pow(z, -0.5) * exp(-1.2337141 / z) * (2.00012 + (0.247105 - (.0649821 - (.0347962 - (.0116720 - .00168691 * z) * z) * z) * z) * z); + } else if (z >= 2) { + return exp( -exp(1.0776 - (2.30695 - (.43424 - (.082433 - (.008056 - .0003146 * z) * z) * z) * z) * z)); + } else { + return 0; + } + } + + public double getProbTail(double n, double z) { + return adinf(z) + errfix(n, adinf(z)); + } + + public static void main(String[] args) { + List data = new ArrayList<>(); + + for (int i = 0; i < 500; i++) { +// data.add(RandomUtil.getInstance().nextUniform(0, 1)); + data.add(RandomUtil.getInstance().nextBeta(2, 5)); + } + + GeneralAndersonDarlingTest test = new GeneralAndersonDarlingTest(data, new UniformRealDistribution(0, 1)); + + System.out.println(test.getASquared()); + System.out.println(test.getASquaredStar()); + System.out.println(test.getP()); + System.out.println(test.getProbTail(data.size(), test.getASquaredStar())); + } } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java index 204fc82252..b4fde7f515 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java @@ -1,5 +1,6 @@ package edu.cmu.tetrad.search; +import edu.cmu.tetrad.data.GeneralAndersonDarlingTest; import edu.cmu.tetrad.graph.Graph; import edu.cmu.tetrad.graph.GraphUtils; import edu.cmu.tetrad.graph.IndependenceFact; @@ -11,6 +12,7 @@ import edu.cmu.tetrad.util.SublistGenerator; import edu.cmu.tetrad.util.UniformityTest; import org.apache.commons.math3.distribution.BinomialDistribution; +import org.apache.commons.math3.distribution.UniformRealDistribution; import org.apache.commons.math3.util.FastMath; import org.apache.commons.math3.util.Pair; import org.jetbrains.annotations.NotNull; @@ -49,6 +51,10 @@ public class MarkovCheck { private double fractionDependentDep = Double.NaN; private double ksPValueIndep = Double.NaN; private double ksPValueDep = Double.NaN; + private double aSquaredStarIndep = Double.NaN; + private double aSquaredStarDep = Double.NaN; + private double andersonDarlingPIndep = Double.NaN; + private double andersonDarlingPDep = Double.NaN; private double bernoulliPIndep = Double.NaN; private double bernoulliPDep = Double.NaN; private int numResamples = 1; @@ -73,14 +79,14 @@ public static AllSubsetsIndependenceFacts getAllSubsetsIndependenceFacts(Graph g MsepTest msepTest = new MsepTest(graph); List nodes = new ArrayList<>(variables); - Collections.sort(nodes); +// Collections.sort(nodes); Set msep = new HashSet<>(); Set mconn = new HashSet<>(); for (Node x : nodes) { List other = new ArrayList<>(variables); - Collections.sort(other); +// Collections.sort(other); other.remove(x); for (Node y : other) { @@ -122,12 +128,14 @@ public void generateResults() { } else { List variables = independenceTest.getVariables(); List nodes = new ArrayList<>(variables); - Collections.sort(nodes); +// Collections.sort(nodes); List order = null; - if (!graph.paths().existsDirectedCycle()) { + try { order = graph.paths().getValidOrder(graph.getNodes(), true); + } catch (Exception e) { + e.printStackTrace(); } Set msep = new HashSet<>(); @@ -169,7 +177,7 @@ public void generateResults() { } List other = new ArrayList<>(graph.getNodes()); - Collections.sort(other); +// Collections.sort(other); other.removeAll(z); for (Node w : other) { @@ -283,6 +291,22 @@ public double getKsPValue(boolean indep) { } } + public double getAndersonDarlingA2Star(boolean indep) { + if (indep) { + return aSquaredStarIndep; + } else { + return aSquaredStarDep; + } + } + + public double getAndersonDarlingP(boolean indep) { + if (indep) { + return andersonDarlingPIndep; + } else { + return andersonDarlingPDep; + } + } + public double getBernoulliPValue(boolean indep) { if (indep) { return bernoulliPIndep; @@ -550,22 +574,32 @@ private void calcStats(boolean indep) { } List pValues = getPValues(results); + double aSquaredStar = new GeneralAndersonDarlingTest(pValues, new UniformRealDistribution(0, 1)).getASquaredStar(); if (indep) { if (pValues.size() < 2) { ksPValueIndep = Double.NaN; bernoulliPIndep = Double.NaN; + aSquaredStarIndep = Double.NaN; + andersonDarlingPIndep = Double.NaN; } else { ksPValueIndep = UniformityTest.getPValue(pValues, 0.0, 1.0); bernoulliPIndep = getBernoulliP(pValues, independenceTest.getAlpha()); + aSquaredStarIndep = aSquaredStar; + andersonDarlingPIndep = 1. - new GeneralAndersonDarlingTest(pValues, new UniformRealDistribution(0, 1)).getProbTail(pValues.size(), aSquaredStar); } } else { if (pValues.size() < 2) { ksPValueDep = Double.NaN; bernoulliPDep = Double.NaN; + aSquaredStarDep = Double.NaN; + andersonDarlingPDep = Double.NaN; + } else { ksPValueDep = UniformityTest.getPValue(pValues, 0.0, 1.0); bernoulliPDep = getBernoulliP(pValues, independenceTest.getAlpha()); + aSquaredStarDep = aSquaredStar; + andersonDarlingPDep = 1. - new GeneralAndersonDarlingTest(pValues, new UniformRealDistribution(0, 1)).getProbTail(pValues.size(), aSquaredStar); } } } @@ -656,13 +690,13 @@ public String toStringDep() { public List getMsep() { List facts = new ArrayList<>(msep); - Collections.sort(facts); +// Collections.sort(facts); return facts; } public List getMconn() { List facts = new ArrayList<>(mconn); - Collections.sort(facts); +// Collections.sort(facts); return facts; } } From d1acbb207fe3128c4c4d78b22071d21c40c9c7db Mon Sep 17 00:00:00 2001 From: jdramsey Date: Wed, 6 Dec 2023 09:19:06 -0500 Subject: [PATCH 011/163] Switching to Anderson-Darling test for Markov Checker. --- .../main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java index 0507eeeb50..723b221ecc 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java @@ -890,9 +890,6 @@ private void setLabelTexts() { + ((Double.isNaN(model.getMarkovCheck().getAndersonDarlingP(false)) ? "-" : NumberFormatUtil.getInstance().getNumberFormat().format(model.getMarkovCheck().getAndersonDarlingP(false))))); - - - bernoulliPLabelIndep.setText("P-value of Bernoulli Test = " + ((Double.isNaN(model.getMarkovCheck().getBernoulliPValue(true)) ? "-" From c519c8368c271eb9fe3f7fc172800b99e6276913 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Thu, 7 Dec 2023 00:49:43 -0500 Subject: [PATCH 012/163] Switching to Anderson-Darling test for Markov Checker. --- .../algorithm/oracle/cpdag/Grasp.java | 7 +- .../edu/cmu/tetrad/graph/EdgeListGraph.java | 45 +- .../main/java/edu/cmu/tetrad/graph/Paths.java | 4 + .../edu/cmu/tetrad/search/MarkovCheck.java | 390 ++++++++++-------- .../cmu/tetrad/search/score/SemBicScorer.java | 2 +- .../edu/cmu/tetrad/search/test/MsepTest.java | 2 +- .../java/edu/cmu/tetrad/test/TestFges.java | 2 +- 7 files changed, 254 insertions(+), 198 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/Grasp.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/Grasp.java index 287699409d..f81ea69ba8 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/Grasp.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/Grasp.java @@ -16,6 +16,7 @@ import edu.cmu.tetrad.graph.EdgeListGraph; import edu.cmu.tetrad.graph.Graph; import edu.cmu.tetrad.search.IndependenceTest; +import edu.cmu.tetrad.search.score.GraphScore; import edu.cmu.tetrad.search.score.Score; import edu.cmu.tetrad.search.utils.LogUtilsSearch; import edu.cmu.tetrad.search.utils.TsUtils; @@ -89,7 +90,11 @@ public Graph search(DataModel dataModel, Parameters parameters) { grasp.setKnowledge(this.knowledge); grasp.bestOrder(score.getVariables()); Graph graph = grasp.getGraph(parameters.getBoolean(Params.OUTPUT_CPDAG)); - LogUtilsSearch.stampWithScores(graph, dataModel, score); + + if (!(score instanceof GraphScore)) { + LogUtilsSearch.stampWithScores(graph, dataModel, score); + } + return graph; } else { Grasp algorithm = new Grasp(this.test, this.score); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/graph/EdgeListGraph.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/graph/EdgeListGraph.java index cca46a120e..040379594c 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/graph/EdgeListGraph.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/graph/EdgeListGraph.java @@ -20,6 +20,8 @@ /////////////////////////////////////////////////////////////////////////////// package edu.cmu.tetrad.graph; +import edu.cmu.tetrad.data.DataBox; + import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.io.IOException; @@ -75,6 +77,7 @@ public class EdgeListGraph implements Graph, TripleClassifier { private Set underLineTriples = new HashSet<>(); private Set dottedUnderLineTriples = new HashSet<>(); private Set ambiguousTriples = new HashSet<>(); + private Map> parentsHash = new HashMap<>(); //==============================CONSTUCTORS===========================// @@ -130,6 +133,7 @@ public EdgeListGraph(EdgeListGraph graph) throws IllegalArgumentException { } this.edgesSet = new HashSet<>(graph.edgesSet); this.namesHash = new HashMap<>(graph.namesHash); + this.parentsHash = new HashMap<>(graph.parentsHash); // this.paths = new Paths(this); this.underLineTriples = graph.getUnderLines(); @@ -358,25 +362,29 @@ public Edge getDirectedEdge(Node node1, Node node2) { */ @Override public List getParents(Node node) { - List parents = new ArrayList<>(); - Set edges = this.edgeLists.get(node); + if (!parentsHash.containsKey(node)) { + List parents = new ArrayList<>(); + Set edges = this.edgeLists.get(node); - if (edges == null) { - throw new IllegalArgumentException("Node " + node + " is not in the graph."); - } + if (edges == null) { + throw new IllegalArgumentException("Node " + node + " is not in the graph."); + } - for (Edge edge : edges) { - if (edge == null) continue; + for (Edge edge : edges) { + if (edge == null) continue; - Endpoint endpoint1 = edge.getDistalEndpoint(node); - Endpoint endpoint2 = edge.getProximalEndpoint(node); + Endpoint endpoint1 = edge.getDistalEndpoint(node); + Endpoint endpoint2 = edge.getProximalEndpoint(node); - if (endpoint1 == Endpoint.TAIL && endpoint2 == Endpoint.ARROW) { - parents.add(edge.getDistalNode(node)); + if (endpoint1 == Endpoint.TAIL && endpoint2 == Endpoint.ARROW) { + parents.add(edge.getDistalNode(node)); + } } + + parentsHash.put(node, parents); } - return parents; + return parentsHash.get(node); } /** @@ -578,6 +586,9 @@ public boolean removeEdge(Node node1, Node node2) { removeTriplesNotInGraph(); + parentsHash.remove(node1); + parentsHash.remove(node2); + return removeEdges(edges); } @@ -680,6 +691,9 @@ public boolean addEdge(Edge edge) { this.edgeLists.get(edge.getNode1()).add(edge); this.edgeLists.get(edge.getNode2()).add(edge); this.edgesSet.add(edge); + + this.parentsHash.remove(edge.getNode1()); + this.parentsHash.remove(edge.getNode2()); } if (Edges.isDirectedEdge(edge)) { @@ -810,6 +824,7 @@ public boolean equals(Object o) { public void fullyConnect(Endpoint endpoint) { this.edgesSet.clear(); this.edgeLists.clear(); + this.parentsHash.clear(); for (Node node : this.nodes) { this.edgeLists.put(node, new HashSet<>()); @@ -940,6 +955,9 @@ public boolean removeEdge(Edge edge) { this.edgeLists.put(edge.getNode1(), edgeList1); this.edgeLists.put(edge.getNode2(), edgeList2); + this.parentsHash.remove(edge.getNode1()); + this.parentsHash.remove(edge.getNode2()); + getPcs().firePropertyChange("edgeRemoved", edge, null); return true; } @@ -997,6 +1015,8 @@ public boolean removeNode(Node node) { Set edgeList2 = this.edgeLists.get(node2); edgeList2.remove(edge); this.edgesSet.remove(edge); + this.parentsHash.remove(edge.getNode1()); + this.parentsHash.remove(edge.getNode2()); changed = true; } @@ -1006,6 +1026,7 @@ public boolean removeNode(Node node) { this.edgeLists.remove(node); this.nodes.remove(node); + this.parentsHash.remove(node); this.namesHash.remove(node.getName()); removeTriplesNotInGraph(); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/graph/Paths.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/graph/Paths.java index 112506f4aa..1712e5b001 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/graph/Paths.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/graph/Paths.java @@ -1706,6 +1706,10 @@ public boolean isMSeparatedFrom(Node node1, Node node2, Set z) { return !isMConnectedTo(node1, node2, z); } + public boolean isMSeparatedFrom(Node node1, Node node2, Set z, Map> ancestors) { + return !isMConnectedTo(node1, node2, z, ancestors); + } + /** * @return true iff there is a semi-directed path from node1 to node2 */ diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java index b4fde7f515..4977766ed8 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java @@ -8,7 +8,6 @@ import edu.cmu.tetrad.search.test.IndependenceResult; import edu.cmu.tetrad.search.test.MsepTest; import edu.cmu.tetrad.search.test.RowsSettable; -import edu.cmu.tetrad.util.RandomUtil; import edu.cmu.tetrad.util.SublistGenerator; import edu.cmu.tetrad.util.UniformityTest; import org.apache.commons.math3.distribution.BinomialDistribution; @@ -39,14 +38,12 @@ * @author josephramsey */ public class MarkovCheck { - private final Graph graph; private final IndependenceTest independenceTest; - private final MsepTest msep; private final List resultsIndep = new ArrayList<>(); private final List resultsDep = new ArrayList<>(); private ConditioningSetType setType; - private boolean parallelized = false; + private boolean parallelized = true; private double fractionDependentIndep = Double.NaN; private double fractionDependentDep = Double.NaN; private double ksPValueIndep = Double.NaN; @@ -57,36 +54,46 @@ public class MarkovCheck { private double andersonDarlingPDep = Double.NaN; private double bernoulliPIndep = Double.NaN; private double bernoulliPDep = Double.NaN; - private int numResamples = 1; private double percentResammple = 0.5; + private int numTestsindep = 0; + private int numTestsDep = 0; /** * Constructor. Takes a graph and an independence test over the variables of the graph. * * @param graph The graph. * @param independenceTest The test over the variables of the graph. + * @param setType The type of conditioning sets to use in the Markov check. */ public MarkovCheck(Graph graph, IndependenceTest independenceTest, ConditioningSetType setType) { this.graph = GraphUtils.replaceNodes(graph, independenceTest.getVariables()); this.independenceTest = independenceTest; - this.msep = new MsepTest(this.graph); this.setType = setType; } + /** + * Returns the set of independence facts used in the Markov check, for dsepation and dconnection separately. + * + * @param graph The graph. + * @return The set of independence facts used in the Markov check, for dsepation and dconnection separately. + */ @NotNull public static AllSubsetsIndependenceFacts getAllSubsetsIndependenceFacts(Graph graph) { List variables = new ArrayList<>(graph.getNodes()); + + for (Node node : variables) { + if (node == null) throw new NullPointerException("Null node in graph."); + } + + MsepTest msepTest = new MsepTest(graph); List nodes = new ArrayList<>(variables); -// Collections.sort(nodes); - Set msep = new HashSet<>(); Set mconn = new HashSet<>(); for (Node x : nodes) { List other = new ArrayList<>(variables); -// Collections.sort(other); other.remove(x); for (Node y : other) { @@ -113,7 +120,8 @@ public static AllSubsetsIndependenceFacts getAllSubsetsIndependenceFacts(Graph g /** * Generates all results, for both the local Markov and local Faithfulness checks, for each node in the graph given - * the parents of that node. These results are stored in the resultsIndep and resultsDep lists. + * the parents of that node. These results are stored in the resultsIndep and resultsDep lists. This should be + * called before any of the results methods. * * @see #getResults(boolean) */ @@ -123,21 +131,21 @@ public void generateResults() { if (setType == ConditioningSetType.GLOBAL_MARKOV) { AllSubsetsIndependenceFacts result = getAllSubsetsIndependenceFacts(graph); - generateResultsAllSubsets(true, result.msep, result.mconn); - generateResultsAllSubsets(false, result.msep, result.mconn); + generateResultsAllSubsets(result.msep, result.mconn); + generateResultsAllSubsets(result.msep, result.mconn); } else { List variables = independenceTest.getVariables(); List nodes = new ArrayList<>(variables); -// Collections.sort(nodes); - List order = null; + List order; try { order = graph.paths().getValidOrder(graph.getNodes(), true); } catch (Exception e) { - e.printStackTrace(); + throw new RuntimeException("Error getting valid order: " + e.getMessage()); } + Set allIndependenceFacts = new HashSet<>(); Set msep = new HashSet<>(); Set mconn = new HashSet<>(); @@ -177,26 +185,20 @@ public void generateResults() { } List other = new ArrayList<>(graph.getNodes()); -// Collections.sort(other); + Collections.sort(other); other.removeAll(z); for (Node w : other) { if (w == x || w == y) continue; if (z.contains(x) || z.contains(y) || z.contains(w)) continue; - if (this.msep.isMSeparated(x, y, z)) { - if (!msep.contains(new IndependenceFact(y, x, z))) { - msep.add(new IndependenceFact(x, y, z)); - } - } else { - if (!mconn.contains(new IndependenceFact(y, x, z))) { - mconn.add(new IndependenceFact(x, y, z)); - } - } + allIndependenceFacts.add(new IndependenceFact(x, y, z)); } } } - generateResults(msep, mconn); + generateMseps(new ArrayList<>(allIndependenceFacts), msep, mconn, new MsepTest(graph)); + generateResults(msep, true); + generateResults(mconn, false); } calcStats(true); @@ -291,6 +293,11 @@ public double getKsPValue(boolean indep) { } } + /** + * Returns the Anderson-Darling A^2* statistic for the given list of results. + * @param indep True if for implied independencies, false if for implied dependencies. + * @return The Anderson-Darling A^2* statistic for the given list of results. + */ public double getAndersonDarlingA2Star(boolean indep) { if (indep) { return aSquaredStarIndep; @@ -299,6 +306,11 @@ public double getAndersonDarlingA2Star(boolean indep) { } } + /** + * Returns the Anderson-Darling p-value for the given list of results. + * @param indep True if for implied independencies, false if for implied dependencies. + * @return The Anderson-Darling p-value for the given list of results. + */ public double getAndersonDarlingP(boolean indep) { if (indep) { return andersonDarlingPIndep; @@ -307,6 +319,11 @@ public double getAndersonDarlingP(boolean indep) { } } + /** + * Returns the Bernoulli p-value for the given list of results. + * @param indep True if for implied independencies, false if for implied dependencies. + * @return The Bernoulli p-value for the given list of results. + */ public double getBernoulliPValue(boolean indep) { if (indep) { return bernoulliPIndep; @@ -324,23 +341,6 @@ public List getVariables() { return new ArrayList<>(independenceTest.getVariables()); } -// /** -// * Returns the Markov Adequacy Score for the graph. This is zero if the p-value of the KS test of Uniformity is less -// * than alpha, and the fraction of dependent pairs otherwise. This is only for continuous Gaussian data, as it -// * hard-codes the Fisher Z test for the local Markov and Faithfulness check. -// * -// * @param alpha The alpha level for the KS test of Uniformity. An alpha level greater than this will be considered -// * uniform. -// * @return The Markov Adequacy Score for this graph given the data. -// */ -// public double getMarkovAdequacyScore(double alpha) { -// if (getKsPValue(true) > alpha) { -// return getFractionDependent(false); -// } else { -// return 0.0; -// } -// } - /** * Returns the variable with the given name. * @@ -360,7 +360,100 @@ public IndependenceTest getIndependenceTest() { return this.independenceTest; } - private void generateResults(Set msep, Set mconn) { + /** + * Sets the percentage of all samples to use when resampling for each conditional independence test. + * + * @param percentResammple The percentage of all samples to use when resampling for each conditional independence + * test. + */ + public void setPercentResammple(double percentResammple) { + this.percentResammple = percentResammple; + } + + /** + * Generates the m-separation sets for the given list of independence facts. The m-separation sets are stored in the + * msep and mconn sets. + * @param allIndependenceFacts The list of independence facts. + * @param msep The set of m-separation facts. + * @param mconn The set of m-connection facts. + * @param msepTest The m-separation test. + */ + private void generateMseps(List allIndependenceFacts, Set msep, Set mconn, + MsepTest msepTest) { + class IndCheckTask implements Callable, Set>> { + private final int from; + private final int to; + private final List facts; + private final MsepTest msepTest; + + IndCheckTask(int from, int to, List facts, MsepTest test) { + this.from = from; + this.to = to; + this.facts = facts; + this.msepTest = test; + } + + @Override + public Pair, Set> call() { + Set msep = new HashSet<>(); + Set mconn = new HashSet<>(); + + for (int i = from; i < to; i++) { + if (Thread.interrupted()) break; + IndependenceFact fact = facts.get(i); + + Node x = fact.getX(); + Node y = fact.getY(); + Set z = fact.getZ(); + + if (this.msepTest.isMSeparated(x, y, z)) { + msep.add(fact); + } else { + mconn.add(fact); + } + } + + return new Pair<>(msep, mconn); + } + } + + List, Set>>> tasks = new ArrayList<>(); + int chunkSize = getChunkSize(allIndependenceFacts.size()); + + for (int i = 0; i < allIndependenceFacts.size() && !Thread.currentThread().isInterrupted(); i += chunkSize) { + IndCheckTask task = new IndCheckTask(i, min(i + chunkSize, allIndependenceFacts.size()), + allIndependenceFacts, msepTest); + + if (!parallelized) { + Pair, Set> _results = task.call(); + msep.addAll(_results.getFirst()); + mconn.addAll(_results.getSecond()); + } else { + tasks.add(task); + } + } + + if (parallelized) { + List, Set>>> theseResults + = ForkJoinPool.commonPool().invokeAll(tasks); + + for (Future, Set>> future : theseResults) { + try { + msep.addAll(future.get().getFirst()); + mconn.addAll(future.get().getSecond()); + } catch (InterruptedException | ExecutionException e) { + throw new RuntimeException(e); + } + } + } + } + + /** + * Generates the results for the given set of independence facts. + * @param facts The set of independence facts. + * @param msep True if for implied independencies, false if for implied dependencies. + */ + private void generateResults(Set facts, boolean msep) { class IndCheckTask implements Callable, Set>> { private final int from; private final int to; @@ -388,32 +481,28 @@ public Pair, Set> call() { Set z = fact.getZ(); if (independenceTest instanceof RowsSettable) { -// for (int t = 0; t < getNumResamples(); t++) { List rows = getSubsampleRows(percentResammple); - ((RowsSettable) independenceTest).setRows(rows); - - boolean verbose = independenceTest.isVerbose(); - independenceTest.setVerbose(false); - IndependenceResult result; - try { - result = independenceTest.checkIndependence(x, y, z); - } catch (Exception e) { - throw new RuntimeException(e); - } - boolean indep = result.isIndependent(); - double pValue = result.getPValue(); - independenceTest.setVerbose(verbose); - - if (!Double.isNaN(pValue)) { - if (msep.contains(new IndependenceFact(x, y, z))) { - resultsIndep.add(new IndependenceResult(fact, indep, pValue, Double.NaN)); - } else if (mconn.contains(new IndependenceFact(x, y, z))) { - resultsDep.add(new IndependenceResult(fact, indep, pValue, Double.NaN)); - } else { - throw new IllegalArgumentException("Unknown separation set: " + z); - } + ((RowsSettable) independenceTest).setRows(rows); + + boolean verbose = independenceTest.isVerbose(); + independenceTest.setVerbose(false); + IndependenceResult result; + try { + result = independenceTest.checkIndependence(x, y, z); + } catch (Exception e) { + throw new RuntimeException(e); + } + boolean indep = result.isIndependent(); + double pValue = result.getPValue(); + independenceTest.setVerbose(verbose); + + if (!Double.isNaN(pValue)) { + if (msep) { + resultsIndep.add(new IndependenceResult(fact, indep, pValue, Double.NaN)); + } else { + resultsDep.add(new IndependenceResult(fact, indep, pValue, Double.NaN)); } -// } + } } else { boolean verbose = independenceTest.isVerbose(); independenceTest.setVerbose(false); @@ -428,12 +517,10 @@ public Pair, Set> call() { independenceTest.setVerbose(verbose); if (!Double.isNaN(pValue)) { - if (msep.contains(new IndependenceFact(x, y, z))) { + if (msep) { resultsIndep.add(new IndependenceResult(fact, indep, pValue, Double.NaN)); - } else if (mconn.contains(new IndependenceFact(x, y, z))) { - resultsDep.add(new IndependenceResult(fact, indep, pValue, Double.NaN)); } else { - throw new IllegalArgumentException("Unknown separation set: " + z); + resultsDep.add(new IndependenceResult(fact, indep, pValue, Double.NaN)); } } } @@ -445,16 +532,10 @@ public Pair, Set> call() { List, Set>>> tasks = new ArrayList<>(); - Set _facts = new HashSet<>(); - _facts.addAll(msep); - _facts.addAll(mconn); - - List facts = new ArrayList<>(_facts); - int chunkSize = getChunkSize(facts.size()); for (int i = 0; i < facts.size() && !Thread.currentThread().isInterrupted(); i += chunkSize) { - IndCheckTask task = new IndCheckTask(i, min(facts.size(), i + chunkSize), facts, independenceTest); + IndCheckTask task = new IndCheckTask(i, min(facts.size(), min(i + chunkSize, facts.size())), new ArrayList<>(facts), independenceTest); if (!parallelized) { Pair, Set> _results = task.call(); @@ -479,88 +560,13 @@ public Pair, Set> call() { } } - private List getSubsampleRows(double v) { - int sampleSize = independenceTest.getSampleSize(); - int subsampleSize = (int) FastMath.ceil(sampleSize * v); - List rows = new ArrayList<>(sampleSize); - for (int i = 0; i < sampleSize; i++) { - rows.add(i); - } - Collections.shuffle(rows); - return rows.subList(0, subsampleSize); - } - - private List getBoostrapSample(double v) { - int sampleSize = independenceTest.getSampleSize(); - int subsampleSize = (int) FastMath.floor(sampleSize * v); - List rows = new ArrayList<>(sampleSize); - for (int i = 0; i < subsampleSize; i++) { - rows.add(RandomUtil.getInstance().nextInt(sampleSize)); - } - return rows; - } - - private void generateResultsAllSubsets(boolean indep, Set msep, Set mconn) { - Set facts = indep ? msep : mconn; - - class IndCheckTask implements Callable> { - private final int from; - private final int to; - private final List facts; - private final IndependenceTest independenceTest; - - IndCheckTask(int from, int to, List facts, IndependenceTest test) { - this.from = from; - this.to = to; - this.facts = facts; - this.independenceTest = test; - } - - @Override - public List call() { - List results = new ArrayList<>(); - - for (int i = from; i < to; i++) { - if (Thread.interrupted()) break; - IndependenceFact fact = facts.get(i); - - Node x = fact.getX(); - Node y = fact.getY(); - Set z = fact.getZ(); - boolean verbose = independenceTest.isVerbose(); - independenceTest.setVerbose(false); - IndependenceResult result; - try { - result = independenceTest.checkIndependence(x, y, z); - } catch (Exception e) { - throw new RuntimeException(e); - } - boolean indep = result.isIndependent(); - double pValue = result.getPValue(); - independenceTest.setVerbose(verbose); - - if (!Double.isNaN(pValue)) { - results.add(new IndependenceResult(fact, indep, pValue, Double.NaN)); - } - } - - return results; - } - } - - generateResults(msep, mconn); - } - + /** + * Calculates the statistics for the given list of results. + * @param indep True if for implied independencies, false if for implied dependencies. + */ private void calcStats(boolean indep) { List results = new ArrayList<>(getResultsLocal(indep)); -// Collections.shuffle(_results); -// -// List results = new ArrayList<>(); -// for (int i = 0; i < _results.size() / getNumResamples(); i++) { -// results.add(_results.get(i)); -// } - int dependent = 0; for (IndependenceResult result : results) { @@ -604,6 +610,32 @@ private void calcStats(boolean indep) { } } + /** + * Returns a list of row indices for a subsample of the data set. + * @param v The fraction of the data set to use. + * @return A list of row indices for a subsample of the data set. + */ + private List getSubsampleRows(double v) { + int sampleSize = independenceTest.getSampleSize(); + int subsampleSize = (int) FastMath.ceil(sampleSize * v); + List rows = new ArrayList<>(sampleSize); + for (int i = 0; i < sampleSize; i++) { + rows.add(i); + } + Collections.shuffle(rows); + return rows.subList(0, subsampleSize); + } + + /** + * Generates the results for the given set of independence facts, for both the local Markov and local Faithfulness + * @param msep The set of m-separation facts. + * @param mconn The set of m-connection facts. + */ + private void generateResultsAllSubsets(Set msep, Set mconn) { + generateResults(msep, true); + generateResults(mconn, false); + } + /** * Returns a Bernoulli p-value for the hypothesis that the distribution of p-values is not Uniform under the null * hypothesis. Values less than alpha imply non-uniform distributions. @@ -628,12 +660,24 @@ private double getBernoulliP(List pValues, double alpha) { return (1.0 - bd.cumulativeProbability(dependentJudgments)) / 2.0 + (bd.probability(n - dependentJudgments) / 2.0); } + /** + * Returns the chunk size for parallelization. + * @param n The number of items to chunk. + * @return The chunk size for parallelization. + */ private int getChunkSize(int n) { - int chunk = (int) FastMath.ceil((n / ((double) (5 * Runtime.getRuntime().availableProcessors())))); + if (true) return 1; + int numProcessors = Runtime.getRuntime().availableProcessors(); + int chunk = (int) FastMath.ceil((n / ((double) numProcessors))) / 10; if (chunk < 1) chunk = 1; return chunk; } + /** + * Returns the list of results for the given condition. + * @param indep True if for implied independencies, false if for implied dependencies. + * @return The list of results for the given condition. + */ private List getResultsLocal(boolean indep) { if (indep) { return this.resultsIndep; @@ -642,22 +686,9 @@ private List getResultsLocal(boolean indep) { } } - public int getNumResamples() { - return numResamples; - } - - public void setNumResamples(int numResamples) { - this.numResamples = numResamples; - } - - public double getPercentResammple() { - return percentResammple; - } - - public void setPercentResammple(double percentResammple) { - this.percentResammple = percentResammple; - } - + /** + * Stores the set of m-separation facts and the set of m-connection facts for a graph, for the global check. + */ public static class AllSubsetsIndependenceFacts { private final Set msep; private final Set mconn; @@ -677,7 +708,6 @@ public String toStringIndep() { return builder.toString(); } - public String toStringDep() { StringBuilder builder = new StringBuilder("All subsets independence facts:\n"); @@ -689,15 +719,11 @@ public String toStringDep() { } public List getMsep() { - List facts = new ArrayList<>(msep); -// Collections.sort(facts); - return facts; + return new ArrayList<>(msep); } public List getMconn() { - List facts = new ArrayList<>(mconn); -// Collections.sort(facts); - return facts; + return new ArrayList<>(mconn); } } } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/SemBicScorer.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/SemBicScorer.java index 57c5979b6a..cd3deb47d6 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/SemBicScorer.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/SemBicScorer.java @@ -48,7 +48,7 @@ public static double scoreDag(Graph dag, DataModel data, double penaltyDiscount, } else if (data instanceof DataSet) { score = new SemBicScore((DataSet) data, precomputeCovariances); } else { - throw new IllegalArgumentException("Expecting a covariance matrix of a dataset."); + throw new IllegalArgumentException("Expecting a covariance matrix or a dataset."); } score.setPenaltyDiscount(penaltyDiscount); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/MsepTest.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/MsepTest.java index bfc2da94a1..0890aafd3a 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/MsepTest.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/MsepTest.java @@ -254,7 +254,7 @@ public boolean isMSeparated(Node x, Node y, Set z) { } } - return getGraph().paths().isMSeparatedFrom(x, y, z); + return getGraph().paths().isMSeparatedFrom(x, y, z, ancestorMap); } /** diff --git a/tetrad-lib/src/test/java/edu/cmu/tetrad/test/TestFges.java b/tetrad-lib/src/test/java/edu/cmu/tetrad/test/TestFges.java index c9e7477ca5..ae53a1122c 100644 --- a/tetrad-lib/src/test/java/edu/cmu/tetrad/test/TestFges.java +++ b/tetrad-lib/src/test/java/edu/cmu/tetrad/test/TestFges.java @@ -267,7 +267,7 @@ public void testExplore4() { public void testExplore5() { Graph graph = GraphUtils.convert("A-->B,A-->C,A-->D,A->E,B-->F,C-->F,D-->F,E-->F"); edu.cmu.tetrad.search.Fges fges = new edu.cmu.tetrad.search.Fges(new GraphScore(graph)); - fges.setFaithfulnessAssumed(false); + fges.setFaithfulnessAssumed(true); Graph CPDAG = fges.search(); assertEquals(GraphTransforms.cpdagForDag(graph), CPDAG); } From 3e3f114483acf34c3ee109a32264fb1b2c0ac5db Mon Sep 17 00:00:00 2001 From: jdramsey Date: Thu, 7 Dec 2023 14:16:42 -0500 Subject: [PATCH 013/163] Cleaned up the MarkovCheck.java code. --- .../edu/cmu/tetrad/search/MarkovCheck.java | 184 ++++++++++-------- 1 file changed, 99 insertions(+), 85 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java index 4977766ed8..2e95eacd0f 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java @@ -63,7 +63,7 @@ public class MarkovCheck { * * @param graph The graph. * @param independenceTest The test over the variables of the graph. - * @param setType The type of conditioning sets to use in the Markov check. + * @param setType The type of conditioning sets to use in the Markov check. */ public MarkovCheck(Graph graph, IndependenceTest independenceTest, ConditioningSetType setType) { this.graph = GraphUtils.replaceNodes(graph, independenceTest.getVariables()); @@ -199,6 +199,9 @@ public void generateResults() { generateMseps(new ArrayList<>(allIndependenceFacts), msep, mconn, new MsepTest(graph)); generateResults(msep, true); generateResults(mconn, false); + + this.numTestsindep = msep.size(); + this.numTestsDep = mconn.size(); } calcStats(true); @@ -295,6 +298,7 @@ public double getKsPValue(boolean indep) { /** * Returns the Anderson-Darling A^2* statistic for the given list of results. + * * @param indep True if for implied independencies, false if for implied dependencies. * @return The Anderson-Darling A^2* statistic for the given list of results. */ @@ -308,6 +312,7 @@ public double getAndersonDarlingA2Star(boolean indep) { /** * Returns the Anderson-Darling p-value for the given list of results. + * * @param indep True if for implied independencies, false if for implied dependencies. * @return The Anderson-Darling p-value for the given list of results. */ @@ -321,6 +326,7 @@ public double getAndersonDarlingP(boolean indep) { /** * Returns the Bernoulli p-value for the given list of results. + * * @param indep True if for implied independencies, false if for implied dependencies. * @return The Bernoulli p-value for the given list of results. */ @@ -332,6 +338,20 @@ public double getBernoulliPValue(boolean indep) { } } + /** + * Returns the number of tests for the given list of results. + * + * @param indep True if for implied independencies, false if for implied dependencies. + * @return The number of tests for the given list of results. + */ + public int getNumTests(boolean indep) { + if (indep) { + return numTestsindep; + } else { + return numTestsDep; + } + } + /** * Returns the variables of the independence test. * @@ -373,22 +393,21 @@ public void setPercentResammple(double percentResammple) { /** * Generates the m-separation sets for the given list of independence facts. The m-separation sets are stored in the * msep and mconn sets. + * * @param allIndependenceFacts The list of independence facts. - * @param msep The set of m-separation facts. - * @param mconn The set of m-connection facts. - * @param msepTest The m-separation test. + * @param msep The set of m-separation facts. + * @param mconn The set of m-connection facts. + * @param msepTest The m-separation test. */ private void generateMseps(List allIndependenceFacts, Set msep, Set mconn, MsepTest msepTest) { class IndCheckTask implements Callable, Set>> { - private final int from; - private final int to; + private final int index; private final List facts; private final MsepTest msepTest; - IndCheckTask(int from, int to, List facts, MsepTest test) { - this.from = from; - this.to = to; + IndCheckTask(int index, List facts, MsepTest test) { + this.index = index; this.facts = facts; this.msepTest = test; } @@ -398,19 +417,16 @@ public Pair, Set> call() { Set msep = new HashSet<>(); Set mconn = new HashSet<>(); - for (int i = from; i < to; i++) { - if (Thread.interrupted()) break; - IndependenceFact fact = facts.get(i); + IndependenceFact fact = facts.get(index); - Node x = fact.getX(); - Node y = fact.getY(); - Set z = fact.getZ(); + Node x = fact.getX(); + Node y = fact.getY(); + Set z = fact.getZ(); - if (this.msepTest.isMSeparated(x, y, z)) { - msep.add(fact); - } else { - mconn.add(fact); - } + if (this.msepTest.isMSeparated(x, y, z)) { + msep.add(fact); + } else { + mconn.add(fact); } return new Pair<>(msep, mconn); @@ -418,11 +434,9 @@ public Pair, Set> call() { } List, Set>>> tasks = new ArrayList<>(); - int chunkSize = getChunkSize(allIndependenceFacts.size()); - for (int i = 0; i < allIndependenceFacts.size() && !Thread.currentThread().isInterrupted(); i += chunkSize) { - IndCheckTask task = new IndCheckTask(i, min(i + chunkSize, allIndependenceFacts.size()), - allIndependenceFacts, msepTest); + for (int i = 0; i < allIndependenceFacts.size() && !Thread.currentThread().isInterrupted(); i++) { + IndCheckTask task = new IndCheckTask(i, allIndependenceFacts, msepTest); if (!parallelized) { Pair, Set> _results = task.call(); @@ -450,19 +464,18 @@ public Pair, Set> call() { /** * Generates the results for the given set of independence facts. + * * @param facts The set of independence facts. - * @param msep True if for implied independencies, false if for implied dependencies. + * @param msep True if for implied independencies, false if for implied dependencies. */ private void generateResults(Set facts, boolean msep) { class IndCheckTask implements Callable, Set>> { - private final int from; - private final int to; + private final int index; private final List facts; private final IndependenceTest independenceTest; - IndCheckTask(int from, int to, List facts, IndependenceTest test) { - this.from = from; - this.to = to; + IndCheckTask(int index, List facts, IndependenceTest test) { + this.index = index; this.facts = facts; this.independenceTest = test; } @@ -472,56 +485,53 @@ public Pair, Set> call() { Set resultsIndep = new HashSet<>(); Set resultsDep = new HashSet<>(); - for (int i = from; i < to; i++) { - if (Thread.interrupted()) break; - IndependenceFact fact = facts.get(i); - - Node x = fact.getX(); - Node y = fact.getY(); - Set z = fact.getZ(); - - if (independenceTest instanceof RowsSettable) { - List rows = getSubsampleRows(percentResammple); - ((RowsSettable) independenceTest).setRows(rows); - - boolean verbose = independenceTest.isVerbose(); - independenceTest.setVerbose(false); - IndependenceResult result; - try { - result = independenceTest.checkIndependence(x, y, z); - } catch (Exception e) { - throw new RuntimeException(e); - } - boolean indep = result.isIndependent(); - double pValue = result.getPValue(); - independenceTest.setVerbose(verbose); - - if (!Double.isNaN(pValue)) { - if (msep) { - resultsIndep.add(new IndependenceResult(fact, indep, pValue, Double.NaN)); - } else { - resultsDep.add(new IndependenceResult(fact, indep, pValue, Double.NaN)); - } - } - } else { - boolean verbose = independenceTest.isVerbose(); - independenceTest.setVerbose(false); - IndependenceResult result; - try { - result = independenceTest.checkIndependence(x, y, z); - } catch (Exception e) { - throw new RuntimeException(e); + IndependenceFact fact = facts.get(index); + + Node x = fact.getX(); + Node y = fact.getY(); + Set z = fact.getZ(); + + if (independenceTest instanceof RowsSettable) { + List rows = getSubsampleRows(percentResammple); + ((RowsSettable) independenceTest).setRows(rows); + + boolean verbose = independenceTest.isVerbose(); + independenceTest.setVerbose(false); + IndependenceResult result; + try { + result = independenceTest.checkIndependence(x, y, z); + } catch (Exception e) { + throw new RuntimeException(e); + } + boolean indep = result.isIndependent(); + double pValue = result.getPValue(); + independenceTest.setVerbose(verbose); + + if (!Double.isNaN(pValue)) { + if (msep) { + resultsIndep.add(new IndependenceResult(fact, indep, pValue, Double.NaN)); + } else { + resultsDep.add(new IndependenceResult(fact, indep, pValue, Double.NaN)); } - boolean indep = result.isIndependent(); - double pValue = result.getPValue(); - independenceTest.setVerbose(verbose); - - if (!Double.isNaN(pValue)) { - if (msep) { - resultsIndep.add(new IndependenceResult(fact, indep, pValue, Double.NaN)); - } else { - resultsDep.add(new IndependenceResult(fact, indep, pValue, Double.NaN)); - } + } + } else { + boolean verbose = independenceTest.isVerbose(); + independenceTest.setVerbose(false); + IndependenceResult result; + try { + result = independenceTest.checkIndependence(x, y, z); + } catch (Exception e) { + throw new RuntimeException(e); + } + boolean indep = result.isIndependent(); + double pValue = result.getPValue(); + independenceTest.setVerbose(verbose); + + if (!Double.isNaN(pValue)) { + if (msep) { + resultsIndep.add(new IndependenceResult(fact, indep, pValue, Double.NaN)); + } else { + resultsDep.add(new IndependenceResult(fact, indep, pValue, Double.NaN)); } } } @@ -532,10 +542,8 @@ public Pair, Set> call() { List, Set>>> tasks = new ArrayList<>(); - int chunkSize = getChunkSize(facts.size()); - - for (int i = 0; i < facts.size() && !Thread.currentThread().isInterrupted(); i += chunkSize) { - IndCheckTask task = new IndCheckTask(i, min(facts.size(), min(i + chunkSize, facts.size())), new ArrayList<>(facts), independenceTest); + for (int i = 0; i < facts.size() && !Thread.currentThread().isInterrupted(); i++) { + IndCheckTask task = new IndCheckTask(i, new ArrayList<>(facts), independenceTest); if (!parallelized) { Pair, Set> _results = task.call(); @@ -562,6 +570,7 @@ public Pair, Set> call() { /** * Calculates the statistics for the given list of results. + * * @param indep True if for implied independencies, false if for implied dependencies. */ private void calcStats(boolean indep) { @@ -612,6 +621,7 @@ private void calcStats(boolean indep) { /** * Returns a list of row indices for a subsample of the data set. + * * @param v The fraction of the data set to use. * @return A list of row indices for a subsample of the data set. */ @@ -628,7 +638,8 @@ private List getSubsampleRows(double v) { /** * Generates the results for the given set of independence facts, for both the local Markov and local Faithfulness - * @param msep The set of m-separation facts. + * + * @param msep The set of m-separation facts. * @param mconn The set of m-connection facts. */ private void generateResultsAllSubsets(Set msep, Set mconn) { @@ -639,8 +650,9 @@ private void generateResultsAllSubsets(Set msep, Set pValues, double alpha) { @@ -662,6 +674,7 @@ private double getBernoulliP(List pValues, double alpha) { /** * Returns the chunk size for parallelization. + * * @param n The number of items to chunk. * @return The chunk size for parallelization. */ @@ -675,6 +688,7 @@ private int getChunkSize(int n) { /** * Returns the list of results for the given condition. + * * @param indep True if for implied independencies, false if for implied dependencies. * @return The list of results for the given condition. */ From be3374f39f7b10e31f891ca93e1bc14f680627b0 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Thu, 7 Dec 2023 16:53:11 -0500 Subject: [PATCH 014/163] Cleaned up the MarkovCheck.java code. --- .../src/main/java/edu/cmu/tetrad/search/Fas.java | 4 +++- .../java/edu/cmu/tetrad/search/MarkovCheck.java | 4 ++-- .../src/main/java/edu/cmu/tetrad/search/Pc.java | 14 +++++++++----- .../edu/cmu/tetrad/search/test/IndTestFisherZ.java | 2 +- 4 files changed, 15 insertions(+), 9 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fas.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fas.java index 8942219381..d851f690ec 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fas.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fas.java @@ -175,7 +175,9 @@ public Graph search(List nodes) { } for (int d = 0; d <= _depth; d++) { - System.out.println("Depth: " + d); + if (verbose) { + System.out.println("Depth: " + d); + } boolean more; diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java index 2e95eacd0f..97b0b4c26f 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java @@ -137,12 +137,12 @@ public void generateResults() { List variables = independenceTest.getVariables(); List nodes = new ArrayList<>(variables); - List order; + List order = null; try { order = graph.paths().getValidOrder(graph.getNodes(), true); } catch (Exception e) { - throw new RuntimeException("Error getting valid order: " + e.getMessage()); + // Leave null. Not an error here. Just means we can't use the ordered local Markov check. } Set allIndependenceFacts = new HashSet<>(); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Pc.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Pc.java index e1f143d1d9..647299fdb3 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Pc.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Pc.java @@ -145,8 +145,10 @@ public Graph search(Set nodes) { * @see IFas */ public Graph search(IFas fas, Set nodes) { - this.logger.forceLogMessage("Starting PC algorithm"); - this.logger.forceLogMessage("Independence test = " + getIndependenceTest() + "."); + if (verbose) { + this.logger.forceLogMessage("Starting PC algorithm"); + this.logger.forceLogMessage("Independence test = " + getIndependenceTest() + "."); + } long startTime = MillisecondTimes.timeMillis(); @@ -189,9 +191,11 @@ public Graph search(IFas fas, Set nodes) { this.elapsedTime = MillisecondTimes.timeMillis() - startTime; - this.logger.forceLogMessage("Elapsed time = " + (this.elapsedTime) / 1000. + " s"); - this.logger.forceLogMessage("Finishing PC Algorithm."); - this.logger.flush(); + if (verbose) { + this.logger.forceLogMessage("Elapsed time = " + (this.elapsedTime) / 1000. + " s"); + this.logger.forceLogMessage("Finishing PC Algorithm."); + this.logger.flush(); + } return this.graph; } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java index b440f0d35b..48c72e6c22 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java @@ -59,7 +59,7 @@ public final class IndTestFisherZ implements IndependenceTest, RowsSettable { private List variables; private double alpha; private DataSet dataSet; - private boolean verbose = true; + private boolean verbose = false; // private double p = Double.NaN; private double r = Double.NaN; private List rows = null; From 99b06e6bb960d6fb50c64ba36c125666a0fb98c0 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Sun, 10 Dec 2023 13:02:02 -0500 Subject: [PATCH 015/163] Cleaned up the MarkovCheck.java code. --- .../tetradapp/editor/MarkovCheckEditor.java | 28 ++++++------ .../simulation/BayesNetSimulation.java | 2 - .../ConditionalGaussianSimulation.java | 2 - .../simulation/GeneralSemSimulation.java | 2 - .../GeneralSemSimulationSpecial1.java | 2 - .../simulation/LeeHastieSimulation.java | 2 - .../simulation/LinearFisherModel.java | 2 - .../simulation/LinearSineSimulation.java | 2 - .../simulation/NLSemSimulation.java | 2 - .../simulation/SemSimulation.java | 2 - .../simulation/SemThenDiscretize.java | 2 - .../simulation/StandardizedSemSimulation.java | 2 - .../edu/cmu/tetrad/search/MarkovCheck.java | 44 ++++++++++++------- .../edu/cmu/tetrad/test/SpecialDataClark.java | 2 - 14 files changed, 41 insertions(+), 55 deletions(-) diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java index 723b221ecc..387831c2e8 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java @@ -85,8 +85,8 @@ public class MarkovCheckEditor extends JPanel { private JLabel ksLabelIndep; // private JLabel masLabelDep; // private JLabel masLabelIndep; - private JLabel bernoulliPLabelDep; - private JLabel bernoulliPLabelIndep; + private JLabel binomialPLabelDep; + private JLabel binomialPLabelIndep; private JLabel andersonDarlingA2LabelDep; private JLabel andersonDarlingA2LabelIndep; private JLabel andersonDarlingPLabelDep; @@ -561,7 +561,7 @@ public void mouseClicked(MouseEvent e) { Box b6a = Box.createHorizontalBox(); b6a.add(Box.createHorizontalGlue()); - b6a.add(bernoulliPLabelDep); + b6a.add(binomialPLabelDep); b0b1.add(b6a); Box b6b = Box.createHorizontalBox(); @@ -769,7 +769,7 @@ public void mouseClicked(MouseEvent e) { Box b6a = Box.createHorizontalBox(); b6a.add(Box.createHorizontalGlue()); - b6a.add(bernoulliPLabelIndep); + b6a.add(binomialPLabelIndep); b0b1.add(b6a); Box b6b = Box.createHorizontalBox(); @@ -824,12 +824,12 @@ private void setLabelTexts() { ksLabelDep = new JLabel(); } - if (bernoulliPLabelIndep == null) { - bernoulliPLabelIndep = new JLabel(); + if (binomialPLabelIndep == null) { + binomialPLabelIndep = new JLabel(); } - if (bernoulliPLabelDep == null) { - bernoulliPLabelDep = new JLabel(); + if (binomialPLabelDep == null) { + binomialPLabelDep = new JLabel(); } if (andersonDarlingA2LabelIndep == null) { @@ -890,14 +890,14 @@ private void setLabelTexts() { + ((Double.isNaN(model.getMarkovCheck().getAndersonDarlingP(false)) ? "-" : NumberFormatUtil.getInstance().getNumberFormat().format(model.getMarkovCheck().getAndersonDarlingP(false))))); - bernoulliPLabelIndep.setText("P-value of Bernoulli Test = " - + ((Double.isNaN(model.getMarkovCheck().getBernoulliPValue(true)) + binomialPLabelIndep.setText("P-value of Binomial Test = " + + ((Double.isNaN(model.getMarkovCheck().getBinomialPValue(true)) ? "-" - : NumberFormatUtil.getInstance().getNumberFormat().format(model.getMarkovCheck().getBernoulliPValue(true))))); - bernoulliPLabelDep.setText("P-value of Bernoulli Test = " - + ((Double.isNaN(model.getMarkovCheck().getBernoulliPValue(false)) + : NumberFormatUtil.getInstance().getNumberFormat().format(model.getMarkovCheck().getBinomialPValue(true))))); + binomialPLabelDep.setText("P-value of Binomial Test = " + + ((Double.isNaN(model.getMarkovCheck().getBinomialPValue(false)) ? "-" - : NumberFormatUtil.getInstance().getNumberFormat().format(model.getMarkovCheck().getBernoulliPValue(false))))); + : NumberFormatUtil.getInstance().getNumberFormat().format(model.getMarkovCheck().getBinomialPValue(false))))); fractionDepLabelIndep.setText("% dependent = " + ((Double.isNaN(model.getMarkovCheck().getFractionDependent(true)) ? "-" diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/simulation/BayesNetSimulation.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/simulation/BayesNetSimulation.java index 8347eceea0..6116af41a6 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/simulation/BayesNetSimulation.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/simulation/BayesNetSimulation.java @@ -84,8 +84,6 @@ public void createData(Parameters parameters, boolean newModel) { this.ims = new ArrayList<>(); for (int i = 0; i < parameters.getInt(Params.NUM_RUNS); i++) { - System.out.println("Simulating dataset #" + (i + 1)); - if (parameters.getBoolean(Params.DIFFERENT_GRAPHS) && i > 0) { graph = this.randomGraph.createGraph(parameters); } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/simulation/ConditionalGaussianSimulation.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/simulation/ConditionalGaussianSimulation.java index 6f1ec1107d..d06b36e6eb 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/simulation/ConditionalGaussianSimulation.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/simulation/ConditionalGaussianSimulation.java @@ -108,8 +108,6 @@ public void createData(Parameters parameters, boolean newModel) { this.graphs = new ArrayList<>(); for (int i = 0; i < parameters.getInt(Params.NUM_RUNS); i++) { - System.out.println("Simulating dataset #" + (i + 1)); - if (parameters.getBoolean(Params.DIFFERENT_GRAPHS) && i > 0) { graph = this.randomGraph.createGraph(parameters); } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/simulation/GeneralSemSimulation.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/simulation/GeneralSemSimulation.java index c33bd2d0ff..dc1b8a97cc 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/simulation/GeneralSemSimulation.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/simulation/GeneralSemSimulation.java @@ -66,8 +66,6 @@ public void createData(Parameters parameters, boolean newModel) { this.ims = new ArrayList<>(); for (int i = 0; i < parameters.getInt(Params.NUM_RUNS); i++) { - System.out.println("Simulating dataset #" + (i + 1)); - if (parameters.getBoolean(Params.DIFFERENT_GRAPHS) && i > 0) { graph = this.randomGraph.createGraph(parameters); } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/simulation/GeneralSemSimulationSpecial1.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/simulation/GeneralSemSimulationSpecial1.java index b2801cc127..5ba3bf423a 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/simulation/GeneralSemSimulationSpecial1.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/simulation/GeneralSemSimulationSpecial1.java @@ -44,8 +44,6 @@ public void createData(Parameters parameters, boolean newModel) { this.graphs = new ArrayList<>(); for (int i = 0; i < parameters.getInt(Params.NUM_RUNS); i++) { - System.out.println("Simulating dataset #" + (i + 1)); - if (parameters.getBoolean(Params.DIFFERENT_GRAPHS) && i > 0) { graph = this.randomGraph.createGraph(parameters); } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/simulation/LeeHastieSimulation.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/simulation/LeeHastieSimulation.java index d20aaf89c1..08f43f7b43 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/simulation/LeeHastieSimulation.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/simulation/LeeHastieSimulation.java @@ -65,8 +65,6 @@ public void createData(Parameters parameters, boolean newModel) { this.graphs = new ArrayList<>(); for (int i = 0; i < parameters.getInt(Params.NUM_RUNS); i++) { - System.out.println("Simulating dataset #" + (i + 1)); - if (parameters.getBoolean(Params.DIFFERENT_GRAPHS) && i > 0) { graph = this.randomGraph.createGraph(parameters); } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/simulation/LinearFisherModel.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/simulation/LinearFisherModel.java index f896c17611..a750843f97 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/simulation/LinearFisherModel.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/simulation/LinearFisherModel.java @@ -70,8 +70,6 @@ public void createData(Parameters parameters, boolean newModel) { System.out.println("degree = " + GraphUtils.getDegree(graph)); for (int i = 0; i < parameters.getInt(Params.NUM_RUNS); i++) { - System.out.println("Simulating dataset #" + (i + 1)); - if (this.shocks != null && this.shocks.size() > 0) { parameters.set(Params.NUM_MEASURES, this.shocks.get(0).getVariables().size()); } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/simulation/LinearSineSimulation.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/simulation/LinearSineSimulation.java index b0cf5836d8..38473e0238 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/simulation/LinearSineSimulation.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/simulation/LinearSineSimulation.java @@ -96,8 +96,6 @@ public void createData(Parameters parameters, boolean newModel) { this.graphs = new ArrayList<>(); for (int i = 0; i < parameters.getInt(Params.NUM_RUNS); i++) { - System.out.println("Simulating dataset #" + (i + 1)); - if (parameters.getBoolean(Params.DIFFERENT_GRAPHS) && i > 0) graph = this.randomGraph.createGraph(parameters); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/simulation/NLSemSimulation.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/simulation/NLSemSimulation.java index ae8e1a97f8..e9e945aeff 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/simulation/NLSemSimulation.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/simulation/NLSemSimulation.java @@ -53,8 +53,6 @@ public void createData(Parameters parameters, boolean newModel) { int numVars = parameters.getInt(Params.NUM_MEASURES); for (int i = 0; i < parameters.getInt(Params.NUM_RUNS); i++) { - System.out.println("Simulating dataset #" + (i + 1)); - if (parameters.getBoolean(Params.DIFFERENT_GRAPHS) && i > 0) { graph = this.randomGraph.createGraph(parameters); } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/simulation/SemSimulation.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/simulation/SemSimulation.java index 989dfd72f0..e782f6d1b7 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/simulation/SemSimulation.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/simulation/SemSimulation.java @@ -67,8 +67,6 @@ public void createData(Parameters parameters, boolean newModel) { this.ims = new ArrayList<>(); for (int i = 0; i < parameters.getInt(Params.NUM_RUNS); i++) { - System.out.println("Simulating dataset #" + (i + 1)); - if (parameters.getBoolean(Params.DIFFERENT_GRAPHS) && i > 0) { graph = this.randomGraph.createGraph(parameters); } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/simulation/SemThenDiscretize.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/simulation/SemThenDiscretize.java index e2bf648fbe..6f8a74aed8 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/simulation/SemThenDiscretize.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/simulation/SemThenDiscretize.java @@ -65,8 +65,6 @@ public void createData(Parameters parameters, boolean newModel) { this.graphs = new ArrayList<>(); for (int i = 0; i < parameters.getInt(Params.NUM_RUNS); i++) { - System.out.println("Simulating dataset #" + (i + 1)); - if (parameters.getBoolean(Params.DIFFERENT_GRAPHS) && i > 0) { graph = this.randomGraph.createGraph(parameters); } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/simulation/StandardizedSemSimulation.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/simulation/StandardizedSemSimulation.java index dcf2f7f114..cf4ecbed1a 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/simulation/StandardizedSemSimulation.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/simulation/StandardizedSemSimulation.java @@ -57,8 +57,6 @@ public void createData(Parameters parameters, boolean newModel) { this.graphs = new ArrayList<>(); for (int i = 0; i < parameters.getInt("numRuns"); i++) { - System.out.println("Simulating dataset #" + (i + 1)); - if (parameters.getBoolean("differentGraphs") && i > 0) { graph = this.randomGraph.createGraph(parameters); } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java index 97b0b4c26f..5db61f904f 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java @@ -52,8 +52,8 @@ public class MarkovCheck { private double aSquaredStarDep = Double.NaN; private double andersonDarlingPIndep = Double.NaN; private double andersonDarlingPDep = Double.NaN; - private double bernoulliPIndep = Double.NaN; - private double bernoulliPDep = Double.NaN; + private double binomialPIndep = Double.NaN; + private double binomialPDep = Double.NaN; private double percentResammple = 0.5; private int numTestsindep = 0; private int numTestsDep = 0; @@ -325,16 +325,16 @@ public double getAndersonDarlingP(boolean indep) { } /** - * Returns the Bernoulli p-value for the given list of results. + * Returns the Binomial p-value for the given list of results. * * @param indep True if for implied independencies, false if for implied dependencies. - * @return The Bernoulli p-value for the given list of results. + * @return The Binomial p-value for the given list of results. */ - public double getBernoulliPValue(boolean indep) { + public double getBinomialPValue(boolean indep) { if (indep) { - return bernoulliPIndep; + return binomialPIndep; } else { - return bernoulliPDep; + return binomialPDep; } } @@ -405,6 +405,7 @@ class IndCheckTask implements Callable, Set facts; private final MsepTest msepTest; + private boolean stopThread = false; IndCheckTask(int index, List facts, MsepTest test) { this.index = index; @@ -431,6 +432,14 @@ public Pair, Set> call() { return new Pair<>(msep, mconn); } + + public boolean isStopThread() { + return stopThread; + } + + public void setStopThread(boolean stopThread) { + this.stopThread = stopThread; + } } List, Set>>> tasks = new ArrayList<>(); @@ -453,8 +462,9 @@ public Pair, Set> call() { for (Future, Set>> future : theseResults) { try { - msep.addAll(future.get().getFirst()); - mconn.addAll(future.get().getSecond()); + Pair, Set> setSetPair = future.get(); + msep.addAll(setSetPair.getFirst()); + mconn.addAll(setSetPair.getSecond()); } catch (InterruptedException | ExecutionException e) { throw new RuntimeException(e); } @@ -594,25 +604,25 @@ private void calcStats(boolean indep) { if (indep) { if (pValues.size() < 2) { ksPValueIndep = Double.NaN; - bernoulliPIndep = Double.NaN; + binomialPIndep = Double.NaN; aSquaredStarIndep = Double.NaN; andersonDarlingPIndep = Double.NaN; } else { ksPValueIndep = UniformityTest.getPValue(pValues, 0.0, 1.0); - bernoulliPIndep = getBernoulliP(pValues, independenceTest.getAlpha()); + binomialPIndep = getBinomialP(pValues, independenceTest.getAlpha()); aSquaredStarIndep = aSquaredStar; andersonDarlingPIndep = 1. - new GeneralAndersonDarlingTest(pValues, new UniformRealDistribution(0, 1)).getProbTail(pValues.size(), aSquaredStar); } } else { if (pValues.size() < 2) { ksPValueDep = Double.NaN; - bernoulliPDep = Double.NaN; + binomialPDep = Double.NaN; aSquaredStarDep = Double.NaN; andersonDarlingPDep = Double.NaN; } else { ksPValueDep = UniformityTest.getPValue(pValues, 0.0, 1.0); - bernoulliPDep = getBernoulliP(pValues, independenceTest.getAlpha()); + binomialPDep = getBinomialP(pValues, independenceTest.getAlpha()); aSquaredStarDep = aSquaredStar; andersonDarlingPDep = 1. - new GeneralAndersonDarlingTest(pValues, new UniformRealDistribution(0, 1)).getProbTail(pValues.size(), aSquaredStar); } @@ -648,14 +658,14 @@ private void generateResultsAllSubsets(Set msep, Set pValues, double alpha) { + private double getBinomialP(List pValues, double alpha) { int dependentJudgments = 0; for (double pValue : pValues) { @@ -669,7 +679,7 @@ private double getBernoulliP(List pValues, double alpha) { BinomialDistribution bd = new BinomialDistribution(n, alpha); // We want the area to the right of this, so we subtract from 1. - return (1.0 - bd.cumulativeProbability(dependentJudgments)) / 2.0 + (bd.probability(n - dependentJudgments) / 2.0); + return (1.0 - bd.cumulativeProbability(dependentJudgments)) + (bd.probability(n - dependentJudgments) / 2.0); } /** diff --git a/tetrad-lib/src/test/java/edu/cmu/tetrad/test/SpecialDataClark.java b/tetrad-lib/src/test/java/edu/cmu/tetrad/test/SpecialDataClark.java index 02fa4f19b2..a39203b1d7 100644 --- a/tetrad-lib/src/test/java/edu/cmu/tetrad/test/SpecialDataClark.java +++ b/tetrad-lib/src/test/java/edu/cmu/tetrad/test/SpecialDataClark.java @@ -51,8 +51,6 @@ public void createData(Parameters parameters, boolean newModel) { this.graphs = new ArrayList<>(); for (int i = 0; i < parameters.getInt("numRuns"); i++) { - System.out.println("Simulating dataset #" + (i + 1)); - if (parameters.getBoolean("differentGraphs") && i > 0) { graph = this.randomGraph.createGraph(parameters); } From 0afec53e31a563d9e46eb173de2c4e95cdbd307a Mon Sep 17 00:00:00 2001 From: jdramsey Date: Sun, 10 Dec 2023 13:02:21 -0500 Subject: [PATCH 016/163] Cleaned up the MarkovCheck.java code. --- tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java index 5db61f904f..5c40a8f437 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java @@ -679,7 +679,7 @@ private double getBinomialP(List pValues, double alpha) { BinomialDistribution bd = new BinomialDistribution(n, alpha); // We want the area to the right of this, so we subtract from 1. - return (1.0 - bd.cumulativeProbability(dependentJudgments)) + (bd.probability(n - dependentJudgments) / 2.0); + return (1.0 - bd.cumulativeProbability(dependentJudgments)) + (bd.probability(n - dependentJudgments)); } /** From 1ff7fd2323249b65921f8087a312b7e0586f9596 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Mon, 11 Dec 2023 09:46:19 -0500 Subject: [PATCH 017/163] Moved docs to lib/resources. --- .../src/main/resources/docs}/manual/README.md | 16 ++++---- .../resources/docs}/manual/css/normalize.css | 0 .../resources/docs}/manual/css/tetrad.css | 0 .../resources/docs}/manual/flowchart.html | 0 .../manual/images/appendix_figure_1a.png | Bin .../manual/images/appendix_figure_1b.png | Bin .../docs}/manual/images/appendix_figure_2.png | Bin .../manual/images/arc_specialization_1.png | Bin .../manual/images/arc_specialization_2.png | Bin .../manual/images/arc_specialization_3.png | Bin .../docs}/manual/images/classify_box_1.png | Bin .../docs}/manual/images/classify_box_2.png | Bin .../docs}/manual/images/classify_box_3.png | Bin .../docs}/manual/images/compare_box_1.png | Bin .../docs}/manual/images/compare_box_10.png | Bin .../docs}/manual/images/compare_box_11.png | Bin .../docs}/manual/images/compare_box_12.png | Bin .../docs}/manual/images/compare_box_13.png | Bin .../docs}/manual/images/compare_box_3.png | Bin .../docs}/manual/images/compare_box_4.png | Bin .../docs}/manual/images/compare_box_5.png | Bin .../docs}/manual/images/compare_box_6.png | Bin .../docs}/manual/images/compare_box_7.png | Bin .../docs}/manual/images/compare_box_8.png | Bin .../docs}/manual/images/compare_box_9.png | Bin .../docs}/manual/images/data_box_1.png | Bin .../docs}/manual/images/data_box_10.png | Bin .../docs}/manual/images/data_box_2.png | Bin .../docs}/manual/images/data_box_3.png | Bin .../docs}/manual/images/data_box_4.png | Bin .../docs}/manual/images/data_box_5.png | Bin .../docs}/manual/images/data_box_6.png | Bin .../docs}/manual/images/data_box_7.png | Bin .../docs}/manual/images/data_box_8.png | Bin .../docs}/manual/images/data_box_8a.png | Bin .../docs}/manual/images/data_box_8b.png | Bin .../docs}/manual/images/data_box_9.png | Bin .../docs}/manual/images/estimator_box_1.png | Bin .../docs}/manual/images/estimator_box_2.png | Bin .../docs}/manual/images/flowchart.pdf | Bin .../docs}/manual/images/flowchart.pptx | Bin .../docs}/manual/images/flowchart/Slide1.png | Bin .../docs}/manual/images/flowchart/Slide2.png | Bin .../images/instantiated_model_box_1.png | Bin .../images/instantiated_model_box_10.png | Bin .../images/instantiated_model_box_11.png | Bin .../images/instantiated_model_box_12.png | Bin .../images/instantiated_model_box_13.png | Bin .../images/instantiated_model_box_14.png | Bin .../images/instantiated_model_box_2.png | Bin .../images/instantiated_model_box_3.png | Bin .../images/instantiated_model_box_4.png | Bin .../images/instantiated_model_box_5.png | Bin .../images/instantiated_model_box_6.png | Bin .../images/instantiated_model_box_7.png | Bin .../images/instantiated_model_box_8.png | Bin .../images/instantiated_model_box_9.png | Bin .../docs}/manual/images/knowledge_box_1.png | Bin .../docs}/manual/images/knowledge_box_2.png | Bin .../docs}/manual/images/knowledge_box_3.png | Bin .../docs}/manual/images/knowledge_box_4.png | Bin .../manual/images/parametric_model_box_1.png | Bin .../manual/images/parametric_model_box_2.png | Bin .../manual/images/parametric_model_box_3.png | Bin .../manual/images/parametric_model_box_4.png | Bin .../manual/images/parametric_model_box_5.png | Bin .../manual/images/parametric_model_box_6.png | Bin .../manual/images/parametric_model_box_7.png | Bin .../manual/images/parametric_model_box_8.png | Bin .../docs}/manual/images/regression_box_1.png | Bin .../docs}/manual/images/regression_box_2.png | Bin .../docs}/manual/images/regression_box_3.png | Bin .../docs}/manual/images/search_box_1.png | Bin .../docs}/manual/images/simulation_box_1.png | Bin .../docs}/manual/images/updater_box_1.png | Bin .../docs}/manual/images/updater_box_10.png | Bin .../docs}/manual/images/updater_box_2.png | Bin .../docs}/manual/images/updater_box_3.png | Bin .../docs}/manual/images/updater_box_4.png | Bin .../docs}/manual/images/updater_box_5.png | Bin .../docs}/manual/images/updater_box_6.png | Bin .../docs}/manual/images/updater_box_7.png | Bin .../docs}/manual/images/updater_box_8.png | Bin .../docs}/manual/images/updater_box_9.png | Bin .../main/resources/docs}/manual/index.html | 0 .../docs}/notes/cfci.orientation.txt | 0 .../main/resources/docs}/notes/cliques.txt | 0 .../src/main/resources/docs}/notes/cmd.txt | 0 .../src/main/resources/docs}/notes/images | 0 .../src/main/resources/docs}/notes/images.1 | 0 .../notes/pc.fci.in.r.spirtes.2.3.2010.txt | 0 .../docs}/notes/serialization_notes.txt | 0 .../referenced_papers/Adjacency-submitted.pdf | Bin .../docs}/referenced_papers/AmStat_review.pdf | Bin .../Bollen_Ting_1993SociolMeth.pdf | Bin .../docs}/referenced_papers/CAUSAL.PS | Bin .../referenced_papers/CMU-ISRI-04-127.pdf | Bin .../docs}/referenced_papers/chickering02b.pdf | Bin .../docs}/referenced_papers/con00random.pdf | Bin .../docs}/referenced_papers/glasso.f90 | 0 .../docs}/referenced_papers/hartiganwong.pdf | Bin .../docs}/referenced_papers/hawkins1989.pdf | Bin .../docs}/referenced_papers/jmlr06.pdf | Bin .../math_s5_v1_article-17.pdf | Bin .../docs}/referenced_papers/optimal.pdf | Bin .../docs}/referenced_papers/p313-grira.pdf | Bin .../docs}/referenced_papers/splits.pdf | Bin .../docs}/referenced_papers/uaidiscovery.pdf | Bin tetrad-lib/pom.xml | 36 +++++++++--------- .../cmu/tetrad/util/ParamDescriptions.java | 2 +- 110 files changed, 27 insertions(+), 27 deletions(-) rename {docs => tetrad-gui/src/main/resources/docs}/manual/README.md (98%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/css/normalize.css (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/css/tetrad.css (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/flowchart.html (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/appendix_figure_1a.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/appendix_figure_1b.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/appendix_figure_2.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/arc_specialization_1.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/arc_specialization_2.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/arc_specialization_3.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/classify_box_1.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/classify_box_2.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/classify_box_3.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/compare_box_1.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/compare_box_10.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/compare_box_11.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/compare_box_12.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/compare_box_13.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/compare_box_3.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/compare_box_4.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/compare_box_5.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/compare_box_6.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/compare_box_7.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/compare_box_8.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/compare_box_9.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/data_box_1.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/data_box_10.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/data_box_2.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/data_box_3.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/data_box_4.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/data_box_5.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/data_box_6.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/data_box_7.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/data_box_8.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/data_box_8a.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/data_box_8b.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/data_box_9.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/estimator_box_1.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/estimator_box_2.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/flowchart.pdf (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/flowchart.pptx (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/flowchart/Slide1.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/flowchart/Slide2.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/instantiated_model_box_1.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/instantiated_model_box_10.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/instantiated_model_box_11.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/instantiated_model_box_12.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/instantiated_model_box_13.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/instantiated_model_box_14.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/instantiated_model_box_2.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/instantiated_model_box_3.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/instantiated_model_box_4.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/instantiated_model_box_5.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/instantiated_model_box_6.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/instantiated_model_box_7.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/instantiated_model_box_8.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/instantiated_model_box_9.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/knowledge_box_1.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/knowledge_box_2.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/knowledge_box_3.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/knowledge_box_4.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/parametric_model_box_1.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/parametric_model_box_2.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/parametric_model_box_3.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/parametric_model_box_4.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/parametric_model_box_5.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/parametric_model_box_6.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/parametric_model_box_7.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/parametric_model_box_8.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/regression_box_1.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/regression_box_2.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/regression_box_3.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/search_box_1.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/simulation_box_1.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/updater_box_1.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/updater_box_10.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/updater_box_2.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/updater_box_3.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/updater_box_4.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/updater_box_5.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/updater_box_6.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/updater_box_7.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/updater_box_8.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/images/updater_box_9.png (100%) rename {docs => tetrad-gui/src/main/resources/docs}/manual/index.html (100%) rename {docs => tetrad-gui/src/main/resources/docs}/notes/cfci.orientation.txt (100%) rename {docs => tetrad-gui/src/main/resources/docs}/notes/cliques.txt (100%) rename {docs => tetrad-gui/src/main/resources/docs}/notes/cmd.txt (100%) rename {docs => tetrad-gui/src/main/resources/docs}/notes/images (100%) rename {docs => tetrad-gui/src/main/resources/docs}/notes/images.1 (100%) rename {docs => tetrad-gui/src/main/resources/docs}/notes/pc.fci.in.r.spirtes.2.3.2010.txt (100%) rename {docs => tetrad-gui/src/main/resources/docs}/notes/serialization_notes.txt (100%) rename {docs => tetrad-gui/src/main/resources/docs}/referenced_papers/Adjacency-submitted.pdf (100%) rename {docs => tetrad-gui/src/main/resources/docs}/referenced_papers/AmStat_review.pdf (100%) rename {docs => tetrad-gui/src/main/resources/docs}/referenced_papers/Bollen_Ting_1993SociolMeth.pdf (100%) rename {docs => tetrad-gui/src/main/resources/docs}/referenced_papers/CAUSAL.PS (100%) rename {docs => tetrad-gui/src/main/resources/docs}/referenced_papers/CMU-ISRI-04-127.pdf (100%) rename {docs => tetrad-gui/src/main/resources/docs}/referenced_papers/chickering02b.pdf (100%) rename {docs => tetrad-gui/src/main/resources/docs}/referenced_papers/con00random.pdf (100%) rename {docs => tetrad-gui/src/main/resources/docs}/referenced_papers/glasso.f90 (100%) rename {docs => tetrad-gui/src/main/resources/docs}/referenced_papers/hartiganwong.pdf (100%) rename {docs => tetrad-gui/src/main/resources/docs}/referenced_papers/hawkins1989.pdf (100%) rename {docs => tetrad-gui/src/main/resources/docs}/referenced_papers/jmlr06.pdf (100%) rename {docs => tetrad-gui/src/main/resources/docs}/referenced_papers/math_s5_v1_article-17.pdf (100%) rename {docs => tetrad-gui/src/main/resources/docs}/referenced_papers/optimal.pdf (100%) rename {docs => tetrad-gui/src/main/resources/docs}/referenced_papers/p313-grira.pdf (100%) rename {docs => tetrad-gui/src/main/resources/docs}/referenced_papers/splits.pdf (100%) rename {docs => tetrad-gui/src/main/resources/docs}/referenced_papers/uaidiscovery.pdf (100%) diff --git a/docs/manual/README.md b/tetrad-gui/src/main/resources/docs/manual/README.md similarity index 98% rename from docs/manual/README.md rename to tetrad-gui/src/main/resources/docs/manual/README.md index 838958ff87..e985d9550e 100644 --- a/docs/manual/README.md +++ b/tetrad-gui/src/main/resources/docs/manual/README.md @@ -1,9 +1,9 @@ -# Tetrad Single-Page HTML Manual - -This `/docs/manual` folder is the home of the Tetrad HTML manual. The live version is published via the Github pages. -And the live URL is: http://cmu-phil.github.io/tetrad/manual/ - -## How to Edit - -If you are a team member and want to edit this HTML manual, just open the `index.html` with your favorite text editor +# Tetrad Single-Page HTML Manual + +This `/docs/manual` folder is the home of the Tetrad HTML manual. The live version is published via the Github pages. +And the live URL is: http://cmu-phil.github.io/tetrad/manual/ + +## How to Edit + +If you are a team member and want to edit this HTML manual, just open the `index.html` with your favorite text editor and search for the corresponding sections to make changes. All the embeded images are stored in the `/images` folder. \ No newline at end of file diff --git a/docs/manual/css/normalize.css b/tetrad-gui/src/main/resources/docs/manual/css/normalize.css similarity index 100% rename from docs/manual/css/normalize.css rename to tetrad-gui/src/main/resources/docs/manual/css/normalize.css diff --git a/docs/manual/css/tetrad.css b/tetrad-gui/src/main/resources/docs/manual/css/tetrad.css similarity index 100% rename from docs/manual/css/tetrad.css rename to tetrad-gui/src/main/resources/docs/manual/css/tetrad.css diff --git a/docs/manual/flowchart.html b/tetrad-gui/src/main/resources/docs/manual/flowchart.html similarity index 100% rename from docs/manual/flowchart.html rename to tetrad-gui/src/main/resources/docs/manual/flowchart.html diff --git a/docs/manual/images/appendix_figure_1a.png b/tetrad-gui/src/main/resources/docs/manual/images/appendix_figure_1a.png similarity index 100% rename from docs/manual/images/appendix_figure_1a.png rename to tetrad-gui/src/main/resources/docs/manual/images/appendix_figure_1a.png diff --git a/docs/manual/images/appendix_figure_1b.png b/tetrad-gui/src/main/resources/docs/manual/images/appendix_figure_1b.png similarity index 100% rename from docs/manual/images/appendix_figure_1b.png rename to tetrad-gui/src/main/resources/docs/manual/images/appendix_figure_1b.png diff --git a/docs/manual/images/appendix_figure_2.png b/tetrad-gui/src/main/resources/docs/manual/images/appendix_figure_2.png similarity index 100% rename from docs/manual/images/appendix_figure_2.png rename to tetrad-gui/src/main/resources/docs/manual/images/appendix_figure_2.png diff --git a/docs/manual/images/arc_specialization_1.png b/tetrad-gui/src/main/resources/docs/manual/images/arc_specialization_1.png similarity index 100% rename from docs/manual/images/arc_specialization_1.png rename to tetrad-gui/src/main/resources/docs/manual/images/arc_specialization_1.png diff --git a/docs/manual/images/arc_specialization_2.png b/tetrad-gui/src/main/resources/docs/manual/images/arc_specialization_2.png similarity index 100% rename from docs/manual/images/arc_specialization_2.png rename to tetrad-gui/src/main/resources/docs/manual/images/arc_specialization_2.png diff --git a/docs/manual/images/arc_specialization_3.png b/tetrad-gui/src/main/resources/docs/manual/images/arc_specialization_3.png similarity index 100% rename from docs/manual/images/arc_specialization_3.png rename to tetrad-gui/src/main/resources/docs/manual/images/arc_specialization_3.png diff --git a/docs/manual/images/classify_box_1.png b/tetrad-gui/src/main/resources/docs/manual/images/classify_box_1.png similarity index 100% rename from docs/manual/images/classify_box_1.png rename to tetrad-gui/src/main/resources/docs/manual/images/classify_box_1.png diff --git a/docs/manual/images/classify_box_2.png b/tetrad-gui/src/main/resources/docs/manual/images/classify_box_2.png similarity index 100% rename from docs/manual/images/classify_box_2.png rename to tetrad-gui/src/main/resources/docs/manual/images/classify_box_2.png diff --git a/docs/manual/images/classify_box_3.png b/tetrad-gui/src/main/resources/docs/manual/images/classify_box_3.png similarity index 100% rename from docs/manual/images/classify_box_3.png rename to tetrad-gui/src/main/resources/docs/manual/images/classify_box_3.png diff --git a/docs/manual/images/compare_box_1.png b/tetrad-gui/src/main/resources/docs/manual/images/compare_box_1.png similarity index 100% rename from docs/manual/images/compare_box_1.png rename to tetrad-gui/src/main/resources/docs/manual/images/compare_box_1.png diff --git a/docs/manual/images/compare_box_10.png b/tetrad-gui/src/main/resources/docs/manual/images/compare_box_10.png similarity index 100% rename from docs/manual/images/compare_box_10.png rename to tetrad-gui/src/main/resources/docs/manual/images/compare_box_10.png diff --git a/docs/manual/images/compare_box_11.png b/tetrad-gui/src/main/resources/docs/manual/images/compare_box_11.png similarity index 100% rename from docs/manual/images/compare_box_11.png rename to tetrad-gui/src/main/resources/docs/manual/images/compare_box_11.png diff --git a/docs/manual/images/compare_box_12.png b/tetrad-gui/src/main/resources/docs/manual/images/compare_box_12.png similarity index 100% rename from docs/manual/images/compare_box_12.png rename to tetrad-gui/src/main/resources/docs/manual/images/compare_box_12.png diff --git a/docs/manual/images/compare_box_13.png b/tetrad-gui/src/main/resources/docs/manual/images/compare_box_13.png similarity index 100% rename from docs/manual/images/compare_box_13.png rename to tetrad-gui/src/main/resources/docs/manual/images/compare_box_13.png diff --git a/docs/manual/images/compare_box_3.png b/tetrad-gui/src/main/resources/docs/manual/images/compare_box_3.png similarity index 100% rename from docs/manual/images/compare_box_3.png rename to tetrad-gui/src/main/resources/docs/manual/images/compare_box_3.png diff --git a/docs/manual/images/compare_box_4.png b/tetrad-gui/src/main/resources/docs/manual/images/compare_box_4.png similarity index 100% rename from docs/manual/images/compare_box_4.png rename to tetrad-gui/src/main/resources/docs/manual/images/compare_box_4.png diff --git a/docs/manual/images/compare_box_5.png b/tetrad-gui/src/main/resources/docs/manual/images/compare_box_5.png similarity index 100% rename from docs/manual/images/compare_box_5.png rename to tetrad-gui/src/main/resources/docs/manual/images/compare_box_5.png diff --git a/docs/manual/images/compare_box_6.png b/tetrad-gui/src/main/resources/docs/manual/images/compare_box_6.png similarity index 100% rename from docs/manual/images/compare_box_6.png rename to tetrad-gui/src/main/resources/docs/manual/images/compare_box_6.png diff --git a/docs/manual/images/compare_box_7.png b/tetrad-gui/src/main/resources/docs/manual/images/compare_box_7.png similarity index 100% rename from docs/manual/images/compare_box_7.png rename to tetrad-gui/src/main/resources/docs/manual/images/compare_box_7.png diff --git a/docs/manual/images/compare_box_8.png b/tetrad-gui/src/main/resources/docs/manual/images/compare_box_8.png similarity index 100% rename from docs/manual/images/compare_box_8.png rename to tetrad-gui/src/main/resources/docs/manual/images/compare_box_8.png diff --git a/docs/manual/images/compare_box_9.png b/tetrad-gui/src/main/resources/docs/manual/images/compare_box_9.png similarity index 100% rename from docs/manual/images/compare_box_9.png rename to tetrad-gui/src/main/resources/docs/manual/images/compare_box_9.png diff --git a/docs/manual/images/data_box_1.png b/tetrad-gui/src/main/resources/docs/manual/images/data_box_1.png similarity index 100% rename from docs/manual/images/data_box_1.png rename to tetrad-gui/src/main/resources/docs/manual/images/data_box_1.png diff --git a/docs/manual/images/data_box_10.png b/tetrad-gui/src/main/resources/docs/manual/images/data_box_10.png similarity index 100% rename from docs/manual/images/data_box_10.png rename to tetrad-gui/src/main/resources/docs/manual/images/data_box_10.png diff --git a/docs/manual/images/data_box_2.png b/tetrad-gui/src/main/resources/docs/manual/images/data_box_2.png similarity index 100% rename from docs/manual/images/data_box_2.png rename to tetrad-gui/src/main/resources/docs/manual/images/data_box_2.png diff --git a/docs/manual/images/data_box_3.png b/tetrad-gui/src/main/resources/docs/manual/images/data_box_3.png similarity index 100% rename from docs/manual/images/data_box_3.png rename to tetrad-gui/src/main/resources/docs/manual/images/data_box_3.png diff --git a/docs/manual/images/data_box_4.png b/tetrad-gui/src/main/resources/docs/manual/images/data_box_4.png similarity index 100% rename from docs/manual/images/data_box_4.png rename to tetrad-gui/src/main/resources/docs/manual/images/data_box_4.png diff --git a/docs/manual/images/data_box_5.png b/tetrad-gui/src/main/resources/docs/manual/images/data_box_5.png similarity index 100% rename from docs/manual/images/data_box_5.png rename to tetrad-gui/src/main/resources/docs/manual/images/data_box_5.png diff --git a/docs/manual/images/data_box_6.png b/tetrad-gui/src/main/resources/docs/manual/images/data_box_6.png similarity index 100% rename from docs/manual/images/data_box_6.png rename to tetrad-gui/src/main/resources/docs/manual/images/data_box_6.png diff --git a/docs/manual/images/data_box_7.png b/tetrad-gui/src/main/resources/docs/manual/images/data_box_7.png similarity index 100% rename from docs/manual/images/data_box_7.png rename to tetrad-gui/src/main/resources/docs/manual/images/data_box_7.png diff --git a/docs/manual/images/data_box_8.png b/tetrad-gui/src/main/resources/docs/manual/images/data_box_8.png similarity index 100% rename from docs/manual/images/data_box_8.png rename to tetrad-gui/src/main/resources/docs/manual/images/data_box_8.png diff --git a/docs/manual/images/data_box_8a.png b/tetrad-gui/src/main/resources/docs/manual/images/data_box_8a.png similarity index 100% rename from docs/manual/images/data_box_8a.png rename to tetrad-gui/src/main/resources/docs/manual/images/data_box_8a.png diff --git a/docs/manual/images/data_box_8b.png b/tetrad-gui/src/main/resources/docs/manual/images/data_box_8b.png similarity index 100% rename from docs/manual/images/data_box_8b.png rename to tetrad-gui/src/main/resources/docs/manual/images/data_box_8b.png diff --git a/docs/manual/images/data_box_9.png b/tetrad-gui/src/main/resources/docs/manual/images/data_box_9.png similarity index 100% rename from docs/manual/images/data_box_9.png rename to tetrad-gui/src/main/resources/docs/manual/images/data_box_9.png diff --git a/docs/manual/images/estimator_box_1.png b/tetrad-gui/src/main/resources/docs/manual/images/estimator_box_1.png similarity index 100% rename from docs/manual/images/estimator_box_1.png rename to tetrad-gui/src/main/resources/docs/manual/images/estimator_box_1.png diff --git a/docs/manual/images/estimator_box_2.png b/tetrad-gui/src/main/resources/docs/manual/images/estimator_box_2.png similarity index 100% rename from docs/manual/images/estimator_box_2.png rename to tetrad-gui/src/main/resources/docs/manual/images/estimator_box_2.png diff --git a/docs/manual/images/flowchart.pdf b/tetrad-gui/src/main/resources/docs/manual/images/flowchart.pdf similarity index 100% rename from docs/manual/images/flowchart.pdf rename to tetrad-gui/src/main/resources/docs/manual/images/flowchart.pdf diff --git a/docs/manual/images/flowchart.pptx b/tetrad-gui/src/main/resources/docs/manual/images/flowchart.pptx similarity index 100% rename from docs/manual/images/flowchart.pptx rename to tetrad-gui/src/main/resources/docs/manual/images/flowchart.pptx diff --git a/docs/manual/images/flowchart/Slide1.png b/tetrad-gui/src/main/resources/docs/manual/images/flowchart/Slide1.png similarity index 100% rename from docs/manual/images/flowchart/Slide1.png rename to tetrad-gui/src/main/resources/docs/manual/images/flowchart/Slide1.png diff --git a/docs/manual/images/flowchart/Slide2.png b/tetrad-gui/src/main/resources/docs/manual/images/flowchart/Slide2.png similarity index 100% rename from docs/manual/images/flowchart/Slide2.png rename to tetrad-gui/src/main/resources/docs/manual/images/flowchart/Slide2.png diff --git a/docs/manual/images/instantiated_model_box_1.png b/tetrad-gui/src/main/resources/docs/manual/images/instantiated_model_box_1.png similarity index 100% rename from docs/manual/images/instantiated_model_box_1.png rename to tetrad-gui/src/main/resources/docs/manual/images/instantiated_model_box_1.png diff --git a/docs/manual/images/instantiated_model_box_10.png b/tetrad-gui/src/main/resources/docs/manual/images/instantiated_model_box_10.png similarity index 100% rename from docs/manual/images/instantiated_model_box_10.png rename to tetrad-gui/src/main/resources/docs/manual/images/instantiated_model_box_10.png diff --git a/docs/manual/images/instantiated_model_box_11.png b/tetrad-gui/src/main/resources/docs/manual/images/instantiated_model_box_11.png similarity index 100% rename from docs/manual/images/instantiated_model_box_11.png rename to tetrad-gui/src/main/resources/docs/manual/images/instantiated_model_box_11.png diff --git a/docs/manual/images/instantiated_model_box_12.png b/tetrad-gui/src/main/resources/docs/manual/images/instantiated_model_box_12.png similarity index 100% rename from docs/manual/images/instantiated_model_box_12.png rename to tetrad-gui/src/main/resources/docs/manual/images/instantiated_model_box_12.png diff --git a/docs/manual/images/instantiated_model_box_13.png b/tetrad-gui/src/main/resources/docs/manual/images/instantiated_model_box_13.png similarity index 100% rename from docs/manual/images/instantiated_model_box_13.png rename to tetrad-gui/src/main/resources/docs/manual/images/instantiated_model_box_13.png diff --git a/docs/manual/images/instantiated_model_box_14.png b/tetrad-gui/src/main/resources/docs/manual/images/instantiated_model_box_14.png similarity index 100% rename from docs/manual/images/instantiated_model_box_14.png rename to tetrad-gui/src/main/resources/docs/manual/images/instantiated_model_box_14.png diff --git a/docs/manual/images/instantiated_model_box_2.png b/tetrad-gui/src/main/resources/docs/manual/images/instantiated_model_box_2.png similarity index 100% rename from docs/manual/images/instantiated_model_box_2.png rename to tetrad-gui/src/main/resources/docs/manual/images/instantiated_model_box_2.png diff --git a/docs/manual/images/instantiated_model_box_3.png b/tetrad-gui/src/main/resources/docs/manual/images/instantiated_model_box_3.png similarity index 100% rename from docs/manual/images/instantiated_model_box_3.png rename to tetrad-gui/src/main/resources/docs/manual/images/instantiated_model_box_3.png diff --git a/docs/manual/images/instantiated_model_box_4.png b/tetrad-gui/src/main/resources/docs/manual/images/instantiated_model_box_4.png similarity index 100% rename from docs/manual/images/instantiated_model_box_4.png rename to tetrad-gui/src/main/resources/docs/manual/images/instantiated_model_box_4.png diff --git a/docs/manual/images/instantiated_model_box_5.png b/tetrad-gui/src/main/resources/docs/manual/images/instantiated_model_box_5.png similarity index 100% rename from docs/manual/images/instantiated_model_box_5.png rename to tetrad-gui/src/main/resources/docs/manual/images/instantiated_model_box_5.png diff --git a/docs/manual/images/instantiated_model_box_6.png b/tetrad-gui/src/main/resources/docs/manual/images/instantiated_model_box_6.png similarity index 100% rename from docs/manual/images/instantiated_model_box_6.png rename to tetrad-gui/src/main/resources/docs/manual/images/instantiated_model_box_6.png diff --git a/docs/manual/images/instantiated_model_box_7.png b/tetrad-gui/src/main/resources/docs/manual/images/instantiated_model_box_7.png similarity index 100% rename from docs/manual/images/instantiated_model_box_7.png rename to tetrad-gui/src/main/resources/docs/manual/images/instantiated_model_box_7.png diff --git a/docs/manual/images/instantiated_model_box_8.png b/tetrad-gui/src/main/resources/docs/manual/images/instantiated_model_box_8.png similarity index 100% rename from docs/manual/images/instantiated_model_box_8.png rename to tetrad-gui/src/main/resources/docs/manual/images/instantiated_model_box_8.png diff --git a/docs/manual/images/instantiated_model_box_9.png b/tetrad-gui/src/main/resources/docs/manual/images/instantiated_model_box_9.png similarity index 100% rename from docs/manual/images/instantiated_model_box_9.png rename to tetrad-gui/src/main/resources/docs/manual/images/instantiated_model_box_9.png diff --git a/docs/manual/images/knowledge_box_1.png b/tetrad-gui/src/main/resources/docs/manual/images/knowledge_box_1.png similarity index 100% rename from docs/manual/images/knowledge_box_1.png rename to tetrad-gui/src/main/resources/docs/manual/images/knowledge_box_1.png diff --git a/docs/manual/images/knowledge_box_2.png b/tetrad-gui/src/main/resources/docs/manual/images/knowledge_box_2.png similarity index 100% rename from docs/manual/images/knowledge_box_2.png rename to tetrad-gui/src/main/resources/docs/manual/images/knowledge_box_2.png diff --git a/docs/manual/images/knowledge_box_3.png b/tetrad-gui/src/main/resources/docs/manual/images/knowledge_box_3.png similarity index 100% rename from docs/manual/images/knowledge_box_3.png rename to tetrad-gui/src/main/resources/docs/manual/images/knowledge_box_3.png diff --git a/docs/manual/images/knowledge_box_4.png b/tetrad-gui/src/main/resources/docs/manual/images/knowledge_box_4.png similarity index 100% rename from docs/manual/images/knowledge_box_4.png rename to tetrad-gui/src/main/resources/docs/manual/images/knowledge_box_4.png diff --git a/docs/manual/images/parametric_model_box_1.png b/tetrad-gui/src/main/resources/docs/manual/images/parametric_model_box_1.png similarity index 100% rename from docs/manual/images/parametric_model_box_1.png rename to tetrad-gui/src/main/resources/docs/manual/images/parametric_model_box_1.png diff --git a/docs/manual/images/parametric_model_box_2.png b/tetrad-gui/src/main/resources/docs/manual/images/parametric_model_box_2.png similarity index 100% rename from docs/manual/images/parametric_model_box_2.png rename to tetrad-gui/src/main/resources/docs/manual/images/parametric_model_box_2.png diff --git a/docs/manual/images/parametric_model_box_3.png b/tetrad-gui/src/main/resources/docs/manual/images/parametric_model_box_3.png similarity index 100% rename from docs/manual/images/parametric_model_box_3.png rename to tetrad-gui/src/main/resources/docs/manual/images/parametric_model_box_3.png diff --git a/docs/manual/images/parametric_model_box_4.png b/tetrad-gui/src/main/resources/docs/manual/images/parametric_model_box_4.png similarity index 100% rename from docs/manual/images/parametric_model_box_4.png rename to tetrad-gui/src/main/resources/docs/manual/images/parametric_model_box_4.png diff --git a/docs/manual/images/parametric_model_box_5.png b/tetrad-gui/src/main/resources/docs/manual/images/parametric_model_box_5.png similarity index 100% rename from docs/manual/images/parametric_model_box_5.png rename to tetrad-gui/src/main/resources/docs/manual/images/parametric_model_box_5.png diff --git a/docs/manual/images/parametric_model_box_6.png b/tetrad-gui/src/main/resources/docs/manual/images/parametric_model_box_6.png similarity index 100% rename from docs/manual/images/parametric_model_box_6.png rename to tetrad-gui/src/main/resources/docs/manual/images/parametric_model_box_6.png diff --git a/docs/manual/images/parametric_model_box_7.png b/tetrad-gui/src/main/resources/docs/manual/images/parametric_model_box_7.png similarity index 100% rename from docs/manual/images/parametric_model_box_7.png rename to tetrad-gui/src/main/resources/docs/manual/images/parametric_model_box_7.png diff --git a/docs/manual/images/parametric_model_box_8.png b/tetrad-gui/src/main/resources/docs/manual/images/parametric_model_box_8.png similarity index 100% rename from docs/manual/images/parametric_model_box_8.png rename to tetrad-gui/src/main/resources/docs/manual/images/parametric_model_box_8.png diff --git a/docs/manual/images/regression_box_1.png b/tetrad-gui/src/main/resources/docs/manual/images/regression_box_1.png similarity index 100% rename from docs/manual/images/regression_box_1.png rename to tetrad-gui/src/main/resources/docs/manual/images/regression_box_1.png diff --git a/docs/manual/images/regression_box_2.png b/tetrad-gui/src/main/resources/docs/manual/images/regression_box_2.png similarity index 100% rename from docs/manual/images/regression_box_2.png rename to tetrad-gui/src/main/resources/docs/manual/images/regression_box_2.png diff --git a/docs/manual/images/regression_box_3.png b/tetrad-gui/src/main/resources/docs/manual/images/regression_box_3.png similarity index 100% rename from docs/manual/images/regression_box_3.png rename to tetrad-gui/src/main/resources/docs/manual/images/regression_box_3.png diff --git a/docs/manual/images/search_box_1.png b/tetrad-gui/src/main/resources/docs/manual/images/search_box_1.png similarity index 100% rename from docs/manual/images/search_box_1.png rename to tetrad-gui/src/main/resources/docs/manual/images/search_box_1.png diff --git a/docs/manual/images/simulation_box_1.png b/tetrad-gui/src/main/resources/docs/manual/images/simulation_box_1.png similarity index 100% rename from docs/manual/images/simulation_box_1.png rename to tetrad-gui/src/main/resources/docs/manual/images/simulation_box_1.png diff --git a/docs/manual/images/updater_box_1.png b/tetrad-gui/src/main/resources/docs/manual/images/updater_box_1.png similarity index 100% rename from docs/manual/images/updater_box_1.png rename to tetrad-gui/src/main/resources/docs/manual/images/updater_box_1.png diff --git a/docs/manual/images/updater_box_10.png b/tetrad-gui/src/main/resources/docs/manual/images/updater_box_10.png similarity index 100% rename from docs/manual/images/updater_box_10.png rename to tetrad-gui/src/main/resources/docs/manual/images/updater_box_10.png diff --git a/docs/manual/images/updater_box_2.png b/tetrad-gui/src/main/resources/docs/manual/images/updater_box_2.png similarity index 100% rename from docs/manual/images/updater_box_2.png rename to tetrad-gui/src/main/resources/docs/manual/images/updater_box_2.png diff --git a/docs/manual/images/updater_box_3.png b/tetrad-gui/src/main/resources/docs/manual/images/updater_box_3.png similarity index 100% rename from docs/manual/images/updater_box_3.png rename to tetrad-gui/src/main/resources/docs/manual/images/updater_box_3.png diff --git a/docs/manual/images/updater_box_4.png b/tetrad-gui/src/main/resources/docs/manual/images/updater_box_4.png similarity index 100% rename from docs/manual/images/updater_box_4.png rename to tetrad-gui/src/main/resources/docs/manual/images/updater_box_4.png diff --git a/docs/manual/images/updater_box_5.png b/tetrad-gui/src/main/resources/docs/manual/images/updater_box_5.png similarity index 100% rename from docs/manual/images/updater_box_5.png rename to tetrad-gui/src/main/resources/docs/manual/images/updater_box_5.png diff --git a/docs/manual/images/updater_box_6.png b/tetrad-gui/src/main/resources/docs/manual/images/updater_box_6.png similarity index 100% rename from docs/manual/images/updater_box_6.png rename to tetrad-gui/src/main/resources/docs/manual/images/updater_box_6.png diff --git a/docs/manual/images/updater_box_7.png b/tetrad-gui/src/main/resources/docs/manual/images/updater_box_7.png similarity index 100% rename from docs/manual/images/updater_box_7.png rename to tetrad-gui/src/main/resources/docs/manual/images/updater_box_7.png diff --git a/docs/manual/images/updater_box_8.png b/tetrad-gui/src/main/resources/docs/manual/images/updater_box_8.png similarity index 100% rename from docs/manual/images/updater_box_8.png rename to tetrad-gui/src/main/resources/docs/manual/images/updater_box_8.png diff --git a/docs/manual/images/updater_box_9.png b/tetrad-gui/src/main/resources/docs/manual/images/updater_box_9.png similarity index 100% rename from docs/manual/images/updater_box_9.png rename to tetrad-gui/src/main/resources/docs/manual/images/updater_box_9.png diff --git a/docs/manual/index.html b/tetrad-gui/src/main/resources/docs/manual/index.html similarity index 100% rename from docs/manual/index.html rename to tetrad-gui/src/main/resources/docs/manual/index.html diff --git a/docs/notes/cfci.orientation.txt b/tetrad-gui/src/main/resources/docs/notes/cfci.orientation.txt similarity index 100% rename from docs/notes/cfci.orientation.txt rename to tetrad-gui/src/main/resources/docs/notes/cfci.orientation.txt diff --git a/docs/notes/cliques.txt b/tetrad-gui/src/main/resources/docs/notes/cliques.txt similarity index 100% rename from docs/notes/cliques.txt rename to tetrad-gui/src/main/resources/docs/notes/cliques.txt diff --git a/docs/notes/cmd.txt b/tetrad-gui/src/main/resources/docs/notes/cmd.txt similarity index 100% rename from docs/notes/cmd.txt rename to tetrad-gui/src/main/resources/docs/notes/cmd.txt diff --git a/docs/notes/images b/tetrad-gui/src/main/resources/docs/notes/images similarity index 100% rename from docs/notes/images rename to tetrad-gui/src/main/resources/docs/notes/images diff --git a/docs/notes/images.1 b/tetrad-gui/src/main/resources/docs/notes/images.1 similarity index 100% rename from docs/notes/images.1 rename to tetrad-gui/src/main/resources/docs/notes/images.1 diff --git a/docs/notes/pc.fci.in.r.spirtes.2.3.2010.txt b/tetrad-gui/src/main/resources/docs/notes/pc.fci.in.r.spirtes.2.3.2010.txt similarity index 100% rename from docs/notes/pc.fci.in.r.spirtes.2.3.2010.txt rename to tetrad-gui/src/main/resources/docs/notes/pc.fci.in.r.spirtes.2.3.2010.txt diff --git a/docs/notes/serialization_notes.txt b/tetrad-gui/src/main/resources/docs/notes/serialization_notes.txt similarity index 100% rename from docs/notes/serialization_notes.txt rename to tetrad-gui/src/main/resources/docs/notes/serialization_notes.txt diff --git a/docs/referenced_papers/Adjacency-submitted.pdf b/tetrad-gui/src/main/resources/docs/referenced_papers/Adjacency-submitted.pdf similarity index 100% rename from docs/referenced_papers/Adjacency-submitted.pdf rename to tetrad-gui/src/main/resources/docs/referenced_papers/Adjacency-submitted.pdf diff --git a/docs/referenced_papers/AmStat_review.pdf b/tetrad-gui/src/main/resources/docs/referenced_papers/AmStat_review.pdf similarity index 100% rename from docs/referenced_papers/AmStat_review.pdf rename to tetrad-gui/src/main/resources/docs/referenced_papers/AmStat_review.pdf diff --git a/docs/referenced_papers/Bollen_Ting_1993SociolMeth.pdf b/tetrad-gui/src/main/resources/docs/referenced_papers/Bollen_Ting_1993SociolMeth.pdf similarity index 100% rename from docs/referenced_papers/Bollen_Ting_1993SociolMeth.pdf rename to tetrad-gui/src/main/resources/docs/referenced_papers/Bollen_Ting_1993SociolMeth.pdf diff --git a/docs/referenced_papers/CAUSAL.PS b/tetrad-gui/src/main/resources/docs/referenced_papers/CAUSAL.PS similarity index 100% rename from docs/referenced_papers/CAUSAL.PS rename to tetrad-gui/src/main/resources/docs/referenced_papers/CAUSAL.PS diff --git a/docs/referenced_papers/CMU-ISRI-04-127.pdf b/tetrad-gui/src/main/resources/docs/referenced_papers/CMU-ISRI-04-127.pdf similarity index 100% rename from docs/referenced_papers/CMU-ISRI-04-127.pdf rename to tetrad-gui/src/main/resources/docs/referenced_papers/CMU-ISRI-04-127.pdf diff --git a/docs/referenced_papers/chickering02b.pdf b/tetrad-gui/src/main/resources/docs/referenced_papers/chickering02b.pdf similarity index 100% rename from docs/referenced_papers/chickering02b.pdf rename to tetrad-gui/src/main/resources/docs/referenced_papers/chickering02b.pdf diff --git a/docs/referenced_papers/con00random.pdf b/tetrad-gui/src/main/resources/docs/referenced_papers/con00random.pdf similarity index 100% rename from docs/referenced_papers/con00random.pdf rename to tetrad-gui/src/main/resources/docs/referenced_papers/con00random.pdf diff --git a/docs/referenced_papers/glasso.f90 b/tetrad-gui/src/main/resources/docs/referenced_papers/glasso.f90 similarity index 100% rename from docs/referenced_papers/glasso.f90 rename to tetrad-gui/src/main/resources/docs/referenced_papers/glasso.f90 diff --git a/docs/referenced_papers/hartiganwong.pdf b/tetrad-gui/src/main/resources/docs/referenced_papers/hartiganwong.pdf similarity index 100% rename from docs/referenced_papers/hartiganwong.pdf rename to tetrad-gui/src/main/resources/docs/referenced_papers/hartiganwong.pdf diff --git a/docs/referenced_papers/hawkins1989.pdf b/tetrad-gui/src/main/resources/docs/referenced_papers/hawkins1989.pdf similarity index 100% rename from docs/referenced_papers/hawkins1989.pdf rename to tetrad-gui/src/main/resources/docs/referenced_papers/hawkins1989.pdf diff --git a/docs/referenced_papers/jmlr06.pdf b/tetrad-gui/src/main/resources/docs/referenced_papers/jmlr06.pdf similarity index 100% rename from docs/referenced_papers/jmlr06.pdf rename to tetrad-gui/src/main/resources/docs/referenced_papers/jmlr06.pdf diff --git a/docs/referenced_papers/math_s5_v1_article-17.pdf b/tetrad-gui/src/main/resources/docs/referenced_papers/math_s5_v1_article-17.pdf similarity index 100% rename from docs/referenced_papers/math_s5_v1_article-17.pdf rename to tetrad-gui/src/main/resources/docs/referenced_papers/math_s5_v1_article-17.pdf diff --git a/docs/referenced_papers/optimal.pdf b/tetrad-gui/src/main/resources/docs/referenced_papers/optimal.pdf similarity index 100% rename from docs/referenced_papers/optimal.pdf rename to tetrad-gui/src/main/resources/docs/referenced_papers/optimal.pdf diff --git a/docs/referenced_papers/p313-grira.pdf b/tetrad-gui/src/main/resources/docs/referenced_papers/p313-grira.pdf similarity index 100% rename from docs/referenced_papers/p313-grira.pdf rename to tetrad-gui/src/main/resources/docs/referenced_papers/p313-grira.pdf diff --git a/docs/referenced_papers/splits.pdf b/tetrad-gui/src/main/resources/docs/referenced_papers/splits.pdf similarity index 100% rename from docs/referenced_papers/splits.pdf rename to tetrad-gui/src/main/resources/docs/referenced_papers/splits.pdf diff --git a/docs/referenced_papers/uaidiscovery.pdf b/tetrad-gui/src/main/resources/docs/referenced_papers/uaidiscovery.pdf similarity index 100% rename from docs/referenced_papers/uaidiscovery.pdf rename to tetrad-gui/src/main/resources/docs/referenced_papers/uaidiscovery.pdf diff --git a/tetrad-lib/pom.xml b/tetrad-lib/pom.xml index 682f91eae0..164de63a93 100644 --- a/tetrad-lib/pom.xml +++ b/tetrad-lib/pom.xml @@ -51,24 +51,24 @@ - - maven-antrun-plugin - 3.1.0 - - - compile - - run - - - - - - - - - + + + + + + + + + + + + + + + + + + diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/util/ParamDescriptions.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/util/ParamDescriptions.java index 923b68262d..a0b89568f8 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/util/ParamDescriptions.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/util/ParamDescriptions.java @@ -47,7 +47,7 @@ private ParamDescriptions() { )); // Read the copied maunal/index.html from within the jar - try (InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("manual/index.html")) { + try (InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("docs/manual/index.html")) { if (inputStream != null) { doc = Jsoup.parse(inputStream, "UTF-8", ""); } From 0e1aef45753aad53236ec52d759db78eac7f7006 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Mon, 11 Dec 2023 10:33:42 -0500 Subject: [PATCH 018/163] Fixing paths. --- .../java/edu/cmu/tetradapp/editor/DagEditor.java | 2 +- .../java/edu/cmu/tetradapp/editor/GraphEditor.java | 2 +- .../cmu/tetradapp/editor/GraphSelectionEditor.java | 2 +- .../edu/cmu/tetradapp/editor/SemGraphEditor.java | 2 +- .../cmu/tetradapp/editor/TimeLagGraphEditor.java | 2 +- .../edu/cmu/tetradapp/editor/search/GraphCard.java | 2 +- .../java/edu/cmu/tetradapp/util/ImageUtils.java | 2 +- .../src/main/resources/docs}/images/AddNodeDown.gif | Bin .../src/main/resources/docs}/images/AddNodeOff.gif | Bin .../src/main/resources/docs}/images/AddNodeRoll.gif | Bin .../src/main/resources/docs}/images/AddNodeUp.gif | Bin .../src/main/resources/docs}/images/Icon32a.png | Bin .../src/main/resources/docs}/images/TETRAD.gif | Bin .../src/main/resources/docs}/images/arrow-down.gif | Bin .../src/main/resources/docs}/images/arrow-left.gif | Bin .../src/main/resources/docs}/images/arrow-up.gif | Bin .../src/main/resources/docs}/images/bidirected2.gif | Bin .../src/main/resources/docs}/images/bidirected3.gif | Bin .../main/resources/docs}/images/bidirectedDown.gif | Bin .../main/resources/docs}/images/bidirectedOff.gif | Bin .../main/resources/docs}/images/bidirectedRoll.gif | Bin .../main/resources/docs}/images/bidirectedUp.gif | Bin .../main/resources/docs}/images/circulararrow.gif | Bin .../src/main/resources/docs}/images/cl/add.gif | Bin .../main/resources/docs}/images/cl/add_latent.gif | Bin .../main/resources/docs}/images/cl/bidirected3.gif | Bin .../main/resources/docs}/images/cl/blackedge.gif | Bin .../src/main/resources/docs}/images/cl/blank.gif | Bin .../src/main/resources/docs}/images/cl/blueedge.gif | Bin .../src/main/resources/docs}/images/cl/clAbout.gif | Bin .../src/main/resources/docs}/images/cl/clsplash.gif | Bin .../main/resources/docs}/images/cl/clsplashBAK.jpg | Bin .../main/resources/docs}/images/cl/clsplashV3_3.gif | Bin .../main/resources/docs}/images/cl/clsplashV4_0.gif | Bin .../main/resources/docs}/images/cl/correctGraph.gif | Bin .../main/resources/docs}/images/cl/directed3.gif | Bin .../src/main/resources/docs}/images/cl/eraser.gif | Bin .../src/main/resources/docs}/images/cl/essay.gif | Bin .../resources/docs}/images/cl/essay_disabled.gif | Bin .../main/resources/docs}/images/cl/expt_setup.gif | Bin .../resources/docs}/images/cl/expt_setup_active.gif | Bin .../resources/docs}/images/cl/expt_setup_down.gif | Bin .../resources/docs}/images/cl/expt_setup_over.gif | Bin .../docs}/images/cl/expt_setup_over_active.gif | Bin .../src/main/resources/docs}/images/cl/feedback.gif | Bin .../resources/docs}/images/cl/feedback_disabled.gif | Bin .../docs}/images/cl/guessedComboDependentIcon.gif | Bin .../resources/docs}/images/cl/guessedComboIcon.gif | Bin .../docs}/images/cl/guessedComboIndependentIcon.gif | Bin .../main/resources/docs}/images/cl/hiddenSign.gif | Bin .../main/resources/docs}/images/cl/hyp_graph.gif | Bin .../resources/docs}/images/cl/hyp_graph_active.gif | Bin .../resources/docs}/images/cl/hyp_graph_down.gif | Bin .../resources/docs}/images/cl/hyp_graph_over.gif | Bin .../resources/docs}/images/cl/hyp_manip_graph.gif | Bin .../docs}/images/cl/hyp_manip_graph_active.gif | Bin .../docs}/images/cl/hyp_manip_graph_down.gif | Bin .../docs}/images/cl/hyp_manip_graph_guess.gif | Bin .../docs}/images/cl/hyp_manip_graph_over.gif | Bin .../src/main/resources/docs}/images/cl/icon.gif | Bin .../src/main/resources/docs}/images/cl/ignored.gif | Bin .../main/resources/docs}/images/cl/ignored_gray.gif | Bin .../main/resources/docs}/images/cl/independent.gif | Bin .../main/resources/docs}/images/cl/invisible.gif | Bin .../src/main/resources/docs}/images/cl/latent3.gif | Bin .../src/main/resources/docs}/images/cl/lock.gif | Bin .../src/main/resources/docs}/images/cl/lock_new.gif | Bin .../main/resources/docs}/images/cl/lock_new2.gif | Bin .../src/main/resources/docs}/images/cl/move.gif | Bin .../src/main/resources/docs}/images/cl/move3.gif | Bin .../resources/docs}/images/cl/notIndependent.gif | Bin .../main/resources/docs}/images/cl/population.gif | Bin .../resources/docs}/images/cl/population_active.gif | Bin .../resources/docs}/images/cl/population_down.gif | Bin .../resources/docs}/images/cl/population_hidden.gif | Bin .../docs}/images/cl/population_hidden_active.gif | Bin .../docs}/images/cl/population_hidden_down.gif | Bin .../docs}/images/cl/population_hidden_over.gif | Bin .../resources/docs}/images/cl/population_over.gif | Bin .../src/main/resources/docs}/images/cl/predict.gif | Bin .../resources/docs}/images/cl/predict_active.gif | Bin .../main/resources/docs}/images/cl/predict_down.gif | Bin .../main/resources/docs}/images/cl/predict_over.gif | Bin .../src/main/resources/docs}/images/cl/random.gif | Bin .../main/resources/docs}/images/cl/random_new.gif | Bin .../main/resources/docs}/images/cl/random_new2.gif | Bin .../src/main/resources/docs}/images/cl/rededge.gif | Bin .../src/main/resources/docs}/images/cl/sample.gif | Bin .../resources/docs}/images/cl/sample_active.gif | Bin .../main/resources/docs}/images/cl/sample_down.gif | Bin .../main/resources/docs}/images/cl/sample_guess.gif | Bin .../main/resources/docs}/images/cl/sample_over.gif | Bin .../main/resources/docs}/images/cl/sample_valid.gif | Bin .../resources/docs}/images/cl/toolbar_checkans.gif | Bin .../docs}/images/cl/toolbar_checkans_disabled.gif | Bin .../resources/docs}/images/cl/toolbar_finances.gif | Bin .../docs}/images/cl/toolbar_finances_disabled.gif | Bin .../docs}/images/cl/toolbar_instruction.gif | Bin .../images/cl/toolbar_instruction_disabled.gif | Bin .../main/resources/docs}/images/cl/toolbar_save.gif | Bin .../docs}/images/cl/toolbar_save_disabled.gif | Bin .../resources/docs}/images/cl/toolbar_showans.gif | Bin .../docs}/images/cl/toolbar_showans_disabled.gif | Bin .../resources/docs}/images/cl/toolbar_submit.gif | Bin .../docs}/images/cl/toolbar_submit_disabled.gif | Bin .../main/resources/docs}/images/cl/true_graph.gif | Bin .../resources/docs}/images/cl/true_graph_active.gif | Bin .../resources/docs}/images/cl/true_graph_down.gif | Bin .../resources/docs}/images/cl/true_graph_hidden.gif | Bin .../docs}/images/cl/true_graph_hidden_active.gif | Bin .../docs}/images/cl/true_graph_hidden_down.gif | Bin .../docs}/images/cl/true_graph_hidden_over.gif | Bin .../resources/docs}/images/cl/true_graph_over.gif | Bin .../resources/docs}/images/cl/true_manip_graph.gif | Bin .../docs}/images/cl/true_manip_graph_active.gif | Bin .../docs}/images/cl/true_manip_graph_down.gif | Bin .../docs}/images/cl/true_manip_graph_hidden.gif | Bin .../images/cl/true_manip_graph_hidden_active.gif | Bin .../images/cl/true_manip_graph_hidden_down.gif | Bin .../images/cl/true_manip_graph_hidden_over.gif | Bin .../docs}/images/cl/true_manip_graph_over.gif | Bin .../main/resources/docs}/images/cl/variable3.gif | Bin .../src/main/resources/docs}/images/cl/visible.gif | Bin .../src/main/resources/docs}/images/cleanupDown.gif | Bin .../src/main/resources/docs}/images/cleanupOff.gif | Bin .../src/main/resources/docs}/images/cleanupRoll.gif | Bin .../src/main/resources/docs}/images/cleanupUp.gif | Bin .../src/main/resources/docs}/images/clear.png | Bin .../resources/docs}/images/clearVariableDown.gif | Bin .../resources/docs}/images/clearVariableOff.gif | Bin .../resources/docs}/images/clearVariableRoll.gif | Bin .../main/resources/docs}/images/clearVariableUp.gif | Bin .../main/resources/docs}/images/clearedgesDown.gif | Bin .../main/resources/docs}/images/clearedgesOff.gif | Bin .../main/resources/docs}/images/clearedgesRoll.gif | Bin .../main/resources/docs}/images/clearedgesUp.gif | Bin .../main/resources/docs}/images/cleargraphDown.gif | Bin .../main/resources/docs}/images/cleargraphOff.gif | Bin .../main/resources/docs}/images/cleargraphRoll.gif | Bin .../main/resources/docs}/images/cleargraphUp.gif | Bin .../src/main/resources/docs}/images/close.png | Bin .../src/main/resources/docs}/images/compareDown.gif | Bin .../src/main/resources/docs}/images/compareIcon.gif | Bin .../src/main/resources/docs}/images/compareOff.gif | Bin .../src/main/resources/docs}/images/compareRoll.gif | Bin .../src/main/resources/docs}/images/compareUp.gif | Bin .../src/main/resources/docs}/images/dataDown.gif | Bin .../src/main/resources/docs}/images/dataIcon.gif | Bin .../src/main/resources/docs}/images/dataOff.gif | Bin .../src/main/resources/docs}/images/dataRoll.gif | Bin .../src/main/resources/docs}/images/dataUp.gif | Bin .../src/main/resources/docs}/images/directDown.gif | Bin .../src/main/resources/docs}/images/directOff.gif | Bin .../src/main/resources/docs}/images/directRoll.gif | Bin .../src/main/resources/docs}/images/directUp.gif | Bin .../src/main/resources/docs}/images/directed2.gif | Bin .../src/main/resources/docs}/images/directed3.gif | Bin .../main/resources/docs}/images/directedDown.gif | Bin .../src/main/resources/docs}/images/directedOff.gif | Bin .../main/resources/docs}/images/directedRoll.gif | Bin .../src/main/resources/docs}/images/directedUp.gif | Bin .../main/resources/docs}/images/estimatorDown.gif | Bin .../main/resources/docs}/images/estimatorIcon.gif | Bin .../main/resources/docs}/images/estimatorOff.gif | Bin .../main/resources/docs}/images/estimatorRoll.gif | Bin .../src/main/resources/docs}/images/estimatorUp.gif | Bin .../src/main/resources/docs}/images/fileDown.gif | Bin .../src/main/resources/docs}/images/fileOff.gif | Bin .../src/main/resources/docs}/images/fileRoll.gif | Bin .../src/main/resources/docs}/images/fileUp.gif | Bin .../src/main/resources/docs}/images/flow.gif | Bin .../src/main/resources/docs}/images/flowDown.gif | Bin .../src/main/resources/docs}/images/flowOff.gif | Bin .../src/main/resources/docs}/images/flowRoll.gif | Bin .../src/main/resources/docs}/images/flowUp.gif | Bin .../main/resources/docs}/images/graduation_hat1.png | Bin .../src/main/resources/docs}/images/graphDown.gif | Bin .../src/main/resources/docs}/images/graphIcon.gif | Bin .../src/main/resources/docs}/images/graphOff.gif | Bin .../src/main/resources/docs}/images/graphRoll.gif | Bin .../src/main/resources/docs}/images/graphUp.gif | Bin .../src/main/resources/docs}/images/ico1.gif | Bin .../src/main/resources/docs}/images/icontry2.gif | Bin .../src/main/resources/docs}/images/imDown.gif | Bin .../src/main/resources/docs}/images/imIcon.gif | Bin .../src/main/resources/docs}/images/imOff.gif | Bin .../src/main/resources/docs}/images/imRoll.gif | Bin .../src/main/resources/docs}/images/imUp.gif | Bin .../src/main/resources/docs}/images/info.png | Bin .../resources/docs}/images/information-icon.png | Bin .../resources/docs}/images/information_small.png | Bin .../docs}/images/information_small_white.png | Bin .../src/main/resources/docs}/images/knowDown.gif | Bin .../src/main/resources/docs}/images/knowIcon.gif | Bin .../src/main/resources/docs}/images/knowOff.gif | Bin .../src/main/resources/docs}/images/knowRoll.gif | Bin .../src/main/resources/docs}/images/knowUp.gif | Bin .../src/main/resources/docs}/images/latent2.gif | Bin .../src/main/resources/docs}/images/latent3.gif | Bin .../src/main/resources/docs}/images/latentDown.gif | Bin .../src/main/resources/docs}/images/latentOff.gif | Bin .../src/main/resources/docs}/images/latentRoll.gif | Bin .../src/main/resources/docs}/images/latentUp.gif | Bin .../src/main/resources/docs}/images/miscB62.gif | Bin .../src/main/resources/docs}/images/move.gif | Bin .../src/main/resources/docs}/images/move2.gif | Bin .../src/main/resources/docs}/images/move3.gif | Bin .../src/main/resources/docs}/images/moveDown.gif | Bin .../src/main/resources/docs}/images/moveOff.gif | Bin .../src/main/resources/docs}/images/moveRoll.gif | Bin .../src/main/resources/docs}/images/moveUp.gif | Bin .../main/resources/docs}/images/nondirected2.gif | Bin .../main/resources/docs}/images/nondirected3.gif | Bin .../main/resources/docs}/images/nondirectedDown.gif | Bin .../main/resources/docs}/images/nondirectedOff.gif | Bin .../main/resources/docs}/images/nondirectedRoll.gif | Bin .../main/resources/docs}/images/nondirectedUp.gif | Bin .../src/main/resources/docs}/images/note.png | Bin .../resources/docs}/images/partiallyoriented2.gif | Bin .../resources/docs}/images/partiallyoriented3.gif | Bin .../docs}/images/partiallyorientedDown.gif | Bin .../resources/docs}/images/partiallyorientedOff.gif | Bin .../docs}/images/partiallyorientedRoll.gif | Bin .../resources/docs}/images/partiallyorientedUp.gif | Bin .../src/main/resources/docs}/images/pmDown.gif | Bin .../src/main/resources/docs}/images/pmIcon.gif | Bin .../src/main/resources/docs}/images/pmOff.gif | Bin .../src/main/resources/docs}/images/pmRoll.gif | Bin .../src/main/resources/docs}/images/pmUp.gif | Bin .../src/main/resources/docs}/images/randomDown.gif | Bin .../src/main/resources/docs}/images/randomIcon.gif | Bin .../src/main/resources/docs}/images/randomOff.gif | Bin .../src/main/resources/docs}/images/randomRoll.gif | Bin .../src/main/resources/docs}/images/randomUp.gif | Bin .../src/main/resources/docs}/images/repeatDown.gif | Bin .../src/main/resources/docs}/images/repeatOff.gif | Bin .../src/main/resources/docs}/images/repeatRoll.gif | Bin .../src/main/resources/docs}/images/repeatUp.gif | Bin .../src/main/resources/docs}/images/save.png | Bin .../src/main/resources/docs}/images/searchDown.gif | Bin .../src/main/resources/docs}/images/searchIcon.gif | Bin .../src/main/resources/docs}/images/searchOff.gif | Bin .../src/main/resources/docs}/images/searchRoll.gif | Bin .../src/main/resources/docs}/images/searchUp.gif | Bin .../resources/docs}/images/smallbidirectedDown.gif | Bin .../resources/docs}/images/smallbidirectedOff.gif | Bin .../resources/docs}/images/smallbidirectedRoll.gif | Bin .../resources/docs}/images/smallbidirectedUp.gif | Bin .../resources/docs}/images/smalldirectedDown.gif | Bin .../resources/docs}/images/smalldirectedOff.gif | Bin .../resources/docs}/images/smalldirectedRoll.gif | Bin .../main/resources/docs}/images/smalldirectedUp.gif | Bin .../docs}/images/smallhalfdirectedDown.gif | Bin .../resources/docs}/images/smallhalfdirectedOff.gif | Bin .../docs}/images/smallhalfdirectedRoll.gif | Bin .../resources/docs}/images/smallhalfdirectedUp.gif | Bin .../resources/docs}/images/smallundirectedDown.gif | Bin .../resources/docs}/images/smallundirectedOff.gif | Bin .../resources/docs}/images/smallundirectedRoll.gif | Bin .../resources/docs}/images/smallundirectedUp.gif | Bin .../resources/docs}/images/smallunorientedDown.gif | Bin .../resources/docs}/images/smallunorientedOff.gif | Bin .../resources/docs}/images/smallunorientedRoll.gif | Bin .../resources/docs}/images/smallunorientedUp.gif | Bin .../main/resources/docs}/images/system_info.html | 0 .../main/resources/docs}/images/system_info_alt.png | Bin .../src/main/resources/docs}/images/tableDown.gif | Bin .../src/main/resources/docs}/images/tableOff.gif | Bin .../src/main/resources/docs}/images/tableRoll.gif | Bin .../src/main/resources/docs}/images/tableUp.gif | Bin .../src/main/resources/docs}/images/tetradicon.gif | Bin .../main/resources/docs}/images/three_arrows.gif | Bin .../main/resources/docs}/images/three_circles.gif | Bin .../resources/docs}/images/toolbar_get_info.png | Bin .../src/main/resources/docs}/images/tyler16.png | Bin .../src/main/resources/docs}/images/tyler32.png | Bin .../src/main/resources/docs}/images/undirected3.gif | Bin .../main/resources/docs}/images/undirectedDown.gif | Bin .../main/resources/docs}/images/undirectedOff.gif | Bin .../main/resources/docs}/images/undirectedRoll.gif | Bin .../main/resources/docs}/images/undirectedUp.gif | Bin .../main/resources/docs}/images/unorientedUp.gif | Bin .../src/main/resources/docs}/images/updaterDown.gif | Bin .../src/main/resources/docs}/images/updaterIcon.gif | Bin .../src/main/resources/docs}/images/updaterOff.gif | Bin .../src/main/resources/docs}/images/updaterRoll.gif | Bin .../src/main/resources/docs}/images/updaterUp.gif | Bin .../src/main/resources/docs}/images/variable2.gif | Bin .../src/main/resources/docs}/images/variable3.gif | Bin .../main/resources/docs}/images/variableDown.gif | Bin .../src/main/resources/docs}/images/variableOff.gif | Bin .../main/resources/docs}/images/variableRoll.gif | Bin .../src/main/resources/docs}/images/variableUp.gif | Bin .../src/main/resources/docs}/images/zoomDown.gif | Bin .../src/main/resources/docs}/images/zoomOff.gif | Bin .../src/main/resources/docs}/images/zoomRoll.gif | Bin .../src/main/resources/docs}/images/zoomUp.gif | Bin .../src/main/resources/docs}/javahelp/Map.jhm | 0 .../src/main/resources/docs}/javahelp/TetradHelp.hs | 0 .../resources/docs}/javahelp/TetradHelpIndex.xml | 0 .../main/resources/docs}/javahelp/TetradHelpTOC.xml | 0 .../manual/boxes/classify/classify_box.html | 0 .../javahelp/manual/boxes/compare/compare_box.html | 0 .../docs}/javahelp/manual/boxes/data/data_box.html | 0 .../javahelp/manual/boxes/data/data_loader.html | 0 .../javahelp/manual/boxes/data/data_set_list.html | 0 .../javahelp/manual/boxes/each_box_explained.html | 0 .../manual/boxes/each_module_explained.html | 0 .../manual/boxes/estimate/dirichlet_estimator.html | 0 .../manual/boxes/estimate/estimate_box.html | 0 .../manual/boxes/estimate/ml_bayes_estimator.html | 0 .../manual/boxes/estimate/sem_estimator.html | 0 .../docs}/javahelp/manual/boxes/graph/dag.html | 0 .../javahelp/manual/boxes/graph/general_graph.html | 0 .../javahelp/manual/boxes/graph/graph_box.html | 0 .../javahelp/manual/boxes/graph/sem_graph.html | 0 .../javahelp/manual/boxes/graph/time_graph.html | 0 .../docs}/javahelp/manual/boxes/im/bayes_im.html | 0 .../manual/boxes/im/dirichlet_bayes_im.html | 0 .../docs}/javahelp/manual/boxes/im/im_box.html | 0 .../docs}/javahelp/manual/boxes/im/sem_im.html | 0 .../manual/boxes/manipulated_data/manipulated2.html | 0 .../manual/boxes/manipulated_data/manipulated3.html | 0 .../manipulated_data/manipulated_data_box.html | 0 .../docs}/javahelp/manual/boxes/pm/bayes_pm.html | 0 .../docs}/javahelp/manual/boxes/pm/pm_box.html | 0 .../docs}/javahelp/manual/boxes/pm/sem_pm.html | 0 .../boxes/regression/logistic_regression.html | 0 .../regression/multiple_linear_regression.html | 0 .../manual/boxes/regression/regression_box.html | 0 .../docs}/javahelp/manual/boxes/search/bdeu.html | 0 .../docs}/javahelp/manual/boxes/search/bpc.html | 0 .../docs}/javahelp/manual/boxes/search/ccd.html | 0 .../docs}/javahelp/manual/boxes/search/cfci.html | 0 .../javahelp/manual/boxes/search/chisquare.html | 0 .../boxes/search/conditional_correlation.html | 0 .../boxes/search/conditional_gaussian_bic.html | 0 .../boxes/search/conditional_gaussian_lrt.html | 0 .../docs}/javahelp/manual/boxes/search/cpc.html | 0 .../docs}/javahelp/manual/boxes/search/cpcs.html | 0 .../javahelp/manual/boxes/search/d_separation.html | 0 .../javahelp/manual/boxes/search/discrete_bic.html | 0 .../docs}/javahelp/manual/boxes/search/eb.html | 0 .../docs}/javahelp/manual/boxes/search/fas.html | 0 .../docs}/javahelp/manual/boxes/search/fci.html | 0 .../javahelp/manual/boxes/search/fisher_z.html | 0 .../docs}/javahelp/manual/boxes/search/gccd.html | 0 .../docs}/javahelp/manual/boxes/search/gfci.html | 0 .../docs}/javahelp/manual/boxes/search/glasso.html | 0 .../docs}/javahelp/manual/boxes/search/gsquare.html | 0 .../docs}/javahelp/manual/boxes/search/images.html | 0 .../docs}/javahelp/manual/boxes/search/lingam.html | 0 .../docs}/javahelp/manual/boxes/search/mbfs.html | 0 .../docs}/javahelp/manual/boxes/search/mgm.html | 0 .../javahelp/manual/boxes/search/mimbuild.html | 0 .../docs}/javahelp/manual/boxes/search/pc.html | 0 .../docs}/javahelp/manual/boxes/search/pcd.html | 0 .../docs}/javahelp/manual/boxes/search/pclocal.html | 0 .../docs}/javahelp/manual/boxes/search/pcmax.html | 0 .../javahelp/manual/boxes/search/pcmaxlocal.html | 0 .../docs}/javahelp/manual/boxes/search/pcs.html | 0 .../docs}/javahelp/manual/boxes/search/purify.html | 0 .../docs}/javahelp/manual/boxes/search/r1.html | 0 .../docs}/javahelp/manual/boxes/search/r2.html | 0 .../docs}/javahelp/manual/boxes/search/r3.html | 0 .../docs}/javahelp/manual/boxes/search/r4.html | 0 .../docs}/javahelp/manual/boxes/search/rfci.html | 0 .../docs}/javahelp/manual/boxes/search/rskew.html | 0 .../docs}/javahelp/manual/boxes/search/rskewe.html | 0 .../javahelp/manual/boxes/search/search_box.html | 0 .../docs}/javahelp/manual/boxes/search/sem_bic.html | 0 .../docs}/javahelp/manual/boxes/search/skew.html | 0 .../docs}/javahelp/manual/boxes/search/skewe.html | 0 .../docs}/javahelp/manual/boxes/search/svarfci.html | 0 .../docs}/javahelp/manual/boxes/search/tsgfci.html | 0 .../javahelp/manual/boxes/search/tsimages.html | 0 .../manual/boxes/search/types_of_algorithms.html | 0 .../docs}/javahelp/manual/boxes/search/wfges.html | 0 .../manual/boxes/update/approximate_updater.html | 0 .../manual/boxes/update/cpt_invariant_updater.html | 0 .../manual/boxes/update/row_summing_updater.html | 0 .../javahelp/manual/boxes/update/update_box.html | 0 .../javahelp/manual/common_tasks/common_tasks.html | 0 .../continuous_and_discrete_variables.html | 0 .../manual/common_tasks/copying_and_pasting.html | 0 .../common_tasks/creating_data_from_scratch.html | 0 .../common_tasks/defining_discrete_variables.html | 0 .../manual/common_tasks/destroying_models.html | 0 .../manual/common_tasks/discretizing_data.html | 0 .../common_tasks/edge_orientation_shortcuts.html | 0 .../common_tasks/editing_covariance_matrices.html | 0 .../manual/common_tasks/editing_knowledge.html | 0 .../common_tasks/editing_node_properties.html | 0 .../manual/common_tasks/editing_tabular_data.html | 0 .../manual/common_tasks/exiting_tetrad.html | 0 .../manual/common_tasks/generating_random_dags.html | 0 .../manual/common_tasks/handling_missing_data.html | 0 .../common_tasks/loading_covariance_matrices.html | 0 .../javahelp/manual/common_tasks/loading_data.html | 0 .../manual/common_tasks/loading_tabular_data.html | 0 .../manual/common_tasks/manipulating_data.html | 0 .../manual/common_tasks/opening_sessions.html | 0 .../manual/common_tasks/saving_screenshots.html | 0 .../manual/common_tasks/saving_sessions.html | 0 .../common_tasks/selecting_groups_of_nodes.html | 0 .../manual/common_tasks/simulating_data.html | 0 .../manual/common_tasks/simulating_data_bayes.html | 0 .../manual/common_tasks/simulating_data_glass.html | 0 .../manual/common_tasks/simulating_data_sem.html | 0 .../manual/common_tasks/tabular_data_sets.html | 0 .../manual/common_tasks/taking_screenshots.html | 0 .../transferring_data_from_other_programs.html | 0 .../common_tasks/transferring_from_excel.html | 0 .../common_tasks/transferring_from_minitab.html | 0 .../manual/common_tasks/using_popup_menus.html | 0 .../manual/common_tasks/using_templates.html | 0 .../javahelp/manual/definitions/definitions.html | 0 .../definitions/measured_latent_variables.html | 0 .../definitions/measurement_structural_graph.html | 0 .../manual/definitions/tetrad_graph_types.html | 0 .../docs}/javahelp/manual/for_further_help.html | 0 .../docs}/javahelp/manual/genetics/genetics.html | 0 .../javahelp/manual/genetics/genetics_old.html | 0 .../docs}/javahelp/manual/graph_edge_types.html | 0 .../docs}/javahelp/manual/images/PMimage.jpg | Bin .../docs}/javahelp/manual/images/Thumbs.db | Bin .../docs}/javahelp/manual/images/UBayescsopy.jpg | Bin .../docs}/javahelp/manual/images/UBaysesIMcopy.jpg | Bin .../docs}/javahelp/manual/images/UComparseimage.jpg | Bin .../docs}/javahelp/manual/images/UIMSEM.jpg | Bin .../docs}/javahelp/manual/images/UIMedcopy.jpg | Bin .../docs}/javahelp/manual/images/UIMimagecopy.jpg | Bin .../resources/docs}/javahelp/manual/images/UPM.jpg | Bin .../javahelp/manual/images/UcompsarePCcopy.jpg | Bin .../docs}/javahelp/manual/images/Ucompsaresheet.jpg | Bin .../docs}/javahelp/manual/images/Ucontsdata.jpg | Bin .../docs}/javahelp/manual/images/Udastasingle.jpg | Bin .../docs}/javahelp/manual/images/Udatsa.jpg | Bin .../docs}/javahelp/manual/images/Uestimsate.jpg | Bin .../docs}/javahelp/manual/images/Uexpsanded.jpg | Bin .../docs}/javahelp/manual/images/Uimportcopy.jpg | Bin .../docs}/javahelp/manual/images/Uimtablecopy.jpg | Bin .../docs}/javahelp/manual/images/UntitiledsROC.jpg | Bin .../javahelp/manual/images/Untitled2Cslassify.jpg | Bin .../manual/images/UntitledClasssifyResult.jpg | Bin .../manual/images/UntitledClsassifyWindow.jpg | Bin .../javahelp/manual/images/UntitledPsseudocount.jpg | Bin .../manual/images/UntitledSsearchImagecopy.jpg | Bin .../javahelp/manual/images/UntitledsGraphSearch.jpg | Bin .../javahelp/manual/images/Untitledupdaterbox.jpg | Bin .../resources/docs}/javahelp/manual/images/Uran.jpg | Bin .../docs}/javahelp/manual/images/Utime.jpg | Bin .../docs}/javahelp/manual/images/arrow_button.gif | Bin .../docs}/javahelp/manual/images/arrow_tool.gif | Bin .../javahelp/manual/images/bayes_im_schema.png | Bin .../javahelp/manual/images/bayes_pm_schema.png | Bin .../docs}/javahelp/manual/images/bayesim1.gif | Bin .../docs}/javahelp/manual/images/bayesim2.gif | Bin .../docs}/javahelp/manual/images/bayesim3.gif | Bin .../docs}/javahelp/manual/images/bayesim4.gif | Bin .../docs}/javahelp/manual/images/bayesim5.gif | Bin .../docs}/javahelp/manual/images/bayesim6.gif | Bin .../docs}/javahelp/manual/images/bayesim7.gif | Bin .../docs}/javahelp/manual/images/bayespm1.gif | Bin .../docs}/javahelp/manual/images/bayespm2.gif | Bin .../docs}/javahelp/manual/images/bayespm3.gif | Bin .../docs}/javahelp/manual/images/bayespm4.gif | Bin .../docs}/javahelp/manual/images/bayespm5.gif | Bin .../docs}/javahelp/manual/images/bidirectedEdge.png | Bin .../manual/images/calvin_hobbes_instructions.gif | Bin .../docs}/javahelp/manual/images/choose_data.png | Bin .../javahelp/manual/images/choose_load_data.png | Bin .../javahelp/manual/images/classify_button.gif | Bin .../javahelp/manual/images/classify_highlight.gif | Bin .../javahelp/manual/images/click_done_data.png | Bin .../docs}/javahelp/manual/images/click_load.png | Bin .../docs}/javahelp/manual/images/cluster1.png | Bin .../docs}/javahelp/manual/images/cluster2.png | Bin .../docs}/javahelp/manual/images/compare_button.gif | Bin .../manual/images/consructing_sessions1.gif | Bin .../manual/images/consructing_sessions2.gif | Bin .../manual/images/consructing_sessions3.gif | Bin .../manual/images/consructing_sessions4.gif | Bin .../manual/images/consructing_sessions5.gif | Bin .../manual/images/consructing_sessions6.gif | Bin .../manual/images/consructing_sessions7.gif | Bin .../docs}/javahelp/manual/images/copying1.gif | Bin .../docs}/javahelp/manual/images/copying2.gif | Bin .../docs}/javahelp/manual/images/copying3.gif | Bin .../docs}/javahelp/manual/images/copying4.gif | Bin .../docs}/javahelp/manual/images/createBayesNet.jpg | Bin .../docs}/javahelp/manual/images/dag_editor.png | Bin .../docs}/javahelp/manual/images/dag_from_data.gif | Bin .../docs}/javahelp/manual/images/dag_from_data2.gif | Bin .../javahelp/manual/images/dag_graph_image.png | Bin .../javahelp/manual/images/dageditorwindow.gif | Bin .../docs}/javahelp/manual/images/data_button.gif | Bin .../docs}/javahelp/manual/images/data_highlight.gif | Bin .../docs}/javahelp/manual/images/data_loader_1.PNG | Bin .../docs}/javahelp/manual/images/data_loader_2.PNG | Bin .../docs}/javahelp/manual/images/data_loader_3.PNG | Bin .../docs}/javahelp/manual/images/data_loader_4.PNG | Bin .../docs}/javahelp/manual/images/data_loader_5.PNG | Bin .../docs}/javahelp/manual/images/data_loader_6.PNG | Bin .../manual/images/data_standatalone_highlight.gif | Bin .../docs}/javahelp/manual/images/databox1.gif | Bin .../docs}/javahelp/manual/images/databox2.gif | Bin .../docs}/javahelp/manual/images/databox3.gif | Bin .../docs}/javahelp/manual/images/databox4.gif | Bin .../docs}/javahelp/manual/images/dataloader1.gif | Bin .../docs}/javahelp/manual/images/dataloader2.gif | Bin .../docs}/javahelp/manual/images/dataloader3.gif | Bin .../docs}/javahelp/manual/images/dataloader4.gif | Bin .../docs}/javahelp/manual/images/dataloader4.jpg | Bin .../docs}/javahelp/manual/images/dataset_schema.png | Bin .../javahelp/manual/images/defineSampleSize.jpg | Bin .../docs}/javahelp/manual/images/directedEdge.png | Bin .../javahelp/manual/images/dirichletbayesim1.gif | Bin .../javahelp/manual/images/dirichletbayesim2.gif | Bin .../javahelp/manual/images/dirichletbayesim3.gif | Bin .../javahelp/manual/images/dirichletbayesim4.gif | Bin .../javahelp/manual/images/dirichletbayesim5.gif | Bin .../javahelp/manual/images/dirichletbayesim6.gif | Bin .../javahelp/manual/images/dirichletbayesim7.gif | Bin .../javahelp/manual/images/discretization1.gif | Bin .../javahelp/manual/images/discretization2.gif | Bin .../javahelp/manual/images/discretization3.gif | Bin .../javahelp/manual/images/discretization4.gif | Bin .../javahelp/manual/images/discretization5.gif | Bin .../javahelp/manual/images/discretization6.gif | Bin .../manual/images/edge_orientation_shortcuts1.gif | Bin .../manual/images/edge_orientation_shortcuts2.gif | Bin .../manual/images/edge_orientation_shortcuts3.gif | Bin .../manual/images/edge_orientation_shortcuts4.gif | Bin .../docs}/javahelp/manual/images/edit_menu.png | Bin .../docs}/javahelp/manual/images/editing_data1.gif | Bin .../docs}/javahelp/manual/images/editing_data2.gif | Bin .../docs}/javahelp/manual/images/editing_data3.gif | Bin .../docs}/javahelp/manual/images/editing_data4.gif | Bin .../javahelp/manual/images/editing_knowledge1.gif | Bin .../javahelp/manual/images/editing_knowledge2.gif | Bin .../javahelp/manual/images/editing_knowledge3.gif | Bin .../javahelp/manual/images/editing_knowledge4.gif | Bin .../javahelp/manual/images/editing_knowledge5.gif | Bin .../javahelp/manual/images/editing_knowledge6.gif | Bin .../docs}/javahelp/manual/images/editing_nodes1.gif | Bin .../docs}/javahelp/manual/images/editing_nodes2.gif | Bin .../docs}/javahelp/manual/images/editing_nodes3.gif | Bin .../javahelp/manual/images/estimator_button.gif | Bin .../manual/images/example_workflow_schema.png | Bin .../docs}/javahelp/manual/images/file_menu.png | Bin .../manual/images/flowchart_dependencies1.gif | Bin .../manual/images/flowchart_dependencies2.gif | Bin .../javahelp/manual/images/flowcharterButton.jpg | Bin .../manual/images/generalgrapheditorwindow.gif | Bin .../docs}/javahelp/manual/images/generateData.jpg | Bin .../resources/docs}/javahelp/manual/images/ges1.png | Bin .../docs}/javahelp/manual/images/graph1.gif | Bin .../docs}/javahelp/manual/images/graph1_to_pm1.gif | Bin .../docs}/javahelp/manual/images/graph1choices.gif | Bin .../javahelp/manual/images/graph1editorwindow.gif | Bin .../manual/images/graph1structureeditor.gif | Bin .../javahelp/manual/images/graph2editorwindow.gif | Bin .../manual/images/graph2structureeditor.gif | Bin .../docs}/javahelp/manual/images/graphButton.jpg | Bin .../docs}/javahelp/manual/images/graphEditor.jpg | Bin .../docs}/javahelp/manual/images/graphWindow.gif | Bin .../docs}/javahelp/manual/images/graph_button.gif | Bin .../javahelp/manual/images/graph_gen_schema.png | Bin .../javahelp/manual/images/graph_highlight.gif | Bin .../docs}/javahelp/manual/images/graph_schema.png | Bin .../docs}/javahelp/manual/images/help_menu.png | Bin .../docs}/javahelp/manual/images/im_button.gif | Bin .../docs}/javahelp/manual/images/im_highlight.gif | Bin .../docs}/javahelp/manual/images/images.png | Bin .../manual/images/instantiatedModelButton.jpg | Bin .../javahelp/manual/images/instantiatedWindow.jpg | Bin .../docs}/javahelp/manual/images/knowledge1.png | Bin .../docs}/javahelp/manual/images/knowledge2.png | Bin .../docs}/javahelp/manual/images/knowledge3.png | Bin .../docs}/javahelp/manual/images/knowledge4.png | Bin .../javahelp/manual/images/knowledge_button.png | Bin .../javahelp/manual/images/knowledge_schema.png | Bin .../docs}/javahelp/manual/images/loading_data1.gif | Bin .../docs}/javahelp/manual/images/loading_data2.gif | Bin .../docs}/javahelp/manual/images/loading_data3.gif | Bin .../docs}/javahelp/manual/images/logging_menu.png | Bin .../docs}/javahelp/manual/images/main_menu.png | Bin .../docs}/javahelp/manual/images/main_workbench.gif | Bin .../javahelp/manual/images/main_workbench2.gif | Bin .../javahelp/manual/images/main_workbench2.png | Bin .../javahelp/manual/images/main_workbench3.gif | Bin .../javahelp/manual/images/main_workbench3.png | Bin .../javahelp/manual/images/main_workbench4.gif | Bin .../docs}/javahelp/manual/images/main_workspace.png | Bin .../javahelp/manual/images/manipulatedButton.jpg | Bin .../javahelp/manual/images/manipulatedData.jpg | Bin .../manual/images/manipulated_data_button.gif | Bin .../manual/images/manipulated_highlight.gif | Bin .../javahelp/manual/images/measured_vs_latent1.gif | Bin .../javahelp/manual/images/measured_vs_latent2.gif | Bin .../docs}/javahelp/manual/images/menubar.png | Bin .../docs}/javahelp/manual/images/mimbuild1.png | Bin .../docs}/javahelp/manual/images/mimbuild3.png | Bin .../docs}/javahelp/manual/images/mimbuild4.png | Bin .../docs}/javahelp/manual/images/objects.png | Bin .../manual/images/parametric_model_button.jpg | Bin .../docs}/javahelp/manual/images/pc_output.png | Bin .../docs}/javahelp/manual/images/pcsearch1.png | Bin .../docs}/javahelp/manual/images/pcsearch2.png | Bin .../docs}/javahelp/manual/images/pcsearch3.png | Bin .../javahelp/manual/images/pcsearch_dialog.png | Bin .../docs}/javahelp/manual/images/place_data_box.png | Bin .../docs}/javahelp/manual/images/pm_button.gif | Bin .../docs}/javahelp/manual/images/pm_highlight.gif | Bin .../docs}/javahelp/manual/images/pm_image.gif | Bin .../docs}/javahelp/manual/images/purify1.png | Bin .../docs}/javahelp/manual/images/purify2.png | Bin .../docs}/javahelp/manual/images/purify3.png | Bin .../docs}/javahelp/manual/images/purify4.png | Bin .../docs}/javahelp/manual/images/red_x.gif | Bin .../javahelp/manual/images/regression_button.gif | Bin .../javahelp/manual/images/regression_highlight.gif | Bin .../docs}/javahelp/manual/images/rubberband1.gif | Bin .../docs}/javahelp/manual/images/rubberband2.gif | Bin .../docs}/javahelp/manual/images/save_data.png | Bin .../javahelp/manual/images/searchCsreation.png | Bin .../docs}/javahelp/manual/images/search_box.png | Bin .../docs}/javahelp/manual/images/search_button.gif | Bin .../docs}/javahelp/manual/images/search_done.png | Bin .../manual/images/search_from_data_highlight.gif | Bin .../manual/images/search_from_graph_highlight.gif | Bin .../docs}/javahelp/manual/images/search_params.png | Bin .../docs}/javahelp/manual/images/search_schema.png | Bin .../docs}/javahelp/manual/images/searcsreation.png | Bin .../javahelp/manual/images/select_move_button.gif | Bin .../docs}/javahelp/manual/images/sem_graph1.gif | Bin .../docs}/javahelp/manual/images/sem_graph2.gif | Bin .../docs}/javahelp/manual/images/sem_graph3.gif | Bin .../docs}/javahelp/manual/images/sem_im_schema.png | Bin .../docs}/javahelp/manual/images/sem_pm_schema.png | Bin .../docs}/javahelp/manual/images/semim1.gif | Bin .../docs}/javahelp/manual/images/semim2.gif | Bin .../docs}/javahelp/manual/images/semim3.gif | Bin .../docs}/javahelp/manual/images/semim4.gif | Bin .../docs}/javahelp/manual/images/semim5.gif | Bin .../docs}/javahelp/manual/images/semim6.gif | Bin .../docs}/javahelp/manual/images/semim7.gif | Bin .../docs}/javahelp/manual/images/semim8.gif | Bin .../docs}/javahelp/manual/images/sempm1.gif | Bin .../docs}/javahelp/manual/images/sempm2.gif | Bin .../docs}/javahelp/manual/images/sempm3.gif | Bin .../docs}/javahelp/manual/images/sempm4.gif | Bin .../docs}/javahelp/manual/images/sempm5.gif | Bin .../docs}/javahelp/manual/images/sempm6.gif | Bin .../manual/images/templates_estimatedatabayes.gif | Bin .../manual/images/templates_estimatedatasem.gif | Bin .../manual/images/templates_estimatesimulated.gif | Bin .../manual/images/templates_estsearchresult.gif | Bin .../images/templates_estsearchresultbayes.gif | Bin .../manual/images/templates_estsearchresultsem.gif | Bin .../manual/images/templates_searchfromdata.gif | Bin .../manual/images/templates_searchsimcomp.gif | Bin .../manual/images/templates_searchsimulated.gif | Bin .../manual/images/templates_simulatedata.gif | Bin .../manual/images/templates_updatebayesim.gif | Bin .../docs}/javahelp/manual/images/tetrad_menu1.gif | Bin .../docs}/javahelp/manual/images/tetrad_menu1.html | Bin .../docs}/javahelp/manual/images/tetrad_menu2.gif | Bin .../docs}/javahelp/manual/images/tetrad_menu3.gif | Bin .../docs}/javahelp/manual/images/tetrad_menu4.gif | Bin .../docs}/javahelp/manual/images/tetrad_menu5.gif | Bin .../javahelp/manual/images/ucomsparesearchcopy.jpg | Bin .../javahelp/manual/images/undirected_edge.png | Bin .../docs}/javahelp/manual/images/updater_button.gif | Bin .../javahelp/manual/images/variables_schema.png | Bin .../docs}/javahelp/manual/images/window_menu.png | Bin .../main_workspace/how_to_build_a_session.html | 0 .../main_workspace/main_workspace_explained.html | 0 .../manual/main_workspace/tetrad_menubar.html | 0 .../manual/main_workspace/tetrad_toolbar.html | 0 .../manual/main_workspace/tetrad_versioning.html | 0 .../resources/docs}/javahelp/manual/manual.html | 0 .../resources/docs}/javahelp/manual/references.html | 0 .../docs}/javahelp/manual/tetrad_overview.html | 0 .../docs}/javahelp/manual/tetrad_tutorial.html | 0 .../docs}/javahelp/manual/under_construction.html | 0 .../docs}/javahelp/manual/why_doesnt_tetrad.html | 0 .../src/main/resources/docs/manual/README.md | 0 .../main/resources/docs/manual/css/normalize.css | 0 .../src/main/resources/docs/manual/css/tetrad.css | 0 .../src/main/resources/docs/manual/flowchart.html | 0 .../docs/manual/images/appendix_figure_1a.png | Bin .../docs/manual/images/appendix_figure_1b.png | Bin .../docs/manual/images/appendix_figure_2.png | Bin .../docs/manual/images/arc_specialization_1.png | Bin .../docs/manual/images/arc_specialization_2.png | Bin .../docs/manual/images/arc_specialization_3.png | Bin .../resources/docs/manual/images/classify_box_1.png | Bin .../resources/docs/manual/images/classify_box_2.png | Bin .../resources/docs/manual/images/classify_box_3.png | Bin .../resources/docs/manual/images/compare_box_1.png | Bin .../resources/docs/manual/images/compare_box_10.png | Bin .../resources/docs/manual/images/compare_box_11.png | Bin .../resources/docs/manual/images/compare_box_12.png | Bin .../resources/docs/manual/images/compare_box_13.png | Bin .../resources/docs/manual/images/compare_box_3.png | Bin .../resources/docs/manual/images/compare_box_4.png | Bin .../resources/docs/manual/images/compare_box_5.png | Bin .../resources/docs/manual/images/compare_box_6.png | Bin .../resources/docs/manual/images/compare_box_7.png | Bin .../resources/docs/manual/images/compare_box_8.png | Bin .../resources/docs/manual/images/compare_box_9.png | Bin .../resources/docs/manual/images/data_box_1.png | Bin .../resources/docs/manual/images/data_box_10.png | Bin .../resources/docs/manual/images/data_box_2.png | Bin .../resources/docs/manual/images/data_box_3.png | Bin .../resources/docs/manual/images/data_box_4.png | Bin .../resources/docs/manual/images/data_box_5.png | Bin .../resources/docs/manual/images/data_box_6.png | Bin .../resources/docs/manual/images/data_box_7.png | Bin .../resources/docs/manual/images/data_box_8.png | Bin .../resources/docs/manual/images/data_box_8a.png | Bin .../resources/docs/manual/images/data_box_8b.png | Bin .../resources/docs/manual/images/data_box_9.png | Bin .../docs/manual/images/estimator_box_1.png | Bin .../docs/manual/images/estimator_box_2.png | Bin .../main/resources/docs/manual/images/flowchart.pdf | Bin .../resources/docs/manual/images/flowchart.pptx | Bin .../docs/manual/images/flowchart/Slide1.png | Bin .../docs/manual/images/flowchart/Slide2.png | Bin .../docs/manual/images/instantiated_model_box_1.png | Bin .../manual/images/instantiated_model_box_10.png | Bin .../manual/images/instantiated_model_box_11.png | Bin .../manual/images/instantiated_model_box_12.png | Bin .../manual/images/instantiated_model_box_13.png | Bin .../manual/images/instantiated_model_box_14.png | Bin .../docs/manual/images/instantiated_model_box_2.png | Bin .../docs/manual/images/instantiated_model_box_3.png | Bin .../docs/manual/images/instantiated_model_box_4.png | Bin .../docs/manual/images/instantiated_model_box_5.png | Bin .../docs/manual/images/instantiated_model_box_6.png | Bin .../docs/manual/images/instantiated_model_box_7.png | Bin .../docs/manual/images/instantiated_model_box_8.png | Bin .../docs/manual/images/instantiated_model_box_9.png | Bin .../docs/manual/images/knowledge_box_1.png | Bin .../docs/manual/images/knowledge_box_2.png | Bin .../docs/manual/images/knowledge_box_3.png | Bin .../docs/manual/images/knowledge_box_4.png | Bin .../docs/manual/images/parametric_model_box_1.png | Bin .../docs/manual/images/parametric_model_box_2.png | Bin .../docs/manual/images/parametric_model_box_3.png | Bin .../docs/manual/images/parametric_model_box_4.png | Bin .../docs/manual/images/parametric_model_box_5.png | Bin .../docs/manual/images/parametric_model_box_6.png | Bin .../docs/manual/images/parametric_model_box_7.png | Bin .../docs/manual/images/parametric_model_box_8.png | Bin .../docs/manual/images/regression_box_1.png | Bin .../docs/manual/images/regression_box_2.png | Bin .../docs/manual/images/regression_box_3.png | Bin .../resources/docs/manual/images/search_box_1.png | Bin .../docs/manual/images/simulation_box_1.png | Bin .../resources/docs/manual/images/updater_box_1.png | Bin .../resources/docs/manual/images/updater_box_10.png | Bin .../resources/docs/manual/images/updater_box_2.png | Bin .../resources/docs/manual/images/updater_box_3.png | Bin .../resources/docs/manual/images/updater_box_4.png | Bin .../resources/docs/manual/images/updater_box_5.png | Bin .../resources/docs/manual/images/updater_box_6.png | Bin .../resources/docs/manual/images/updater_box_7.png | Bin .../resources/docs/manual/images/updater_box_8.png | Bin .../resources/docs/manual/images/updater_box_9.png | Bin .../src/main/resources/docs/manual/index.html | 0 .../main/resources/docs/notes/cfci.orientation.txt | 0 .../src/main/resources/docs/notes/cliques.txt | 0 .../src/main/resources/docs/notes/cmd.txt | 0 .../src/main/resources/docs/notes/images | 0 .../src/main/resources/docs/notes/images.1 | 0 .../docs/notes/pc.fci.in.r.spirtes.2.3.2010.txt | 0 .../resources/docs/notes/serialization_notes.txt | 0 .../docs/referenced_papers/Adjacency-submitted.pdf | Bin .../docs/referenced_papers/AmStat_review.pdf | Bin .../Bollen_Ting_1993SociolMeth.pdf | Bin .../main/resources/docs/referenced_papers/CAUSAL.PS | Bin .../docs/referenced_papers/CMU-ISRI-04-127.pdf | Bin .../docs/referenced_papers/chickering02b.pdf | Bin .../docs/referenced_papers/con00random.pdf | Bin .../resources/docs/referenced_papers/glasso.f90 | 0 .../docs/referenced_papers/hartiganwong.pdf | Bin .../docs/referenced_papers/hawkins1989.pdf | Bin .../resources/docs/referenced_papers/jmlr06.pdf | Bin .../referenced_papers/math_s5_v1_article-17.pdf | Bin .../resources/docs/referenced_papers/optimal.pdf | Bin .../resources/docs/referenced_papers/p313-grira.pdf | Bin .../resources/docs/referenced_papers/splits.pdf | Bin .../docs/referenced_papers/uaidiscovery.pdf | Bin 796 files changed, 7 insertions(+), 7 deletions(-) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/AddNodeDown.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/AddNodeOff.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/AddNodeRoll.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/AddNodeUp.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/Icon32a.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/TETRAD.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/arrow-down.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/arrow-left.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/arrow-up.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/bidirected2.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/bidirected3.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/bidirectedDown.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/bidirectedOff.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/bidirectedRoll.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/bidirectedUp.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/circulararrow.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/add.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/add_latent.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/bidirected3.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/blackedge.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/blank.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/blueedge.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/clAbout.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/clsplash.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/clsplashBAK.jpg (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/clsplashV3_3.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/clsplashV4_0.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/correctGraph.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/directed3.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/eraser.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/essay.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/essay_disabled.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/expt_setup.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/expt_setup_active.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/expt_setup_down.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/expt_setup_over.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/expt_setup_over_active.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/feedback.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/feedback_disabled.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/guessedComboDependentIcon.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/guessedComboIcon.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/guessedComboIndependentIcon.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/hiddenSign.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/hyp_graph.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/hyp_graph_active.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/hyp_graph_down.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/hyp_graph_over.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/hyp_manip_graph.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/hyp_manip_graph_active.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/hyp_manip_graph_down.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/hyp_manip_graph_guess.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/hyp_manip_graph_over.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/icon.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/ignored.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/ignored_gray.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/independent.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/invisible.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/latent3.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/lock.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/lock_new.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/lock_new2.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/move.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/move3.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/notIndependent.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/population.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/population_active.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/population_down.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/population_hidden.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/population_hidden_active.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/population_hidden_down.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/population_hidden_over.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/population_over.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/predict.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/predict_active.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/predict_down.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/predict_over.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/random.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/random_new.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/random_new2.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/rededge.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/sample.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/sample_active.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/sample_down.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/sample_guess.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/sample_over.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/sample_valid.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/toolbar_checkans.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/toolbar_checkans_disabled.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/toolbar_finances.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/toolbar_finances_disabled.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/toolbar_instruction.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/toolbar_instruction_disabled.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/toolbar_save.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/toolbar_save_disabled.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/toolbar_showans.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/toolbar_showans_disabled.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/toolbar_submit.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/toolbar_submit_disabled.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/true_graph.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/true_graph_active.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/true_graph_down.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/true_graph_hidden.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/true_graph_hidden_active.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/true_graph_hidden_down.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/true_graph_hidden_over.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/true_graph_over.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/true_manip_graph.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/true_manip_graph_active.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/true_manip_graph_down.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/true_manip_graph_hidden.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/true_manip_graph_hidden_active.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/true_manip_graph_hidden_down.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/true_manip_graph_hidden_over.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/true_manip_graph_over.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/variable3.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cl/visible.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cleanupDown.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cleanupOff.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cleanupRoll.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cleanupUp.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/clear.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/clearVariableDown.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/clearVariableOff.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/clearVariableRoll.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/clearVariableUp.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/clearedgesDown.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/clearedgesOff.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/clearedgesRoll.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/clearedgesUp.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cleargraphDown.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cleargraphOff.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cleargraphRoll.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/cleargraphUp.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/close.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/compareDown.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/compareIcon.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/compareOff.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/compareRoll.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/compareUp.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/dataDown.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/dataIcon.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/dataOff.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/dataRoll.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/dataUp.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/directDown.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/directOff.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/directRoll.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/directUp.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/directed2.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/directed3.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/directedDown.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/directedOff.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/directedRoll.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/directedUp.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/estimatorDown.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/estimatorIcon.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/estimatorOff.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/estimatorRoll.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/estimatorUp.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/fileDown.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/fileOff.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/fileRoll.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/fileUp.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/flow.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/flowDown.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/flowOff.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/flowRoll.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/flowUp.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/graduation_hat1.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/graphDown.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/graphIcon.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/graphOff.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/graphRoll.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/graphUp.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/ico1.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/icontry2.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/imDown.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/imIcon.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/imOff.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/imRoll.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/imUp.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/info.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/information-icon.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/information_small.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/information_small_white.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/knowDown.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/knowIcon.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/knowOff.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/knowRoll.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/knowUp.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/latent2.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/latent3.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/latentDown.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/latentOff.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/latentRoll.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/latentUp.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/miscB62.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/move.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/move2.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/move3.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/moveDown.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/moveOff.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/moveRoll.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/moveUp.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/nondirected2.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/nondirected3.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/nondirectedDown.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/nondirectedOff.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/nondirectedRoll.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/nondirectedUp.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/note.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/partiallyoriented2.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/partiallyoriented3.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/partiallyorientedDown.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/partiallyorientedOff.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/partiallyorientedRoll.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/partiallyorientedUp.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/pmDown.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/pmIcon.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/pmOff.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/pmRoll.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/pmUp.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/randomDown.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/randomIcon.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/randomOff.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/randomRoll.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/randomUp.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/repeatDown.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/repeatOff.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/repeatRoll.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/repeatUp.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/save.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/searchDown.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/searchIcon.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/searchOff.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/searchRoll.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/searchUp.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/smallbidirectedDown.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/smallbidirectedOff.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/smallbidirectedRoll.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/smallbidirectedUp.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/smalldirectedDown.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/smalldirectedOff.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/smalldirectedRoll.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/smalldirectedUp.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/smallhalfdirectedDown.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/smallhalfdirectedOff.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/smallhalfdirectedRoll.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/smallhalfdirectedUp.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/smallundirectedDown.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/smallundirectedOff.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/smallundirectedRoll.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/smallundirectedUp.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/smallunorientedDown.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/smallunorientedOff.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/smallunorientedRoll.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/smallunorientedUp.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/system_info.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/system_info_alt.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/tableDown.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/tableOff.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/tableRoll.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/tableUp.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/tetradicon.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/three_arrows.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/three_circles.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/toolbar_get_info.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/tyler16.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/tyler32.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/undirected3.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/undirectedDown.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/undirectedOff.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/undirectedRoll.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/undirectedUp.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/unorientedUp.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/updaterDown.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/updaterIcon.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/updaterOff.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/updaterRoll.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/updaterUp.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/variable2.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/variable3.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/variableDown.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/variableOff.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/variableRoll.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/variableUp.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/zoomDown.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/zoomOff.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/zoomRoll.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/images/zoomUp.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/Map.jhm (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/TetradHelp.hs (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/TetradHelpIndex.xml (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/TetradHelpTOC.xml (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/classify/classify_box.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/compare/compare_box.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/data/data_box.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/data/data_loader.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/data/data_set_list.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/each_box_explained.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/each_module_explained.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/estimate/dirichlet_estimator.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/estimate/estimate_box.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/estimate/ml_bayes_estimator.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/estimate/sem_estimator.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/graph/dag.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/graph/general_graph.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/graph/graph_box.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/graph/sem_graph.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/graph/time_graph.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/im/bayes_im.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/im/dirichlet_bayes_im.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/im/im_box.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/im/sem_im.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/manipulated_data/manipulated2.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/manipulated_data/manipulated3.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/manipulated_data/manipulated_data_box.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/pm/bayes_pm.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/pm/pm_box.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/pm/sem_pm.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/regression/logistic_regression.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/regression/multiple_linear_regression.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/regression/regression_box.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/search/bdeu.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/search/bpc.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/search/ccd.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/search/cfci.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/search/chisquare.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/search/conditional_correlation.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/search/conditional_gaussian_bic.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/search/conditional_gaussian_lrt.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/search/cpc.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/search/cpcs.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/search/d_separation.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/search/discrete_bic.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/search/eb.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/search/fas.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/search/fci.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/search/fisher_z.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/search/gccd.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/search/gfci.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/search/glasso.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/search/gsquare.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/search/images.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/search/lingam.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/search/mbfs.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/search/mgm.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/search/mimbuild.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/search/pc.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/search/pcd.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/search/pclocal.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/search/pcmax.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/search/pcmaxlocal.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/search/pcs.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/search/purify.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/search/r1.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/search/r2.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/search/r3.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/search/r4.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/search/rfci.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/search/rskew.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/search/rskewe.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/search/search_box.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/search/sem_bic.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/search/skew.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/search/skewe.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/search/svarfci.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/search/tsgfci.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/search/tsimages.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/search/types_of_algorithms.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/search/wfges.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/update/approximate_updater.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/update/cpt_invariant_updater.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/update/row_summing_updater.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/boxes/update/update_box.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/common_tasks/common_tasks.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/common_tasks/continuous_and_discrete_variables.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/common_tasks/copying_and_pasting.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/common_tasks/creating_data_from_scratch.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/common_tasks/defining_discrete_variables.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/common_tasks/destroying_models.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/common_tasks/discretizing_data.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/common_tasks/edge_orientation_shortcuts.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/common_tasks/editing_covariance_matrices.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/common_tasks/editing_knowledge.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/common_tasks/editing_node_properties.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/common_tasks/editing_tabular_data.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/common_tasks/exiting_tetrad.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/common_tasks/generating_random_dags.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/common_tasks/handling_missing_data.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/common_tasks/loading_covariance_matrices.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/common_tasks/loading_data.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/common_tasks/loading_tabular_data.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/common_tasks/manipulating_data.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/common_tasks/opening_sessions.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/common_tasks/saving_screenshots.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/common_tasks/saving_sessions.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/common_tasks/selecting_groups_of_nodes.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/common_tasks/simulating_data.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/common_tasks/simulating_data_bayes.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/common_tasks/simulating_data_glass.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/common_tasks/simulating_data_sem.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/common_tasks/tabular_data_sets.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/common_tasks/taking_screenshots.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/common_tasks/transferring_data_from_other_programs.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/common_tasks/transferring_from_excel.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/common_tasks/transferring_from_minitab.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/common_tasks/using_popup_menus.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/common_tasks/using_templates.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/definitions/definitions.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/definitions/measured_latent_variables.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/definitions/measurement_structural_graph.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/definitions/tetrad_graph_types.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/for_further_help.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/genetics/genetics.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/genetics/genetics_old.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/graph_edge_types.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/PMimage.jpg (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/Thumbs.db (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/UBayescsopy.jpg (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/UBaysesIMcopy.jpg (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/UComparseimage.jpg (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/UIMSEM.jpg (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/UIMedcopy.jpg (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/UIMimagecopy.jpg (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/UPM.jpg (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/UcompsarePCcopy.jpg (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/Ucompsaresheet.jpg (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/Ucontsdata.jpg (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/Udastasingle.jpg (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/Udatsa.jpg (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/Uestimsate.jpg (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/Uexpsanded.jpg (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/Uimportcopy.jpg (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/Uimtablecopy.jpg (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/UntitiledsROC.jpg (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/Untitled2Cslassify.jpg (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/UntitledClasssifyResult.jpg (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/UntitledClsassifyWindow.jpg (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/UntitledPsseudocount.jpg (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/UntitledSsearchImagecopy.jpg (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/UntitledsGraphSearch.jpg (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/Untitledupdaterbox.jpg (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/Uran.jpg (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/Utime.jpg (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/arrow_button.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/arrow_tool.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/bayes_im_schema.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/bayes_pm_schema.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/bayesim1.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/bayesim2.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/bayesim3.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/bayesim4.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/bayesim5.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/bayesim6.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/bayesim7.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/bayespm1.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/bayespm2.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/bayespm3.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/bayespm4.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/bayespm5.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/bidirectedEdge.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/calvin_hobbes_instructions.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/choose_data.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/choose_load_data.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/classify_button.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/classify_highlight.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/click_done_data.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/click_load.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/cluster1.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/cluster2.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/compare_button.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/consructing_sessions1.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/consructing_sessions2.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/consructing_sessions3.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/consructing_sessions4.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/consructing_sessions5.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/consructing_sessions6.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/consructing_sessions7.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/copying1.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/copying2.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/copying3.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/copying4.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/createBayesNet.jpg (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/dag_editor.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/dag_from_data.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/dag_from_data2.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/dag_graph_image.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/dageditorwindow.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/data_button.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/data_highlight.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/data_loader_1.PNG (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/data_loader_2.PNG (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/data_loader_3.PNG (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/data_loader_4.PNG (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/data_loader_5.PNG (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/data_loader_6.PNG (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/data_standatalone_highlight.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/databox1.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/databox2.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/databox3.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/databox4.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/dataloader1.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/dataloader2.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/dataloader3.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/dataloader4.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/dataloader4.jpg (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/dataset_schema.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/defineSampleSize.jpg (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/directedEdge.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/dirichletbayesim1.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/dirichletbayesim2.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/dirichletbayesim3.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/dirichletbayesim4.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/dirichletbayesim5.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/dirichletbayesim6.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/dirichletbayesim7.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/discretization1.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/discretization2.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/discretization3.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/discretization4.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/discretization5.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/discretization6.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/edge_orientation_shortcuts1.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/edge_orientation_shortcuts2.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/edge_orientation_shortcuts3.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/edge_orientation_shortcuts4.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/edit_menu.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/editing_data1.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/editing_data2.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/editing_data3.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/editing_data4.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/editing_knowledge1.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/editing_knowledge2.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/editing_knowledge3.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/editing_knowledge4.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/editing_knowledge5.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/editing_knowledge6.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/editing_nodes1.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/editing_nodes2.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/editing_nodes3.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/estimator_button.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/example_workflow_schema.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/file_menu.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/flowchart_dependencies1.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/flowchart_dependencies2.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/flowcharterButton.jpg (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/generalgrapheditorwindow.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/generateData.jpg (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/ges1.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/graph1.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/graph1_to_pm1.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/graph1choices.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/graph1editorwindow.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/graph1structureeditor.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/graph2editorwindow.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/graph2structureeditor.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/graphButton.jpg (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/graphEditor.jpg (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/graphWindow.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/graph_button.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/graph_gen_schema.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/graph_highlight.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/graph_schema.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/help_menu.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/im_button.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/im_highlight.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/images.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/instantiatedModelButton.jpg (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/instantiatedWindow.jpg (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/knowledge1.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/knowledge2.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/knowledge3.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/knowledge4.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/knowledge_button.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/knowledge_schema.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/loading_data1.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/loading_data2.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/loading_data3.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/logging_menu.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/main_menu.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/main_workbench.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/main_workbench2.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/main_workbench2.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/main_workbench3.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/main_workbench3.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/main_workbench4.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/main_workspace.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/manipulatedButton.jpg (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/manipulatedData.jpg (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/manipulated_data_button.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/manipulated_highlight.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/measured_vs_latent1.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/measured_vs_latent2.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/menubar.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/mimbuild1.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/mimbuild3.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/mimbuild4.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/objects.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/parametric_model_button.jpg (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/pc_output.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/pcsearch1.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/pcsearch2.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/pcsearch3.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/pcsearch_dialog.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/place_data_box.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/pm_button.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/pm_highlight.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/pm_image.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/purify1.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/purify2.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/purify3.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/purify4.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/red_x.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/regression_button.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/regression_highlight.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/rubberband1.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/rubberband2.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/save_data.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/searchCsreation.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/search_box.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/search_button.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/search_done.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/search_from_data_highlight.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/search_from_graph_highlight.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/search_params.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/search_schema.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/searcsreation.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/select_move_button.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/sem_graph1.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/sem_graph2.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/sem_graph3.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/sem_im_schema.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/sem_pm_schema.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/semim1.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/semim2.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/semim3.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/semim4.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/semim5.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/semim6.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/semim7.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/semim8.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/sempm1.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/sempm2.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/sempm3.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/sempm4.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/sempm5.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/sempm6.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/templates_estimatedatabayes.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/templates_estimatedatasem.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/templates_estimatesimulated.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/templates_estsearchresult.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/templates_estsearchresultbayes.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/templates_estsearchresultsem.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/templates_searchfromdata.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/templates_searchsimcomp.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/templates_searchsimulated.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/templates_simulatedata.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/templates_updatebayesim.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/tetrad_menu1.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/tetrad_menu1.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/tetrad_menu2.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/tetrad_menu3.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/tetrad_menu4.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/tetrad_menu5.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/ucomsparesearchcopy.jpg (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/undirected_edge.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/updater_button.gif (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/variables_schema.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/images/window_menu.png (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/main_workspace/how_to_build_a_session.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/main_workspace/main_workspace_explained.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/main_workspace/tetrad_menubar.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/main_workspace/tetrad_toolbar.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/main_workspace/tetrad_versioning.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/manual.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/references.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/tetrad_overview.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/tetrad_tutorial.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/under_construction.html (100%) rename {tetrad-gui/src/main/resources/resources => tetrad-lib/src/main/resources/docs}/javahelp/manual/why_doesnt_tetrad.html (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/README.md (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/css/normalize.css (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/css/tetrad.css (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/flowchart.html (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/appendix_figure_1a.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/appendix_figure_1b.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/appendix_figure_2.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/arc_specialization_1.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/arc_specialization_2.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/arc_specialization_3.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/classify_box_1.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/classify_box_2.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/classify_box_3.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/compare_box_1.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/compare_box_10.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/compare_box_11.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/compare_box_12.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/compare_box_13.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/compare_box_3.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/compare_box_4.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/compare_box_5.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/compare_box_6.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/compare_box_7.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/compare_box_8.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/compare_box_9.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/data_box_1.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/data_box_10.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/data_box_2.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/data_box_3.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/data_box_4.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/data_box_5.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/data_box_6.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/data_box_7.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/data_box_8.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/data_box_8a.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/data_box_8b.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/data_box_9.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/estimator_box_1.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/estimator_box_2.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/flowchart.pdf (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/flowchart.pptx (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/flowchart/Slide1.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/flowchart/Slide2.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/instantiated_model_box_1.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/instantiated_model_box_10.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/instantiated_model_box_11.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/instantiated_model_box_12.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/instantiated_model_box_13.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/instantiated_model_box_14.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/instantiated_model_box_2.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/instantiated_model_box_3.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/instantiated_model_box_4.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/instantiated_model_box_5.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/instantiated_model_box_6.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/instantiated_model_box_7.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/instantiated_model_box_8.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/instantiated_model_box_9.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/knowledge_box_1.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/knowledge_box_2.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/knowledge_box_3.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/knowledge_box_4.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/parametric_model_box_1.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/parametric_model_box_2.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/parametric_model_box_3.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/parametric_model_box_4.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/parametric_model_box_5.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/parametric_model_box_6.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/parametric_model_box_7.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/parametric_model_box_8.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/regression_box_1.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/regression_box_2.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/regression_box_3.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/search_box_1.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/simulation_box_1.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/updater_box_1.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/updater_box_10.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/updater_box_2.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/updater_box_3.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/updater_box_4.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/updater_box_5.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/updater_box_6.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/updater_box_7.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/updater_box_8.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/images/updater_box_9.png (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/manual/index.html (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/notes/cfci.orientation.txt (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/notes/cliques.txt (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/notes/cmd.txt (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/notes/images (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/notes/images.1 (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/notes/pc.fci.in.r.spirtes.2.3.2010.txt (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/notes/serialization_notes.txt (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/referenced_papers/Adjacency-submitted.pdf (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/referenced_papers/AmStat_review.pdf (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/referenced_papers/Bollen_Ting_1993SociolMeth.pdf (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/referenced_papers/CAUSAL.PS (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/referenced_papers/CMU-ISRI-04-127.pdf (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/referenced_papers/chickering02b.pdf (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/referenced_papers/con00random.pdf (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/referenced_papers/glasso.f90 (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/referenced_papers/hartiganwong.pdf (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/referenced_papers/hawkins1989.pdf (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/referenced_papers/jmlr06.pdf (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/referenced_papers/math_s5_v1_article-17.pdf (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/referenced_papers/optimal.pdf (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/referenced_papers/p313-grira.pdf (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/referenced_papers/splits.pdf (100%) rename {tetrad-gui => tetrad-lib}/src/main/resources/docs/referenced_papers/uaidiscovery.pdf (100%) diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/DagEditor.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/DagEditor.java index 1f5441e5b8..d0caaf38c3 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/DagEditor.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/DagEditor.java @@ -263,7 +263,7 @@ private void initUI(DagWrapper dagWrapper) { @Override public void actionPerformed(ActionEvent e) { // Initialize helpSet - final String helpHS = "/resources/javahelp/TetradHelp.hs"; + final String helpHS = "/docs/javahelp/TetradHelp.hs"; try { URL url = this.getClass().getResource(helpHS); diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/GraphEditor.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/GraphEditor.java index 97430d165d..11ca86bd80 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/GraphEditor.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/GraphEditor.java @@ -265,7 +265,7 @@ private void initUI(GraphWrapper graphWrapper) { @Override public void actionPerformed(ActionEvent e) { // Initialize helpSet - final String helpHS = "/resources/javahelp/TetradHelp.hs"; + final String helpHS = "/docs/javahelp/TetradHelp.hs"; try { URL url = this.getClass().getResource(helpHS); diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/GraphSelectionEditor.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/GraphSelectionEditor.java index 563461d367..5a5dbc4d3f 100755 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/GraphSelectionEditor.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/GraphSelectionEditor.java @@ -95,7 +95,7 @@ public GraphSelectionEditor(GraphSelectionWrapper wrapper) { } // Initialize helpSet - Zhou - String helpHS = "/resources/javahelp/TetradHelp.hs"; + String helpHS = "/docs/javahelp/TetradHelp.hs"; try { URL url = this.getClass().getResource(helpHS); diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/SemGraphEditor.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/SemGraphEditor.java index 0c627b5cb9..75c83fe070 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/SemGraphEditor.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/SemGraphEditor.java @@ -266,7 +266,7 @@ private void initUI(SemGraphWrapper semGraphWrapper) { @Override public void actionPerformed(ActionEvent e) { // Initialize helpSet - final String helpHS = "/resources/javahelp/TetradHelp.hs"; + final String helpHS = "/docs/javahelp/TetradHelp.hs"; try { URL url = this.getClass().getResource(helpHS); diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/TimeLagGraphEditor.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/TimeLagGraphEditor.java index df624a2e68..07f7a5f7b1 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/TimeLagGraphEditor.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/TimeLagGraphEditor.java @@ -241,7 +241,7 @@ private void initUI(TimeLagGraphWrapper timeLagGraphWrapper) { @Override public void actionPerformed(ActionEvent e) { // Initialize helpSet - final String helpHS = "/resources/javahelp/TetradHelp.hs"; + final String helpHS = "/docs/javahelp/TetradHelp.hs"; try { URL url = this.getClass().getResource(helpHS); diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/search/GraphCard.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/search/GraphCard.java index 69972c031d..669985bd5e 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/search/GraphCard.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/search/GraphCard.java @@ -152,7 +152,7 @@ private Box createInstructionBox() { @Override public void actionPerformed(ActionEvent e) { // Initialize helpSet - final String helpHS = "/resources/javahelp/TetradHelp.hs"; + final String helpHS = "/docs/javahelp/TetradHelp.hs"; try { URL url = this.getClass().getResource(helpHS); diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/ImageUtils.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/ImageUtils.java index 4dcbacc4b1..b221fcb8bd 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/ImageUtils.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/ImageUtils.java @@ -53,7 +53,7 @@ public static Image getImage(Object anchor, String path) { throw new NullPointerException("Path must not be null."); } - String fullPath = "/resources/images/" + path; + String fullPath = "/docs/images/" + path; URL url = anchor.getClass().getResource(fullPath); if (url == null) { diff --git a/tetrad-gui/src/main/resources/resources/images/AddNodeDown.gif b/tetrad-lib/src/main/resources/docs/images/AddNodeDown.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/AddNodeDown.gif rename to tetrad-lib/src/main/resources/docs/images/AddNodeDown.gif diff --git a/tetrad-gui/src/main/resources/resources/images/AddNodeOff.gif b/tetrad-lib/src/main/resources/docs/images/AddNodeOff.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/AddNodeOff.gif rename to tetrad-lib/src/main/resources/docs/images/AddNodeOff.gif diff --git a/tetrad-gui/src/main/resources/resources/images/AddNodeRoll.gif b/tetrad-lib/src/main/resources/docs/images/AddNodeRoll.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/AddNodeRoll.gif rename to tetrad-lib/src/main/resources/docs/images/AddNodeRoll.gif diff --git a/tetrad-gui/src/main/resources/resources/images/AddNodeUp.gif b/tetrad-lib/src/main/resources/docs/images/AddNodeUp.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/AddNodeUp.gif rename to tetrad-lib/src/main/resources/docs/images/AddNodeUp.gif diff --git a/tetrad-gui/src/main/resources/resources/images/Icon32a.png b/tetrad-lib/src/main/resources/docs/images/Icon32a.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/Icon32a.png rename to tetrad-lib/src/main/resources/docs/images/Icon32a.png diff --git a/tetrad-gui/src/main/resources/resources/images/TETRAD.gif b/tetrad-lib/src/main/resources/docs/images/TETRAD.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/TETRAD.gif rename to tetrad-lib/src/main/resources/docs/images/TETRAD.gif diff --git a/tetrad-gui/src/main/resources/resources/images/arrow-down.gif b/tetrad-lib/src/main/resources/docs/images/arrow-down.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/arrow-down.gif rename to tetrad-lib/src/main/resources/docs/images/arrow-down.gif diff --git a/tetrad-gui/src/main/resources/resources/images/arrow-left.gif b/tetrad-lib/src/main/resources/docs/images/arrow-left.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/arrow-left.gif rename to tetrad-lib/src/main/resources/docs/images/arrow-left.gif diff --git a/tetrad-gui/src/main/resources/resources/images/arrow-up.gif b/tetrad-lib/src/main/resources/docs/images/arrow-up.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/arrow-up.gif rename to tetrad-lib/src/main/resources/docs/images/arrow-up.gif diff --git a/tetrad-gui/src/main/resources/resources/images/bidirected2.gif b/tetrad-lib/src/main/resources/docs/images/bidirected2.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/bidirected2.gif rename to tetrad-lib/src/main/resources/docs/images/bidirected2.gif diff --git a/tetrad-gui/src/main/resources/resources/images/bidirected3.gif b/tetrad-lib/src/main/resources/docs/images/bidirected3.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/bidirected3.gif rename to tetrad-lib/src/main/resources/docs/images/bidirected3.gif diff --git a/tetrad-gui/src/main/resources/resources/images/bidirectedDown.gif b/tetrad-lib/src/main/resources/docs/images/bidirectedDown.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/bidirectedDown.gif rename to tetrad-lib/src/main/resources/docs/images/bidirectedDown.gif diff --git a/tetrad-gui/src/main/resources/resources/images/bidirectedOff.gif b/tetrad-lib/src/main/resources/docs/images/bidirectedOff.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/bidirectedOff.gif rename to tetrad-lib/src/main/resources/docs/images/bidirectedOff.gif diff --git a/tetrad-gui/src/main/resources/resources/images/bidirectedRoll.gif b/tetrad-lib/src/main/resources/docs/images/bidirectedRoll.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/bidirectedRoll.gif rename to tetrad-lib/src/main/resources/docs/images/bidirectedRoll.gif diff --git a/tetrad-gui/src/main/resources/resources/images/bidirectedUp.gif b/tetrad-lib/src/main/resources/docs/images/bidirectedUp.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/bidirectedUp.gif rename to tetrad-lib/src/main/resources/docs/images/bidirectedUp.gif diff --git a/tetrad-gui/src/main/resources/resources/images/circulararrow.gif b/tetrad-lib/src/main/resources/docs/images/circulararrow.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/circulararrow.gif rename to tetrad-lib/src/main/resources/docs/images/circulararrow.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/add.gif b/tetrad-lib/src/main/resources/docs/images/cl/add.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/add.gif rename to tetrad-lib/src/main/resources/docs/images/cl/add.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/add_latent.gif b/tetrad-lib/src/main/resources/docs/images/cl/add_latent.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/add_latent.gif rename to tetrad-lib/src/main/resources/docs/images/cl/add_latent.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/bidirected3.gif b/tetrad-lib/src/main/resources/docs/images/cl/bidirected3.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/bidirected3.gif rename to tetrad-lib/src/main/resources/docs/images/cl/bidirected3.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/blackedge.gif b/tetrad-lib/src/main/resources/docs/images/cl/blackedge.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/blackedge.gif rename to tetrad-lib/src/main/resources/docs/images/cl/blackedge.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/blank.gif b/tetrad-lib/src/main/resources/docs/images/cl/blank.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/blank.gif rename to tetrad-lib/src/main/resources/docs/images/cl/blank.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/blueedge.gif b/tetrad-lib/src/main/resources/docs/images/cl/blueedge.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/blueedge.gif rename to tetrad-lib/src/main/resources/docs/images/cl/blueedge.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/clAbout.gif b/tetrad-lib/src/main/resources/docs/images/cl/clAbout.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/clAbout.gif rename to tetrad-lib/src/main/resources/docs/images/cl/clAbout.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/clsplash.gif b/tetrad-lib/src/main/resources/docs/images/cl/clsplash.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/clsplash.gif rename to tetrad-lib/src/main/resources/docs/images/cl/clsplash.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/clsplashBAK.jpg b/tetrad-lib/src/main/resources/docs/images/cl/clsplashBAK.jpg similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/clsplashBAK.jpg rename to tetrad-lib/src/main/resources/docs/images/cl/clsplashBAK.jpg diff --git a/tetrad-gui/src/main/resources/resources/images/cl/clsplashV3_3.gif b/tetrad-lib/src/main/resources/docs/images/cl/clsplashV3_3.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/clsplashV3_3.gif rename to tetrad-lib/src/main/resources/docs/images/cl/clsplashV3_3.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/clsplashV4_0.gif b/tetrad-lib/src/main/resources/docs/images/cl/clsplashV4_0.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/clsplashV4_0.gif rename to tetrad-lib/src/main/resources/docs/images/cl/clsplashV4_0.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/correctGraph.gif b/tetrad-lib/src/main/resources/docs/images/cl/correctGraph.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/correctGraph.gif rename to tetrad-lib/src/main/resources/docs/images/cl/correctGraph.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/directed3.gif b/tetrad-lib/src/main/resources/docs/images/cl/directed3.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/directed3.gif rename to tetrad-lib/src/main/resources/docs/images/cl/directed3.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/eraser.gif b/tetrad-lib/src/main/resources/docs/images/cl/eraser.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/eraser.gif rename to tetrad-lib/src/main/resources/docs/images/cl/eraser.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/essay.gif b/tetrad-lib/src/main/resources/docs/images/cl/essay.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/essay.gif rename to tetrad-lib/src/main/resources/docs/images/cl/essay.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/essay_disabled.gif b/tetrad-lib/src/main/resources/docs/images/cl/essay_disabled.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/essay_disabled.gif rename to tetrad-lib/src/main/resources/docs/images/cl/essay_disabled.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/expt_setup.gif b/tetrad-lib/src/main/resources/docs/images/cl/expt_setup.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/expt_setup.gif rename to tetrad-lib/src/main/resources/docs/images/cl/expt_setup.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/expt_setup_active.gif b/tetrad-lib/src/main/resources/docs/images/cl/expt_setup_active.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/expt_setup_active.gif rename to tetrad-lib/src/main/resources/docs/images/cl/expt_setup_active.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/expt_setup_down.gif b/tetrad-lib/src/main/resources/docs/images/cl/expt_setup_down.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/expt_setup_down.gif rename to tetrad-lib/src/main/resources/docs/images/cl/expt_setup_down.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/expt_setup_over.gif b/tetrad-lib/src/main/resources/docs/images/cl/expt_setup_over.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/expt_setup_over.gif rename to tetrad-lib/src/main/resources/docs/images/cl/expt_setup_over.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/expt_setup_over_active.gif b/tetrad-lib/src/main/resources/docs/images/cl/expt_setup_over_active.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/expt_setup_over_active.gif rename to tetrad-lib/src/main/resources/docs/images/cl/expt_setup_over_active.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/feedback.gif b/tetrad-lib/src/main/resources/docs/images/cl/feedback.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/feedback.gif rename to tetrad-lib/src/main/resources/docs/images/cl/feedback.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/feedback_disabled.gif b/tetrad-lib/src/main/resources/docs/images/cl/feedback_disabled.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/feedback_disabled.gif rename to tetrad-lib/src/main/resources/docs/images/cl/feedback_disabled.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/guessedComboDependentIcon.gif b/tetrad-lib/src/main/resources/docs/images/cl/guessedComboDependentIcon.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/guessedComboDependentIcon.gif rename to tetrad-lib/src/main/resources/docs/images/cl/guessedComboDependentIcon.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/guessedComboIcon.gif b/tetrad-lib/src/main/resources/docs/images/cl/guessedComboIcon.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/guessedComboIcon.gif rename to tetrad-lib/src/main/resources/docs/images/cl/guessedComboIcon.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/guessedComboIndependentIcon.gif b/tetrad-lib/src/main/resources/docs/images/cl/guessedComboIndependentIcon.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/guessedComboIndependentIcon.gif rename to tetrad-lib/src/main/resources/docs/images/cl/guessedComboIndependentIcon.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/hiddenSign.gif b/tetrad-lib/src/main/resources/docs/images/cl/hiddenSign.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/hiddenSign.gif rename to tetrad-lib/src/main/resources/docs/images/cl/hiddenSign.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/hyp_graph.gif b/tetrad-lib/src/main/resources/docs/images/cl/hyp_graph.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/hyp_graph.gif rename to tetrad-lib/src/main/resources/docs/images/cl/hyp_graph.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/hyp_graph_active.gif b/tetrad-lib/src/main/resources/docs/images/cl/hyp_graph_active.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/hyp_graph_active.gif rename to tetrad-lib/src/main/resources/docs/images/cl/hyp_graph_active.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/hyp_graph_down.gif b/tetrad-lib/src/main/resources/docs/images/cl/hyp_graph_down.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/hyp_graph_down.gif rename to tetrad-lib/src/main/resources/docs/images/cl/hyp_graph_down.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/hyp_graph_over.gif b/tetrad-lib/src/main/resources/docs/images/cl/hyp_graph_over.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/hyp_graph_over.gif rename to tetrad-lib/src/main/resources/docs/images/cl/hyp_graph_over.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/hyp_manip_graph.gif b/tetrad-lib/src/main/resources/docs/images/cl/hyp_manip_graph.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/hyp_manip_graph.gif rename to tetrad-lib/src/main/resources/docs/images/cl/hyp_manip_graph.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/hyp_manip_graph_active.gif b/tetrad-lib/src/main/resources/docs/images/cl/hyp_manip_graph_active.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/hyp_manip_graph_active.gif rename to tetrad-lib/src/main/resources/docs/images/cl/hyp_manip_graph_active.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/hyp_manip_graph_down.gif b/tetrad-lib/src/main/resources/docs/images/cl/hyp_manip_graph_down.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/hyp_manip_graph_down.gif rename to tetrad-lib/src/main/resources/docs/images/cl/hyp_manip_graph_down.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/hyp_manip_graph_guess.gif b/tetrad-lib/src/main/resources/docs/images/cl/hyp_manip_graph_guess.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/hyp_manip_graph_guess.gif rename to tetrad-lib/src/main/resources/docs/images/cl/hyp_manip_graph_guess.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/hyp_manip_graph_over.gif b/tetrad-lib/src/main/resources/docs/images/cl/hyp_manip_graph_over.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/hyp_manip_graph_over.gif rename to tetrad-lib/src/main/resources/docs/images/cl/hyp_manip_graph_over.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/icon.gif b/tetrad-lib/src/main/resources/docs/images/cl/icon.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/icon.gif rename to tetrad-lib/src/main/resources/docs/images/cl/icon.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/ignored.gif b/tetrad-lib/src/main/resources/docs/images/cl/ignored.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/ignored.gif rename to tetrad-lib/src/main/resources/docs/images/cl/ignored.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/ignored_gray.gif b/tetrad-lib/src/main/resources/docs/images/cl/ignored_gray.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/ignored_gray.gif rename to tetrad-lib/src/main/resources/docs/images/cl/ignored_gray.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/independent.gif b/tetrad-lib/src/main/resources/docs/images/cl/independent.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/independent.gif rename to tetrad-lib/src/main/resources/docs/images/cl/independent.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/invisible.gif b/tetrad-lib/src/main/resources/docs/images/cl/invisible.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/invisible.gif rename to tetrad-lib/src/main/resources/docs/images/cl/invisible.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/latent3.gif b/tetrad-lib/src/main/resources/docs/images/cl/latent3.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/latent3.gif rename to tetrad-lib/src/main/resources/docs/images/cl/latent3.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/lock.gif b/tetrad-lib/src/main/resources/docs/images/cl/lock.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/lock.gif rename to tetrad-lib/src/main/resources/docs/images/cl/lock.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/lock_new.gif b/tetrad-lib/src/main/resources/docs/images/cl/lock_new.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/lock_new.gif rename to tetrad-lib/src/main/resources/docs/images/cl/lock_new.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/lock_new2.gif b/tetrad-lib/src/main/resources/docs/images/cl/lock_new2.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/lock_new2.gif rename to tetrad-lib/src/main/resources/docs/images/cl/lock_new2.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/move.gif b/tetrad-lib/src/main/resources/docs/images/cl/move.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/move.gif rename to tetrad-lib/src/main/resources/docs/images/cl/move.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/move3.gif b/tetrad-lib/src/main/resources/docs/images/cl/move3.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/move3.gif rename to tetrad-lib/src/main/resources/docs/images/cl/move3.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/notIndependent.gif b/tetrad-lib/src/main/resources/docs/images/cl/notIndependent.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/notIndependent.gif rename to tetrad-lib/src/main/resources/docs/images/cl/notIndependent.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/population.gif b/tetrad-lib/src/main/resources/docs/images/cl/population.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/population.gif rename to tetrad-lib/src/main/resources/docs/images/cl/population.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/population_active.gif b/tetrad-lib/src/main/resources/docs/images/cl/population_active.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/population_active.gif rename to tetrad-lib/src/main/resources/docs/images/cl/population_active.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/population_down.gif b/tetrad-lib/src/main/resources/docs/images/cl/population_down.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/population_down.gif rename to tetrad-lib/src/main/resources/docs/images/cl/population_down.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/population_hidden.gif b/tetrad-lib/src/main/resources/docs/images/cl/population_hidden.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/population_hidden.gif rename to tetrad-lib/src/main/resources/docs/images/cl/population_hidden.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/population_hidden_active.gif b/tetrad-lib/src/main/resources/docs/images/cl/population_hidden_active.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/population_hidden_active.gif rename to tetrad-lib/src/main/resources/docs/images/cl/population_hidden_active.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/population_hidden_down.gif b/tetrad-lib/src/main/resources/docs/images/cl/population_hidden_down.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/population_hidden_down.gif rename to tetrad-lib/src/main/resources/docs/images/cl/population_hidden_down.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/population_hidden_over.gif b/tetrad-lib/src/main/resources/docs/images/cl/population_hidden_over.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/population_hidden_over.gif rename to tetrad-lib/src/main/resources/docs/images/cl/population_hidden_over.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/population_over.gif b/tetrad-lib/src/main/resources/docs/images/cl/population_over.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/population_over.gif rename to tetrad-lib/src/main/resources/docs/images/cl/population_over.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/predict.gif b/tetrad-lib/src/main/resources/docs/images/cl/predict.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/predict.gif rename to tetrad-lib/src/main/resources/docs/images/cl/predict.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/predict_active.gif b/tetrad-lib/src/main/resources/docs/images/cl/predict_active.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/predict_active.gif rename to tetrad-lib/src/main/resources/docs/images/cl/predict_active.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/predict_down.gif b/tetrad-lib/src/main/resources/docs/images/cl/predict_down.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/predict_down.gif rename to tetrad-lib/src/main/resources/docs/images/cl/predict_down.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/predict_over.gif b/tetrad-lib/src/main/resources/docs/images/cl/predict_over.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/predict_over.gif rename to tetrad-lib/src/main/resources/docs/images/cl/predict_over.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/random.gif b/tetrad-lib/src/main/resources/docs/images/cl/random.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/random.gif rename to tetrad-lib/src/main/resources/docs/images/cl/random.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/random_new.gif b/tetrad-lib/src/main/resources/docs/images/cl/random_new.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/random_new.gif rename to tetrad-lib/src/main/resources/docs/images/cl/random_new.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/random_new2.gif b/tetrad-lib/src/main/resources/docs/images/cl/random_new2.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/random_new2.gif rename to tetrad-lib/src/main/resources/docs/images/cl/random_new2.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/rededge.gif b/tetrad-lib/src/main/resources/docs/images/cl/rededge.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/rededge.gif rename to tetrad-lib/src/main/resources/docs/images/cl/rededge.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/sample.gif b/tetrad-lib/src/main/resources/docs/images/cl/sample.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/sample.gif rename to tetrad-lib/src/main/resources/docs/images/cl/sample.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/sample_active.gif b/tetrad-lib/src/main/resources/docs/images/cl/sample_active.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/sample_active.gif rename to tetrad-lib/src/main/resources/docs/images/cl/sample_active.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/sample_down.gif b/tetrad-lib/src/main/resources/docs/images/cl/sample_down.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/sample_down.gif rename to tetrad-lib/src/main/resources/docs/images/cl/sample_down.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/sample_guess.gif b/tetrad-lib/src/main/resources/docs/images/cl/sample_guess.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/sample_guess.gif rename to tetrad-lib/src/main/resources/docs/images/cl/sample_guess.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/sample_over.gif b/tetrad-lib/src/main/resources/docs/images/cl/sample_over.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/sample_over.gif rename to tetrad-lib/src/main/resources/docs/images/cl/sample_over.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/sample_valid.gif b/tetrad-lib/src/main/resources/docs/images/cl/sample_valid.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/sample_valid.gif rename to tetrad-lib/src/main/resources/docs/images/cl/sample_valid.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/toolbar_checkans.gif b/tetrad-lib/src/main/resources/docs/images/cl/toolbar_checkans.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/toolbar_checkans.gif rename to tetrad-lib/src/main/resources/docs/images/cl/toolbar_checkans.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/toolbar_checkans_disabled.gif b/tetrad-lib/src/main/resources/docs/images/cl/toolbar_checkans_disabled.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/toolbar_checkans_disabled.gif rename to tetrad-lib/src/main/resources/docs/images/cl/toolbar_checkans_disabled.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/toolbar_finances.gif b/tetrad-lib/src/main/resources/docs/images/cl/toolbar_finances.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/toolbar_finances.gif rename to tetrad-lib/src/main/resources/docs/images/cl/toolbar_finances.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/toolbar_finances_disabled.gif b/tetrad-lib/src/main/resources/docs/images/cl/toolbar_finances_disabled.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/toolbar_finances_disabled.gif rename to tetrad-lib/src/main/resources/docs/images/cl/toolbar_finances_disabled.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/toolbar_instruction.gif b/tetrad-lib/src/main/resources/docs/images/cl/toolbar_instruction.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/toolbar_instruction.gif rename to tetrad-lib/src/main/resources/docs/images/cl/toolbar_instruction.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/toolbar_instruction_disabled.gif b/tetrad-lib/src/main/resources/docs/images/cl/toolbar_instruction_disabled.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/toolbar_instruction_disabled.gif rename to tetrad-lib/src/main/resources/docs/images/cl/toolbar_instruction_disabled.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/toolbar_save.gif b/tetrad-lib/src/main/resources/docs/images/cl/toolbar_save.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/toolbar_save.gif rename to tetrad-lib/src/main/resources/docs/images/cl/toolbar_save.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/toolbar_save_disabled.gif b/tetrad-lib/src/main/resources/docs/images/cl/toolbar_save_disabled.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/toolbar_save_disabled.gif rename to tetrad-lib/src/main/resources/docs/images/cl/toolbar_save_disabled.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/toolbar_showans.gif b/tetrad-lib/src/main/resources/docs/images/cl/toolbar_showans.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/toolbar_showans.gif rename to tetrad-lib/src/main/resources/docs/images/cl/toolbar_showans.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/toolbar_showans_disabled.gif b/tetrad-lib/src/main/resources/docs/images/cl/toolbar_showans_disabled.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/toolbar_showans_disabled.gif rename to tetrad-lib/src/main/resources/docs/images/cl/toolbar_showans_disabled.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/toolbar_submit.gif b/tetrad-lib/src/main/resources/docs/images/cl/toolbar_submit.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/toolbar_submit.gif rename to tetrad-lib/src/main/resources/docs/images/cl/toolbar_submit.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/toolbar_submit_disabled.gif b/tetrad-lib/src/main/resources/docs/images/cl/toolbar_submit_disabled.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/toolbar_submit_disabled.gif rename to tetrad-lib/src/main/resources/docs/images/cl/toolbar_submit_disabled.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/true_graph.gif b/tetrad-lib/src/main/resources/docs/images/cl/true_graph.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/true_graph.gif rename to tetrad-lib/src/main/resources/docs/images/cl/true_graph.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/true_graph_active.gif b/tetrad-lib/src/main/resources/docs/images/cl/true_graph_active.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/true_graph_active.gif rename to tetrad-lib/src/main/resources/docs/images/cl/true_graph_active.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/true_graph_down.gif b/tetrad-lib/src/main/resources/docs/images/cl/true_graph_down.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/true_graph_down.gif rename to tetrad-lib/src/main/resources/docs/images/cl/true_graph_down.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/true_graph_hidden.gif b/tetrad-lib/src/main/resources/docs/images/cl/true_graph_hidden.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/true_graph_hidden.gif rename to tetrad-lib/src/main/resources/docs/images/cl/true_graph_hidden.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/true_graph_hidden_active.gif b/tetrad-lib/src/main/resources/docs/images/cl/true_graph_hidden_active.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/true_graph_hidden_active.gif rename to tetrad-lib/src/main/resources/docs/images/cl/true_graph_hidden_active.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/true_graph_hidden_down.gif b/tetrad-lib/src/main/resources/docs/images/cl/true_graph_hidden_down.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/true_graph_hidden_down.gif rename to tetrad-lib/src/main/resources/docs/images/cl/true_graph_hidden_down.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/true_graph_hidden_over.gif b/tetrad-lib/src/main/resources/docs/images/cl/true_graph_hidden_over.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/true_graph_hidden_over.gif rename to tetrad-lib/src/main/resources/docs/images/cl/true_graph_hidden_over.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/true_graph_over.gif b/tetrad-lib/src/main/resources/docs/images/cl/true_graph_over.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/true_graph_over.gif rename to tetrad-lib/src/main/resources/docs/images/cl/true_graph_over.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/true_manip_graph.gif b/tetrad-lib/src/main/resources/docs/images/cl/true_manip_graph.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/true_manip_graph.gif rename to tetrad-lib/src/main/resources/docs/images/cl/true_manip_graph.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/true_manip_graph_active.gif b/tetrad-lib/src/main/resources/docs/images/cl/true_manip_graph_active.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/true_manip_graph_active.gif rename to tetrad-lib/src/main/resources/docs/images/cl/true_manip_graph_active.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/true_manip_graph_down.gif b/tetrad-lib/src/main/resources/docs/images/cl/true_manip_graph_down.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/true_manip_graph_down.gif rename to tetrad-lib/src/main/resources/docs/images/cl/true_manip_graph_down.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/true_manip_graph_hidden.gif b/tetrad-lib/src/main/resources/docs/images/cl/true_manip_graph_hidden.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/true_manip_graph_hidden.gif rename to tetrad-lib/src/main/resources/docs/images/cl/true_manip_graph_hidden.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/true_manip_graph_hidden_active.gif b/tetrad-lib/src/main/resources/docs/images/cl/true_manip_graph_hidden_active.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/true_manip_graph_hidden_active.gif rename to tetrad-lib/src/main/resources/docs/images/cl/true_manip_graph_hidden_active.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/true_manip_graph_hidden_down.gif b/tetrad-lib/src/main/resources/docs/images/cl/true_manip_graph_hidden_down.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/true_manip_graph_hidden_down.gif rename to tetrad-lib/src/main/resources/docs/images/cl/true_manip_graph_hidden_down.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/true_manip_graph_hidden_over.gif b/tetrad-lib/src/main/resources/docs/images/cl/true_manip_graph_hidden_over.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/true_manip_graph_hidden_over.gif rename to tetrad-lib/src/main/resources/docs/images/cl/true_manip_graph_hidden_over.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/true_manip_graph_over.gif b/tetrad-lib/src/main/resources/docs/images/cl/true_manip_graph_over.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/true_manip_graph_over.gif rename to tetrad-lib/src/main/resources/docs/images/cl/true_manip_graph_over.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/variable3.gif b/tetrad-lib/src/main/resources/docs/images/cl/variable3.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/variable3.gif rename to tetrad-lib/src/main/resources/docs/images/cl/variable3.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cl/visible.gif b/tetrad-lib/src/main/resources/docs/images/cl/visible.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cl/visible.gif rename to tetrad-lib/src/main/resources/docs/images/cl/visible.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cleanupDown.gif b/tetrad-lib/src/main/resources/docs/images/cleanupDown.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cleanupDown.gif rename to tetrad-lib/src/main/resources/docs/images/cleanupDown.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cleanupOff.gif b/tetrad-lib/src/main/resources/docs/images/cleanupOff.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cleanupOff.gif rename to tetrad-lib/src/main/resources/docs/images/cleanupOff.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cleanupRoll.gif b/tetrad-lib/src/main/resources/docs/images/cleanupRoll.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cleanupRoll.gif rename to tetrad-lib/src/main/resources/docs/images/cleanupRoll.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cleanupUp.gif b/tetrad-lib/src/main/resources/docs/images/cleanupUp.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cleanupUp.gif rename to tetrad-lib/src/main/resources/docs/images/cleanupUp.gif diff --git a/tetrad-gui/src/main/resources/resources/images/clear.png b/tetrad-lib/src/main/resources/docs/images/clear.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/clear.png rename to tetrad-lib/src/main/resources/docs/images/clear.png diff --git a/tetrad-gui/src/main/resources/resources/images/clearVariableDown.gif b/tetrad-lib/src/main/resources/docs/images/clearVariableDown.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/clearVariableDown.gif rename to tetrad-lib/src/main/resources/docs/images/clearVariableDown.gif diff --git a/tetrad-gui/src/main/resources/resources/images/clearVariableOff.gif b/tetrad-lib/src/main/resources/docs/images/clearVariableOff.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/clearVariableOff.gif rename to tetrad-lib/src/main/resources/docs/images/clearVariableOff.gif diff --git a/tetrad-gui/src/main/resources/resources/images/clearVariableRoll.gif b/tetrad-lib/src/main/resources/docs/images/clearVariableRoll.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/clearVariableRoll.gif rename to tetrad-lib/src/main/resources/docs/images/clearVariableRoll.gif diff --git a/tetrad-gui/src/main/resources/resources/images/clearVariableUp.gif b/tetrad-lib/src/main/resources/docs/images/clearVariableUp.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/clearVariableUp.gif rename to tetrad-lib/src/main/resources/docs/images/clearVariableUp.gif diff --git a/tetrad-gui/src/main/resources/resources/images/clearedgesDown.gif b/tetrad-lib/src/main/resources/docs/images/clearedgesDown.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/clearedgesDown.gif rename to tetrad-lib/src/main/resources/docs/images/clearedgesDown.gif diff --git a/tetrad-gui/src/main/resources/resources/images/clearedgesOff.gif b/tetrad-lib/src/main/resources/docs/images/clearedgesOff.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/clearedgesOff.gif rename to tetrad-lib/src/main/resources/docs/images/clearedgesOff.gif diff --git a/tetrad-gui/src/main/resources/resources/images/clearedgesRoll.gif b/tetrad-lib/src/main/resources/docs/images/clearedgesRoll.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/clearedgesRoll.gif rename to tetrad-lib/src/main/resources/docs/images/clearedgesRoll.gif diff --git a/tetrad-gui/src/main/resources/resources/images/clearedgesUp.gif b/tetrad-lib/src/main/resources/docs/images/clearedgesUp.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/clearedgesUp.gif rename to tetrad-lib/src/main/resources/docs/images/clearedgesUp.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cleargraphDown.gif b/tetrad-lib/src/main/resources/docs/images/cleargraphDown.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cleargraphDown.gif rename to tetrad-lib/src/main/resources/docs/images/cleargraphDown.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cleargraphOff.gif b/tetrad-lib/src/main/resources/docs/images/cleargraphOff.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cleargraphOff.gif rename to tetrad-lib/src/main/resources/docs/images/cleargraphOff.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cleargraphRoll.gif b/tetrad-lib/src/main/resources/docs/images/cleargraphRoll.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cleargraphRoll.gif rename to tetrad-lib/src/main/resources/docs/images/cleargraphRoll.gif diff --git a/tetrad-gui/src/main/resources/resources/images/cleargraphUp.gif b/tetrad-lib/src/main/resources/docs/images/cleargraphUp.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/cleargraphUp.gif rename to tetrad-lib/src/main/resources/docs/images/cleargraphUp.gif diff --git a/tetrad-gui/src/main/resources/resources/images/close.png b/tetrad-lib/src/main/resources/docs/images/close.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/close.png rename to tetrad-lib/src/main/resources/docs/images/close.png diff --git a/tetrad-gui/src/main/resources/resources/images/compareDown.gif b/tetrad-lib/src/main/resources/docs/images/compareDown.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/compareDown.gif rename to tetrad-lib/src/main/resources/docs/images/compareDown.gif diff --git a/tetrad-gui/src/main/resources/resources/images/compareIcon.gif b/tetrad-lib/src/main/resources/docs/images/compareIcon.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/compareIcon.gif rename to tetrad-lib/src/main/resources/docs/images/compareIcon.gif diff --git a/tetrad-gui/src/main/resources/resources/images/compareOff.gif b/tetrad-lib/src/main/resources/docs/images/compareOff.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/compareOff.gif rename to tetrad-lib/src/main/resources/docs/images/compareOff.gif diff --git a/tetrad-gui/src/main/resources/resources/images/compareRoll.gif b/tetrad-lib/src/main/resources/docs/images/compareRoll.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/compareRoll.gif rename to tetrad-lib/src/main/resources/docs/images/compareRoll.gif diff --git a/tetrad-gui/src/main/resources/resources/images/compareUp.gif b/tetrad-lib/src/main/resources/docs/images/compareUp.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/compareUp.gif rename to tetrad-lib/src/main/resources/docs/images/compareUp.gif diff --git a/tetrad-gui/src/main/resources/resources/images/dataDown.gif b/tetrad-lib/src/main/resources/docs/images/dataDown.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/dataDown.gif rename to tetrad-lib/src/main/resources/docs/images/dataDown.gif diff --git a/tetrad-gui/src/main/resources/resources/images/dataIcon.gif b/tetrad-lib/src/main/resources/docs/images/dataIcon.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/dataIcon.gif rename to tetrad-lib/src/main/resources/docs/images/dataIcon.gif diff --git a/tetrad-gui/src/main/resources/resources/images/dataOff.gif b/tetrad-lib/src/main/resources/docs/images/dataOff.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/dataOff.gif rename to tetrad-lib/src/main/resources/docs/images/dataOff.gif diff --git a/tetrad-gui/src/main/resources/resources/images/dataRoll.gif b/tetrad-lib/src/main/resources/docs/images/dataRoll.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/dataRoll.gif rename to tetrad-lib/src/main/resources/docs/images/dataRoll.gif diff --git a/tetrad-gui/src/main/resources/resources/images/dataUp.gif b/tetrad-lib/src/main/resources/docs/images/dataUp.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/dataUp.gif rename to tetrad-lib/src/main/resources/docs/images/dataUp.gif diff --git a/tetrad-gui/src/main/resources/resources/images/directDown.gif b/tetrad-lib/src/main/resources/docs/images/directDown.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/directDown.gif rename to tetrad-lib/src/main/resources/docs/images/directDown.gif diff --git a/tetrad-gui/src/main/resources/resources/images/directOff.gif b/tetrad-lib/src/main/resources/docs/images/directOff.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/directOff.gif rename to tetrad-lib/src/main/resources/docs/images/directOff.gif diff --git a/tetrad-gui/src/main/resources/resources/images/directRoll.gif b/tetrad-lib/src/main/resources/docs/images/directRoll.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/directRoll.gif rename to tetrad-lib/src/main/resources/docs/images/directRoll.gif diff --git a/tetrad-gui/src/main/resources/resources/images/directUp.gif b/tetrad-lib/src/main/resources/docs/images/directUp.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/directUp.gif rename to tetrad-lib/src/main/resources/docs/images/directUp.gif diff --git a/tetrad-gui/src/main/resources/resources/images/directed2.gif b/tetrad-lib/src/main/resources/docs/images/directed2.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/directed2.gif rename to tetrad-lib/src/main/resources/docs/images/directed2.gif diff --git a/tetrad-gui/src/main/resources/resources/images/directed3.gif b/tetrad-lib/src/main/resources/docs/images/directed3.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/directed3.gif rename to tetrad-lib/src/main/resources/docs/images/directed3.gif diff --git a/tetrad-gui/src/main/resources/resources/images/directedDown.gif b/tetrad-lib/src/main/resources/docs/images/directedDown.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/directedDown.gif rename to tetrad-lib/src/main/resources/docs/images/directedDown.gif diff --git a/tetrad-gui/src/main/resources/resources/images/directedOff.gif b/tetrad-lib/src/main/resources/docs/images/directedOff.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/directedOff.gif rename to tetrad-lib/src/main/resources/docs/images/directedOff.gif diff --git a/tetrad-gui/src/main/resources/resources/images/directedRoll.gif b/tetrad-lib/src/main/resources/docs/images/directedRoll.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/directedRoll.gif rename to tetrad-lib/src/main/resources/docs/images/directedRoll.gif diff --git a/tetrad-gui/src/main/resources/resources/images/directedUp.gif b/tetrad-lib/src/main/resources/docs/images/directedUp.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/directedUp.gif rename to tetrad-lib/src/main/resources/docs/images/directedUp.gif diff --git a/tetrad-gui/src/main/resources/resources/images/estimatorDown.gif b/tetrad-lib/src/main/resources/docs/images/estimatorDown.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/estimatorDown.gif rename to tetrad-lib/src/main/resources/docs/images/estimatorDown.gif diff --git a/tetrad-gui/src/main/resources/resources/images/estimatorIcon.gif b/tetrad-lib/src/main/resources/docs/images/estimatorIcon.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/estimatorIcon.gif rename to tetrad-lib/src/main/resources/docs/images/estimatorIcon.gif diff --git a/tetrad-gui/src/main/resources/resources/images/estimatorOff.gif b/tetrad-lib/src/main/resources/docs/images/estimatorOff.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/estimatorOff.gif rename to tetrad-lib/src/main/resources/docs/images/estimatorOff.gif diff --git a/tetrad-gui/src/main/resources/resources/images/estimatorRoll.gif b/tetrad-lib/src/main/resources/docs/images/estimatorRoll.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/estimatorRoll.gif rename to tetrad-lib/src/main/resources/docs/images/estimatorRoll.gif diff --git a/tetrad-gui/src/main/resources/resources/images/estimatorUp.gif b/tetrad-lib/src/main/resources/docs/images/estimatorUp.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/estimatorUp.gif rename to tetrad-lib/src/main/resources/docs/images/estimatorUp.gif diff --git a/tetrad-gui/src/main/resources/resources/images/fileDown.gif b/tetrad-lib/src/main/resources/docs/images/fileDown.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/fileDown.gif rename to tetrad-lib/src/main/resources/docs/images/fileDown.gif diff --git a/tetrad-gui/src/main/resources/resources/images/fileOff.gif b/tetrad-lib/src/main/resources/docs/images/fileOff.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/fileOff.gif rename to tetrad-lib/src/main/resources/docs/images/fileOff.gif diff --git a/tetrad-gui/src/main/resources/resources/images/fileRoll.gif b/tetrad-lib/src/main/resources/docs/images/fileRoll.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/fileRoll.gif rename to tetrad-lib/src/main/resources/docs/images/fileRoll.gif diff --git a/tetrad-gui/src/main/resources/resources/images/fileUp.gif b/tetrad-lib/src/main/resources/docs/images/fileUp.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/fileUp.gif rename to tetrad-lib/src/main/resources/docs/images/fileUp.gif diff --git a/tetrad-gui/src/main/resources/resources/images/flow.gif b/tetrad-lib/src/main/resources/docs/images/flow.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/flow.gif rename to tetrad-lib/src/main/resources/docs/images/flow.gif diff --git a/tetrad-gui/src/main/resources/resources/images/flowDown.gif b/tetrad-lib/src/main/resources/docs/images/flowDown.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/flowDown.gif rename to tetrad-lib/src/main/resources/docs/images/flowDown.gif diff --git a/tetrad-gui/src/main/resources/resources/images/flowOff.gif b/tetrad-lib/src/main/resources/docs/images/flowOff.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/flowOff.gif rename to tetrad-lib/src/main/resources/docs/images/flowOff.gif diff --git a/tetrad-gui/src/main/resources/resources/images/flowRoll.gif b/tetrad-lib/src/main/resources/docs/images/flowRoll.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/flowRoll.gif rename to tetrad-lib/src/main/resources/docs/images/flowRoll.gif diff --git a/tetrad-gui/src/main/resources/resources/images/flowUp.gif b/tetrad-lib/src/main/resources/docs/images/flowUp.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/flowUp.gif rename to tetrad-lib/src/main/resources/docs/images/flowUp.gif diff --git a/tetrad-gui/src/main/resources/resources/images/graduation_hat1.png b/tetrad-lib/src/main/resources/docs/images/graduation_hat1.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/graduation_hat1.png rename to tetrad-lib/src/main/resources/docs/images/graduation_hat1.png diff --git a/tetrad-gui/src/main/resources/resources/images/graphDown.gif b/tetrad-lib/src/main/resources/docs/images/graphDown.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/graphDown.gif rename to tetrad-lib/src/main/resources/docs/images/graphDown.gif diff --git a/tetrad-gui/src/main/resources/resources/images/graphIcon.gif b/tetrad-lib/src/main/resources/docs/images/graphIcon.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/graphIcon.gif rename to tetrad-lib/src/main/resources/docs/images/graphIcon.gif diff --git a/tetrad-gui/src/main/resources/resources/images/graphOff.gif b/tetrad-lib/src/main/resources/docs/images/graphOff.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/graphOff.gif rename to tetrad-lib/src/main/resources/docs/images/graphOff.gif diff --git a/tetrad-gui/src/main/resources/resources/images/graphRoll.gif b/tetrad-lib/src/main/resources/docs/images/graphRoll.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/graphRoll.gif rename to tetrad-lib/src/main/resources/docs/images/graphRoll.gif diff --git a/tetrad-gui/src/main/resources/resources/images/graphUp.gif b/tetrad-lib/src/main/resources/docs/images/graphUp.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/graphUp.gif rename to tetrad-lib/src/main/resources/docs/images/graphUp.gif diff --git a/tetrad-gui/src/main/resources/resources/images/ico1.gif b/tetrad-lib/src/main/resources/docs/images/ico1.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/ico1.gif rename to tetrad-lib/src/main/resources/docs/images/ico1.gif diff --git a/tetrad-gui/src/main/resources/resources/images/icontry2.gif b/tetrad-lib/src/main/resources/docs/images/icontry2.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/icontry2.gif rename to tetrad-lib/src/main/resources/docs/images/icontry2.gif diff --git a/tetrad-gui/src/main/resources/resources/images/imDown.gif b/tetrad-lib/src/main/resources/docs/images/imDown.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/imDown.gif rename to tetrad-lib/src/main/resources/docs/images/imDown.gif diff --git a/tetrad-gui/src/main/resources/resources/images/imIcon.gif b/tetrad-lib/src/main/resources/docs/images/imIcon.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/imIcon.gif rename to tetrad-lib/src/main/resources/docs/images/imIcon.gif diff --git a/tetrad-gui/src/main/resources/resources/images/imOff.gif b/tetrad-lib/src/main/resources/docs/images/imOff.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/imOff.gif rename to tetrad-lib/src/main/resources/docs/images/imOff.gif diff --git a/tetrad-gui/src/main/resources/resources/images/imRoll.gif b/tetrad-lib/src/main/resources/docs/images/imRoll.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/imRoll.gif rename to tetrad-lib/src/main/resources/docs/images/imRoll.gif diff --git a/tetrad-gui/src/main/resources/resources/images/imUp.gif b/tetrad-lib/src/main/resources/docs/images/imUp.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/imUp.gif rename to tetrad-lib/src/main/resources/docs/images/imUp.gif diff --git a/tetrad-gui/src/main/resources/resources/images/info.png b/tetrad-lib/src/main/resources/docs/images/info.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/info.png rename to tetrad-lib/src/main/resources/docs/images/info.png diff --git a/tetrad-gui/src/main/resources/resources/images/information-icon.png b/tetrad-lib/src/main/resources/docs/images/information-icon.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/information-icon.png rename to tetrad-lib/src/main/resources/docs/images/information-icon.png diff --git a/tetrad-gui/src/main/resources/resources/images/information_small.png b/tetrad-lib/src/main/resources/docs/images/information_small.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/information_small.png rename to tetrad-lib/src/main/resources/docs/images/information_small.png diff --git a/tetrad-gui/src/main/resources/resources/images/information_small_white.png b/tetrad-lib/src/main/resources/docs/images/information_small_white.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/information_small_white.png rename to tetrad-lib/src/main/resources/docs/images/information_small_white.png diff --git a/tetrad-gui/src/main/resources/resources/images/knowDown.gif b/tetrad-lib/src/main/resources/docs/images/knowDown.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/knowDown.gif rename to tetrad-lib/src/main/resources/docs/images/knowDown.gif diff --git a/tetrad-gui/src/main/resources/resources/images/knowIcon.gif b/tetrad-lib/src/main/resources/docs/images/knowIcon.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/knowIcon.gif rename to tetrad-lib/src/main/resources/docs/images/knowIcon.gif diff --git a/tetrad-gui/src/main/resources/resources/images/knowOff.gif b/tetrad-lib/src/main/resources/docs/images/knowOff.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/knowOff.gif rename to tetrad-lib/src/main/resources/docs/images/knowOff.gif diff --git a/tetrad-gui/src/main/resources/resources/images/knowRoll.gif b/tetrad-lib/src/main/resources/docs/images/knowRoll.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/knowRoll.gif rename to tetrad-lib/src/main/resources/docs/images/knowRoll.gif diff --git a/tetrad-gui/src/main/resources/resources/images/knowUp.gif b/tetrad-lib/src/main/resources/docs/images/knowUp.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/knowUp.gif rename to tetrad-lib/src/main/resources/docs/images/knowUp.gif diff --git a/tetrad-gui/src/main/resources/resources/images/latent2.gif b/tetrad-lib/src/main/resources/docs/images/latent2.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/latent2.gif rename to tetrad-lib/src/main/resources/docs/images/latent2.gif diff --git a/tetrad-gui/src/main/resources/resources/images/latent3.gif b/tetrad-lib/src/main/resources/docs/images/latent3.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/latent3.gif rename to tetrad-lib/src/main/resources/docs/images/latent3.gif diff --git a/tetrad-gui/src/main/resources/resources/images/latentDown.gif b/tetrad-lib/src/main/resources/docs/images/latentDown.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/latentDown.gif rename to tetrad-lib/src/main/resources/docs/images/latentDown.gif diff --git a/tetrad-gui/src/main/resources/resources/images/latentOff.gif b/tetrad-lib/src/main/resources/docs/images/latentOff.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/latentOff.gif rename to tetrad-lib/src/main/resources/docs/images/latentOff.gif diff --git a/tetrad-gui/src/main/resources/resources/images/latentRoll.gif b/tetrad-lib/src/main/resources/docs/images/latentRoll.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/latentRoll.gif rename to tetrad-lib/src/main/resources/docs/images/latentRoll.gif diff --git a/tetrad-gui/src/main/resources/resources/images/latentUp.gif b/tetrad-lib/src/main/resources/docs/images/latentUp.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/latentUp.gif rename to tetrad-lib/src/main/resources/docs/images/latentUp.gif diff --git a/tetrad-gui/src/main/resources/resources/images/miscB62.gif b/tetrad-lib/src/main/resources/docs/images/miscB62.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/miscB62.gif rename to tetrad-lib/src/main/resources/docs/images/miscB62.gif diff --git a/tetrad-gui/src/main/resources/resources/images/move.gif b/tetrad-lib/src/main/resources/docs/images/move.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/move.gif rename to tetrad-lib/src/main/resources/docs/images/move.gif diff --git a/tetrad-gui/src/main/resources/resources/images/move2.gif b/tetrad-lib/src/main/resources/docs/images/move2.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/move2.gif rename to tetrad-lib/src/main/resources/docs/images/move2.gif diff --git a/tetrad-gui/src/main/resources/resources/images/move3.gif b/tetrad-lib/src/main/resources/docs/images/move3.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/move3.gif rename to tetrad-lib/src/main/resources/docs/images/move3.gif diff --git a/tetrad-gui/src/main/resources/resources/images/moveDown.gif b/tetrad-lib/src/main/resources/docs/images/moveDown.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/moveDown.gif rename to tetrad-lib/src/main/resources/docs/images/moveDown.gif diff --git a/tetrad-gui/src/main/resources/resources/images/moveOff.gif b/tetrad-lib/src/main/resources/docs/images/moveOff.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/moveOff.gif rename to tetrad-lib/src/main/resources/docs/images/moveOff.gif diff --git a/tetrad-gui/src/main/resources/resources/images/moveRoll.gif b/tetrad-lib/src/main/resources/docs/images/moveRoll.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/moveRoll.gif rename to tetrad-lib/src/main/resources/docs/images/moveRoll.gif diff --git a/tetrad-gui/src/main/resources/resources/images/moveUp.gif b/tetrad-lib/src/main/resources/docs/images/moveUp.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/moveUp.gif rename to tetrad-lib/src/main/resources/docs/images/moveUp.gif diff --git a/tetrad-gui/src/main/resources/resources/images/nondirected2.gif b/tetrad-lib/src/main/resources/docs/images/nondirected2.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/nondirected2.gif rename to tetrad-lib/src/main/resources/docs/images/nondirected2.gif diff --git a/tetrad-gui/src/main/resources/resources/images/nondirected3.gif b/tetrad-lib/src/main/resources/docs/images/nondirected3.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/nondirected3.gif rename to tetrad-lib/src/main/resources/docs/images/nondirected3.gif diff --git a/tetrad-gui/src/main/resources/resources/images/nondirectedDown.gif b/tetrad-lib/src/main/resources/docs/images/nondirectedDown.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/nondirectedDown.gif rename to tetrad-lib/src/main/resources/docs/images/nondirectedDown.gif diff --git a/tetrad-gui/src/main/resources/resources/images/nondirectedOff.gif b/tetrad-lib/src/main/resources/docs/images/nondirectedOff.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/nondirectedOff.gif rename to tetrad-lib/src/main/resources/docs/images/nondirectedOff.gif diff --git a/tetrad-gui/src/main/resources/resources/images/nondirectedRoll.gif b/tetrad-lib/src/main/resources/docs/images/nondirectedRoll.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/nondirectedRoll.gif rename to tetrad-lib/src/main/resources/docs/images/nondirectedRoll.gif diff --git a/tetrad-gui/src/main/resources/resources/images/nondirectedUp.gif b/tetrad-lib/src/main/resources/docs/images/nondirectedUp.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/nondirectedUp.gif rename to tetrad-lib/src/main/resources/docs/images/nondirectedUp.gif diff --git a/tetrad-gui/src/main/resources/resources/images/note.png b/tetrad-lib/src/main/resources/docs/images/note.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/note.png rename to tetrad-lib/src/main/resources/docs/images/note.png diff --git a/tetrad-gui/src/main/resources/resources/images/partiallyoriented2.gif b/tetrad-lib/src/main/resources/docs/images/partiallyoriented2.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/partiallyoriented2.gif rename to tetrad-lib/src/main/resources/docs/images/partiallyoriented2.gif diff --git a/tetrad-gui/src/main/resources/resources/images/partiallyoriented3.gif b/tetrad-lib/src/main/resources/docs/images/partiallyoriented3.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/partiallyoriented3.gif rename to tetrad-lib/src/main/resources/docs/images/partiallyoriented3.gif diff --git a/tetrad-gui/src/main/resources/resources/images/partiallyorientedDown.gif b/tetrad-lib/src/main/resources/docs/images/partiallyorientedDown.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/partiallyorientedDown.gif rename to tetrad-lib/src/main/resources/docs/images/partiallyorientedDown.gif diff --git a/tetrad-gui/src/main/resources/resources/images/partiallyorientedOff.gif b/tetrad-lib/src/main/resources/docs/images/partiallyorientedOff.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/partiallyorientedOff.gif rename to tetrad-lib/src/main/resources/docs/images/partiallyorientedOff.gif diff --git a/tetrad-gui/src/main/resources/resources/images/partiallyorientedRoll.gif b/tetrad-lib/src/main/resources/docs/images/partiallyorientedRoll.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/partiallyorientedRoll.gif rename to tetrad-lib/src/main/resources/docs/images/partiallyorientedRoll.gif diff --git a/tetrad-gui/src/main/resources/resources/images/partiallyorientedUp.gif b/tetrad-lib/src/main/resources/docs/images/partiallyorientedUp.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/partiallyorientedUp.gif rename to tetrad-lib/src/main/resources/docs/images/partiallyorientedUp.gif diff --git a/tetrad-gui/src/main/resources/resources/images/pmDown.gif b/tetrad-lib/src/main/resources/docs/images/pmDown.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/pmDown.gif rename to tetrad-lib/src/main/resources/docs/images/pmDown.gif diff --git a/tetrad-gui/src/main/resources/resources/images/pmIcon.gif b/tetrad-lib/src/main/resources/docs/images/pmIcon.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/pmIcon.gif rename to tetrad-lib/src/main/resources/docs/images/pmIcon.gif diff --git a/tetrad-gui/src/main/resources/resources/images/pmOff.gif b/tetrad-lib/src/main/resources/docs/images/pmOff.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/pmOff.gif rename to tetrad-lib/src/main/resources/docs/images/pmOff.gif diff --git a/tetrad-gui/src/main/resources/resources/images/pmRoll.gif b/tetrad-lib/src/main/resources/docs/images/pmRoll.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/pmRoll.gif rename to tetrad-lib/src/main/resources/docs/images/pmRoll.gif diff --git a/tetrad-gui/src/main/resources/resources/images/pmUp.gif b/tetrad-lib/src/main/resources/docs/images/pmUp.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/pmUp.gif rename to tetrad-lib/src/main/resources/docs/images/pmUp.gif diff --git a/tetrad-gui/src/main/resources/resources/images/randomDown.gif b/tetrad-lib/src/main/resources/docs/images/randomDown.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/randomDown.gif rename to tetrad-lib/src/main/resources/docs/images/randomDown.gif diff --git a/tetrad-gui/src/main/resources/resources/images/randomIcon.gif b/tetrad-lib/src/main/resources/docs/images/randomIcon.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/randomIcon.gif rename to tetrad-lib/src/main/resources/docs/images/randomIcon.gif diff --git a/tetrad-gui/src/main/resources/resources/images/randomOff.gif b/tetrad-lib/src/main/resources/docs/images/randomOff.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/randomOff.gif rename to tetrad-lib/src/main/resources/docs/images/randomOff.gif diff --git a/tetrad-gui/src/main/resources/resources/images/randomRoll.gif b/tetrad-lib/src/main/resources/docs/images/randomRoll.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/randomRoll.gif rename to tetrad-lib/src/main/resources/docs/images/randomRoll.gif diff --git a/tetrad-gui/src/main/resources/resources/images/randomUp.gif b/tetrad-lib/src/main/resources/docs/images/randomUp.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/randomUp.gif rename to tetrad-lib/src/main/resources/docs/images/randomUp.gif diff --git a/tetrad-gui/src/main/resources/resources/images/repeatDown.gif b/tetrad-lib/src/main/resources/docs/images/repeatDown.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/repeatDown.gif rename to tetrad-lib/src/main/resources/docs/images/repeatDown.gif diff --git a/tetrad-gui/src/main/resources/resources/images/repeatOff.gif b/tetrad-lib/src/main/resources/docs/images/repeatOff.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/repeatOff.gif rename to tetrad-lib/src/main/resources/docs/images/repeatOff.gif diff --git a/tetrad-gui/src/main/resources/resources/images/repeatRoll.gif b/tetrad-lib/src/main/resources/docs/images/repeatRoll.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/repeatRoll.gif rename to tetrad-lib/src/main/resources/docs/images/repeatRoll.gif diff --git a/tetrad-gui/src/main/resources/resources/images/repeatUp.gif b/tetrad-lib/src/main/resources/docs/images/repeatUp.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/repeatUp.gif rename to tetrad-lib/src/main/resources/docs/images/repeatUp.gif diff --git a/tetrad-gui/src/main/resources/resources/images/save.png b/tetrad-lib/src/main/resources/docs/images/save.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/save.png rename to tetrad-lib/src/main/resources/docs/images/save.png diff --git a/tetrad-gui/src/main/resources/resources/images/searchDown.gif b/tetrad-lib/src/main/resources/docs/images/searchDown.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/searchDown.gif rename to tetrad-lib/src/main/resources/docs/images/searchDown.gif diff --git a/tetrad-gui/src/main/resources/resources/images/searchIcon.gif b/tetrad-lib/src/main/resources/docs/images/searchIcon.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/searchIcon.gif rename to tetrad-lib/src/main/resources/docs/images/searchIcon.gif diff --git a/tetrad-gui/src/main/resources/resources/images/searchOff.gif b/tetrad-lib/src/main/resources/docs/images/searchOff.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/searchOff.gif rename to tetrad-lib/src/main/resources/docs/images/searchOff.gif diff --git a/tetrad-gui/src/main/resources/resources/images/searchRoll.gif b/tetrad-lib/src/main/resources/docs/images/searchRoll.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/searchRoll.gif rename to tetrad-lib/src/main/resources/docs/images/searchRoll.gif diff --git a/tetrad-gui/src/main/resources/resources/images/searchUp.gif b/tetrad-lib/src/main/resources/docs/images/searchUp.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/searchUp.gif rename to tetrad-lib/src/main/resources/docs/images/searchUp.gif diff --git a/tetrad-gui/src/main/resources/resources/images/smallbidirectedDown.gif b/tetrad-lib/src/main/resources/docs/images/smallbidirectedDown.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/smallbidirectedDown.gif rename to tetrad-lib/src/main/resources/docs/images/smallbidirectedDown.gif diff --git a/tetrad-gui/src/main/resources/resources/images/smallbidirectedOff.gif b/tetrad-lib/src/main/resources/docs/images/smallbidirectedOff.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/smallbidirectedOff.gif rename to tetrad-lib/src/main/resources/docs/images/smallbidirectedOff.gif diff --git a/tetrad-gui/src/main/resources/resources/images/smallbidirectedRoll.gif b/tetrad-lib/src/main/resources/docs/images/smallbidirectedRoll.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/smallbidirectedRoll.gif rename to tetrad-lib/src/main/resources/docs/images/smallbidirectedRoll.gif diff --git a/tetrad-gui/src/main/resources/resources/images/smallbidirectedUp.gif b/tetrad-lib/src/main/resources/docs/images/smallbidirectedUp.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/smallbidirectedUp.gif rename to tetrad-lib/src/main/resources/docs/images/smallbidirectedUp.gif diff --git a/tetrad-gui/src/main/resources/resources/images/smalldirectedDown.gif b/tetrad-lib/src/main/resources/docs/images/smalldirectedDown.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/smalldirectedDown.gif rename to tetrad-lib/src/main/resources/docs/images/smalldirectedDown.gif diff --git a/tetrad-gui/src/main/resources/resources/images/smalldirectedOff.gif b/tetrad-lib/src/main/resources/docs/images/smalldirectedOff.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/smalldirectedOff.gif rename to tetrad-lib/src/main/resources/docs/images/smalldirectedOff.gif diff --git a/tetrad-gui/src/main/resources/resources/images/smalldirectedRoll.gif b/tetrad-lib/src/main/resources/docs/images/smalldirectedRoll.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/smalldirectedRoll.gif rename to tetrad-lib/src/main/resources/docs/images/smalldirectedRoll.gif diff --git a/tetrad-gui/src/main/resources/resources/images/smalldirectedUp.gif b/tetrad-lib/src/main/resources/docs/images/smalldirectedUp.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/smalldirectedUp.gif rename to tetrad-lib/src/main/resources/docs/images/smalldirectedUp.gif diff --git a/tetrad-gui/src/main/resources/resources/images/smallhalfdirectedDown.gif b/tetrad-lib/src/main/resources/docs/images/smallhalfdirectedDown.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/smallhalfdirectedDown.gif rename to tetrad-lib/src/main/resources/docs/images/smallhalfdirectedDown.gif diff --git a/tetrad-gui/src/main/resources/resources/images/smallhalfdirectedOff.gif b/tetrad-lib/src/main/resources/docs/images/smallhalfdirectedOff.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/smallhalfdirectedOff.gif rename to tetrad-lib/src/main/resources/docs/images/smallhalfdirectedOff.gif diff --git a/tetrad-gui/src/main/resources/resources/images/smallhalfdirectedRoll.gif b/tetrad-lib/src/main/resources/docs/images/smallhalfdirectedRoll.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/smallhalfdirectedRoll.gif rename to tetrad-lib/src/main/resources/docs/images/smallhalfdirectedRoll.gif diff --git a/tetrad-gui/src/main/resources/resources/images/smallhalfdirectedUp.gif b/tetrad-lib/src/main/resources/docs/images/smallhalfdirectedUp.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/smallhalfdirectedUp.gif rename to tetrad-lib/src/main/resources/docs/images/smallhalfdirectedUp.gif diff --git a/tetrad-gui/src/main/resources/resources/images/smallundirectedDown.gif b/tetrad-lib/src/main/resources/docs/images/smallundirectedDown.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/smallundirectedDown.gif rename to tetrad-lib/src/main/resources/docs/images/smallundirectedDown.gif diff --git a/tetrad-gui/src/main/resources/resources/images/smallundirectedOff.gif b/tetrad-lib/src/main/resources/docs/images/smallundirectedOff.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/smallundirectedOff.gif rename to tetrad-lib/src/main/resources/docs/images/smallundirectedOff.gif diff --git a/tetrad-gui/src/main/resources/resources/images/smallundirectedRoll.gif b/tetrad-lib/src/main/resources/docs/images/smallundirectedRoll.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/smallundirectedRoll.gif rename to tetrad-lib/src/main/resources/docs/images/smallundirectedRoll.gif diff --git a/tetrad-gui/src/main/resources/resources/images/smallundirectedUp.gif b/tetrad-lib/src/main/resources/docs/images/smallundirectedUp.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/smallundirectedUp.gif rename to tetrad-lib/src/main/resources/docs/images/smallundirectedUp.gif diff --git a/tetrad-gui/src/main/resources/resources/images/smallunorientedDown.gif b/tetrad-lib/src/main/resources/docs/images/smallunorientedDown.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/smallunorientedDown.gif rename to tetrad-lib/src/main/resources/docs/images/smallunorientedDown.gif diff --git a/tetrad-gui/src/main/resources/resources/images/smallunorientedOff.gif b/tetrad-lib/src/main/resources/docs/images/smallunorientedOff.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/smallunorientedOff.gif rename to tetrad-lib/src/main/resources/docs/images/smallunorientedOff.gif diff --git a/tetrad-gui/src/main/resources/resources/images/smallunorientedRoll.gif b/tetrad-lib/src/main/resources/docs/images/smallunorientedRoll.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/smallunorientedRoll.gif rename to tetrad-lib/src/main/resources/docs/images/smallunorientedRoll.gif diff --git a/tetrad-gui/src/main/resources/resources/images/smallunorientedUp.gif b/tetrad-lib/src/main/resources/docs/images/smallunorientedUp.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/smallunorientedUp.gif rename to tetrad-lib/src/main/resources/docs/images/smallunorientedUp.gif diff --git a/tetrad-gui/src/main/resources/resources/images/system_info.html b/tetrad-lib/src/main/resources/docs/images/system_info.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/system_info.html rename to tetrad-lib/src/main/resources/docs/images/system_info.html diff --git a/tetrad-gui/src/main/resources/resources/images/system_info_alt.png b/tetrad-lib/src/main/resources/docs/images/system_info_alt.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/system_info_alt.png rename to tetrad-lib/src/main/resources/docs/images/system_info_alt.png diff --git a/tetrad-gui/src/main/resources/resources/images/tableDown.gif b/tetrad-lib/src/main/resources/docs/images/tableDown.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/tableDown.gif rename to tetrad-lib/src/main/resources/docs/images/tableDown.gif diff --git a/tetrad-gui/src/main/resources/resources/images/tableOff.gif b/tetrad-lib/src/main/resources/docs/images/tableOff.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/tableOff.gif rename to tetrad-lib/src/main/resources/docs/images/tableOff.gif diff --git a/tetrad-gui/src/main/resources/resources/images/tableRoll.gif b/tetrad-lib/src/main/resources/docs/images/tableRoll.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/tableRoll.gif rename to tetrad-lib/src/main/resources/docs/images/tableRoll.gif diff --git a/tetrad-gui/src/main/resources/resources/images/tableUp.gif b/tetrad-lib/src/main/resources/docs/images/tableUp.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/tableUp.gif rename to tetrad-lib/src/main/resources/docs/images/tableUp.gif diff --git a/tetrad-gui/src/main/resources/resources/images/tetradicon.gif b/tetrad-lib/src/main/resources/docs/images/tetradicon.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/tetradicon.gif rename to tetrad-lib/src/main/resources/docs/images/tetradicon.gif diff --git a/tetrad-gui/src/main/resources/resources/images/three_arrows.gif b/tetrad-lib/src/main/resources/docs/images/three_arrows.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/three_arrows.gif rename to tetrad-lib/src/main/resources/docs/images/three_arrows.gif diff --git a/tetrad-gui/src/main/resources/resources/images/three_circles.gif b/tetrad-lib/src/main/resources/docs/images/three_circles.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/three_circles.gif rename to tetrad-lib/src/main/resources/docs/images/three_circles.gif diff --git a/tetrad-gui/src/main/resources/resources/images/toolbar_get_info.png b/tetrad-lib/src/main/resources/docs/images/toolbar_get_info.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/toolbar_get_info.png rename to tetrad-lib/src/main/resources/docs/images/toolbar_get_info.png diff --git a/tetrad-gui/src/main/resources/resources/images/tyler16.png b/tetrad-lib/src/main/resources/docs/images/tyler16.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/tyler16.png rename to tetrad-lib/src/main/resources/docs/images/tyler16.png diff --git a/tetrad-gui/src/main/resources/resources/images/tyler32.png b/tetrad-lib/src/main/resources/docs/images/tyler32.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/tyler32.png rename to tetrad-lib/src/main/resources/docs/images/tyler32.png diff --git a/tetrad-gui/src/main/resources/resources/images/undirected3.gif b/tetrad-lib/src/main/resources/docs/images/undirected3.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/undirected3.gif rename to tetrad-lib/src/main/resources/docs/images/undirected3.gif diff --git a/tetrad-gui/src/main/resources/resources/images/undirectedDown.gif b/tetrad-lib/src/main/resources/docs/images/undirectedDown.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/undirectedDown.gif rename to tetrad-lib/src/main/resources/docs/images/undirectedDown.gif diff --git a/tetrad-gui/src/main/resources/resources/images/undirectedOff.gif b/tetrad-lib/src/main/resources/docs/images/undirectedOff.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/undirectedOff.gif rename to tetrad-lib/src/main/resources/docs/images/undirectedOff.gif diff --git a/tetrad-gui/src/main/resources/resources/images/undirectedRoll.gif b/tetrad-lib/src/main/resources/docs/images/undirectedRoll.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/undirectedRoll.gif rename to tetrad-lib/src/main/resources/docs/images/undirectedRoll.gif diff --git a/tetrad-gui/src/main/resources/resources/images/undirectedUp.gif b/tetrad-lib/src/main/resources/docs/images/undirectedUp.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/undirectedUp.gif rename to tetrad-lib/src/main/resources/docs/images/undirectedUp.gif diff --git a/tetrad-gui/src/main/resources/resources/images/unorientedUp.gif b/tetrad-lib/src/main/resources/docs/images/unorientedUp.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/unorientedUp.gif rename to tetrad-lib/src/main/resources/docs/images/unorientedUp.gif diff --git a/tetrad-gui/src/main/resources/resources/images/updaterDown.gif b/tetrad-lib/src/main/resources/docs/images/updaterDown.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/updaterDown.gif rename to tetrad-lib/src/main/resources/docs/images/updaterDown.gif diff --git a/tetrad-gui/src/main/resources/resources/images/updaterIcon.gif b/tetrad-lib/src/main/resources/docs/images/updaterIcon.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/updaterIcon.gif rename to tetrad-lib/src/main/resources/docs/images/updaterIcon.gif diff --git a/tetrad-gui/src/main/resources/resources/images/updaterOff.gif b/tetrad-lib/src/main/resources/docs/images/updaterOff.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/updaterOff.gif rename to tetrad-lib/src/main/resources/docs/images/updaterOff.gif diff --git a/tetrad-gui/src/main/resources/resources/images/updaterRoll.gif b/tetrad-lib/src/main/resources/docs/images/updaterRoll.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/updaterRoll.gif rename to tetrad-lib/src/main/resources/docs/images/updaterRoll.gif diff --git a/tetrad-gui/src/main/resources/resources/images/updaterUp.gif b/tetrad-lib/src/main/resources/docs/images/updaterUp.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/updaterUp.gif rename to tetrad-lib/src/main/resources/docs/images/updaterUp.gif diff --git a/tetrad-gui/src/main/resources/resources/images/variable2.gif b/tetrad-lib/src/main/resources/docs/images/variable2.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/variable2.gif rename to tetrad-lib/src/main/resources/docs/images/variable2.gif diff --git a/tetrad-gui/src/main/resources/resources/images/variable3.gif b/tetrad-lib/src/main/resources/docs/images/variable3.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/variable3.gif rename to tetrad-lib/src/main/resources/docs/images/variable3.gif diff --git a/tetrad-gui/src/main/resources/resources/images/variableDown.gif b/tetrad-lib/src/main/resources/docs/images/variableDown.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/variableDown.gif rename to tetrad-lib/src/main/resources/docs/images/variableDown.gif diff --git a/tetrad-gui/src/main/resources/resources/images/variableOff.gif b/tetrad-lib/src/main/resources/docs/images/variableOff.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/variableOff.gif rename to tetrad-lib/src/main/resources/docs/images/variableOff.gif diff --git a/tetrad-gui/src/main/resources/resources/images/variableRoll.gif b/tetrad-lib/src/main/resources/docs/images/variableRoll.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/variableRoll.gif rename to tetrad-lib/src/main/resources/docs/images/variableRoll.gif diff --git a/tetrad-gui/src/main/resources/resources/images/variableUp.gif b/tetrad-lib/src/main/resources/docs/images/variableUp.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/variableUp.gif rename to tetrad-lib/src/main/resources/docs/images/variableUp.gif diff --git a/tetrad-gui/src/main/resources/resources/images/zoomDown.gif b/tetrad-lib/src/main/resources/docs/images/zoomDown.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/zoomDown.gif rename to tetrad-lib/src/main/resources/docs/images/zoomDown.gif diff --git a/tetrad-gui/src/main/resources/resources/images/zoomOff.gif b/tetrad-lib/src/main/resources/docs/images/zoomOff.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/zoomOff.gif rename to tetrad-lib/src/main/resources/docs/images/zoomOff.gif diff --git a/tetrad-gui/src/main/resources/resources/images/zoomRoll.gif b/tetrad-lib/src/main/resources/docs/images/zoomRoll.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/zoomRoll.gif rename to tetrad-lib/src/main/resources/docs/images/zoomRoll.gif diff --git a/tetrad-gui/src/main/resources/resources/images/zoomUp.gif b/tetrad-lib/src/main/resources/docs/images/zoomUp.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/images/zoomUp.gif rename to tetrad-lib/src/main/resources/docs/images/zoomUp.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/Map.jhm b/tetrad-lib/src/main/resources/docs/javahelp/Map.jhm similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/Map.jhm rename to tetrad-lib/src/main/resources/docs/javahelp/Map.jhm diff --git a/tetrad-gui/src/main/resources/resources/javahelp/TetradHelp.hs b/tetrad-lib/src/main/resources/docs/javahelp/TetradHelp.hs similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/TetradHelp.hs rename to tetrad-lib/src/main/resources/docs/javahelp/TetradHelp.hs diff --git a/tetrad-gui/src/main/resources/resources/javahelp/TetradHelpIndex.xml b/tetrad-lib/src/main/resources/docs/javahelp/TetradHelpIndex.xml similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/TetradHelpIndex.xml rename to tetrad-lib/src/main/resources/docs/javahelp/TetradHelpIndex.xml diff --git a/tetrad-gui/src/main/resources/resources/javahelp/TetradHelpTOC.xml b/tetrad-lib/src/main/resources/docs/javahelp/TetradHelpTOC.xml similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/TetradHelpTOC.xml rename to tetrad-lib/src/main/resources/docs/javahelp/TetradHelpTOC.xml diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/classify/classify_box.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/classify/classify_box.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/classify/classify_box.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/classify/classify_box.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/compare/compare_box.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/compare/compare_box.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/compare/compare_box.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/compare/compare_box.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/data/data_box.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/data/data_box.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/data/data_box.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/data/data_box.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/data/data_loader.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/data/data_loader.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/data/data_loader.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/data/data_loader.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/data/data_set_list.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/data/data_set_list.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/data/data_set_list.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/data/data_set_list.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/each_box_explained.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/each_box_explained.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/each_box_explained.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/each_box_explained.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/each_module_explained.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/each_module_explained.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/each_module_explained.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/each_module_explained.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/estimate/dirichlet_estimator.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/estimate/dirichlet_estimator.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/estimate/dirichlet_estimator.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/estimate/dirichlet_estimator.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/estimate/estimate_box.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/estimate/estimate_box.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/estimate/estimate_box.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/estimate/estimate_box.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/estimate/ml_bayes_estimator.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/estimate/ml_bayes_estimator.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/estimate/ml_bayes_estimator.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/estimate/ml_bayes_estimator.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/estimate/sem_estimator.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/estimate/sem_estimator.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/estimate/sem_estimator.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/estimate/sem_estimator.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/graph/dag.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/graph/dag.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/graph/dag.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/graph/dag.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/graph/general_graph.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/graph/general_graph.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/graph/general_graph.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/graph/general_graph.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/graph/graph_box.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/graph/graph_box.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/graph/graph_box.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/graph/graph_box.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/graph/sem_graph.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/graph/sem_graph.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/graph/sem_graph.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/graph/sem_graph.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/graph/time_graph.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/graph/time_graph.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/graph/time_graph.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/graph/time_graph.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/im/bayes_im.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/im/bayes_im.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/im/bayes_im.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/im/bayes_im.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/im/dirichlet_bayes_im.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/im/dirichlet_bayes_im.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/im/dirichlet_bayes_im.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/im/dirichlet_bayes_im.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/im/im_box.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/im/im_box.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/im/im_box.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/im/im_box.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/im/sem_im.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/im/sem_im.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/im/sem_im.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/im/sem_im.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/manipulated_data/manipulated2.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/manipulated_data/manipulated2.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/manipulated_data/manipulated2.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/manipulated_data/manipulated2.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/manipulated_data/manipulated3.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/manipulated_data/manipulated3.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/manipulated_data/manipulated3.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/manipulated_data/manipulated3.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/manipulated_data/manipulated_data_box.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/manipulated_data/manipulated_data_box.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/manipulated_data/manipulated_data_box.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/manipulated_data/manipulated_data_box.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/pm/bayes_pm.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/pm/bayes_pm.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/pm/bayes_pm.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/pm/bayes_pm.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/pm/pm_box.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/pm/pm_box.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/pm/pm_box.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/pm/pm_box.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/pm/sem_pm.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/pm/sem_pm.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/pm/sem_pm.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/pm/sem_pm.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/regression/logistic_regression.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/regression/logistic_regression.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/regression/logistic_regression.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/regression/logistic_regression.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/regression/multiple_linear_regression.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/regression/multiple_linear_regression.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/regression/multiple_linear_regression.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/regression/multiple_linear_regression.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/regression/regression_box.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/regression/regression_box.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/regression/regression_box.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/regression/regression_box.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/bdeu.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/bdeu.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/bdeu.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/bdeu.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/bpc.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/bpc.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/bpc.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/bpc.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/ccd.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/ccd.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/ccd.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/ccd.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/cfci.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/cfci.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/cfci.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/cfci.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/chisquare.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/chisquare.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/chisquare.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/chisquare.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/conditional_correlation.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/conditional_correlation.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/conditional_correlation.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/conditional_correlation.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/conditional_gaussian_bic.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/conditional_gaussian_bic.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/conditional_gaussian_bic.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/conditional_gaussian_bic.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/conditional_gaussian_lrt.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/conditional_gaussian_lrt.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/conditional_gaussian_lrt.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/conditional_gaussian_lrt.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/cpc.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/cpc.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/cpc.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/cpc.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/cpcs.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/cpcs.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/cpcs.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/cpcs.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/d_separation.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/d_separation.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/d_separation.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/d_separation.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/discrete_bic.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/discrete_bic.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/discrete_bic.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/discrete_bic.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/eb.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/eb.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/eb.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/eb.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/fas.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/fas.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/fas.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/fas.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/fci.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/fci.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/fci.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/fci.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/fisher_z.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/fisher_z.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/fisher_z.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/fisher_z.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/gccd.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/gccd.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/gccd.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/gccd.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/gfci.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/gfci.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/gfci.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/gfci.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/glasso.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/glasso.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/glasso.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/glasso.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/gsquare.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/gsquare.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/gsquare.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/gsquare.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/images.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/images.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/images.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/images.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/lingam.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/lingam.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/lingam.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/lingam.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/mbfs.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/mbfs.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/mbfs.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/mbfs.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/mgm.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/mgm.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/mgm.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/mgm.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/mimbuild.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/mimbuild.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/mimbuild.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/mimbuild.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/pc.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/pc.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/pc.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/pc.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/pcd.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/pcd.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/pcd.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/pcd.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/pclocal.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/pclocal.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/pclocal.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/pclocal.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/pcmax.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/pcmax.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/pcmax.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/pcmax.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/pcmaxlocal.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/pcmaxlocal.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/pcmaxlocal.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/pcmaxlocal.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/pcs.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/pcs.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/pcs.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/pcs.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/purify.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/purify.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/purify.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/purify.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/r1.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/r1.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/r1.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/r1.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/r2.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/r2.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/r2.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/r2.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/r3.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/r3.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/r3.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/r3.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/r4.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/r4.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/r4.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/r4.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/rfci.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/rfci.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/rfci.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/rfci.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/rskew.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/rskew.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/rskew.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/rskew.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/rskewe.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/rskewe.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/rskewe.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/rskewe.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/search_box.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/search_box.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/search_box.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/search_box.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/sem_bic.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/sem_bic.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/sem_bic.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/sem_bic.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/skew.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/skew.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/skew.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/skew.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/skewe.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/skewe.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/skewe.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/skewe.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/svarfci.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/svarfci.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/svarfci.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/svarfci.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/tsgfci.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/tsgfci.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/tsgfci.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/tsgfci.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/tsimages.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/tsimages.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/tsimages.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/tsimages.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/types_of_algorithms.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/types_of_algorithms.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/types_of_algorithms.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/types_of_algorithms.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/wfges.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/wfges.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/search/wfges.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/search/wfges.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/update/approximate_updater.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/update/approximate_updater.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/update/approximate_updater.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/update/approximate_updater.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/update/cpt_invariant_updater.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/update/cpt_invariant_updater.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/update/cpt_invariant_updater.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/update/cpt_invariant_updater.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/update/row_summing_updater.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/update/row_summing_updater.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/update/row_summing_updater.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/update/row_summing_updater.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/update/update_box.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/update/update_box.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/boxes/update/update_box.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/boxes/update/update_box.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/common_tasks.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/common_tasks.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/common_tasks.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/common_tasks.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/continuous_and_discrete_variables.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/continuous_and_discrete_variables.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/continuous_and_discrete_variables.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/continuous_and_discrete_variables.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/copying_and_pasting.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/copying_and_pasting.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/copying_and_pasting.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/copying_and_pasting.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/creating_data_from_scratch.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/creating_data_from_scratch.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/creating_data_from_scratch.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/creating_data_from_scratch.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/defining_discrete_variables.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/defining_discrete_variables.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/defining_discrete_variables.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/defining_discrete_variables.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/destroying_models.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/destroying_models.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/destroying_models.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/destroying_models.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/discretizing_data.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/discretizing_data.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/discretizing_data.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/discretizing_data.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/edge_orientation_shortcuts.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/edge_orientation_shortcuts.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/edge_orientation_shortcuts.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/edge_orientation_shortcuts.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/editing_covariance_matrices.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/editing_covariance_matrices.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/editing_covariance_matrices.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/editing_covariance_matrices.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/editing_knowledge.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/editing_knowledge.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/editing_knowledge.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/editing_knowledge.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/editing_node_properties.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/editing_node_properties.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/editing_node_properties.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/editing_node_properties.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/editing_tabular_data.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/editing_tabular_data.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/editing_tabular_data.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/editing_tabular_data.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/exiting_tetrad.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/exiting_tetrad.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/exiting_tetrad.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/exiting_tetrad.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/generating_random_dags.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/generating_random_dags.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/generating_random_dags.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/generating_random_dags.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/handling_missing_data.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/handling_missing_data.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/handling_missing_data.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/handling_missing_data.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/loading_covariance_matrices.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/loading_covariance_matrices.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/loading_covariance_matrices.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/loading_covariance_matrices.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/loading_data.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/loading_data.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/loading_data.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/loading_data.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/loading_tabular_data.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/loading_tabular_data.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/loading_tabular_data.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/loading_tabular_data.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/manipulating_data.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/manipulating_data.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/manipulating_data.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/manipulating_data.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/opening_sessions.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/opening_sessions.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/opening_sessions.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/opening_sessions.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/saving_screenshots.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/saving_screenshots.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/saving_screenshots.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/saving_screenshots.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/saving_sessions.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/saving_sessions.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/saving_sessions.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/saving_sessions.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/selecting_groups_of_nodes.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/selecting_groups_of_nodes.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/selecting_groups_of_nodes.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/selecting_groups_of_nodes.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/simulating_data.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/simulating_data.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/simulating_data.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/simulating_data.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/simulating_data_bayes.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/simulating_data_bayes.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/simulating_data_bayes.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/simulating_data_bayes.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/simulating_data_glass.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/simulating_data_glass.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/simulating_data_glass.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/simulating_data_glass.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/simulating_data_sem.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/simulating_data_sem.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/simulating_data_sem.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/simulating_data_sem.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/tabular_data_sets.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/tabular_data_sets.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/tabular_data_sets.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/tabular_data_sets.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/taking_screenshots.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/taking_screenshots.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/taking_screenshots.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/taking_screenshots.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/transferring_data_from_other_programs.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/transferring_data_from_other_programs.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/transferring_data_from_other_programs.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/transferring_data_from_other_programs.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/transferring_from_excel.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/transferring_from_excel.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/transferring_from_excel.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/transferring_from_excel.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/transferring_from_minitab.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/transferring_from_minitab.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/transferring_from_minitab.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/transferring_from_minitab.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/using_popup_menus.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/using_popup_menus.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/using_popup_menus.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/using_popup_menus.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/using_templates.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/using_templates.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/common_tasks/using_templates.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/common_tasks/using_templates.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/definitions/definitions.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/definitions/definitions.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/definitions/definitions.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/definitions/definitions.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/definitions/measured_latent_variables.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/definitions/measured_latent_variables.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/definitions/measured_latent_variables.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/definitions/measured_latent_variables.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/definitions/measurement_structural_graph.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/definitions/measurement_structural_graph.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/definitions/measurement_structural_graph.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/definitions/measurement_structural_graph.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/definitions/tetrad_graph_types.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/definitions/tetrad_graph_types.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/definitions/tetrad_graph_types.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/definitions/tetrad_graph_types.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/for_further_help.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/for_further_help.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/for_further_help.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/for_further_help.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/genetics/genetics.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/genetics/genetics.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/genetics/genetics.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/genetics/genetics.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/genetics/genetics_old.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/genetics/genetics_old.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/genetics/genetics_old.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/genetics/genetics_old.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/graph_edge_types.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/graph_edge_types.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/graph_edge_types.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/graph_edge_types.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/PMimage.jpg b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/PMimage.jpg similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/PMimage.jpg rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/PMimage.jpg diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/Thumbs.db b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/Thumbs.db similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/Thumbs.db rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/Thumbs.db diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/UBayescsopy.jpg b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/UBayescsopy.jpg similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/UBayescsopy.jpg rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/UBayescsopy.jpg diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/UBaysesIMcopy.jpg b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/UBaysesIMcopy.jpg similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/UBaysesIMcopy.jpg rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/UBaysesIMcopy.jpg diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/UComparseimage.jpg b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/UComparseimage.jpg similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/UComparseimage.jpg rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/UComparseimage.jpg diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/UIMSEM.jpg b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/UIMSEM.jpg similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/UIMSEM.jpg rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/UIMSEM.jpg diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/UIMedcopy.jpg b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/UIMedcopy.jpg similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/UIMedcopy.jpg rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/UIMedcopy.jpg diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/UIMimagecopy.jpg b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/UIMimagecopy.jpg similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/UIMimagecopy.jpg rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/UIMimagecopy.jpg diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/UPM.jpg b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/UPM.jpg similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/UPM.jpg rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/UPM.jpg diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/UcompsarePCcopy.jpg b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/UcompsarePCcopy.jpg similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/UcompsarePCcopy.jpg rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/UcompsarePCcopy.jpg diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/Ucompsaresheet.jpg b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/Ucompsaresheet.jpg similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/Ucompsaresheet.jpg rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/Ucompsaresheet.jpg diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/Ucontsdata.jpg b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/Ucontsdata.jpg similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/Ucontsdata.jpg rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/Ucontsdata.jpg diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/Udastasingle.jpg b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/Udastasingle.jpg similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/Udastasingle.jpg rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/Udastasingle.jpg diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/Udatsa.jpg b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/Udatsa.jpg similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/Udatsa.jpg rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/Udatsa.jpg diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/Uestimsate.jpg b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/Uestimsate.jpg similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/Uestimsate.jpg rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/Uestimsate.jpg diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/Uexpsanded.jpg b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/Uexpsanded.jpg similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/Uexpsanded.jpg rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/Uexpsanded.jpg diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/Uimportcopy.jpg b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/Uimportcopy.jpg similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/Uimportcopy.jpg rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/Uimportcopy.jpg diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/Uimtablecopy.jpg b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/Uimtablecopy.jpg similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/Uimtablecopy.jpg rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/Uimtablecopy.jpg diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/UntitiledsROC.jpg b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/UntitiledsROC.jpg similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/UntitiledsROC.jpg rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/UntitiledsROC.jpg diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/Untitled2Cslassify.jpg b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/Untitled2Cslassify.jpg similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/Untitled2Cslassify.jpg rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/Untitled2Cslassify.jpg diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/UntitledClasssifyResult.jpg b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/UntitledClasssifyResult.jpg similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/UntitledClasssifyResult.jpg rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/UntitledClasssifyResult.jpg diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/UntitledClsassifyWindow.jpg b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/UntitledClsassifyWindow.jpg similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/UntitledClsassifyWindow.jpg rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/UntitledClsassifyWindow.jpg diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/UntitledPsseudocount.jpg b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/UntitledPsseudocount.jpg similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/UntitledPsseudocount.jpg rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/UntitledPsseudocount.jpg diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/UntitledSsearchImagecopy.jpg b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/UntitledSsearchImagecopy.jpg similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/UntitledSsearchImagecopy.jpg rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/UntitledSsearchImagecopy.jpg diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/UntitledsGraphSearch.jpg b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/UntitledsGraphSearch.jpg similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/UntitledsGraphSearch.jpg rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/UntitledsGraphSearch.jpg diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/Untitledupdaterbox.jpg b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/Untitledupdaterbox.jpg similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/Untitledupdaterbox.jpg rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/Untitledupdaterbox.jpg diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/Uran.jpg b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/Uran.jpg similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/Uran.jpg rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/Uran.jpg diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/Utime.jpg b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/Utime.jpg similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/Utime.jpg rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/Utime.jpg diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/arrow_button.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/arrow_button.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/arrow_button.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/arrow_button.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/arrow_tool.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/arrow_tool.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/arrow_tool.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/arrow_tool.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/bayes_im_schema.png b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/bayes_im_schema.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/bayes_im_schema.png rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/bayes_im_schema.png diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/bayes_pm_schema.png b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/bayes_pm_schema.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/bayes_pm_schema.png rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/bayes_pm_schema.png diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/bayesim1.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/bayesim1.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/bayesim1.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/bayesim1.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/bayesim2.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/bayesim2.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/bayesim2.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/bayesim2.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/bayesim3.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/bayesim3.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/bayesim3.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/bayesim3.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/bayesim4.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/bayesim4.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/bayesim4.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/bayesim4.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/bayesim5.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/bayesim5.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/bayesim5.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/bayesim5.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/bayesim6.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/bayesim6.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/bayesim6.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/bayesim6.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/bayesim7.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/bayesim7.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/bayesim7.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/bayesim7.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/bayespm1.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/bayespm1.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/bayespm1.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/bayespm1.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/bayespm2.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/bayespm2.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/bayespm2.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/bayespm2.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/bayespm3.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/bayespm3.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/bayespm3.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/bayespm3.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/bayespm4.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/bayespm4.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/bayespm4.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/bayespm4.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/bayespm5.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/bayespm5.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/bayespm5.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/bayespm5.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/bidirectedEdge.png b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/bidirectedEdge.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/bidirectedEdge.png rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/bidirectedEdge.png diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/calvin_hobbes_instructions.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/calvin_hobbes_instructions.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/calvin_hobbes_instructions.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/calvin_hobbes_instructions.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/choose_data.png b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/choose_data.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/choose_data.png rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/choose_data.png diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/choose_load_data.png b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/choose_load_data.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/choose_load_data.png rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/choose_load_data.png diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/classify_button.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/classify_button.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/classify_button.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/classify_button.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/classify_highlight.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/classify_highlight.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/classify_highlight.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/classify_highlight.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/click_done_data.png b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/click_done_data.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/click_done_data.png rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/click_done_data.png diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/click_load.png b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/click_load.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/click_load.png rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/click_load.png diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/cluster1.png b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/cluster1.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/cluster1.png rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/cluster1.png diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/cluster2.png b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/cluster2.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/cluster2.png rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/cluster2.png diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/compare_button.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/compare_button.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/compare_button.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/compare_button.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/consructing_sessions1.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/consructing_sessions1.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/consructing_sessions1.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/consructing_sessions1.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/consructing_sessions2.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/consructing_sessions2.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/consructing_sessions2.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/consructing_sessions2.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/consructing_sessions3.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/consructing_sessions3.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/consructing_sessions3.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/consructing_sessions3.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/consructing_sessions4.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/consructing_sessions4.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/consructing_sessions4.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/consructing_sessions4.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/consructing_sessions5.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/consructing_sessions5.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/consructing_sessions5.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/consructing_sessions5.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/consructing_sessions6.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/consructing_sessions6.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/consructing_sessions6.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/consructing_sessions6.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/consructing_sessions7.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/consructing_sessions7.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/consructing_sessions7.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/consructing_sessions7.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/copying1.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/copying1.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/copying1.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/copying1.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/copying2.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/copying2.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/copying2.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/copying2.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/copying3.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/copying3.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/copying3.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/copying3.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/copying4.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/copying4.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/copying4.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/copying4.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/createBayesNet.jpg b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/createBayesNet.jpg similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/createBayesNet.jpg rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/createBayesNet.jpg diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/dag_editor.png b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/dag_editor.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/dag_editor.png rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/dag_editor.png diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/dag_from_data.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/dag_from_data.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/dag_from_data.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/dag_from_data.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/dag_from_data2.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/dag_from_data2.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/dag_from_data2.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/dag_from_data2.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/dag_graph_image.png b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/dag_graph_image.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/dag_graph_image.png rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/dag_graph_image.png diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/dageditorwindow.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/dageditorwindow.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/dageditorwindow.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/dageditorwindow.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/data_button.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/data_button.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/data_button.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/data_button.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/data_highlight.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/data_highlight.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/data_highlight.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/data_highlight.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/data_loader_1.PNG b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/data_loader_1.PNG similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/data_loader_1.PNG rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/data_loader_1.PNG diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/data_loader_2.PNG b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/data_loader_2.PNG similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/data_loader_2.PNG rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/data_loader_2.PNG diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/data_loader_3.PNG b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/data_loader_3.PNG similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/data_loader_3.PNG rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/data_loader_3.PNG diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/data_loader_4.PNG b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/data_loader_4.PNG similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/data_loader_4.PNG rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/data_loader_4.PNG diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/data_loader_5.PNG b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/data_loader_5.PNG similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/data_loader_5.PNG rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/data_loader_5.PNG diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/data_loader_6.PNG b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/data_loader_6.PNG similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/data_loader_6.PNG rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/data_loader_6.PNG diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/data_standatalone_highlight.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/data_standatalone_highlight.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/data_standatalone_highlight.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/data_standatalone_highlight.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/databox1.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/databox1.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/databox1.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/databox1.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/databox2.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/databox2.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/databox2.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/databox2.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/databox3.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/databox3.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/databox3.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/databox3.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/databox4.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/databox4.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/databox4.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/databox4.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/dataloader1.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/dataloader1.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/dataloader1.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/dataloader1.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/dataloader2.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/dataloader2.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/dataloader2.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/dataloader2.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/dataloader3.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/dataloader3.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/dataloader3.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/dataloader3.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/dataloader4.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/dataloader4.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/dataloader4.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/dataloader4.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/dataloader4.jpg b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/dataloader4.jpg similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/dataloader4.jpg rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/dataloader4.jpg diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/dataset_schema.png b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/dataset_schema.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/dataset_schema.png rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/dataset_schema.png diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/defineSampleSize.jpg b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/defineSampleSize.jpg similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/defineSampleSize.jpg rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/defineSampleSize.jpg diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/directedEdge.png b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/directedEdge.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/directedEdge.png rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/directedEdge.png diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/dirichletbayesim1.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/dirichletbayesim1.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/dirichletbayesim1.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/dirichletbayesim1.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/dirichletbayesim2.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/dirichletbayesim2.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/dirichletbayesim2.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/dirichletbayesim2.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/dirichletbayesim3.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/dirichletbayesim3.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/dirichletbayesim3.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/dirichletbayesim3.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/dirichletbayesim4.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/dirichletbayesim4.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/dirichletbayesim4.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/dirichletbayesim4.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/dirichletbayesim5.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/dirichletbayesim5.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/dirichletbayesim5.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/dirichletbayesim5.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/dirichletbayesim6.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/dirichletbayesim6.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/dirichletbayesim6.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/dirichletbayesim6.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/dirichletbayesim7.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/dirichletbayesim7.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/dirichletbayesim7.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/dirichletbayesim7.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/discretization1.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/discretization1.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/discretization1.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/discretization1.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/discretization2.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/discretization2.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/discretization2.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/discretization2.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/discretization3.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/discretization3.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/discretization3.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/discretization3.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/discretization4.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/discretization4.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/discretization4.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/discretization4.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/discretization5.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/discretization5.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/discretization5.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/discretization5.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/discretization6.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/discretization6.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/discretization6.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/discretization6.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/edge_orientation_shortcuts1.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/edge_orientation_shortcuts1.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/edge_orientation_shortcuts1.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/edge_orientation_shortcuts1.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/edge_orientation_shortcuts2.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/edge_orientation_shortcuts2.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/edge_orientation_shortcuts2.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/edge_orientation_shortcuts2.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/edge_orientation_shortcuts3.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/edge_orientation_shortcuts3.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/edge_orientation_shortcuts3.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/edge_orientation_shortcuts3.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/edge_orientation_shortcuts4.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/edge_orientation_shortcuts4.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/edge_orientation_shortcuts4.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/edge_orientation_shortcuts4.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/edit_menu.png b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/edit_menu.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/edit_menu.png rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/edit_menu.png diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/editing_data1.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/editing_data1.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/editing_data1.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/editing_data1.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/editing_data2.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/editing_data2.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/editing_data2.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/editing_data2.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/editing_data3.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/editing_data3.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/editing_data3.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/editing_data3.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/editing_data4.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/editing_data4.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/editing_data4.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/editing_data4.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/editing_knowledge1.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/editing_knowledge1.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/editing_knowledge1.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/editing_knowledge1.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/editing_knowledge2.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/editing_knowledge2.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/editing_knowledge2.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/editing_knowledge2.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/editing_knowledge3.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/editing_knowledge3.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/editing_knowledge3.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/editing_knowledge3.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/editing_knowledge4.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/editing_knowledge4.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/editing_knowledge4.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/editing_knowledge4.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/editing_knowledge5.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/editing_knowledge5.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/editing_knowledge5.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/editing_knowledge5.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/editing_knowledge6.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/editing_knowledge6.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/editing_knowledge6.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/editing_knowledge6.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/editing_nodes1.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/editing_nodes1.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/editing_nodes1.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/editing_nodes1.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/editing_nodes2.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/editing_nodes2.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/editing_nodes2.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/editing_nodes2.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/editing_nodes3.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/editing_nodes3.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/editing_nodes3.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/editing_nodes3.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/estimator_button.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/estimator_button.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/estimator_button.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/estimator_button.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/example_workflow_schema.png b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/example_workflow_schema.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/example_workflow_schema.png rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/example_workflow_schema.png diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/file_menu.png b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/file_menu.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/file_menu.png rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/file_menu.png diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/flowchart_dependencies1.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/flowchart_dependencies1.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/flowchart_dependencies1.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/flowchart_dependencies1.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/flowchart_dependencies2.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/flowchart_dependencies2.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/flowchart_dependencies2.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/flowchart_dependencies2.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/flowcharterButton.jpg b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/flowcharterButton.jpg similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/flowcharterButton.jpg rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/flowcharterButton.jpg diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/generalgrapheditorwindow.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/generalgrapheditorwindow.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/generalgrapheditorwindow.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/generalgrapheditorwindow.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/generateData.jpg b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/generateData.jpg similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/generateData.jpg rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/generateData.jpg diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/ges1.png b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/ges1.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/ges1.png rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/ges1.png diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/graph1.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/graph1.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/graph1.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/graph1.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/graph1_to_pm1.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/graph1_to_pm1.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/graph1_to_pm1.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/graph1_to_pm1.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/graph1choices.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/graph1choices.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/graph1choices.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/graph1choices.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/graph1editorwindow.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/graph1editorwindow.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/graph1editorwindow.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/graph1editorwindow.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/graph1structureeditor.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/graph1structureeditor.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/graph1structureeditor.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/graph1structureeditor.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/graph2editorwindow.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/graph2editorwindow.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/graph2editorwindow.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/graph2editorwindow.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/graph2structureeditor.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/graph2structureeditor.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/graph2structureeditor.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/graph2structureeditor.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/graphButton.jpg b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/graphButton.jpg similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/graphButton.jpg rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/graphButton.jpg diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/graphEditor.jpg b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/graphEditor.jpg similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/graphEditor.jpg rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/graphEditor.jpg diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/graphWindow.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/graphWindow.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/graphWindow.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/graphWindow.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/graph_button.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/graph_button.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/graph_button.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/graph_button.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/graph_gen_schema.png b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/graph_gen_schema.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/graph_gen_schema.png rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/graph_gen_schema.png diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/graph_highlight.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/graph_highlight.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/graph_highlight.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/graph_highlight.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/graph_schema.png b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/graph_schema.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/graph_schema.png rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/graph_schema.png diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/help_menu.png b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/help_menu.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/help_menu.png rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/help_menu.png diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/im_button.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/im_button.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/im_button.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/im_button.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/im_highlight.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/im_highlight.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/im_highlight.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/im_highlight.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/images.png b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/images.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/images.png rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/images.png diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/instantiatedModelButton.jpg b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/instantiatedModelButton.jpg similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/instantiatedModelButton.jpg rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/instantiatedModelButton.jpg diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/instantiatedWindow.jpg b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/instantiatedWindow.jpg similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/instantiatedWindow.jpg rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/instantiatedWindow.jpg diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/knowledge1.png b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/knowledge1.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/knowledge1.png rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/knowledge1.png diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/knowledge2.png b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/knowledge2.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/knowledge2.png rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/knowledge2.png diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/knowledge3.png b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/knowledge3.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/knowledge3.png rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/knowledge3.png diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/knowledge4.png b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/knowledge4.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/knowledge4.png rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/knowledge4.png diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/knowledge_button.png b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/knowledge_button.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/knowledge_button.png rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/knowledge_button.png diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/knowledge_schema.png b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/knowledge_schema.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/knowledge_schema.png rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/knowledge_schema.png diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/loading_data1.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/loading_data1.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/loading_data1.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/loading_data1.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/loading_data2.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/loading_data2.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/loading_data2.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/loading_data2.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/loading_data3.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/loading_data3.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/loading_data3.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/loading_data3.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/logging_menu.png b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/logging_menu.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/logging_menu.png rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/logging_menu.png diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/main_menu.png b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/main_menu.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/main_menu.png rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/main_menu.png diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/main_workbench.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/main_workbench.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/main_workbench.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/main_workbench.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/main_workbench2.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/main_workbench2.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/main_workbench2.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/main_workbench2.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/main_workbench2.png b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/main_workbench2.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/main_workbench2.png rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/main_workbench2.png diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/main_workbench3.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/main_workbench3.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/main_workbench3.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/main_workbench3.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/main_workbench3.png b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/main_workbench3.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/main_workbench3.png rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/main_workbench3.png diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/main_workbench4.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/main_workbench4.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/main_workbench4.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/main_workbench4.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/main_workspace.png b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/main_workspace.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/main_workspace.png rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/main_workspace.png diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/manipulatedButton.jpg b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/manipulatedButton.jpg similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/manipulatedButton.jpg rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/manipulatedButton.jpg diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/manipulatedData.jpg b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/manipulatedData.jpg similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/manipulatedData.jpg rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/manipulatedData.jpg diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/manipulated_data_button.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/manipulated_data_button.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/manipulated_data_button.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/manipulated_data_button.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/manipulated_highlight.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/manipulated_highlight.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/manipulated_highlight.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/manipulated_highlight.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/measured_vs_latent1.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/measured_vs_latent1.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/measured_vs_latent1.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/measured_vs_latent1.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/measured_vs_latent2.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/measured_vs_latent2.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/measured_vs_latent2.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/measured_vs_latent2.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/menubar.png b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/menubar.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/menubar.png rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/menubar.png diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/mimbuild1.png b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/mimbuild1.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/mimbuild1.png rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/mimbuild1.png diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/mimbuild3.png b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/mimbuild3.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/mimbuild3.png rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/mimbuild3.png diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/mimbuild4.png b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/mimbuild4.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/mimbuild4.png rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/mimbuild4.png diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/objects.png b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/objects.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/objects.png rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/objects.png diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/parametric_model_button.jpg b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/parametric_model_button.jpg similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/parametric_model_button.jpg rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/parametric_model_button.jpg diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/pc_output.png b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/pc_output.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/pc_output.png rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/pc_output.png diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/pcsearch1.png b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/pcsearch1.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/pcsearch1.png rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/pcsearch1.png diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/pcsearch2.png b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/pcsearch2.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/pcsearch2.png rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/pcsearch2.png diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/pcsearch3.png b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/pcsearch3.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/pcsearch3.png rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/pcsearch3.png diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/pcsearch_dialog.png b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/pcsearch_dialog.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/pcsearch_dialog.png rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/pcsearch_dialog.png diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/place_data_box.png b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/place_data_box.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/place_data_box.png rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/place_data_box.png diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/pm_button.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/pm_button.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/pm_button.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/pm_button.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/pm_highlight.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/pm_highlight.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/pm_highlight.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/pm_highlight.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/pm_image.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/pm_image.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/pm_image.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/pm_image.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/purify1.png b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/purify1.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/purify1.png rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/purify1.png diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/purify2.png b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/purify2.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/purify2.png rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/purify2.png diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/purify3.png b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/purify3.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/purify3.png rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/purify3.png diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/purify4.png b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/purify4.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/purify4.png rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/purify4.png diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/red_x.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/red_x.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/red_x.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/red_x.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/regression_button.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/regression_button.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/regression_button.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/regression_button.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/regression_highlight.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/regression_highlight.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/regression_highlight.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/regression_highlight.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/rubberband1.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/rubberband1.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/rubberband1.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/rubberband1.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/rubberband2.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/rubberband2.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/rubberband2.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/rubberband2.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/save_data.png b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/save_data.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/save_data.png rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/save_data.png diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/searchCsreation.png b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/searchCsreation.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/searchCsreation.png rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/searchCsreation.png diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/search_box.png b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/search_box.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/search_box.png rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/search_box.png diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/search_button.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/search_button.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/search_button.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/search_button.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/search_done.png b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/search_done.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/search_done.png rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/search_done.png diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/search_from_data_highlight.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/search_from_data_highlight.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/search_from_data_highlight.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/search_from_data_highlight.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/search_from_graph_highlight.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/search_from_graph_highlight.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/search_from_graph_highlight.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/search_from_graph_highlight.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/search_params.png b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/search_params.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/search_params.png rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/search_params.png diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/search_schema.png b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/search_schema.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/search_schema.png rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/search_schema.png diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/searcsreation.png b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/searcsreation.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/searcsreation.png rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/searcsreation.png diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/select_move_button.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/select_move_button.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/select_move_button.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/select_move_button.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/sem_graph1.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/sem_graph1.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/sem_graph1.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/sem_graph1.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/sem_graph2.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/sem_graph2.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/sem_graph2.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/sem_graph2.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/sem_graph3.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/sem_graph3.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/sem_graph3.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/sem_graph3.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/sem_im_schema.png b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/sem_im_schema.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/sem_im_schema.png rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/sem_im_schema.png diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/sem_pm_schema.png b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/sem_pm_schema.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/sem_pm_schema.png rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/sem_pm_schema.png diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/semim1.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/semim1.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/semim1.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/semim1.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/semim2.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/semim2.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/semim2.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/semim2.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/semim3.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/semim3.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/semim3.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/semim3.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/semim4.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/semim4.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/semim4.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/semim4.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/semim5.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/semim5.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/semim5.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/semim5.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/semim6.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/semim6.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/semim6.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/semim6.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/semim7.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/semim7.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/semim7.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/semim7.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/semim8.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/semim8.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/semim8.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/semim8.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/sempm1.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/sempm1.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/sempm1.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/sempm1.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/sempm2.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/sempm2.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/sempm2.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/sempm2.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/sempm3.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/sempm3.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/sempm3.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/sempm3.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/sempm4.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/sempm4.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/sempm4.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/sempm4.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/sempm5.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/sempm5.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/sempm5.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/sempm5.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/sempm6.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/sempm6.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/sempm6.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/sempm6.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/templates_estimatedatabayes.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/templates_estimatedatabayes.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/templates_estimatedatabayes.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/templates_estimatedatabayes.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/templates_estimatedatasem.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/templates_estimatedatasem.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/templates_estimatedatasem.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/templates_estimatedatasem.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/templates_estimatesimulated.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/templates_estimatesimulated.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/templates_estimatesimulated.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/templates_estimatesimulated.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/templates_estsearchresult.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/templates_estsearchresult.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/templates_estsearchresult.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/templates_estsearchresult.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/templates_estsearchresultbayes.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/templates_estsearchresultbayes.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/templates_estsearchresultbayes.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/templates_estsearchresultbayes.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/templates_estsearchresultsem.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/templates_estsearchresultsem.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/templates_estsearchresultsem.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/templates_estsearchresultsem.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/templates_searchfromdata.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/templates_searchfromdata.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/templates_searchfromdata.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/templates_searchfromdata.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/templates_searchsimcomp.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/templates_searchsimcomp.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/templates_searchsimcomp.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/templates_searchsimcomp.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/templates_searchsimulated.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/templates_searchsimulated.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/templates_searchsimulated.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/templates_searchsimulated.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/templates_simulatedata.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/templates_simulatedata.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/templates_simulatedata.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/templates_simulatedata.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/templates_updatebayesim.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/templates_updatebayesim.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/templates_updatebayesim.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/templates_updatebayesim.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/tetrad_menu1.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/tetrad_menu1.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/tetrad_menu1.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/tetrad_menu1.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/tetrad_menu1.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/tetrad_menu1.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/tetrad_menu1.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/tetrad_menu1.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/tetrad_menu2.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/tetrad_menu2.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/tetrad_menu2.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/tetrad_menu2.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/tetrad_menu3.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/tetrad_menu3.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/tetrad_menu3.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/tetrad_menu3.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/tetrad_menu4.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/tetrad_menu4.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/tetrad_menu4.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/tetrad_menu4.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/tetrad_menu5.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/tetrad_menu5.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/tetrad_menu5.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/tetrad_menu5.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/ucomsparesearchcopy.jpg b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/ucomsparesearchcopy.jpg similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/ucomsparesearchcopy.jpg rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/ucomsparesearchcopy.jpg diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/undirected_edge.png b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/undirected_edge.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/undirected_edge.png rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/undirected_edge.png diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/updater_button.gif b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/updater_button.gif similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/updater_button.gif rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/updater_button.gif diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/variables_schema.png b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/variables_schema.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/variables_schema.png rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/variables_schema.png diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/images/window_menu.png b/tetrad-lib/src/main/resources/docs/javahelp/manual/images/window_menu.png similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/images/window_menu.png rename to tetrad-lib/src/main/resources/docs/javahelp/manual/images/window_menu.png diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/main_workspace/how_to_build_a_session.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/main_workspace/how_to_build_a_session.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/main_workspace/how_to_build_a_session.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/main_workspace/how_to_build_a_session.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/main_workspace/main_workspace_explained.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/main_workspace/main_workspace_explained.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/main_workspace/main_workspace_explained.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/main_workspace/main_workspace_explained.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/main_workspace/tetrad_menubar.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/main_workspace/tetrad_menubar.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/main_workspace/tetrad_menubar.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/main_workspace/tetrad_menubar.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/main_workspace/tetrad_toolbar.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/main_workspace/tetrad_toolbar.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/main_workspace/tetrad_toolbar.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/main_workspace/tetrad_toolbar.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/main_workspace/tetrad_versioning.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/main_workspace/tetrad_versioning.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/main_workspace/tetrad_versioning.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/main_workspace/tetrad_versioning.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/manual.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/manual.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/manual.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/manual.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/references.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/references.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/references.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/references.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/tetrad_overview.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/tetrad_overview.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/tetrad_overview.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/tetrad_overview.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/tetrad_tutorial.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/tetrad_tutorial.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/tetrad_tutorial.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/tetrad_tutorial.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/under_construction.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/under_construction.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/under_construction.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/under_construction.html diff --git a/tetrad-gui/src/main/resources/resources/javahelp/manual/why_doesnt_tetrad.html b/tetrad-lib/src/main/resources/docs/javahelp/manual/why_doesnt_tetrad.html similarity index 100% rename from tetrad-gui/src/main/resources/resources/javahelp/manual/why_doesnt_tetrad.html rename to tetrad-lib/src/main/resources/docs/javahelp/manual/why_doesnt_tetrad.html diff --git a/tetrad-gui/src/main/resources/docs/manual/README.md b/tetrad-lib/src/main/resources/docs/manual/README.md similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/README.md rename to tetrad-lib/src/main/resources/docs/manual/README.md diff --git a/tetrad-gui/src/main/resources/docs/manual/css/normalize.css b/tetrad-lib/src/main/resources/docs/manual/css/normalize.css similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/css/normalize.css rename to tetrad-lib/src/main/resources/docs/manual/css/normalize.css diff --git a/tetrad-gui/src/main/resources/docs/manual/css/tetrad.css b/tetrad-lib/src/main/resources/docs/manual/css/tetrad.css similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/css/tetrad.css rename to tetrad-lib/src/main/resources/docs/manual/css/tetrad.css diff --git a/tetrad-gui/src/main/resources/docs/manual/flowchart.html b/tetrad-lib/src/main/resources/docs/manual/flowchart.html similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/flowchart.html rename to tetrad-lib/src/main/resources/docs/manual/flowchart.html diff --git a/tetrad-gui/src/main/resources/docs/manual/images/appendix_figure_1a.png b/tetrad-lib/src/main/resources/docs/manual/images/appendix_figure_1a.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/appendix_figure_1a.png rename to tetrad-lib/src/main/resources/docs/manual/images/appendix_figure_1a.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/appendix_figure_1b.png b/tetrad-lib/src/main/resources/docs/manual/images/appendix_figure_1b.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/appendix_figure_1b.png rename to tetrad-lib/src/main/resources/docs/manual/images/appendix_figure_1b.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/appendix_figure_2.png b/tetrad-lib/src/main/resources/docs/manual/images/appendix_figure_2.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/appendix_figure_2.png rename to tetrad-lib/src/main/resources/docs/manual/images/appendix_figure_2.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/arc_specialization_1.png b/tetrad-lib/src/main/resources/docs/manual/images/arc_specialization_1.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/arc_specialization_1.png rename to tetrad-lib/src/main/resources/docs/manual/images/arc_specialization_1.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/arc_specialization_2.png b/tetrad-lib/src/main/resources/docs/manual/images/arc_specialization_2.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/arc_specialization_2.png rename to tetrad-lib/src/main/resources/docs/manual/images/arc_specialization_2.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/arc_specialization_3.png b/tetrad-lib/src/main/resources/docs/manual/images/arc_specialization_3.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/arc_specialization_3.png rename to tetrad-lib/src/main/resources/docs/manual/images/arc_specialization_3.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/classify_box_1.png b/tetrad-lib/src/main/resources/docs/manual/images/classify_box_1.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/classify_box_1.png rename to tetrad-lib/src/main/resources/docs/manual/images/classify_box_1.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/classify_box_2.png b/tetrad-lib/src/main/resources/docs/manual/images/classify_box_2.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/classify_box_2.png rename to tetrad-lib/src/main/resources/docs/manual/images/classify_box_2.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/classify_box_3.png b/tetrad-lib/src/main/resources/docs/manual/images/classify_box_3.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/classify_box_3.png rename to tetrad-lib/src/main/resources/docs/manual/images/classify_box_3.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/compare_box_1.png b/tetrad-lib/src/main/resources/docs/manual/images/compare_box_1.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/compare_box_1.png rename to tetrad-lib/src/main/resources/docs/manual/images/compare_box_1.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/compare_box_10.png b/tetrad-lib/src/main/resources/docs/manual/images/compare_box_10.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/compare_box_10.png rename to tetrad-lib/src/main/resources/docs/manual/images/compare_box_10.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/compare_box_11.png b/tetrad-lib/src/main/resources/docs/manual/images/compare_box_11.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/compare_box_11.png rename to tetrad-lib/src/main/resources/docs/manual/images/compare_box_11.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/compare_box_12.png b/tetrad-lib/src/main/resources/docs/manual/images/compare_box_12.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/compare_box_12.png rename to tetrad-lib/src/main/resources/docs/manual/images/compare_box_12.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/compare_box_13.png b/tetrad-lib/src/main/resources/docs/manual/images/compare_box_13.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/compare_box_13.png rename to tetrad-lib/src/main/resources/docs/manual/images/compare_box_13.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/compare_box_3.png b/tetrad-lib/src/main/resources/docs/manual/images/compare_box_3.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/compare_box_3.png rename to tetrad-lib/src/main/resources/docs/manual/images/compare_box_3.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/compare_box_4.png b/tetrad-lib/src/main/resources/docs/manual/images/compare_box_4.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/compare_box_4.png rename to tetrad-lib/src/main/resources/docs/manual/images/compare_box_4.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/compare_box_5.png b/tetrad-lib/src/main/resources/docs/manual/images/compare_box_5.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/compare_box_5.png rename to tetrad-lib/src/main/resources/docs/manual/images/compare_box_5.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/compare_box_6.png b/tetrad-lib/src/main/resources/docs/manual/images/compare_box_6.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/compare_box_6.png rename to tetrad-lib/src/main/resources/docs/manual/images/compare_box_6.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/compare_box_7.png b/tetrad-lib/src/main/resources/docs/manual/images/compare_box_7.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/compare_box_7.png rename to tetrad-lib/src/main/resources/docs/manual/images/compare_box_7.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/compare_box_8.png b/tetrad-lib/src/main/resources/docs/manual/images/compare_box_8.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/compare_box_8.png rename to tetrad-lib/src/main/resources/docs/manual/images/compare_box_8.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/compare_box_9.png b/tetrad-lib/src/main/resources/docs/manual/images/compare_box_9.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/compare_box_9.png rename to tetrad-lib/src/main/resources/docs/manual/images/compare_box_9.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/data_box_1.png b/tetrad-lib/src/main/resources/docs/manual/images/data_box_1.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/data_box_1.png rename to tetrad-lib/src/main/resources/docs/manual/images/data_box_1.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/data_box_10.png b/tetrad-lib/src/main/resources/docs/manual/images/data_box_10.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/data_box_10.png rename to tetrad-lib/src/main/resources/docs/manual/images/data_box_10.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/data_box_2.png b/tetrad-lib/src/main/resources/docs/manual/images/data_box_2.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/data_box_2.png rename to tetrad-lib/src/main/resources/docs/manual/images/data_box_2.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/data_box_3.png b/tetrad-lib/src/main/resources/docs/manual/images/data_box_3.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/data_box_3.png rename to tetrad-lib/src/main/resources/docs/manual/images/data_box_3.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/data_box_4.png b/tetrad-lib/src/main/resources/docs/manual/images/data_box_4.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/data_box_4.png rename to tetrad-lib/src/main/resources/docs/manual/images/data_box_4.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/data_box_5.png b/tetrad-lib/src/main/resources/docs/manual/images/data_box_5.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/data_box_5.png rename to tetrad-lib/src/main/resources/docs/manual/images/data_box_5.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/data_box_6.png b/tetrad-lib/src/main/resources/docs/manual/images/data_box_6.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/data_box_6.png rename to tetrad-lib/src/main/resources/docs/manual/images/data_box_6.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/data_box_7.png b/tetrad-lib/src/main/resources/docs/manual/images/data_box_7.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/data_box_7.png rename to tetrad-lib/src/main/resources/docs/manual/images/data_box_7.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/data_box_8.png b/tetrad-lib/src/main/resources/docs/manual/images/data_box_8.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/data_box_8.png rename to tetrad-lib/src/main/resources/docs/manual/images/data_box_8.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/data_box_8a.png b/tetrad-lib/src/main/resources/docs/manual/images/data_box_8a.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/data_box_8a.png rename to tetrad-lib/src/main/resources/docs/manual/images/data_box_8a.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/data_box_8b.png b/tetrad-lib/src/main/resources/docs/manual/images/data_box_8b.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/data_box_8b.png rename to tetrad-lib/src/main/resources/docs/manual/images/data_box_8b.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/data_box_9.png b/tetrad-lib/src/main/resources/docs/manual/images/data_box_9.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/data_box_9.png rename to tetrad-lib/src/main/resources/docs/manual/images/data_box_9.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/estimator_box_1.png b/tetrad-lib/src/main/resources/docs/manual/images/estimator_box_1.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/estimator_box_1.png rename to tetrad-lib/src/main/resources/docs/manual/images/estimator_box_1.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/estimator_box_2.png b/tetrad-lib/src/main/resources/docs/manual/images/estimator_box_2.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/estimator_box_2.png rename to tetrad-lib/src/main/resources/docs/manual/images/estimator_box_2.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/flowchart.pdf b/tetrad-lib/src/main/resources/docs/manual/images/flowchart.pdf similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/flowchart.pdf rename to tetrad-lib/src/main/resources/docs/manual/images/flowchart.pdf diff --git a/tetrad-gui/src/main/resources/docs/manual/images/flowchart.pptx b/tetrad-lib/src/main/resources/docs/manual/images/flowchart.pptx similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/flowchart.pptx rename to tetrad-lib/src/main/resources/docs/manual/images/flowchart.pptx diff --git a/tetrad-gui/src/main/resources/docs/manual/images/flowchart/Slide1.png b/tetrad-lib/src/main/resources/docs/manual/images/flowchart/Slide1.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/flowchart/Slide1.png rename to tetrad-lib/src/main/resources/docs/manual/images/flowchart/Slide1.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/flowchart/Slide2.png b/tetrad-lib/src/main/resources/docs/manual/images/flowchart/Slide2.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/flowchart/Slide2.png rename to tetrad-lib/src/main/resources/docs/manual/images/flowchart/Slide2.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/instantiated_model_box_1.png b/tetrad-lib/src/main/resources/docs/manual/images/instantiated_model_box_1.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/instantiated_model_box_1.png rename to tetrad-lib/src/main/resources/docs/manual/images/instantiated_model_box_1.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/instantiated_model_box_10.png b/tetrad-lib/src/main/resources/docs/manual/images/instantiated_model_box_10.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/instantiated_model_box_10.png rename to tetrad-lib/src/main/resources/docs/manual/images/instantiated_model_box_10.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/instantiated_model_box_11.png b/tetrad-lib/src/main/resources/docs/manual/images/instantiated_model_box_11.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/instantiated_model_box_11.png rename to tetrad-lib/src/main/resources/docs/manual/images/instantiated_model_box_11.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/instantiated_model_box_12.png b/tetrad-lib/src/main/resources/docs/manual/images/instantiated_model_box_12.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/instantiated_model_box_12.png rename to tetrad-lib/src/main/resources/docs/manual/images/instantiated_model_box_12.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/instantiated_model_box_13.png b/tetrad-lib/src/main/resources/docs/manual/images/instantiated_model_box_13.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/instantiated_model_box_13.png rename to tetrad-lib/src/main/resources/docs/manual/images/instantiated_model_box_13.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/instantiated_model_box_14.png b/tetrad-lib/src/main/resources/docs/manual/images/instantiated_model_box_14.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/instantiated_model_box_14.png rename to tetrad-lib/src/main/resources/docs/manual/images/instantiated_model_box_14.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/instantiated_model_box_2.png b/tetrad-lib/src/main/resources/docs/manual/images/instantiated_model_box_2.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/instantiated_model_box_2.png rename to tetrad-lib/src/main/resources/docs/manual/images/instantiated_model_box_2.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/instantiated_model_box_3.png b/tetrad-lib/src/main/resources/docs/manual/images/instantiated_model_box_3.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/instantiated_model_box_3.png rename to tetrad-lib/src/main/resources/docs/manual/images/instantiated_model_box_3.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/instantiated_model_box_4.png b/tetrad-lib/src/main/resources/docs/manual/images/instantiated_model_box_4.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/instantiated_model_box_4.png rename to tetrad-lib/src/main/resources/docs/manual/images/instantiated_model_box_4.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/instantiated_model_box_5.png b/tetrad-lib/src/main/resources/docs/manual/images/instantiated_model_box_5.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/instantiated_model_box_5.png rename to tetrad-lib/src/main/resources/docs/manual/images/instantiated_model_box_5.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/instantiated_model_box_6.png b/tetrad-lib/src/main/resources/docs/manual/images/instantiated_model_box_6.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/instantiated_model_box_6.png rename to tetrad-lib/src/main/resources/docs/manual/images/instantiated_model_box_6.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/instantiated_model_box_7.png b/tetrad-lib/src/main/resources/docs/manual/images/instantiated_model_box_7.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/instantiated_model_box_7.png rename to tetrad-lib/src/main/resources/docs/manual/images/instantiated_model_box_7.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/instantiated_model_box_8.png b/tetrad-lib/src/main/resources/docs/manual/images/instantiated_model_box_8.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/instantiated_model_box_8.png rename to tetrad-lib/src/main/resources/docs/manual/images/instantiated_model_box_8.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/instantiated_model_box_9.png b/tetrad-lib/src/main/resources/docs/manual/images/instantiated_model_box_9.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/instantiated_model_box_9.png rename to tetrad-lib/src/main/resources/docs/manual/images/instantiated_model_box_9.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/knowledge_box_1.png b/tetrad-lib/src/main/resources/docs/manual/images/knowledge_box_1.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/knowledge_box_1.png rename to tetrad-lib/src/main/resources/docs/manual/images/knowledge_box_1.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/knowledge_box_2.png b/tetrad-lib/src/main/resources/docs/manual/images/knowledge_box_2.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/knowledge_box_2.png rename to tetrad-lib/src/main/resources/docs/manual/images/knowledge_box_2.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/knowledge_box_3.png b/tetrad-lib/src/main/resources/docs/manual/images/knowledge_box_3.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/knowledge_box_3.png rename to tetrad-lib/src/main/resources/docs/manual/images/knowledge_box_3.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/knowledge_box_4.png b/tetrad-lib/src/main/resources/docs/manual/images/knowledge_box_4.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/knowledge_box_4.png rename to tetrad-lib/src/main/resources/docs/manual/images/knowledge_box_4.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/parametric_model_box_1.png b/tetrad-lib/src/main/resources/docs/manual/images/parametric_model_box_1.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/parametric_model_box_1.png rename to tetrad-lib/src/main/resources/docs/manual/images/parametric_model_box_1.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/parametric_model_box_2.png b/tetrad-lib/src/main/resources/docs/manual/images/parametric_model_box_2.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/parametric_model_box_2.png rename to tetrad-lib/src/main/resources/docs/manual/images/parametric_model_box_2.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/parametric_model_box_3.png b/tetrad-lib/src/main/resources/docs/manual/images/parametric_model_box_3.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/parametric_model_box_3.png rename to tetrad-lib/src/main/resources/docs/manual/images/parametric_model_box_3.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/parametric_model_box_4.png b/tetrad-lib/src/main/resources/docs/manual/images/parametric_model_box_4.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/parametric_model_box_4.png rename to tetrad-lib/src/main/resources/docs/manual/images/parametric_model_box_4.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/parametric_model_box_5.png b/tetrad-lib/src/main/resources/docs/manual/images/parametric_model_box_5.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/parametric_model_box_5.png rename to tetrad-lib/src/main/resources/docs/manual/images/parametric_model_box_5.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/parametric_model_box_6.png b/tetrad-lib/src/main/resources/docs/manual/images/parametric_model_box_6.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/parametric_model_box_6.png rename to tetrad-lib/src/main/resources/docs/manual/images/parametric_model_box_6.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/parametric_model_box_7.png b/tetrad-lib/src/main/resources/docs/manual/images/parametric_model_box_7.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/parametric_model_box_7.png rename to tetrad-lib/src/main/resources/docs/manual/images/parametric_model_box_7.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/parametric_model_box_8.png b/tetrad-lib/src/main/resources/docs/manual/images/parametric_model_box_8.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/parametric_model_box_8.png rename to tetrad-lib/src/main/resources/docs/manual/images/parametric_model_box_8.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/regression_box_1.png b/tetrad-lib/src/main/resources/docs/manual/images/regression_box_1.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/regression_box_1.png rename to tetrad-lib/src/main/resources/docs/manual/images/regression_box_1.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/regression_box_2.png b/tetrad-lib/src/main/resources/docs/manual/images/regression_box_2.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/regression_box_2.png rename to tetrad-lib/src/main/resources/docs/manual/images/regression_box_2.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/regression_box_3.png b/tetrad-lib/src/main/resources/docs/manual/images/regression_box_3.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/regression_box_3.png rename to tetrad-lib/src/main/resources/docs/manual/images/regression_box_3.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/search_box_1.png b/tetrad-lib/src/main/resources/docs/manual/images/search_box_1.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/search_box_1.png rename to tetrad-lib/src/main/resources/docs/manual/images/search_box_1.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/simulation_box_1.png b/tetrad-lib/src/main/resources/docs/manual/images/simulation_box_1.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/simulation_box_1.png rename to tetrad-lib/src/main/resources/docs/manual/images/simulation_box_1.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/updater_box_1.png b/tetrad-lib/src/main/resources/docs/manual/images/updater_box_1.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/updater_box_1.png rename to tetrad-lib/src/main/resources/docs/manual/images/updater_box_1.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/updater_box_10.png b/tetrad-lib/src/main/resources/docs/manual/images/updater_box_10.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/updater_box_10.png rename to tetrad-lib/src/main/resources/docs/manual/images/updater_box_10.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/updater_box_2.png b/tetrad-lib/src/main/resources/docs/manual/images/updater_box_2.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/updater_box_2.png rename to tetrad-lib/src/main/resources/docs/manual/images/updater_box_2.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/updater_box_3.png b/tetrad-lib/src/main/resources/docs/manual/images/updater_box_3.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/updater_box_3.png rename to tetrad-lib/src/main/resources/docs/manual/images/updater_box_3.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/updater_box_4.png b/tetrad-lib/src/main/resources/docs/manual/images/updater_box_4.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/updater_box_4.png rename to tetrad-lib/src/main/resources/docs/manual/images/updater_box_4.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/updater_box_5.png b/tetrad-lib/src/main/resources/docs/manual/images/updater_box_5.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/updater_box_5.png rename to tetrad-lib/src/main/resources/docs/manual/images/updater_box_5.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/updater_box_6.png b/tetrad-lib/src/main/resources/docs/manual/images/updater_box_6.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/updater_box_6.png rename to tetrad-lib/src/main/resources/docs/manual/images/updater_box_6.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/updater_box_7.png b/tetrad-lib/src/main/resources/docs/manual/images/updater_box_7.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/updater_box_7.png rename to tetrad-lib/src/main/resources/docs/manual/images/updater_box_7.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/updater_box_8.png b/tetrad-lib/src/main/resources/docs/manual/images/updater_box_8.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/updater_box_8.png rename to tetrad-lib/src/main/resources/docs/manual/images/updater_box_8.png diff --git a/tetrad-gui/src/main/resources/docs/manual/images/updater_box_9.png b/tetrad-lib/src/main/resources/docs/manual/images/updater_box_9.png similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/images/updater_box_9.png rename to tetrad-lib/src/main/resources/docs/manual/images/updater_box_9.png diff --git a/tetrad-gui/src/main/resources/docs/manual/index.html b/tetrad-lib/src/main/resources/docs/manual/index.html similarity index 100% rename from tetrad-gui/src/main/resources/docs/manual/index.html rename to tetrad-lib/src/main/resources/docs/manual/index.html diff --git a/tetrad-gui/src/main/resources/docs/notes/cfci.orientation.txt b/tetrad-lib/src/main/resources/docs/notes/cfci.orientation.txt similarity index 100% rename from tetrad-gui/src/main/resources/docs/notes/cfci.orientation.txt rename to tetrad-lib/src/main/resources/docs/notes/cfci.orientation.txt diff --git a/tetrad-gui/src/main/resources/docs/notes/cliques.txt b/tetrad-lib/src/main/resources/docs/notes/cliques.txt similarity index 100% rename from tetrad-gui/src/main/resources/docs/notes/cliques.txt rename to tetrad-lib/src/main/resources/docs/notes/cliques.txt diff --git a/tetrad-gui/src/main/resources/docs/notes/cmd.txt b/tetrad-lib/src/main/resources/docs/notes/cmd.txt similarity index 100% rename from tetrad-gui/src/main/resources/docs/notes/cmd.txt rename to tetrad-lib/src/main/resources/docs/notes/cmd.txt diff --git a/tetrad-gui/src/main/resources/docs/notes/images b/tetrad-lib/src/main/resources/docs/notes/images similarity index 100% rename from tetrad-gui/src/main/resources/docs/notes/images rename to tetrad-lib/src/main/resources/docs/notes/images diff --git a/tetrad-gui/src/main/resources/docs/notes/images.1 b/tetrad-lib/src/main/resources/docs/notes/images.1 similarity index 100% rename from tetrad-gui/src/main/resources/docs/notes/images.1 rename to tetrad-lib/src/main/resources/docs/notes/images.1 diff --git a/tetrad-gui/src/main/resources/docs/notes/pc.fci.in.r.spirtes.2.3.2010.txt b/tetrad-lib/src/main/resources/docs/notes/pc.fci.in.r.spirtes.2.3.2010.txt similarity index 100% rename from tetrad-gui/src/main/resources/docs/notes/pc.fci.in.r.spirtes.2.3.2010.txt rename to tetrad-lib/src/main/resources/docs/notes/pc.fci.in.r.spirtes.2.3.2010.txt diff --git a/tetrad-gui/src/main/resources/docs/notes/serialization_notes.txt b/tetrad-lib/src/main/resources/docs/notes/serialization_notes.txt similarity index 100% rename from tetrad-gui/src/main/resources/docs/notes/serialization_notes.txt rename to tetrad-lib/src/main/resources/docs/notes/serialization_notes.txt diff --git a/tetrad-gui/src/main/resources/docs/referenced_papers/Adjacency-submitted.pdf b/tetrad-lib/src/main/resources/docs/referenced_papers/Adjacency-submitted.pdf similarity index 100% rename from tetrad-gui/src/main/resources/docs/referenced_papers/Adjacency-submitted.pdf rename to tetrad-lib/src/main/resources/docs/referenced_papers/Adjacency-submitted.pdf diff --git a/tetrad-gui/src/main/resources/docs/referenced_papers/AmStat_review.pdf b/tetrad-lib/src/main/resources/docs/referenced_papers/AmStat_review.pdf similarity index 100% rename from tetrad-gui/src/main/resources/docs/referenced_papers/AmStat_review.pdf rename to tetrad-lib/src/main/resources/docs/referenced_papers/AmStat_review.pdf diff --git a/tetrad-gui/src/main/resources/docs/referenced_papers/Bollen_Ting_1993SociolMeth.pdf b/tetrad-lib/src/main/resources/docs/referenced_papers/Bollen_Ting_1993SociolMeth.pdf similarity index 100% rename from tetrad-gui/src/main/resources/docs/referenced_papers/Bollen_Ting_1993SociolMeth.pdf rename to tetrad-lib/src/main/resources/docs/referenced_papers/Bollen_Ting_1993SociolMeth.pdf diff --git a/tetrad-gui/src/main/resources/docs/referenced_papers/CAUSAL.PS b/tetrad-lib/src/main/resources/docs/referenced_papers/CAUSAL.PS similarity index 100% rename from tetrad-gui/src/main/resources/docs/referenced_papers/CAUSAL.PS rename to tetrad-lib/src/main/resources/docs/referenced_papers/CAUSAL.PS diff --git a/tetrad-gui/src/main/resources/docs/referenced_papers/CMU-ISRI-04-127.pdf b/tetrad-lib/src/main/resources/docs/referenced_papers/CMU-ISRI-04-127.pdf similarity index 100% rename from tetrad-gui/src/main/resources/docs/referenced_papers/CMU-ISRI-04-127.pdf rename to tetrad-lib/src/main/resources/docs/referenced_papers/CMU-ISRI-04-127.pdf diff --git a/tetrad-gui/src/main/resources/docs/referenced_papers/chickering02b.pdf b/tetrad-lib/src/main/resources/docs/referenced_papers/chickering02b.pdf similarity index 100% rename from tetrad-gui/src/main/resources/docs/referenced_papers/chickering02b.pdf rename to tetrad-lib/src/main/resources/docs/referenced_papers/chickering02b.pdf diff --git a/tetrad-gui/src/main/resources/docs/referenced_papers/con00random.pdf b/tetrad-lib/src/main/resources/docs/referenced_papers/con00random.pdf similarity index 100% rename from tetrad-gui/src/main/resources/docs/referenced_papers/con00random.pdf rename to tetrad-lib/src/main/resources/docs/referenced_papers/con00random.pdf diff --git a/tetrad-gui/src/main/resources/docs/referenced_papers/glasso.f90 b/tetrad-lib/src/main/resources/docs/referenced_papers/glasso.f90 similarity index 100% rename from tetrad-gui/src/main/resources/docs/referenced_papers/glasso.f90 rename to tetrad-lib/src/main/resources/docs/referenced_papers/glasso.f90 diff --git a/tetrad-gui/src/main/resources/docs/referenced_papers/hartiganwong.pdf b/tetrad-lib/src/main/resources/docs/referenced_papers/hartiganwong.pdf similarity index 100% rename from tetrad-gui/src/main/resources/docs/referenced_papers/hartiganwong.pdf rename to tetrad-lib/src/main/resources/docs/referenced_papers/hartiganwong.pdf diff --git a/tetrad-gui/src/main/resources/docs/referenced_papers/hawkins1989.pdf b/tetrad-lib/src/main/resources/docs/referenced_papers/hawkins1989.pdf similarity index 100% rename from tetrad-gui/src/main/resources/docs/referenced_papers/hawkins1989.pdf rename to tetrad-lib/src/main/resources/docs/referenced_papers/hawkins1989.pdf diff --git a/tetrad-gui/src/main/resources/docs/referenced_papers/jmlr06.pdf b/tetrad-lib/src/main/resources/docs/referenced_papers/jmlr06.pdf similarity index 100% rename from tetrad-gui/src/main/resources/docs/referenced_papers/jmlr06.pdf rename to tetrad-lib/src/main/resources/docs/referenced_papers/jmlr06.pdf diff --git a/tetrad-gui/src/main/resources/docs/referenced_papers/math_s5_v1_article-17.pdf b/tetrad-lib/src/main/resources/docs/referenced_papers/math_s5_v1_article-17.pdf similarity index 100% rename from tetrad-gui/src/main/resources/docs/referenced_papers/math_s5_v1_article-17.pdf rename to tetrad-lib/src/main/resources/docs/referenced_papers/math_s5_v1_article-17.pdf diff --git a/tetrad-gui/src/main/resources/docs/referenced_papers/optimal.pdf b/tetrad-lib/src/main/resources/docs/referenced_papers/optimal.pdf similarity index 100% rename from tetrad-gui/src/main/resources/docs/referenced_papers/optimal.pdf rename to tetrad-lib/src/main/resources/docs/referenced_papers/optimal.pdf diff --git a/tetrad-gui/src/main/resources/docs/referenced_papers/p313-grira.pdf b/tetrad-lib/src/main/resources/docs/referenced_papers/p313-grira.pdf similarity index 100% rename from tetrad-gui/src/main/resources/docs/referenced_papers/p313-grira.pdf rename to tetrad-lib/src/main/resources/docs/referenced_papers/p313-grira.pdf diff --git a/tetrad-gui/src/main/resources/docs/referenced_papers/splits.pdf b/tetrad-lib/src/main/resources/docs/referenced_papers/splits.pdf similarity index 100% rename from tetrad-gui/src/main/resources/docs/referenced_papers/splits.pdf rename to tetrad-lib/src/main/resources/docs/referenced_papers/splits.pdf diff --git a/tetrad-gui/src/main/resources/docs/referenced_papers/uaidiscovery.pdf b/tetrad-lib/src/main/resources/docs/referenced_papers/uaidiscovery.pdf similarity index 100% rename from tetrad-gui/src/main/resources/docs/referenced_papers/uaidiscovery.pdf rename to tetrad-lib/src/main/resources/docs/referenced_papers/uaidiscovery.pdf From cfc226299db711758d58d0ad47b49438c0e487cf Mon Sep 17 00:00:00 2001 From: jdramsey Date: Mon, 11 Dec 2023 10:42:41 -0500 Subject: [PATCH 019/163] Fixing paths. --- .../src/main/java/edu/cmu/tetrad/search/MarkovCheck.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java index 5c40a8f437..6b86fc6689 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java @@ -666,10 +666,10 @@ private void generateResultsAllSubsets(Set msep, Set pValues, double alpha) { - int dependentJudgments = 0; + int independentJudgements = 0; for (double pValue : pValues) { - if (pValue < alpha) dependentJudgments++; + if (pValue > alpha) independentJudgements++; } int n = pValues.size(); @@ -679,7 +679,7 @@ private double getBinomialP(List pValues, double alpha) { BinomialDistribution bd = new BinomialDistribution(n, alpha); // We want the area to the right of this, so we subtract from 1. - return (1.0 - bd.cumulativeProbability(dependentJudgments)) + (bd.probability(n - dependentJudgments)); + return (1.0 - bd.cumulativeProbability(independentJudgements)) + (bd.probability(n - independentJudgements)); } /** From 69399ac9b5de4159a9fa9084136747909118f33c Mon Sep 17 00:00:00 2001 From: jdramsey Date: Thu, 14 Dec 2023 06:50:46 -0500 Subject: [PATCH 020/163] Added a method, isCpdag, to GraphSearchUtils. --- .../tetradapp/editor/MarkovCheckEditor.java | 2 +- .../cmu/tetradapp/model/CPDAGFitModel.java | 4 +-- .../tetradapp/model/DagFromCPDAGWrapper.java | 2 +- .../algcomparison/statistic/BicDiff.java | 4 +-- .../statistic/BicDiffPerRecord.java | 4 +-- .../algcomparison/statistic/BicEst.java | 2 +- .../algcomparison/statistic/BicTrue.java | 2 +- .../edu/cmu/tetrad/graph/GraphTransforms.java | 30 ++++++++++++++++-- .../main/java/edu/cmu/tetrad/search/Fges.java | 2 +- .../java/edu/cmu/tetrad/search/FgesMb.java | 2 +- .../edu/cmu/tetrad/search/MarkovCheck.java | 19 ++++++------ .../tetrad/search/utils/GraphSearchUtils.java | 31 +++++++++++++++++++ .../tetrad/search/utils/LogUtilsSearch.java | 2 +- .../edu/cmu/tetrad/search/utils/MbUtils.java | 2 +- .../search/work_in_progress/HbsmsBeam.java | 2 +- .../search/work_in_progress/HbsmsGes.java | 2 +- .../edu/cmu/tetrad/simulation/HsimAutoC.java | 2 +- .../cmu/tetrad/simulation/HsimAutoRun.java | 2 +- .../tetrad/simulation/HsimEvalFromData.java | 2 +- .../tetrad/simulation/HsimRobustCompare.java | 2 +- .../edu/cmu/tetrad/simulation/HsimRun.java | 2 +- .../edu/cmu/tetrad/study/RBExperiments.java | 2 +- .../bayesian/constraint/search/RfciBsc.java | 2 +- 23 files changed, 91 insertions(+), 35 deletions(-) diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java index 387831c2e8..2f8939557b 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java @@ -323,7 +323,7 @@ public void watch() { private void refreshResult(MarkovCheckIndTestModel model, DoubleTextField percent) { setTest(); - model.getMarkovCheck().setPercentResammple(percent.getValue()); + model.getMarkovCheck().setPercentResample(percent.getValue()); model.getMarkovCheck().generateResults(); tableModelIndep.fireTableDataChanged(); tableModelDep.fireTableDataChanged(); diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/CPDAGFitModel.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/CPDAGFitModel.java index d8118a2dd3..1bc171316e 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/CPDAGFitModel.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/CPDAGFitModel.java @@ -84,7 +84,7 @@ public CPDAGFitModel(Simulation simulation, GeneralAlgorithmRunner algorithmRunn for (int i = 0; i < dataModels.size(); i++) { DataSet dataSet = (DataSet) dataModels.get(0); - Graph dag = GraphTransforms.dagFromCPDAG(graphs.get(0), null); + Graph dag = GraphTransforms.dagFromCpdag(graphs.get(0), null); BayesPm pm = new BayesPmWrapper(dag, new DataWrapper(dataSet)).getBayesPm(); this.bayesPms.add(pm); this.bayesIms.add(estimate(dataSet, pm)); @@ -95,7 +95,7 @@ public CPDAGFitModel(Simulation simulation, GeneralAlgorithmRunner algorithmRunn for (int i = 0; i < dataModels.size(); i++) { DataSet dataSet = (DataSet) dataModels.get(0); - Graph dag = GraphTransforms.dagFromCPDAG(graphs.get(0), null); + Graph dag = GraphTransforms.dagFromCpdag(graphs.get(0), null); try { SemPm pm = new SemPm(dag); diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/DagFromCPDAGWrapper.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/DagFromCPDAGWrapper.java index a948a06a0e..f2518dc5da 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/DagFromCPDAGWrapper.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/DagFromCPDAGWrapper.java @@ -47,7 +47,7 @@ public DagFromCPDAGWrapper(Graph graph) { } private static Graph getGraph(Graph graph) { - return GraphTransforms.dagFromCPDAG(graph, null); + return GraphTransforms.dagFromCpdag(graph, null); } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/BicDiff.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/BicDiff.java index 83241bb266..4b5ba79e93 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/BicDiff.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/BicDiff.java @@ -28,8 +28,8 @@ public String getDescription() { @Override public double getValue(Graph trueGraph, Graph estGraph, DataModel dataModel) { - double _true = SemBicScorer.scoreDag(GraphTransforms.dagFromCPDAG(trueGraph, null), dataModel, precomputeCovariances); - double est = SemBicScorer.scoreDag(GraphTransforms.dagFromCPDAG(estGraph, null), dataModel, precomputeCovariances); + double _true = SemBicScorer.scoreDag(GraphTransforms.dagFromCpdag(trueGraph, null), dataModel, precomputeCovariances); + double est = SemBicScorer.scoreDag(GraphTransforms.dagFromCpdag(estGraph, null), dataModel, precomputeCovariances); return (_true - est); } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/BicDiffPerRecord.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/BicDiffPerRecord.java index c98412966e..3a34af506c 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/BicDiffPerRecord.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/BicDiffPerRecord.java @@ -31,8 +31,8 @@ public String getDescription() { @Override public double getValue(Graph trueGraph, Graph estGraph, DataModel dataModel) { - double _true = SemBicScorer.scoreDag(GraphTransforms.dagFromCPDAG(trueGraph, null), dataModel, precomputeCovariances); - double est = SemBicScorer.scoreDag(GraphTransforms.dagFromCPDAG(estGraph, null), dataModel, precomputeCovariances); + double _true = SemBicScorer.scoreDag(GraphTransforms.dagFromCpdag(trueGraph, null), dataModel, precomputeCovariances); + double est = SemBicScorer.scoreDag(GraphTransforms.dagFromCpdag(estGraph, null), dataModel, precomputeCovariances); if (abs(_true) < 0.0001) _true = 0.0; if (abs(est) < 0.0001) est = 0.0; return (_true - est) / ((DataSet) dataModel).getNumRows(); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/BicEst.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/BicEst.java index 2fc7024067..7d253bac49 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/BicEst.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/BicEst.java @@ -38,7 +38,7 @@ public String getDescription() { @Override public double getValue(Graph trueGraph, Graph estGraph, DataModel dataModel) { // double _true = SemBicScorer.scoreDag(SearchGraphUtils.dagFromCPDAG(trueGraph), dataModel); - return SemBicScorer.scoreDag(GraphTransforms.dagFromCPDAG(estGraph, null), dataModel, precomputeCovariances); + return SemBicScorer.scoreDag(GraphTransforms.dagFromCpdag(estGraph, null), dataModel, precomputeCovariances); } @Override diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/BicTrue.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/BicTrue.java index c41e272e5e..f372c1b5f1 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/BicTrue.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/BicTrue.java @@ -29,7 +29,7 @@ public String getDescription() { @Override public double getValue(Graph trueGraph, Graph estGraph, DataModel dataModel) { // double est = SemBicScorer.scoreDag(SearchGraphUtils.dagFromCPDAG(estGraph), dataModel); - return SemBicScorer.scoreDag(GraphTransforms.dagFromCPDAG(trueGraph, null), dataModel, precomputeCovariances); + return SemBicScorer.scoreDag(GraphTransforms.dagFromCpdag(trueGraph, null), dataModel, precomputeCovariances); } @Override diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/graph/GraphTransforms.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/graph/GraphTransforms.java index 012a9b4663..9454faf935 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/graph/GraphTransforms.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/graph/GraphTransforms.java @@ -16,11 +16,11 @@ * @author josephramsey */ public class GraphTransforms { - public static Graph dagFromCPDAG(Graph graph) { - return dagFromCPDAG(graph, null); + public static Graph dagFromCpdag(Graph graph) { + return dagFromCpdag(graph, null); } - public static Graph dagFromCPDAG(Graph graph, Knowledge knowledge) { + public static Graph dagFromCpdag(Graph graph, Knowledge knowledge) { Graph dag = new EdgeListGraph(graph); for (Edge edge : dag.getEdges()) { @@ -56,6 +56,30 @@ public static Graph dagFromCPDAG(Graph graph, Knowledge knowledge) { return dag; } + public static boolean isCpdag(Graph graph) { + MeekRules rules = new MeekRules(); + rules.setRevertToUnshieldedColliders(true); + rules.orientImplied(graph); + + NEXT: + while (true) { + for (Edge edge : graph.getEdges()) { + Node x = edge.getNode1(); + Node y = edge.getNode2(); + + if (Edges.isUndirectedEdge(edge)) { + direct(x, y, graph); + rules.orientImplied(graph); + continue NEXT; + } + } + + break; + } + + return !graph.paths().existsDirectedCycle(); + } + // Zhang 2008 Theorem 2 public static Graph pagToMag(Graph pag) { Graph mag = new EdgeListGraph(pag.getNodes()); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fges.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fges.java index 094758eeb9..a8b7353ab0 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fges.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fges.java @@ -240,7 +240,7 @@ public Graph search() { this.logger.forceLogMessage("Elapsed time = " + (elapsedTime) / 1000. + " s"); } - this.modelScore = scoreDag(GraphTransforms.dagFromCPDAG(graph, null), true); + this.modelScore = scoreDag(GraphTransforms.dagFromCpdag(graph, null), true); return graph; } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/FgesMb.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/FgesMb.java index b78b44f668..b200507c35 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/FgesMb.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/FgesMb.java @@ -230,7 +230,7 @@ public Graph search(List targets) { this.logger.forceLogMessage("Elapsed time = " + (elapsedTime) / 1000. + " s"); } - this.modelScore = scoreDag(GraphTransforms.dagFromCPDAG(graph, null), true); + this.modelScore = scoreDag(GraphTransforms.dagFromCpdag(graph, null), true); graph = GraphUtils.trimGraph(targets, graph, trimmingStyle); return graph; } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java index 6b86fc6689..ee2f0a3c4e 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java @@ -54,7 +54,7 @@ public class MarkovCheck { private double andersonDarlingPDep = Double.NaN; private double binomialPIndep = Double.NaN; private double binomialPDep = Double.NaN; - private double percentResammple = 0.5; + private double percentResample = 0.5; private int numTestsindep = 0; private int numTestsDep = 0; @@ -150,7 +150,8 @@ public void generateResults() { Set mconn = new HashSet<>(); for (int i = 0; i < nodes.size(); i++) { - for (int j = i + 1; j < nodes.size(); j++) { + for (int j = 0; j < nodes.size(); j++) { + if (i == j) continue; Node x = nodes.get(i); Node y = nodes.get(j); @@ -383,11 +384,11 @@ public IndependenceTest getIndependenceTest() { /** * Sets the percentage of all samples to use when resampling for each conditional independence test. * - * @param percentResammple The percentage of all samples to use when resampling for each conditional independence + * @param percentResample The percentage of all samples to use when resampling for each conditional independence * test. */ - public void setPercentResammple(double percentResammple) { - this.percentResammple = percentResammple; + public void setPercentResample(double percentResample) { + this.percentResample = percentResample; } /** @@ -502,7 +503,7 @@ public Pair, Set> call() { Set z = fact.getZ(); if (independenceTest instanceof RowsSettable) { - List rows = getSubsampleRows(percentResammple); + List rows = getSubsampleRows(percentResample); ((RowsSettable) independenceTest).setRows(rows); boolean verbose = independenceTest.isVerbose(); @@ -672,14 +673,14 @@ private double getBinomialP(List pValues, double alpha) { if (pValue > alpha) independentJudgements++; } - int n = pValues.size(); + int p = pValues.size(); // The left tail of this binomial distribution is a p-value for getting too few dependent judgments for // the distribution to count as uniform. - BinomialDistribution bd = new BinomialDistribution(n, alpha); + BinomialDistribution bd = new BinomialDistribution(p, alpha); // We want the area to the right of this, so we subtract from 1. - return (1.0 - bd.cumulativeProbability(independentJudgements)) + (bd.probability(n - independentJudgements)); + return (1.0 - bd.cumulativeProbability(independentJudgements)) + (bd.probability(p - independentJudgements)); } /** diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/GraphSearchUtils.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/GraphSearchUtils.java index 642cd9ade1..29c0e30877 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/GraphSearchUtils.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/GraphSearchUtils.java @@ -347,6 +347,37 @@ public static void basicCpdagRestricted2(Graph graph, Node node) { } } + public static boolean isCpdag(Graph graph) { + MeekRules rules = new MeekRules(); + rules.setRevertToUnshieldedColliders(true); + rules.orientImplied(graph); + + NEXT: + while (true) { + for (Edge edge : graph.getEdges()) { + Node x = edge.getNode1(); + Node y = edge.getNode2(); + + if (Edges.isUndirectedEdge(edge)) { + direct(x, y, graph); + rules.orientImplied(graph); + continue NEXT; + } + } + + break; + } + + return !graph.paths().existsDirectedCycle(); + } + + private static void direct(Node a, Node c, Graph graph) { + Edge before = graph.getEdge(a, c); + Edge after = Edges.directedEdge(a, c); + graph.removeEdge(before); + graph.addEdge(after); + } + public static LegalPagRet isLegalPag(Graph pag) { for (Node n : pag.getNodes()) { diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/LogUtilsSearch.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/LogUtilsSearch.java index 484cd1bc91..181c2c0620 100755 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/LogUtilsSearch.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/LogUtilsSearch.java @@ -159,7 +159,7 @@ public static Map buildIndexing(List nodes) { @NotNull public static void stampWithScores(Graph graph, DataModel dataModel, Score score) { if (!graph.getAllAttributes().containsKey("Score")) { - Graph dag = GraphTransforms.dagFromCPDAG(graph); + Graph dag = GraphTransforms.dagFromCpdag(graph); Map hashIndices = buildIndexing(dag.getNodes()); double _score = 0.0; diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/MbUtils.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/MbUtils.java index 7d320a1bfc..b81957cc2b 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/MbUtils.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/MbUtils.java @@ -238,7 +238,7 @@ public static List generateMbDags(Graph mbCPDAG, * @return An example DAG in this CPDAG. */ public static Graph getOneMbDag(Graph mbCpdag) { - return GraphTransforms.dagFromCPDAG(mbCpdag, null); + return GraphTransforms.dagFromCpdag(mbCpdag, null); } /** diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/work_in_progress/HbsmsBeam.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/work_in_progress/HbsmsBeam.java index 4cf15d1fe4..f0a1cf542a 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/work_in_progress/HbsmsBeam.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/work_in_progress/HbsmsBeam.java @@ -83,7 +83,7 @@ public HbsmsBeam(Graph graph, CovarianceMatrix cov, Knowledge knowledge) { public Graph search() { EdgeListGraph _graph = new EdgeListGraph(this.externalGraph); addRequiredEdges(_graph); - Graph bestGraph = GraphTransforms.dagFromCPDAG(_graph, null); + Graph bestGraph = GraphTransforms.dagFromCpdag(_graph, null); if (getGraph().getNumEdges() == 0) { System.out.println("Found one!"); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/work_in_progress/HbsmsGes.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/work_in_progress/HbsmsGes.java index debf8bf9d1..ccdc2a31c0 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/work_in_progress/HbsmsGes.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/work_in_progress/HbsmsGes.java @@ -166,7 +166,7 @@ private void saveModelIfSignificant(Graph graph) { } public Score scoreGraph(Graph graph) { - Graph dag = GraphTransforms.dagFromCPDAG(graph, getKnowledge()); + Graph dag = GraphTransforms.dagFromCpdag(graph, getKnowledge()); this.scorer.score(dag); return new Score(this.scorer); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/simulation/HsimAutoC.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/simulation/HsimAutoC.java index c01171c804..9aeb4f6bfd 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/simulation/HsimAutoC.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/simulation/HsimAutoC.java @@ -71,7 +71,7 @@ public double[] run(int resimSize) { Graph estGraph = fges.search(); //if (verbose) System.out.println(estGraph); - Graph estGraphDAG = GraphTransforms.dagFromCPDAG(estGraph, null); + Graph estGraphDAG = GraphTransforms.dagFromCpdag(estGraph, null); Dag estDAG = new Dag(estGraphDAG); //Dag estDAG = new Dag(estGraph); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/simulation/HsimAutoRun.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/simulation/HsimAutoRun.java index 9c37e02850..f07619227b 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/simulation/HsimAutoRun.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/simulation/HsimAutoRun.java @@ -89,7 +89,7 @@ public double[] run(int resimSize) { //if (verbose) System.out.println(estGraph); Graph estCPDAG = new EdgeListGraph(estGraph); - Graph estGraphDAG = GraphTransforms.dagFromCPDAG(estCPDAG, null); + Graph estGraphDAG = GraphTransforms.dagFromCpdag(estCPDAG, null); Dag estDAG = new Dag(estGraphDAG); //===========Identify the nodes to be resimulated=========== diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/simulation/HsimEvalFromData.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/simulation/HsimEvalFromData.java index ca82e2e486..d4919e452a 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/simulation/HsimEvalFromData.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/simulation/HsimEvalFromData.java @@ -89,7 +89,7 @@ public static void main(String[] args) { for (whichFrepeat = 0; whichFrepeat < fsimRepeat.size(); whichFrepeat++) { ArrayList errorsList = new ArrayList<>(); for (int r = 0; r < fsimRepeat.get(whichFrepeat); r++) { - Graph fgsDag = GraphTransforms.dagFromCPDAG(oFGSGraph, null); + Graph fgsDag = GraphTransforms.dagFromCpdag(oFGSGraph, null); Dag fgsdag2 = new Dag(fgsDag); //then fit an IM to this dag and the data. GeneralizedSemEstimator seems to bug out diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/simulation/HsimRobustCompare.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/simulation/HsimRobustCompare.java index 86f9911c9a..d70b675050 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/simulation/HsimRobustCompare.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/simulation/HsimRobustCompare.java @@ -64,7 +64,7 @@ public static List run(int numVars, double edgesPerNode, int numCases, //create various simulated data sets ////let's do the full simulated data set first: a dag in the FGES CPDAG fit to the data set. - Graph fgesDag = GraphTransforms.dagFromCPDAG(oGraphOut, null); + Graph fgesDag = GraphTransforms.dagFromCpdag(oGraphOut, null); Dag fgesdag2 = new Dag(fgesDag); BayesPm simBayesPm = new BayesPm(fgesdag2, bayesPm); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/simulation/HsimRun.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/simulation/HsimRun.java index f4b9d720bb..a779fbe92d 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/simulation/HsimRun.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/simulation/HsimRun.java @@ -49,7 +49,7 @@ public static void run(String readfilename, String filenameOut, char delimiter, System.out.println(estGraph); Graph estCPDAG = new EdgeListGraph(estGraph); - Graph estGraphDAG = GraphTransforms.dagFromCPDAG(estCPDAG, null); + Graph estGraphDAG = GraphTransforms.dagFromCpdag(estCPDAG, null); Dag estDAG = new Dag(estGraphDAG); //===========Identify the nodes to be resimulated=========== diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/study/RBExperiments.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/study/RBExperiments.java index 6828eefd88..d27ec0165f 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/study/RBExperiments.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/study/RBExperiments.java @@ -187,7 +187,7 @@ public void experiment(String modelName, int numCases, int numModels, int numBoo // learn structure of constraints using empirical data Graph depCPDAG = runFGS(depData); - Graph estDepBN = GraphTransforms.dagFromCPDAG(depCPDAG, null); + Graph estDepBN = GraphTransforms.dagFromCpdag(depCPDAG, null); System.out.println("estDepBN: " + estDepBN.getEdges()); out.println("DepGraph(nodes,edges):" + estDepBN.getNumNodes() + "," + estDepBN.getNumEdges()); System.out.println("Dependency graph done!"); diff --git a/tetrad-lib/src/main/java/edu/pitt/dbmi/algo/bayesian/constraint/search/RfciBsc.java b/tetrad-lib/src/main/java/edu/pitt/dbmi/algo/bayesian/constraint/search/RfciBsc.java index 534b63a0bc..c2066e294e 100644 --- a/tetrad-lib/src/main/java/edu/pitt/dbmi/algo/bayesian/constraint/search/RfciBsc.java +++ b/tetrad-lib/src/main/java/edu/pitt/dbmi/algo/bayesian/constraint/search/RfciBsc.java @@ -399,7 +399,7 @@ public Boolean call() throws Exception { Graph depPattern = fges.search(); depPattern = GraphUtils.replaceNodes(depPattern, depData.getVariables()); - Graph estDepBN = GraphTransforms.dagFromCPDAG(depPattern, null); + Graph estDepBN = GraphTransforms.dagFromCpdag(depPattern, null); if (this.verbose) { this.out.println("estDepBN:"); From cdfe89ee6d16ec8ec11eca1375d54c0423a9fc47 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Thu, 14 Dec 2023 22:33:04 -0500 Subject: [PATCH 021/163] Added a method, isCpdag, to GraphSearchUtils. --- .../tetrad/search/utils/GraphSearchUtils.java | 46 +++++++++++++++++-- .../edu/cmu/tetrad/test/TestGraphUtils.java | 7 +++ 2 files changed, 49 insertions(+), 4 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/GraphSearchUtils.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/GraphSearchUtils.java index 29c0e30877..487c0dfd8f 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/GraphSearchUtils.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/GraphSearchUtils.java @@ -347,11 +347,40 @@ public static void basicCpdagRestricted2(Graph graph, Node node) { } } + /** + * Returns true just in case the given graph is a CPDAG. + * @param graph the graph to check. + * @return true just in case the given graph is a CPDAG. + */ public static boolean isCpdag(Graph graph) { + + // Make sure all of the edges are directed or undirected. + for (Edge edge : graph.getEdges()) { + if (!(Edges.isDirectedEdge(edge) || Edges.isUndirectedEdge(edge))) { + return false; + } + } + + // Make sure there are no 2-cycles. + List nodes = graph.getNodes(); + + for (int i = 0; i < nodes.size(); i++) { + for (int j = i + 1; j < nodes.size(); j++) { + if (graph.getEdges(nodes.get(i), nodes.get(j)).size() > 1) { + return false; + } + } + } + + // Make sure there's no way to orient a directed cycle using the Meek rules. MeekRules rules = new MeekRules(); rules.setRevertToUnshieldedColliders(true); rules.orientImplied(graph); + if (graph.paths().existsDirectedCycle()) return false; + + rules.setRevertToUnshieldedColliders(false); + NEXT: while (true) { for (Edge edge : graph.getEdges()) { @@ -359,16 +388,25 @@ public static boolean isCpdag(Graph graph) { Node y = edge.getNode2(); if (Edges.isUndirectedEdge(edge)) { - direct(x, y, graph); - rules.orientImplied(graph); + Graph _graph = new EdgeListGraph(graph); + direct(x, y, _graph); + rules.orientImplied(_graph); + if (_graph.paths().existsDirectedCycle()) return false; + + _graph = new EdgeListGraph(graph); + direct(y, x, _graph); + rules.orientImplied(_graph); + if (_graph.paths().existsDirectedCycle()) return false; + + graph = _graph; continue NEXT; } - } + } break; } - return !graph.paths().existsDirectedCycle(); + return true; } private static void direct(Node a, Node c, Graph graph) { diff --git a/tetrad-lib/src/test/java/edu/cmu/tetrad/test/TestGraphUtils.java b/tetrad-lib/src/test/java/edu/cmu/tetrad/test/TestGraphUtils.java index efebaeaa34..d6d9c702da 100644 --- a/tetrad-lib/src/test/java/edu/cmu/tetrad/test/TestGraphUtils.java +++ b/tetrad-lib/src/test/java/edu/cmu/tetrad/test/TestGraphUtils.java @@ -23,6 +23,7 @@ import edu.cmu.tetrad.data.ContinuousVariable; import edu.cmu.tetrad.graph.*; +import edu.cmu.tetrad.search.utils.GraphSearchUtils; import edu.cmu.tetrad.util.RandomUtil; import org.junit.Test; @@ -273,6 +274,12 @@ public void test8() { } } + @Test + public void test9() { + Graph graph = GraphUtils.convert("X1---X2,X2---X3, X3---X4, X4---X1"); + assert(!GraphSearchUtils.isCpdag(graph)); + } + private Set set(Node... z) { Set list = new HashSet<>(); Collections.addAll(list, z); From 0a0a38c70b0eeb0c6153876c46e04660f055d58d Mon Sep 17 00:00:00 2001 From: jdramsey Date: Fri, 15 Dec 2023 10:12:50 -0500 Subject: [PATCH 022/163] Added a method, isCpdag, to GraphSearchUtils. --- .../cmu/tetrad/algcomparison/algorithm/oracle/cpdag/Fges.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/Fges.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/Fges.java index d3298a8528..b666743328 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/Fges.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/Fges.java @@ -100,7 +100,7 @@ public Graph search(DataModel dataModel, Parameters parameters) { graph = search.search(); - if (!graph.getAllAttributes().containsKey("BIC")) { + if (dataModel.isContinuous() && !graph.getAllAttributes().containsKey("BIC")) { graph.addAttribute("BIC", new BicEst().getValue(null, graph, dataModel)); } From 5eedff465e86b7bdabb1794afb4e3e8072086e55 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Thu, 21 Dec 2023 10:43:32 -0500 Subject: [PATCH 023/163] Added a method, isCpdag, to GraphSearchUtils. --- .../main/java/edu/cmu/tetrad/search/utils/LogUtilsSearch.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/LogUtilsSearch.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/LogUtilsSearch.java index 181c2c0620..99cb7f8889 100755 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/LogUtilsSearch.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/LogUtilsSearch.java @@ -184,7 +184,7 @@ public static void stampWithScores(Graph graph, DataModel dataModel, Score score } public static void stampWithBic(Graph graph, DataModel dataModel) { - if (!graph.getAllAttributes().containsKey("BIC")) { + if (dataModel.isContinuous() && !graph.getAllAttributes().containsKey("BIC")) { try { graph.addAttribute("BIC", new BicEst().getValue(null, graph, dataModel)); } catch (Exception e) { From 07495d6e9c31d822c43d2137bfc81264dcf291ac Mon Sep 17 00:00:00 2001 From: jdramsey Date: Thu, 21 Dec 2023 15:50:11 -0500 Subject: [PATCH 024/163] Added a tool to allow users to check violations of knowledge for a graph. --- .../editor/CheckKnowledgeEditor.java | 87 +++++++++++ .../tetradapp/model/CheckKnowledgeModel.java | 135 ++++++++++++++++++ .../src/main/resources/config/devConfig.xml | 12 +- .../src/main/resources/config/prodConfig.xml | 12 +- .../edu/cmu/tetrad/search/CheckKnowledge.java | 81 +++++++++++ 5 files changed, 325 insertions(+), 2 deletions(-) create mode 100644 tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/CheckKnowledgeEditor.java create mode 100644 tetrad-gui/src/main/java/edu/cmu/tetradapp/model/CheckKnowledgeModel.java create mode 100644 tetrad-lib/src/main/java/edu/cmu/tetrad/search/CheckKnowledge.java diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/CheckKnowledgeEditor.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/CheckKnowledgeEditor.java new file mode 100644 index 0000000000..401cf9a5e6 --- /dev/null +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/CheckKnowledgeEditor.java @@ -0,0 +1,87 @@ +/////////////////////////////////////////////////////////////////////////////// +// For information as to what this class does, see the Javadoc, below. // +// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, // +// 2007, 2008, 2009, 2010, 2014, 2015, 2022 by Peter Spirtes, Richard // +// Scheines, Joseph Ramsey, and Clark Glymour. // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation; either version 2 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program; if not, write to the Free Software // +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // +/////////////////////////////////////////////////////////////////////////////// +package edu.cmu.tetradapp.editor; + +import edu.cmu.tetrad.util.Parameters; +import edu.cmu.tetradapp.model.CheckKnowledgeModel; +import edu.cmu.tetradapp.model.EdgewiseComparisonModel; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; +import java.awt.*; + +/** + * Provides a little display/editor for notes in the session workbench. This may be elaborated in the future to allow + * marked up text. + * + * @author josephramsey + */ +public class CheckKnowledgeEditor extends JPanel { + + private static final long serialVersionUID = 7921819261142670181L; + + /** + * The model for the note. + */ + private final CheckKnowledgeModel comparison; + private final Parameters params; + private JTextArea area; + + /** + * Constructs the editor given the model + */ + public CheckKnowledgeEditor(CheckKnowledgeModel comparison) { + this.comparison = comparison; + this.params = comparison.getParams(); + setup(); + } + + //============================ Private Methods =========================// + private void setup() { + setLayout(new BorderLayout()); + + JPanel pane = new JPanel(); + + Font font = new Font("Monospaced", Font.PLAIN, 14); + area = new JTextArea(); + area.setText(tableTextWithHeader()); + + area.setFont(font); + + JScrollPane scrollTextPane = new JScrollPane(area); + scrollTextPane.setPreferredSize(new Dimension(500, 600)); + + pane.add(scrollTextPane, new BorderLayout()); + + add(pane); + + this.area.setText(comparison.getComparisonString()); + this.area.moveCaretPosition(0); + this.area.setSelectionStart(0); + this.area.setSelectionEnd(0); + + this.area.repaint(); + } + + private String tableTextWithHeader() { + return this.comparison.getComparisonString(); + } +} diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/CheckKnowledgeModel.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/CheckKnowledgeModel.java new file mode 100644 index 0000000000..2549b1d9f4 --- /dev/null +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/CheckKnowledgeModel.java @@ -0,0 +1,135 @@ +/////////////////////////////////////////////////////////////////////////////// +// For information as to what this class does, see the Javadoc, below. // +// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, // +// 2007, 2008, 2009, 2010, 2014, 2015, 2022 by Peter Spirtes, Richard // +// Scheines, Joseph Ramsey, and Clark Glymour. // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation; either version 2 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program; if not, write to the Free Software // +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // +/////////////////////////////////////////////////////////////////////////////// + +package edu.cmu.tetradapp.model; + +import edu.cmu.tetrad.data.Knowledge; +import edu.cmu.tetrad.graph.Edge; +import edu.cmu.tetrad.graph.Graph; +import edu.cmu.tetrad.search.CheckKnowledge; +import edu.cmu.tetrad.session.SessionModel; +import edu.cmu.tetrad.util.Parameters; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.util.List; + + +/** + * Compares a target workbench with a reference workbench by counting errors of omission and commission. (for edge + * presence only, not orientation). + * + * @author josephramsey + * @author Erin Korber (added remove latents functionality July 2004) + */ +public final class CheckKnowledgeModel implements SessionModel { + private static final long serialVersionUID = 23L; + private final Graph graph; + private final Knowledge knowledge; + private final Parameters params; + private final String modelName; + private String name = "Check Knowledge"; + + /** + * Compares the results of a PC to a reference workbench by counting errors of omission and commission. The counts + * can be retrieved using the methods + * countOmissionErrors and countCommissionErrors. + */ + public CheckKnowledgeModel(GraphSource model, KnowledgeBoxModel knowledgeBoxModel, Parameters params) { + if (params == null) { + throw new NullPointerException("Parameters must not be null"); + } + + if (model == null) { + throw new NullPointerException("Null graph source>"); + } + + if (knowledgeBoxModel == null) { + throw new NullPointerException("Null knowledge box model"); + } + + this.graph = model.getGraph(); + this.knowledge = knowledgeBoxModel.getKnowledge(); + this.params = params; + this.modelName = model.getName(); + } + + + public String getComparisonString() { + List forbiddenViolations = CheckKnowledge.forbiddenViolations(graph, knowledge); + List requiredViolations = CheckKnowledge.requiredViolations(graph, knowledge); + + StringBuilder sb = new StringBuilder(); + sb.append("Violations of knowledge for ").append(modelName).append(": "); + + sb.append("\n\nForbidden Violations:\n"); + + for (Edge edge : forbiddenViolations) { + sb.append("\n"); + sb.append(edge.toString()); + sb.append(", "); + } + + sb.append("\n\nRequired Violations:\n"); + + for (Edge edge : requiredViolations) { + sb.append("\n"); + sb.append(edge.toString()); + sb.append(", "); + } + + sb.append("\n\nKnowledge:\n\n"); + sb.append(knowledge); + + sb.append("\n\nGraph:\n\n"); + sb.append(graph); + + return sb.toString(); + } + + /** + * Adds semantic checks to the default deserialization method. This method must have the standard signature for a + * readObject method, and the body of the method must begin with "s.defaultReadObject();". Other than that, any + * semantic checks can be specified and do not need to stay the same from version to version. A readObject method of + * this form may be added to any class, even if Tetrad sessions were previously saved out using a version of the + * class that didn't include it. (That's what the "s.defaultReadObject();" is for. See J. Bloch, Effective Java, for + * help.) + */ + private void readObject(ObjectInputStream s) + throws IOException, ClassNotFoundException { + s.defaultReadObject(); + } + + public Parameters getParams() { + return this.params; + } + + @Override + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} + + diff --git a/tetrad-gui/src/main/resources/config/devConfig.xml b/tetrad-gui/src/main/resources/config/devConfig.xml index 14bff1cbeb..226049fdb6 100644 --- a/tetrad-gui/src/main/resources/config/devConfig.xml +++ b/tetrad-gui/src/main/resources/config/devConfig.xml @@ -1142,11 +1142,21 @@ edu.cmu.tetradapp.editor.EdgeWeightComparisonEditor + help="Model Fit" category="Simulation-Algorithm Comparisons"> edu.cmu.tetradapp.model.CPDAGFitModel edu.cmu.tetradapp.editor.CPDAGFitEditor + + + + + + edu.cmu.tetradapp.model.CheckKnowledgeModel + + edu.cmu.tetradapp.editor.CheckKnowledgeEditor + diff --git a/tetrad-gui/src/main/resources/config/prodConfig.xml b/tetrad-gui/src/main/resources/config/prodConfig.xml index f3494d414d..48a4b2f1aa 100644 --- a/tetrad-gui/src/main/resources/config/prodConfig.xml +++ b/tetrad-gui/src/main/resources/config/prodConfig.xml @@ -1112,11 +1112,21 @@ edu.cmu.tetradapp.editor.EdgeWeightComparisonEditor + help="Model Fit" category="Simulation-Algorithm Comparisons"> edu.cmu.tetradapp.model.CPDAGFitModel edu.cmu.tetradapp.editor.CPDAGFitEditor + + + + + + edu.cmu.tetradapp.model.CheckKnowledgeModel + + edu.cmu.tetradapp.editor.CheckKnowledgeEditor + diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/CheckKnowledge.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/CheckKnowledge.java new file mode 100644 index 0000000000..f0dfc1296d --- /dev/null +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/CheckKnowledge.java @@ -0,0 +1,81 @@ +package edu.cmu.tetrad.search; + +import edu.cmu.tetrad.data.Knowledge; +import edu.cmu.tetrad.data.KnowledgeEdge; +import edu.cmu.tetrad.graph.Edge; +import edu.cmu.tetrad.graph.Edges; +import edu.cmu.tetrad.graph.Graph; +import edu.cmu.tetrad.graph.Node; +import org.apache.commons.math3.util.Pair; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +/** + *

Identifies violations of knowledge for a given graph. Both forbidden and required + * knowledge is checked, by separate methods. Sorted lists of edges violating knowledge + * are returned.

+ * + * @author josephramsey + */ +public class CheckKnowledge { + + /** + * Private constructor to prevent instantiation. + */ + private CheckKnowledge() { + } + + /** + * Returns a sorted list of edges that violate the given knowledge. + * @param graph the graph. + * @param knowledge the knowledge. + * @return a sorted list of edges that violate the given knowledge. + */ + public static List forbiddenViolations(Graph graph, Knowledge knowledge) { + List forbiddenViolations = new ArrayList<>(); + + for (Edge edge : graph.getEdges()) { + if (edge.isDirected()) { + Node x = Edges.getDirectedEdgeTail(edge); + Node y = Edges.getDirectedEdgeHead(edge); + + if (knowledge.isForbidden(x.getName(), y.getName())) { + forbiddenViolations.add(edge); + } + } + } + + Collections.sort(forbiddenViolations); + + return forbiddenViolations; + } + + /** + * Returns a sorted list of edges that are required by knowledge but which do not appear in the graph. + * @param graph the graph. + * @param knowledge the knowledge. + * @return a sorted list of edges that are required by knowledge but which do not appear in the graph. + */ + public static List requiredViolations(Graph graph, Knowledge knowledge) { + List requiredViolations = new ArrayList<>(); + + Iterator knowledgeEdgeIterator = knowledge.requiredEdgesIterator(); + + while (knowledgeEdgeIterator.hasNext()) { + KnowledgeEdge edge = knowledgeEdgeIterator.next(); + Node x = graph.getNode(edge.getFrom()); + Node y = graph.getNode(edge.getTo()); + + if (!graph.containsEdge(Edges.directedEdge(x, y))) { + requiredViolations.add(Edges.directedEdge(x, y)); + } + } + + Collections.sort(requiredViolations); + + return requiredViolations; + } +} From b371e7675bcf483d848f22043a04c67ec0971ae6 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Mon, 1 Jan 2024 14:31:42 -0500 Subject: [PATCH 025/163] gernum --- .../java/edu/cmu/tetrad/bayes/MlBayesIm.java | 8 ++++-- .../edu/cmu/tetrad/search/MarkovCheck.java | 4 +-- .../cmu/tetrad/search/test/ChiSquareTest.java | 25 ++++++++++--------- .../cmu/tetrad/search/test/GSquareTest.java | 18 ++++++------- .../tetrad/search/test/IndTestGSquare.java | 8 +++--- .../src/main/resources/tetrad-lib.properties | 2 +- 6 files changed, 34 insertions(+), 31 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/bayes/MlBayesIm.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/bayes/MlBayesIm.java index 77003ff05c..4efb082c60 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/bayes/MlBayesIm.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/bayes/MlBayesIm.java @@ -32,7 +32,10 @@ import java.io.IOException; import java.io.ObjectInputStream; import java.text.NumberFormat; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; import static org.apache.commons.math3.util.FastMath.abs; import static org.apache.commons.math3.util.FastMath.pow; @@ -239,7 +242,8 @@ private static double[] getRandomWeights3(int size) { double sum = 0.0; for (int i = 0; i < size; i++) { - row[i] = RandomUtil.getInstance().nextBeta(size / 4d, size); + row[i] = RandomUtil.getInstance().nextUniform(0.05, 0.95); +// row[i] = RandomUtil.getInstance().nextBeta(size / 4d, size); sum += row[i]; } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java index ee2f0a3c4e..a9efeadc13 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java @@ -22,8 +22,6 @@ import java.util.concurrent.ForkJoinPool; import java.util.concurrent.Future; -import static org.apache.commons.math3.util.FastMath.min; - /** *

Checks whether a graph is locally Markov or locally Faithful given a data set. First a lists of m-separation * predictions are made for each pair of variables in the graph given the parents of one of the variables, one list (for @@ -43,7 +41,7 @@ public class MarkovCheck { private final List resultsIndep = new ArrayList<>(); private final List resultsDep = new ArrayList<>(); private ConditioningSetType setType; - private boolean parallelized = true; + private boolean parallelized = false; private double fractionDependentIndep = Double.NaN; private double fractionDependentDep = Double.NaN; private double ksPValueIndep = Double.NaN; diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java index 1adc8bd541..89664dfc9e 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java @@ -135,8 +135,7 @@ public Result calcChiSquare(int[] testIndices) { System.arraycopy(combination, 0, coords, 2, combination.length); long total = getCellTable().calcMargin(coords, bothVars); - - if (total == 0) continue; + if (total < ((long) testIndices[0] * (long) testIndices[1])) continue; double _xSquare = 0.0; @@ -149,18 +148,18 @@ public Result calcChiSquare(int[] testIndices) { long sumCol = getCellTable().calcMargin(coords, secondVar); long observed = getCellTable().getValue(coords); - if (sumRow == 0L) { + if (sumRow < 2) { attestedRows[i] = false; - continue; } - if (sumCol == 0L) { + if (sumCol < 2) { attestedCols[j] = false; - continue; } - double expected = (sumRow * sumCol) / (double) total; - _xSquare += FastMath.pow(observed - expected, 2.0) / expected; + if (attestedRows[i] && attestedCols[j]) { + double expected = (sumRow * sumCol) / (double) total; + _xSquare += FastMath.pow(observed - expected, 2.0) / expected; + } } } @@ -179,15 +178,17 @@ public Result calcChiSquare(int[] testIndices) { } } - if (numAttestedRows > 0 && numAttestedCols > 0) { - df += (numAttestedRows - 1) * (numAttestedCols - 1); + int _df = (numAttestedRows - 1) * (numAttestedCols - 1); + + if (_df > 0) { + df += _df; xSquare += _xSquare; } } - // If df == 0, this is definitely an independent table. + // If df == 0, this is definitely an independent table, but we can't assign a p-value. if (df == 0) { - final double pValue = 1.0; + final double pValue = Double.NaN; return new Result(xSquare, pValue, 0, true); } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/GSquareTest.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/GSquareTest.java index 7b230e59f5..f78886938c 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/GSquareTest.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/GSquareTest.java @@ -158,15 +158,15 @@ public Result calcGSquare(int[] testIndices) { boolean skip = false; - if (sumRow == 0) { - attestedRows[i] = false; - skip = true; - } - - if (sumCol == 0) { - attestedCols[j] = false; - skip = true; - } +// if (sumRow == 0) { +// attestedRows[i] = false; +// skip = true; +// } +// +// if (sumCol == 0) { +// attestedCols[j] = false; +// skip = true; +// } if (skip) { continue; diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestGSquare.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestGSquare.java index 0c847c44ce..f0c3a0c106 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestGSquare.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestGSquare.java @@ -192,10 +192,10 @@ public IndependenceResult checkIndependence(Node x, Node y, Set _z) { GSquareTest.Result result = this.gSquareTest.calcGSquare(testIndices); this.pValue = result.getPValue(); - if (Double.isNaN(this.pValue)) { - throw new RuntimeException("Undefined p-value encountered when testing " + - LogUtilsSearch.independenceFact(x, y, _z)); - } +// if (Double.isNaN(this.pValue)) { +// throw new RuntimeException("Undefined p-value encountered when testing " + +// LogUtilsSearch.independenceFact(x, y, _z)); +// } if (this.verbose) { if (result.isIndep()) { diff --git a/tetrad-lib/src/main/resources/tetrad-lib.properties b/tetrad-lib/src/main/resources/tetrad-lib.properties index e54506daf9..dc9a71c048 100644 --- a/tetrad-lib/src/main/resources/tetrad-lib.properties +++ b/tetrad-lib/src/main/resources/tetrad-lib.properties @@ -1,6 +1,6 @@ latest.version.url=https://cloud.ccd.pitt.edu datatype.continuous.test.default=edu.cmu.tetrad.algcomparison.independence.FisherZ -datatype.discrete.test.default=edu.cmu.tetrad.algcomparison.independence.Gsquare +datatype.discrete.test.default=edu.cmu.tetrad.algcomparison.independence.ChiSquare datatype.mixed.test.default=edu.cmu.tetrad.algcomparison.independence.ConditionalGaussianLRT datatype.continuous.score.default=edu.cmu.tetrad.algcomparison.score.SemBicScore datatype.discrete.score.default=edu.cmu.tetrad.algcomparison.score.BdeuScore From 877635a59f8d2e04c48e1a2143ba7815244195ec Mon Sep 17 00:00:00 2001 From: jdramsey Date: Tue, 2 Jan 2024 15:40:57 -0500 Subject: [PATCH 026/163] Added min edge count per table parameter to Chi-Square. --- .../algcomparison/independence/ChiSquare.java | 4 +- .../main/java/edu/cmu/tetrad/graph/Edge.java | 2 +- .../cmu/tetrad/search/test/ChiSquareTest.java | 45 ++++++++++++++++--- .../tetrad/search/test/IndTestChiSquare.java | 32 ++++++++++++- .../main/java/edu/cmu/tetrad/util/Params.java | 2 + .../src/main/resources/docs/manual/index.html | 22 +++++++++ .../java/edu/cmu/tetrad/test/TestFges.java | 2 +- 7 files changed, 99 insertions(+), 10 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/ChiSquare.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/ChiSquare.java index d78c8c1147..26021e5ffb 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/ChiSquare.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/ChiSquare.java @@ -28,7 +28,9 @@ public class ChiSquare implements IndependenceWrapper { @Override public IndependenceTest getTest(DataModel dataSet, Parameters parameters) { - return new IndTestChiSquare(SimpleDataLoader.getDiscreteDataSet(dataSet), parameters.getDouble("alpha")); + IndTestChiSquare test = new IndTestChiSquare(SimpleDataLoader.getDiscreteDataSet(dataSet), parameters.getDouble("test")); + test.setMinCountPerTable(parameters.getInt(Params.MIN_COUNT_PER_TABLE)); + return test; } @Override diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/graph/Edge.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/graph/Edge.java index 374b74cac7..ed6f1ba5c6 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/graph/Edge.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/graph/Edge.java @@ -317,7 +317,7 @@ public final String toString() { } public final int hashCode() { - return 1; + return node1.hashCode() + node2.hashCode(); } /** diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java index 89664dfc9e..c8a13b8a50 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java @@ -31,7 +31,9 @@ import java.util.Arrays; /** - * Calculates marginal chi square test results for a discrete dataset. + * Calculates chi-square for a conditional cross-tabulation table for independence question 0 _||_ 1 | 2, 3, ...max by + * summing up chi-square and degrees of freedom for each conditional table in turn, where rows or columns that consist + * entirely of zeros have been removed. The conitional tables are restricted to have at least minCountPerTable counts. * * @author frankwimberly * @author josephramsey @@ -58,6 +60,14 @@ public class ChiSquareTest { */ private double alpha; + /** + * The minimum number of counts per conditional table for chi-square for that table and its degrees of freedom to be + * included in the overall chi-square and degrees of freedom. The default is 20. Note that this should not be too + * small, or the chi-square distribution will not be a good approximation to the distribution of the test + * statistic. + */ + private long minCountPerTable = 20; + /** * Constructs a test using the given data set and significance level. @@ -135,7 +145,7 @@ public Result calcChiSquare(int[] testIndices) { System.arraycopy(combination, 0, coords, 2, combination.length); long total = getCellTable().calcMargin(coords, bothVars); - if (total < ((long) testIndices[0] * (long) testIndices[1])) continue; + if (total < minCountPerTable) continue; double _xSquare = 0.0; @@ -148,17 +158,20 @@ public Result calcChiSquare(int[] testIndices) { long sumCol = getCellTable().calcMargin(coords, secondVar); long observed = getCellTable().getValue(coords); - if (sumRow < 2) { + if (sumRow == 0) { attestedRows[i] = false; } - if (sumCol < 2) { + if (sumCol == 9) { attestedCols[j] = false; } if (attestedRows[i] && attestedCols[j]) { double expected = (sumRow * sumCol) / (double) total; - _xSquare += FastMath.pow(observed - expected, 2.0) / expected; + + if (expected > 0) { + _xSquare += FastMath.pow(observed - expected, 2.0) / expected; + } } } } @@ -302,6 +315,28 @@ private CellTable getCellTable() { return this.cellTable; } + /** + * The minimum number of counts per conditional table for chi-square for that table and its degrees of freedom to be + * included in the overall chi-square and degrees of freedom. Note that this should not be too small, or the + * chi-square distribution will not be a good approximation to the distribution of the test statistic. + * + * @return The minimum number of counts per conditional table. + */ + public long getMinCountPerTable() { + return minCountPerTable; + } + + /** + * The minimum number of counts per conditional table for chi-square for that table and its degrees of freedom to be + * included in the overall chi-square and degrees of freedom. Note that this should not be too small, or the + * chi-square distribution will not be a good approximation to the distribution of the test statistic. + * + * @param minCountPerTable The minimum number of counts per conditional table. + */ + public void setMinCountPerTable(long minCountPerTable) { + this.minCountPerTable = minCountPerTable; + } + /** * Simple class to store the parameters of the result returned by the G Square test. diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestChiSquare.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestChiSquare.java index 655b9e983b..f7fde5e8c7 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestChiSquare.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestChiSquare.java @@ -38,8 +38,8 @@ /** * Checks the conditional independence X _||_ Y | S, where S is a set of discrete variable, and X and Y are discrete * variable not in S, by applying a conditional Chi Square test. A description of such a test is given in Fienberg, "The - * Analysis of Cross-Classified Categorical Data," 2nd edition. - * The formulas for the degrees of freedom used in this test are equivalent to the formulation on page 142 of Fienberg. + * Analysis of Cross-Classified Categorical Data," 2nd edition. The formulas for the degrees of freedom used in this + * test are equivalent to the formulation on page 142 of Fienberg. * * @author josephramsey * @see ChiSquareTest @@ -73,6 +73,8 @@ public final class IndTestChiSquare implements IndependenceTest { */ private int df; + private int minCountPerTable = 20; + private boolean verbose; /** @@ -342,6 +344,32 @@ private double getDeterminationP() { */ return 0.99; } + + /** + * The minimum number of counts per conditional table for chi-square for that table and its degrees of freedom to be + * included in the overall chi-square and degrees of freedom. The default is 20. Note that this should not be too + * small, or the chi-square distribution will not be a good approximation to the distribution of the test + * statistic. + * + * @return The minimum number of counts per conditional table for chi-square for that table and its degrees of + * freedom to be included in the overall chi-square and degrees of freedom. + */ + public int getMinCountPerTable() { + return minCountPerTable; + } + + /** + * The minimum number of counts per conditional table for chi-square for that table and its degrees of freedom to be + * included in the overall chi-square and degrees of freedom. The default is 20. Note that this should not be too + * small, or the chi-square distribution will not be a good approximation to the distribution of the test + * statistic. + * + * @param minCountPerTable The minimum number of counts per conditional table for chi-square for that table and its + * degrees of freedom to be included in the overall chi-square and degrees of freedom. + */ + public void setMinCountPerTable(int minCountPerTable) { + this.minCountPerTable = minCountPerTable; + } } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/util/Params.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/util/Params.java index 6668fbdb10..c94f04780e 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/util/Params.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/util/Params.java @@ -254,6 +254,8 @@ public final class Params { public static final String REMOVE_EFFECT_NODES = "removeEffectNodes"; public static final String SAMPLE_STYLE = "sampleStyle"; public static final String NUM_THREADS = "numThreads"; + public static String MIN_COUNT_PER_TABLE = "minCountPerTable"; + // All parameters that are found in HTML manual documentation private static final Set ALL_PARAMS_IN_HTML_MANUAL = new HashSet<>(Arrays.asList( diff --git a/tetrad-lib/src/main/resources/docs/manual/index.html b/tetrad-lib/src/main/resources/docs/manual/index.html index 4521501ef5..de7663a93e 100755 --- a/tetrad-lib/src/main/resources/docs/manual/index.html +++ b/tetrad-lib/src/main/resources/docs/manual/index.html @@ -5441,6 +5441,28 @@

depth

id="depth_value_type">Integer +

minCountPerTable

+
    +
  • Short Description: + Minimum count per conditional table
  • +
  • Long Description: + The minimum number of counts per conditional table for chi-square for that table + and its degrees of freedom to be included in the overall chi-square and degrees of + freedom. The default is 20. Note that this should not be too small, or the + chi-square distribution will not be a good approximation to the distribution of + the test statistic.
  • +
  • Default Value: 20
  • +
  • Lower + Bound: 1
  • +
  • Upper Bound: 2147483647
  • +
  • Value Type: + Integer
  • +
+

determinismThreshold

    Date: Tue, 2 Jan 2024 15:43:29 -0500 Subject: [PATCH 027/163] Added min edge count per table parameter to Chi-Square. --- .../edu/cmu/tetrad/algcomparison/independence/ChiSquare.java | 1 + 1 file changed, 1 insertion(+) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/ChiSquare.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/ChiSquare.java index 26021e5ffb..41e2c97a9e 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/ChiSquare.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/ChiSquare.java @@ -47,6 +47,7 @@ public DataType getDataType() { public List getParameters() { List params = new ArrayList<>(); params.add(Params.ALPHA); + params.add(Params.MIN_COUNT_PER_TABLE); return params; } From 64a51c0e2ad979d162e252a5e67bf3b18f853792 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Wed, 3 Jan 2024 10:13:20 -0500 Subject: [PATCH 028/163] Added min edge count per table parameter to Chi-Square. --- .../algcomparison/independence/ChiSquare.java | 2 +- .../java/edu/cmu/tetrad/data/CellTable.java | 31 +++++++-- .../edu/cmu/tetrad/search/MarkovCheck.java | 8 ++- .../cmu/tetrad/search/test/ChiSquareTest.java | 69 +++++++------------ .../tetrad/search/test/IndTestChiSquare.java | 2 + 5 files changed, 59 insertions(+), 53 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/ChiSquare.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/ChiSquare.java index 41e2c97a9e..5ae4054c97 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/ChiSquare.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/ChiSquare.java @@ -28,7 +28,7 @@ public class ChiSquare implements IndependenceWrapper { @Override public IndependenceTest getTest(DataModel dataSet, Parameters parameters) { - IndTestChiSquare test = new IndTestChiSquare(SimpleDataLoader.getDiscreteDataSet(dataSet), parameters.getDouble("test")); + IndTestChiSquare test = new IndTestChiSquare(SimpleDataLoader.getDiscreteDataSet(dataSet), parameters.getDouble(Params.ALPHA)); test.setMinCountPerTable(parameters.getInt(Params.MIN_COUNT_PER_TABLE)); return test; } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/data/CellTable.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/data/CellTable.java index 58d59bdd6f..b6c65987ff 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/data/CellTable.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/data/CellTable.java @@ -23,7 +23,9 @@ import edu.cmu.tetrad.util.MultiDimIntTable; +import java.util.ArrayList; import java.util.Arrays; +import java.util.List; /** @@ -35,17 +37,12 @@ */ public final class CellTable { - -// /** -// * Stores a copy of coordinates for temporary use. (Reused.) -// */ -// private int[] coordCopy; - private final MultiDimIntTable table; /** * The value used in the data for missing values. */ private int missingValue = -99; + private List rows; /** * Constructs a new cell table using the given array for dimensions, initializing all cells in the table to zero. @@ -57,6 +54,17 @@ public CellTable(int[] dims) { } public void addToTable(DataSet dataSet, int[] indices) { + if (rows == null) { + rows = new ArrayList<>(); + for (int i = 0; i < dataSet.getNumRows(); i++) { + rows.add(i); + } + } else { + for (int i = 0; i < rows.size(); i++) { + if (rows.get(i) >= dataSet.getNumRows()) throw new IllegalArgumentException("Row " + i + " is too large."); + } + } + int[] dims = new int[indices.length]; for (int i = 0; i < indices.length; i++) { @@ -70,7 +78,7 @@ public void addToTable(DataSet dataSet, int[] indices) { int[] coords = new int[indices.length]; points: - for (int i = 0; i < dataSet.getNumRows(); i++) { + for (int i : rows) { for (int j = 0; j < indices.length; j++) { try { coords[j] = dataSet.getInt(i, indices[j]); @@ -173,6 +181,15 @@ public void setMissingValue(int missingValue) { public long getValue(int[] testCell) { return this.table.getValue(testCell); } + + public void setRows(List rows) { + if (rows == null) throw new NullPointerException("Rows is null."); + for (int i = 0; i < rows.size(); i++) { + if (rows.get(i) == null) throw new NullPointerException("Row " + i + " is null."); + if (rows.get(i) < 0) throw new IllegalArgumentException("Row " + i + " is negative."); + } + this.rows = rows; + } } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java index a9efeadc13..1bc16a9db7 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java @@ -516,7 +516,9 @@ public Pair, Set> call() { double pValue = result.getPValue(); independenceTest.setVerbose(verbose); - if (!Double.isNaN(pValue)) { + if (Double.isNaN(pValue)) { + System.out.println("Skipping " + fact + " because p-value is NaN."); + } else { if (msep) { resultsIndep.add(new IndependenceResult(fact, indep, pValue, Double.NaN)); } else { @@ -536,7 +538,9 @@ public Pair, Set> call() { double pValue = result.getPValue(); independenceTest.setVerbose(verbose); - if (!Double.isNaN(pValue)) { + if (Double.isNaN(pValue)) { + System.out.println("Skipping " + fact + " because p-value is NaN."); + } else { if (msep) { resultsIndep.add(new IndependenceResult(fact, indep, pValue, Double.NaN)); } else { diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java index c8a13b8a50..9d71405b02 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java @@ -30,10 +30,12 @@ import java.util.Arrays; +import static org.apache.commons.math3.util.FastMath.pow; + /** * Calculates chi-square for a conditional cross-tabulation table for independence question 0 _||_ 1 | 2, 3, ...max by * summing up chi-square and degrees of freedom for each conditional table in turn, where rows or columns that consist - * entirely of zeros have been removed. The conitional tables are restricted to have at least minCountPerTable counts. + * entirely of zeros have been removed. The conditional tables are restricted to have at least minCountPerTable counts. * * @author frankwimberly * @author josephramsey @@ -134,78 +136,59 @@ public Result calcChiSquare(int[] testIndices) { // Make a chi square table for each condition combination, strike zero rows and columns and calculate // chi square and degrees of freedom for the remaining rows and columns in the table. See Friedman. while (combinationIterator.hasNext()) { - boolean[] attestedRows = new boolean[numRows]; - boolean[] attestedCols = new boolean[numCols]; - - Arrays.fill(attestedRows, true); - Arrays.fill(attestedCols, true); - int[] combination = combinationIterator.next(); System.arraycopy(combination, 0, coords, 2, combination.length); - long total = getCellTable().calcMargin(coords, bothVars); - if (total < minCountPerTable) continue; - double _xSquare = 0.0; + int zeros = 0; for (int i = 0; i < numRows; i++) { for (int j = 0; j < numCols; j++) { coords[0] = i; coords[1] = j; - long sumRow = getCellTable().calcMargin(coords, firstVar); - long sumCol = getCellTable().calcMargin(coords, secondVar); - long observed = getCellTable().getValue(coords); + double sumRow = getCellTable().calcMargin(coords, firstVar); + double sumCol = getCellTable().calcMargin(coords, secondVar); + double observed = getCellTable().getValue(coords); + double total = getCellTable().calcMargin(coords, bothVars); - if (sumRow == 0) { - attestedRows[i] = false; - } - - if (sumCol == 9) { - attestedCols[j] = false; - } - - if (attestedRows[i] && attestedCols[j]) { - double expected = (sumRow * sumCol) / (double) total; + if (total >= minCountPerTable) { + double expected = (sumRow * sumCol) / (total); if (expected > 0) { - _xSquare += FastMath.pow(observed - expected, 2.0) / expected; + _xSquare += pow(observed - expected, 2.0) / expected; + } else { + zeros++; } + } else { + zeros += numRows * numCols; } } } - int numAttestedRows = 0; - int numAttestedCols = 0; - - for (boolean attestedRow : attestedRows) { - if (attestedRow) { - numAttestedRows++; - } - } - - for (boolean attestedCol : attestedCols) { - if (attestedCol) { - numAttestedCols++; - } - } - - int _df = (numAttestedRows - 1) * (numAttestedCols - 1); + int _df = (numRows - 1) * (numCols - 1) - zeros; + // There were free degrees of freedom in the table, so we count this chi-square and df. if (_df > 0) { df += _df; xSquare += _xSquare; } } - // If df == 0, this is definitely an independent table, but we can't assign a p-value. + // None of the conditional tables had enough counts to be included in the overall chi-square. if (df == 0) { - final double pValue = Double.NaN; - return new Result(xSquare, pValue, 0, true); + return new Result(xSquare, Double.NaN, df, true); } + // Cannot be NaN. double pValue = 1.0 - new ChiSquaredDistribution(df).cumulativeProbability(xSquare); + + // The Chi-Square distribution doesn't go out this far numerically, so this value can't be trusted. + if (pValue == 1.0) { + return new Result(xSquare, Double.NaN, df, false); + } + boolean indep = (pValue > getAlpha()); return new Result(xSquare, pValue, df, indep); } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestChiSquare.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestChiSquare.java index f7fde5e8c7..066abd809e 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestChiSquare.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestChiSquare.java @@ -101,6 +101,7 @@ public IndTestChiSquare(DataSet dataSet, double alpha) { this.variables = new ArrayList<>(dataSet.getVariables()); this.chiSquareTest = new ChiSquareTest(dataSet, alpha); + this.chiSquareTest.setMinCountPerTable(minCountPerTable); } /** @@ -369,6 +370,7 @@ public int getMinCountPerTable() { */ public void setMinCountPerTable(int minCountPerTable) { this.minCountPerTable = minCountPerTable; + this.chiSquareTest.setMinCountPerTable(minCountPerTable); } } From 38951ab05c71b03fcc5313d7ee8e7e06ade58efd Mon Sep 17 00:00:00 2001 From: jdramsey Date: Wed, 3 Jan 2024 10:46:32 -0500 Subject: [PATCH 029/163] Added min edge count per table parameter to Chi-Square. --- .../algcomparison/independence/ChiSquare.java | 5 +-- .../cmu/tetrad/search/test/ChiSquareTest.java | 24 +++++------ .../tetrad/search/test/IndTestChiSquare.java | 36 ++++++++-------- .../main/java/edu/cmu/tetrad/util/Params.java | 2 +- .../src/main/resources/docs/manual/index.html | 43 +++++++++---------- 5 files changed, 51 insertions(+), 59 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/ChiSquare.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/ChiSquare.java index 5ae4054c97..f9fada3f20 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/ChiSquare.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/ChiSquare.java @@ -29,7 +29,7 @@ public class ChiSquare implements IndependenceWrapper { @Override public IndependenceTest getTest(DataModel dataSet, Parameters parameters) { IndTestChiSquare test = new IndTestChiSquare(SimpleDataLoader.getDiscreteDataSet(dataSet), parameters.getDouble(Params.ALPHA)); - test.setMinCountPerTable(parameters.getInt(Params.MIN_COUNT_PER_TABLE)); + test.setMinCountFraction(parameters.getInt(Params.MIN_COUNT_FRACTION)); return test; } @@ -47,8 +47,7 @@ public DataType getDataType() { public List getParameters() { List params = new ArrayList<>(); params.add(Params.ALPHA); - params.add(Params.MIN_COUNT_PER_TABLE); + params.add(Params.MIN_COUNT_FRACTION); return params; } - } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java index 9d71405b02..e5bd5d5476 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java @@ -26,9 +26,6 @@ import edu.cmu.tetrad.data.DiscreteVariable; import edu.cmu.tetrad.util.CombinationIterator; import org.apache.commons.math3.distribution.ChiSquaredDistribution; -import org.apache.commons.math3.util.FastMath; - -import java.util.Arrays; import static org.apache.commons.math3.util.FastMath.pow; @@ -63,12 +60,11 @@ public class ChiSquareTest { private double alpha; /** - * The minimum number of counts per conditional table for chi-square for that table and its degrees of freedom to be - * included in the overall chi-square and degrees of freedom. The default is 20. Note that this should not be too - * small, or the chi-square distribution will not be a good approximation to the distribution of the test - * statistic. + * The minimum number of counts per conditional table for chi-square expressed as a multiple of the total number of + * cells in the table. Note that this should not be too small, or the chi-square distribution will not be a good + * approximation to the distribution of the test statistic. */ - private long minCountPerTable = 20; + private double minCountFraction = 2.0; /** @@ -153,7 +149,7 @@ public Result calcChiSquare(int[] testIndices) { double observed = getCellTable().getValue(coords); double total = getCellTable().calcMargin(coords, bothVars); - if (total >= minCountPerTable) { + if (total >= minCountFraction * (numRows * numCols)) { double expected = (sumRow * sumCol) / (total); if (expected > 0) { @@ -305,8 +301,8 @@ private CellTable getCellTable() { * * @return The minimum number of counts per conditional table. */ - public long getMinCountPerTable() { - return minCountPerTable; + public double getMinCountFraction() { + return minCountFraction; } /** @@ -314,10 +310,10 @@ public long getMinCountPerTable() { * included in the overall chi-square and degrees of freedom. Note that this should not be too small, or the * chi-square distribution will not be a good approximation to the distribution of the test statistic. * - * @param minCountPerTable The minimum number of counts per conditional table. + * @param minCountFraction The minimum number of counts per conditional table. */ - public void setMinCountPerTable(long minCountPerTable) { - this.minCountPerTable = minCountPerTable; + public void setMinCountFraction(double minCountFraction) { + this.minCountFraction = minCountFraction; } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestChiSquare.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestChiSquare.java index 066abd809e..166e35ae7b 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestChiSquare.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestChiSquare.java @@ -73,7 +73,7 @@ public final class IndTestChiSquare implements IndependenceTest { */ private int df; - private int minCountPerTable = 20; + private int minCountFraction = 20; private boolean verbose; @@ -101,7 +101,7 @@ public IndTestChiSquare(DataSet dataSet, double alpha) { this.variables = new ArrayList<>(dataSet.getVariables()); this.chiSquareTest = new ChiSquareTest(dataSet, alpha); - this.chiSquareTest.setMinCountPerTable(minCountPerTable); + this.chiSquareTest.setMinCountFraction(minCountFraction); } /** @@ -347,30 +347,28 @@ private double getDeterminationP() { } /** - * The minimum number of counts per conditional table for chi-square for that table and its degrees of freedom to be - * included in the overall chi-square and degrees of freedom. The default is 20. Note that this should not be too - * small, or the chi-square distribution will not be a good approximation to the distribution of the test - * statistic. + * The minimum number of counts per conditional table for chi-square expressed as a fraction of the total number of + * cells in the conditional table. Default is 2. Note that this should not be too small, or the chi-square + * distribution will not be a good approximation to the distribution of the test statistic. * - * @return The minimum number of counts per conditional table for chi-square for that table and its degrees of - * freedom to be included in the overall chi-square and degrees of freedom. + * @return The minimum number of counts per conditional table expressed as a fraction of the total number of cells + * in the conditional table. */ - public int getMinCountPerTable() { - return minCountPerTable; + public int getMinCountFraction() { + return minCountFraction; } /** - * The minimum number of counts per conditional table for chi-square for that table and its degrees of freedom to be - * included in the overall chi-square and degrees of freedom. The default is 20. Note that this should not be too - * small, or the chi-square distribution will not be a good approximation to the distribution of the test - * statistic. + * The minimum number of counts per conditional table for chi-square expressed as a fraction of the total number of + * cells in the conditional table. Default is 2. Note that this should not be too small, or the chi-square + * distribution will not be a good approximation to the distribution of the test statistic. * - * @param minCountPerTable The minimum number of counts per conditional table for chi-square for that table and its - * degrees of freedom to be included in the overall chi-square and degrees of freedom. + * @param minCountFraction The minimum number of counts per conditional table expressed as a fraction of the total + * number of cells in the conditional table. */ - public void setMinCountPerTable(int minCountPerTable) { - this.minCountPerTable = minCountPerTable; - this.chiSquareTest.setMinCountPerTable(minCountPerTable); + public void setMinCountFraction(int minCountFraction) { + this.minCountFraction = minCountFraction; + this.chiSquareTest.setMinCountFraction(minCountFraction); } } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/util/Params.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/util/Params.java index c94f04780e..ef40400f6a 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/util/Params.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/util/Params.java @@ -254,7 +254,7 @@ public final class Params { public static final String REMOVE_EFFECT_NODES = "removeEffectNodes"; public static final String SAMPLE_STYLE = "sampleStyle"; public static final String NUM_THREADS = "numThreads"; - public static String MIN_COUNT_PER_TABLE = "minCountPerTable"; + public static String MIN_COUNT_FRACTION = "minCountFraction"; // All parameters that are found in HTML manual documentation diff --git a/tetrad-lib/src/main/resources/docs/manual/index.html b/tetrad-lib/src/main/resources/docs/manual/index.html index de7663a93e..8aa04e1835 100755 --- a/tetrad-lib/src/main/resources/docs/manual/index.html +++ b/tetrad-lib/src/main/resources/docs/manual/index.html @@ -5441,28 +5441,6 @@

    depth

    id="depth_value_type">Integer
-

minCountPerTable

-
    -
  • Short Description: - Minimum count per conditional table
  • -
  • Long Description: - The minimum number of counts per conditional table for chi-square for that table - and its degrees of freedom to be included in the overall chi-square and degrees of - freedom. The default is 20. Note that this should not be too small, or the - chi-square distribution will not be a good approximation to the distribution of - the test statistic.
  • -
  • Default Value: 20
  • -
  • Lower - Bound: 1
  • -
  • Upper Bound: 2147483647
  • -
  • Value Type: - Integer
  • -
-

determinismThreshold

    kciEpsilon id="kernelRegressionSampleSize_value_type">Integer
+

minCountFraction

+
    +
  • Short Description: + Minimum fraction of number of cells in a conditional table.
  • +
  • Long Description: + The minimum number of counts per conditional table for chi-square expressed as + a fraction of the total number of cells in the conditional table. Default is 2. + Note that this should not be too small, or the chi-square distribution will not + be a good approximation to the distribution of the test statistic
  • +
  • Default Value: 2.0
  • +
  • Lower + Bound: 0.0
  • +
  • Upper Bound: Infinity
  • +
  • Value Type: + Double
  • +
+

kernelType

  • Short Description: Date: Wed, 3 Jan 2024 10:48:02 -0500 Subject: [PATCH 030/163] Added min edge count per table parameter to Chi-Square. --- .../cmu/tetrad/search/test/ChiSquareTest.java | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java index e5bd5d5476..e480bb9419 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java @@ -233,9 +233,9 @@ public boolean isDetermined(int[] testIndices, double p) { for (int i = 0; i < numValues; i++) { coords[0] = i; - long numi = this.getCellTable().getValue(coords); + long value = this.getCellTable().getValue(coords); - if ((double) numi / total >= p) { + if ((double) value / total >= p) { dominates = true; } } @@ -294,17 +294,6 @@ private CellTable getCellTable() { return this.cellTable; } - /** - * The minimum number of counts per conditional table for chi-square for that table and its degrees of freedom to be - * included in the overall chi-square and degrees of freedom. Note that this should not be too small, or the - * chi-square distribution will not be a good approximation to the distribution of the test statistic. - * - * @return The minimum number of counts per conditional table. - */ - public double getMinCountFraction() { - return minCountFraction; - } - /** * The minimum number of counts per conditional table for chi-square for that table and its degrees of freedom to be * included in the overall chi-square and degrees of freedom. Note that this should not be too small, or the @@ -340,7 +329,7 @@ public static class Result { private final int df; /** - * Whether the conditional independence holds or not. (True if it does, false if it doesn't. + * Whether the conditional independence holds or not. (True if it does, false if it doesn't.) */ private final boolean isIndep; From 8aff66e6e58e30ae32c4c85c4f2f7ae6eaebc65e Mon Sep 17 00:00:00 2001 From: jdramsey Date: Wed, 3 Jan 2024 10:50:47 -0500 Subject: [PATCH 031/163] Added min edge count per table parameter to Chi-Square. --- .../main/java/edu/cmu/tetrad/data/CellTable.java | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/data/CellTable.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/data/CellTable.java index b6c65987ff..b4321f8257 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/data/CellTable.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/data/CellTable.java @@ -83,7 +83,6 @@ public void addToTable(DataSet dataSet, int[] indices) { try { coords[j] = dataSet.getInt(i, indices[j]); } catch (Exception e) { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. coords[j] = dataSet.getInt(i, j); } @@ -116,7 +115,7 @@ public int getNumValues(int varIndex) { public long calcMargin(int[] coords) { int[] coordCopy = internalCoordCopy(coords); - int sum = 0; + long sum = 0; int i = -1; while (++i < coordCopy.length) { @@ -137,7 +136,7 @@ public long calcMargin(int[] coords) { /** * An alternative way to specify a marginal calculation. In this case, coords specifies a particular cell in the * table, and varIndices is an array containing the indices of the variables over which the margin sum should be - * calculated. The sum is over the cell specified by 'coord' and all of the cells which differ from that cell in any + * calculated. The sum is over the cell specified by 'coord' and all the cells which differ from that cell in any * of the specified coordinates. * * @param coords an int[] value @@ -158,16 +157,7 @@ public long calcMargin(int[] coords, int[] marginVars) { * Makes a copy of the coordinate array so that the original is not messed up. */ private int[] internalCoordCopy(int[] coords) { - int[] coordCopy = Arrays.copyOf(coords, coords.length); - -// if ((this.coordCopy == null) || -// (this.coordCopy.length != coords.length)) { -// this.coordCopy = new int[coords.length]; -// } -// -// System.arraycopy(coords, 0, this.coordCopy, 0, coords.length); - - return coordCopy; + return Arrays.copyOf(coords, coords.length); } private int getMissingValue() { From 7b266332c3904fefe3d613191b03b2163769f4d5 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Wed, 3 Jan 2024 11:40:12 -0500 Subject: [PATCH 032/163] Made GSquare and option in the ChiSquareTest, and got right of the previous GSquareTest. --- .../cmu/tetrad/search/test/ChiSquareTest.java | 44 +- .../cmu/tetrad/search/test/GSquareTest.java | 402 ------------------ .../tetrad/search/test/IndTestChiSquare.java | 2 +- .../tetrad/search/test/IndTestGSquare.java | 15 +- 4 files changed, 33 insertions(+), 430 deletions(-) delete mode 100644 tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/GSquareTest.java diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java index e480bb9419..d410c90b71 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java @@ -26,6 +26,7 @@ import edu.cmu.tetrad.data.DiscreteVariable; import edu.cmu.tetrad.util.CombinationIterator; import org.apache.commons.math3.distribution.ChiSquaredDistribution; +import org.apache.commons.math3.util.FastMath; import static org.apache.commons.math3.util.FastMath.pow; @@ -38,25 +39,24 @@ * @author josephramsey */ public class ChiSquareTest { + public enum TestType { + CHI_SQUARE, + G_SQUARE + } - /** - * The data set this test uses. - */ + // The type of test to perform. + private TestType testType = TestType.CHI_SQUARE; + + // The data set this test uses. private final DataSet dataSet; - /** - * The number of values for each variable in the data. - */ + // The number of values for each variable in the data. private final int[] dims; - /** - * Stores the data in the form of a cell table. - */ + // Stores the data in the form of a cell table. private final CellTable cellTable; - /** - * The significance level of the test. - */ + // The significance level of the test. private double alpha; /** @@ -70,10 +70,11 @@ public class ChiSquareTest { /** * Constructs a test using the given data set and significance level. * - * @param dataSet A data set consisting entirely of discrete variables. - * @param alpha The significance level, usually 0.05. + * @param dataSet A data set consisting entirely of discrete variables. + * @param alpha The significance level, usually 0.05. + * @param testType The type of test to perform, either CHI_SQUARE or G_SQUARE. */ - public ChiSquareTest(DataSet dataSet, double alpha) { + public ChiSquareTest(DataSet dataSet, double alpha, TestType testType) { if (alpha < 0.0 || alpha > 1.0) { throw new IllegalArgumentException("Significance level must be in " + "[0, 1]: " + alpha); @@ -87,6 +88,7 @@ public ChiSquareTest(DataSet dataSet, double alpha) { this.getDims()[i] = variable.getNumCategories(); } + this.testType = testType; this.dataSet = dataSet; this.alpha = alpha; this.cellTable = new CellTable(null); @@ -153,7 +155,17 @@ public Result calcChiSquare(int[] testIndices) { double expected = (sumRow * sumCol) / (total); if (expected > 0) { - _xSquare += pow(observed - expected, 2.0) / expected; + if (testType == TestType.CHI_SQUARE) { + _xSquare += pow(observed - expected, 2.0) / expected; + } else if (testType == TestType.G_SQUARE) { + if (observed > 0) { + _xSquare += 2.0 * observed * FastMath.log(observed / expected); + } else { + zeros++; + } + } else { + throw new IllegalArgumentException("Unknown test type: " + testType); + } } else { zeros++; } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/GSquareTest.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/GSquareTest.java deleted file mode 100644 index f78886938c..0000000000 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/GSquareTest.java +++ /dev/null @@ -1,402 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// For information as to what this class does, see the Javadoc, below. // -// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, // -// 2007, 2008, 2009, 2010, 2014, 2015, 2022 by Peter Spirtes, Richard // -// Scheines, Joseph Ramsey, and Clark Glymour. // -// // -// This program is free software; you can redistribute it and/or modify // -// it under the terms of the GNU General Public License as published by // -// the Free Software Foundation; either version 2 of the License, or // -// (at your option) any later version. // -// // -// This program is distributed in the hope that it will be useful, // -// but WITHOUT ANY WARRANTY; without even the implied warranty of // -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // -// GNU General Public License for more details. // -// // -// You should have received a copy of the GNU General Public License // -// along with this program; if not, write to the Free Software // -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // -/////////////////////////////////////////////////////////////////////////////// - -package edu.cmu.tetrad.search.test; - -import edu.cmu.tetrad.data.CellTable; -import edu.cmu.tetrad.data.DataSet; -import edu.cmu.tetrad.data.DiscreteVariable; -import edu.cmu.tetrad.util.CombinationIterator; -import edu.cmu.tetrad.util.ProbUtils; -import org.apache.commons.math3.util.FastMath; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -/** - *

    Performs conditional independence tests of discrete data using the G Square method. - * Degrees of freedom are calculated as in Fienberg (2007), this reference:

    - * - *

    Fienberg, S. E. (2007). The analysis of cross-classified categorical data. - * Springer Science & Business Media.

    - * - * @author Frank Wimberly original version - * @author josephramsey revision 10/01 - */ -public final class GSquareTest { - - /** - * The data set this test uses. - */ - private final DataSet dataSet; - - /** - * The number of values for each variable in the data. - */ - private final int[] dims; - - /** - * Stores the data in the form of a cell table. - */ - private final CellTable cellTable; - - /** - * The significance level of the test. - */ - private double alpha; - - /** - * Constructor - * - * @param dataSet The discrete dataset for which test results are requested. - * @param alpha The alpha sigificance level cutoff. - */ - public GSquareTest(DataSet dataSet, double alpha) { - if (alpha < 0.0 || alpha > 1.0) { - throw new IllegalArgumentException("Significance level must be in " + - "[0, 1]: " + alpha); - } - - this.dims = new int[dataSet.getNumColumns()]; - - for (int i = 0; i < getDims().length; i++) { - DiscreteVariable variable = - (DiscreteVariable) dataSet.getVariable(i); - this.getDims()[i] = variable.getNumCategories(); - } - - this.dataSet = dataSet; - this.alpha = alpha; - this.cellTable = new CellTable(null); - this.getCellTable().setMissingValue(DiscreteVariable.MISSING_VALUE); - } - - /** - * Calculates g square for a conditional crosstabulation table for independence question 0 _||_ 1 | 2, 3, ...max by - * summing up g square and degrees of freedom for each conditional table in turn, where rows or columns that consist - * entirely of zeros have been removed. - * - * @param testIndices The indices of the test result needed, in order. So for the above, [0 1 2 3...max]. - * @return the test result. - * @see Result - */ - public Result calcGSquare(int[] testIndices) { - - if (testIndices.length < 2) - throw new IllegalArgumentException("Need at least two variables for G Square test."); - - // Reset the cell table for the columns referred to in - // 'testIndices.' Do cell coefs for those columns. - getCellTable().addToTable(getDataSet(), testIndices); - - // Indicator arrays to tell the cell table which margins - // to calculate. For x _||_ y | z1, z2, ..., we want to - // calculate the margin for x, the margin for y, and the - // margin for x and y. (These will be used later.) - int[] firstVar = {0}; - int[] secondVar = {1}; - int[] bothVars = {0, 1}; - - double g2 = 0.0; - int df = 0; - - int[] condDims = new int[testIndices.length - 2]; - System.arraycopy(selectFromArray(getDims(), testIndices), 2, condDims, 0, - condDims.length); - - int[] coords = new int[testIndices.length]; - int numRows = this.getCellTable().getNumValues(0); - int numCols = this.getCellTable().getNumValues(1); - - boolean[] attestedRows = new boolean[numRows]; - boolean[] attestedCols = new boolean[numCols]; - - CombinationIterator combinationIterator = - new CombinationIterator(condDims); - - while (combinationIterator.hasNext()) { - int[] combination = combinationIterator.next(); - - System.arraycopy(combination, 0, coords, 2, combination.length); - Arrays.fill(attestedRows, true); - Arrays.fill(attestedCols, true); - - long total = this.getCellTable().calcMargin(coords, bothVars); - - double _gSquare = 0.0; - - List e = new ArrayList<>(); - List o = new ArrayList<>(); - - for (int i = 0; i < numRows; i++) { - for (int j = 0; j < numCols; j++) { - coords[0] = i; - coords[1] = j; - - long sumRow = this.getCellTable().calcMargin(coords, secondVar); - long sumCol = this.getCellTable().calcMargin(coords, firstVar); - long observed = (int) this.getCellTable().getValue(coords); - - boolean skip = false; - -// if (sumRow == 0) { -// attestedRows[i] = false; -// skip = true; -// } -// -// if (sumCol == 0) { -// attestedCols[j] = false; -// skip = true; -// } - - if (skip) { - continue; - } - - e.add((double) sumCol * sumRow); - o.add(observed); - } - } - - for (int i = 0; i < o.size(); i++) { - double expected = e.get(i) / (double) total; - - if (o.get(i) != 0) { - _gSquare += 2.0 * o.get(i) * FastMath.log(o.get(i) / expected); - } - } - - if (total == 0) { - continue; - } - - int numAttestedRows = 0; - int numAttestedCols = 0; - - for (boolean attestedRow : attestedRows) { - if (attestedRow) { - numAttestedRows++; - } - } - - for (boolean attestedCol : attestedCols) { - if (attestedCol) { - numAttestedCols++; - } - } - - int _df = (numAttestedRows - 1) * (numAttestedCols - 1); - - if (_df > 0) { - df += _df; - g2 += _gSquare; - } - } - - // If df == 0, return indep. - if (df == 0) { - df = 1; - } - - double pValue = 1.0 - ProbUtils.chisqCdf(g2, df); - boolean indep = (pValue > getAlpha()); - return new Result(g2, pValue, df, indep); - } - - /** - * Returns the dimensions of the variables, in order. - * - * @return These dimensions, as an int[] array. For instance, if the array is [2 3], then the first variable has 2 - * categories and second variable has 3 categories. - */ - public int[] getDims() { - return this.dims; - } - - /** - * Returns the cell table for this test. - * - * @return This table. - * @see CellTable - */ - public CellTable getCellTable() { - return this.cellTable; - } - - /** - * @return the getModel significance level being used for tests. - */ - public double getAlpha() { - return this.alpha; - } - - /** - * Sets the significance level to be used for tests. - * - * @param alpha The alpha significance level of the test. - */ - public void setAlpha(double alpha) { - if (alpha < 0.0 || alpha > 1.0) { - throw new IllegalArgumentException("Significance level must be in " + - "[0, 1]: " + alpha); - } - - this.alpha = alpha; - } - - /** - * Returns the dataset used for this test. - * - * @return This dataset. - */ - public DataSet getDataSet() { - return this.dataSet; - } - - /** - * Returns a judgement of whether the variables index by 'testIndices' determine the variable index by 'p'. - * - * @param testIndices The indices of the conditioning variables. - * @param p The index of the child variable. - * @return True if the conditioning variables determine the child variable. - */ - public boolean isDetermined(int[] testIndices, double p) { - - // Reset the cell table for the columns referred to in - // 'testIndices.' Do cell coefs for those columns. - this.getCellTable().addToTable(getDataSet(), testIndices); - - // Indicator arrays to tell the cell table which margins - // to calculate. For x _||_ y | z1, z2, ..., we want to - // calculate the margin for x, the margin for y, and the - // margin for x and y. (These will be used later.) - int[] firstVar = {0}; - - int[] condDims = new int[testIndices.length - 1]; - System.arraycopy(selectFromArray(getDims(), testIndices), 1, condDims, 0, - condDims.length); - - int[] coords = new int[testIndices.length]; - int numValues = this.getCellTable().getNumValues(0); - - CombinationIterator combinationIterator = - new CombinationIterator(condDims); - - while (combinationIterator.hasNext()) { - int[] combination = combinationIterator.next(); - System.arraycopy(combination, 0, coords, 1, combination.length); - - long total = this.getCellTable().calcMargin(coords, firstVar); - - if (total == 0) { - continue; - } - - boolean dominates = false; - - for (int i = 0; i < numValues; i++) { - coords[0] = i; - - long numi = this.getCellTable().getValue(coords); - - if ((double) numi / total >= p) { - dominates = true; - } - } - - if (!dominates) { - return false; - } - } - - return true; - } - - private int[] selectFromArray(int[] arr, int[] indices) { - int[] retArr = new int[indices.length]; - - for (int i = 0; i < indices.length; i++) { - retArr[i] = arr[indices[i]]; - } - - return retArr; - } - - /** - * Stores the parameters of the result returned by the G Square test and its p-value. - * - * @author Frank Wimberly - */ - public static final class Result { - - /** - * The g square value itself. - */ - private final double gSquare; - - /** - * The pValue of the result. - */ - private final double pValue; - - /** - * The adjusted degrees of freedom. - */ - private final int df; - - /** - * Whether the conditional independence holds or not. (True if it does, false if it doesn't. - */ - private final boolean isIndep; - - /** - * Constructs a new g square result using the given parameters. - */ - public Result(double gSquare, double pValue, int df, boolean isIndep) { - this.gSquare = gSquare; - this.pValue = pValue; - this.df = df; - this.isIndep = isIndep; - } - - public double getGSquare() { - return this.gSquare; - } - - public double getPValue() { - return this.pValue; - } - - public int getDf() { - return this.df; - } - - public boolean isIndep() { - return this.isIndep; - } - } -} - - - - - diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestChiSquare.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestChiSquare.java index 166e35ae7b..be0a47651a 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestChiSquare.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestChiSquare.java @@ -100,7 +100,7 @@ public IndTestChiSquare(DataSet dataSet, double alpha) { this.dataSet = dataSet; this.variables = new ArrayList<>(dataSet.getVariables()); - this.chiSquareTest = new ChiSquareTest(dataSet, alpha); + this.chiSquareTest = new ChiSquareTest(dataSet, alpha, ChiSquareTest.TestType.CHI_SQUARE); this.chiSquareTest.setMinCountFraction(minCountFraction); } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestGSquare.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestGSquare.java index f0c3a0c106..2ea9d5b35e 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestGSquare.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestGSquare.java @@ -42,7 +42,7 @@ * equivalent to the formulation on page 142 of Fienberg. * * @author josephramsey - * @see GSquareTest + * @see ChiSquareTest */ public final class IndTestGSquare implements IndependenceTest { @@ -53,7 +53,7 @@ public final class IndTestGSquare implements IndependenceTest { /** * The G Square tester. */ - private final GSquareTest gSquareTest; + private final ChiSquareTest gSquareTest; /** * The variables in the discrete data sets or which conditional independence judgements are desired. */ @@ -101,7 +101,7 @@ public IndTestGSquare(DataSet dataSet, double alpha) { this.alpha = alpha; this.variables = new ArrayList<>(dataSet.getVariables()); - this.gSquareTest = new GSquareTest(dataSet, alpha); + this.gSquareTest = new ChiSquareTest(dataSet, alpha, ChiSquareTest.TestType.G_SQUARE); } /** @@ -187,16 +187,9 @@ public IndependenceResult checkIndependence(Node x, Node y, Set _z) { } } - // System.out.println("Testing " + x + " _||_ " + y + " | " + z); - - GSquareTest.Result result = this.gSquareTest.calcGSquare(testIndices); + ChiSquareTest.Result result = this.gSquareTest.calcChiSquare(testIndices); this.pValue = result.getPValue(); -// if (Double.isNaN(this.pValue)) { -// throw new RuntimeException("Undefined p-value encountered when testing " + -// LogUtilsSearch.independenceFact(x, y, _z)); -// } - if (this.verbose) { if (result.isIndep()) { TetradLogger.getInstance().forceLogMessage( From 900d9e4660e3b35f1e04c16be4ef91310fb89535 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Thu, 4 Jan 2024 07:46:23 -0500 Subject: [PATCH 033/163] Fixed some inefficiencies in chi square test. --- .../algcomparison/independence/Gsquare.java | 5 +- .../java/edu/cmu/tetrad/data/CellTable.java | 24 ++-- .../cmu/tetrad/search/test/ChiSquareTest.java | 107 +++++++++++++----- .../tetrad/search/test/IndTestChiSquare.java | 45 +++++--- .../tetrad/search/test/IndTestGSquare.java | 48 +++++++- 5 files changed, 175 insertions(+), 54 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/Gsquare.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/Gsquare.java index e1574d1c92..059d23036a 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/Gsquare.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/Gsquare.java @@ -28,7 +28,9 @@ public class Gsquare implements IndependenceWrapper { @Override public IndependenceTest getTest(DataModel dataSet, Parameters parameters) { - return new IndTestGSquare(SimpleDataLoader.getDiscreteDataSet(dataSet), parameters.getDouble("alpha")); + IndTestGSquare test = new IndTestGSquare(SimpleDataLoader.getDiscreteDataSet(dataSet), parameters.getDouble("test")); + test.setMinCountFraction(parameters.getInt(Params.MIN_COUNT_FRACTION)); + return test; } @Override @@ -45,6 +47,7 @@ public DataType getDataType() { public List getParameters() { List params = new ArrayList<>(); params.add(Params.ALPHA); + params.add(Params.MIN_COUNT_FRACTION); return params; } } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/data/CellTable.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/data/CellTable.java index b4321f8257..472e204ad3 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/data/CellTable.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/data/CellTable.java @@ -61,15 +61,15 @@ public void addToTable(DataSet dataSet, int[] indices) { } } else { for (int i = 0; i < rows.size(); i++) { - if (rows.get(i) >= dataSet.getNumRows()) throw new IllegalArgumentException("Row " + i + " is too large."); + if (rows.get(i) >= dataSet.getNumRows()) + throw new IllegalArgumentException("Row " + i + " is too large."); } } int[] dims = new int[indices.length]; for (int i = 0; i < indices.length; i++) { - DiscreteVariable variable = - (DiscreteVariable) dataSet.getVariable(indices[i]); + DiscreteVariable variable = (DiscreteVariable) dataSet.getVariable(indices[i]); dims[i] = variable.getNumCategories(); } @@ -136,8 +136,8 @@ public long calcMargin(int[] coords) { /** * An alternative way to specify a marginal calculation. In this case, coords specifies a particular cell in the * table, and varIndices is an array containing the indices of the variables over which the margin sum should be - * calculated. The sum is over the cell specified by 'coord' and all the cells which differ from that cell in any - * of the specified coordinates. + * calculated. The sum is over the cell specified by 'coord' and all the cells which differ from that cell in any of + * the specified coordinates. * * @param coords an int[] value * @param marginVars an int[] value @@ -173,12 +173,16 @@ public long getValue(int[] testCell) { } public void setRows(List rows) { - if (rows == null) throw new NullPointerException("Rows is null."); - for (int i = 0; i < rows.size(); i++) { - if (rows.get(i) == null) throw new NullPointerException("Row " + i + " is null."); - if (rows.get(i) < 0) throw new IllegalArgumentException("Row " + i + " is negative."); + if (rows == null) { + this.rows = null; + } else { + for (int i = 0; i < rows.size(); i++) { + if (rows.get(i) == null) throw new NullPointerException("Row " + i + " is null."); + if (rows.get(i) < 0) throw new IllegalArgumentException("Row " + i + " is negative."); + } + + this.rows = rows; } - this.rows = rows; } } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java index d410c90b71..c5cf5420e8 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java @@ -25,9 +25,13 @@ import edu.cmu.tetrad.data.DataSet; import edu.cmu.tetrad.data.DiscreteVariable; import edu.cmu.tetrad.util.CombinationIterator; +import edu.cmu.tetrad.util.Matrix; import org.apache.commons.math3.distribution.ChiSquaredDistribution; import org.apache.commons.math3.util.FastMath; +import java.util.List; + +import static org.apache.commons.math3.util.FastMath.log; import static org.apache.commons.math3.util.FastMath.pow; /** @@ -39,26 +43,18 @@ * @author josephramsey */ public class ChiSquareTest { - public enum TestType { - CHI_SQUARE, - G_SQUARE - } - - // The type of test to perform. - private TestType testType = TestType.CHI_SQUARE; - // The data set this test uses. private final DataSet dataSet; - // The number of values for each variable in the data. private final int[] dims; - // Stores the data in the form of a cell table. private final CellTable cellTable; - + // The type of test to perform. + private TestType testType = TestType.CHI_SQUARE; // The significance level of the test. private double alpha; - + // The rows used in the data. + private List rows = null; /** * The minimum number of counts per conditional table for chi-square expressed as a multiple of the total number of * cells in the table. Note that this should not be too small, or the chi-square distribution will not be a good @@ -66,7 +62,6 @@ public enum TestType { */ private double minCountFraction = 2.0; - /** * Constructs a test using the given data set and significance level. * @@ -138,28 +133,71 @@ public Result calcChiSquare(int[] testIndices) { System.arraycopy(combination, 0, coords, 2, combination.length); + boolean[] zeroRows = new boolean[numRows]; + boolean[] zeroCols = new boolean[numCols]; + double[] sumRows = new double[numRows]; + double[] sumCols = new double[numCols]; + + for (int i = 0; i < numRows; i++) { + coords[0] = i; + + sumRows[i] = getCellTable().calcMargin(coords, secondVar); + + if (sumRows[i] == 0) { + zeroRows[i] = true; + } + } + + for (int j = 0; j < numCols; j++) { + coords[1] = j; + + sumCols[j] = getCellTable().calcMargin(coords, firstVar); + + if (sumCols[j] == 0) { + zeroCols[j] = true; + } + } + + double total = getCellTable().calcMargin(coords, bothVars); + + // Count non-zero rows and columns + int numNonZeroRows = 0; + int numNonZeroCols = 0; + + for (int i = 0; i < numRows; i++) { + if (!zeroRows[i]) { + numNonZeroRows++; + } + } + + for (int j = 0; j < numCols; j++) { + if (!zeroCols[j]) { + numNonZeroCols++; + } + } + double _xSquare = 0.0; int zeros = 0; - for (int i = 0; i < numRows; i++) { - for (int j = 0; j < numCols; j++) { - coords[0] = i; - coords[1] = j; + if (total < minCountFraction * (numNonZeroRows * numNonZeroCols)) { + zeros += numNonZeroRows * numNonZeroCols; + } else { + for (int i = 0; i < numRows; i++) { + for (int j = 0; j < numCols; j++) { + if (sumRows[i] == 0 || sumCols[j] == 0) continue; - double sumRow = getCellTable().calcMargin(coords, firstVar); - double sumCol = getCellTable().calcMargin(coords, secondVar); - double observed = getCellTable().getValue(coords); - double total = getCellTable().calcMargin(coords, bothVars); + coords[0] = i; + coords[1] = j; - if (total >= minCountFraction * (numRows * numCols)) { - double expected = (sumRow * sumCol) / (total); + double observed = getCellTable().getValue(coords); + double expected = (sumRows[i] * sumCols[j]) / (total); if (expected > 0) { if (testType == TestType.CHI_SQUARE) { _xSquare += pow(observed - expected, 2.0) / expected; } else if (testType == TestType.G_SQUARE) { if (observed > 0) { - _xSquare += 2.0 * observed * FastMath.log(observed / expected); + _xSquare += 2.0 * observed * log(observed / expected); } else { zeros++; } @@ -169,13 +207,11 @@ public Result calcChiSquare(int[] testIndices) { } else { zeros++; } - } else { - zeros += numRows * numCols; } } } - int _df = (numRows - 1) * (numCols - 1) - zeros; + int _df = (numNonZeroRows - 1) * (numNonZeroCols - 1) - zeros; // There were free degrees of freedom in the table, so we count this chi-square and df. if (_df > 0) { @@ -186,10 +222,10 @@ public Result calcChiSquare(int[] testIndices) { // None of the conditional tables had enough counts to be included in the overall chi-square. if (df == 0) { - return new Result(xSquare, Double.NaN, df, true); + return new Result(xSquare, Double.NaN, df, false); } - // Cannot be NaN. + // Cannot be NaN at this point. double pValue = 1.0 - new ChiSquaredDistribution(df).cumulativeProbability(xSquare); // The Chi-Square distribution doesn't go out this far numerically, so this value can't be trusted. @@ -283,6 +319,15 @@ public void setAlpha(double alpha) { this.alpha = alpha; } + /** + * Sets the rows to use in the data. + * + * @param rows The rows to use. + */ + public void setRows(List rows) { + this.cellTable.setRows(rows); + this.rows = rows; + } private int[] selectFromArray(int[] arr, int[] indices) { int[] retArr = new int[indices.length]; @@ -317,6 +362,10 @@ public void setMinCountFraction(double minCountFraction) { this.minCountFraction = minCountFraction; } + public enum TestType { + CHI_SQUARE, + G_SQUARE + } /** * Simple class to store the parameters of the result returned by the G Square test. diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestChiSquare.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestChiSquare.java index be0a47651a..d099ab78c1 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestChiSquare.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestChiSquare.java @@ -44,7 +44,7 @@ * @author josephramsey * @see ChiSquareTest */ -public final class IndTestChiSquare implements IndependenceTest { +public final class IndTestChiSquare implements IndependenceTest, RowsSettable { /** * The Chi Square tester. @@ -76,6 +76,7 @@ public final class IndTestChiSquare implements IndependenceTest { private int minCountFraction = 20; private boolean verbose; + private List rows = null; /** * Constructs a new independence checker to check conditional independence facts for discrete data using a g square @@ -346,18 +347,6 @@ private double getDeterminationP() { return 0.99; } - /** - * The minimum number of counts per conditional table for chi-square expressed as a fraction of the total number of - * cells in the conditional table. Default is 2. Note that this should not be too small, or the chi-square - * distribution will not be a good approximation to the distribution of the test statistic. - * - * @return The minimum number of counts per conditional table expressed as a fraction of the total number of cells - * in the conditional table. - */ - public int getMinCountFraction() { - return minCountFraction; - } - /** * The minimum number of counts per conditional table for chi-square expressed as a fraction of the total number of * cells in the conditional table. Default is 2. Note that this should not be too small, or the chi-square @@ -370,6 +359,36 @@ public void setMinCountFraction(int minCountFraction) { this.minCountFraction = minCountFraction; this.chiSquareTest.setMinCountFraction(minCountFraction); } + + /** + * Returns the rows used for the test. If null, all rows are used. + * @return The rows used for the test. Can be null. + */ + @Override + public List getRows() { + return new ArrayList<>(rows); + } + + /** + * Sets the rows to use for the test. If null, all rows are used. + * @param rows The rows to use for the test. Can be null. + */ + @Override + public void setRows(List rows) { + if (rows == null) { + this.rows = null; + chiSquareTest.setRows(null); + } else { + for (int i : rows) { + if (i < 0 || i >= dataSet.getNumRows()) { + throw new IllegalArgumentException("Row " + i + " is out of bounds."); + } + } + + this.rows = new ArrayList<>(rows); + chiSquareTest.setRows(this.rows); + } + } } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestGSquare.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestGSquare.java index 2ea9d5b35e..c7b8f0c24e 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestGSquare.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestGSquare.java @@ -44,7 +44,7 @@ * @author josephramsey * @see ChiSquareTest */ -public final class IndTestGSquare implements IndependenceTest { +public final class IndTestGSquare implements IndependenceTest, RowsSettable { /** * The standard number formatter for Tetrad. @@ -76,6 +76,8 @@ public final class IndTestGSquare implements IndependenceTest { */ private double determinationP = 0.99; private boolean verbose; + private int minCountFraction; + private List rows = null; /** * Constructs a new independence checker to check conditional independence facts for discrete data using a g square @@ -102,6 +104,7 @@ public IndTestGSquare(DataSet dataSet, double alpha) { this.variables = new ArrayList<>(dataSet.getVariables()); this.gSquareTest = new ChiSquareTest(dataSet, alpha, ChiSquareTest.TestType.G_SQUARE); + this.gSquareTest.setMinCountFraction(minCountFraction); } /** @@ -340,6 +343,49 @@ public boolean isVerbose() { public void setVerbose(boolean verbose) { this.verbose = verbose; } + + /** + * The minimum number of counts per conditional table for chi-square expressed as a fraction of the total number of + * cells in the conditional table. Default is 2. Note that this should not be too small, or the chi-square + * distribution will not be a good approximation to the distribution of the test statistic. + * + * @param minCountFraction The minimum number of counts per conditional table expressed as a fraction of the total + * number of cells in the conditional table. + */ + public void setMinCountFraction(int minCountFraction) { + this.minCountFraction = minCountFraction; + this.gSquareTest.setMinCountFraction(minCountFraction); + } + + /** + * Returns the rows used for the test. If null, all rows are used. + * @return The rows used for the test. Can be null. + */ + @Override + public List getRows() { + return new ArrayList<>(rows); + } + + /** + * Sets the rows to use for the test. If null, all rows are used. + * @param rows The rows to use for the test. Can be null. + */ + @Override + public void setRows(List rows) { + if (rows == null) { + this.rows = null; + gSquareTest.setRows(null); + } else { + for (int i : rows) { + if (i < 0 || i >= dataSet.getNumRows()) { + throw new IllegalArgumentException("Row " + i + " is out of bounds."); + } + } + + this.rows = new ArrayList<>(rows); + gSquareTest.setRows(this.rows); + } + } } From f881cf4745d601a245adad40a46e87df97b1769d Mon Sep 17 00:00:00 2001 From: jdramsey Date: Thu, 4 Jan 2024 09:31:04 -0500 Subject: [PATCH 034/163] Fixed some inefficiencies in chi square test. --- .../cmu/tetrad/search/test/ChiSquareTest.java | 26 +++++++++---------- .../src/main/resources/docs/manual/index.html | 10 +++---- 2 files changed, 17 insertions(+), 19 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java index c5cf5420e8..fb940b60e4 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java @@ -125,6 +125,7 @@ public Result calcChiSquare(int[] testIndices) { int numCols = this.getCellTable().getNumValues(1); CombinationIterator combinationIterator = new CombinationIterator(condDims); + boolean allRepresented = true; // Make a chi square table for each condition combination, strike zero rows and columns and calculate // chi square and degrees of freedom for the remaining rows and columns in the table. See Friedman. @@ -176,11 +177,14 @@ public Result calcChiSquare(int[] testIndices) { } } - double _xSquare = 0.0; + // Sum up chi square and degrees of freedom for the conditional table. Keep track of zeroes in the table + // and substract them from the degrees of freedom. If there are no free degrees of freedom, don't increment + // the chi square or degrees of freedom. int zeros = 0; + double _xSquare = 0.0; - if (total < minCountFraction * (numNonZeroRows * numNonZeroCols)) { - zeros += numNonZeroRows * numNonZeroCols; + if (total < minCountFraction * numNonZeroRows * numNonZeroCols) { + zeros += (numNonZeroRows - 1) * (numNonZeroCols - 1); } else { for (int i = 0; i < numRows; i++) { for (int j = 0; j < numCols; j++) { @@ -217,22 +221,16 @@ public Result calcChiSquare(int[] testIndices) { if (_df > 0) { df += _df; xSquare += _xSquare; - } - } + } else { - // None of the conditional tables had enough counts to be included in the overall chi-square. - if (df == 0) { - return new Result(xSquare, Double.NaN, df, false); + // Not all conditional tables were represented, so we can't trust this result. + return new Result(Double.NaN, Double.NaN, -1, false); + } } - // Cannot be NaN at this point. + // At this point in the code, the p-value cannot be NaN. double pValue = 1.0 - new ChiSquaredDistribution(df).cumulativeProbability(xSquare); - // The Chi-Square distribution doesn't go out this far numerically, so this value can't be trusted. - if (pValue == 1.0) { - return new Result(xSquare, Double.NaN, df, false); - } - boolean indep = (pValue > getAlpha()); return new Result(xSquare, pValue, df, indep); } diff --git a/tetrad-lib/src/main/resources/docs/manual/index.html b/tetrad-lib/src/main/resources/docs/manual/index.html index 8aa04e1835..cd7397ba58 100755 --- a/tetrad-lib/src/main/resources/docs/manual/index.html +++ b/tetrad-lib/src/main/resources/docs/manual/index.html @@ -6487,14 +6487,14 @@

    kciEpsilon

    • Short Description: - Minimum fraction of number of cells in a conditional table.
    • + Minimum fraction of number of cells in a conditional table. +
    • Long Description: The minimum number of counts per conditional table for chi-square expressed as - a fraction of the total number of cells in the conditional table. Default is 2. - Note that this should not be too small, or the chi-square distribution will not - be a good approximation to the distribution of the test statistic
    • + a fraction of the total number of cells in the conditional table. Default is 0. +
    • Default Value: 2.0
    • + id="minCountFraction_default_value">0.0
    • Lower Bound: 0.0
    • Upper Bound: Date: Thu, 4 Jan 2024 09:31:35 -0500 Subject: [PATCH 035/163] Fixed some inefficiencies in chi square test. --- .../src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java index fb940b60e4..9bccbcc079 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java @@ -178,7 +178,7 @@ public Result calcChiSquare(int[] testIndices) { } // Sum up chi square and degrees of freedom for the conditional table. Keep track of zeroes in the table - // and substract them from the degrees of freedom. If there are no free degrees of freedom, don't increment + // and subtract them from the degrees of freedom. If there are no free degrees of freedom, don't increment // the chi square or degrees of freedom. int zeros = 0; double _xSquare = 0.0; From 073fc814fc79d981a737ad47264d96bf3f7ed6a4 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Thu, 4 Jan 2024 09:32:02 -0500 Subject: [PATCH 036/163] Fixed some inefficiencies in chi square test. --- .../main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java index 9bccbcc079..88a36aaf46 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java @@ -217,8 +217,9 @@ public Result calcChiSquare(int[] testIndices) { int _df = (numNonZeroRows - 1) * (numNonZeroCols - 1) - zeros; - // There were free degrees of freedom in the table, so we count this chi-square and df. if (_df > 0) { + + // There were free degrees of freedom in the table, so we count this chi-square and df. df += _df; xSquare += _xSquare; } else { From 1f273c72ffa3082ec29ecf7381c9f9da60484cf9 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Thu, 4 Jan 2024 09:49:07 -0500 Subject: [PATCH 037/163] Adding isValid parameter to independence results, in case an algorithm wants to use this information. A result is invalid if the test cannot determine whether the result is 'dependent' or 'independent'. --- .../cmu/tetrad/search/test/ChiSquareTest.java | 69 ++++++++++++++----- .../search/test/IndependenceResult.java | 42 ++++++++++- 2 files changed, 90 insertions(+), 21 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java index 88a36aaf46..f5f24ae790 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java @@ -25,9 +25,7 @@ import edu.cmu.tetrad.data.DataSet; import edu.cmu.tetrad.data.DiscreteVariable; import edu.cmu.tetrad.util.CombinationIterator; -import edu.cmu.tetrad.util.Matrix; import org.apache.commons.math3.distribution.ChiSquaredDistribution; -import org.apache.commons.math3.util.FastMath; import java.util.List; @@ -225,7 +223,7 @@ public Result calcChiSquare(int[] testIndices) { } else { // Not all conditional tables were represented, so we can't trust this result. - return new Result(Double.NaN, Double.NaN, -1, false); + return new Result(Double.NaN, Double.NaN, -1, false, false); } } @@ -372,52 +370,87 @@ public enum TestType { * @author Frank Wimberly */ public static class Result { - - /** - * The chi square value. - */ private final double chiSquare; - - /** - * The pValue of the result. - */ private final double pValue; - - /** - * The adjusted degrees of freedom. - */ private final int df; + private final boolean isIndep; + private final boolean isValid; /** - * Whether the conditional independence holds or not. (True if it does, false if it doesn't.) + * Constructs a new g square result using the given parameters. + * + * @param chiSquare The chi square value. + * @param pValue The pValue of the result. + * @param df The adjusted degrees of freedom. + * @param isIndep Whether the conditional independence holds or not. (True if it does, false if it doesn't.) */ - private final boolean isIndep; + public Result(double chiSquare, double pValue, int df, boolean isIndep) { + this(chiSquare, pValue, df, isIndep, true); + } /** * Constructs a new g square result using the given parameters. + * + * @param chiSquare The chi square value. + * @param pValue The pValue of the result. + * @param df The adjusted degrees of freedom. + * @param isIndep Whether the conditional independence holds or not. (True if it does, false if it doesn't.) + * @param isValid Whether the result is isValid or not. */ - public Result(double chiSquare, double pValue, int df, boolean isIndep) { + public Result(double chiSquare, double pValue, int df, boolean isIndep, boolean isValid) { this.chiSquare = chiSquare; this.pValue = pValue; this.df = df; this.isIndep = isIndep; + this.isValid = isValid; } + /** + * Returns the chi square value, or NaN if the chi square value cannot be determined. + * + * @return the chi square value. + */ public double getXSquare() { return this.chiSquare; } + /** + * Returns the pValue of the result, or NaN if the p-value cannot be determined. + * + * @return the pValue of the result. + */ public double getPValue() { return this.pValue; } + /** + * Returns the adjusted degrees of freedom, or -1 if the degrees of freedom cannot be determined. + * + * @return the adjusted degrees of freedom. + */ public int getDf() { return this.df; } + /** + * Returns whether the conditional independence holds or not. (True if it does, false if it doesn't.) For + * invalid results, this method returns a value set by the test. + * + * @return whether the conditional independence holds or not. + */ public boolean isIndep() { return this.isIndep; } + + /** + * Returns whether the result is valid or not. A result is valid if its judgment of independence is not + * indeterminate. + * + * @return whether the result is valid or not. + */ + public boolean isValid() { + return isValid; + } } } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndependenceResult.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndependenceResult.java index 8e1740369f..09a7448ea2 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndependenceResult.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndependenceResult.java @@ -7,8 +7,8 @@ import edu.cmu.tetrad.util.TetradSerializableUtils; /** - *

      Stores a single conditional independence result, e.g., whether - * X _||_ Y | Z1,..,Zn holds or does not, and the p-value of the test.

      + * Stores a single conditional independence result, e.g., whether X _||_ Y | Z1,..,Zn holds or does not, and the p-value + * of the test. * * @author josephramsey */ @@ -19,20 +19,40 @@ public final class IndependenceResult implements TetradSerializable { private final boolean indep; private final double pValue; private final double score; + private final boolean isValid; /** - * Constructor. + * Constructor. For this constructor, is it assumed that the test is valid. * * @param fact The fact itself. * @param indep The conditional independence result, true if the fact holds, false if not. * @param pValue The p-values of the independence result, under the null (independence) hypothesis. + * @param score The score of the test, which is alpha - p if the test returns a p-value or else a bump if the test + * is based on a score. * @see IndependenceFact */ public IndependenceResult(IndependenceFact fact, boolean indep, double pValue, double score) { + this(fact, indep, pValue, score, true); + } + + /** + * Constructor. For this constructor, the validity of the test is specified. + * + * @param fact The fact itself. + * @param indep The conditional independence result, true if the fact holds, false if not. + * @param pValue The p-values of the independence result, under the null (independence) hypothesis. + * @param score The score of the test, which is alpha - p if the test returns a p-value or else a bump if the test + * is based on a score. + * @param isValid Whether the result is valid or not. A test is not valid if the test is not able to determine + * whether the fact holds or not. + * @see IndependenceFact + */ + public IndependenceResult(IndependenceFact fact, boolean indep, double pValue, double score, boolean isValid) { this.fact = fact; this.indep = indep; this.pValue = pValue; this.score = score; + this.isValid = isValid; } /** @@ -98,7 +118,23 @@ public String toString() { NumberFormatUtil.getInstance().getNumberFormat().format(getPValue()); } + /** + * Returns the score of the test, which is alpha - p if the test returns a p-value or else a bump if the test is + * based on a score. + * + * @return The score of the test. + */ public double getScore() { return score; } + + /** + * Returns whether the result is valid or not. A test is not valid if the test is not able to determine whether the + * fact holds or not. + * + * @return True if the result is valid, false if not. + */ + public boolean isValid() { + return isValid; + } } From 24a5141770a43a2d35e2cba14225adb055b4e103 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Thu, 4 Jan 2024 09:56:16 -0500 Subject: [PATCH 038/163] Adding isValid parameter to independence results, in case an algorithm wants to use this information. A result is invalid if the test cannot determine whether the result is 'dependent' or 'independent'. --- .../java/edu/cmu/tetrad/search/test/IndependenceResult.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndependenceResult.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndependenceResult.java index 09a7448ea2..1ca866c5ce 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndependenceResult.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndependenceResult.java @@ -109,7 +109,7 @@ public double getPValue() { } /** - * Returns a string represnetation of this independence fact. + * Returns a string representation of this independence fact. * * @return This string. */ From bdd50fcc00a52a31523dc8ef2b1cfcb6fa8890fb Mon Sep 17 00:00:00 2001 From: jdramsey Date: Thu, 4 Jan 2024 09:59:08 -0500 Subject: [PATCH 039/163] Cleanup. --- .../java/edu/cmu/tetrad/search/test/ChiSquareTest.java | 7 ++----- .../java/edu/cmu/tetrad/search/test/IndTestGSquare.java | 6 +++--- .../src/main/java/edu/cmu/tetrad/util/dist/ChiSquare.java | 6 +++--- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java index f5f24ae790..57e38c9426 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java @@ -48,11 +48,9 @@ public class ChiSquareTest { // Stores the data in the form of a cell table. private final CellTable cellTable; // The type of test to perform. - private TestType testType = TestType.CHI_SQUARE; + private final TestType testType; // The significance level of the test. private double alpha; - // The rows used in the data. - private List rows = null; /** * The minimum number of counts per conditional table for chi-square expressed as a multiple of the total number of * cells in the table. Note that this should not be too small, or the chi-square distribution will not be a good @@ -123,7 +121,6 @@ public Result calcChiSquare(int[] testIndices) { int numCols = this.getCellTable().getNumValues(1); CombinationIterator combinationIterator = new CombinationIterator(condDims); - boolean allRepresented = true; // Make a chi square table for each condition combination, strike zero rows and columns and calculate // chi square and degrees of freedom for the remaining rows and columns in the table. See Friedman. @@ -323,7 +320,7 @@ public void setAlpha(double alpha) { */ public void setRows(List rows) { this.cellTable.setRows(rows); - this.rows = rows; + // The rows used in the data. } private int[] selectFromArray(int[] arr, int[] indices) { diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestGSquare.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestGSquare.java index c7b8f0c24e..e46b1d4ca7 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestGSquare.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestGSquare.java @@ -72,7 +72,7 @@ public final class IndTestGSquare implements IndependenceTest, RowsSettable { private double pValue; /** * The lower bound of percentages of observation of some category in the data, given some particular combination of - * values of conditioning variables, that coefs as 'determining." + * values of conditioning variables, that coefs as 'determining.' */ private double determinationP = 0.99; private boolean verbose; @@ -224,7 +224,7 @@ public void setAlpha(double alpha) { } /** - * Return the list of variables over which this independence checker is capable of determinine independence + * Return the list of variables over which this independence checker is capable of determining independence * relations-- that is, all the variables in the given graph or the given data set. * * @return This list. @@ -307,7 +307,7 @@ public boolean determines(Set _z, Node x) { } /** - * Sets the threshold for making judgments of detemrination. + * Sets the threshold for making judgments of determination. * * @param determinationP This threshold. */ diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/util/dist/ChiSquare.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/util/dist/ChiSquare.java index 2654893d12..095ec817fe 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/util/dist/ChiSquare.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/util/dist/ChiSquare.java @@ -36,10 +36,10 @@ public class ChiSquare implements Distribution { private static final long serialVersionUID = 23L; /** - * The stored degees of freedom. Needed because the wrapped distribution does not provide getters for its + * The stored degrees of freedom. Needed because the wrapped distribution does not provide getters for its * parameters. */ - private double df = 5.0; + private double df; /** * Constructs a new Chi Square distribution. @@ -104,7 +104,7 @@ public String toString() { * semantic checks can be specified and do not need to stay the same from version to version. A readObject method of * this form may be added to any class, even if Tetrad sessions were previously saved out using a version of the * class that didn't include it. (That's what the "s.defaultReadObject();" is for. See J. Bloch, Effective Java, for - * help. + * help.) * * @param s Ibid. * @throws java.io.IOException If the stream cannot be read. From f3b1f4a6b421bd187ec6fef613fe8aae85367bdd Mon Sep 17 00:00:00 2001 From: jdramsey Date: Thu, 4 Jan 2024 10:06:37 -0500 Subject: [PATCH 040/163] Cleanup. --- .../edu/cmu/tetrad/search/test/ChiSquareTest.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java index 57e38c9426..c0fca40ace 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java @@ -35,20 +35,30 @@ /** * Calculates chi-square for a conditional cross-tabulation table for independence question 0 _||_ 1 | 2, 3, ...max by * summing up chi-square and degrees of freedom for each conditional table in turn, where rows or columns that consist - * entirely of zeros have been removed. The conditional tables are restricted to have at least minCountPerTable counts. + * entirely of zeros have been removed. The adjusted conditional tables are required to have at least c * numNonZeroRows + * * numNonZeroCols counts, where c is a parameter. The default value of c is 0. If any conditional table has fewer than + * c * numNonZeroRows * numNonZeroCols counts or zero free degrees of freedom, the test is invalid. Otherwise, the test + * is valid and the chi-square and degrees of freedom are calculated by summing up the chi-square and degrees of freedom + * for each conditional table. The p-value is calculated from the chi-square and degrees of freedom using the + * chi-square distribution. * * @author frankwimberly * @author josephramsey */ public class ChiSquareTest { + // The data set this test uses. private final DataSet dataSet; + // The number of values for each variable in the data. private final int[] dims; + // Stores the data in the form of a cell table. private final CellTable cellTable; + // The type of test to perform. private final TestType testType; + // The significance level of the test. private double alpha; /** From 518601b3d5366c0fd36f88297157ab537bb77d44 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Thu, 4 Jan 2024 11:46:11 -0500 Subject: [PATCH 041/163] Cleanup. --- .../src/main/java/edu/cmu/tetrad/search/MarkovCheck.java | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java index 1bc16a9db7..a9efeadc13 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java @@ -516,9 +516,7 @@ public Pair, Set> call() { double pValue = result.getPValue(); independenceTest.setVerbose(verbose); - if (Double.isNaN(pValue)) { - System.out.println("Skipping " + fact + " because p-value is NaN."); - } else { + if (!Double.isNaN(pValue)) { if (msep) { resultsIndep.add(new IndependenceResult(fact, indep, pValue, Double.NaN)); } else { @@ -538,9 +536,7 @@ public Pair, Set> call() { double pValue = result.getPValue(); independenceTest.setVerbose(verbose); - if (Double.isNaN(pValue)) { - System.out.println("Skipping " + fact + " because p-value is NaN."); - } else { + if (!Double.isNaN(pValue)) { if (msep) { resultsIndep.add(new IndependenceResult(fact, indep, pValue, Double.NaN)); } else { From 7ec902232cc4545d0fdc9947e0e29f040dd9c22b Mon Sep 17 00:00:00 2001 From: jdramsey Date: Sat, 6 Jan 2024 02:38:04 -0500 Subject: [PATCH 042/163] Cleanup. --- .../main/java/edu/cmu/tetrad/search/utils/LogUtilsSearch.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/LogUtilsSearch.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/LogUtilsSearch.java index 99cb7f8889..6d1e6c4cc2 100755 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/LogUtilsSearch.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/LogUtilsSearch.java @@ -184,7 +184,7 @@ public static void stampWithScores(Graph graph, DataModel dataModel, Score score } public static void stampWithBic(Graph graph, DataModel dataModel) { - if (dataModel.isContinuous() && !graph.getAllAttributes().containsKey("BIC")) { + if (dataModel != null && dataModel.isContinuous() && !graph.getAllAttributes().containsKey("BIC")) { try { graph.addAttribute("BIC", new BicEst().getValue(null, graph, dataModel)); } catch (Exception e) { From 666325f9a0a98057dae295fa1abe80ddcf139ab3 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Sat, 6 Jan 2024 13:41:54 -0500 Subject: [PATCH 043/163] Cleanup. --- .../algcomparison/independence/{Gsquare.java => GSquare.java} | 2 +- .../examples/conditions/ExampleCompareSimulationDiscrete.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) rename tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/{Gsquare.java => GSquare.java} (96%) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/Gsquare.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/GSquare.java similarity index 96% rename from tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/Gsquare.java rename to tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/GSquare.java index 059d23036a..30ec6241ac 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/Gsquare.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/GSquare.java @@ -22,7 +22,7 @@ command = "g-square-test", dataType = DataType.Discrete ) -public class Gsquare implements IndependenceWrapper { +public class GSquare implements IndependenceWrapper { private static final long serialVersionUID = 23L; diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/study/examples/conditions/ExampleCompareSimulationDiscrete.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/study/examples/conditions/ExampleCompareSimulationDiscrete.java index 157dbf11ea..c0793409b6 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/study/examples/conditions/ExampleCompareSimulationDiscrete.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/study/examples/conditions/ExampleCompareSimulationDiscrete.java @@ -27,7 +27,7 @@ import edu.cmu.tetrad.algcomparison.algorithm.oracle.cpdag.Pc; import edu.cmu.tetrad.algcomparison.graph.RandomForward; import edu.cmu.tetrad.algcomparison.independence.ChiSquare; -import edu.cmu.tetrad.algcomparison.independence.Gsquare; +import edu.cmu.tetrad.algcomparison.independence.GSquare; import edu.cmu.tetrad.algcomparison.score.BdeuScore; import edu.cmu.tetrad.algcomparison.score.ConditionalGaussianBicScore; import edu.cmu.tetrad.algcomparison.score.DiscreteBicScore; @@ -88,7 +88,7 @@ public static void main(String... args) { Algorithms algorithms = new Algorithms(); algorithms.add(new Pc(new ChiSquare())); - algorithms.add(new Pc(new Gsquare())); + algorithms.add(new Pc(new GSquare())); // algorithms.add(new Fges(new BdeuScore())); algorithms.add(new Fges(new DiscreteBicScore())); From 190763b2977d289adcddf3136fed5dbc8b8bd887 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Sun, 7 Jan 2024 01:04:36 -0500 Subject: [PATCH 044/163] Switching to JDK 17 in the pom files. --- data-reader/pom.xml | 8 ++++---- tetrad-gui/pom.xml | 4 ++-- tetrad-lib/pom.xml | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/data-reader/pom.xml b/data-reader/pom.xml index 55a001ea55..696dd77b99 100644 --- a/data-reader/pom.xml +++ b/data-reader/pom.xml @@ -13,8 +13,8 @@ UTF-8 - 1.8 - 1.8 + 17 + 17 @@ -24,8 +24,8 @@ maven-compiler-plugin 3.11.0 - 1.8 - 1.8 + 17 + 17 diff --git a/tetrad-gui/pom.xml b/tetrad-gui/pom.xml index e2df09adae..f86e58b548 100644 --- a/tetrad-gui/pom.xml +++ b/tetrad-gui/pom.xml @@ -33,8 +33,8 @@ maven-compiler-plugin 3.11.0 - 1.8 - 1.8 + 17 + 17 diff --git a/tetrad-lib/pom.xml b/tetrad-lib/pom.xml index 164de63a93..4bad72a2bb 100644 --- a/tetrad-lib/pom.xml +++ b/tetrad-lib/pom.xml @@ -18,8 +18,8 @@ maven-compiler-plugin 3.11.0 - 1.8 - 1.8 + 17 + 17 From cbffcbde847a7499a1d918decbe9a4b43041434b Mon Sep 17 00:00:00 2001 From: jdramsey Date: Mon, 8 Jan 2024 15:57:29 -0500 Subject: [PATCH 045/163] Making fisher z row-settable. --- .../algcomparison/examples/TestBoss.java | 35 +++++++++++++ .../tetrad/search/test/IndTestFisherZ.java | 51 ++----------------- 2 files changed, 40 insertions(+), 46 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/examples/TestBoss.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/examples/TestBoss.java index 526ba12154..238428f396 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/examples/TestBoss.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/examples/TestBoss.java @@ -31,8 +31,12 @@ import edu.cmu.tetrad.algcomparison.simulation.SemSimulation; import edu.cmu.tetrad.algcomparison.simulation.Simulations; import edu.cmu.tetrad.algcomparison.statistic.*; +import edu.cmu.tetrad.util.MillisecondTimes; import edu.cmu.tetrad.util.Parameters; import edu.cmu.tetrad.util.Params; +import org.apache.commons.math3.linear.Array2DRowRealMatrix; +import org.apache.commons.math3.linear.BlockRealMatrix; +import org.apache.commons.math3.linear.RealMatrix; /** * Test the degenerate Gaussian score. @@ -41,6 +45,11 @@ */ public class TestBoss { public static void main(String... args) { + if (true) { + testGigaflops(); + return; + } + Parameters parameters = new Parameters(); parameters.set(Params.NUM_RUNS, 1); parameters.set(Params.DIFFERENT_GRAPHS, true); @@ -94,6 +103,32 @@ public static void main(String... args) { comparison.compareFromSimulations("comparison", simulations, algorithms, statistics, parameters); } + + public static void testGigaflops() { + + final long start = MillisecondTimes.timeMillis();// System.currentTimeMillis(); + + for (int i = 0; i < 200; i++) { + int N = 1024; + RealMatrix A = new BlockRealMatrix(N, N); + RealMatrix B = new BlockRealMatrix(N, N); + + MillisecondTimes.type = MillisecondTimes.Type.CPU; + + RealMatrix C = A.multiply(B); + final long end = MillisecondTimes.timeMillis();// System.currentTimeMillis(); + + double gflop = N * N * N * 2e-9; + double sec = (end - start) * 1e-3; + + System.out.println(gflop / sec); + } + + final long end = MillisecondTimes.timeMillis();// System.currentTimeMillis(); + + System.out.println((end - start) * 1e-3); + + } } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java index 48c72e6c22..3779fa0bad 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java @@ -49,20 +49,18 @@ * @author josephramsey * @author Frank Wimberly */ -public final class IndTestFisherZ implements IndependenceTest, RowsSettable { +public final class IndTestFisherZ implements IndependenceTest { private final Map indexMap; private final Map nameMap; private final NormalDistribution normal = new NormalDistribution(0, 1, 1e-15); private final Map nodesHash; - private final int sampleSize; private ICovarianceMatrix cor = null; private List variables; private double alpha; private DataSet dataSet; - private boolean verbose = false; + private boolean verbose = true; // private double p = Double.NaN; private double r = Double.NaN; - private List rows = null; /** @@ -73,7 +71,7 @@ public final class IndTestFisherZ implements IndependenceTest, RowsSettable { * @param alpha The alpha level of the test. */ public IndTestFisherZ(DataSet dataSet, double alpha) { - this.dataSet = dataSet.copy(); + this.dataSet = dataSet; if (!(dataSet.isContinuous())) { throw new IllegalArgumentException("Data set must be continuous."); @@ -115,8 +113,6 @@ public IndTestFisherZ(DataSet dataSet, double alpha) { this.nodesHash = nodesHash; } - - this.sampleSize = dataSet.getNumRows(); } /** @@ -141,8 +137,6 @@ public IndTestFisherZ(Matrix data, List variables, double alpha) { } this.nodesHash = nodesHash; - this.sampleSize = dataSet.getNumRows(); - } /** @@ -166,8 +160,6 @@ public IndTestFisherZ(ICovarianceMatrix covMatrix, double alpha) { } this.nodesHash = nodesHash; - this.sampleSize = cor.getSampleSize(); - } @@ -364,7 +356,7 @@ public List getDataSets() { */ @Override public int getSampleSize() { - return this.sampleSize(); + return this.cor.getSampleSize(); } /** @@ -477,7 +469,7 @@ private double getR(Node x, Node y, Set z, List rows) { } private int sampleSize() { - return sampleSize; + return covMatrix().getSampleSize(); } private ICovarianceMatrix covMatrix() { @@ -505,10 +497,6 @@ private Map indexMap(List variables) { } private List getRows(List allVars, Map nodesHash) { - if (rows != null) { - return rows; - } - List rows = new ArrayList<>(); K: @@ -522,35 +510,6 @@ private List getRows(List allVars, Map nodesHash) return rows; } - - /** - * Gets the rows to use for the test. These rows over override testwise deletion - * if set. - * @return The rows to use for the test. Can be null. - */ - public List getRows() { - return rows; - } - - /** - * Sets the rows to use for the test. This will override testwise deletion. - * @param rows The rows to use for the test. Can be null. - */ - public void setRows(List rows) { - if (rows != null) { - for (int i = 0; i < rows.size(); i++) { - if (rows.get(i) < 0 || rows.get(i) > sampleSize()) { - throw new IllegalArgumentException("Row index = " + i + "=" + rows.get(i) + " is out of bounds."); - } - } - - this.rows = rows; - this.cor = null; - } else { - this.cor = new CorrelationMatrix(dataSet); - this.rows = null; - } - } } From 91bb087b9e39645bc7128efab92fa8f6524d84bf Mon Sep 17 00:00:00 2001 From: jdramsey Date: Mon, 8 Jan 2024 15:59:29 -0500 Subject: [PATCH 046/163] Switching to JDK 17 in the pom files. --- .../src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java index c0fca40ace..a8192fb30a 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java @@ -189,7 +189,7 @@ public Result calcChiSquare(int[] testIndices) { double _xSquare = 0.0; if (total < minCountFraction * numNonZeroRows * numNonZeroCols) { - zeros += (numNonZeroRows - 1) * (numNonZeroCols - 1); + zeros += (numNonZeroRows) * (numNonZeroCols); } else { for (int i = 0; i < numRows; i++) { for (int j = 0; j < numCols; j++) { From ca8ab18d070941607226c51604c189fcb90aa7bc Mon Sep 17 00:00:00 2001 From: jdramsey Date: Mon, 8 Jan 2024 16:10:11 -0500 Subject: [PATCH 047/163] Making fisher z row-settable. --- .../tetrad/search/test/IndTestFisherZ.java | 35 ++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java index 3779fa0bad..c587a07326 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java @@ -25,6 +25,7 @@ import edu.cmu.tetrad.graph.IndependenceFact; import edu.cmu.tetrad.graph.Node; import edu.cmu.tetrad.search.IndependenceTest; +import edu.cmu.tetrad.search.utils.GraphSearchUtils; import edu.cmu.tetrad.search.utils.LogUtilsSearch; import edu.cmu.tetrad.util.Matrix; import edu.cmu.tetrad.util.MatrixUtils; @@ -49,7 +50,7 @@ * @author josephramsey * @author Frank Wimberly */ -public final class IndTestFisherZ implements IndependenceTest { +public final class IndTestFisherZ implements IndependenceTest, RowsSettable { private final Map indexMap; private final Map nameMap; private final NormalDistribution normal = new NormalDistribution(0, 1, 1e-15); @@ -61,6 +62,7 @@ public final class IndTestFisherZ implements IndependenceTest { private boolean verbose = true; // private double p = Double.NaN; private double r = Double.NaN; + private List rows = null; /** @@ -497,6 +499,10 @@ private Map indexMap(List variables) { } private List getRows(List allVars, Map nodesHash) { + if (this.rows != null) { + return this.rows; + } + List rows = new ArrayList<>(); K: @@ -510,6 +516,33 @@ private List getRows(List allVars, Map nodesHash) return rows; } + + /** + * Returns the rows used in the test. + * @return The rows used in the test. + */ + public List getRows() { + return rows; + } + + /** + * Allows the user to set which rows are used in the test. Otherwise, all rows are used, except + * those with missing values. + * @param rows The rows to use. + */ + public void setRows(List rows) { + if (dataSet == null) { + throw new IllegalStateException("Cannot set rows without a data set."); + } + + for (int i = 0; i < dataSet.getNumRows(); i++) { + if (rows.get(i) < 0 || rows.get(i) >= sampleSize()) { + throw new IllegalArgumentException("Row index out of bounds."); + } + } + + this.rows = rows; + } } From 7f28bdcd3c6bfe8daefde7c4818d6993fa14746b Mon Sep 17 00:00:00 2001 From: jdramsey Date: Tue, 9 Jan 2024 10:15:53 -0500 Subject: [PATCH 048/163] Changed the Causal Order layout to judge both --> and o-> as putting nodes in a subsequent tier. --- .../src/main/java/edu/cmu/tetrad/graph/LayoutUtil.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/graph/LayoutUtil.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/graph/LayoutUtil.java index dbb476ca16..8f07aa92bb 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/graph/LayoutUtil.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/graph/LayoutUtil.java @@ -182,7 +182,10 @@ private static List> getTiers(Graph graph) { List thisTier = new LinkedList<>(); for (Node node : notFound) { - if (found.containsAll(graph.getParents(node))) { + List nodesInTo = graph.getNodesInTo(node, Endpoint.ARROW); + nodesInTo.removeAll(graph.getNodesOutTo(node, Endpoint.ARROW)); + + if (found.containsAll(nodesInTo)) { thisTier.add(node); } } From a7c8811a298a208ac3902bb351f8dfb3b57d6c94 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Tue, 9 Jan 2024 17:49:35 -0500 Subject: [PATCH 049/163] Work on Chi Square test. Made a parameter to allow the user to specify the minimum row and cell counts for calculating chi-square and g-square. --- .../algcomparison/independence/ChiSquare.java | 4 +-- .../algcomparison/independence/GSquare.java | 4 +-- .../java/edu/cmu/tetrad/bayes/MlBayesIm.java | 20 +++++++++----- .../main/java/edu/cmu/tetrad/graph/Paths.java | 6 ++++- .../cmu/tetrad/search/test/ChiSquareTest.java | 26 +++++++++---------- .../tetrad/search/test/IndTestChiSquare.java | 12 ++++----- .../tetrad/search/test/IndTestGSquare.java | 12 ++++----- .../main/java/edu/cmu/tetrad/util/Params.java | 2 +- .../src/main/resources/docs/manual/index.html | 22 ++++++++-------- 9 files changed, 58 insertions(+), 50 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/ChiSquare.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/ChiSquare.java index f9fada3f20..d0d135e0ba 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/ChiSquare.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/ChiSquare.java @@ -29,7 +29,7 @@ public class ChiSquare implements IndependenceWrapper { @Override public IndependenceTest getTest(DataModel dataSet, Parameters parameters) { IndTestChiSquare test = new IndTestChiSquare(SimpleDataLoader.getDiscreteDataSet(dataSet), parameters.getDouble(Params.ALPHA)); - test.setMinCountFraction(parameters.getInt(Params.MIN_COUNT_FRACTION)); + test.setMinSumRowOrCol(parameters.getInt(Params.MIN_SUM_ROW_OR_COL)); return test; } @@ -47,7 +47,7 @@ public DataType getDataType() { public List getParameters() { List params = new ArrayList<>(); params.add(Params.ALPHA); - params.add(Params.MIN_COUNT_FRACTION); + params.add(Params.MIN_SUM_ROW_OR_COL); return params; } } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/GSquare.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/GSquare.java index 30ec6241ac..91bed10d2b 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/GSquare.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/GSquare.java @@ -29,7 +29,7 @@ public class GSquare implements IndependenceWrapper { @Override public IndependenceTest getTest(DataModel dataSet, Parameters parameters) { IndTestGSquare test = new IndTestGSquare(SimpleDataLoader.getDiscreteDataSet(dataSet), parameters.getDouble("test")); - test.setMinCountFraction(parameters.getInt(Params.MIN_COUNT_FRACTION)); + test.setMinSumRowOrCol(parameters.getInt(Params.MIN_SUM_ROW_OR_COL)); return test; } @@ -47,7 +47,7 @@ public DataType getDataType() { public List getParameters() { List params = new ArrayList<>(); params.add(Params.ALPHA); - params.add(Params.MIN_COUNT_FRACTION); + params.add(Params.MIN_SUM_ROW_OR_COL); return params; } } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/bayes/MlBayesIm.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/bayes/MlBayesIm.java index 4efb082c60..c79902586e 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/bayes/MlBayesIm.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/bayes/MlBayesIm.java @@ -32,10 +32,7 @@ import java.io.IOException; import java.io.ObjectInputStream; import java.text.NumberFormat; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.LinkedList; -import java.util.List; +import java.util.*; import static org.apache.commons.math3.util.FastMath.abs; import static org.apache.commons.math3.util.FastMath.pow; @@ -235,15 +232,24 @@ private static double[] getRandomWeights2(int size, double[] biases) { return row; } +// static int strong_ = 0; + + Random random = new Random(); + private static double[] getRandomWeights3(int size) { - assert size >= 0; + assert size > 0; double[] row = new double[size]; double sum = 0.0; for (int i = 0; i < size; i++) { - row[i] = RandomUtil.getInstance().nextUniform(0.05, 0.95); -// row[i] = RandomUtil.getInstance().nextBeta(size / 4d, size); + //noinspection StatementWithEmptyBody + for (int j = 0; j < RandomUtil.getInstance().nextInt(10); j++) { + // empty + } + + row[i] = pow(RandomUtil.getInstance().nextUniform(0.0, 1.0), 3); + sum += row[i]; } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/graph/Paths.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/graph/Paths.java index 1712e5b001..393dedc072 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/graph/Paths.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/graph/Paths.java @@ -4,6 +4,7 @@ import edu.cmu.tetrad.search.utils.SepsetMap; import edu.cmu.tetrad.util.SublistGenerator; import edu.cmu.tetrad.util.TaskManager; +import edu.cmu.tetrad.util.TetradLogger; import edu.cmu.tetrad.util.TetradSerializable; import java.util.*; @@ -1588,7 +1589,10 @@ private boolean visibleEdgeHelperVisit(Node c, Node a, Node b, LinkedList public boolean existsDirectedCycle() { for (Node node : graph.getNodes()) { - if (existsDirectedPathFromTo(node, node)) return true; + if (existsDirectedPathFromTo(node, node)) { + TetradLogger.getInstance().forceLogMessage("Cycle found at node " + node.getName() + "."); + return true; + } } return false; } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java index a8192fb30a..77b691087d 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java @@ -66,7 +66,7 @@ public class ChiSquareTest { * cells in the table. Note that this should not be too small, or the chi-square distribution will not be a good * approximation to the distribution of the test statistic. */ - private double minCountFraction = 2.0; + private int minSumRowOrCol = 0; /** * Constructs a test using the given data set and significance level. @@ -149,7 +149,7 @@ public Result calcChiSquare(int[] testIndices) { sumRows[i] = getCellTable().calcMargin(coords, secondVar); - if (sumRows[i] == 0) { + if (sumRows[i] < minSumRowOrCol) { zeroRows[i] = true; } } @@ -159,7 +159,7 @@ public Result calcChiSquare(int[] testIndices) { sumCols[j] = getCellTable().calcMargin(coords, firstVar); - if (sumCols[j] == 0) { + if (sumCols[j] < minSumRowOrCol) { zeroCols[j] = true; } } @@ -188,13 +188,11 @@ public Result calcChiSquare(int[] testIndices) { int zeros = 0; double _xSquare = 0.0; - if (total < minCountFraction * numNonZeroRows * numNonZeroCols) { - zeros += (numNonZeroRows) * (numNonZeroCols); + if (total == 0 || (numNonZeroRows < 2 && numNonZeroCols < 2)) { + continue; } else { for (int i = 0; i < numRows; i++) { for (int j = 0; j < numCols; j++) { - if (sumRows[i] == 0 || sumCols[j] == 0) continue; - coords[0] = i; coords[1] = j; @@ -227,13 +225,13 @@ public Result calcChiSquare(int[] testIndices) { // There were free degrees of freedom in the table, so we count this chi-square and df. df += _df; xSquare += _xSquare; - } else { - - // Not all conditional tables were represented, so we can't trust this result. - return new Result(Double.NaN, Double.NaN, -1, false, false); } } + if (df == 0) { + return new Result(Double.NaN, Double.NaN, -1, false, false); + } + // At this point in the code, the p-value cannot be NaN. double pValue = 1.0 - new ChiSquaredDistribution(df).cumulativeProbability(xSquare); @@ -360,10 +358,10 @@ private CellTable getCellTable() { * included in the overall chi-square and degrees of freedom. Note that this should not be too small, or the * chi-square distribution will not be a good approximation to the distribution of the test statistic. * - * @param minCountFraction The minimum number of counts per conditional table. + * @param minSumRowOrCol The minimum number of counts per conditional table. */ - public void setMinCountFraction(double minCountFraction) { - this.minCountFraction = minCountFraction; + public void setMinSumRowOrCol(int minSumRowOrCol) { + this.minSumRowOrCol = minSumRowOrCol; } public enum TestType { diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestChiSquare.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestChiSquare.java index d099ab78c1..c4e3beedb3 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestChiSquare.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestChiSquare.java @@ -73,7 +73,7 @@ public final class IndTestChiSquare implements IndependenceTest, RowsSettable { */ private int df; - private int minCountFraction = 20; + private int minSumRowOrCol = 0; private boolean verbose; private List rows = null; @@ -102,7 +102,7 @@ public IndTestChiSquare(DataSet dataSet, double alpha) { this.variables = new ArrayList<>(dataSet.getVariables()); this.chiSquareTest = new ChiSquareTest(dataSet, alpha, ChiSquareTest.TestType.CHI_SQUARE); - this.chiSquareTest.setMinCountFraction(minCountFraction); + this.chiSquareTest.setMinSumRowOrCol(minSumRowOrCol); } /** @@ -352,12 +352,12 @@ private double getDeterminationP() { * cells in the conditional table. Default is 2. Note that this should not be too small, or the chi-square * distribution will not be a good approximation to the distribution of the test statistic. * - * @param minCountFraction The minimum number of counts per conditional table expressed as a fraction of the total + * @param minSumRowOrCol The minimum number of counts per conditional table expressed as a fraction of the total * number of cells in the conditional table. */ - public void setMinCountFraction(int minCountFraction) { - this.minCountFraction = minCountFraction; - this.chiSquareTest.setMinCountFraction(minCountFraction); + public void setMinSumRowOrCol(int minSumRowOrCol) { + this.minSumRowOrCol = minSumRowOrCol; + this.chiSquareTest.setMinSumRowOrCol(minSumRowOrCol); } /** diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestGSquare.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestGSquare.java index e46b1d4ca7..0691b81d03 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestGSquare.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestGSquare.java @@ -76,7 +76,7 @@ public final class IndTestGSquare implements IndependenceTest, RowsSettable { */ private double determinationP = 0.99; private boolean verbose; - private int minCountFraction; + private int minSumRowOrCol; private List rows = null; /** @@ -104,7 +104,7 @@ public IndTestGSquare(DataSet dataSet, double alpha) { this.variables = new ArrayList<>(dataSet.getVariables()); this.gSquareTest = new ChiSquareTest(dataSet, alpha, ChiSquareTest.TestType.G_SQUARE); - this.gSquareTest.setMinCountFraction(minCountFraction); + this.gSquareTest.setMinSumRowOrCol(minSumRowOrCol); } /** @@ -349,12 +349,12 @@ public void setVerbose(boolean verbose) { * cells in the conditional table. Default is 2. Note that this should not be too small, or the chi-square * distribution will not be a good approximation to the distribution of the test statistic. * - * @param minCountFraction The minimum number of counts per conditional table expressed as a fraction of the total + * @param minSumRowOrCol The minimum number of counts per conditional table expressed as a fraction of the total * number of cells in the conditional table. */ - public void setMinCountFraction(int minCountFraction) { - this.minCountFraction = minCountFraction; - this.gSquareTest.setMinCountFraction(minCountFraction); + public void setMinSumRowOrCol(int minSumRowOrCol) { + this.minSumRowOrCol = minSumRowOrCol; + this.gSquareTest.setMinSumRowOrCol(minSumRowOrCol); } /** diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/util/Params.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/util/Params.java index ef40400f6a..e786c780b0 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/util/Params.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/util/Params.java @@ -254,7 +254,7 @@ public final class Params { public static final String REMOVE_EFFECT_NODES = "removeEffectNodes"; public static final String SAMPLE_STYLE = "sampleStyle"; public static final String NUM_THREADS = "numThreads"; - public static String MIN_COUNT_FRACTION = "minCountFraction"; + public static String MIN_SUM_ROW_OR_COL = "minSumRowOrCol"; // All parameters that are found in HTML manual documentation diff --git a/tetrad-lib/src/main/resources/docs/manual/index.html b/tetrad-lib/src/main/resources/docs/manual/index.html index cd7397ba58..adff18d813 100755 --- a/tetrad-lib/src/main/resources/docs/manual/index.html +++ b/tetrad-lib/src/main/resources/docs/manual/index.html @@ -6483,24 +6483,24 @@

      kciEpsilon

    minCountFraction

    + id="minSumRowOrCol">minSumRowOrCol
      -
    • Short Description: - Minimum fraction of number of cells in a conditional table. + class="minSumRowOrCol_list"> +
    • Short Description: + Minimum row or column sum in conditional tables.
    • -
    • Long Description: - The minimum number of counts per conditional table for chi-square expressed as - a fraction of the total number of cells in the conditional table. Default is 0. +
    • Long Description: + The minimum row or column sum for any conditional table, for any summand + used in the test. Default is zero.
    • Default Value: 0.0
    • + id="minSumRowOrCol_default_value">0
    • Lower - Bound: 0.0
    • + Bound: 0
    • Upper Bound: Infinity
    • + id="minSumRowOrCol_upper_bound">2147483647
    • Value Type: - Double
    • + Integer

    kernelType

    From 12df53298c47ac9f169d41f0dca7f46c05f28373 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Tue, 9 Jan 2024 17:49:57 -0500 Subject: [PATCH 050/163] Work on Chi Square test. Made a parameter to allow the user to specify the minimum row and cell counts for calculating chi-square and g-square. --- .../search/CompositeIndependenceTest.java | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 tetrad-lib/src/main/java/edu/cmu/tetrad/search/CompositeIndependenceTest.java diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/CompositeIndependenceTest.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/CompositeIndependenceTest.java new file mode 100644 index 0000000000..5f18b940cb --- /dev/null +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/CompositeIndependenceTest.java @@ -0,0 +1,41 @@ +package edu.cmu.tetrad.search; + +import edu.cmu.tetrad.data.DataModel; +import edu.cmu.tetrad.graph.Node; +import edu.cmu.tetrad.search.test.IndependenceResult; + +import java.util.List; +import java.util.Set; + +public class CompositeIndependenceTest implements IndependenceTest { + private final IndependenceTest[] independenceTests; + + public CompositeIndependenceTest(IndependenceTest[] independenceTests) { + this.independenceTests = independenceTests; + } + + @Override + public IndependenceResult checkIndependence(Node x, Node y, Set z) { + return null; + } + + @Override + public List getVariables() { + return null; + } + + @Override + public DataModel getData() { + return null; + } + + @Override + public boolean isVerbose() { + return false; + } + + @Override + public void setVerbose(boolean verbose) { + + } +} From 6371dd03ac318d6087518364143e561f608dbe0d Mon Sep 17 00:00:00 2001 From: jdramsey Date: Tue, 9 Jan 2024 19:14:03 -0500 Subject: [PATCH 051/163] Work on Chi Square test. Made a parameter to allow the user to specify the minimum row and cell counts for calculating chi-square and g-square. --- .../edu/cmu/tetrad/search/test/ChiSquareTest.java | 13 +++++++------ .../src/main/resources/docs/manual/index.html | 4 ++-- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java index 77b691087d..9ca5c802be 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java @@ -29,8 +29,7 @@ import java.util.List; -import static org.apache.commons.math3.util.FastMath.log; -import static org.apache.commons.math3.util.FastMath.pow; +import static org.apache.commons.math3.util.FastMath.*; /** * Calculates chi-square for a conditional cross-tabulation table for independence question 0 _||_ 1 | 2, 3, ...max by @@ -185,7 +184,7 @@ public Result calcChiSquare(int[] testIndices) { // Sum up chi square and degrees of freedom for the conditional table. Keep track of zeroes in the table // and subtract them from the degrees of freedom. If there are no free degrees of freedom, don't increment // the chi square or degrees of freedom. - int zeros = 0; + int terms = 0; double _xSquare = 0.0; if (total == 0 || (numNonZeroRows < 2 && numNonZeroCols < 2)) { @@ -202,23 +201,25 @@ public Result calcChiSquare(int[] testIndices) { if (expected > 0) { if (testType == TestType.CHI_SQUARE) { _xSquare += pow(observed - expected, 2.0) / expected; + terms++; } else if (testType == TestType.G_SQUARE) { if (observed > 0) { _xSquare += 2.0 * observed * log(observed / expected); + terms++; } else { - zeros++; +// zeros++; } } else { throw new IllegalArgumentException("Unknown test type: " + testType); } } else { - zeros++; +// zeros++; } } } } - int _df = (numNonZeroRows - 1) * (numNonZeroCols - 1) - zeros; + int _df = min((numNonZeroRows - 1) * (numNonZeroCols - 1), terms); if (_df > 0) { diff --git a/tetrad-lib/src/main/resources/docs/manual/index.html b/tetrad-lib/src/main/resources/docs/manual/index.html index adff18d813..db149d352c 100755 --- a/tetrad-lib/src/main/resources/docs/manual/index.html +++ b/tetrad-lib/src/main/resources/docs/manual/index.html @@ -6494,9 +6494,9 @@

    kciEpsilon

    used in the test. Default is zero.
  • Default Value: 0
  • + id="minSumRowOrCol_default_value">1
  • Lower - Bound: 0
  • + Bound: 1
  • Upper Bound: 2147483647
  • Value Type: From 9d97837d1018d0bd93c025897e293e96d565c920 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Wed, 10 Jan 2024 02:22:14 -0500 Subject: [PATCH 052/163] Work on Chi Square test. Made a parameter to allow the user to specify the minimum row and cell counts for calculating chi-square and g-square. --- .../java/edu/cmu/tetrad/bayes/MlBayesIm.java | 117 ++---------------- .../cmu/tetrad/search/test/ChiSquareTest.java | 38 +++--- 2 files changed, 35 insertions(+), 120 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/bayes/MlBayesIm.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/bayes/MlBayesIm.java index c79902586e..e58a394afb 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/bayes/MlBayesIm.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/bayes/MlBayesIm.java @@ -31,6 +31,7 @@ import java.io.IOException; import java.io.ObjectInputStream; +import java.io.Serial; import java.text.NumberFormat; import java.util.*; @@ -76,8 +77,10 @@ public final class MlBayesIm implements BayesIm { * Indicates that new rows in this BayesIm should be initialized randomly. */ public static final int RANDOM = 1; + @Serial private static final long serialVersionUID = 23L; private static final double ALLOWABLE_DIFFERENCE = 1.0e-3; + static private final Random random = new Random(); /** * The associated Bayes PM model. @@ -212,76 +215,19 @@ public static List getParameterNames() { return new ArrayList<>(); } - private static double[] getRandomWeights2(int size, double[] biases) { - assert size >= 0; - - double[] row = new double[size]; - double sum = 0.0; - - for (int i = 0; i < size; i++) { -// row[i] = RandomUtil.getInstance().nextDouble() + biases[i]; - double v = RandomUtil.getInstance().nextUniform(0, biases[i]); - row[i] = v > 0.5 ? 2 * v : v; - sum += row[i]; - } - - for (int i = 0; i < size; i++) { - row[i] /= sum; - } - - return row; - } - -// static int strong_ = 0; - - Random random = new Random(); - - private static double[] getRandomWeights3(int size) { - assert size > 0; - - double[] row = new double[size]; - double sum = 0.0; - - for (int i = 0; i < size; i++) { - //noinspection StatementWithEmptyBody - for (int j = 0; j < RandomUtil.getInstance().nextInt(10); j++) { - // empty - } - - row[i] = pow(RandomUtil.getInstance().nextUniform(0.0, 1.0), 3); - - sum += row[i]; - } - - for (int i = 0; i < size; i++) { - row[i] /= sum; - } - - return row; - } - - /** - * This method chooses random probabilities for a row which add up to 1.0. Random doubles are drawn from a random - * distribution, and the final row is then normalized. - * - * @param size the length of the row. - * @return an array with randomly distributed probabilities of this length. - * @see #randomizeRow - */ private static double[] getRandomWeights(int size) { - assert size >= 0; + assert size > 0; double[] row = new double[size]; double sum = 0.0; - // Renders rows more deterministic. - final double bias = 0; + int strong = (int) Math.floor(random.nextDouble() * size); for (int i = 0; i < size; i++) { - row[i] = RandomUtil.getInstance().nextDouble(); - - if (row[i] > 0.5) { - row[i] += bias; + if (i == strong) { + row[i] = 1.0; + } else { + row[i] = RandomUtil.getInstance().nextDouble() * 0.1; } sum += row[i]; @@ -608,12 +554,7 @@ public void clearRow(int nodeIndex, int rowIndex) { */ public void randomizeRow(int nodeIndex, int rowIndex) { int size = getNumColumns(nodeIndex); - this.probs[nodeIndex][rowIndex] = MlBayesIm.getRandomWeights3(size); - } - - private void randomizeRow2(int nodeIndex, int rowIndex, double[] biases) { - int size = getNumColumns(nodeIndex); - this.probs[nodeIndex][rowIndex] = MlBayesIm.getRandomWeights2(size, biases); + this.probs[nodeIndex][rowIndex] = MlBayesIm.getRandomWeights(size); } /** @@ -638,39 +579,6 @@ public void randomizeTable(int nodeIndex) { for (int rowIndex = 0; rowIndex < getNumRows(nodeIndex); rowIndex++) { randomizeRow(nodeIndex, rowIndex); } -// randomizeTable4(nodeIndex); - } - - private void randomizeTable4(int nodeIndex) { - for (int rowIndex = 0; rowIndex < getNumRows(nodeIndex); rowIndex++) { - randomizeRow(nodeIndex, rowIndex); - } - - double[][] saved = new double[getNumRows(nodeIndex)][getNumColumns(nodeIndex)]; - - double max = Double.NEGATIVE_INFINITY; - - for (int i = 0; i < 10; i++) { - for (int rowIndex = 0; rowIndex < getNumRows(nodeIndex); rowIndex++) { -// randomizeRow(nodeIndex, rowIndex); - randomizeRow2(nodeIndex, rowIndex, this.probs[nodeIndex][rowIndex]); - } - - int score = score(nodeIndex); - - if (score > max) { - max = score; - copy(this.probs[nodeIndex], saved); - } - - if (score == getNumParents(nodeIndex)) { - break; - } - } - - for (int rowIndex = 0; rowIndex < getNumRows(nodeIndex); rowIndex++) { - copy(saved, this.probs[nodeIndex]); - } } private int score(int nodeIndex) { @@ -1113,12 +1021,10 @@ public boolean equals(Object o) { return true; } - if (!(o instanceof BayesIm)) { + if (!(o instanceof BayesIm otherIm)) { return false; } - BayesIm otherIm = (BayesIm) o; - if (getNumNodes() != otherIm.getNumNodes()) { return false; } @@ -1455,6 +1361,7 @@ private void copyValuesFromOldToNew(int oldNodeIndex, int oldRowIndex, * class that didn't include it. (That's what the "s.defaultReadObject();" is for. See J. Bloch, Effective Java, for * help. */ + @Serial private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException { s.defaultReadObject(); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java index 9ca5c802be..af72f32b08 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java @@ -38,8 +38,8 @@ * * numNonZeroCols counts, where c is a parameter. The default value of c is 0. If any conditional table has fewer than * c * numNonZeroRows * numNonZeroCols counts or zero free degrees of freedom, the test is invalid. Otherwise, the test * is valid and the chi-square and degrees of freedom are calculated by summing up the chi-square and degrees of freedom - * for each conditional table. The p-value is calculated from the chi-square and degrees of freedom using the - * chi-square distribution. + * for each conditional table. The p-value is calculated from the chi-square and degrees of freedom using the chi-square + * distribution. * * @author frankwimberly * @author josephramsey @@ -186,8 +186,10 @@ public Result calcChiSquare(int[] testIndices) { // the chi square or degrees of freedom. int terms = 0; double _xSquare = 0.0; + int zeros = 0; - if (total == 0 || (numNonZeroRows < 2 && numNonZeroCols < 2)) { + if (total == 0 || (numNonZeroRows < 2 || numNonZeroCols < 2)) { +// return new Result(Double.NaN, Double.NaN, 0, true, false); continue; } else { for (int i = 0; i < numRows; i++) { @@ -195,8 +197,12 @@ public Result calcChiSquare(int[] testIndices) { coords[0] = i; coords[1] = j; + if (zeroRows[i] || zeroCols[j]) { + continue; + } + double observed = getCellTable().getValue(coords); - double expected = (sumRows[i] * sumCols[j]) / (total); + double expected = (sumRows[i] * sumCols[j]) / total; if (expected > 0) { if (testType == TestType.CHI_SQUARE) { @@ -207,37 +213,39 @@ public Result calcChiSquare(int[] testIndices) { _xSquare += 2.0 * observed * log(observed / expected); terms++; } else { -// zeros++; + zeros++; } } else { throw new IllegalArgumentException("Unknown test type: " + testType); } } else { -// zeros++; + zeros++; } } } } - int _df = min((numNonZeroRows - 1) * (numNonZeroCols - 1), terms); + int maxDf = (numNonZeroRows - 1) * (numNonZeroCols - 1); + int _df = min(maxDf, terms); - if (_df > 0) { +// _df = (numNonZeroRows - 1) * (numNonZeroCols - 1) - zeros; - // There were free degrees of freedom in the table, so we count this chi-square and df. + if (_df > 0) { df += _df; xSquare += _xSquare; } } if (df == 0) { - return new Result(Double.NaN, Double.NaN, -1, false, false); - } - // At this point in the code, the p-value cannot be NaN. - double pValue = 1.0 - new ChiSquaredDistribution(df).cumulativeProbability(xSquare); + // If no conditional table had positive degrees of freedom, the test is invalid. + return new Result(Double.NaN, Double.NaN, 0, true, false); + } else { - boolean indep = (pValue > getAlpha()); - return new Result(xSquare, pValue, df, indep); + // Otherwise, we can calculate a p-value for the test. + double pValue = 1.0 - new ChiSquaredDistribution(df).cumulativeProbability(xSquare); + return new Result(xSquare, pValue, df, (pValue > getAlpha()), true); + } } /** From fb897e44b6e0cedd077336013f73f6d73b487a0f Mon Sep 17 00:00:00 2001 From: jdramsey Date: Wed, 10 Jan 2024 02:48:56 -0500 Subject: [PATCH 053/163] Work on Chi Square test. Made a parameter to allow the user to specify the minimum row and cell counts for calculating chi-square and g-square. --- pom.xml | 8 ++++---- .../java/edu/cmu/tetrad/search/MarkovCheck.java | 2 +- .../edu/cmu/tetrad/search/test/IndTestFisherZ.java | 13 +++++++------ 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/pom.xml b/pom.xml index 459e93e964..9903fa546a 100644 --- a/pom.xml +++ b/pom.xml @@ -64,8 +64,8 @@ maven-compiler-plugin 3.11.0 - 1.8 - 1.8 + 17 + 17 @@ -188,8 +188,8 @@ UTF-8 -Xdoclint:none - 1.8 - 1.8 + 17 + 17 diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java index a9efeadc13..6e8ab36048 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java @@ -636,7 +636,7 @@ private void calcStats(boolean indep) { */ private List getSubsampleRows(double v) { int sampleSize = independenceTest.getSampleSize(); - int subsampleSize = (int) FastMath.ceil(sampleSize * v); + int subsampleSize = (int) FastMath.floor(sampleSize * v); List rows = new ArrayList<>(sampleSize); for (int i = 0; i < sampleSize; i++) { rows.add(i); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java index c587a07326..8ada535acc 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java @@ -25,7 +25,6 @@ import edu.cmu.tetrad.graph.IndependenceFact; import edu.cmu.tetrad.graph.Node; import edu.cmu.tetrad.search.IndependenceTest; -import edu.cmu.tetrad.search.utils.GraphSearchUtils; import edu.cmu.tetrad.search.utils.LogUtilsSearch; import edu.cmu.tetrad.util.Matrix; import edu.cmu.tetrad.util.MatrixUtils; @@ -203,7 +202,7 @@ public IndependenceTest indTestSubset(List vars) { * @see IndependenceResult */ public IndependenceResult checkIndependence(Node x, Node y, Set z) { - double p = Double.NaN; + double p; try { p = getPValue(x, y, z); @@ -519,6 +518,7 @@ private List getRows(List allVars, Map nodesHash) /** * Returns the rows used in the test. + * * @return The rows used in the test. */ public List getRows() { @@ -526,8 +526,9 @@ public List getRows() { } /** - * Allows the user to set which rows are used in the test. Otherwise, all rows are used, except - * those with missing values. + * Allows the user to set which rows are used in the test. Otherwise, all rows are used, except those with missing + * values. + * * @param rows The rows to use. */ public void setRows(List rows) { @@ -535,8 +536,8 @@ public void setRows(List rows) { throw new IllegalStateException("Cannot set rows without a data set."); } - for (int i = 0; i < dataSet.getNumRows(); i++) { - if (rows.get(i) < 0 || rows.get(i) >= sampleSize()) { + for (Integer row : rows) { + if (row < 0 || row >= sampleSize()) { throw new IllegalArgumentException("Row index out of bounds."); } } From 79ac5d8de4b1a575beec269245a72589eeb6c21c Mon Sep 17 00:00:00 2001 From: jdramsey Date: Wed, 10 Jan 2024 08:39:24 -0500 Subject: [PATCH 054/163] Updated some dependencies. --- pom.xml | 4 +-- tetrad-gui/pom.xml | 2 +- tetrad-lib/dependency-reduced-pom.xml | 35 ++++++++----------- tetrad-lib/pom.xml | 6 ++-- .../cmu/tetrad/search/test/ChiSquareTest.java | 8 ----- .../tetrad/search/utils/GraphSearchUtils.java | 16 +++++++-- 6 files changed, 35 insertions(+), 36 deletions(-) diff --git a/pom.xml b/pom.xml index 9903fa546a..cff05d0bb4 100644 --- a/pom.xml +++ b/pom.xml @@ -116,7 +116,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.6.2 + 3.6.3 /usr/bin/javadoc @@ -144,7 +144,7 @@ org.apache.maven.plugins maven-source-plugin - 3.2.1 + 3.3.0 attach-sources diff --git a/tetrad-gui/pom.xml b/tetrad-gui/pom.xml index f86e58b548..f9fc45341b 100644 --- a/tetrad-gui/pom.xml +++ b/tetrad-gui/pom.xml @@ -40,7 +40,7 @@ org.apache.maven.plugins maven-shade-plugin - 3.1.0 + 3.5.1 package diff --git a/tetrad-lib/dependency-reduced-pom.xml b/tetrad-lib/dependency-reduced-pom.xml index 1a34c60792..1c02aa9cb9 100644 --- a/tetrad-lib/dependency-reduced-pom.xml +++ b/tetrad-lib/dependency-reduced-pom.xml @@ -3,7 +3,7 @@ tetrad io.github.cmu-phil - 7.6.0-SNAPSHOT + 7.6.2-SNAPSHOT 4.0.0 tetrad-lib @@ -20,35 +20,31 @@ maven-compiler-plugin 3.11.0 - 1.8 - 1.8 + 17 + 17 maven-shade-plugin - 3.1.0 + 3.5.1 package shade - - - - - maven-antrun-plugin - 3.1.0 - - - compile - - run - - - - + + + + all-permissions + ${project.name} + ${project.version} + + + + true + shaded @@ -59,4 +55,3 @@ UTF-8 - diff --git a/tetrad-lib/pom.xml b/tetrad-lib/pom.xml index 4bad72a2bb..e6056c4bfd 100644 --- a/tetrad-lib/pom.xml +++ b/tetrad-lib/pom.xml @@ -25,7 +25,7 @@ org.apache.maven.plugins maven-shade-plugin - 3.1.0 + 3.5.1 package @@ -93,7 +93,7 @@ org.apache.commons commons-lang3 - 3.12.0 + 3.14.0 colt @@ -144,7 +144,7 @@ org.json json - 20230227 + 20231013 compile diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java index af72f32b08..19c735438c 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java @@ -186,7 +186,6 @@ public Result calcChiSquare(int[] testIndices) { // the chi square or degrees of freedom. int terms = 0; double _xSquare = 0.0; - int zeros = 0; if (total == 0 || (numNonZeroRows < 2 || numNonZeroCols < 2)) { // return new Result(Double.NaN, Double.NaN, 0, true, false); @@ -212,14 +211,10 @@ public Result calcChiSquare(int[] testIndices) { if (observed > 0) { _xSquare += 2.0 * observed * log(observed / expected); terms++; - } else { - zeros++; } } else { throw new IllegalArgumentException("Unknown test type: " + testType); } - } else { - zeros++; } } } @@ -228,8 +223,6 @@ public Result calcChiSquare(int[] testIndices) { int maxDf = (numNonZeroRows - 1) * (numNonZeroCols - 1); int _df = min(maxDf, terms); -// _df = (numNonZeroRows - 1) * (numNonZeroCols - 1) - zeros; - if (_df > 0) { df += _df; xSquare += _xSquare; @@ -337,7 +330,6 @@ public void setAlpha(double alpha) { */ public void setRows(List rows) { this.cellTable.setRows(rows); - // The rows used in the data. } private int[] selectFromArray(int[] arr, int[] indices) { diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/GraphSearchUtils.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/GraphSearchUtils.java index 487c0dfd8f..3aedf21989 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/GraphSearchUtils.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/GraphSearchUtils.java @@ -389,12 +389,24 @@ public static boolean isCpdag(Graph graph) { if (Edges.isUndirectedEdge(edge)) { Graph _graph = new EdgeListGraph(graph); - direct(x, y, _graph); + + if (!_graph.paths().isAncestorOf(y, x)) { + direct(x, y, graph); + } else { + direct(y, x, graph); + } + rules.orientImplied(_graph); if (_graph.paths().existsDirectedCycle()) return false; _graph = new EdgeListGraph(graph); - direct(y, x, _graph); + + if (!_graph.paths().isAncestorOf(y, x)) { + direct(x, y, graph); + } else { + direct(y, x, graph); + } + rules.orientImplied(_graph); if (_graph.paths().existsDirectedCycle()) return false; From ebc99d719bfee67eb69ea563c081f3a3b3dafcf8 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Thu, 11 Jan 2024 14:27:55 -0500 Subject: [PATCH 055/163] Updated some dependencies. --- .../cmu/tetrad/search/test/ChiSquareTest.java | 68 +++++++------------ .../src/main/resources/docs/manual/index.html | 2 +- 2 files changed, 24 insertions(+), 46 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java index 19c735438c..f92afc4a3e 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java @@ -29,7 +29,7 @@ import java.util.List; -import static org.apache.commons.math3.util.FastMath.*; +import static org.apache.commons.math3.util.FastMath.log; /** * Calculates chi-square for a conditional cross-tabulation table for independence question 0 _||_ 1 | 2, 3, ...max by @@ -135,62 +135,45 @@ public Result calcChiSquare(int[] testIndices) { // chi square and degrees of freedom for the remaining rows and columns in the table. See Friedman. while (combinationIterator.hasNext()) { int[] combination = combinationIterator.next(); - System.arraycopy(combination, 0, coords, 2, combination.length); - boolean[] zeroRows = new boolean[numRows]; - boolean[] zeroCols = new boolean[numCols]; double[] sumRows = new double[numRows]; double[] sumCols = new double[numCols]; + boolean[] zeroRows = new boolean[numRows]; + boolean[] zeroCols = new boolean[numCols]; + int numNonZeroRows = 0; + int numNonZeroCols = 0; for (int i = 0; i < numRows; i++) { coords[0] = i; - sumRows[i] = getCellTable().calcMargin(coords, secondVar); if (sumRows[i] < minSumRowOrCol) { zeroRows[i] = true; + } else { + numNonZeroRows++; } } for (int j = 0; j < numCols; j++) { coords[1] = j; - sumCols[j] = getCellTable().calcMargin(coords, firstVar); if (sumCols[j] < minSumRowOrCol) { zeroCols[j] = true; + } else { + numNonZeroCols++; } } double total = getCellTable().calcMargin(coords, bothVars); - // Count non-zero rows and columns - int numNonZeroRows = 0; - int numNonZeroCols = 0; - - for (int i = 0; i < numRows; i++) { - if (!zeroRows[i]) { - numNonZeroRows++; - } - } - - for (int j = 0; j < numCols; j++) { - if (!zeroCols[j]) { - numNonZeroCols++; - } - } - // Sum up chi square and degrees of freedom for the conditional table. Keep track of zeroes in the table // and subtract them from the degrees of freedom. If there are no free degrees of freedom, don't increment // the chi square or degrees of freedom. - int terms = 0; - double _xSquare = 0.0; + if (total > 0 && numNonZeroRows > 1 && numNonZeroCols > 1) { + double _xSquare = 0.0; - if (total == 0 || (numNonZeroRows < 2 || numNonZeroCols < 2)) { -// return new Result(Double.NaN, Double.NaN, 0, true, false); - continue; - } else { for (int i = 0; i < numRows; i++) { for (int j = 0; j < numCols; j++) { coords[0] = i; @@ -201,31 +184,26 @@ public Result calcChiSquare(int[] testIndices) { } double observed = getCellTable().getValue(coords); + + // Under the above conditions, expected > 0. double expected = (sumRows[i] * sumCols[j]) / total; - if (expected > 0) { - if (testType == TestType.CHI_SQUARE) { - _xSquare += pow(observed - expected, 2.0) / expected; - terms++; - } else if (testType == TestType.G_SQUARE) { - if (observed > 0) { - _xSquare += 2.0 * observed * log(observed / expected); - terms++; - } - } else { - throw new IllegalArgumentException("Unknown test type: " + testType); + if (testType == TestType.CHI_SQUARE) { + double d = observed - expected; + _xSquare += (d * d) / expected; + } else if (testType == TestType.G_SQUARE) { + if (observed > 0) { + _xSquare += 2.0 * observed * log(observed / expected); } + } else { + throw new IllegalArgumentException("Unknown test type: " + testType); } } } - } - int maxDf = (numNonZeroRows - 1) * (numNonZeroCols - 1); - int _df = min(maxDf, terms); - - if (_df > 0) { - df += _df; + int _df = (numNonZeroRows - 1) * (numNonZeroCols - 1); xSquare += _xSquare; + df += _df; } } diff --git a/tetrad-lib/src/main/resources/docs/manual/index.html b/tetrad-lib/src/main/resources/docs/manual/index.html index db149d352c..92896f836c 100755 --- a/tetrad-lib/src/main/resources/docs/manual/index.html +++ b/tetrad-lib/src/main/resources/docs/manual/index.html @@ -5837,7 +5837,7 @@

    faskDelta

    id="pcHeuristic">pcHeuristic
    • Short Description: - Heuristics in CPC to stabilize skeleton: 0 = None, 1 = Heuristic 1, 2 = Heuristic 2, 3 = Heuristic 3 + Heuristics to stabilize skeleton: 0 = None, 1 = Heuristic 1, 2 = Heuristic 2, 3 = Heuristic 3
    • Long Description: From ec32b53dcbb2bb2d96478b4b222513790e1f009d Mon Sep 17 00:00:00 2001 From: jdramsey Date: Thu, 11 Jan 2024 14:36:42 -0500 Subject: [PATCH 056/163] Cleaned up version of Chi-Square with promise of uniform p-values under the null. --- .../cmu/tetrad/search/test/ChiSquareTest.java | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java index f92afc4a3e..e626d446e3 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java @@ -32,17 +32,15 @@ import static org.apache.commons.math3.util.FastMath.log; /** - * Calculates chi-square for a conditional cross-tabulation table for independence question 0 _||_ 1 | 2, 3, ...max by - * summing up chi-square and degrees of freedom for each conditional table in turn, where rows or columns that consist - * entirely of zeros have been removed. The adjusted conditional tables are required to have at least c * numNonZeroRows - * * numNonZeroCols counts, where c is a parameter. The default value of c is 0. If any conditional table has fewer than - * c * numNonZeroRows * numNonZeroCols counts or zero free degrees of freedom, the test is invalid. Otherwise, the test - * is valid and the chi-square and degrees of freedom are calculated by summing up the chi-square and degrees of freedom - * for each conditional table. The p-value is calculated from the chi-square and degrees of freedom using the chi-square - * distribution. + * Calculates chi-square or g-square for a conditional cross-tabulation table for independence question 0 _||_ 1 | 2, 3, + * ...max by summing up chi-square and degrees of freedom for each conditional table in turn, where rows or columns that + * sum to less than a given threshold have been removed. The adjusted conditional tables are required to have more than + * 0 total counts and at least 2 rows and 2 columns; otherwise, the test is judged to be invalid. Otherwise, a p-value + * is returned based on the Chi-Square distribution with the total degrees of freedom and total chi-square. * * @author frankwimberly * @author josephramsey + * @see TestType */ public class ChiSquareTest { @@ -60,9 +58,10 @@ public class ChiSquareTest { // The significance level of the test. private double alpha; + /** - * The minimum number of counts per conditional table for chi-square expressed as a multiple of the total number of - * cells in the table. Note that this should not be too small, or the chi-square distribution will not be a good + * The minimum sum of a row or column for a conditional table to be included in the overall chi-square and degrees + * of freedom. Note that this should not be too small, or the chi-square distribution will not be a good * approximation to the distribution of the test statistic. */ private int minSumRowOrCol = 0; @@ -98,7 +97,10 @@ public ChiSquareTest(DataSet dataSet, double alpha, TestType testType) { /** * Calculates chi square for a conditional cross-tabulation table for independence question 0 _||_ 1 | 2, 3, ...max * by summing up chi square and degrees of freedom for each conditional table in turn, where rows or columns that - * consist entirely of zeros have been removed. + * with fewer than minSumRowOrCol counts have been removed. The adjusted conditional tables are required to have + * more than 0 total counts and at least 2 rows and 2 columns; otherwise, the test is judged to be invalid. + * Otherwise, a p-value is returned based on the Chi-Square distribution with the total degrees of freedom and total + * chi-square. * * @param testIndices These indices, in order. * @return a Chi square test result. From 88966e8c604ba860f5bf79af312a695355725481 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Thu, 11 Jan 2024 14:37:34 -0500 Subject: [PATCH 057/163] Cleaned up version of Chi-Square with promise of uniform p-values under the null. --- .../main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java index e626d446e3..eee8d942e2 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java @@ -345,6 +345,9 @@ public void setMinSumRowOrCol(int minSumRowOrCol) { this.minSumRowOrCol = minSumRowOrCol; } + /** + * The type of test to perform. + */ public enum TestType { CHI_SQUARE, G_SQUARE From 8b97a51b306d1a7006d53a9af8a79986803421b7 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Thu, 11 Jan 2024 15:15:03 -0500 Subject: [PATCH 058/163] Cleaned up version of Chi-Square with promise of uniform p-values under the null. --- .../cmu/tetrad/search/test/ChiSquareTest.java | 27 +++++++++---------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java index eee8d942e2..2b5d3f0ddb 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java @@ -75,15 +75,13 @@ public class ChiSquareTest { */ public ChiSquareTest(DataSet dataSet, double alpha, TestType testType) { if (alpha < 0.0 || alpha > 1.0) { - throw new IllegalArgumentException("Significance level must be in " + - "[0, 1]: " + alpha); + throw new IllegalArgumentException("Significance level must be in " + "[0, 1]: " + alpha); } this.dims = new int[dataSet.getNumColumns()]; for (int i = 0; i < getDims().length; i++) { - DiscreteVariable variable = - (DiscreteVariable) dataSet.getVariable(i); + DiscreteVariable variable = (DiscreteVariable) dataSet.getVariable(i); this.getDims()[i] = variable.getNumCategories(); } @@ -124,8 +122,7 @@ public Result calcChiSquare(int[] testIndices) { int df = 0; int[] condDims = new int[testIndices.length - 2]; - System.arraycopy(selectFromArray(getDims(), testIndices), 2, condDims, 0, - condDims.length); + System.arraycopy(selectFromArray(getDims(), testIndices), 2, condDims, 0, condDims.length); int[] coords = new int[testIndices.length]; int numRows = this.getCellTable().getNumValues(0); @@ -194,8 +191,14 @@ public Result calcChiSquare(int[] testIndices) { double d = observed - expected; _xSquare += (d * d) / expected; } else if (testType == TestType.G_SQUARE) { + + // The G-square test is a likelihood ratio test, so we need to take the log of the + // observed/expected ratio. When observed is zero, we add 0 to the total. This is the + // correct thing to do, since the limit of x * log(x) as x approaches zero is zero. if (observed > 0) { _xSquare += 2.0 * observed * log(observed / expected); + } else { + _xSquare += 0.0; } } else { throw new IllegalArgumentException("Unknown test type: " + testType); @@ -241,14 +244,12 @@ public boolean isDetermined(int[] testIndices, double p) { int[] firstVar = {0}; int[] condDims = new int[testIndices.length - 1]; - System.arraycopy(selectFromArray(getDims(), testIndices), 1, condDims, 0, - condDims.length); + System.arraycopy(selectFromArray(getDims(), testIndices), 1, condDims, 0, condDims.length); int[] coords = new int[testIndices.length]; int numValues = this.getCellTable().getNumValues(0); - CombinationIterator combinationIterator = - new CombinationIterator(condDims); + CombinationIterator combinationIterator = new CombinationIterator(condDims); while (combinationIterator.hasNext()) { int[] combination = combinationIterator.next(); @@ -296,8 +297,7 @@ public double getAlpha() { */ public void setAlpha(double alpha) { if (alpha < 0.0 || alpha > 1.0) { - throw new IllegalArgumentException("Significance level must be in " + - "[0, 1]: " + alpha); + throw new IllegalArgumentException("Significance level must be in " + "[0, 1]: " + alpha); } this.alpha = alpha; @@ -349,8 +349,7 @@ public void setMinSumRowOrCol(int minSumRowOrCol) { * The type of test to perform. */ public enum TestType { - CHI_SQUARE, - G_SQUARE + CHI_SQUARE, G_SQUARE } /** From 0993eaafde7dfc2e753a930c91e214f0d24ec233 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Thu, 11 Jan 2024 15:56:40 -0500 Subject: [PATCH 059/163] Cleaned up version of Chi-Square with promise of uniform p-values under the null. --- .../main/java/edu/cmu/tetrad/search/Ida.java | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Ida.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Ida.java index 586627ef7a..383d495ba0 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Ida.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Ida.java @@ -1,6 +1,9 @@ package edu.cmu.tetrad.search; -import edu.cmu.tetrad.data.*; +import edu.cmu.tetrad.data.CovarianceMatrix; +import edu.cmu.tetrad.data.DataSet; +import edu.cmu.tetrad.data.DataTransforms; +import edu.cmu.tetrad.data.ICovarianceMatrix; import edu.cmu.tetrad.graph.Graph; import edu.cmu.tetrad.graph.GraphUtils; import edu.cmu.tetrad.graph.Node; @@ -17,14 +20,13 @@ import static org.apache.commons.math3.util.FastMath.min; /** - *

      Implements the IDA algorithm. The reference is here:

      - * - *

      Maathuis, Marloes H., Markus Kalisch, and Peter Bühlmann. - * "Estimating high-dimensional intervention effects from observational data." The Annals of Statistics 37.6A (2009): - * 3133-3164.

      - * - *

      The IDA algorithm seeks to give a list of possible parents - * of a given variable Y and their corresponding lower-bounded effects on Y.

      + * Implements the IDA algorithm. The reference is here: + *

      + * Maathuis, Marloes H., Markus Kalisch, and Peter Bühlmann. "Estimating high-dimensional intervention effects from + * observational data." The Annals of Statistics 37.6A (2009): 3133-3164. + *

      + * The IDA algorithm seeks to give a list of possible parents of a given variable Y and their corresponding + * lower-bounded effects on Y. * * @author josephramsey * @see Cstar From 60c06c3a8adfbf9a152d425e11ea5f1de61197b6 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Sat, 13 Jan 2024 13:44:44 -0500 Subject: [PATCH 060/163] Cleaned up version of Chi-Square with promise of uniform p-values under the null. --- .../algcomparison/statistic/BicEst.java | 39 ++++++++++--- .../algcomparison/statistic/FBetaAdj.java | 56 +++++++++++++++++++ .../tetrad/search/score/DiscreteBicScore.java | 2 +- .../cmu/tetrad/search/test/ChiSquareTest.java | 4 ++ .../tetrad/search/test/IndTestFisherZ.java | 3 +- 5 files changed, 94 insertions(+), 10 deletions(-) create mode 100644 tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/FBetaAdj.java diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/BicEst.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/BicEst.java index 7d253bac49..7d3a9410a8 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/BicEst.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/BicEst.java @@ -1,10 +1,15 @@ package edu.cmu.tetrad.algcomparison.statistic; import edu.cmu.tetrad.data.DataModel; +import edu.cmu.tetrad.data.DataSet; import edu.cmu.tetrad.graph.Graph; import edu.cmu.tetrad.graph.GraphTransforms; +import edu.cmu.tetrad.graph.Node; +import edu.cmu.tetrad.search.score.DiscreteBicScore; import edu.cmu.tetrad.search.score.SemBicScorer; +import java.util.List; + import static org.apache.commons.math3.util.FastMath.tanh; /** @@ -15,16 +20,11 @@ public class BicEst implements Statistic { private static final long serialVersionUID = 23L; - private double penaltyDiscount = 1.0; private boolean precomputeCovariances = true; public BicEst() { } - public BicEst(double penaltyDiscount) { - this.penaltyDiscount = penaltyDiscount; - } - @Override public String getAbbreviation() { return "BicEst"; @@ -37,8 +37,33 @@ public String getDescription() { @Override public double getValue(Graph trueGraph, Graph estGraph, DataModel dataModel) { -// double _true = SemBicScorer.scoreDag(SearchGraphUtils.dagFromCPDAG(trueGraph), dataModel); - return SemBicScorer.scoreDag(GraphTransforms.dagFromCpdag(estGraph, null), dataModel, precomputeCovariances); + if (dataModel.isDiscrete()) { + DiscreteBicScore score = new DiscreteBicScore((DataSet) dataModel); + + Graph dag = GraphTransforms.dagFromCpdag(estGraph, null); + List nodes = dag.getNodes(); + + double _score = 0.0; + + for (Node node : dag.getNodes()) { + score.setPenaltyDiscount(1); + int i = nodes.indexOf(node); + List parents = dag.getParents(node); + int[] parentIndices = new int[parents.size()]; + + for (Node parent : parents) { + parentIndices[parents.indexOf(parent)] = nodes.indexOf(parent); + } + + _score += score.localScore(i, parentIndices); + } + + return _score; + } else if (dataModel.isContinuous()) { + return SemBicScorer.scoreDag(GraphTransforms.dagFromCpdag(estGraph, null), dataModel, precomputeCovariances); + } else { + throw new IllegalArgumentException("Data must be either discrete or continuous"); + } } @Override diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/FBetaAdj.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/FBetaAdj.java new file mode 100644 index 0000000000..059d4675d6 --- /dev/null +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/FBetaAdj.java @@ -0,0 +1,56 @@ +package edu.cmu.tetrad.algcomparison.statistic; + +import edu.cmu.tetrad.algcomparison.statistic.utils.AdjacencyConfusion; +import edu.cmu.tetrad.data.DataModel; +import edu.cmu.tetrad.graph.Graph; + +/** + * Calculates the F1 statistic for adjacencies. See + *

      + * https://en.wikipedia.org/wiki/F1_score + *

      + * We use what's on this page called the "traditional" F1 statistic. + * + * @author Joseh Ramsey + */ +public class FBetaAdj implements Statistic { + private static final long serialVersionUID = 23L; + + private double beta = 1; + + @Override + public String getAbbreviation() { + return "FBetaAdj"; + } + + @Override + public String getDescription() { + return "FBeta statistic for adjacencies"; + } + + @Override + public double getValue(Graph trueGraph, Graph estGraph, DataModel dataModel) { + AdjacencyConfusion adjConfusion = new AdjacencyConfusion(trueGraph, estGraph); + int adjTp = adjConfusion.getTp(); + int adjFp = adjConfusion.getFp(); + int adjFn = adjConfusion.getFn(); + int adjTn = adjConfusion.getTn(); + double adjPrecision = adjTp / (double) (adjTp + adjFp); + double adjRecall = adjTp / (double) (adjTp + adjFn); + return (1 + beta * beta) * (adjPrecision * adjRecall) + / (beta * beta * adjPrecision + adjRecall); + } + + @Override + public double getNormValue(double value) { + return value; + } + + public double getBeta() { + return beta; + } + + public void setBeta(double beta) { + this.beta = beta; + } +} diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/DiscreteBicScore.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/DiscreteBicScore.java index 773a34073e..8272737aa4 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/DiscreteBicScore.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/DiscreteBicScore.java @@ -189,7 +189,7 @@ public double localScore(int node, int[] parents) { int params = r * (c - 1); - double score = 2 * lik - this.penaltyDiscount * params * FastMath.log(N) + 2 * getPriorForStructure(parents.length); + double score = 2 * lik - this.penaltyDiscount * params * FastMath.log(N) - 2 * getPriorForStructure(parents.length); if (Double.isNaN(score) || Double.isInfinite(score)) { return Double.NaN; diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java index 2b5d3f0ddb..ed7c873620 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java @@ -170,6 +170,10 @@ public Result calcChiSquare(int[] testIndices) { // Sum up chi square and degrees of freedom for the conditional table. Keep track of zeroes in the table // and subtract them from the degrees of freedom. If there are no free degrees of freedom, don't increment // the chi square or degrees of freedom. + if (total == 0) { + return new Result(Double.NaN, Double.NaN, 0, true, false); + } + if (total > 0 && numNonZeroRows > 1 && numNonZeroCols > 1) { double _xSquare = 0.0; diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java index 8ada535acc..777315ce9f 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java @@ -52,14 +52,13 @@ public final class IndTestFisherZ implements IndependenceTest, RowsSettable { private final Map indexMap; private final Map nameMap; - private final NormalDistribution normal = new NormalDistribution(0, 1, 1e-15); + private final NormalDistribution normal = new NormalDistribution(0, 1); private final Map nodesHash; private ICovarianceMatrix cor = null; private List variables; private double alpha; private DataSet dataSet; private boolean verbose = true; - // private double p = Double.NaN; private double r = Double.NaN; private List rows = null; From f42dd16f772aa757b52537fcbce171b897b174fd Mon Sep 17 00:00:00 2001 From: jdramsey Date: Sat, 13 Jan 2024 16:09:53 -0500 Subject: [PATCH 061/163] Cleaned up version of Chi-Square with promise of uniform p-values under the null. --- .../statistic/BayesParametersEst.java | 72 +++++++++++++++++++ .../edu/cmu/tetrad/graph/GraphTransforms.java | 37 ++-------- .../tetrad/search/score/DiscreteBicScore.java | 18 ++++- .../tetrad/search/utils/GraphSearchUtils.java | 38 +++++----- .../edu/cmu/tetrad/test/TestGraphUtils.java | 2 +- 5 files changed, 115 insertions(+), 52 deletions(-) create mode 100644 tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/BayesParametersEst.java diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/BayesParametersEst.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/BayesParametersEst.java new file mode 100644 index 0000000000..62b216b177 --- /dev/null +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/BayesParametersEst.java @@ -0,0 +1,72 @@ +package edu.cmu.tetrad.algcomparison.statistic; + +import edu.cmu.tetrad.data.DataModel; +import edu.cmu.tetrad.data.DataSet; +import edu.cmu.tetrad.graph.Graph; +import edu.cmu.tetrad.graph.GraphTransforms; +import edu.cmu.tetrad.graph.Node; +import edu.cmu.tetrad.search.score.DiscreteBicScore; + +import java.io.Serial; +import java.util.List; + +import static org.apache.commons.math3.util.FastMath.tanh; + +/** + * Number of parameters for a discrete Bayes model of the data. Must be for a discrete dataset. + * + * @author josephramsey + */ +public class BayesParametersEst implements Statistic { + + @Serial + private static final long serialVersionUID = 23L; + + public BayesParametersEst() { + } + + @Override + public String getAbbreviation() { + return "DiscreteBicParams"; + } + + @Override + public String getDescription() { + return "Number of parameters for the estimated graph as a Bayes model"; + } + + @Override + public double getValue(Graph trueGraph, Graph estGraph, DataModel dataModel) { + if (dataModel.isDiscrete()) { + DiscreteBicScore score = new DiscreteBicScore((DataSet) dataModel); + + Graph dag = GraphTransforms.dagFromCpdag(estGraph, null); + List nodes = dag.getNodes(); + + double params = 0.0; + + for (Node node : dag.getNodes()) { + score.setPenaltyDiscount(1); + int i = nodes.indexOf(node); + List parents = dag.getParents(node); + int[] parentIndices = new int[parents.size()]; + + for (Node parent : parents) { + parentIndices[parents.indexOf(parent)] = nodes.indexOf(parent); + } + + params += score.numParameters(i, parentIndices); + } + + return params; + } else { + throw new IllegalArgumentException("Data must be discrete"); + } + } + + @Override + public double getNormValue(double value) { + return tanh(value / 1e6); + } +} + diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/graph/GraphTransforms.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/graph/GraphTransforms.java index 9454faf935..88b38e1975 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/graph/GraphTransforms.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/graph/GraphTransforms.java @@ -3,6 +3,7 @@ import edu.cmu.tetrad.data.Knowledge; import edu.cmu.tetrad.search.utils.DagInCpcagIterator; import edu.cmu.tetrad.search.utils.DagToPag; +import edu.cmu.tetrad.search.utils.GraphSearchUtils; import edu.cmu.tetrad.search.utils.MeekRules; import edu.cmu.tetrad.util.CombinationGenerator; import org.jetbrains.annotations.NotNull; @@ -20,15 +21,15 @@ public static Graph dagFromCpdag(Graph graph) { return dagFromCpdag(graph, null); } + /** + * Returns a DAG from the given CPDAG. If the given CPDAG is not a PDAG, returns null. + * @param graph the CPDAG + * @param knowledge the knowledge + * @return a DAG from the given CPDAG. If the given CPDAG is not a PDAG, returns null. + */ public static Graph dagFromCpdag(Graph graph, Knowledge knowledge) { Graph dag = new EdgeListGraph(graph); - for (Edge edge : dag.getEdges()) { - if (Edges.isBidirectedEdge(edge)) { - throw new IllegalArgumentException("That 'cpdag' contains a bidirected edge."); - } - } - MeekRules rules = new MeekRules(); if (knowledge != null) { @@ -56,30 +57,6 @@ public static Graph dagFromCpdag(Graph graph, Knowledge knowledge) { return dag; } - public static boolean isCpdag(Graph graph) { - MeekRules rules = new MeekRules(); - rules.setRevertToUnshieldedColliders(true); - rules.orientImplied(graph); - - NEXT: - while (true) { - for (Edge edge : graph.getEdges()) { - Node x = edge.getNode1(); - Node y = edge.getNode2(); - - if (Edges.isUndirectedEdge(edge)) { - direct(x, y, graph); - rules.orientImplied(graph); - continue NEXT; - } - } - - break; - } - - return !graph.paths().existsDirectedCycle(); - } - // Zhang 2008 Theorem 2 public static Graph pagToMag(Graph pag) { Graph mag = new EdgeListGraph(pag.getNodes()); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/DiscreteBicScore.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/DiscreteBicScore.java index 8272737aa4..342298cf30 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/DiscreteBicScore.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/DiscreteBicScore.java @@ -24,6 +24,7 @@ import edu.cmu.tetrad.data.*; import edu.cmu.tetrad.graph.Node; import edu.cmu.tetrad.search.Fges; +import edu.cmu.tetrad.util.ChoiceGenerator; import org.apache.commons.math3.util.FastMath; import javax.help.UnsupportedOperationException; @@ -50,7 +51,7 @@ public class DiscreteBicScore implements DiscreteScore { private final int[] numCategories; private List variables; private double penaltyDiscount = 1; - private double structurePrior = 1; + private double structurePrior = 0; /** * Constructor. @@ -189,7 +190,7 @@ public double localScore(int node, int[] parents) { int params = r * (c - 1); - double score = 2 * lik - this.penaltyDiscount * params * FastMath.log(N) - 2 * getPriorForStructure(parents.length); + double score = 2 * lik - this.penaltyDiscount * params * FastMath.log(N) + 2 * getPriorForStructure(parents.length); if (Double.isNaN(score) || Double.isInfinite(score)) { return Double.NaN; @@ -198,6 +199,19 @@ public double localScore(int node, int[] parents) { } } + /** + * Returns the number of parameters for a node given its parents. + */ + public int numParameters(int node, int[] parents) { + int numRows = 1; + + for (int k = 0; k < parents.length; k++) { + numRows *= this.numCategories[parents[k]]; + } + + return numRows * (this.numCategories[node] - 1); + } + /** * Returns localScore(y | z, x) - localScore(y | z). * diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/GraphSearchUtils.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/GraphSearchUtils.java index 3aedf21989..168a098b65 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/GraphSearchUtils.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/GraphSearchUtils.java @@ -349,12 +349,13 @@ public static void basicCpdagRestricted2(Graph graph, Node node) { /** * Returns true just in case the given graph is a CPDAG. + * * @param graph the graph to check. * @return true just in case the given graph is a CPDAG. */ - public static boolean isCpdag(Graph graph) { + public static boolean isPdag(Graph graph) { - // Make sure all of the edges are directed or undirected. + // Make sure all the edges are directed or undirected. for (Edge edge : graph.getEdges()) { if (!(Edges.isDirectedEdge(edge) || Edges.isUndirectedEdge(edge))) { return false; @@ -372,6 +373,14 @@ public static boolean isCpdag(Graph graph) { } } + // Make sure there are no underlinings. + if (!graph.getUnderLines().isEmpty()) { + return false; + } + if (!graph.getDottedUnderlines().isEmpty()) { + return false; + } + // Make sure there's no way to orient a directed cycle using the Meek rules. MeekRules rules = new MeekRules(); rules.setRevertToUnshieldedColliders(true); @@ -413,7 +422,7 @@ public static boolean isCpdag(Graph graph) { graph = _graph; continue NEXT; } - } + } break; } @@ -471,7 +480,7 @@ public static LegalPagRet isLegalPag(Graph pag) { "a MAG and PAG"; } - if (!edgeMismatch.equals("")) { + if (!edgeMismatch.isEmpty()) { reason = reason + ". " + edgeMismatch; } @@ -597,7 +606,7 @@ public static void arrangeByKnowledgeTiers(Graph graph, int x = 0; int y = 50 - ySpace; - if (notInTier.size() > 0) { + if (!notInTier.isEmpty()) { y += ySpace; for (String name : notInTier) { @@ -721,7 +730,7 @@ public static Set getReachableNodes(List initialNodes, int pathLength = 1; - while (nextEdges.size() > 0) { + while (!nextEdges.isEmpty()) { // System.out.println("Path length = " + pathLength); if (++pathLength > maxPathLength) { return reachable; @@ -918,20 +927,11 @@ private static int structuralHammingDistanceOneEdge(Edge e1, Edge e2) { if (!e1.equals(e2)) { error++; } - } else if (e2 == null) { - if (Edges.isUndirectedEdge(e1)) { - error++; - } else { - error++; - error++; - } + } else if (Edges.isUndirectedEdge(Objects.requireNonNullElse(e2, e1))) { + error++; } else { - if (Edges.isUndirectedEdge(e2)) { - error++; - } else { - error++; - error++; - } + error++; + error++; } } diff --git a/tetrad-lib/src/test/java/edu/cmu/tetrad/test/TestGraphUtils.java b/tetrad-lib/src/test/java/edu/cmu/tetrad/test/TestGraphUtils.java index d6d9c702da..eadcca6cc8 100644 --- a/tetrad-lib/src/test/java/edu/cmu/tetrad/test/TestGraphUtils.java +++ b/tetrad-lib/src/test/java/edu/cmu/tetrad/test/TestGraphUtils.java @@ -277,7 +277,7 @@ public void test8() { @Test public void test9() { Graph graph = GraphUtils.convert("X1---X2,X2---X3, X3---X4, X4---X1"); - assert(!GraphSearchUtils.isCpdag(graph)); + assert(!GraphSearchUtils.isPdag(graph)); } private Set set(Node... z) { From df448eb8b74463a208b58d23f4c57dd27218c926 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Sun, 14 Jan 2024 12:10:10 -0500 Subject: [PATCH 062/163] Cleaned up version of Chi-Square with promise of uniform p-values under the null. --- .../algcomparison/independence/ChiSquare.java | 4 +-- .../algcomparison/independence/GSquare.java | 6 ++-- .../cmu/tetrad/search/score/BdeuScore.java | 4 +-- .../cmu/tetrad/search/test/ChiSquareTest.java | 33 +++++++++++-------- .../tetrad/search/test/IndTestChiSquare.java | 19 +++++------ .../tetrad/search/test/IndTestGSquare.java | 19 +++++------ .../main/java/edu/cmu/tetrad/util/Params.java | 2 +- .../src/main/resources/docs/manual/index.html | 29 ++++++++-------- 8 files changed, 61 insertions(+), 55 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/ChiSquare.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/ChiSquare.java index d0d135e0ba..aa1a7d771a 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/ChiSquare.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/ChiSquare.java @@ -29,7 +29,7 @@ public class ChiSquare implements IndependenceWrapper { @Override public IndependenceTest getTest(DataModel dataSet, Parameters parameters) { IndTestChiSquare test = new IndTestChiSquare(SimpleDataLoader.getDiscreteDataSet(dataSet), parameters.getDouble(Params.ALPHA)); - test.setMinSumRowOrCol(parameters.getInt(Params.MIN_SUM_ROW_OR_COL)); + test.setMinCountPerCell(parameters.getDouble(Params.MIN_COUNT_PER_CELL)); return test; } @@ -47,7 +47,7 @@ public DataType getDataType() { public List getParameters() { List params = new ArrayList<>(); params.add(Params.ALPHA); - params.add(Params.MIN_SUM_ROW_OR_COL); + params.add(Params.MIN_COUNT_PER_CELL); return params; } } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/GSquare.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/GSquare.java index 91bed10d2b..f7673b15a2 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/GSquare.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/GSquare.java @@ -9,6 +9,7 @@ import edu.cmu.tetrad.util.Parameters; import edu.cmu.tetrad.util.Params; +import java.io.Serial; import java.util.ArrayList; import java.util.List; @@ -24,12 +25,13 @@ ) public class GSquare implements IndependenceWrapper { + @Serial private static final long serialVersionUID = 23L; @Override public IndependenceTest getTest(DataModel dataSet, Parameters parameters) { IndTestGSquare test = new IndTestGSquare(SimpleDataLoader.getDiscreteDataSet(dataSet), parameters.getDouble("test")); - test.setMinSumRowOrCol(parameters.getInt(Params.MIN_SUM_ROW_OR_COL)); + test.setMinCountPerCell(parameters.getDouble(Params.MIN_COUNT_PER_CELL)); return test; } @@ -47,7 +49,7 @@ public DataType getDataType() { public List getParameters() { List params = new ArrayList<>(); params.add(Params.ALPHA); - params.add(Params.MIN_SUM_ROW_OR_COL); + params.add(Params.MIN_COUNT_PER_CELL); return params; } } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/BdeuScore.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/BdeuScore.java index bc89865464..b0a31cdee6 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/BdeuScore.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/BdeuScore.java @@ -50,8 +50,8 @@ public class BdeuScore implements DiscreteScore { private final int[] numCategories; private final DataSet dataSet; private List variables; - private double samplePrior = 1; - private double structurePrior = 1; + private double samplePrior = 1d; + private double structurePrior = 0d; /** * Constructs a BDe score for the given dataset. diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java index ed7c873620..17c67d7405 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java @@ -29,6 +29,7 @@ import java.util.List; +import static java.lang.StrictMath.floor; import static org.apache.commons.math3.util.FastMath.log; /** @@ -64,7 +65,7 @@ public class ChiSquareTest { * of freedom. Note that this should not be too small, or the chi-square distribution will not be a good * approximation to the distribution of the test statistic. */ - private int minSumRowOrCol = 0; + private double minCountPerCell = 1.0; /** * Constructs a test using the given data set and significance level. @@ -147,7 +148,7 @@ public Result calcChiSquare(int[] testIndices) { coords[0] = i; sumRows[i] = getCellTable().calcMargin(coords, secondVar); - if (sumRows[i] < minSumRowOrCol) { + if (sumRows[i] == 0 || sumRows[i] < minCountPerCell * numCols) { zeroRows[i] = true; } else { numNonZeroRows++; @@ -156,9 +157,9 @@ public Result calcChiSquare(int[] testIndices) { for (int j = 0; j < numCols; j++) { coords[1] = j; - sumCols[j] = getCellTable().calcMargin(coords, firstVar); + sumCols[j] = getCellTable().calcMargin(coords, firstVar); - if (sumCols[j] < minSumRowOrCol) { + if (sumCols[j] == 0 || sumCols[j] < minCountPerCell * numRows) { zeroCols[j] = true; } else { numNonZeroCols++; @@ -167,11 +168,8 @@ public Result calcChiSquare(int[] testIndices) { double total = getCellTable().calcMargin(coords, bothVars); - // Sum up chi square and degrees of freedom for the conditional table. Keep track of zeroes in the table - // and subtract them from the degrees of freedom. If there are no free degrees of freedom, don't increment - // the chi square or degrees of freedom. - if (total == 0) { - return new Result(Double.NaN, Double.NaN, 0, true, false); + if (total < minCountPerCell * numRows * numCols) { + continue; } if (total > 0 && numNonZeroRows > 1 && numNonZeroCols > 1) { @@ -192,8 +190,14 @@ public Result calcChiSquare(int[] testIndices) { double expected = (sumRows[i] * sumCols[j]) / total; if (testType == TestType.CHI_SQUARE) { - double d = observed - expected; - _xSquare += (d * d) / expected; + if (expected == 0) { + throw new IllegalArgumentException("Total is zero."); + } + + if (expected > 0.0) { + double d = observed - expected; + _xSquare += (d * d) / expected; + } } else if (testType == TestType.G_SQUARE) { // The G-square test is a likelihood ratio test, so we need to take the log of the @@ -211,6 +215,7 @@ public Result calcChiSquare(int[] testIndices) { } int _df = (numNonZeroRows - 1) * (numNonZeroCols - 1); + if (_df == 0) _df = 1; xSquare += _xSquare; df += _df; } @@ -343,10 +348,10 @@ private CellTable getCellTable() { * included in the overall chi-square and degrees of freedom. Note that this should not be too small, or the * chi-square distribution will not be a good approximation to the distribution of the test statistic. * - * @param minSumRowOrCol The minimum number of counts per conditional table. + * @param minCountPerCell The minimum number of counts per conditional table. The default is 1; this must be >= 0. */ - public void setMinSumRowOrCol(int minSumRowOrCol) { - this.minSumRowOrCol = minSumRowOrCol; + public void setMinCountPerCell(double minCountPerCell) { + this.minCountPerCell = minCountPerCell; } /** diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestChiSquare.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestChiSquare.java index c4e3beedb3..854f6f1977 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestChiSquare.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestChiSquare.java @@ -73,7 +73,7 @@ public final class IndTestChiSquare implements IndependenceTest, RowsSettable { */ private int df; - private int minSumRowOrCol = 0; + private double minCountPerCell = 1.0; private boolean verbose; private List rows = null; @@ -102,7 +102,7 @@ public IndTestChiSquare(DataSet dataSet, double alpha) { this.variables = new ArrayList<>(dataSet.getVariables()); this.chiSquareTest = new ChiSquareTest(dataSet, alpha, ChiSquareTest.TestType.CHI_SQUARE); - this.chiSquareTest.setMinSumRowOrCol(minSumRowOrCol); + this.chiSquareTest.setMinCountPerCell(minCountPerCell); } /** @@ -348,16 +348,15 @@ private double getDeterminationP() { } /** - * The minimum number of counts per conditional table for chi-square expressed as a fraction of the total number of - * cells in the conditional table. Default is 2. Note that this should not be too small, or the chi-square - * distribution will not be a good approximation to the distribution of the test statistic. + * The minimum number of counts per conditional table for chi-square for that table and its degrees of freedom to be + * included in the overall chi-square and degrees of freedom. Note that this should not be too small, or the + * chi-square distribution will not be a good approximation to the distribution of the test statistic. * - * @param minSumRowOrCol The minimum number of counts per conditional table expressed as a fraction of the total - * number of cells in the conditional table. + * @param minCountPerCell The minimum number of counts per conditional table. The default is 1; this must be >= 0. */ - public void setMinSumRowOrCol(int minSumRowOrCol) { - this.minSumRowOrCol = minSumRowOrCol; - this.chiSquareTest.setMinSumRowOrCol(minSumRowOrCol); + public void setMinCountPerCell(double minCountPerCell) { + this.minCountPerCell = minCountPerCell; + this.chiSquareTest.setMinCountPerCell(minCountPerCell); } /** diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestGSquare.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestGSquare.java index 0691b81d03..a6881d5d8a 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestGSquare.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestGSquare.java @@ -76,7 +76,7 @@ public final class IndTestGSquare implements IndependenceTest, RowsSettable { */ private double determinationP = 0.99; private boolean verbose; - private int minSumRowOrCol; + private double minCountPerCell = 1.0; private List rows = null; /** @@ -104,7 +104,7 @@ public IndTestGSquare(DataSet dataSet, double alpha) { this.variables = new ArrayList<>(dataSet.getVariables()); this.gSquareTest = new ChiSquareTest(dataSet, alpha, ChiSquareTest.TestType.G_SQUARE); - this.gSquareTest.setMinSumRowOrCol(minSumRowOrCol); + this.gSquareTest.setMinCountPerCell(minCountPerCell); } /** @@ -345,16 +345,15 @@ public void setVerbose(boolean verbose) { } /** - * The minimum number of counts per conditional table for chi-square expressed as a fraction of the total number of - * cells in the conditional table. Default is 2. Note that this should not be too small, or the chi-square - * distribution will not be a good approximation to the distribution of the test statistic. + * The minimum number of counts per conditional table for chi-square for that table and its degrees of freedom to be + * included in the overall chi-square and degrees of freedom. Note that this should not be too small, or the + * chi-square distribution will not be a good approximation to the distribution of the test statistic. * - * @param minSumRowOrCol The minimum number of counts per conditional table expressed as a fraction of the total - * number of cells in the conditional table. + * @param minCountPerCell The minimum number of counts per conditional table. The default is 1; this must be >= 0. */ - public void setMinSumRowOrCol(int minSumRowOrCol) { - this.minSumRowOrCol = minSumRowOrCol; - this.gSquareTest.setMinSumRowOrCol(minSumRowOrCol); + public void setMinCountPerCell(double minCountPerCell) { + this.minCountPerCell = minCountPerCell; + this.gSquareTest.setMinCountPerCell(minCountPerCell); } /** diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/util/Params.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/util/Params.java index e786c780b0..f9319f919a 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/util/Params.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/util/Params.java @@ -254,7 +254,7 @@ public final class Params { public static final String REMOVE_EFFECT_NODES = "removeEffectNodes"; public static final String SAMPLE_STYLE = "sampleStyle"; public static final String NUM_THREADS = "numThreads"; - public static String MIN_SUM_ROW_OR_COL = "minSumRowOrCol"; + public static String MIN_COUNT_PER_CELL = "minCountPerCell"; // All parameters that are found in HTML manual documentation diff --git a/tetrad-lib/src/main/resources/docs/manual/index.html b/tetrad-lib/src/main/resources/docs/manual/index.html index 92896f836c..da0a180f38 100755 --- a/tetrad-lib/src/main/resources/docs/manual/index.html +++ b/tetrad-lib/src/main/resources/docs/manual/index.html @@ -6483,24 +6483,25 @@

      kciEpsilon

    minSumRowOrCol

    + id="minCountPerCell">minCountPerCell
      -
    • Short Description: - Minimum row or column sum in conditional tables. -
    • -
    • Long Description: - The minimum row or column sum for any conditional table, for any summand - used in the test. Default is zero. + class="minCountPerCell_list"> +
    • Short Description: + Minimum expected count per cell for nonempty Chi-Square tables.
    • +
    • Long Description: + The minimum count per cell in any nonempty conditional Chi-Square table + This is real-valued and must be > 0.0; the default is 1.0. No matter + what this value is, if a row is empty, it will be removed from the + table.
    • Default Value: 1
    • + id="minCountPerCell_default_value">1.0
    • Lower - Bound: 1
    • + Bound: 0.0
    • Upper Bound: 2147483647
    • + id="minCountPerCell_upper_bound">Infinity
    • Value Type: - Integer
    • + Double

    kernelType

    @@ -8544,9 +8545,9 @@

    stableFAS

    with about that number of parents. The prior structure weights are distributed according to a binomial distribution.
  • Default Value: 1.0
  • + id="structurePrior_default_value">0.0
  • Lower Bound: - 0
  • + 0.0
  • Upper Bound: 1.7976931348623157E308
  • From fab6122d28e749318f92afa9cb23e7ca9d8d4947 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Sun, 14 Jan 2024 12:21:57 -0500 Subject: [PATCH 063/163] Cleanup. --- .../cmu/tetrad/search/score/SemBicScore.java | 43 +++++++++---------- 1 file changed, 20 insertions(+), 23 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/SemBicScore.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/SemBicScore.java index 7b069f6634..b77be2bfbf 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/SemBicScore.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/SemBicScore.java @@ -42,29 +42,26 @@ import static org.apache.commons.math3.util.FastMath.log; /** - *

    Implements the linear, Gaussian BIC score, with a 'penalty discount' multiplier - * on the BIC penalty. The formula used for the score is BIC = 2L - ck ln n, where c is the penalty discount and L is - * the linear, Gaussian log likelihood--that is, the sum of the log likelihoods of the individual records, which are - * assumed to be i.i.d.

    - * - *

    For FGES, Chickering uses the standard linear, Gaussian BIC score, so we will - * for lack of a better reference give his paper:

    - * - *

    Chickering (2002) "Optimal structure identification with greedy search" - * Journal of Machine Learning Research.

    - * - *

    The version of the score due to Nandy et al. is given in this reference:

    - * - *

    Nandy, P., Hauser, A., & Maathuis, M. H. (2018). High-dimensional consistency - * in score-based and hybrid structure learning. The Annals of Statistics, 46(6A), 3151-3183.

    - * - *

    This score may be used anywhere though where a linear, Gaussian score is needed. - * Anectodally, the score is fairly robust to non-Gaussianity, though with some additional unfaithfulness over and above - * waht the score would give for Guassian data, a detriment that can be overcome to an extent by use a permutation - * algorithm such as SP, GRaSP, or BOSS

    - * - *

    As for all scores in Tetrad, higher scores mean more dependence, and negative - * scores indicate independence.

    + * Implements the linear, Gaussian BIC score, with a 'penalty discount' multiplier on the BIC penalty. The formula used + * for the score is BIC = 2L - ck ln n, where c is the penalty discount and L is the linear, Gaussian log + * likelihood--that is, the sum of the log likelihoods of the individual records, which are assumed to be i.i.d. + *

    + * For FGES, Chickering uses the standard linear, Gaussian BIC score, so we will for lack of a better reference give his + * paper: + *

    + * Chickering (2002) "Optimal structure identification with greedy search" Journal of Machine Learning Research. + *

    + * The version of the score due to Nandy et al. is given in this reference: + *

    + * Nandy, P., Hauser, A., & Maathuis, M. H. (2018). High-dimensional consistency in score-based and hybrid structure + * learning. The Annals of Statistics, 46(6A), 3151-3183. + *

    + * This score may be used anywhere though where a linear, Gaussian score is needed. Anectodally, the score is fairly + * robust to non-Gaussianity, though with some additional unfaithfulness over and above waht the score would give for + * Guassian data, a detriment that can be overcome to an extent by use a permutation algorithm such as SP, GRaSP, or + * BOSS. + *

    + * As for all scores in Tetrad, higher scores mean more dependence, and negative scores indicate independence. * * @author josephramsey * @see edu.cmu.tetrad.search.Fges From 04943eb234994a666a9dc2eaa5b8e7e11d316924 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Sun, 14 Jan 2024 12:29:07 -0500 Subject: [PATCH 064/163] Cleanup. --- .../cmu/tetrad/search/score/SemBicScore.java | 96 +++++++++++++++++-- 1 file changed, 88 insertions(+), 8 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/SemBicScore.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/SemBicScore.java index b77be2bfbf..45f1db7438 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/SemBicScore.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/SemBicScore.java @@ -144,6 +144,15 @@ public SemBicScore(DataSet dataSet, boolean precomputeCovariances) { this.logN = log(sampleSize); } + /** + * Returns the variance of the residual of the regression of the ith variable on its parents. + * + * @param i The index of the variable. + * @param parents The indices of the parents. + * @param covariances The covariance matrix. + * @param calculateRowSubsets True if row subsets should be calculated. + * @return The variance of the residual of the regression of the ith variable on its parents. + */ public static double getVarRy(int i, int[] parents, Matrix data, ICovarianceMatrix covariances, boolean calculateRowSubsets) throws SingularMatrixException { int[] all = SemBicScore.concat(i, parents); @@ -157,7 +166,7 @@ public static double getVarRy(int i, int[] parents, Matrix data, ICovarianceMatr } @NotNull - public static Matrix bStar(Matrix b) { + private static Matrix bStar(Matrix b) { Matrix byx = new Matrix(b.getNumRows() + 1, 1); byx.set(0, 0, 1); for (int j = 0; j < b.getNumRows(); j++) byx.set(j + 1, 0, -b.get(j, 0)); @@ -269,6 +278,8 @@ public double nandyBic(int x, int y, int[] z) { } /** + * Returns the score for the given node and its parents. + * * @param i The index of the node. * @param parents The indices of the node's parents. * @return The score, or NaN if the score cannot be calculated. @@ -306,30 +317,47 @@ public double localScore(int i, int... parents) { } } - -// private final Map, Double> cache = new ConcurrentHashMap<>(); - /** - * Specialized scoring method for a single parent. Used to speed up the effect edges search. + * Returns the multiplier on the penalty term for this score. + * + * @return The multiplier on the penalty term for this score. */ - - public double getPenaltyDiscount() { return this.penaltyDiscount; } + /** + * Sets the multiplier on the penalty term for this score. + * + * @param penaltyDiscount The multiplier on the penalty term for this score. + */ public void setPenaltyDiscount(double penaltyDiscount) { this.penaltyDiscount = penaltyDiscount; } + /** + * Returns the structure prior for this score. + * + * @return The structure prior for this score. + */ public double getStructurePrior() { return this.structurePrior; } + /** + * Sets the structure prior for this score. + * + * @param structurePrior The structure prior for this score. + */ public void setStructurePrior(double structurePrior) { this.structurePrior = structurePrior; } + /** + * Returns the covariance matrix. + * + * @return The covariance matrix. + */ public ICovarianceMatrix getCovariances() { return this.covariances; } @@ -342,32 +370,68 @@ private void setCovariances(ICovarianceMatrix covariances) { } + /** + * Returns the sample size. + * + * @return The sample size. + */ public int getSampleSize() { return this.sampleSize; } + /** + * Returns true if the given bump is an effect edge. + * + * @param bump The bump. + * @return True if the given bump is an effect edge. + */ @Override public boolean isEffectEdge(double bump) { return bump > 0; } + /** + * Returns the data model. + * + * @return The data model. + */ public DataModel getDataModel() { return this.dataModel; } + /** + * Returns true if verbose output should be sent to out. + * + * @return True if verbose output should be sent to out. + */ public boolean isVerbose() { return this.verbose; } + /** + * Sets whether verbose output should be sent to out. + * + * @param verbose True if verbose output should be sent to out. + */ public void setVerbose(boolean verbose) { this.verbose = verbose; } + /** + * Returns the variables of the covariance matrix. + * + * @return The variables of the covariance matrix. + */ @Override public List getVariables() { return new ArrayList<>(this.variables); } + /** + * Sets the variables of the covariance matrix. + * + * @param variables The variables of the covariance matrix. + */ public void setVariables(List variables) { if (this.covariances != null) { this.covariances.setVariables(variables); @@ -376,11 +440,23 @@ public void setVariables(List variables) { this.variables = variables; } + /** + * Returns the maximum degree of the score. + * + * @return The maximum degree of the score. + */ @Override public int getMaxDegree() { return (int) FastMath.ceil(log(this.sampleSize)); } + /** + * Returns true is the variables in z determine the variable y. + * + * @param z The set of nodes. + * @param y The node. + * @return True is the variables in z determine the variable y. + */ @Override public boolean determines(List z, Node y) { int i = this.variables.indexOf(y); @@ -401,7 +477,11 @@ public boolean determines(List z, Node y) { return false; } - // @Override + /** + * Returns the data model. + * + * @return The data model. + */ public DataModel getData() { return this.dataModel; } From 9e7a0710a6849ea92abfd45ceed1ed1a01052d40 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Sun, 14 Jan 2024 13:23:01 -0500 Subject: [PATCH 065/163] Cleaned up the manual according to complains from IntelliJ (spelling and such). --- .../src/main/resources/docs/manual/index.html | 454 +++++++----------- 1 file changed, 183 insertions(+), 271 deletions(-) diff --git a/tetrad-lib/src/main/resources/docs/manual/index.html b/tetrad-lib/src/main/resources/docs/manual/index.html index da0a180f38..6d57fab3e8 100755 --- a/tetrad-lib/src/main/resources/docs/manual/index.html +++ b/tetrad-lib/src/main/resources/docs/manual/index.html @@ -20,7 +20,7 @@

    Tetrad Manual

    -

    Last updated: 02/09/2023

    +

    Last updated: 1/14/2024

  • Loading an existing data set, restricting - potential models using your a priori causal knowledge, and searching for + potential models using your a-priori causal knowledge, and searching for a model that explains it using one of Tetrad’s causal search algorithms
  • Loading an existing causal graph and existing data set, and @@ -98,7 +98,7 @@

    In order to use a box, click on it in the sidebar, then click inside the workspace. This creates an empty box, which you can - instantiated by double-clicking. Most boxes have multiple options + be instantiated by double-clicking. Most boxes have multiple options available on instantiation, which will be explained in further detail in this manual.

    @@ -400,13 +400,13 @@

    Edges and Edge Type Frequencies

    At the bottom of the graph box, the Edges and Edge Type Frequencies section provides an accounting of every edge in the graph, and how certain Tetrad is of its type. The first three columns contain a - list, in text form, of all of the edges in the graph. The columns to the + list, in text form, of all the edges in the graph. The columns to the right are all blank in manually constructed graphs, user-loaded graphs, and graphs output by searches with default settings. They are only filled in for graphs that are output by searches performed with bootstrapping. In those cases, the fourth column will contain the percentage of bootstrap outputs in which the edge type between these two variables - matches the edge type in the final graph. All of the columns to the right + matches the edge type in the final graph. All the columns to the right contain the percentages of the bootstrap outputs that output each possible edge type.

    @@ -672,7 +672,7 @@

    Possible Child Boxes of the Parametric Model Box:

    Bayes Parametric Models

    A Bayes parametric model takes as input a DAG. Bayes PMs represent - causal structures in which all of the variables are categorical.

    + causal structures in which all the variables are categorical.

    Bayes PMs consist of three components: the graphical representation of the causal structure of the model; for each named @@ -711,7 +711,7 @@

    Bayes Parametric Models

    provided under the “Presets” tab on the right. If you choose one of these configurations, the number of categories associated with the current variable will automatically be changed to agree with the configuration - you have chosen. If you want all of the categories associated with a + you have chosen. If you want all the categories associated with a variable to have the same name with a number appended (e.g., x1, x2, x3), choose the “x1, x2, x3…” option under Presets.

    @@ -746,7 +746,7 @@

    SEM Parametric Models

    terms.

    To change a parameter’s name or starting value for estimation, - double click on the parameter in the window.

    + double-click on the parameter in the window.

    Generalized SEM Parametric Models

    @@ -785,11 +785,11 @@

    Generalized SEM Parametric Models

    in the IM box, a fixed value of each parameter will be selected according to the specified distribution.

    -

    To edit an expression or parameter, double click on it (in any +

    To edit an expression or parameter, double-click on it (in any tab). This will open up a window allowing you to change the function that defines the variable or distribution of the parameter.

    -

    For instance, if you double click on the expression next to X1 +

    For instance, if you double-click on the expression next to X1 (b1*X5+E_X1), the following window opens:

    @@ -834,7 +834,7 @@

    Generalized SEM Parametric Models

    product, with the dollar sign ($) functioning as a wild card. For example, in the image above, TSUM(NEW(b)*$) means that, for each parent variable of the variable in question, a new “b” will be created and - multiplied by the parent variable’s value, and then all of the products + multiplied by the parent variable’s value, and then all the products will be added together.

    @@ -909,15 +909,15 @@

    Bayes Instantiated Models

    on the variable in the graph or choose it from the drop-down menu on the right. You can manually set a given probability value by overwriting the text box. Be warned that changing the value in one cell will delete the - values in all of the other cells in the row. Since the values in any row - must sum to one, if all of the cells in a row but one are set, Tetrad + values in all the other cells in the row. Since the values in any row + must sum to one, if all the cells in a row but one are set, Tetrad will automatically change the value in the last cell to make the sum correct. For instance, in the above model, if you change the first row such that the probability that X5 = 0 is 0.5000 and the probability that X5 = 1 is 0.4000, the probability that X5 = 2 will automatically be set to 0.1000.

    -

    If you right click on a cell in the table (or two-finger click on +

    If you right-click on a cell in the table (or two-finger click on Macs), you can choose to randomize the probabilities in the row containing that cell, randomize the values in all incomplete rows in the table, randomize the entire table, or randomize the table of every @@ -952,7 +952,7 @@

    Dirichlet Instantiated Models

    three total (pseudo) data points in which X2=0 and X6=0. You can view the pseudocounts of any variable by clicking on it in the graph or choosing it from the drop-down menu at the top of the window. To edit the value of - a pseudocount, double click on it and overwrite it. The total count of a + a pseudocount, double-click on it and overwrite it. The total count of a row cannot be directly edited.

    From the pseudocounts, Tetrad determines the conditional @@ -997,9 +997,9 @@

    SEM Instantiated Models

    You can now manually edit the values of parameters in one of two - ways. Double clicking on the parameter in the graph will open up a small + ways. Double-clicking on the parameter in the graph will open up a small text box for you to overwrite. Or you can click on the Tabular Editor - tab, which will show all of the parameters in a table which you can edit. + tab, which will show all the parameters in a table which you can edit. The Tabular Editor tab of our SEM IM looks like this:

    @@ -1043,7 +1043,7 @@

    Standardized SEM Instantiated Models

    -

    To edit a parameter, double click on it. A slider will open at the +

    To edit a parameter, double-click on it. A slider will open at the bottom of the window (shown above for the edge parameter between X1 and X2). Click and drag the slider to change the value of the parameter, or enter the specific value you wish into the box. The value must stay @@ -1059,10 +1059,10 @@

    Standardized SEM Instantiated Models

    It is possible to make a SEM IM with a time lag graph, even with latent variables. This does not work for other types of models, such as - Bayes IM's or for mixed data (for which no IM is currently available-- + Bayes IMs or for mixed data (for which no IM is currently available-- though mixed data can be simulated in the Simulate box with an appropriate choice of simulation model). Standardization for time lag model - is not currently avialable.

    + is not currently available.

    The Implied Matrices tab works in the same way that it does in a normal SEM IM.

    @@ -1090,7 +1090,7 @@

    Generalized SEM Instantiated Models

    all variables and their formulae. You can change the cutoff point for long formulae by clicking Tools: Formula Cutoff.

    -

    If you double click on a formula in either the graph or the +

    If you double-click on a formula in either the graph or the Variables tab, you can change the value of the parameters in that formula.

    @@ -1144,8 +1144,8 @@

    Loading Data

    General Tabular Data

    -

    To load data, create a data box with no parent. When you double - click it, an empty data window will appear:

    +

    To load data, create a data box with no parent. When you double-click + it, an empty data window will appear:

    @@ -1185,7 +1185,7 @@

    General Tabular Data

    Metadata JSON File

    Metadata is optional in general data handling. But it can be very helpful if you want to overwrite the data - type of a given variable column. And the metadata MUST be a JSON file + type of given variable column. And the metadata MUST be a JSON file like the following example.

    @@ -1327,7 +1327,7 @@ 

    Handling Tabular Data with Interventional Variables

    `null`. The data type of each variable can either be discrete or continuous. We use a boolean flag to indicate the data type. From the above example, we only specified two domain variables in the metadata - JSON, any variables not specifed in the metadata will be treated as + JSON, any variables not specified in the metadata will be treated as domain variables.

    @@ -1401,10 +1401,10 @@

    Merge Deterministic Interventional Variables

    This option looks for pairs of interventional variables (currently only discrete variables) that are deterministic and merges them into one - combined variable. For domain variables that are fully determinised, + combined variable. For domain variables that are fully determined, we'll add an attribute to them. Later in the knowledge box (Edges and Tiers), all the interventional variables (both status and value - variables) and the fully-determinised domain variables will be + variables) and the fully-determined domain variables will be automatically put to top tier. And all other domain variables will be placed in the second tier.

    @@ -1488,7 +1488,7 @@

    Nonparanormal Transform

    Takes a continuous tabular data set and increases its Gaussianity, using a nonparanormal transformation to smooth the variables. (Note: This - operation increases only marginal Gaussanity, not the joint, and in + operation increases only marginal Gaussianity, not the joint, and in linear systems may eliminate information about higher moments that can aid in non-Gaussian orientation procedures.)

    @@ -1496,7 +1496,7 @@

    Convert to Residuals

    The input for this operation is a directed acyclic graph (DAG) and a data set. Tetrad performs a linear regression on each variable in the - data set with respect to all of the variables that the graph shows to be + data set with respect to all the variables that the graph shows to be its parents, and derives the error terms. The output data set contains only the error terms.

    @@ -1518,7 +1518,7 @@

    Replace Missing Values with Column Mode

    Replace Missing Values with Column Mean

    If you choose this operation, Tetrad will replace any missing - value markers with the average of all of the values in the column. + value markers with the average of all the values in the column. Replace Missing Values with Regression Predictions: If you choose this operation, Tetrad will perform a linear regression on the data in order to estimate the most likely value of any missing value.

    @@ -1633,7 +1633,7 @@

    Manually Editing Data

    cell contains the number 2) Tetrad will set every cell to the missing data marker.

    -

    Under the Tools tab, the Calculator tool allows you add and edit +

    Under the Tools tab, the Calculator tool allows you to add or edit relationships between variables in the graph. For more information on how the Calculator tool works, see “Manipulating Data” section above.

    @@ -1642,7 +1642,7 @@

    Data Information

    Under the Tools tab, there are options to view information about your data in several formats.

    -

    The Plot Matrix tool shows a grid of scatterplots and histograms for selected variables. +

    The Plot Matrix tool shows a grid of scatter plots and histograms for selected variables. This may be used for continuous, discrete, or mixtures of continuous and discrete data. To select which variables to include in the rows and columns of the grid, click the variable lists to the right of the tool. To select multiple variables in these lists, use the shift @@ -1662,7 +1662,7 @@

    Data Information

    Double-click on the magnified plot to return to the grid.

    The “Settings” menu contains some tools to control the output. One may add regression lines - to the scatterplots or select the number of bins to include in the histograms.

    + to the scatter plots or select the number of bins to include in the histograms.

    Finally, one may condition on ranges of variables or particular discrete values by selecting “Edit Conditioning Variables and Ranges.” This brings up a dialog that lets one @@ -1695,9 +1695,9 @@

    Estimator

    The estimator box takes as input a data box (or simulation box) and a parametric model box and estimates, tests, and outputs an - instantiated model for the data. With the exception of the EM Bayes + instantiated model for the data. Except for the EM Bayes estimator, Tetrad estimators do not accept missing values. If your data - set contains missing values, the missing values can interpolated or + set contains missing values, the missing values can be interpolated or removed using the data box. (Note that missing values are allowed in various Tetrad search procedures; see the section on the search box.)

    @@ -1784,13 +1784,13 @@

    SEM Estimates

    latent variables.

    Tetrad also provides two scores that can be used in estimation: - feasible generalized least squares (FGLS) and Full Information Maximum + feasible generalized the least squares (FGLS) and Full Information Maximum Likelihood (FML).

    If the graph for the SEM is a DAG, and we may assume that the SEM is linear with Gaussian error terms, we use multilinear regression to estimate coefficients and residual variances. Otherwise, we use a - standard maximum likelihoood fitting function (see Bollen, Structural + standard maximum likelihood fitting function (see Bollen, Structural Equations with Latent Variables, Wiley, 1989, pg. 107) to minimize the distance between (a) the covariance over the variables as implied by the coefficient and error covariance parameter values of the model and (b) @@ -1799,7 +1799,7 @@

    SEM Estimates

    minimized, yields the maximum likelihood estimation point in parameter space.

    -

    In either case, an Fml value may be obtained for the maximum +

    In either case, a Fml value may be obtained for the maximum likelihood point in parameter space, either by regression or by direct minimization of the Fml function itself. The value of Fml at this minimum (maximum likelihood) point, multiplied by N - 1 (where N is the sample @@ -1824,7 +1824,7 @@

    SEM Estimates

    values of the estimation.

    The Model Statistics tab provides the degrees of freedom, chi - square, p value, comparative fit index (CFI), root mean square error of + square, p value, comparative fit index (CFI), root-mean-square error of approximation (RMSEA) and BIC score of a test of the model. It should be noted that while these test statistics are standard, they are not in general correct. See Mathias Drton, 2009, Likelihood ratio tests and @@ -1835,16 +1835,6 @@

    SEM Estimates

    recommend multiple random restarts. The number of restarts can be set in the lower right hand corner of the Estimator Box. -

    - - - -

    Generalized Estimator

    A generalized graphical model may have non-linear relations and @@ -2013,8 +2003,8 @@

    Row Summing Exact Updater

    Junction Tree Exact Updater

    -

    The Junction Tree exact updater is a another exact learning - algroithm. Its window functions exactly as the approximate updater down, +

    The Junction Tree exact updater is another exact learning + algorithm. Its window functions exactly as the approximate updater down, with one exception: in “Multiple Variables” mode, you can see conditional as well as marginal probabilities.

    @@ -2142,7 +2132,7 @@

    Tiers

    -

    Tiers separate your variables into a time line. Variables in +

    Tiers separate your variables into a timeline. Variables in higher-numbered tiers occur later than variables in lower-numbered tiers, which gives Tetrad information about causation. For example, a variable in Tier 3 could not possibly be a cause of a variable in Tier 1.

    @@ -2159,7 +2149,7 @@

    Tiers

    would find and select variables X1 and X10.

    You can also limit the search such that edges from one tier only - are added to the next immediate tier e.g,. if Tier 1 "Can cause only next + are added to the next immediate tier e.g., if Tier 1 "Can cause only next tier" is checked then edges from variables in Tier 1 to variables in Tier 3 are forbidden.

    @@ -2314,7 +2304,7 @@
    Random Forward DAG
    Erdos Renyi DAG
    -

    This option creates a DAG by randomly adding edgew with a given edge +

    This option creates a DAG by randomly adding edges with a given edge probability. The graph is then oriented as a DAG by choosing a causal order.

    @@ -2555,7 +2545,7 @@

    Using the Search Box

    Choosing the correct algorithm for your needs is an important consideration. Tetrad provides over 30 search algorithms (and more are - added all of the time) each of which makes different assumptions about + added all the time) each of which makes different assumptions about the input data, uses different parameters, and produces different kinds of output. For instance, some algorithms produce Markov blankets or CPDAGs, and some produce full graphs; some algorithms work best with @@ -2600,10 +2590,10 @@

    Description

    sample should ideally be i.i.d.. Simulations show that PC and several of the other algorithms described here often succeed when these assumptions, needed to prove their correctness, do not strictly hold. - The PC algorithm will sometimes output double headed edges. In the - large sample limit, double headed edges in the output indicate that + The PC algorithm will sometimes output double-headed edges. In the + large sample limit, double-headed edges in the output indicate that the adjacent variables have an unrecorded common cause, but PC tends - to produce false positive double headed edges on small samples.

    + to produce false positive double-headed edges on small samples.

    The PC algorithm is correct whenever decision procedures for independence and conditional independence are available. The @@ -2621,7 +2611,7 @@

    Description

    and Search for details on tests). In either case, the tests require an alpha value for rejecting the null hypothesis, which can be adjusted by the user. The procedures make no adjustment for multiple - testing. (For PC, CPC, JPC, JCPC, FCI, all testing searches.)

    + testing. (For PC, CPC, FCI, all testing searches.)

    The PC algorithm as given in Causation, Prediction and Search (Spirtes, Glymour, and Scheines, 2000) comes with three heuristics designed @@ -2633,7 +2623,7 @@

    Description

    Causation, Prediction, and Search for more details for these heuristics.

    -

    Note: If one wants to analyze time series data using this algorithms, +

    Note: If one wants to analyze time series data using this algorithm, one may set the time lag parameter to a value greater than 0, which will automatically apply the time lag transform. The same goes for any algorithm that has this parameter available in the interface.

    @@ -2643,7 +2633,7 @@

    Description

    Input Assumptions

    The algorithm effectively takes conditional independence facts as - input. Thus it will work for any type of data for which a conditional + input. Thus, it will work for any type of data for which a conditional independence facts are known. In the interface, it will work for linear, Gaussian data (the Fisher Z test), discrete multinomial data the Chi Square test) and mixed multinomial/Gaussian data (the Conditional @@ -2653,12 +2643,12 @@

    Output Format

    The graph outputs a CPDAG. This is an equivalence class of directed acyclic graphs (DAGs). Each DAG in the equivalence class has all - of the adjacencies (and no more) of the CPDAG. Each oriented edge in the + the adjacencies (and no more) of the CPDAG. Each oriented edge in the CPDAG is so oriented in each of the DAG in the equivalence class. Unoriented edges in the equivalence class cannot be oriented by conditional independence facts. For example, if the model is X->Y->Z, the - output will be X—Y—Z. There are not collider in this model, so the - algorithm will not detect one. Since there are not colliders, the Meek + output will be X—Y—Z. There are no collider in this model, so the + algorithm will not detect one. Since there are no colliders, the Meek cannot orient additional edges. If the model were X<-Y<-Z, the output would also be X—Y—Z; this model is in the same equivalence class as X->Y->Z. The model X->Y<-Z would be its own equivalence class, since the @@ -2708,9 +2698,9 @@

    Description

    and Search for details on tests). In either case, the tests require an alpha value for rejecting the null hypothesis, which can be adjusted by the user. The procedures make no adjustment for multiple - testing. (For PC, CPC, JPC, JCPC, FCI, all testing searches.)

    + testing. (For PC, CPC, FCI, all testing searches.)

    -

    Note: If one wants to analyze time series data using this algorithms, +

    Note: If one wants to analyze time series data using this algorithm, one may set the time lag parameter to a value greater than 0, which will automatically apply the time lag transform. The same goes for any algorithm that has this parameter available in the interface.

    @@ -2756,7 +2746,7 @@

    Description

    or orient as a collider, arbitrarily. This guarantees that the resulting graph will be a CPDAG.

    -

    Note: If one wants to analyze time series data using this algorithms, +

    Note: If one wants to analyze time series data using this algorithm, one may set the time lag parameter to a value greater than 0, which will automatically apply the time lag transform. The same goes for any algorithm that has this parameter available in the interface.

    @@ -2788,7 +2778,7 @@

    Description

    developed by Meek [Meek, 1997] called the Greedy Equivalence Search (GES). The algorithm was further developed and studied by Chickering [Chickering, 2002]. GES is a Bayesian algorithm that heuristically - searches the space of CBNs and returns the model with highest + searches the space of CBNs and returns the model with the highest Bayesian score it finds. In particular, GES starts its search with the empty graph. It then performs a forward stepping search in which edges are added between nodes in order to increase the Bayesian @@ -2802,7 +2792,7 @@

    Description

    user-documentation-7_20_2016-sample-size.pdf">here. The reference is Ramsey et al., 2017.

    -

    The algorithms requires a decomposable score—that is, a score +

    The algorithm requires a decomposable score—that is, a score that for the entire DAG model is a sum of logged scores of each variables given its parents in the model. The algorithms can take all continuous data (using the SEM BIC score), all discrete data (using @@ -2810,7 +2800,7 @@

    Description

    the Conditional Gaussian score); these are all decomposable scores.

    -

    Note: If one wants to analyze time series data using this algorithms, +

    Note: If one wants to analyze time series data using this algorithm, one may set the time lag parameter to a value greater than 0, which will automatically apply the time lag transform. The same goes for any algorithm that has this parameter available in the interface.

    @@ -2837,55 +2827,6 @@

    Output Format

    A CPDAG, same as PC.

    - -

    Parameters

    - -

    samplePrior, structurePrior, penaltyDiscount, symmetricFirstStep, faithfulnessAssumed, maxDegree, parallelized, - verbose meekVerbose

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    The IMaGES Algorithm

    - -

    Description

    -

    Adjusts the selected score for FGES so @@ -2907,7 +2848,7 @@

    Output Format

    Parameters

    -

    All of the parameters from FGES are available for IMaGES. +

    All the parameters from FGES are available for IMaGES. Additionally:

    numRuns, Description

    subset of the observed variables; any conditioning set that leads to the removal of an adjacency is stored. After the adjacency phase, the resulting undirected graph has the correct set of adjacencies, but - all of the edges are unoriented. FCI then enters an orientation phase + all the edges are unoriented. FCI then enters an orientation phase that uses the stored conditioning sets that led to the removal of adjacencies to orient as many of the edges as possible. See [Spirtes, 1993].

    -

    Note: If one wants to analyze time series data using this algorithms, +

    Note: If one wants to analyze time series data using this algorithm, one may set the time lag parameter to a value greater than 0, which will automatically apply the time lag transform. The same goes for any algorithm that has this parameter available in the interface.

    @@ -2957,7 +2898,7 @@

    Output Format

    Parameters

    -

    All of the parameters from FCI are below.

    +

    All the parameters from FCI are below.

    depth, maxPathLength, Description

    The FCI-Max algorithm simply changes the first collider orientation rule in FCI to use the PC-Max orientation.

    -

    Note: If one wants to analyze time series data using this algorithms, +

    Note: If one wants to analyze time series data using this algorithm, one may set the time lag parameter to a value greater than 0, which will automatically apply the time lag transform. The same goes for any algorithm that has this parameter available in the interface.

    @@ -2990,7 +2931,7 @@

    Output Format

    Parameters

    -

    All of the parameters from FCI are below.

    +

    All the parameters from FCI are below.

    depth, maxPathLength, Description slow in some steps) and is almost as informative. See Colombo et al., 2012.

    -

    Note: If one wants to analyze time series data using this algorithms, +

    Note: If one wants to analyze time series data using this algorithm, one may set the time lag parameter to a value greater than 0, which will automatically apply the time lag transform. The same goes for any algorithm that has this parameter available in the interface.

    @@ -3027,7 +2968,7 @@

    Output Format

    Parameters

    -

    All of the parameters from FCI are available for RFCI. +

    All the parameters from FCI are available for RFCI. Additionally:

    depth, Description

    A modification of the RFCI algorithm which does probabilistic bootstrap sampling with respect to the RFCI PAG output.For discrete data only. Parameters are: (a) Number of search probabilistic models, (b) boostrap - ensemble method to use (see bootstrapping), (c) maximimum size of + ensemble method to use (see bootstrapping), (c) maximum size of conditioning set (depth), (d) maximum length of any discriminating path (a property for RFCI). This must use the probabilistic test, which must be selected. Parameters for the probabilistic test are (d) independence cutoff threshold, default 0.5, (e) prior equivalent sample size, and (f) whether the cutoff in (d) is used in the independence test calculation; - if not, then a coin flip is used (probaility 0.5). + if not, then a coin flip is used (probability 0.5).

  • @@ -3089,7 +3030,7 @@

    Description

    href="https://www.ccd.pitt.edu//wp-content/uploads/2018/10/GFCIc- overview-11_22_2016.pdf">here (continuous variables)
    .

    -

    Note: If one wants to analyze time series data using this algorithms, +

    Note: If one wants to analyze time series data using this algorithm, one may set the time lag parameter to a value greater than 0, which will automatically apply the time lag transform. The same goes for any algorithm that has this parameter available in the interface.

    @@ -3118,16 +3059,16 @@

    Description

    GRaSP-FCI is wrapper around the GRaSP algorithm that replaces - the FGES step in GFCI with the more accurate GRaSP algrorithm, which + the FGES step in GFCI with the more accurate GRaSP algorithm, which reasons by considering permutations of variables. The second collider - orienatation step in GFCI is also done using permutation reasoning, + orientation step in GFCI is also done using permutation reasoning, leaving the discriminating path rule as the only rule that requires a "raw" conditional independence judgment. Ultimately this independence judgment can be decided using the same scoring apparatus as the other - permutation steps, so ultimatly GRaSP-FCI can be treated as a scoring + permutation steps, so ultimately GRaSP-FCI can be treated as a scoring algorithm.

    -

    Note: If one wants to analyze time series data using this algorithms, +

    Note: If one wants to analyze time series data using this algorithm, one may set the time lag parameter to a value greater than 0, which will automatically apply the time lag transform. The same goes for any algorithm that has this parameter available in the interface.

    @@ -3154,7 +3095,7 @@

    Description

    SP-FCI is wrapper around the SP algorithm that replaces - the FGES step in GFCI with the more accurate SP algrorithm, which + the FGES step in GFCI with the more accurate SP algorithm, which reasons by considering permutations of variables. This uses the same method for wrapping SP with an FCI method similar to GFCI as GRaSP-FCI. The difference is that SP considers every permutation @@ -3162,7 +3103,7 @@

    Description

    can only be used for very small models, of up to about 8 or 9 variables, because of the super-exponential step of considering every permutation of the variables. The second collider - orienatation step in GFCI is done using permutation reasoning, + orientation step in GFCI is done using permutation reasoning, leaving the discriminating path rule as the only rule that requires a "raw" conditional independence judgment. Ultimately this independence judgment can be decided using the same scoring apparatus as the other @@ -3205,7 +3146,7 @@

    Description

    with the above naming convention. The new sample size will be the old sample size minus n.

    -

    Since this algorithms specifically requires time series data, +

    Since this algorithm specifically requires time series data, one must set the time lag parameter to a value greater than 0, which will automatically apply the time lag transform.

    @@ -3251,7 +3192,7 @@

    Description

    is removed as the result of a score increase, all similar (or “homologous”) edges are also removed.

    -

    Since this algorithms specifically requires time series data, +

    Since this algorithm specifically requires time series data, one must set the time lag parameter to a value greater than 0, which will automatically apply the time lag transform.

    @@ -3332,7 +3273,7 @@

    Description

    targets. In the interface, just one target may be specified. See Ramsey et al., 2017 for details. In the general case, finding the graph over the Markov blanket variables of a target (including the - target) is far faster than finding the CPDAG for all of the + target) is far faster than finding the CPDAG for all the variables.

    @@ -3478,7 +3419,6 @@

    Parameters

    href="#graspNonSingularDepth">graspNonSingularDepth graspSingularDepth graspOrderedAlg graspUseVermaPearl verbose numStarts

    @@ -3509,7 +3449,7 @@

    Description

    graspNonsingularDepth - This controls the depth at which nonsingular tucks are explored.

    graspSingularDepth - - This controls the depth at which singlular tucks are considered. + - This controls the depth at which singular tucks are considered.

    numRestarts - By default 1; if > 1, additional random restarts are done, and the best of these results is returned. @@ -3517,9 +3457,9 @@

    Description

    to singular depth 0, nonsingular depth 0. ESP corresponds to singular depth > 0, nonsingular depth = 0. GRaSP corresponds to singular depth > 0, nonsingular depth > 0. In each case, an ordering option is available - to find best permutations from lower levels before proceeding to + to find the best permutations from lower levels before proceeding to higher levels. -

    The algorithms works by building DAGs given +

    The algorithm works by building DAGs given permutations in ways similar to those described in Raskutti and Uhler (ref?) and Solus et al. Two ways of building DAGs are considered, one independence-based, due to Raskutti and Uhler and a score-based @@ -3539,7 +3479,6 @@

    Description

    Raskutti, G., & Uhler, C. (2018). Learning directed acyclic graph models based on sparsest permutations. Stat, 7(1), -

    Solus, L., Wang, Y., Matejovicova, L., & Uhler, C. (2017). Consistency guarantees for permutation-based causal inference algorithms. arXiv @@ -3565,7 +3504,6 @@

    Parameters

    href="#graspNonSingularDepth">graspNonSingularDepth graspSingularDepth graspOrderedAlg graspUseVermaPearl verbose numStarts

    @@ -3580,7 +3518,7 @@

    Description

    generalizes and extends the GSP (Greedy Sparsest Permutation) algorithm. It has been tested to 1000 variables with an average degree of 20 and gives near perfect precisions and recalls for N = 10,000 (with - recall that drop to 0.9 for N = 1000). The algorithms works by building DAGs given + recall that drop to 0.9 for N = 1000). The algorithm works by building DAGs given permutations in ways similar to those described in Raskutti and Uhler (ref?) and Solus et al.

    The parameters are as @@ -3588,14 +3526,14 @@

    Description

    useBes - True if the final BES (Backward Equivalence Search) step is used from the GES (Greedy Equivalence Search) algorithm. This step is needed for correctness but for large models, since usually - nearly all edges are oriented in the CPDAG, it is heurically not needed.

    -

    numStarts - The number of times the algroithm should be re-run from different + nearly all edges are oriented in the CPDAG, it is heuristically not needed.

    +

    numStarts - The number of times the algorithm should be re-run from different random starting permutations. The model with the most optimal BIC score will be selected.

    allowInternalRandomness - If true, the algorithm allow the algorithm to use certain heuristic random steps. This can improve performance, but may make the algorithm non-deterministic.

    -

    timeLag - This creates a time-series model autimatically with a certain +

    timeLag - This creates a time-series model automatically with a certain number of lags.

    Knowledge of forbidden edges and required edges may be used with this algorithm. Also, knowledge of tiers may be used. If tiered knowledge is @@ -3632,7 +3570,6 @@

    Parameters

    href="#graspNonSingularDepth">graspNonSingularDepth graspSingularDepth graspOrderedAlg graspUseVermaPearl verbose numStarts

    @@ -3644,7 +3581,7 @@

    Parameters

    @@ -3686,7 +3623,7 @@

    Description

    matrix over the latent variables that are parents of the measures and use some algorithm such as PC or GES to estimate a CPDAG over the latents. The algorithm to run PC or GES on this covariance matrix is - called MimBuild (“MIM” is the the graph, Multiple Indicator Model; + called MimBuild (“MIM” is the graph, Multiple Indicator Model; “Build” means build). In this way, one may recover causal structure over the latents. The more measures one has for each latent, the better the result is, generally. The larger the sample size the @@ -3754,7 +3691,7 @@

    Description

    relevant tetrad constraints still hold. There are different ways of going about this. One could try to build one cluster up as far as possible, then remove all of those variables from the set, and try to - make a another cluster using the remaining variables (SAG, Seed and + make another cluster using the remaining variables (SAG, Seed and Grow). Or one can try in parallel to grow all possible clusters and then choose among the grown clusters using some criterion such as cluster size (GAP, Grow and Pick). In general, GAP is more accurate. @@ -3775,8 +3712,8 @@

    Description

    variables. The algorithm will in effect remove one measure in each impure pair from consideration. - Note that for FOFC, a test is done for each final cluster as - to whether the variables in teh cluster are all mutually + Note that for FOFC, a test is done for each final cluster to see + whether the variables in the cluster are all mutually dependent. In the interface, in order to see teh results of this test, one needs to open the logging window. See the Logging menu.

    @@ -3791,11 +3728,11 @@

    Description

    FTFC (Find Two Factor Clusters) is similar to FOFC, but instead of each cluster having one latent that is the parent of all - of the measure in the cluster, it instead has two such latents. So + the measure in the cluster, it instead has two such latents. So each measure has two latent parents; these are two “factors.” Similarly to FOFC, constraints are checked for, but in this case, the constraints must be sextad constraints, and more of them must be - satisfied for each pure cluster (see Kummerfelt et al., 2014). Thus, + satisfied for each pure cluster (see Kummerfeld et al., 2014). Thus, the number of measures in each cluster, once impure edges have been taken into account, must be at least six, preferably more.

    @@ -3844,7 +3781,7 @@

    Description

    Our implementation of LiNGAM has one parameter, penalty discount, used for the FGES adjacency search. The method as implemented does not scale much beyond 10 variables, because it is - checking every permutation of all of the variables (twice). The + checking every permutation of all the variables (twice). The implementation of ICA we use is FastIca (Hyvärinen et al., 2004).

    @@ -3855,7 +3792,7 @@

    Description

    Hyvärinen, A., Karhunen, J., & Oja, E. (2004). Independent component analysis (Vol. 46). John Wiley & Sons.

    -

    Direct LiNGAM is an implemention of said algorithms as specified in this reference:

    +

    Direct LiNGAM is an implementation of said algorithms as specified in this reference:

    Shimizu, S., Inazumi, T., Sogawa, Y., Hyvarinen, A., Kawahara, Y., Washio, T., ... & Hoyer, P. (2011). DirectLiNGAM: A direct method for learning a linear non-Gaussian structural equation model. Journal of @@ -3868,7 +3805,7 @@

    The FASK Algorithm

    Description

    -

    FASK learns a linear model in which all of the +

    FASK learns a linear model in which all the variables are skewed.

    The idea is as follows. First, FAS-stable is run on the data, @@ -3928,7 +3865,7 @@

    Description

    FASK-Vote is a metascript that learns a model from a list of datasets in a method similar to IMaGES (see). For adjacencies, it uses FAS-Stable with the voting-based score from IMaGES - used as a test (using all of the datasets, standardized), producing a + used as a test (using all the datasets, standardized), producing a single undirected graph G. It then orients each edge X--Y in G for each dataset using the FASK (see) left-right rule and orient X->Y if that rule orients X--Y as such in at least half of the datasets. The final graph is @@ -4023,7 +3960,7 @@

    Input Assumptions

    Output Format

    -

    Orients all of the edges in the input graph using the selected +

    Orients all the edges in the input graph using the selected score.

    Parameters

    @@ -4047,7 +3984,7 @@

    Description

    The procedure is best used, however, as a command line procedure, in py-causal, rpy-causal, or Causal Command. Upon running the algorithm (even in the interface), a directory of result files will be produced as - a record, including the dataset used, the possible causes and effects used, all of the CPDAGs used and + a record, including the dataset used, the possible causes and effects used, all the CPDAGs used and the tables of their IDA effects, and the CStaR output table itself.

    @@ -4062,8 +3999,8 @@

    Description

    If a directory already exists at the path, then any information available in path directory will be used to generate results in the path-.[n] directory.

    -

    Number of Subsamples. CStaR finds CPDAGs over subsampled data of size n / 2; this specifies how many - subsamples to use.

    +

    Number of Sub-samples. CStaR finds CPDAGs over sub-sampled data of size n / 2; this specifies how many + sub-samples to use.

    Minimum effect size. This allows a shorter table to be produced. It this is set to a value m > 0, then only records with PI > m will be displayed.

    @@ -4111,7 +4048,7 @@

    Input Assumptions

    Statistical Tests

    -

    All of the below tests do testwise deletion as a default way of +

    All the below tests do testwise deletion as a default way of dealing with missing values. For testwise deletion, if a test, say, I(X, Y | Z), is done, columns for X, Y, and Z are scanned for missing values. If any row occurs in which X, Y, or Z is missing, that row is deleted @@ -4138,11 +4075,6 @@

    BDeu Test

    subtracted, in that order. If the difference is negative, independence is inferred.

    -

    Parameters

    - -

    equivalentSamplelSize, structurePrior

    -

    Fisher Z Test

    Fisher Z judges independence if the @@ -4177,7 +4109,7 @@

    Generalized Information Criterion Scores

    based on the paper, Kim, Y., Kwon, S., & Choi, H. (2012). Consistent model selection criteria on high dimensions. The Journal 0of Machine Learning Research, 13(1), 1037-1057. One needs to select which lambda to use in place of the - usual lambda for the linear, Gaussian BIC score. An penalty discount parameter + usual lambda for the linear, Gaussian BIC score. A penalty discount parameter may also be specified, though this is by default for these scores equal to 1 (since the lambda choice is essentially picking a penalty discount for you). @@ -4220,7 +4152,7 @@

    Conditional Correlation Independence (CCI) Test

    to a (possibly nonlinear) function of its parents, plus some additive noise, where the noise may be arbitrarily distributed. That is, X = f(parent(X)) + E, where f is any function and E is noise however - distributed; the only requirement is that thre be the “+” in the formula + distributed; the only requirement is that there be the “+” in the formula separating the function from the noise. The noise can’t for instance, be multiplicative, e.g., X = f(parent(X)) x E. The goal of the method is to estimate whether X is independent of Y given variables Z, for some X, Y, @@ -4260,7 +4192,7 @@

    M-Separation Test

    property of graphs, not distributions. It's not really a test, but it can be used in place of a test of the true graph is known. This is a way to find out, for constraint-based algorithms, or even for some score-based - algorithms like FGES, what answer the algorithm would give if all of the + algorithms like FGES, what answer the algorithm would give if all the statistical decisions made are correct. Just draw an edge from the true graph to the algorithm--the m-separation option will appear, and you can then just run the search as usual. Note that D-Separation and M-separation @@ -4320,7 +4252,7 @@

    Kernel Conditional Independence (KCI) Test

    Parameters

    alpha, kciUseAppromation, kciUseApproximation, kernelMultiplier, kciNumBootstraps, thresholdForNumEigenvalues, Conditional Gaussian Likelihood Ratio Test Gaussian conditional on each combination of values for the discrete variables, though it will work fairly well even if that assumption does not hold strictly. This test may be used with any constraint-based - algorithm (PC, FCI, etc.). See See Andrews, B., Ramsey, J., & Cooper, G. + algorithm (PC, FCI, etc.). See Andrews, B., Ramsey, J., & Cooper, G. F. (2018). Scoring Bayesian networks of mixed variables. International journal of data science and analytics, 6(1), 3-18.

    Degenerate Gaussian Likelihood Ratio Test may be used for the case where there is a mixture of discrete and - Gaussian variables. Calculates a a likelihood ratio based on likelihood + Gaussian variables. Calculates a likelihood ratio based on likelihood that is calculated using a conditional Gaussian assumption. See Andrews, B., Ramsey, J., & Cooper, G. F. (2019). Learning high-dimensional directed acyclic graphs with mixed data-types. Proceedings of machine @@ -4362,7 +4294,7 @@

    Resampling

    is available on the Set Parameters screen. When it is selected, the search will be performed multiple times on randomly selected subsets of the data, and the final output graph will be the result of a voting - procedure among all of the graphs. These subsets may be selected with + procedure among all the graphs. These subsets may be selected with replacement (bootstrapping) or without. There are also options for the user to set the size of the subset, and the number of resampling runs. The default number of resampling runs is zero, in which case no @@ -4396,12 +4328,12 @@

    Resampling

    there are three columns. These are to capture various types of --> edges that may be found in estimated PAGs--whether the --> edge is visible and/or definitely direct. For estimated CPDAGs, these three columns may be summed. - Similarly for <-- edges. + Similarly, for <-- edges.

    Scoring Functions

    -

    Like the tests, above, all of the below tests do testwise deletion +

    Like the tests, above, all the below tests do testwise deletion as a default way of dealing with missing values. For testwise deletion, if a score, say, score(X | Y, Z), is done, columns for X, Y, and Z are scanned for missing values. If any row occurs in which X, Y, or Z is @@ -4426,9 +4358,6 @@

    BDeu Score

    Parameters

    -

    equivalentSampleSize, samplePrior

    -

    Conditional Gaussian BIC Score

    Conditional Gaussian BIC Score may be @@ -4533,7 +4462,7 @@

    GIC Scores

    the paper, Kim, Y., Kwon, S., & Choi, H. (2012). Consistent model selection criteria on high dimensions. The Journal 0of Machine Learning Research, 13(1), 1037-1057. One needs to select which lambda to use in place of the - usual lambda for the linear, Gaussian BIC score. An penalty discount parameter + usual lambda for the linear, Gaussian BIC score. A penalty discount parameter may also be specified, though this is by default for these scores equal to 1 (since the lambda choice is essentially picking a penalty discount for you). @@ -4822,7 +4751,7 @@

    alpha

    0.0)
  • Long Description: The cutoff, beyond which test results are judged as dependent, for a - statistical test of independence. Detaulf 0.05. Higher alpha yields a + statistical test of independence. Default 0.05. Higher alpha yields a sparser graph.
  • Default Value: 0.01
  • @@ -4970,7 +4899,7 @@

    coefLow

    id="coefLow_short_desc"> Low end of coefficient range (min = 0.0)
  • Long Description: - The parameter m1 for coefficents drawn from U(-m2, -m1) U U(m1, + The parameter m1 for coefficients drawn from U(-m2, -m1) U U(m1, m2).
  • Default Value: 0.0
  • @@ -5269,20 +5198,20 @@

    topBracket

numSubsamples

-
    -
  • Short Description: Number of - subsamples
  • + id="numSub-samples">numSub-samples +
      +
    • Short Description: Number of + sub-samples
    • Long Description: Number of subsamples
    • + id="numSub-samples_long_desc">Number of sub-samples
    • Default Value: 50
    • + id="numSub-samples_default_value">50
    • Lower Bound: - 1
    • + 1
    • Upper Bound: - 500000
    • + 500000
    • Value - Type: Integer
    • + Type: Integer

    covHigh

    @@ -5447,7 +5376,7 @@

    depth

    class="parameter_description_list">
  • Short Description: Threshold for judging a - regression of a variable onto its parents to be deternimistic (min = + regression of a variable onto its parents to be deterministic (min = 0.0)
  • Long Description: When regressing a child variable @@ -5509,7 +5438,7 @@

    discretize

  • Long Description: Yes if for the conditional Gaussian likelihood, when scoring X->D where X is continuous and D discrete, - one shoudl to simply discretize X for just those cases. If no, the + one should to simply discretize X for just those cases. If no, the integration will be exact.
  • Default Value: true
  • @@ -5531,7 +5460,7 @@

    discretize

  • Long Description: The generalized information criterion is defined with an information term that take a - Euclidean norm squares; the can be calculated directly.
  • + Euclidean norm squares; there can be calculated directly.
  • Default Value: false
  • Lower @@ -6273,7 +6202,7 @@

    ia

    • Short Description: Interval beween shocks (R. A. + id="intervalBetweenShocks_short_desc"> Interval between shocks (R. A. Fisher simulation model) (min = 1)
    • Long Description: This is a parameter for @@ -6417,25 +6346,25 @@

      kciEpsilon

    kciUseAppromation

    + id="kciUseApproximation">kciUseApproximation
    • Short Description: Use the approximate Gamma + id="kciUseApproximation_short_desc">Use the approximate Gamma approximation algorithm
    • Long Description: Referring to Zhang, K., Peters, J., + id="kciUseApproximation_long_desc"> Referring to Zhang, K., Peters, J., Janzing, D., & Schölkopf, B. (2012), if this parameter is set to ‘Yes’, the Gamma approximation algorithm is used; if no, the exact procedure is used.
    • Default Value: true
    • + id="kciUseApproximation_default_value">true
    • Lower - Bound:
    • + Bound:
    • Upper Bound:
    • + id="kciUseApproximation_upper_bound">
    • Value Type: Boolean
    • + id="kciUseApproximation_value_type">Boolean

    kciEpsilon

    class="parameter_description_list">
  • Short Description: Bowman and Azzalini (1997) default - kernel bandwidhts should be multiplied by...
  • + kernel bandwidths should be multiplied by...
  • Long Description: For the conditional correlation algorithm. Bowman, A. W., & Azzalini, A. @@ -6510,7 +6439,7 @@

    kernelType

    id="kernelType_short_desc">Kernel type (1 = Gaussian, 2 = Epinechnikov)
  • Long Description: For CCI, this determine which kernel type + id="kernelType_long_desc"> For CCI, this determines which kernel type will be used (1 = Gaussian, 2 = Epinechnikov).
  • Default Value: 2
  • Lower Bound: 1
  • @@ -6704,7 +6633,7 @@

    zsMaxIndegree

    algorithm should go through orienting edges
  • Long Description: In orienting, this - algorith may go through a number of iterations, conditioning on more + algorithm may go through a number of iterations, conditioning on more and more variables until orientations are set. This sets that number.
  • Default Value: meanLow
  • Long Description: If the value is greater than zero, independent Gaussian noise will be added with mean zero and the - given variance to each variables in the simulated output. + given variance to each variable in the simulated output.
  • Default Value: 0.0
  • @@ -7008,7 +6937,7 @@

    mgmParam3

    • Short Description: Yes, if use the + id="noRandomlyDeterminedIndependence_short_desc"> Yes, if using the cutoff threshold for the independence test.
    • Long Description: mgmParam3
    • Long Description: In case the exact algorithm is not used for discrete children and continuous parents is not used, - the This parameter gives the number of categories to use for this + this parameter gives the number of categories to use for this second (discretize) backup copy of the continuous variables.
    • Default Value: numLatents id="numLatents_short_desc">Number of additional latent variables (min = 0)
    • Long Description: Thye numbger of additional latent + id="numLatents_long_desc"> The number of additional latent variables to include in the datasets
    • Default Value: 0
    • @@ -7237,7 +7166,7 @@

      probRemoveColumn

      edges
    • Long Description: This is a parameter for generating - random multiple indictor models (MIMs). A structural edge is an edge + random multiple indicator models (MIMs). A structural edge is an edge connecting two structural nodes.
    • Default Value: 3
    • @@ -7260,7 +7189,7 @@

      probRemoveColumn

      nodes
    • Long Description: This is a parameter for generating - random multiple indictor models (MIMs). A structural node is one of + random multiple indicator models (MIMs). A structural node is one of the latent variables in the model; each structural node has a number of child measured variables.
    • Default Value: numStarts first (default 1)
    • Long Description: The number of times the algorithm should - srarted from different initializations. By default, the algorithm + be started from different initializations. By default, the algorithm will be run through at least once using the initialized parameters (zero random restarts).
    • Default Value: useBes

    graspBreakAFterImprovement

    + id="graspBreakAfterImprovement">graspBreakAfterImprovement
    • Short Description: Yes if depth first search + id="graspBreakAfterImprovement_short_desc"> Yes if depth first search returns after first improvement, No for depth first traversal.
    • Long Description: Exploring the full list in + id="graspBreakAfterImprovement_long_desc"> Exploring the full list in every DFS call is equivalent to what we've been calling the Random Carnival Game procedure (RCG).
    • Default Value: true
    • + id="graspBreakAfterImprovement_default_value">true
    • Lower Bound:
    • + id="graspBreakAfterImprovement_lower_bound">
    • Upper - Bound:
    • + Bound:
    • Value Type: Boolean
    • + id="graspBreakAfterImprovement_value_type">Boolean

    graspDepth

    tucks
  • Long Description: This is the depth of recursion - at which multiple tucks may be consdidered per score improvement + at which multiple tucks may be considered per score improvement
  • Default Value: 1
  • @@ -7669,7 +7598,7 @@

    timeout

    id="timeout_short_desc">Timeout (best graph returned, -1 = no timeout)
  • Long Description: The algorithm will timeout at approximately + id="timeout_long_desc"> The algorithm will time out at approximately this number of seconds from when it started and return the final graph found at that point.
  • Default Value: precomputeCovarianc be precomputed for tubular continuous data
  • Long Description: - For more than 5000 variables or so, set this to false to calculate covariances + For more than 5000 variables or so, set this to false in order to calculate covariances on the fly from data.
  • Default Value: @@ -8071,7 +8000,7 @@

    probCycle

    in the graph (0 - 1)
  • Long Description: Any edge X*-*Y may be replaced with a - 2-cycle (feedback loop) between X and Y with this probility. + 2-cycle (feedback loop) between X and Y with this probability.
  • Default Value: 0.0
  • @@ -8110,7 +8039,7 @@

    probCycle

    class="parameter_description_list">
  • Short Description: Yes if the order of the columns in - each datasets should be randomized
  • + each dataset should be randomized
  • Long Description: In the real world where unfaithfulness is an issue the order of variables in the data may for @@ -8174,8 +8103,8 @@

    probCycle

    id="resamplingEnsemble_short_desc">Ensemble method: Preserved (1), Highest (2), Majority (3)
  • Long Description: Preserved = keep highest frequency - edges; Highest = keep highest frequency edges but ignore the no edge + id="resamplingEnsemble_long_desc"> Preserved = keep the highest frequency + edges; Highest = keep the highest frequency edges but ignore the no edge case if maximal; Majority = keep edges only if their frequency is greater than 0.5.
  • Default Value: sampleSize
  • Short Description: Sample size (min = 1)
  • Long - Description: Ddetermines now many + Description: Determines now many records should be generated for the data. The minimum number of records is 1; the default is set to 1000.
  • Default @@ -8407,7 +8336,7 @@

    semBicRule

    id="semBicRule_short_desc"> Lambda: 1 = Chickering, 2 = Nandy
  • Long Description: The - Chickering Rule uses a the difference of BIC scores to add or remove + Chickering Rule uses the difference of BIC scores to add or remove edges. The Nandy et al. rule uses a single calculation of a partial correlation in place of the likelihood difference.
  • Default Value: 1
  • @@ -8520,7 +8449,7 @@

    stableFAS

    id="standardize_short_desc">Yes if the data should be standardized
  • Long Description: Yes if each varaibles in the data should + id="standardize_long_desc"> Yes if each variable in the data should be standardized to have mean zero and variance 1.
  • Default Value: false
  • @@ -8560,7 +8489,7 @@

    stableFAS

    • Short Description: Yes if the first step step for + id="symmetricFirstStep_short_desc"> Yes if the first step for FGES should do scoring for both X->Y and Y->X
    • Long Description: If Yes, scores @@ -8638,11 +8567,11 @@

      thr

      • Short Description: Yes, if use the + id="thresholdNoRandomConstrainSearch_short_desc"> Yes, if using the cutoff threshold for the meta-constraints independence test (stage 2).
      • Long Description: Yes, if use the + id="thresholdNoRandomConstrainSearch_long_desc"> Yes, if using the cutoff threshold for the meta-constraints independence test (stage 2).
      • Default Value: thr
        • Short Description: Yes, if use the cutoff + id="thresholdNoRandomDataSearch_short_desc"> Yes, if using the cutoff threshold for the constraints independence test (stage 1).
        • Long Description: useGap
          • Short Description: Yes if the GAP algorithms should be used. No + id="useGap_short_desc">Yes if the GAP algorithms should be used. Not if the SAG algorithm should be used
          • Long Description: True if one should first find all possible initial sets, grows these out, and then picks a - non-overlapping such largest sets from these. No if one should grow + non-overlapping such largest sets from these. Not if one should grow pure clusters one at a time, excluding variables found in earlier clusters.
          • Default Value: useGap

            useWishart

            • Short Description: Yes if the Wishart test shoud be used. No + id="useWishart_short_desc">Yes if the Wishart test should be used. Not if the Delta test should be used
            • Long Description: This is a parameter for the FOFC (Find One Factor Clusters) algorithm. There are two tests implemented there for testing for tetrads being zero, Wishart and Delta. This - parameter picks which of these tests should be use: ‘Yes’ for Wishart + parameter picks which of these tests should be used: ‘Yes’ for Wishart and ‘No’ for Delta.
            • Default Value: false
            • @@ -9131,7 +9060,7 @@

              verbose

              applications should be printed or logged
            • Long Description: If this parameter is - set to ‘Yes’, Meek rule appications will be printed out to the + set to ‘Yes’, Meek rule applications will be printed out to the log.
            • Default Value: false
            • @@ -9167,7 +9096,7 @@

              useScore

              • Short Description: Yes if CPDAG should be ouput, no if a + id="outputCpdag_short_desc">Yes if CPDAG should be output, no if a DAG.
              • Long Description: BOSS can output a DAG or the CPDAG of the @@ -9208,12 +9137,12 @@

                useScore

                class="parameter_description_list">
              • Short Description: Yes if the (MimBuild) - stucture model should be included in the output graph
              • + structure model should be included in the output graph
              • Long Description: FOFC proper yields a measurement model--that is, a set of pure children for each of the discovered latents. One can estimate the structure over the latents (the structure model) using Mimbuild. This - struture model is included in the output if this parameter is set to + structure model is included in the output if this parameter is set to Yes.
              • Default Value: true
              • @@ -9278,7 +9207,7 @@

                Multiple Linear Regression

                simply click on another variable and click on the arrow again.

                To select a variable as a predictor variable, click on it in the - leftmost box, and then click on the second right- pointing arrow. To + leftmost box, and then click on the second right-pointing arrow. To remove a predictor variable, click on it in the predictor box and then click on the left-pointing arrow.

                @@ -9314,7 +9243,7 @@

                Appendices

                An Introduction to PAGs

                -

                Peter Spirites

                +

                Peter Spirtes

                The output of the FCI algorithm [Spirtes, 2001] is a partial ancestral graph (PAG), which is a graphical object that represents a set @@ -9360,9 +9289,9 @@

                An Introduction to - A --> B + A --> B A is a cause of B. It may - be a direct or indirect cause that may include other measured + be a direct or indirect because that may include other measured variables. Also, there may be an unmeasured confounder of A and B. B is not a cause of A. @@ -9413,8 +9342,8 @@

                An Introduction to an edge between A and B means "A is a cause of B"; an arrowhead ">" at the A end of an edge between A and B means "A is not a cause of B"; and a circle "o" at the A end of an edge between A and B means "can't tell - whether or not A is a cause of B". For example A --> B means that A is a - cause of B, and that B is not a cause of A in all of the CBNs represented + whether A is a cause of B". For example A --> B means that A is a + cause of B, and that B is not a cause of A in all the CBNs represented by the PAG.

                The PAG in Figure 2 shows examples of each type of edge, and the CBNs. Figure 1. show some examples of what kinds of CBNs @@ -9477,8 +9406,8 @@

                Arc Specializations in PAGs

                Solving Out of Memory Errors

                -

                By default Java will - allocate the smaller of 1/4 system memory or 1GB to the Java virtual +

                By default, Java will + allocate the smaller option of 1/4 system memory or 1GB to the Java virtual machine (JVM). If you run out of memory (heap memory space) running your analyses you should increase the memory allocated to the JVM with the following switch '-XmxXXG' where XX is the number of gigabytes of ram you @@ -9491,7 +9420,7 @@

                Glossary of Terms

                Adjacent

                Two vertices in a graph are adjacent if there is - a directed, or undirected, or double headed edge between them.

                + a directed, or undirected, or double-headed edge between them.

                Degree

                The total number of edges directed both into and @@ -9561,23 +9490,6 @@

                Trek
                Y or from Y to X, or two directed paths from a third variable Z into X and Y that do not intersect except at Z.

                - - - - - - - From e02cdc3708669477bf2b5aad9c4f4e028f2210c2 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Sun, 14 Jan 2024 13:26:38 -0500 Subject: [PATCH 066/163] Cleaned up the manual according to complains from IntelliJ (spelling and such). --- tetrad-lib/src/main/resources/docs/manual/index.html | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/tetrad-lib/src/main/resources/docs/manual/index.html b/tetrad-lib/src/main/resources/docs/manual/index.html index 6d57fab3e8..b7d61a8c74 100755 --- a/tetrad-lib/src/main/resources/docs/manual/index.html +++ b/tetrad-lib/src/main/resources/docs/manual/index.html @@ -1,8 +1,7 @@ - + Tetrad Single HTML Manual @@ -12,10 +11,7 @@ - +
                From bb2dd63a35c4c55f1bd4a375ee4728d4d3153d14 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Sun, 14 Jan 2024 13:32:09 -0500 Subject: [PATCH 067/163] Cleaned up the manual according to complains from IntelliJ (spelling and such). --- .../src/main/resources/docs/manual/index.html | 193 ++---------------- 1 file changed, 20 insertions(+), 173 deletions(-) diff --git a/tetrad-lib/src/main/resources/docs/manual/index.html b/tetrad-lib/src/main/resources/docs/manual/index.html index b7d61a8c74..2708d8d6a6 100755 --- a/tetrad-lib/src/main/resources/docs/manual/index.html +++ b/tetrad-lib/src/main/resources/docs/manual/index.html @@ -8,8 +8,7 @@ - + @@ -24,33 +23,19 @@ Table of Contents
                @@ -113,10 +98,8 @@

                Graph

                The graph box can be used to create a new graph, or to copy or edit a graph from another box.

                -

                Possible - Parent Boxes of the Graph Box

                +

                Possible Parent Boxes of the Graph Box

                -
                • Another graph box
                • A parametric model box
                • @@ -127,10 +110,10 @@

                  Graph
                • A search box
                • An updater box
                • A regression box
                • -

                Possible Child Boxes of the Graph Box

                +

              + +

              Possible Child Boxes of the Graph Box

              -
              • Another graph box
              • A compare box
              • @@ -202,7 +185,6 @@

                Creating a Random Graph

                Random graph generation is not available for time lag graphs.

                -

                Loading a Saved Graph

                If you have previously saved a graph from Tetrad, you can load it @@ -227,20 +209,7 @@

                Copying a Graph

                new graph box in the workspace, and draw an arrow from the box whose graph you want to copy to the new graph box. When opened, the new graph box will automatically contain a direct copy of the graph its parent box - contains.

                - - - - + contains.

                Manipulating a Graph

                @@ -1989,14 +1958,6 @@

                Row Summing Exact Updater

                see conditional as well as marginal probabilities, and in “Single Variable” mode, you can see joint values.

                - - - - - - - -

                Junction Tree Exact Updater

                The Junction Tree exact updater is another exact learning @@ -2029,66 +1990,6 @@

                SEM Updater

                The rest of the window has the same functionality as a SEM instantiated model window, except as noted above.

                - - - -

                Knowledge Box

                @@ -3570,33 +3471,6 @@

                Parameters

                - - - - - - - - - - - - - - - - - - - - - - -

                The BPC/Mimbuild Algorithm

                Description

                @@ -4381,25 +4255,6 @@

                Parameters

                structurePrior

                - - - - - - - - -

                M-separation Score

                This uses m-separation to make something @@ -4485,13 +4340,6 @@

                Zhang-Shen Bound Score

                - - - - - - -

                Search Parameters

                Zhang-Shen Bound Score

                Note: You must specify the "Value Type" of each parameter, and the value type must be one of the following: Integer, Long, Double, String, - Boolean.

                + Boolean.

                sampleStyle

                From e9237f20292a68732291d6f84538d1d06683fd6f Mon Sep 17 00:00:00 2001 From: jdramsey Date: Sun, 14 Jan 2024 13:35:53 -0500 Subject: [PATCH 068/163] Cleanup. --- .../cmu/tetrad/search/score/BdeuScore.java | 27 ++++--------------- 1 file changed, 5 insertions(+), 22 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/BdeuScore.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/BdeuScore.java index b0a31cdee6..6fbc77f679 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/BdeuScore.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/BdeuScore.java @@ -49,7 +49,7 @@ public class BdeuScore implements DiscreteScore { private final int sampleSize; private final int[] numCategories; private final DataSet dataSet; - private List variables; + private final List variables; private double samplePrior = 1d; private double structurePrior = 0d; @@ -196,7 +196,7 @@ public double localScore(int node, int[] parents) { * * @param x The index of x. * @param y The index of y. - * @param z The indeces of the z variables. + * @param z The indices of the z variables. * @return The score difference. */ @Override @@ -214,23 +214,6 @@ public List getVariables() { return this.variables; } - /** - * Sets the variables to another of the same names, in the same order. - * - * @param variables The new varialbe list. - * @see edu.cmu.tetrad.algcomparison.algorithm.multi.Images - */ - void setVariables(List variables) { - for (int i = 0; i < variables.size(); i++) { - if (!variables.get(i).getName().equals(this.variables.get(i).getName())) { - throw new IllegalArgumentException("Variable in index " + (i + 1) + " does not have the same name " + - "as the variable being substituted for it."); - } - } - - this.variables = variables; - } - /** * Returns the sample size of the data. * @@ -280,7 +263,7 @@ public void setStructurePrior(double structurePrior) { } /** - * Returns the smaple prior. + * Returns the sample prior. * * @return This prior. */ @@ -306,7 +289,7 @@ public void setSamplePrior(double samplePrior) { @Override public String toString() { NumberFormat nf = new DecimalFormat("0.00"); - return "BDeu Score SampP " + nf.format(this.samplePrior) + " StuctP " + nf.format(this.structurePrior); + return "BDeu Score Sample prior = " + nf.format(this.samplePrior) + " Structure prior = " + nf.format(this.structurePrior); } /** @@ -320,7 +303,7 @@ public int getMaxDegree() { } /** - * This score does not implement a method to decide whehter a node is determined by its parents. + * This score does not implement a method to decide whether a node is determined by its parents. * * @param z The parents. * @param y The node. From 6a88fdf5699998bcc45cdc4222c1a76b31bc29ad Mon Sep 17 00:00:00 2001 From: jdramsey Date: Sun, 14 Jan 2024 13:41:00 -0500 Subject: [PATCH 069/163] Cleanup. --- .../edu/cmu/tetrad/algcomparison/independence/Kci.java | 4 ++-- .../src/main/java/edu/cmu/tetrad/util/Params.java | 10 ++-------- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/Kci.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/Kci.java index 82436d94b0..1e03b0b752 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/Kci.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/Kci.java @@ -34,7 +34,7 @@ public class Kci implements IndependenceWrapper { public IndependenceTest getTest(DataModel dataSet, Parameters parameters) { edu.cmu.tetrad.search.test.Kci kci = new edu.cmu.tetrad.search.test.Kci(SimpleDataLoader.getContinuousDataSet(dataSet), parameters.getDouble(Params.ALPHA)); - kci.setApproximate(parameters.getBoolean(Params.KCI_USE_APPROMATION)); + kci.setApproximate(parameters.getBoolean(Params.KCI_USE_APPROXIMATION)); kci.setWidthMultiplier(parameters.getDouble(Params.KERNEL_MULTIPLIER)); kci.setNumBootstraps(parameters.getInt(Params.KCI_NUM_BOOTSTRAPS)); kci.setThreshold(parameters.getDouble(Params.THRESHOLD_FOR_NUM_EIGENVALUES)); @@ -55,7 +55,7 @@ public DataType getDataType() { @Override public List getParameters() { List params = new ArrayList<>(); - params.add(Params.KCI_USE_APPROMATION); + params.add(Params.KCI_USE_APPROXIMATION); params.add(Params.ALPHA); params.add(Params.KERNEL_MULTIPLIER); params.add(Params.KCI_NUM_BOOTSTRAPS); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/util/Params.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/util/Params.java index f9319f919a..89b15b3a8e 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/util/Params.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/util/Params.java @@ -74,13 +74,10 @@ public final class Params { public static final String FASK_ADJACENCY_METHOD = "faskAdjacencyMethod"; public static final String FASK_NONEMPIRICAL = "faskNonempirical"; public static final String FAITHFULNESS_ASSUMED = "faithfulnessAssumed"; - // public static final String PC_HEURISTIC = "pcHeuristic"; public static final String FAS_RULE = "fasRule"; public static final String FAST_ICA_A = "fastIcaA"; public static final String FAST_ICA_MAX_ITER = "fastIcaMaxIter"; public static final String FAST_ICA_TOLERANCE = "fastIcaTolerance"; - public static final String ICA_ALGORITHM = "icaAlgorithm"; - public static final String ICA_FUNCTION = "icaFunction"; public static final String THRESHOLD_B = "thresholdBHat"; public static final String GUARANTEE_ACYCLIC = "guaranteeAcyclic"; public static final String THRESHOLD_SPINE = "thresholdSpine"; @@ -106,7 +103,7 @@ public final class Params { public static final String KCI_CUTOFF = "kciCutoff"; public static final String KCI_EPSILON = "kciEpsilon"; public static final String KCI_NUM_BOOTSTRAPS = "kciNumBootstraps"; - public static final String KCI_USE_APPROMATION = "kciUseAppromation"; + public static final String KCI_USE_APPROXIMATION = "kciUseApproximation"; public static final String KERNEL_MULTIPLIER = "kernelMultiplier"; public static final String KERNEL_REGRESSION_SAMPLE_SIZE = "kernelRegressionSampleSize"; public static final String KERNEL_TYPE = "kernelType"; @@ -204,9 +201,7 @@ public final class Params { public static final String USE_BES = "useBes"; public static final String NUM_STARTS = "numStarts"; public static final String CACHE_SCORES = "cacheScores"; - public static final String OTHER_PERM_METHOD = "otherPermMethod"; public static final String BOSS_ALG = "bossAlg"; - public static final String BREAK_TIES = "breakTies"; public static final String OUTPUT_CPDAG = "outputCpdag"; public static final String ZS_RISK_BOUND = "zSRiskBound"; public static final String NUM_ROUNDS = "numRounds"; @@ -250,7 +245,6 @@ public final class Params { public static final String NUMBER_OF_EXPANSIONS = "numberOfExpansions"; public static final String CSTAR_CPDAG_ALGORITHM = "cstarCpdagAlgorithm"; public static final String FILE_OUT_PATH = "fileOutPath"; - public static final String PI_THR = "piThr"; public static final String REMOVE_EFFECT_NODES = "removeEffectNodes"; public static final String SAMPLE_STYLE = "sampleStyle"; public static final String NUM_THREADS = "numThreads"; @@ -272,7 +266,7 @@ public final class Params { Params.INCLUDE_NEGATIVE_SKEWS_FOR_BETA, Params.INCLUDE_POSITIVE_COEFS, Params.INCLUDE_POSITIVE_SKEWS_FOR_BETA, Params.INCLUDE_STRUCTURE_MODEL, Params.INTERVAL_BETWEEN_RECORDINGS, Params.INTERVAL_BETWEEN_SHOCKS, Params.IPEN, Params.IS, Params.ITR, - Params.KCI_ALPHA, Params.KCI_CUTOFF, Params.KCI_EPSILON, Params.KCI_NUM_BOOTSTRAPS, Params.KCI_USE_APPROMATION, + Params.KCI_ALPHA, Params.KCI_CUTOFF, Params.KCI_EPSILON, Params.KCI_NUM_BOOTSTRAPS, Params.KCI_USE_APPROXIMATION, Params.KERNEL_MULTIPLIER, Params.KERNEL_REGRESSION_SAMPLE_SIZE, Params.KERNEL_TYPE, Params.KERNEL_WIDTH, Params.LATENT_MEASURED_IMPURE_PARENTS, Params.LOWER_BOUND, Params.MAX_CATEGORIES, Params.MAX_DEGREE, Params.MAX_DISTINCT_VALUES_DISCRETE, Params.MAX_INDEGREE, Params.MAX_ITERATIONS, Params.MAX_OUTDEGREE, From a082229e5daf0492e48bd47537a623dfd1b1513f Mon Sep 17 00:00:00 2001 From: jdramsey Date: Sun, 14 Jan 2024 13:47:28 -0500 Subject: [PATCH 070/163] Cleanup. --- tetrad-lib/src/main/resources/docs/manual/index.html | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tetrad-lib/src/main/resources/docs/manual/index.html b/tetrad-lib/src/main/resources/docs/manual/index.html index 2708d8d6a6..55b9dc5eb1 100755 --- a/tetrad-lib/src/main/resources/docs/manual/index.html +++ b/tetrad-lib/src/main/resources/docs/manual/index.html @@ -87,6 +87,8 @@ them by clicking on the arrow tool in the sidebar, and clicking and dragging from the first box to the second in the workspace.

                +

                Starting 1/14/2024, we will compile Tetrad under JDK 17 and use language level 17.

                +

                Tetrad may be cited using the following reference: Ramsey, J. D., Zhang, K., Glymour, M., Romero, R. S., Huang, B., Ebert-Uphoff, I., ... & Glymour, C. (2018). TETRAD—A toolbox for causal discovery. In 8th From b455e050b3330bde3a7f4e3ab6b614d35e7bdcf7 Mon Sep 17 00:00:00 2001 From: Joseph Ramsey Date: Sun, 14 Jan 2024 16:41:54 -0500 Subject: [PATCH 071/163] Update README.md --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 96f161e71a..a249fe0552 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,10 @@ Please visit our [Tetrad web page](https://sites.google.com/view/tetradcausal) for current links, a list of contributors, some history, documentation, descriptions, links for our various projects, Javadocs, and more. +# Note + +Starting 1/14/2024, the Tetrad codebase will target language level 17, and all jars will be compiled using Corretto's JDK 17. + ## Tetrad Application See out insructions for [Installing the Tetrad Application](https://github.com/cmu-phil/tetrad/blob/development/INSTALL_APPLICATION.md). From ef845978cbe76d902ffc382dabc2e53c1157c9aa Mon Sep 17 00:00:00 2001 From: Joseph Ramsey Date: Sun, 14 Jan 2024 17:07:20 -0500 Subject: [PATCH 072/163] Update README.md --- README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index a249fe0552..0352dec0cb 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,7 @@ Please visit our [Tetrad web page](https://sites.google.com/view/tetradcausal) for current links, a list of contributors, some history, documentation, descriptions, links for our various projects, Javadocs, and more. -# Note - -Starting 1/14/2024, the Tetrad codebase will target language level 17, and all jars will be compiled using Corretto's JDK 17. +Note: Starting 1/14/2024, the Tetrad codebase will target language level 17, and all jars will be compiled using Corretto's JDK 17. ## Tetrad Application From 6b23e2b5c126aaa95a03e73ebb6555ab0ed4dd8b Mon Sep 17 00:00:00 2001 From: jdramsey Date: Sun, 14 Jan 2024 20:29:47 -0500 Subject: [PATCH 073/163] Cleanup. --- .../main/java/edu/cmu/tetrad/search/Pc.java | 37 +++++++++++-------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Pc.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Pc.java index 647299fdb3..0c2c65b4f7 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Pc.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Pc.java @@ -30,6 +30,7 @@ import edu.cmu.tetrad.search.utils.SepsetMap; import edu.cmu.tetrad.util.MillisecondTimes; import edu.cmu.tetrad.util.TetradLogger; +import org.jetbrains.annotations.NotNull; import java.util.HashSet; import java.util.List; @@ -162,6 +163,26 @@ public Graph search(IFas fas, Set nodes) { "be in the domain of the independence test provided."); } + PcCommon search = getPcCommon(); + + this.graph = search.search(); + this.sepsets = fas.getSepsets(); + + this.numIndependenceTests = fas.getNumIndependenceTests(); + + this.elapsedTime = MillisecondTimes.timeMillis() - startTime; + + if (verbose) { + this.logger.forceLogMessage("Elapsed time = " + (this.elapsedTime) / 1000. + " s"); + this.logger.forceLogMessage("Finishing PC Algorithm."); + this.logger.flush(); + } + + return this.graph; + } + + @NotNull + private PcCommon getPcCommon() { PcCommon search = new PcCommon(independenceTest); search.setDepth(depth); search.setMeekPreventCycles(meekPreventCycles); @@ -183,21 +204,7 @@ public Graph search(IFas fas, Set nodes) { search.setConflictRule(conflictRule); search.setPcHeuristicType(pcHeuristicType); search.setVerbose(verbose); - - this.graph = search.search(); - this.sepsets = fas.getSepsets(); - - this.numIndependenceTests = fas.getNumIndependenceTests(); - - this.elapsedTime = MillisecondTimes.timeMillis() - startTime; - - if (verbose) { - this.logger.forceLogMessage("Elapsed time = " + (this.elapsedTime) / 1000. + " s"); - this.logger.forceLogMessage("Finishing PC Algorithm."); - this.logger.flush(); - } - - return this.graph; + return search; } /** From e8e192458e4f5c0243b7ab765c8f1427ced83609 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Mon, 15 Jan 2024 03:18:27 -0500 Subject: [PATCH 074/163] Cleanup. --- .../{BayesParametersEst.java => NumParametersEst.java} | 10 ++++++---- .../edu/cmu/tetrad/search/test/IndTestFisherZ.java | 7 +++++-- 2 files changed, 11 insertions(+), 6 deletions(-) rename tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/{BayesParametersEst.java => NumParametersEst.java} (86%) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/BayesParametersEst.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/NumParametersEst.java similarity index 86% rename from tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/BayesParametersEst.java rename to tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/NumParametersEst.java index 62b216b177..a09152bf0f 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/BayesParametersEst.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/NumParametersEst.java @@ -17,22 +17,22 @@ * * @author josephramsey */ -public class BayesParametersEst implements Statistic { +public class NumParametersEst implements Statistic { @Serial private static final long serialVersionUID = 23L; - public BayesParametersEst() { + public NumParametersEst() { } @Override public String getAbbreviation() { - return "DiscreteBicParams"; + return "NumParams"; } @Override public String getDescription() { - return "Number of parameters for the estimated graph as a Bayes model"; + return "Number of parameters for the estimated graph for a Bayes or SEM model"; } @Override @@ -59,6 +59,8 @@ public double getValue(Graph trueGraph, Graph estGraph, DataModel dataModel) { } return params; + } else if (dataModel.isContinuous()) { + return estGraph.getNumEdges(); } else { throw new IllegalArgumentException("Data must be discrete"); } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java index 777315ce9f..1418c1404a 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java @@ -356,7 +356,8 @@ public List getDataSets() { */ @Override public int getSampleSize() { - return this.cor.getSampleSize(); + if (dataSet != null) return dataSet.getNumRows(); + else return this.cor.getSampleSize(); } /** @@ -469,7 +470,8 @@ private double getR(Node x, Node y, Set z, List rows) { } private int sampleSize() { - return covMatrix().getSampleSize(); + if (dataSet != null) return dataSet.getNumRows(); + else return covMatrix().getSampleSize(); } private ICovarianceMatrix covMatrix() { @@ -542,6 +544,7 @@ public void setRows(List rows) { } this.rows = rows; + cor = null; } } From 1c91a20b106398fc610e2595aa3df927831b4e7d Mon Sep 17 00:00:00 2001 From: jdramsey Date: Mon, 15 Jan 2024 08:54:15 -0500 Subject: [PATCH 075/163] Cleanup. Also, re-introduced the 'pcHeuristic' parameter. --- .../algorithm/oracle/cpdag/Cpc.java | 54 +-- .../algorithm/oracle/cpdag/Fas.java | 33 +- .../algorithm/oracle/cpdag/Pc.java | 30 +- .../algorithm/oracle/pag/Fci.java | 32 +- .../algorithm/oracle/pag/FciMax.java | 31 +- .../algorithm/oracle/pag/Gfci.java | 4 +- .../algorithm/oracle/pag/SvarFci.java | 4 +- .../main/java/edu/cmu/tetrad/search/Fasd.java | 1 - .../java/edu/cmu/tetrad/search/FciMax.java | 23 +- .../java/edu/cmu/tetrad/search/SvarFas.java | 33 +- .../java/edu/cmu/tetrad/search/SvarFci.java | 20 +- .../tetrad/search/work_in_progress/Fas2.java | 410 ---------------- .../tetrad/search/work_in_progress/Fas3.java | 459 ------------------ .../main/java/edu/cmu/tetrad/util/Params.java | 1 + 14 files changed, 113 insertions(+), 1022 deletions(-) delete mode 100644 tetrad-lib/src/main/java/edu/cmu/tetrad/search/work_in_progress/Fas2.java delete mode 100644 tetrad-lib/src/main/java/edu/cmu/tetrad/search/work_in_progress/Fas3.java diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/Cpc.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/Cpc.java index 7c34c9f73b..cfbdfa40ca 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/Cpc.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/Cpc.java @@ -65,47 +65,27 @@ public Graph search(DataModel dataModel, Parameters parameters) { knowledge = timeSeries.getKnowledge(); } - PcCommon.ConflictRule conflictRule; - - switch (parameters.getInt(Params.CONFLICT_RULE)) { - case 1: - conflictRule = PcCommon.ConflictRule.PRIORITIZE_EXISTING; - break; - case 2: - conflictRule = PcCommon.ConflictRule.ORIENT_BIDIRECTED; - break; - case 3: - conflictRule = PcCommon.ConflictRule.OVERWRITE_EXISTING; - break; - default: - throw new IllegalArgumentException("Unknown conflict rule: " + parameters.getInt(Params.CONFLICT_RULE)); - - } - -// PcCommon.PcHeuristicType pcHeuristicType; -// -// switch (parameters.getInt(Params.PC_HEURISTIC)) { -// case 0: -// pcHeuristicType = PcCommon.PcHeuristicType.NONE; -// break; -// case 1: -// pcHeuristicType = PcCommon.PcHeuristicType.HEURISTIC_1; -// break; -// case 2: -// pcHeuristicType = PcCommon.PcHeuristicType.HEURISTIC_2; -// break; -// case 3: -// pcHeuristicType = PcCommon.PcHeuristicType.HEURISTIC_3; -// break; -// default: -// throw new IllegalArgumentException("Unknown conflict rule: " + parameters.getInt(Params.CONFLICT_RULE)); -// -// } + PcCommon.ConflictRule conflictRule = switch (parameters.getInt(Params.CONFLICT_RULE)) { + case 1 -> PcCommon.ConflictRule.PRIORITIZE_EXISTING; + case 2 -> PcCommon.ConflictRule.ORIENT_BIDIRECTED; + case 3 -> PcCommon.ConflictRule.OVERWRITE_EXISTING; + default -> + throw new IllegalArgumentException("Unknown conflict rule: " + parameters.getInt(Params.CONFLICT_RULE)); + }; + + PcCommon.PcHeuristicType pcHeuristicType = switch (parameters.getInt(Params.PC_HEURISTIC)) { + case 0 -> PcCommon.PcHeuristicType.NONE; + case 1 -> PcCommon.PcHeuristicType.HEURISTIC_1; + case 2 -> PcCommon.PcHeuristicType.HEURISTIC_2; + case 3 -> PcCommon.PcHeuristicType.HEURISTIC_3; + default -> + throw new IllegalArgumentException("Unknown conflict rule: " + parameters.getInt(Params.CONFLICT_RULE)); + }; edu.cmu.tetrad.search.Cpc search = new edu.cmu.tetrad.search.Cpc(getIndependenceWrapper().getTest(dataModel, parameters)); search.setDepth(parameters.getInt(Params.DEPTH)); search.meekPreventCycles(parameters.getBoolean(Params.MEEK_PREVENT_CYCLES)); -// search.setPcHeuristicType(pcHeuristicType); + search.setPcHeuristicType(pcHeuristicType); search.setVerbose(parameters.getBoolean(Params.VERBOSE)); search.setKnowledge(knowledge); search.setConflictRule(conflictRule); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/Fas.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/Fas.java index bd8df26b75..babb6958dc 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/Fas.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/Fas.java @@ -14,11 +14,13 @@ import edu.cmu.tetrad.graph.EdgeListGraph; import edu.cmu.tetrad.graph.Graph; import edu.cmu.tetrad.graph.GraphTransforms; +import edu.cmu.tetrad.search.utils.PcCommon; import edu.cmu.tetrad.util.Parameters; import edu.cmu.tetrad.util.Params; import edu.pitt.dbmi.algo.resampling.GeneralResamplingTest; import java.io.PrintStream; +import java.io.Serial; import java.util.ArrayList; import java.util.List; @@ -36,6 +38,7 @@ public class Fas implements Algorithm, HasKnowledge, TakesIndependenceWrapper, ReturnsBootstrapGraphs { + @Serial private static final long serialVersionUID = 23L; private IndependenceWrapper test; private Knowledge knowledge = new Knowledge(); @@ -51,28 +54,18 @@ public Fas(IndependenceWrapper test) { @Override public Graph search(DataModel dataSet, Parameters parameters) { if (parameters.getInt(Params.NUMBER_RESAMPLING) < 1) { -// PcCommon.PcHeuristicType pcHeuristicType; -// -// switch (parameters.getInt(Params.PC_HEURISTIC)) { -// case 0: -// pcHeuristicType = PcCommon.PcHeuristicType.NONE; -// break; -// case 1: -// pcHeuristicType = PcCommon.PcHeuristicType.HEURISTIC_1; -// break; -// case 2: -// pcHeuristicType = PcCommon.PcHeuristicType.HEURISTIC_2; -// break; -// case 3: -// pcHeuristicType = PcCommon.PcHeuristicType.HEURISTIC_3; -// break; -// default: -// throw new IllegalArgumentException("Unknown conflict rule: " + parameters.getInt(Params.CONFLICT_RULE)); -// } + PcCommon.PcHeuristicType pcHeuristicType = switch (parameters.getInt(Params.PC_HEURISTIC)) { + case 0 -> PcCommon.PcHeuristicType.NONE; + case 1 -> PcCommon.PcHeuristicType.HEURISTIC_1; + case 2 -> PcCommon.PcHeuristicType.HEURISTIC_2; + case 3 -> PcCommon.PcHeuristicType.HEURISTIC_3; + default -> + throw new IllegalArgumentException("Unknown conflict rule: " + parameters.getInt(Params.CONFLICT_RULE)); + }; edu.cmu.tetrad.search.Fas search = new edu.cmu.tetrad.search.Fas(this.test.getTest(dataSet, parameters)); search.setStable(parameters.getBoolean(Params.STABLE_FAS)); -// search.setPcHeuristicType(pcHeuristicType); + search.setPcHeuristicType(pcHeuristicType); search.setDepth(parameters.getInt(Params.DEPTH)); search.setKnowledge(this.knowledge); search.setVerbose(parameters.getBoolean(Params.VERBOSE)); @@ -119,7 +112,7 @@ public DataType getDataType() { public List getParameters() { List parameters = new ArrayList<>(); parameters.add(Params.DEPTH); -// parameters.add(Params.PC_HEURISTIC); + parameters.add(Params.PC_HEURISTIC); parameters.add(Params.STABLE_FAS); parameters.add(Params.VERBOSE); return parameters; diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/Pc.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/Pc.java index decfad9141..af654e4205 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/Pc.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/Pc.java @@ -80,30 +80,20 @@ public Graph search(DataModel dataModel, Parameters parameters) { } -// PcCommon.PcHeuristicType pcHeuristicType; -// -// switch (parameters.getInt(Params.PC_HEURISTIC)) { -// case 0: -// pcHeuristicType = PcCommon.PcHeuristicType.NONE; -// break; -// case 1: -// pcHeuristicType = PcCommon.PcHeuristicType.HEURISTIC_1; -// break; -// case 2: -// pcHeuristicType = PcCommon.PcHeuristicType.HEURISTIC_2; -// break; -// case 3: -// pcHeuristicType = PcCommon.PcHeuristicType.HEURISTIC_3; -// break; -// default: -// throw new IllegalArgumentException("Unknown conflict rule: " + parameters.getInt(Params.CONFLICT_RULE)); -// } + PcCommon.PcHeuristicType pcHeuristicType = switch (parameters.getInt(Params.PC_HEURISTIC)) { + case 0 -> PcCommon.PcHeuristicType.NONE; + case 1 -> PcCommon.PcHeuristicType.HEURISTIC_1; + case 2 -> PcCommon.PcHeuristicType.HEURISTIC_2; + case 3 -> PcCommon.PcHeuristicType.HEURISTIC_3; + default -> + throw new IllegalArgumentException("Unknown conflict rule: " + parameters.getInt(Params.CONFLICT_RULE)); + }; edu.cmu.tetrad.search.Pc search = new edu.cmu.tetrad.search.Pc(getIndependenceWrapper().getTest(dataModel, parameters)); search.setUseMaxPHeuristic(parameters.getBoolean(Params.USE_MAX_P_HEURISTIC)); search.setDepth(parameters.getInt(Params.DEPTH)); search.setMeekPreventCycles(parameters.getBoolean(Params.MEEK_PREVENT_CYCLES)); -// search.setPcHeuristicType(pcHeuristicType); + search.setPcHeuristicType(pcHeuristicType); search.setVerbose(parameters.getBoolean(Params.VERBOSE)); search.setKnowledge(this.knowledge); search.setStable(parameters.getBoolean(Params.STABLE_FAS)); @@ -149,7 +139,7 @@ public List getParameters() { parameters.add(Params.USE_MAX_P_HEURISTIC); parameters.add(Params.CONFLICT_RULE); parameters.add(Params.MEEK_PREVENT_CYCLES); -// parameters.add(Params.PC_HEURISTIC); + parameters.add(Params.PC_HEURISTIC); parameters.add(Params.DEPTH); parameters.add(Params.TIME_LAG); parameters.add(Params.VERBOSE); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/pag/Fci.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/pag/Fci.java index 752d387009..85390ea95c 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/pag/Fci.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/pag/Fci.java @@ -14,11 +14,13 @@ import edu.cmu.tetrad.graph.EdgeListGraph; import edu.cmu.tetrad.graph.Graph; import edu.cmu.tetrad.graph.GraphTransforms; +import edu.cmu.tetrad.search.utils.PcCommon; import edu.cmu.tetrad.search.utils.TsUtils; import edu.cmu.tetrad.util.Parameters; import edu.cmu.tetrad.util.Params; import edu.pitt.dbmi.algo.resampling.GeneralResamplingTest; +import java.io.Serial; import java.util.ArrayList; import java.util.List; @@ -36,6 +38,7 @@ public class Fci implements Algorithm, HasKnowledge, TakesIndependenceWrapper, ReturnsBootstrapGraphs { + @Serial private static final long serialVersionUID = 23L; private IndependenceWrapper test; private Knowledge knowledge = new Knowledge(); @@ -62,24 +65,14 @@ public Graph search(DataModel dataModel, Parameters parameters) { knowledge = timeSeries.getKnowledge(); } -// PcCommon.PcHeuristicType pcHeuristicType; -// -// switch (parameters.getInt(Params.PC_HEURISTIC)) { -// case 0: -// pcHeuristicType = PcCommon.PcHeuristicType.NONE; -// break; -// case 1: -// pcHeuristicType = PcCommon.PcHeuristicType.HEURISTIC_1; -// break; -// case 2: -// pcHeuristicType = PcCommon.PcHeuristicType.HEURISTIC_2; -// break; -// case 3: -// pcHeuristicType = PcCommon.PcHeuristicType.HEURISTIC_3; -// break; -// default: -// throw new IllegalArgumentException("Unknown conflict rule: " + parameters.getInt(Params.CONFLICT_RULE)); -// } + PcCommon.PcHeuristicType pcHeuristicType = switch (parameters.getInt(Params.PC_HEURISTIC)) { + case 0 -> PcCommon.PcHeuristicType.NONE; + case 1 -> PcCommon.PcHeuristicType.HEURISTIC_1; + case 2 -> PcCommon.PcHeuristicType.HEURISTIC_2; + case 3 -> PcCommon.PcHeuristicType.HEURISTIC_3; + default -> + throw new IllegalArgumentException("Unknown conflict rule: " + parameters.getInt(Params.CONFLICT_RULE)); + }; edu.cmu.tetrad.search.Fci search = new edu.cmu.tetrad.search.Fci(this.test.getTest(dataModel, parameters)); search.setDepth(parameters.getInt(Params.DEPTH)); @@ -89,7 +82,7 @@ public Graph search(DataModel dataModel, Parameters parameters) { search.setPossibleMsepSearchDone(parameters.getBoolean(Params.POSSIBLE_MSEP_DONE)); search.setDoDiscriminatingPathRule(parameters.getBoolean(Params.DO_DISCRIMINATING_PATH_RULE)); search.setVerbose(parameters.getBoolean(Params.VERBOSE)); -// search.setPcHeuristicType(pcHeuristicType); + search.setPcHeuristicType(pcHeuristicType); search.setStable(parameters.getBoolean(Params.STABLE_FAS)); return search.search(); @@ -128,6 +121,7 @@ public List getParameters() { List parameters = new ArrayList<>(); parameters.add(Params.DEPTH); parameters.add(Params.STABLE_FAS); + parameters.add(Params.PC_HEURISTIC); parameters.add(Params.MAX_PATH_LENGTH); parameters.add(Params.POSSIBLE_MSEP_DONE); parameters.add(Params.DO_DISCRIMINATING_PATH_RULE); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/pag/FciMax.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/pag/FciMax.java index 4eb8e3c8f0..48a0147fd9 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/pag/FciMax.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/pag/FciMax.java @@ -14,11 +14,13 @@ import edu.cmu.tetrad.graph.EdgeListGraph; import edu.cmu.tetrad.graph.Graph; import edu.cmu.tetrad.graph.GraphTransforms; +import edu.cmu.tetrad.search.utils.PcCommon; import edu.cmu.tetrad.search.utils.TsUtils; import edu.cmu.tetrad.util.Parameters; import edu.cmu.tetrad.util.Params; import edu.pitt.dbmi.algo.resampling.GeneralResamplingTest; +import java.io.Serial; import java.util.ArrayList; import java.util.List; @@ -36,6 +38,7 @@ public class FciMax implements Algorithm, HasKnowledge, TakesIndependenceWrapper, ReturnsBootstrapGraphs { + @Serial private static final long serialVersionUID = 23L; private IndependenceWrapper test; private Knowledge knowledge = new Knowledge(); @@ -61,24 +64,14 @@ public Graph search(DataModel dataModel, Parameters parameters) { knowledge = timeSeries.getKnowledge(); } -// PcCommon.PcHeuristicType pcHeuristicType; -// -// switch (parameters.getInt(Params.PC_HEURISTIC)) { -// case 0: -// pcHeuristicType = PcCommon.PcHeuristicType.NONE; -// break; -// case 1: -// pcHeuristicType = PcCommon.PcHeuristicType.HEURISTIC_1; -// break; -// case 2: -// pcHeuristicType = PcCommon.PcHeuristicType.HEURISTIC_2; -// break; -// case 3: -// pcHeuristicType = PcCommon.PcHeuristicType.HEURISTIC_3; -// break; -// default: -// throw new IllegalArgumentException("Unknown conflict rule: " + parameters.getInt(Params.CONFLICT_RULE)); -// } + PcCommon.PcHeuristicType pcHeuristicType = switch (parameters.getInt(Params.PC_HEURISTIC)) { + case 0 -> PcCommon.PcHeuristicType.NONE; + case 1 -> PcCommon.PcHeuristicType.HEURISTIC_1; + case 2 -> PcCommon.PcHeuristicType.HEURISTIC_2; + case 3 -> PcCommon.PcHeuristicType.HEURISTIC_3; + default -> + throw new IllegalArgumentException("Unknown conflict rule: " + parameters.getInt(Params.CONFLICT_RULE)); + }; edu.cmu.tetrad.search.FciMax search = new edu.cmu.tetrad.search.FciMax(this.test.getTest(dataModel, parameters)); search.setDepth(parameters.getInt(Params.DEPTH)); @@ -87,7 +80,7 @@ public Graph search(DataModel dataModel, Parameters parameters) { search.setCompleteRuleSetUsed(parameters.getBoolean(Params.COMPLETE_RULE_SET_USED)); search.setDoDiscriminatingPathRule(parameters.getBoolean(Params.DO_DISCRIMINATING_PATH_RULE)); search.setPossibleMsepSearchDone(parameters.getBoolean(Params.POSSIBLE_MSEP_DONE)); -// search.setPcHeuristicType(pcHeuristicType); + search.setPcHeuristicType(pcHeuristicType); search.setVerbose(parameters.getBoolean(Params.VERBOSE)); return search.search(); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/pag/Gfci.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/pag/Gfci.java index c4404a117c..8c04f9d55b 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/pag/Gfci.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/pag/Gfci.java @@ -22,6 +22,7 @@ import edu.pitt.dbmi.algo.resampling.GeneralResamplingTest; import java.io.PrintStream; +import java.io.Serial; import java.util.ArrayList; import java.util.List; @@ -40,6 +41,7 @@ public class Gfci implements Algorithm, HasKnowledge, UsesScoreWrapper, TakesIndependenceWrapper, ReturnsBootstrapGraphs { + @Serial private static final long serialVersionUID = 23L; private IndependenceWrapper test; private ScoreWrapper score; @@ -138,7 +140,7 @@ public Knowledge getKnowledge() { @Override public void setKnowledge(Knowledge knowledge) { - this.knowledge = new Knowledge((Knowledge) knowledge); + this.knowledge = new Knowledge(knowledge); } @Override diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/pag/SvarFci.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/pag/SvarFci.java index 40c66a4e1b..792c776ad1 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/pag/SvarFci.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/pag/SvarFci.java @@ -20,6 +20,7 @@ import edu.cmu.tetrad.util.Params; import edu.pitt.dbmi.algo.resampling.GeneralResamplingTest; +import java.io.Serial; import java.util.ArrayList; import java.util.List; @@ -39,6 +40,7 @@ public class SvarFci implements Algorithm, HasKnowledge, TakesIndependenceWrapper, ReturnsBootstrapGraphs { + @Serial private static final long serialVersionUID = 23L; private IndependenceWrapper test; private Knowledge knowledge; @@ -117,7 +119,7 @@ public Knowledge getKnowledge() { @Override public void setKnowledge(Knowledge knowledge) { - this.knowledge = new Knowledge((Knowledge) knowledge); + this.knowledge = new Knowledge(knowledge); } @Override diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fasd.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fasd.java index 01056c1fe4..faaea6f313 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fasd.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fasd.java @@ -299,7 +299,6 @@ private boolean searchAtDepth0(List nodes, IndependenceTest test, Map nodes, IndependenceTest test, Map itx1 = simListX.iterator(); Iterator ity1 = simListY.iterator(); @@ -294,13 +294,13 @@ private boolean searchAtDepth0(List nodes, IndependenceTest test, Map nodes, IndependenceTest test, Map condSetAB = new HashSet<>(); for (Node tempNode : condSet) { - int ind_temptier = this.knowledge.isInWhichTier(tempNode); - List temptier = this.knowledge.getTier(ind_temptier); - int ind_temp = -1; - for (int j = 0; j < temptier.size(); ++j) { - if (getNameNoLag(tempNode.getName()).equals(getNameNoLag(temptier.get(j)))) { - ind_temp = j; + int indTempTier = this.knowledge.isInWhichTier(tempNode); + List tempTier = this.knowledge.getTier(indTempTier); + int indTemp = -1; + for (int j = 0; j < tempTier.size(); ++j) { + if (getNameNoLag(tempNode.getName()).equals(getNameNoLag(tempTier.get(j)))) { + indTemp = j; break; } } - int cond_diff = indx_tier - ind_temptier; + int cond_diff = indx_tier - indTempTier; int condAB_tier = this.knowledge.isInWhichTier(x1) - cond_diff; if (condAB_tier < 0 || condAB_tier > (ntiers - 1) || this.knowledge.getTier(condAB_tier).size() == 1) { // added condition for time tier 05.29.2016 @@ -576,7 +575,7 @@ private void removeSimilarPairs(Map> adjacencies, IndependenceTe continue; } List new_tier = this.knowledge.getTier(condAB_tier); - String tempNode1 = new_tier.get(ind_temp); + String tempNode1 = new_tier.get(indTemp); System.out.println("adding variable " + tempNode1 + " to SepSet"); condSetAB.add(test.getVariable(tempNode1)); } @@ -597,17 +596,17 @@ private void removeSimilarPairs(Map> adjacencies, IndependenceTe System.out.println("removed edge between " + x1 + " and " + y1 + " because of structure knowledge"); Set condSetAB = new HashSet<>(); for (Node tempNode : condSet) { - int ind_temptier = this.knowledge.isInWhichTier(tempNode); - List temptier = this.knowledge.getTier(ind_temptier); + int indTempTier = this.knowledge.isInWhichTier(tempNode); + List tempTier = this.knowledge.getTier(indTempTier); int ind_temp = -1; - for (int j = 0; j < temptier.size(); ++j) { - if (getNameNoLag(tempNode.getName()).equals(getNameNoLag(temptier.get(j)))) { + for (int j = 0; j < tempTier.size(); ++j) { + if (getNameNoLag(tempNode.getName()).equals(getNameNoLag(tempTier.get(j)))) { ind_temp = j; break; } } - int cond_diff = indx_tier - ind_temptier; + int cond_diff = indx_tier - indTempTier; int condAB_tier = this.knowledge.isInWhichTier(x1) - cond_diff; if (condAB_tier < 0 || condAB_tier > (ntiers - 1) || this.knowledge.getTier(condAB_tier).size() == 1) { // added condition for time tier 05.29.2016 diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SvarFci.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SvarFci.java index 7e46fa7170..22a33d1a72 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SvarFci.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SvarFci.java @@ -385,22 +385,22 @@ private void removeSimilarPairs(IndependenceTest test, Node x, Node y, Set break; } - int ind_temptier = this.knowledge.isInWhichTier(tempNode); - List temptier = this.knowledge.getTier(ind_temptier); + int indTempTier = this.knowledge.isInWhichTier(tempNode); + List tempTier = this.knowledge.getTier(indTempTier); int ind_temp = -1; - for (int j = 0; j < temptier.size(); ++j) { + for (int j = 0; j < tempTier.size(); ++j) { if (Thread.currentThread().isInterrupted()) { break; } - if (getNameNoLag(tempNode.getName()).equals(getNameNoLag(temptier.get(j)))) { + if (getNameNoLag(tempNode.getName()).equals(getNameNoLag(tempTier.get(j)))) { ind_temp = j; break; } } - int cond_diff = indx_tier - ind_temptier; + int cond_diff = indx_tier - indTempTier; int condAB_tier = this.knowledge.isInWhichTier(x1) - cond_diff; if (condAB_tier < 0 || condAB_tier > (ntiers - 1) @@ -434,18 +434,18 @@ private void removeSimilarPairs(IndependenceTest test, Node x, Node y, Set break; } - int ind_temptier = this.knowledge.isInWhichTier(tempNode); - List temptier = this.knowledge.getTier(ind_temptier); + int indTempTier = this.knowledge.isInWhichTier(tempNode); + List tempTier = this.knowledge.getTier(indTempTier); int ind_temp = -1; - for (int j = 0; j < temptier.size(); ++j) { - if (getNameNoLag(tempNode.getName()).equals(getNameNoLag(temptier.get(j)))) { + for (int j = 0; j < tempTier.size(); ++j) { + if (getNameNoLag(tempNode.getName()).equals(getNameNoLag(tempTier.get(j)))) { ind_temp = j; break; } } - int cond_diff = indx_tier - ind_temptier; + int cond_diff = indx_tier - indTempTier; int condAB_tier = this.knowledge.isInWhichTier(x1) - cond_diff; if (condAB_tier < 0 || condAB_tier > (ntiers - 1) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/work_in_progress/Fas2.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/work_in_progress/Fas2.java deleted file mode 100644 index 0e6fe4e7b2..0000000000 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/work_in_progress/Fas2.java +++ /dev/null @@ -1,410 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// For information as to what this class does, see the Javadoc, below. // -// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, // -// 2007, 2008, 2009, 2010, 2014 by Peter Spirtes, Richard Scheines, Joseph // -// Ramsey, and Clark Glymour. // -// // -// This program is free software; you can redistribute it and/or modify // -// it under the terms of the GNU General Public License as published by // -// the Free Software Foundation; either version 2 of the License, or // -// (at your option) any later version. // -// // -// This program is distributed in the hope that it will be useful, // -// but WITHOUT ANY WARRANTY; without even the implied warranty of // -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // -// GNU General Public License for more details. // -// // -// You should have received a copy of the GNU General Public License // -// along with this program; if not, write to the Free Software // -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // -/////////////////////////////////////////////////////////////////////////////// - -package edu.cmu.tetrad.search.work_in_progress; - -import edu.cmu.tetrad.data.Knowledge; -import edu.cmu.tetrad.graph.*; -import edu.cmu.tetrad.search.IFas; -import edu.cmu.tetrad.search.IndependenceTest; -import edu.cmu.tetrad.search.utils.PcCommon; -import edu.cmu.tetrad.search.utils.SepsetMap; -import edu.cmu.tetrad.util.ChoiceGenerator; -import edu.cmu.tetrad.util.TetradLogger; - -import java.io.PrintStream; -import java.util.*; - -/** - * Implements the "fast adjacency search" used in several causal algorithm in this package. In the fast adjacency - * search, at a given stage of the search, an edge X*-*Y is removed from the graph if X _||_ Y | S, where S is a subset - * of size d either of adj(X) or of adj(Y), where d is the depth of the search. The fast adjacency search performs this - * procedure for each pair of adjacent edges in the graph and for each depth d = 0, 1, 2, ..., d1, where d1 is either - * the maximum depth or else the first such depth at which no edges can be removed. The interpretation of this adjacency - * search is different for different algorithm, depending on the assumptions of the algorithm. A mapping from {x, y} to - * S({x, y}) is returned for edges x *-* y that have been removed. - * - * @author Joseph Ramsey. - */ -public class Fas2 implements IFas { - - /** - * The search nodes. - */ - private final List nodes; - - /** - * The independence test. This should be appropriate to the types - */ - private final IndependenceTest test; - /** - * The logger, by default the empty logger. - */ - private final TetradLogger logger = TetradLogger.getInstance(); - /** - * Specification of which edges are forbidden or required. - */ - private Knowledge knowledge = new Knowledge(); - /** - * The maximum number of variables conditioned on in any conditional independence test. If the depth is -1, it will - * be taken to be the maximum value, which is 1000. Otherwise, it should be set to a non-negative integer. - */ - private int depth = 1000; - /** - * The number of independence tests. - */ - private int numIndependenceTests; - /** - * The sepsets found during the search. - */ - private SepsetMap sepset = new SepsetMap(); - - /** - * The depth 0 graph, specified initially. - */ - private Graph initialGraph; - - /** - * True iff verbose output should be printed. - */ - private boolean verbose = false; - - private PrintStream out = System.out; - private PcCommon.PcHeuristicType pcHeuristicType; - - //==========================CONSTRUCTORS=============================// - - /** - * Constructs a new FastAdjacencySearch. - */ - public Fas2(Graph initialGraph, IndependenceTest test) { - if (initialGraph != null) { - this.initialGraph = new EdgeListGraph(initialGraph); - } - this.test = test; - this.nodes = test.getVariables(); - } - - public Fas2(IndependenceTest test) { - this.test = test; - this.nodes = test.getVariables(); - } - - //==========================PUBLIC METHODS===========================// - - public Graph search(List nodes) { -// return search(nodes, new Knowledge()); - throw new UnsupportedOperationException(); - } - - /** - * Discovers all adjacencies in data. The procedure is to remove edges in the graph which connect pairs of - * variables which are independent conditional on some other set of variables in the graph (the "sepset"). These are - * removed in tiers. First, edges which are independent conditional on zero other variables are removed, then edges - * which are independent conditional on one other variable are removed, then two, then three, and so on, until no - * more edges can be removed from the graph. The edges which remain in the graph after this procedure are the - * adjacencies in the data. - * - * @return a SepSet, which indicates which variables are independent conditional on which other variables - */ - public Graph search() { - this.logger.log("info", "Starting Fast Adjacency Search."); - - sepset = new SepsetMap(); -// sepset.setReturnEmptyIfNotSet(sepsetsReturnEmptyIfNotFixed); - - int _depth = depth; - - if (_depth == -1) { - _depth = 1000; - } - - Map> adjacencies = new HashMap<>(); - - for (Node node : nodes) { - adjacencies.put(node, new TreeSet<>()); - } - - for (int d = 0; d <= _depth; d++) { - boolean more; - - if (d == 0) { - more = searchAtDepth0(nodes, test, adjacencies); - } else { - more = searchAtDepth(nodes, test, adjacencies, d); - } - - if (!more) { - break; - } - } - - Graph graph = new EdgeListGraph(nodes); - - for (int i = 0; i < nodes.size(); i++) { - for (int j = i + 1; j < nodes.size(); j++) { - Node x = nodes.get(i); - Node y = nodes.get(j); - - if (adjacencies.get(x).contains(y)) { - graph.addUndirectedEdge(x, y); - } - } - } - - this.logger.log("info", "Finishing Fast Adjacency Search."); - - return graph; - } - - public int getDepth() { - return depth; - } - - public void setDepth(int depth) { - if (depth < -1) { - throw new IllegalArgumentException( - "Depth must be -1 (unlimited) or >= 0."); - } - - this.depth = depth; - } - - public Knowledge getKnowledge() { - return knowledge; - } - - public void setKnowledge(Knowledge knowledge) { - if (knowledge == null) { - throw new NullPointerException("Cannot set knowledge to null"); - } - this.knowledge = knowledge; - } - - //==============================PRIVATE METHODS======================/ - - private boolean searchAtDepth0(List nodes, IndependenceTest test, Map> adjacencies) { - Set empty = Collections.emptySet(); - for (int i = 0; i < nodes.size(); i++) { - if (verbose) { - if ((i + 1) % 100 == 0) out.println("Node # " + (i + 1)); - } - - if (Thread.currentThread().isInterrupted()) { - break; - } - - Node x = nodes.get(i); - - for (int j = i + 1; j < nodes.size(); j++) { - - Node y = nodes.get(j); - - if (initialGraph != null) { - Node x2 = initialGraph.getNode(x.getName()); - Node y2 = initialGraph.getNode(y.getName()); - - if (!initialGraph.isAdjacentTo(x2, y2)) { - continue; - } - } - - boolean independent; - - try { - numIndependenceTests++; - independent = test.checkIndependence(x, y, empty).isIndependent(); - } catch (Exception e) { - e.printStackTrace(); - independent = false; - } - - boolean noEdgeRequired = - knowledge.noEdgeRequired(x.getName(), y.getName()); - - if (independent && noEdgeRequired) { - getSepsets().set(x, y, empty); - } else if (!forbiddenEdge(x, y)) { - adjacencies.get(x).add(y); - adjacencies.get(y).add(x); - } - } - } - - return freeDegree(nodes, adjacencies) > 0; - } - - private int freeDegree(List nodes, Map> adjacencies) { - int max = 0; - - for (Node x : nodes) { - Set opposites = adjacencies.get(x); - - for (Node y : opposites) { - Set adjx = new HashSet<>(opposites); - adjx.remove(y); - - if (adjx.size() > max) { - max = adjx.size(); - } - } - } - - return max; - } - - private boolean forbiddenEdge(Node x, Node y) { - String name1 = x.getName(); - String name2 = y.getName(); - - if (knowledge.isForbidden(name1, name2) && - knowledge.isForbidden(name2, name1)) { - System.out.println(Edges.undirectedEdge(x, y) + " because it was " + - "forbidden by background knowledge."); - - return true; - } - - return false; - } - - private boolean searchAtDepth(List nodes, final IndependenceTest test, Map> adjacencies, int depth) { - int count = 0; - - for (Node x : nodes) { - if (verbose) { - if (++count % 100 == 0) out.println("count " + count + " of " + nodes.size()); - } - - if (Thread.currentThread().isInterrupted()) { - break; - } - - List adjx = new ArrayList<>(adjacencies.get(x)); - - EDGE: - for (Node y : adjx) { - List _adjx = new ArrayList<>(adjacencies.get(x)); - _adjx.remove(y); - List ppx = possibleParents(x, _adjx, knowledge); - - if (ppx.size() >= depth) { - ChoiceGenerator cg = new ChoiceGenerator(ppx.size(), depth); - int[] choice; - - while ((choice = cg.next()) != null) { - if (Thread.currentThread().isInterrupted()) { - break; - } - - Set condSet = GraphUtils.asSet(choice, ppx); - - boolean independent; - - try { - numIndependenceTests++; - independent = test.checkIndependence(x, y, condSet).isIndependent(); - } catch (Exception e) { - independent = false; - } - - boolean noEdgeRequired = - knowledge.noEdgeRequired(x.getName(), y.getName()); - - if (independent && noEdgeRequired) { - adjacencies.get(x).remove(y); - adjacencies.get(y).remove(x); - - getSepsets().set(x, y, condSet); - - continue EDGE; - } - } - } - } - } - - return freeDegree(nodes, adjacencies) > depth; - } - - private List possibleParents(Node x, List adjx, Knowledge knowledge) { - List possibleParents = new LinkedList<>(); - String _x = x.getName(); - - for (Node z : adjx) { - String _z = z.getName(); - - if (possibleParentOf(_z, _x, knowledge)) { - possibleParents.add(z); - } - } - - return possibleParents; - } - - private boolean possibleParentOf(String z, String x, Knowledge knowledge) { - return !knowledge.isForbidden(z, x) && !knowledge.isRequired(x, z); - } - - public int getNumIndependenceTests() { - return numIndependenceTests; - } - - public SepsetMap getSepsets() { - return sepset; - } - - public boolean isVerbose() { - return verbose; - } - - public void setVerbose(boolean verbose) { - this.verbose = verbose; - } - - @Override - public long getElapsedTime() { - return 0; - } - - @Override - public List getNodes() { - return test.getVariables(); - } - - @Override - public List getAmbiguousTriples(Node node) { - return null; - } - - @Override - public void setOut(PrintStream out) { - this.out = out; - } - - public void setPcHeuristicType(PcCommon.PcHeuristicType pcHeuristicType) { - this.pcHeuristicType = pcHeuristicType; - } - - public void setStable(boolean b) { - boolean stable = b; - } -} diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/work_in_progress/Fas3.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/work_in_progress/Fas3.java deleted file mode 100644 index d8801baf24..0000000000 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/work_in_progress/Fas3.java +++ /dev/null @@ -1,459 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// For information as to what this class does, see the Javadoc, below. // -// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, // -// 2007, 2008, 2009, 2010, 2014 by Peter Spirtes, Richard Scheines, Joseph // -// Ramsey, and Clark Glymour. // -// // -// This program is free software; you can redistribute it and/or modify // -// it under the terms of the GNU General Public License as published by // -// the Free Software Foundation; either version 2 of the License, or // -// (at your option) any later version. // -// // -// This program is distributed in the hope that it will be useful, // -// but WITHOUT ANY WARRANTY; without even the implied warranty of // -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // -// GNU General Public License for more details. // -// // -// You should have received a copy of the GNU General Public License // -// along with this program; if not, write to the Free Software // -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // -/////////////////////////////////////////////////////////////////////////////// - -package edu.cmu.tetrad.search.work_in_progress; - -import edu.cmu.tetrad.data.Knowledge; -import edu.cmu.tetrad.graph.*; -import edu.cmu.tetrad.search.Fci; -import edu.cmu.tetrad.search.IFas; -import edu.cmu.tetrad.search.IndependenceTest; -import edu.cmu.tetrad.search.Pc; -import edu.cmu.tetrad.search.test.IndependenceResult; -import edu.cmu.tetrad.search.utils.PcCommon; -import edu.cmu.tetrad.search.utils.SepsetMap; -import edu.cmu.tetrad.util.ChoiceGenerator; -import edu.cmu.tetrad.util.MillisecondTimes; -import edu.cmu.tetrad.util.TetradLogger; - -import java.io.PrintStream; -import java.util.*; - -/** - *

                Implements the Fast Adjacency Search (FAS), which is the adjacency search of the PC algorithm (see). This is a - * useful algorithm in many contexts, including as the first step of FCI (see).

                - * - *

                The idea of FAS is that at a given stage of the search, an edge X*-*Y is removed from the - * graph if X _||_ Y | S, where S is a subset of size d either of adj(X) or of adj(Y), where d is the depth of the - * search. The fast adjacency search performs this procedure for each pair of adjacent edges in the graph and for each - * depth d = 0, 1, 2, ..., d1, where d1 is either the maximum depth or else the first such depth at which no edges can - * be removed. The interpretation of this adjacency search is different for different algorithm, depending on the - * assumptions of the algorithm. A mapping from {x, y} to S({x, y}) is returned for edges x *-* y that have been - * removed.

                - * - *

                FAS may optionally use a heuristic from Causation, Prediction and Search, which (like PC-Stable) - * renders the output invariant to the order of the input variables.

                - * - *

                This algorithm was described in the earlier edition of this book:

                - * - *

                Spirtes, P., Glymour, C. N., Scheines, R., & Heckerman, D. (2000). Causation, prediction, and search. MIT - * press.

                - * - *

                This class is configured to respect knowledge of forbidden and required edges, including knowledge of temporal - * tiers.

                - * - * @author peterspirtes - * @author clarkglymour - * @author josephramsey. - * @see Pc - * @see Fci - * @see Knowledge - */ -public class Fas3 implements IFas { - private final IndependenceTest test; - private final TetradLogger logger = TetradLogger.getInstance(); - private Knowledge knowledge = new Knowledge(); - private int numIndependenceTests; - private SepsetMap sepset = new SepsetMap(); - private PcCommon.PcHeuristicType heuristic = PcCommon.PcHeuristicType.NONE; - private int depth = 1000; - private boolean stable = true; - private long elapsedTime = 0L; - private PrintStream out = System.out; - private boolean verbose = false; - - //==========================CONSTRUCTORS=============================// - - /** - * Constructor. - * - * @param test The test to use for oracle conditional independence test results. - */ - public Fas3(IndependenceTest test) { - this.test = test; - } - - //==========================PUBLIC METHODS===========================// - - /** - * Runs the search and returns the resulting (undirected) graph. - * - * @return This graph. - */ - @Override - public Graph search() { - return search(test.getVariables()); - } - - /** - * Discovers all adjacencies in data. The procedure is to remove edges in the graph which connect pairs of - * variables which are independent conditional on some other set of variables in the graph (the "sepset"). These are - * removed in tiers. First, edges which are independent conditional on zero other variables are removed, then edges - * which are independent conditional on one other variable are removed, then two, then three, and so on, until no - * more edges can be removed from the graph. The edges which remain in the graph after this procedure are the - * adjacencies in the data. - * - * @param nodes A list of nodes to search over. - * @return An undirected graph that summarizes the conditional independendencies that obtain in the data. - */ - public Graph search(List nodes) { - long startTime = MillisecondTimes.timeMillis(); - nodes = new ArrayList<>(nodes); - - this.logger.addOutputStream(out); - - if (verbose) { - this.logger.forceLogMessage("Starting Fast Adjacency Search."); - } - - this.test.setVerbose(this.verbose); - - int _depth = this.depth; - - if (_depth == -1) { - _depth = 1000; - } - - this.sepset = new SepsetMap(); - - List edges = new ArrayList<>(); - Map scores = new HashMap<>(); - - if (this.heuristic == PcCommon.PcHeuristicType.HEURISTIC_1) { - Collections.sort(nodes); - } - - for (int i = 0; i < nodes.size(); i++) { - for (int j = i + 1; j < nodes.size(); j++) { - edges.add(Edges.undirectedEdge(nodes.get(i), nodes.get(j))); - } - } - - for (Edge edge : edges) { - IndependenceResult result = this.test.checkIndependence(edge.getNode1(), edge.getNode2(), new HashSet<>()); - scores.put(edge, result.getScore()); - } - - if (this.heuristic == PcCommon.PcHeuristicType.HEURISTIC_2 || this.heuristic == PcCommon.PcHeuristicType.HEURISTIC_3) { - edges.sort(Comparator.comparing(scores::get)); - } - - Map> adjacencies = new HashMap<>(); - - for (Node node : nodes) { - Set set = new LinkedHashSet<>(); - - for (Node _node : nodes) { - if (_node == node) continue; - set.add(_node); - } - - adjacencies.put(node, set); - } - - for (Edge edge : new ArrayList<>(edges)) { - if (scores.get(edge) != null && scores.get(edge) < 0 - || (this.knowledge.isForbidden(edge.getNode1().getName(), edge.getNode2().getName()) - && (this.knowledge.isForbidden(edge.getNode2().getName(), edge.getNode1().getName())))) { - edges.remove(edge); - adjacencies.get(edge.getNode1()).remove(edge.getNode2()); - adjacencies.get(edge.getNode2()).remove(edge.getNode1()); - this.sepset.set(edge.getNode1(), edge.getNode2(), new HashSet<>()); - } - } - - for (int d = 0; d <= _depth; d++) { - System.out.println("Depth: " + d); - - boolean more; - - if (this.stable) { - Map> adjacenciesCopy = new HashMap<>(); - - for (Node node : adjacencies.keySet()) { - adjacenciesCopy.put(node, new LinkedHashSet<>(adjacencies.get(node))); - } - - adjacencies = adjacenciesCopy; - } - - more = searchAtDepth(scores, edges, this.test, adjacencies, d); - - if (!more) { - break; - } - } - - // The search graph. It is assumed going in that all the true adjacencies of x are in this graph for every node - // x. It is hoped (i.e. true in the large sample limit) that true adjacencies are never removed. - Graph graph = new EdgeListGraph(nodes); - - for (int i = 0; i < nodes.size(); i++) { - for (int j = i + 1; j < nodes.size(); j++) { - Node x = nodes.get(i); - Node y = nodes.get(j); - - if (adjacencies.get(x).contains(y)) { - graph.addUndirectedEdge(x, y); - } - } - } - - if (verbose) { - this.logger.forceLogMessage("Finishing Fast Adjacency Search."); - } - - this.elapsedTime = MillisecondTimes.timeMillis() - startTime; - - return graph; - } - - /** - * Sets the depth of the search, which is the maximum number of variables that ben be conditioned on in any - * conditional independence test. - * - * @param depth This maximum. - */ - public void setDepth(int depth) { - if (depth < -1) { - throw new IllegalArgumentException( - "Depth must be -1 (unlimited) or >= 0."); - } - - this.depth = depth; - } - - /** - * Sets the knowledge to be used int the search. - * - * @param knowledge This knoweldge. - * @see Knowledge - */ - public void setKnowledge(Knowledge knowledge) { - this.knowledge = new Knowledge(knowledge); - } - - /** - * Returns the number of independence tests that were done. - * - * @return This number. - */ - public int getNumIndependenceTests() { - return this.numIndependenceTests; - } - - /** - * Returns the sepsets that were discovered in the search. A 'sepset' for test X _||_ Y | Z1,...,Zm would be - * {Z1,...,Zm} - * - * @return A map of these sepsets indexed by {X, Y}. - */ - public SepsetMap getSepsets() { - return this.sepset; - } - - /** - * Sets whether verbose output should be printed. - * - * @param verbose True iff the case. - */ - public void setVerbose(boolean verbose) { - this.verbose = verbose; - } - - /** - * Returns the elapsed time of the search. - * - * @return This elapsed time. - */ - public long getElapsedTime() { - return elapsedTime; - } - - /** - * Returns the nodes from the test. - * - * @return These nodes. - */ - @Override - public List getNodes() { - return this.test.getVariables(); - } - - /** - * There are no ambiguous triples for this search, for any nodes. - * - * @param node The nodes in question. - * @return An empty list. - */ - @Override - public List getAmbiguousTriples(Node node) { - return new ArrayList<>(); - } - - /** - * @param out This print stream. - */ - @Override - public void setOut(PrintStream out) { - this.out = out; - } - - /** - * @param pcHeuristic Which PC heuristic to use (see Causation, Prediction and Search). Default is - * PcHeuristicType.NONE. - * @see PcCommon.PcHeuristicType - */ - public void setPcHeuristicType(PcCommon.PcHeuristicType pcHeuristic) { - this.heuristic = pcHeuristic; - } - - /** - *

                Sets whether the stable adjacency search should be used. Default is false. Default is false. See the - * following reference for this:

                - * - *

                Colombo, D., & Maathuis, M. H. (2014). Order-independent constraint-based causal structure learning. J. Mach. - * Learn. Res., 15(1), 3741-3782.

                - * - * @param stable True iff the case. - */ - public void setStable(boolean stable) { - this.stable = stable; - } - - //==============================PRIVATE METHODS======================/ - - private int freeDegree(Map> adjacencies) { - int max = 0; - - for (Node x : adjacencies.keySet()) { - Set opposites = adjacencies.get(x); - - for (Node y : opposites) { - Set adjx = new LinkedHashSet<>(opposites); - adjx.remove(y); - - if (adjx.size() > max) { - max = adjx.size(); - } - } - } - - return max; - } - - private boolean searchAtDepth(Map scores, List edges, IndependenceTest test, Map> adjacencies, int depth) { - - for (Edge edge : edges) { - Node x = edge.getNode1(); - Node y = edge.getNode2(); - - if (Thread.currentThread().isInterrupted()) { - break; - } - - boolean b = checkSide(scores, test, adjacencies, depth, x, y); - if (!b) checkSide(scores, test, adjacencies, depth, y, x); - } - - return freeDegree(adjacencies) > depth; - } - - private boolean checkSide(Map scores, IndependenceTest test, Map> adjacencies, int depth, Node x, Node y) { - if (!adjacencies.get(x).contains(y)) return false; - - List _adjx = new ArrayList<>(adjacencies.get(x)); - _adjx.remove(y); - - if (this.heuristic == PcCommon.PcHeuristicType.HEURISTIC_1 || this.heuristic == PcCommon.PcHeuristicType.HEURISTIC_2) { - Collections.sort(_adjx); - } - - List ppx = possibleParents(x, _adjx, this.knowledge, y); - - Map scores2 = new HashMap<>(); - - for (Node node : ppx) { - Double _score = scores.get(Edges.undirectedEdge(node, x)); - scores2.put(node, _score); - } - - if (this.heuristic == PcCommon.PcHeuristicType.HEURISTIC_3) { - ppx.sort(Comparator.comparing(scores2::get)); - Collections.reverse(ppx); - } - - Graph g0 = new EdgeListGraph(getNodes()); - - if (ppx.size() >= depth) { - ChoiceGenerator cg = new ChoiceGenerator(ppx.size(), depth); - int[] choice; - - while ((choice = cg.next()) != null) { - if (Thread.currentThread().isInterrupted()) { - break; - } - - Set Z = GraphUtils.asSet(choice, ppx); - - this.numIndependenceTests++; - - boolean independent = test.checkIndependence(x, y, Z).isIndependent(); - - boolean noEdgeRequired = this.knowledge.noEdgeRequired(x.getName(), y.getName()); - - if (independent && noEdgeRequired) { - adjacencies.get(x).remove(y); - adjacencies.get(y).remove(x); - - getSepsets().set(x, y, Z); - - return true; - } - } - } - - return false; - } - - private List possibleParents(Node x, List adjx, - Knowledge knowledge, Node y) { - List possibleParents = new LinkedList<>(); - String _x = x.getName(); - - for (Node z : adjx) { - if (z == x) continue; - if (z == y) continue; - String _z = z.getName(); - - if (possibleParentOf(_z, _x, knowledge)) { - possibleParents.add(z); - } - } - - return possibleParents; - } - - private boolean possibleParentOf(String z, String x, Knowledge knowledge) { - return !knowledge.isForbidden(z, x) && !knowledge.isRequired(x, z); - } -} - diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/util/Params.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/util/Params.java index 89b15b3a8e..ccc47ac1ec 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/util/Params.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/util/Params.java @@ -249,6 +249,7 @@ public final class Params { public static final String SAMPLE_STYLE = "sampleStyle"; public static final String NUM_THREADS = "numThreads"; public static String MIN_COUNT_PER_CELL = "minCountPerCell"; + public static String PC_HEURISTIC = "pcHeuristic"; // All parameters that are found in HTML manual documentation From b1043292e76e1d468fc603b8fa33546f14ced6d4 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Tue, 16 Jan 2024 02:57:47 -0500 Subject: [PATCH 076/163] Cleanup. Also, re-introduced the 'pcHeuristic' parameter. --- .../main/java/edu/cmu/tetrad/graph/GraphTransforms.java | 1 - tetrad-lib/src/main/java/edu/cmu/tetrad/search/SpFci.java | 8 ++++++-- .../src/main/java/edu/cmu/tetrad/search/SvarGfci.java | 8 ++++++-- .../main/java/edu/cmu/tetrad/search/utils/FciOrient.java | 8 ++++++-- .../edu/cmu/tetrad/search/utils/GraphSearchUtils.java | 2 -- .../java/edu/cmu/tetrad/search/utils/SvarFciOrient.java | 8 ++++++-- 6 files changed, 24 insertions(+), 11 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/graph/GraphTransforms.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/graph/GraphTransforms.java index 88b38e1975..50e3929e83 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/graph/GraphTransforms.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/graph/GraphTransforms.java @@ -214,7 +214,6 @@ public static Graph dagToPag(Graph trueGraph) { return new DagToPag(trueGraph).convert(); } - private static void direct(Node a, Node c, Graph graph) { Edge before = graph.getEdge(a, c); Edge after = Edges.directedEdge(a, c); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SpFci.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SpFci.java index fd33a5e157..bb93f354e3 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SpFci.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SpFci.java @@ -329,7 +329,9 @@ private void modifiedR0(Graph fgesGraph, SepsetProducer sepsets) { * Orients according to background knowledge */ private void fciOrientbk(Knowledge knowledge, Graph graph, List variables) { - this.logger.log("info", "Starting BK Orientation."); + if (verbose) { + this.logger.log("info", "Starting BK Orientation."); + } for (Iterator it = knowledge.forbiddenEdgesIterator(); it.hasNext(); ) { KnowledgeEdge edge = it.next(); @@ -371,7 +373,9 @@ private void fciOrientbk(Knowledge knowledge, Graph graph, List variables) this.logger.log("knowledgeOrientation", LogUtilsSearch.edgeOrientedMsg("Knowledge", graph.getEdge(from, to))); } - this.logger.log("info", "Finishing BK Orientation."); + if (verbose) { + this.logger.log("info", "Finishing BK Orientation."); + } } } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SvarGfci.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SvarGfci.java index 50cccb97f3..1d7c36e730 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SvarGfci.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SvarGfci.java @@ -300,7 +300,9 @@ private void modifiedR0(Graph fgesGraph) { * Orients according to background knowledge */ private void fciOrientbk(Knowledge knowledge, Graph graph, List variables) { - this.logger.log("info", "Starting BK Orientation."); + if (verbose) { + this.logger.log("info", "Starting BK Orientation."); + } for (Iterator it = knowledge.forbiddenEdgesIterator(); it.hasNext(); ) { KnowledgeEdge edge = it.next(); @@ -344,7 +346,9 @@ private void fciOrientbk(Knowledge knowledge, Graph graph, List variables) this.logger.log("knowledgeOrientation", LogUtilsSearch.edgeOrientedMsg("Knowledge", graph.getEdge(from, to))); } - this.logger.log("info", "Finishing BK Orientation."); + if (verbose) { + this.logger.log("info", "Finishing BK Orientation."); + } } private String getNameNoLag(Object obj) { diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/FciOrient.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/FciOrient.java index 59d5f48a30..7cb98280ad 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/FciOrient.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/FciOrient.java @@ -1021,7 +1021,9 @@ public boolean ruleR9(Node a, Node c, Graph graph) { * Orients according to background knowledge */ public void fciOrientbk(Knowledge bk, Graph graph, List variables) { - this.logger.forceLogMessage("Starting BK Orientation."); + if (verbose) { + this.logger.forceLogMessage("Starting BK Orientation."); + } for (Iterator it = bk.forbiddenEdgesIterator(); it.hasNext(); ) { @@ -1083,7 +1085,9 @@ public void fciOrientbk(Knowledge bk, Graph graph, List variables) { this.logger.forceLogMessage(LogUtilsSearch.edgeOrientedMsg("Knowledge", graph.getEdge(from, to))); } - this.logger.forceLogMessage("Finishing BK Orientation."); + if (verbose) { + this.logger.forceLogMessage("Finishing BK Orientation."); + } } /** diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/GraphSearchUtils.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/GraphSearchUtils.java index 168a098b65..f8027522a3 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/GraphSearchUtils.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/GraphSearchUtils.java @@ -69,8 +69,6 @@ public static void pcOrientbk(Knowledge bk, Graph graph, List nodes) { // Orient to-->from graph.removeEdge(from, to); graph.addDirectedEdge(to, from); - - TetradLogger.getInstance().log("knowledgeOrientations", LogUtilsSearch.edgeOrientedMsg("Knowledge", graph.getEdge(to, from))); } for (Iterator it = bk.requiredEdgesIterator(); it.hasNext(); ) { diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/SvarFciOrient.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/SvarFciOrient.java index b9b7b03020..adb4af7111 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/SvarFciOrient.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/SvarFciOrient.java @@ -868,7 +868,9 @@ private void ruleR10(Node a, Node c, Graph graph) { * Orients according to background knowledge */ private void fciOrientbk(Knowledge bk, Graph graph, List variables) { - this.logger.log("info", "Starting BK Orientation."); + if (verbose) { + this.logger.log("info", "Starting BK Orientation."); + } for (Iterator it = bk.forbiddenEdgesIterator(); it.hasNext(); ) { @@ -916,7 +918,9 @@ private void fciOrientbk(Knowledge bk, Graph graph, List variables) { this.logger.log("knowledgeOrientation", LogUtilsSearch.edgeOrientedMsg("Knowledge", graph.getEdge(from, to))); } - this.logger.log("info", "Finishing BK Orientation."); + if (verbose) { + this.logger.log("info", "Finishing BK Orientation."); + } } From 5a3a7568a26c15c202d89e28ffaec1ab95a7d3a9 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Wed, 17 Jan 2024 05:52:32 -0500 Subject: [PATCH 077/163] Cleanup. Also, re-introduced the 'pcHeuristic' parameter. --- .../edu/cmu/tetrad/search/MarkovCheck.java | 28 +++++++++++++++++-- .../tetrad/search/utils/SepsetsGreedy.java | 1 + 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java index 6e8ab36048..b96103caed 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java @@ -46,6 +46,8 @@ public class MarkovCheck { private double fractionDependentDep = Double.NaN; private double ksPValueIndep = Double.NaN; private double ksPValueDep = Double.NaN; + private double aSquaredIndep = Double.NaN; + private double aSquaredDep = Double.NaN; private double aSquaredStarIndep = Double.NaN; private double aSquaredStarDep = Double.NaN; private double andersonDarlingPIndep = Double.NaN; @@ -295,6 +297,20 @@ public double getKsPValue(boolean indep) { } } + /** + * Returns the Anderson-Darling A^2 statistic for the given list of results. + * + * @param indep True if for implied independencies, false if for implied dependencies. + * @return The Anderson-Darling A^2 statistic for the given list of results. + */ + public double getAndersonDarlingA2(boolean indep) { + if (indep) { + return aSquaredIndep; + } else { + return aSquaredDep; + } + } + /** * Returns the Anderson-Darling A^2* statistic for the given list of results. * @@ -598,32 +614,38 @@ private void calcStats(boolean indep) { } List pValues = getPValues(results); - double aSquaredStar = new GeneralAndersonDarlingTest(pValues, new UniformRealDistribution(0, 1)).getASquaredStar(); + GeneralAndersonDarlingTest generalAndersonDarlingTest = new GeneralAndersonDarlingTest(pValues, new UniformRealDistribution(0, 1)); + double aSquared = generalAndersonDarlingTest.getASquared(); + double aSquaredStar = generalAndersonDarlingTest.getASquaredStar(); if (indep) { if (pValues.size() < 2) { ksPValueIndep = Double.NaN; binomialPIndep = Double.NaN; + aSquaredIndep = Double.NaN; aSquaredStarIndep = Double.NaN; andersonDarlingPIndep = Double.NaN; } else { ksPValueIndep = UniformityTest.getPValue(pValues, 0.0, 1.0); binomialPIndep = getBinomialP(pValues, independenceTest.getAlpha()); + aSquaredIndep = aSquared; aSquaredStarIndep = aSquaredStar; - andersonDarlingPIndep = 1. - new GeneralAndersonDarlingTest(pValues, new UniformRealDistribution(0, 1)).getProbTail(pValues.size(), aSquaredStar); + andersonDarlingPIndep = 1. - generalAndersonDarlingTest.getProbTail(pValues.size(), aSquaredStar); } } else { if (pValues.size() < 2) { ksPValueDep = Double.NaN; binomialPDep = Double.NaN; + aSquaredDep = Double.NaN; aSquaredStarDep = Double.NaN; andersonDarlingPDep = Double.NaN; } else { ksPValueDep = UniformityTest.getPValue(pValues, 0.0, 1.0); binomialPDep = getBinomialP(pValues, independenceTest.getAlpha()); + aSquaredDep = aSquared; aSquaredStarDep = aSquaredStar; - andersonDarlingPDep = 1. - new GeneralAndersonDarlingTest(pValues, new UniformRealDistribution(0, 1)).getProbTail(pValues.size(), aSquaredStar); + andersonDarlingPDep = 1. - generalAndersonDarlingTest.getProbTail(pValues.size(), aSquaredStar); } } } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/SepsetsGreedy.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/SepsetsGreedy.java index 9b441e666a..066fa2d78e 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/SepsetsGreedy.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/SepsetsGreedy.java @@ -99,6 +99,7 @@ public boolean isVerbose() { @Override public void setVerbose(boolean verbose) { + independenceTest.setVerbose(verbose); this.verbose = verbose; } From af19c892606086eccada5625a3d3796a1677ff54 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Wed, 17 Jan 2024 10:55:48 -0500 Subject: [PATCH 078/163] Some adjustments to DiscreteBic. --- .../cmu/tetrad/search/score/DiscreteBicScore.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/DiscreteBicScore.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/DiscreteBicScore.java index 342298cf30..1b068e5497 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/DiscreteBicScore.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/DiscreteBicScore.java @@ -183,12 +183,20 @@ public double localScore(int node, int[] parents) { int cellCount = n_jk[rowIndex][childValue]; int rowCount = n_j[rowIndex]; - if (cellCount == 0) continue; + if (cellCount == 0 || rowCount == 0) continue; lik += cellCount * FastMath.log(cellCount / (double) rowCount); } } - int params = r * (c - 1); + int attestedRows = 0; + + for (int rowIndex = 0; rowIndex < r; rowIndex++) { + if (n_j[rowIndex] > 0) { + attestedRows++; + } + } + + int params = attestedRows * (c - 1); double score = 2 * lik - this.penaltyDiscount * params * FastMath.log(N) + 2 * getPriorForStructure(parents.length); From b070f92ea32472cecba2e991c3cae173cc3a7f6b Mon Sep 17 00:00:00 2001 From: jdramsey Date: Wed, 17 Jan 2024 11:00:25 -0500 Subject: [PATCH 079/163] Some adjustments to DiscreteBic. --- .../tetrad/search/score/DiscreteBicScore.java | 63 +++++++++++++++++-- 1 file changed, 59 insertions(+), 4 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/DiscreteBicScore.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/DiscreteBicScore.java index 1b068e5497..9abde25316 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/DiscreteBicScore.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/DiscreteBicScore.java @@ -211,13 +211,68 @@ public double localScore(int node, int[] parents) { * Returns the number of parameters for a node given its parents. */ public int numParameters(int node, int[] parents) { - int numRows = 1; + if (!(this.variables.get(node) instanceof DiscreteVariable)) { + throw new IllegalArgumentException("Not discrete: " + this.variables.get(node)); + } + + for (int t : parents) { + if (!(this.variables.get(t) instanceof DiscreteVariable)) { + throw new IllegalArgumentException("Not discrete: " + this.variables.get(t)); + } + } + + // Numbers of categories of parents. + int[] dims = new int[parents.length]; + + for (int p = 0; p < parents.length; p++) { + dims[p] = this.numCategories[parents[p]]; + } + + // Number of parent states. + int r = 1; + + for (int p = 0; p < parents.length; p++) { + r *= dims[p]; + } + + // Conditional cell coefs of data for node given parents(node). + int[] n_j = new int[r]; + + int[] parentValues = new int[parents.length]; + + int[][] myParents = new int[parents.length][]; + for (int i = 0; i < parents.length; i++) { + myParents[i] = this.data[parents[i]]; + } + + int[] myChild = this.data[node]; + + ROW: + for (int i = 0; i < this.sampleSize; i++) { + for (int p = 0; p < parents.length; p++) { + if (myParents[p][i] == -99) continue ROW; + parentValues[p] = myParents[p][i]; + } + + int childValue = myChild[i]; - for (int k = 0; k < parents.length; k++) { - numRows *= this.numCategories[parents[k]]; + if (childValue == -99) { + continue; + } + + int rowIndex = DiscreteBicScore.getRowIndex(dims, parentValues); + n_j[rowIndex]++; + } + + int attestedRows = 0; + + for (int rowIndex = 0; rowIndex < r; rowIndex++) { + if (n_j[rowIndex] > 0) { + attestedRows++; + } } - return numRows * (this.numCategories[node] - 1); + return attestedRows * (this.numCategories[node] - 1); } /** From d3a2669c63ad1a496dcadf19ad901281185c097e Mon Sep 17 00:00:00 2001 From: jdramsey Date: Wed, 17 Jan 2024 11:01:08 -0500 Subject: [PATCH 080/163] Some adjustments to DiscreteBic. --- .../java/edu/cmu/tetrad/search/score/DiscreteBicScore.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/DiscreteBicScore.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/DiscreteBicScore.java index 9abde25316..d166fd3148 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/DiscreteBicScore.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/DiscreteBicScore.java @@ -24,7 +24,6 @@ import edu.cmu.tetrad.data.*; import edu.cmu.tetrad.graph.Node; import edu.cmu.tetrad.search.Fges; -import edu.cmu.tetrad.util.ChoiceGenerator; import org.apache.commons.math3.util.FastMath; import javax.help.UnsupportedOperationException; @@ -34,7 +33,7 @@ import static org.apache.commons.math3.util.FastMath.log; /** - * Calculates the discrete BIC score. The likelihood for this score is calculated as SUM(ln(P(X | Z) P(Z)) across all + * Calculates the discrete BIC score. The likelihood for this score is calculated as SUM(ln(P(X | Z) P(Z))) across all * cells in all conditional probability tables for the discrete model. The parameters are counted as SUM(rows * (cols - * 1)) for all conditional probability tables in the model. Then the BIC score is calculated as 2L - ck ln N, where c is * a multiplier on the penalty ("penalty discount"). From e9acb95297cad7209cd2de506261fcb7c531ea88 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Wed, 17 Jan 2024 11:02:12 -0500 Subject: [PATCH 081/163] Some adjustments to DiscreteBic. --- .../java/edu/cmu/tetrad/search/score/DiscreteBicScore.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/DiscreteBicScore.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/DiscreteBicScore.java index d166fd3148..3bf88abb44 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/DiscreteBicScore.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/DiscreteBicScore.java @@ -35,8 +35,9 @@ /** * Calculates the discrete BIC score. The likelihood for this score is calculated as SUM(ln(P(X | Z) P(Z))) across all * cells in all conditional probability tables for the discrete model. The parameters are counted as SUM(rows * (cols - - * 1)) for all conditional probability tables in the model. Then the BIC score is calculated as 2L - ck ln N, where c is - * a multiplier on the penalty ("penalty discount"). + * 1)) for all conditional probability tables in the model, where rows summing to zero are discounted, as their marginal + * probabilities cannot be calcualted. Then the BIC score is calculated as 2L - ck ln N, where c is a multiplier on the + * penalty ("penalty discount"). * *

                As for all scores in Tetrad, higher scores mean more dependence, and negative * scores indicate independence.

                From 3902de3f37cbe56eaacdffd84eaa85be5d00fd4f Mon Sep 17 00:00:00 2001 From: jdramsey Date: Wed, 17 Jan 2024 11:14:53 -0500 Subject: [PATCH 082/163] Some adjustments to DiscreteBic. --- .../java/edu/cmu/tetrad/search/score/DiscreteBicScore.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/DiscreteBicScore.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/DiscreteBicScore.java index 3bf88abb44..d6955d5e9d 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/DiscreteBicScore.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/DiscreteBicScore.java @@ -153,8 +153,6 @@ public double localScore(int node, int[] parents) { int[] myChild = this.data[node]; - int N = 0; - ROW: for (int i = 0; i < this.sampleSize; i++) { for (int p = 0; p < parents.length; p++) { @@ -172,7 +170,6 @@ public double localScore(int node, int[] parents) { n_jk[rowIndex][childValue]++; n_j[rowIndex]++; - N++; } //Finally, compute the score @@ -198,7 +195,7 @@ public double localScore(int node, int[] parents) { int params = attestedRows * (c - 1); - double score = 2 * lik - this.penaltyDiscount * params * FastMath.log(N) + 2 * getPriorForStructure(parents.length); + double score = 2 * lik - this.penaltyDiscount * params * FastMath.log(sampleSize) + 2 * getPriorForStructure(parents.length); if (Double.isNaN(score) || Double.isInfinite(score)) { return Double.NaN; From bc8e49f0cf2edf10b5d200ab5a7d88a3edf01e41 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Fri, 19 Jan 2024 10:12:22 -0500 Subject: [PATCH 083/163] Added a version of SEM BIC score that uses pseudoinverses to avoid exceptions. --- .../score/SemBicScoreGeneralizedInverse.java | 92 +++ .../edu/cmu/tetrad/search/MarkovCheck.java | 63 +- .../score/SemBicScoreGeneralizedInverse.java | 639 ++++++++++++++++++ .../cmu/tetrad/search/test/ChiSquareTest.java | 3 +- .../java/edu/cmu/tetrad/util/MatrixUtils.java | 7 +- 5 files changed, 761 insertions(+), 43 deletions(-) create mode 100644 tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/score/SemBicScoreGeneralizedInverse.java create mode 100644 tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/SemBicScoreGeneralizedInverse.java diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/score/SemBicScoreGeneralizedInverse.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/score/SemBicScoreGeneralizedInverse.java new file mode 100644 index 0000000000..c0eeb00033 --- /dev/null +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/score/SemBicScoreGeneralizedInverse.java @@ -0,0 +1,92 @@ +package edu.cmu.tetrad.algcomparison.score; + +import edu.cmu.tetrad.annotation.LinearGaussian; +import edu.cmu.tetrad.data.DataModel; +import edu.cmu.tetrad.data.DataSet; +import edu.cmu.tetrad.data.DataType; +import edu.cmu.tetrad.data.ICovarianceMatrix; +import edu.cmu.tetrad.graph.Node; +import edu.cmu.tetrad.search.score.Score; +import edu.cmu.tetrad.util.Parameters; +import edu.cmu.tetrad.util.Params; + +import java.io.Serial; +import java.util.ArrayList; +import java.util.List; + +/** + * Wrapper for linear, Gaussian SEM BIC score. This version of the SEM BIC score uses the generalized inverse of the + * covariance matrix, which is more numerically stable than the standard inverse. + * + * @author josephramsey + */ +@edu.cmu.tetrad.annotation.Score( + name = "Sem BIC Score Generalized Inverse", + command = "sem-bic-score-gen-inv", + dataType = {DataType.Continuous, DataType.Covariance} +) +@LinearGaussian +public class SemBicScoreGeneralizedInverse implements ScoreWrapper { + + @Serial + private static final long serialVersionUID = 23L; + private DataModel dataSet; + + @Override + public Score getScore(DataModel dataSet, Parameters parameters) { + this.dataSet = dataSet; + + edu.cmu.tetrad.search.score.SemBicScoreGeneralizedInverse semBicScore; + boolean precomputeCovariances = parameters.getBoolean(Params.PRECOMPUTE_COVARIANCES); + + if (dataSet instanceof DataSet) { + semBicScore = new edu.cmu.tetrad.search.score.SemBicScoreGeneralizedInverse((DataSet) this.dataSet, precomputeCovariances); + } else if (dataSet instanceof ICovarianceMatrix) { + semBicScore = new edu.cmu.tetrad.search.score.SemBicScoreGeneralizedInverse((ICovarianceMatrix) this.dataSet); + } else { + throw new IllegalArgumentException("Expecting either a dataset or a covariance matrix."); + } + + semBicScore.setPenaltyDiscount(parameters.getDouble(Params.PENALTY_DISCOUNT)); + semBicScore.setStructurePrior(parameters.getDouble(Params.SEM_BIC_STRUCTURE_PRIOR)); + + switch (parameters.getInt(Params.SEM_BIC_RULE)) { + case 1: + semBicScore.setRuleType(edu.cmu.tetrad.search.score.SemBicScoreGeneralizedInverse.RuleType.CHICKERING); + break; + case 2: + semBicScore.setRuleType(edu.cmu.tetrad.search.score.SemBicScoreGeneralizedInverse.RuleType.NANDY); + break; + default: + throw new IllegalStateException("Expecting 1 or 2: " + parameters.getInt(Params.SEM_BIC_RULE)); + } + + return semBicScore; + } + + @Override + public String getDescription() { + return "Sem BIC Score Generalized Inverse"; + } + + @Override + public DataType getDataType() { + return DataType.Continuous; + } + + @Override + public List getParameters() { + List parameters = new ArrayList<>(); + parameters.add(Params.PENALTY_DISCOUNT); + parameters.add(Params.SEM_BIC_STRUCTURE_PRIOR); + parameters.add(Params.SEM_BIC_RULE); + parameters.add(Params.PRECOMPUTE_COVARIANCES); + return parameters; + } + + @Override + public Node getVariable(String name) { + return this.dataSet.getVariable(name); + } + +} diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java index b96103caed..0e2d1ae471 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java @@ -519,50 +519,35 @@ public Pair, Set> call() { if (independenceTest instanceof RowsSettable) { List rows = getSubsampleRows(percentResample); ((RowsSettable) independenceTest).setRows(rows); - - boolean verbose = independenceTest.isVerbose(); - independenceTest.setVerbose(false); - IndependenceResult result; - try { - result = independenceTest.checkIndependence(x, y, z); - } catch (Exception e) { - throw new RuntimeException(e); - } - boolean indep = result.isIndependent(); - double pValue = result.getPValue(); - independenceTest.setVerbose(verbose); - - if (!Double.isNaN(pValue)) { - if (msep) { - resultsIndep.add(new IndependenceResult(fact, indep, pValue, Double.NaN)); - } else { - resultsDep.add(new IndependenceResult(fact, indep, pValue, Double.NaN)); - } - } + addResults(resultsIndep, resultsDep, fact, x, y, z); } else { - boolean verbose = independenceTest.isVerbose(); - independenceTest.setVerbose(false); - IndependenceResult result; - try { - result = independenceTest.checkIndependence(x, y, z); - } catch (Exception e) { - throw new RuntimeException(e); - } - boolean indep = result.isIndependent(); - double pValue = result.getPValue(); - independenceTest.setVerbose(verbose); - - if (!Double.isNaN(pValue)) { - if (msep) { - resultsIndep.add(new IndependenceResult(fact, indep, pValue, Double.NaN)); - } else { - resultsDep.add(new IndependenceResult(fact, indep, pValue, Double.NaN)); - } - } + addResults(resultsIndep, resultsDep, fact, x, y, z); } return new Pair<>(resultsIndep, resultsDep); } + + private void addResults(Set resultsIndep, Set resultsDep, IndependenceFact fact, Node x, Node y, Set z) { + boolean verbose = independenceTest.isVerbose(); + independenceTest.setVerbose(false); + IndependenceResult result; + try { + result = independenceTest.checkIndependence(x, y, z); + } catch (Exception e) { + throw new RuntimeException(e); + } + boolean indep = result.isIndependent(); + double pValue = result.getPValue(); + independenceTest.setVerbose(verbose); + + if (!Double.isNaN(pValue)) { + if (msep) { + resultsIndep.add(new IndependenceResult(fact, indep, pValue, Double.NaN)); + } else { + resultsDep.add(new IndependenceResult(fact, indep, pValue, Double.NaN)); + } + } + } } List, Set>>> tasks = new ArrayList<>(); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/SemBicScoreGeneralizedInverse.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/SemBicScoreGeneralizedInverse.java new file mode 100644 index 0000000000..f68da6a70a --- /dev/null +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/SemBicScoreGeneralizedInverse.java @@ -0,0 +1,639 @@ +/////////////////////////////////////////////////////////////////////////////// +// For information as to what this class does, see the Javadoc, below. // +// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, // +// 2007, 2008, 2009, 2010, 2014, 2015, 2022 by Peter Spirtes, Richard // +// Scheines, Joseph Ramsey, and Clark Glymour. // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation; either version 2 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program; if not, write to the Free Software // +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // +/////////////////////////////////////////////////////////////////////////////// + +package edu.cmu.tetrad.search.score; + +import edu.cmu.tetrad.data.DataModel; +import edu.cmu.tetrad.data.DataSet; +import edu.cmu.tetrad.data.ICovarianceMatrix; +import edu.cmu.tetrad.data.SimpleDataLoader; +import edu.cmu.tetrad.graph.Node; +import edu.cmu.tetrad.search.utils.LogUtilsSearch; +import edu.cmu.tetrad.util.Matrix; +import edu.cmu.tetrad.util.MatrixUtils; +import edu.cmu.tetrad.util.StatUtils; +import edu.cmu.tetrad.util.TetradLogger; +import org.apache.commons.math3.linear.SingularMatrixException; +import org.apache.commons.math3.util.FastMath; +import org.jetbrains.annotations.NotNull; + +import java.util.*; + +import static edu.cmu.tetrad.util.MatrixUtils.convertCovToCorr; +import static java.lang.Double.NaN; +import static org.apache.commons.math3.util.FastMath.abs; +import static org.apache.commons.math3.util.FastMath.log; + +/** + * Implements the linear, Gaussian BIC score, with a 'penalty discount' multiplier on the BIC penalty. The formula used + * for the score is BIC = 2L - ck ln n, where c is the penalty discount and L is the linear, Gaussian log + * likelihood--that is, the sum of the log likelihoods of the individual records, which are assumed to be i.i.d. + *

                + * This version of the score uses the generalized inverse of the covariance matrix, which is more numerically stable + * than the standard inverse. + *

                + *

                + * For FGES, Chickering uses the standard linear, Gaussian BIC score, so we will for lack of a better reference give his + * paper: + *

                + * Chickering (2002) "Optimal structure identification with greedy search" Journal of Machine Learning Research. + *

                + * The version of the score due to Nandy et al. is given in this reference: + *

                + * Nandy, P., Hauser, A., & Maathuis, M. H. (2018). High-dimensional consistency in score-based and hybrid structure + * learning. The Annals of Statistics, 46(6A), 3151-3183. + *

                + * This score may be used anywhere though where a linear, Gaussian score is needed. Anectodally, the score is fairly + * robust to non-Gaussianity, though with some additional unfaithfulness over and above waht the score would give for + * Guassian data, a detriment that can be overcome to an extent by use a permutation algorithm such as SP, GRaSP, or + * BOSS. + *

                + * As for all scores in Tetrad, higher scores mean more dependence, and negative scores indicate independence. + * + * @author josephramsey + * @see edu.cmu.tetrad.search.Fges + * @see edu.cmu.tetrad.search.Sp + * @see edu.cmu.tetrad.search.Grasp + * @see edu.cmu.tetrad.search.Boss + */ +public class SemBicScoreGeneralizedInverse implements Score { + + // The sample size of the covariance matrix. + private final int sampleSize; + // A map from variable names to their indices. + private final Map indexMap; + private final double logN; + private boolean calculateRowSubsets; + // The dataset. + private DataModel dataModel; + // .. as matrix + private Matrix data; + // The correlation matrix. + private ICovarianceMatrix covariances; + // The variables of the covariance matrix. + private List variables; + // True if verbose output should be sent to out. + private boolean verbose; + // The penalty penaltyDiscount, 1 for standard BIC. + private double penaltyDiscount = 1.0; + + // The structure prior, 0 for standard BIC. + private double structurePrior; + + // Equivalent sample size + private Matrix matrix; + + // The rule type to use. + private RuleType ruleType = RuleType.CHICKERING; + + /** + * Constructs the score using a covariance matrix. + */ + public SemBicScoreGeneralizedInverse(ICovarianceMatrix covariances) { + if (covariances == null) { + throw new NullPointerException(); + } + + setCovariances(covariances); + this.variables = covariances.getVariables(); + this.sampleSize = covariances.getSampleSize(); + this.indexMap = indexMap(this.variables); + this.logN = log(sampleSize); + } + + /** + * Constructs the score using a covariance matrix. + */ + public SemBicScoreGeneralizedInverse(DataSet dataSet, boolean precomputeCovariances) { + + if (dataSet == null) { + throw new NullPointerException(); + } + + this.dataModel = dataSet; + this.data = dataSet.getDoubleData(); + + if (!dataSet.existsMissingValue()) { + setCovariances(getCovarianceMatrix(dataSet, precomputeCovariances)); + + this.variables = this.covariances.getVariables(); + this.sampleSize = this.covariances.getSampleSize(); + this.indexMap = indexMap(this.variables); + this.calculateRowSubsets = false; + this.logN = log(sampleSize); + return; + } + + this.variables = dataSet.getVariables(); + this.sampleSize = dataSet.getNumRows(); + this.indexMap = indexMap(this.variables); + this.calculateRowSubsets = true; + this.logN = log(sampleSize); + } + + /** + * Returns the variance of the residual of the regression of the ith variable on its parents. + * + * @param i The index of the variable. + * @param parents The indices of the parents. + * @param covariances The covariance matrix. + * @param calculateRowSubsets True if row subsets should be calculated. + * @return The variance of the residual of the regression of the ith variable on its parents. + */ + public static double getVarRy(int i, int[] parents, Matrix data, ICovarianceMatrix covariances, boolean calculateRowSubsets) + throws SingularMatrixException { + int[] all = SemBicScoreGeneralizedInverse.concat(i, parents); + Matrix cov = SemBicScoreGeneralizedInverse.getCov(SemBicScoreGeneralizedInverse.getRows(i, parents, data, calculateRowSubsets), all, all, data, covariances); + int[] pp = SemBicScoreGeneralizedInverse.indexedParents(parents); + Matrix covxx = cov.getSelection(pp, pp); + Matrix covxy = cov.getSelection(pp, new int[]{0}); + Matrix b = new Matrix(MatrixUtils.pseudoInverse(covxx.toArray())).times(covxy); + Matrix bStar = bStar(b); + return (bStar.transpose().times(cov).times(bStar).get(0, 0)); + } + + @NotNull + private static Matrix bStar(Matrix b) { + Matrix byx = new Matrix(b.getNumRows() + 1, 1); + byx.set(0, 0, 1); + for (int j = 0; j < b.getNumRows(); j++) byx.set(j + 1, 0, -b.get(j, 0)); + return byx; + } + + private static int[] indexedParents(int[] parents) { + int[] pp = new int[parents.length]; + for (int j = 0; j < pp.length; j++) pp[j] = j + 1; + return pp; + } + + private static int[] concat(int i, int[] parents) { + int[] all = new int[parents.length + 1]; + all[0] = i; + System.arraycopy(parents, 0, all, 1, parents.length); + return all; + } + + private static Matrix getCov(List rows, int[] _rows, int[] cols, Matrix data, ICovarianceMatrix covarianceMatrix) { + if (rows == null) { + return covarianceMatrix.getSelection(_rows, cols); + } + + Matrix cov = new Matrix(_rows.length, cols.length); + + for (int i = 0; i < _rows.length; i++) { + for (int j = 0; j < cols.length; j++) { + double mui = 0.0; + double muj = 0.0; + + for (int k : rows) { + mui += data.get(k, _rows[i]); + muj += data.get(k, cols[j]); + } + + mui /= rows.size() - 1; + muj /= rows.size() - 1; + + double _cov = 0.0; + + for (int k : rows) { + _cov += (data.get(k, _rows[i]) - mui) * (data.get(k, cols[j]) - muj); + } + + double mean = _cov / (rows.size()); + cov.set(i, j, mean); + } + } + + return cov; + } + + private static List getRows(int i, int[] parents, Matrix data, boolean calculateRowSubsets) { + if (!calculateRowSubsets) { + return null; + } + + List rows = new ArrayList<>(); + + K: + for (int k = 0; k < data.getNumRows(); k++) { + if (Double.isNaN(data.get(k, i))) continue; + + for (int p : parents) { + if (Double.isNaN(data.get(k, p))) continue K; + } + + rows.add(k); + } + + return rows; + } + + @NotNull + private ICovarianceMatrix getCovarianceMatrix(DataSet dataSet, boolean precomputeCovariances) { + return SimpleDataLoader.getCovarianceMatrix(dataSet, precomputeCovariances); + } + + @Override + public double localScoreDiff(int x, int y, int[] z) { + if (this.ruleType == RuleType.NANDY) { + return nandyBic(x, y, z); + } else { + return localScore(y, append(z, x)) - localScore(y, z); + } + } + + public double nandyBic(int x, int y, int[] z) { + double sp1 = getStructurePrior(z.length + 1); + double sp2 = getStructurePrior(z.length); + + Node _x = this.variables.get(x); + Node _y = this.variables.get(y); + List _z = getVariableList(z); + + List rows = getRows(x, z); + + if (rows != null) { + rows.retainAll(Objects.requireNonNull(getRows(y, z))); + } + + double r = partialCorrelation(_x, _y, _z, rows); + + double c = getPenaltyDiscount(); + + return -this.sampleSize * log(1.0 - r * r) - c * log(this.sampleSize) + - 2.0 * (sp1 - sp2); + } + + /** + * Returns the score for the given node and its parents. + * + * @param i The index of the node. + * @param parents The indices of the node's parents. + * @return The score, or NaN if the score cannot be calculated. + */ + public double localScore(int i, int... parents) { + int k = parents.length; + double lik; + + Arrays.sort(parents); + + try { + double varey = SemBicScoreGeneralizedInverse.getVarRy(i, parents, this.data, this.covariances, this.calculateRowSubsets); + lik = -(double) (this.sampleSize / 2.0) * log(varey); + } catch (SingularMatrixException e) { + System.out.println("Singularity encountered when scoring " + + LogUtilsSearch.getScoreFact(i, parents, variables)); + return Double.NaN; + } + + + double c = getPenaltyDiscount(); + + if (this.ruleType == RuleType.CHICKERING || this.ruleType == RuleType.NANDY) { + + // Standard BIC, with penalty discount and structure prior. + double _score = lik - c * (k / 2.0) * logN - getStructurePrior(k); + + if (Double.isNaN(_score) || Double.isInfinite(_score)) { + return Double.NaN; + } else { + return _score; + } + } else { + throw new IllegalStateException("That rule type is not implemented: " + this.ruleType); + } + } + + /** + * Returns the multiplier on the penalty term for this score. + * + * @return The multiplier on the penalty term for this score. + */ + public double getPenaltyDiscount() { + return this.penaltyDiscount; + } + + /** + * Sets the multiplier on the penalty term for this score. + * + * @param penaltyDiscount The multiplier on the penalty term for this score. + */ + public void setPenaltyDiscount(double penaltyDiscount) { + this.penaltyDiscount = penaltyDiscount; + } + + /** + * Returns the structure prior for this score. + * + * @return The structure prior for this score. + */ + public double getStructurePrior() { + return this.structurePrior; + } + + /** + * Sets the structure prior for this score. + * + * @param structurePrior The structure prior for this score. + */ + public void setStructurePrior(double structurePrior) { + this.structurePrior = structurePrior; + } + + /** + * Returns the covariance matrix. + * + * @return The covariance matrix. + */ + public ICovarianceMatrix getCovariances() { + return this.covariances; + } + + private void setCovariances(ICovarianceMatrix covariances) { + this.covariances = covariances; + this.matrix = this.covariances.getMatrix(); + + this.dataModel = covariances; + + } + + /** + * Returns the sample size. + * + * @return The sample size. + */ + public int getSampleSize() { + return this.sampleSize; + } + + /** + * Returns true if the given bump is an effect edge. + * + * @param bump The bump. + * @return True if the given bump is an effect edge. + */ + @Override + public boolean isEffectEdge(double bump) { + return bump > 0; + } + + /** + * Returns the data model. + * + * @return The data model. + */ + public DataModel getDataModel() { + return this.dataModel; + } + + /** + * Returns true if verbose output should be sent to out. + * + * @return True if verbose output should be sent to out. + */ + public boolean isVerbose() { + return this.verbose; + } + + /** + * Sets whether verbose output should be sent to out. + * + * @param verbose True if verbose output should be sent to out. + */ + public void setVerbose(boolean verbose) { + this.verbose = verbose; + } + + /** + * Returns the variables of the covariance matrix. + * + * @return The variables of the covariance matrix. + */ + @Override + public List getVariables() { + return new ArrayList<>(this.variables); + } + + /** + * Sets the variables of the covariance matrix. + * + * @param variables The variables of the covariance matrix. + */ + public void setVariables(List variables) { + if (this.covariances != null) { + this.covariances.setVariables(variables); + } + + this.variables = variables; + } + + /** + * Returns the maximum degree of the score. + * + * @return The maximum degree of the score. + */ + @Override + public int getMaxDegree() { + return (int) FastMath.ceil(log(this.sampleSize)); + } + + /** + * Returns true is the variables in z determine the variable y. + * + * @param z The set of nodes. + * @param y The node. + * @return True is the variables in z determine the variable y. + */ + @Override + public boolean determines(List z, Node y) { + int i = this.variables.indexOf(y); + + int[] k = new int[z.size()]; + + for (int t = 0; t < z.size(); t++) { + k[t] = this.variables.indexOf(z.get(t)); + } + + try { + localScore(i, k); + } catch (RuntimeException e) { + TetradLogger.getInstance().forceLogMessage(e.getMessage()); + return true; + } + + return false; + } + + /** + * Returns the data model. + * + * @return The data model. + */ + public DataModel getData() { + return this.dataModel; + } + + private double getStructurePrior(int parents) { + if (abs(getStructurePrior()) <= 0) { + return 0; + } else { + double p = (getStructurePrior()) / (this.variables.size()); + return -((parents) * log(p) + (this.variables.size() - (parents)) * log(1.0 - p)); + } + } + + private List getVariableList(int[] indices) { + List variables = new ArrayList<>(); + for (int i : indices) { + variables.add(this.variables.get(i)); + } + return variables; + } + + private Map indexMap(List variables) { + Map indexMap = new HashMap<>(); + + for (int i = 0; variables.size() > i; i++) { + indexMap.put(variables.get(i), i); + } + + return indexMap; + } + + private List getRows(int i, int[] parents) { + if (this.dataModel == null) { + return null; + } + + List rows = new ArrayList<>(); + + DataSet dataSet = (DataSet) this.dataModel; + + K: + for (int k = 0; k < dataSet.getNumRows(); k++) { + if (Double.isNaN(dataSet.getDouble(k, i))) continue; + + for (int p : parents) { + if (Double.isNaN(dataSet.getDouble(k, p))) continue K; + } + + rows.add(k); + } + + return rows; + } + + private double partialCorrelation(Node x, Node y, List z, List rows) { + try { + return StatUtils.partialCorrelation(convertCovToCorr(getCov(rows, indices(x, y, z)))); + } catch (Exception e) { + return NaN; + } + } + + private int[] indices(Node x, Node y, List z) { + int[] indices = new int[z.size() + 2]; + indices[0] = this.indexMap.get(x); + indices[1] = this.indexMap.get(y); + for (int i = 0; i < z.size(); i++) indices[i + 2] = this.indexMap.get(z.get(i)); + return indices; + } + + private Matrix getCov(List rows, int[] cols) { + if (this.dataModel == null) { + return this.matrix.getSelection(cols, cols); + } + + DataSet dataSet = (DataSet) this.dataModel; + + Matrix cov = new Matrix(cols.length, cols.length); + + for (int i = 0; i < cols.length; i++) { + for (int j = i + 1; j < cols.length; j++) { + double mui = 0.0; + double muj = 0.0; + + for (int k : rows) { + mui += dataSet.getDouble(k, cols[i]); + muj += dataSet.getDouble(k, cols[j]); + } + + mui /= rows.size() - 1; + muj /= rows.size() - 1; + + double _cov = 0.0; + + for (int k : rows) { + _cov += (dataSet.getDouble(k, cols[i]) - mui) * (dataSet.getDouble(k, cols[j]) - muj); + } + + double mean = _cov / (rows.size()); + cov.set(i, j, mean); + cov.set(j, i, mean); + } + } + + for (int i = 0; i < cols.length; i++) { + double mui = 0.0; + + for (int k : rows) { + mui += dataSet.getDouble(k, cols[i]); + } + + mui /= rows.size(); + + double _cov = 0.0; + + for (int k : rows) { + _cov += (dataSet.getDouble(k, cols[i]) - mui) * (dataSet.getDouble(k, cols[i]) - mui); + } + + double mean = _cov / (rows.size()); + cov.set(i, i, mean); + } + + return cov; + } + + public void setRuleType(RuleType ruleType) { + this.ruleType = ruleType; + } + + public SemBicScoreGeneralizedInverse subset(List pi2) { + int[] cols = new int[pi2.size()]; + for (int i = 0; i < cols.length; i++) { + cols[i] = variables.indexOf(pi2.get(i)); + } + ICovarianceMatrix cov = getCovariances().getSubmatrix(cols); + return new SemBicScoreGeneralizedInverse(cov); + } + + public String toString() { + return "SEM BIC Score"; + } + + /** + * Gives two options for calculating the BIC score, one describe by Chickering and the other due to Nandy et al. + */ + public enum RuleType {CHICKERING, NANDY} +} + + diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java index 17c67d7405..9d03127aac 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java @@ -29,7 +29,6 @@ import java.util.List; -import static java.lang.StrictMath.floor; import static org.apache.commons.math3.util.FastMath.log; /** @@ -157,7 +156,7 @@ public Result calcChiSquare(int[] testIndices) { for (int j = 0; j < numCols; j++) { coords[1] = j; - sumCols[j] = getCellTable().calcMargin(coords, firstVar); + sumCols[j] = getCellTable().calcMargin(coords, firstVar); if (sumCols[j] == 0 || sumCols[j] < minCountPerCell * numRows) { zeroCols[j] = true; diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/util/MatrixUtils.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/util/MatrixUtils.java index f68868fc9d..ece7bc01ff 100755 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/util/MatrixUtils.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/util/MatrixUtils.java @@ -243,8 +243,11 @@ public static double[][] inverse(double[][] m) { } public static double[][] pseudoInverse(double[][] x) { - SingularValueDecomposition svd - = new SingularValueDecomposition(new BlockRealMatrix(x)); + if (x.length == 0) { + return new Matrix(x).toArray(); + } + + SingularValueDecomposition svd = new SingularValueDecomposition(new BlockRealMatrix(x)); RealMatrix U = svd.getU(); RealMatrix V = svd.getV(); From 2f788965e3b8bd0590ae1abe388c66848f44bae4 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Fri, 19 Jan 2024 10:21:39 -0500 Subject: [PATCH 084/163] Changed "generalized inverse" to "pseudoinverse" throughout. --- .../model/AbstractMBSearchRunner.java | 4 ++-- .../cmu/tetradapp/model/IndTestChooser.java | 4 ++-- ...rse.java => SemBicScorePseudoinverse.java} | 20 +++++++++---------- ...rse.java => SemBicScorePseudoinverse.java} | 20 +++++++++---------- .../cmu/tetrad/search/utils/FgesOrienter.java | 2 +- ....java => IndTestFisherZPseudoinverse.java} | 10 +++++----- .../TestIndTestFisherGeneralizedInverse.java | 6 +++--- 7 files changed, 33 insertions(+), 33 deletions(-) rename tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/score/{SemBicScoreGeneralizedInverse.java => SemBicScorePseudoinverse.java} (82%) rename tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/{SemBicScoreGeneralizedInverse.java => SemBicScorePseudoinverse.java} (95%) rename tetrad-lib/src/main/java/edu/cmu/tetrad/search/work_in_progress/{IndTestFisherZGeneralizedInverse.java => IndTestFisherZPseudoinverse.java} (96%) diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/AbstractMBSearchRunner.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/AbstractMBSearchRunner.java index b8ebf4dd11..eb52f3eb80 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/AbstractMBSearchRunner.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/AbstractMBSearchRunner.java @@ -31,7 +31,7 @@ import edu.cmu.tetrad.search.test.IndTestFisherZ; import edu.cmu.tetrad.search.test.IndTestGSquare; import edu.cmu.tetrad.search.test.IndTestRegression; -import edu.cmu.tetrad.search.work_in_progress.IndTestFisherZGeneralizedInverse; +import edu.cmu.tetrad.search.work_in_progress.IndTestFisherZPseudoinverse; import edu.cmu.tetrad.util.Parameters; import edu.cmu.tetradapp.util.IndTestType; @@ -185,7 +185,7 @@ IndependenceTest getIndependenceTest() { return new IndTestFisherZ(this.source, this.params.getDouble("alpha", 0.001)); } if (IndTestType.FISHER_ZD == type) { - return new IndTestFisherZGeneralizedInverse(this.source, this.params.getDouble("alpha", 0.001)); + return new IndTestFisherZPseudoinverse(this.source, this.params.getDouble("alpha", 0.001)); } if (IndTestType.LINEAR_REGRESSION == type) { return new IndTestRegression(this.source, this.params.getDouble("alpha", 0.001)); diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/IndTestChooser.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/IndTestChooser.java index 3829a1bc98..737f2f809a 100755 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/IndTestChooser.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/IndTestChooser.java @@ -29,7 +29,7 @@ import edu.cmu.tetrad.search.score.SemBicScore; import edu.cmu.tetrad.search.test.*; import edu.cmu.tetrad.search.utils.ResolveSepsets; -import edu.cmu.tetrad.search.work_in_progress.IndTestFisherZGeneralizedInverse; +import edu.cmu.tetrad.search.work_in_progress.IndTestFisherZPseudoinverse; import edu.cmu.tetrad.search.work_in_progress.IndTestFisherZPercentIndependent; import edu.cmu.tetrad.search.work_in_progress.IndTestMultinomialLogisticRegression; import edu.cmu.tetrad.util.Parameters; @@ -137,7 +137,7 @@ private IndependenceTest getContinuousTest(DataSet dataSet, return new IndTestFisherZ(dataSet, params.getDouble("alpha", 0.001)); } if (IndTestType.FISHER_ZD == testType) { - return new IndTestFisherZGeneralizedInverse(dataSet, params.getDouble("alpha", 0.001)); + return new IndTestFisherZPseudoinverse(dataSet, params.getDouble("alpha", 0.001)); } if (IndTestType.SEM_BIC == testType) { return new ScoreIndTest(new SemBicScore(new CovarianceMatrix(dataSet))); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/score/SemBicScoreGeneralizedInverse.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/score/SemBicScorePseudoinverse.java similarity index 82% rename from tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/score/SemBicScoreGeneralizedInverse.java rename to tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/score/SemBicScorePseudoinverse.java index c0eeb00033..4fbcbeac72 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/score/SemBicScoreGeneralizedInverse.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/score/SemBicScorePseudoinverse.java @@ -15,18 +15,18 @@ import java.util.List; /** - * Wrapper for linear, Gaussian SEM BIC score. This version of the SEM BIC score uses the generalized inverse of the + * Wrapper for linear, Gaussian SEM BIC score. This version of the SEM BIC score uses the pseudoinverse of the * covariance matrix, which is more numerically stable than the standard inverse. * * @author josephramsey */ @edu.cmu.tetrad.annotation.Score( - name = "Sem BIC Score Generalized Inverse", - command = "sem-bic-score-gen-inv", + name = "Sem BIC Score Pseudoinverse", + command = "sem-bic-score-pseudoinverse", dataType = {DataType.Continuous, DataType.Covariance} ) @LinearGaussian -public class SemBicScoreGeneralizedInverse implements ScoreWrapper { +public class SemBicScorePseudoinverse implements ScoreWrapper { @Serial private static final long serialVersionUID = 23L; @@ -36,13 +36,13 @@ public class SemBicScoreGeneralizedInverse implements ScoreWrapper { public Score getScore(DataModel dataSet, Parameters parameters) { this.dataSet = dataSet; - edu.cmu.tetrad.search.score.SemBicScoreGeneralizedInverse semBicScore; + edu.cmu.tetrad.search.score.SemBicScorePseudoinverse semBicScore; boolean precomputeCovariances = parameters.getBoolean(Params.PRECOMPUTE_COVARIANCES); if (dataSet instanceof DataSet) { - semBicScore = new edu.cmu.tetrad.search.score.SemBicScoreGeneralizedInverse((DataSet) this.dataSet, precomputeCovariances); + semBicScore = new edu.cmu.tetrad.search.score.SemBicScorePseudoinverse((DataSet) this.dataSet, precomputeCovariances); } else if (dataSet instanceof ICovarianceMatrix) { - semBicScore = new edu.cmu.tetrad.search.score.SemBicScoreGeneralizedInverse((ICovarianceMatrix) this.dataSet); + semBicScore = new edu.cmu.tetrad.search.score.SemBicScorePseudoinverse((ICovarianceMatrix) this.dataSet); } else { throw new IllegalArgumentException("Expecting either a dataset or a covariance matrix."); } @@ -52,10 +52,10 @@ public Score getScore(DataModel dataSet, Parameters parameters) { switch (parameters.getInt(Params.SEM_BIC_RULE)) { case 1: - semBicScore.setRuleType(edu.cmu.tetrad.search.score.SemBicScoreGeneralizedInverse.RuleType.CHICKERING); + semBicScore.setRuleType(edu.cmu.tetrad.search.score.SemBicScorePseudoinverse.RuleType.CHICKERING); break; case 2: - semBicScore.setRuleType(edu.cmu.tetrad.search.score.SemBicScoreGeneralizedInverse.RuleType.NANDY); + semBicScore.setRuleType(edu.cmu.tetrad.search.score.SemBicScorePseudoinverse.RuleType.NANDY); break; default: throw new IllegalStateException("Expecting 1 or 2: " + parameters.getInt(Params.SEM_BIC_RULE)); @@ -66,7 +66,7 @@ public Score getScore(DataModel dataSet, Parameters parameters) { @Override public String getDescription() { - return "Sem BIC Score Generalized Inverse"; + return "Sem BIC Score Pseudoinverse"; } @Override diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/SemBicScoreGeneralizedInverse.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/SemBicScorePseudoinverse.java similarity index 95% rename from tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/SemBicScoreGeneralizedInverse.java rename to tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/SemBicScorePseudoinverse.java index f68da6a70a..0788fb19bb 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/SemBicScoreGeneralizedInverse.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/SemBicScorePseudoinverse.java @@ -47,7 +47,7 @@ * for the score is BIC = 2L - ck ln n, where c is the penalty discount and L is the linear, Gaussian log * likelihood--that is, the sum of the log likelihoods of the individual records, which are assumed to be i.i.d. *

                - * This version of the score uses the generalized inverse of the covariance matrix, which is more numerically stable + * This version of the score uses the pseudoinverse of the covariance matrix, which is more numerically stable * than the standard inverse. *

                *

                @@ -74,7 +74,7 @@ * @see edu.cmu.tetrad.search.Grasp * @see edu.cmu.tetrad.search.Boss */ -public class SemBicScoreGeneralizedInverse implements Score { +public class SemBicScorePseudoinverse implements Score { // The sample size of the covariance matrix. private final int sampleSize; @@ -107,7 +107,7 @@ public class SemBicScoreGeneralizedInverse implements Score { /** * Constructs the score using a covariance matrix. */ - public SemBicScoreGeneralizedInverse(ICovarianceMatrix covariances) { + public SemBicScorePseudoinverse(ICovarianceMatrix covariances) { if (covariances == null) { throw new NullPointerException(); } @@ -122,7 +122,7 @@ public SemBicScoreGeneralizedInverse(ICovarianceMatrix covariances) { /** * Constructs the score using a covariance matrix. */ - public SemBicScoreGeneralizedInverse(DataSet dataSet, boolean precomputeCovariances) { + public SemBicScorePseudoinverse(DataSet dataSet, boolean precomputeCovariances) { if (dataSet == null) { throw new NullPointerException(); @@ -160,9 +160,9 @@ public SemBicScoreGeneralizedInverse(DataSet dataSet, boolean precomputeCovarian */ public static double getVarRy(int i, int[] parents, Matrix data, ICovarianceMatrix covariances, boolean calculateRowSubsets) throws SingularMatrixException { - int[] all = SemBicScoreGeneralizedInverse.concat(i, parents); - Matrix cov = SemBicScoreGeneralizedInverse.getCov(SemBicScoreGeneralizedInverse.getRows(i, parents, data, calculateRowSubsets), all, all, data, covariances); - int[] pp = SemBicScoreGeneralizedInverse.indexedParents(parents); + int[] all = SemBicScorePseudoinverse.concat(i, parents); + Matrix cov = SemBicScorePseudoinverse.getCov(SemBicScorePseudoinverse.getRows(i, parents, data, calculateRowSubsets), all, all, data, covariances); + int[] pp = SemBicScorePseudoinverse.indexedParents(parents); Matrix covxx = cov.getSelection(pp, pp); Matrix covxy = cov.getSelection(pp, new int[]{0}); Matrix b = new Matrix(MatrixUtils.pseudoInverse(covxx.toArray())).times(covxy); @@ -296,7 +296,7 @@ public double localScore(int i, int... parents) { Arrays.sort(parents); try { - double varey = SemBicScoreGeneralizedInverse.getVarRy(i, parents, this.data, this.covariances, this.calculateRowSubsets); + double varey = SemBicScorePseudoinverse.getVarRy(i, parents, this.data, this.covariances, this.calculateRowSubsets); lik = -(double) (this.sampleSize / 2.0) * log(varey); } catch (SingularMatrixException e) { System.out.println("Singularity encountered when scoring " + @@ -617,13 +617,13 @@ public void setRuleType(RuleType ruleType) { this.ruleType = ruleType; } - public SemBicScoreGeneralizedInverse subset(List pi2) { + public SemBicScorePseudoinverse subset(List pi2) { int[] cols = new int[pi2.size()]; for (int i = 0; i < cols.length; i++) { cols[i] = variables.indexOf(pi2.get(i)); } ICovarianceMatrix cov = getCovariances().getSubmatrix(cols); - return new SemBicScoreGeneralizedInverse(cov); + return new SemBicScorePseudoinverse(cov); } public String toString() { diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/FgesOrienter.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/FgesOrienter.java index d91ab15023..5e8be11fc8 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/FgesOrienter.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/FgesOrienter.java @@ -1436,7 +1436,7 @@ private double localSemScore(int i, int[] parents) { covxxInv = covxx.inverse(); } catch (Exception e) { printMinimalLinearlyDependentSet(parents, cov); - this.out.println("Using generalized inverse."); + this.out.println("Using pseudoinverse."); covxxInv = covxx.ginverse(); } Vector covxy = getSelection2(cov, parents, i); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/work_in_progress/IndTestFisherZGeneralizedInverse.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/work_in_progress/IndTestFisherZPseudoinverse.java similarity index 96% rename from tetrad-lib/src/main/java/edu/cmu/tetrad/search/work_in_progress/IndTestFisherZGeneralizedInverse.java rename to tetrad-lib/src/main/java/edu/cmu/tetrad/search/work_in_progress/IndTestFisherZPseudoinverse.java index f7dafb2aa7..1c5760108b 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/work_in_progress/IndTestFisherZGeneralizedInverse.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/work_in_progress/IndTestFisherZPseudoinverse.java @@ -44,13 +44,13 @@ /** * Checks independence of X _||_ Y | Z for variables X and Y and list Z of variables. Partial correlations are - * calculated using generalized inverses, so linearly dependent variables do not throw exceptions. Must supply a + * calculated using pseudoinverses, so linearly dependent variables do not throw exceptions. Must supply a * continuous data set; don't know how to do this with covariance or correlation matrices. * * @author josephramsey * @author Frank Wimberly adapted IndTestCramerT for Fisher's Z */ -public final class IndTestFisherZGeneralizedInverse implements IndependenceTest { +public final class IndTestFisherZPseudoinverse implements IndependenceTest { /** * Formats as 0.0000. @@ -88,7 +88,7 @@ public final class IndTestFisherZGeneralizedInverse implements IndependenceTest * @param dataSet A data set containing only continuous columns. * @param alpha The alpha level of the test. */ - public IndTestFisherZGeneralizedInverse(DataSet dataSet, double alpha) { + public IndTestFisherZPseudoinverse(DataSet dataSet, double alpha) { if (!(alpha >= 0 && alpha <= 1)) { throw new IllegalArgumentException("Alpha mut be in [0, 1]"); } @@ -259,7 +259,7 @@ public List getVariables() { public String toString() { - return "Fisher's Z - Generalized Inverse, alpha = " + IndTestFisherZGeneralizedInverse.nf.format(getAlpha()); + return "Fisher's Z - Pseudoinverse, alpha = " + IndTestFisherZPseudoinverse.nf.format(getAlpha()); } /** @@ -360,7 +360,7 @@ public boolean determines(List zList, Node xVar) { sb.append("}"); // sb.append(" p = ").append(nf.format(p)); - sb.append(" SSE = ").append(IndTestFisherZGeneralizedInverse.nf.format(SSE)); + sb.append(" SSE = ").append(IndTestFisherZPseudoinverse.nf.format(SSE)); TetradLogger.getInstance().log("independencies", sb.toString()); System.out.println(sb); diff --git a/tetrad-lib/src/test/java/edu/cmu/tetrad/test/TestIndTestFisherGeneralizedInverse.java b/tetrad-lib/src/test/java/edu/cmu/tetrad/test/TestIndTestFisherGeneralizedInverse.java index 7cc0119326..b8b3469f70 100644 --- a/tetrad-lib/src/test/java/edu/cmu/tetrad/test/TestIndTestFisherGeneralizedInverse.java +++ b/tetrad-lib/src/test/java/edu/cmu/tetrad/test/TestIndTestFisherGeneralizedInverse.java @@ -25,7 +25,7 @@ import edu.cmu.tetrad.graph.*; import edu.cmu.tetrad.search.IndependenceTest; import edu.cmu.tetrad.search.test.IndependenceResult; -import edu.cmu.tetrad.search.work_in_progress.IndTestFisherZGeneralizedInverse; +import edu.cmu.tetrad.search.work_in_progress.IndTestFisherZPseudoinverse; import edu.cmu.tetrad.sem.SemIm; import edu.cmu.tetrad.sem.SemPm; import edu.cmu.tetrad.util.RandomUtil; @@ -77,8 +77,8 @@ public void testDirections() { DataSet data1 = im1.simulateData(500, false); DataSet data2 = im2.simulateData(500, false); - IndependenceTest test1 = new IndTestFisherZGeneralizedInverse(data1, 0.05); - IndependenceTest test2 = new IndTestFisherZGeneralizedInverse(data2, 0.05); + IndependenceTest test1 = new IndTestFisherZPseudoinverse(data1, 0.05); + IndependenceTest test2 = new IndTestFisherZPseudoinverse(data2, 0.05); IndependenceResult result1 = test1.checkIndependence(data1.getVariable(x.getName()), data1.getVariable(y.getName())); double p1 = result1.getPValue(); From 26acea6506e0de8188063c66438fa84a2120f1a9 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Fri, 19 Jan 2024 11:32:56 -0500 Subject: [PATCH 085/163] Adding Knowledge to Markov Checker. In this knowledge, we consider independence facts X _||_ Y | Z. Here, X and Y can range over the variables in the last tier, and Z can range over the variables in previous tiers. --- .../tetradapp/editor/MarkovCheckEditor.java | 40 +- .../algcomparison/score/SemBicScore.java | 2 + .../score/SemBicScorePseudoinverse.java | 92 --- .../edu/cmu/tetrad/search/MarkovCheck.java | 109 ++- .../cmu/tetrad/search/score/SemBicScore.java | 21 +- .../score/SemBicScorePseudoinverse.java | 639 ------------------ .../main/java/edu/cmu/tetrad/util/Params.java | 1 + .../src/main/resources/docs/manual/index.html | 26 + 8 files changed, 165 insertions(+), 765 deletions(-) delete mode 100644 tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/score/SemBicScorePseudoinverse.java delete mode 100644 tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/SemBicScorePseudoinverse.java diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java index 2f8939557b..0e0e47e204 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java @@ -83,7 +83,7 @@ public class MarkovCheckEditor extends JPanel { private JLabel fractionDepLabelDep; private JLabel ksLabelDep; private JLabel ksLabelIndep; -// private JLabel masLabelDep; + // private JLabel masLabelDep; // private JLabel masLabelIndep; private JLabel binomialPLabelDep; private JLabel binomialPLabelIndep; @@ -192,7 +192,7 @@ public void watch() { setTest(); Graph _graph = model.getGraph(); - Graph graph = GraphUtils.replaceNodes(_graph, model.getMarkovCheck().getVariables()); + Graph graph = GraphUtils.replaceNodes(_graph, model.getMarkovCheck().getVariables(model.getGraph().getNodes(), model.getMarkovCheck().getIndependenceNodes(), model.getMarkovCheck().getConditioningNodes())); JPanel indep = buildGuiIndep(); JPanel dep = buildGuiDep(); @@ -201,7 +201,7 @@ public void watch() { tableModelDep.fireTableDataChanged(); Graph sourceGraph = model.getGraph(); - List variables = model.getMarkovCheck().getVariables(); + List variables = model.getMarkovCheck().getVariables(model.getGraph().getNodes(), model.getMarkovCheck().getIndependenceNodes(), model.getMarkovCheck().getConditioningNodes()); List newVars = new ArrayList<>(); @@ -321,23 +321,6 @@ public void watch() { add(box); } - private void refreshResult(MarkovCheckIndTestModel model, DoubleTextField percent) { - setTest(); - model.getMarkovCheck().setPercentResample(percent.getValue()); - model.getMarkovCheck().generateResults(); - tableModelIndep.fireTableDataChanged(); - tableModelDep.fireTableDataChanged(); - histogramPanelDep.removeAll(); - histogramPanelIndep.removeAll(); - histogramPanelDep.add(createHistogramPanel(false), BorderLayout.CENTER); - histogramPanelIndep.add(createHistogramPanel(true), BorderLayout.CENTER); - histogramPanelDep.validate(); - histogramPanelIndep.validate(); - histogramPanelDep.repaint(); - histogramPanelIndep.repaint(); - setLabelTexts(); - } - @NotNull private static String getHelpMessage() { return "This tool lets you plot statistics for independence tests of a pair of variables given some conditioning calculated for one of those variables, for a given graph and dataset. Two tables are made, one in which the independence facts predicted by the graph using these conditioning sets are tested in the data and the other in which the graph's predicted dependence facts are tested. The first of these sets is a check for \"Markov\" (a check for implied independence facts) for the chosen conditioning sets; the is a check of the \"Dependent Distribution.\" (a check of implied dependence facts)”\n" + @@ -357,6 +340,23 @@ private static String getHelpMessage() { "A note about Markov Blankets: The \"Markov Blanket\" conditioning set choice implements the Markov blanket calculation in a way that is correct for DAGs, CPDAGs, MAGs, and PAGs. For all of these graph types, the list of m-connecting facts in the Faithfulness tab should be empty, since the Markov blanket should screen off the target from any other variables in the dataset. It's possible that for some other graph types this list may not be empty (i.e., the Markov blanket calculation may not be correct)."; } + private void refreshResult(MarkovCheckIndTestModel model, DoubleTextField percent) { + setTest(); + model.getMarkovCheck().setPercentResample(percent.getValue()); + model.getMarkovCheck().generateResults(); + tableModelIndep.fireTableDataChanged(); + tableModelDep.fireTableDataChanged(); + histogramPanelDep.removeAll(); + histogramPanelIndep.removeAll(); + histogramPanelDep.add(createHistogramPanel(false), BorderLayout.CENTER); + histogramPanelIndep.add(createHistogramPanel(true), BorderLayout.CENTER); + histogramPanelDep.validate(); + histogramPanelIndep.validate(); + histogramPanelDep.repaint(); + histogramPanelIndep.repaint(); + setLabelTexts(); + } + //========================PUBLIC METHODS==========================// private void setTest() { diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/score/SemBicScore.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/score/SemBicScore.java index be60ded960..214d97f7b6 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/score/SemBicScore.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/score/SemBicScore.java @@ -46,6 +46,7 @@ public Score getScore(DataModel dataSet, Parameters parameters) { semBicScore.setPenaltyDiscount(parameters.getDouble(Params.PENALTY_DISCOUNT)); semBicScore.setStructurePrior(parameters.getDouble(Params.SEM_BIC_STRUCTURE_PRIOR)); + semBicScore.setUsePseudoInverse(parameters.getBoolean(Params.USE_PSEUDOINVERSE)); switch (parameters.getInt(Params.SEM_BIC_RULE)) { case 1: @@ -78,6 +79,7 @@ public List getParameters() { parameters.add(Params.SEM_BIC_STRUCTURE_PRIOR); parameters.add(Params.SEM_BIC_RULE); parameters.add(Params.PRECOMPUTE_COVARIANCES); + parameters.add(Params.USE_PSEUDOINVERSE); return parameters; } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/score/SemBicScorePseudoinverse.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/score/SemBicScorePseudoinverse.java deleted file mode 100644 index 4fbcbeac72..0000000000 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/score/SemBicScorePseudoinverse.java +++ /dev/null @@ -1,92 +0,0 @@ -package edu.cmu.tetrad.algcomparison.score; - -import edu.cmu.tetrad.annotation.LinearGaussian; -import edu.cmu.tetrad.data.DataModel; -import edu.cmu.tetrad.data.DataSet; -import edu.cmu.tetrad.data.DataType; -import edu.cmu.tetrad.data.ICovarianceMatrix; -import edu.cmu.tetrad.graph.Node; -import edu.cmu.tetrad.search.score.Score; -import edu.cmu.tetrad.util.Parameters; -import edu.cmu.tetrad.util.Params; - -import java.io.Serial; -import java.util.ArrayList; -import java.util.List; - -/** - * Wrapper for linear, Gaussian SEM BIC score. This version of the SEM BIC score uses the pseudoinverse of the - * covariance matrix, which is more numerically stable than the standard inverse. - * - * @author josephramsey - */ -@edu.cmu.tetrad.annotation.Score( - name = "Sem BIC Score Pseudoinverse", - command = "sem-bic-score-pseudoinverse", - dataType = {DataType.Continuous, DataType.Covariance} -) -@LinearGaussian -public class SemBicScorePseudoinverse implements ScoreWrapper { - - @Serial - private static final long serialVersionUID = 23L; - private DataModel dataSet; - - @Override - public Score getScore(DataModel dataSet, Parameters parameters) { - this.dataSet = dataSet; - - edu.cmu.tetrad.search.score.SemBicScorePseudoinverse semBicScore; - boolean precomputeCovariances = parameters.getBoolean(Params.PRECOMPUTE_COVARIANCES); - - if (dataSet instanceof DataSet) { - semBicScore = new edu.cmu.tetrad.search.score.SemBicScorePseudoinverse((DataSet) this.dataSet, precomputeCovariances); - } else if (dataSet instanceof ICovarianceMatrix) { - semBicScore = new edu.cmu.tetrad.search.score.SemBicScorePseudoinverse((ICovarianceMatrix) this.dataSet); - } else { - throw new IllegalArgumentException("Expecting either a dataset or a covariance matrix."); - } - - semBicScore.setPenaltyDiscount(parameters.getDouble(Params.PENALTY_DISCOUNT)); - semBicScore.setStructurePrior(parameters.getDouble(Params.SEM_BIC_STRUCTURE_PRIOR)); - - switch (parameters.getInt(Params.SEM_BIC_RULE)) { - case 1: - semBicScore.setRuleType(edu.cmu.tetrad.search.score.SemBicScorePseudoinverse.RuleType.CHICKERING); - break; - case 2: - semBicScore.setRuleType(edu.cmu.tetrad.search.score.SemBicScorePseudoinverse.RuleType.NANDY); - break; - default: - throw new IllegalStateException("Expecting 1 or 2: " + parameters.getInt(Params.SEM_BIC_RULE)); - } - - return semBicScore; - } - - @Override - public String getDescription() { - return "Sem BIC Score Pseudoinverse"; - } - - @Override - public DataType getDataType() { - return DataType.Continuous; - } - - @Override - public List getParameters() { - List parameters = new ArrayList<>(); - parameters.add(Params.PENALTY_DISCOUNT); - parameters.add(Params.SEM_BIC_STRUCTURE_PRIOR); - parameters.add(Params.SEM_BIC_RULE); - parameters.add(Params.PRECOMPUTE_COVARIANCES); - return parameters; - } - - @Override - public Node getVariable(String name) { - return this.dataSet.getVariable(name); - } - -} diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java index 0e2d1ae471..3e616d46c3 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java @@ -1,6 +1,7 @@ package edu.cmu.tetrad.search; import edu.cmu.tetrad.data.GeneralAndersonDarlingTest; +import edu.cmu.tetrad.data.Knowledge; import edu.cmu.tetrad.graph.Graph; import edu.cmu.tetrad.graph.GraphUtils; import edu.cmu.tetrad.graph.IndependenceFact; @@ -58,6 +59,11 @@ public class MarkovCheck { private int numTestsindep = 0; private int numTestsDep = 0; + // A knowledge object to specify independence and conditioning ranges. Empty by default. + private Knowledge knowledge = new Knowledge(); + private List independenceNodes; + private List conditioningNodes; + /** * Constructor. Takes a graph and an independence test over the variables of the graph. * @@ -69,6 +75,8 @@ public MarkovCheck(Graph graph, IndependenceTest independenceTest, ConditioningS this.graph = GraphUtils.replaceNodes(graph, independenceTest.getVariables()); this.independenceTest = independenceTest; this.setType = setType; + this.independenceNodes = new ArrayList<>(independenceTest.getVariables()); + this.conditioningNodes = new ArrayList<>(independenceTest.getVariables()); } /** @@ -78,8 +86,8 @@ public MarkovCheck(Graph graph, IndependenceTest independenceTest, ConditioningS * @return The set of independence facts used in the Markov check, for dsepation and dconnection separately. */ @NotNull - public static AllSubsetsIndependenceFacts getAllSubsetsIndependenceFacts(Graph graph) { - List variables = new ArrayList<>(graph.getNodes()); + public AllSubsetsIndependenceFacts getAllSubsetsIndependenceFacts(Graph graph) { + List variables = new ArrayList<>(getVariables(graph.getNodes(), independenceNodes, conditioningNodes)); for (Node node : variables) { if (node == null) throw new NullPointerException("Null node in graph."); @@ -118,6 +126,24 @@ public static AllSubsetsIndependenceFacts getAllSubsetsIndependenceFacts(Graph g return new AllSubsetsIndependenceFacts(msep, mconn); } + /** + * Returns the variables of the independence test. + * + * @return The variables of the independence test. + */ + public List getVariables(List graphNodes, List independenceNodes, List conditioningNodes) { + List vars = new ArrayList<>(graphNodes); + + conditioningNodes = new ArrayList<>(conditioningNodes); + independenceNodes = new ArrayList<>(independenceNodes); + + List sublistedVariables = independenceNodes; + sublistedVariables.addAll(conditioningNodes); + vars.retainAll(sublistedVariables); + + return vars; + } + /** * Generates all results, for both the local Markov and local Faithfulness checks, for each node in the graph given * the parents of that node. These results are stored in the resultsIndep and resultsDep lists. This should be @@ -134,7 +160,7 @@ public void generateResults() { generateResultsAllSubsets(result.msep, result.mconn); generateResultsAllSubsets(result.msep, result.mconn); } else { - List variables = independenceTest.getVariables(); + List variables = getVariables(graph.getNodes(), independenceNodes, conditioningNodes); List nodes = new ArrayList<>(variables); List order = null; @@ -367,15 +393,6 @@ public int getNumTests(boolean indep) { } } - /** - * Returns the variables of the independence test. - * - * @return The variables of the independence test. - */ - public List getVariables() { - return new ArrayList<>(independenceTest.getVariables()); - } - /** * Returns the variable with the given name. * @@ -399,7 +416,7 @@ public IndependenceTest getIndependenceTest() { * Sets the percentage of all samples to use when resampling for each conditional independence test. * * @param percentResample The percentage of all samples to use when resampling for each conditional independence - * test. + * test. */ public void setPercentResample(double percentResample) { this.percentResample = percentResample; @@ -716,6 +733,72 @@ private List getResultsLocal(boolean indep) { } } + public Knowledge getKnowledge() { + return knowledge; + } + + /** + * Sets the knowledge object for the Markov checker. The knowledge object should contain the tier knowledge for the + * Markov checker. The last tier contains the possible X and Y for X _||_ Y | Z1,..,Zn, and the previous tiers + * contain the possible Z1,..,Zn for X _||_ Y | Z1,..,Zn. + * + * @param knowledge The knowledge object. + */ + public void setKnowledge(Knowledge knowledge) { + if (!(knowledge.getListOfExplicitlyForbiddenEdges().isEmpty() && knowledge.getListOfRequiredEdges().isEmpty())) { + throw new IllegalArgumentException("Knowledge object for the Markov checker cannot contain required of " + + "explicitly forbidden edges; only tier knowledge is used. The last tier contains the possible X " + + "and Y for X _||_ Y | Z1,..,Zn, and the previous tiers contain the possible Z1,..,Zn for X _||_ Y " + + "| Z1,..,Zn."); + } + + List independenceNames = knowledge.getTier(knowledge.getNumTiers() - 1); + + List conditioningNames = new ArrayList<>(); + for (int i = 0; i < knowledge.getNumTiers() - 1; i++) { + conditioningNames.addAll(knowledge.getTier(i)); + } + + List independenceNodes = new ArrayList<>(); + for (String name : independenceNames) { + Node variable = getVariable(name); + if (variable != null) { + independenceNodes.add(variable); + } + } + + List conditioningNodes = new ArrayList<>(); + for (String name : conditioningNames) { + Node variable = getVariable(name); + if (variable != null) { + conditioningNodes.add(variable); + } + } + + this.independenceNodes = independenceNodes; + this.conditioningNodes = conditioningNodes; + + this.knowledge = knowledge.copy(); + } + + /** + * Returns the nodes that are possible X and Y for X _||_ Y | Z1,..,Zn. + * + * @return The nodes that are possible X and Y for X _||_ Y | Z1,..,Zn. + */ + public List getIndependenceNodes() { + return independenceNodes; + } + + /** + * Returns the nodes that are possible Z1,..,Zn for X _||_ Y | Z1,..,Zn. + * + * @return The nodes that are possible Z1,..,Zn for X _||_ Y | Z1,..,Zn. + */ + public List getConditioningNodes() { + return conditioningNodes; + } + /** * Stores the set of m-separation facts and the set of m-connection facts for a graph, for the global check. */ diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/SemBicScore.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/SemBicScore.java index 45f1db7438..6fb7f4a17b 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/SemBicScore.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/SemBicScore.java @@ -28,6 +28,7 @@ import edu.cmu.tetrad.graph.Node; import edu.cmu.tetrad.search.utils.LogUtilsSearch; import edu.cmu.tetrad.util.Matrix; +import edu.cmu.tetrad.util.MatrixUtils; import edu.cmu.tetrad.util.StatUtils; import edu.cmu.tetrad.util.TetradLogger; import org.apache.commons.math3.linear.SingularMatrixException; @@ -99,6 +100,10 @@ public class SemBicScore implements Score { // The rule type to use. private RuleType ruleType = RuleType.CHICKERING; + // True iff the pseudo-inverse should be used instead of the inverse to avoid exceptions. + private static boolean usePseudoInverse = false; + + /** * Constructs the score using a covariance matrix. */ @@ -160,7 +165,17 @@ public static double getVarRy(int i, int[] parents, Matrix data, ICovarianceMatr int[] pp = SemBicScore.indexedParents(parents); Matrix covxx = cov.getSelection(pp, pp); Matrix covxy = cov.getSelection(pp, new int[]{0}); - Matrix b = (covxx.inverse().times(covxy)); + + Matrix b; + + if (usePseudoInverse) { + b = b = new Matrix(MatrixUtils.pseudoInverse(covxx.toArray())).times(covxy); + } else { + b = covxx.inverse().times(covxy); + } + + +// Matrix b = (covxx.inverse().times(covxy)); Matrix bStar = bStar(b); return (bStar.transpose().times(cov).times(bStar).get(0, 0)); } @@ -241,6 +256,10 @@ private static List getRows(int i, int[] parents, Matrix data, boolean return rows; } + public static void setUsePseudoInverse(boolean usePseudoInverse) { + SemBicScore.usePseudoInverse = usePseudoInverse; + } + @NotNull private ICovarianceMatrix getCovarianceMatrix(DataSet dataSet, boolean precomputeCovariances) { return SimpleDataLoader.getCovarianceMatrix(dataSet, precomputeCovariances); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/SemBicScorePseudoinverse.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/SemBicScorePseudoinverse.java deleted file mode 100644 index 0788fb19bb..0000000000 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/SemBicScorePseudoinverse.java +++ /dev/null @@ -1,639 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// For information as to what this class does, see the Javadoc, below. // -// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, // -// 2007, 2008, 2009, 2010, 2014, 2015, 2022 by Peter Spirtes, Richard // -// Scheines, Joseph Ramsey, and Clark Glymour. // -// // -// This program is free software; you can redistribute it and/or modify // -// it under the terms of the GNU General Public License as published by // -// the Free Software Foundation; either version 2 of the License, or // -// (at your option) any later version. // -// // -// This program is distributed in the hope that it will be useful, // -// but WITHOUT ANY WARRANTY; without even the implied warranty of // -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // -// GNU General Public License for more details. // -// // -// You should have received a copy of the GNU General Public License // -// along with this program; if not, write to the Free Software // -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // -/////////////////////////////////////////////////////////////////////////////// - -package edu.cmu.tetrad.search.score; - -import edu.cmu.tetrad.data.DataModel; -import edu.cmu.tetrad.data.DataSet; -import edu.cmu.tetrad.data.ICovarianceMatrix; -import edu.cmu.tetrad.data.SimpleDataLoader; -import edu.cmu.tetrad.graph.Node; -import edu.cmu.tetrad.search.utils.LogUtilsSearch; -import edu.cmu.tetrad.util.Matrix; -import edu.cmu.tetrad.util.MatrixUtils; -import edu.cmu.tetrad.util.StatUtils; -import edu.cmu.tetrad.util.TetradLogger; -import org.apache.commons.math3.linear.SingularMatrixException; -import org.apache.commons.math3.util.FastMath; -import org.jetbrains.annotations.NotNull; - -import java.util.*; - -import static edu.cmu.tetrad.util.MatrixUtils.convertCovToCorr; -import static java.lang.Double.NaN; -import static org.apache.commons.math3.util.FastMath.abs; -import static org.apache.commons.math3.util.FastMath.log; - -/** - * Implements the linear, Gaussian BIC score, with a 'penalty discount' multiplier on the BIC penalty. The formula used - * for the score is BIC = 2L - ck ln n, where c is the penalty discount and L is the linear, Gaussian log - * likelihood--that is, the sum of the log likelihoods of the individual records, which are assumed to be i.i.d. - *

                - * This version of the score uses the pseudoinverse of the covariance matrix, which is more numerically stable - * than the standard inverse. - *

                - *

                - * For FGES, Chickering uses the standard linear, Gaussian BIC score, so we will for lack of a better reference give his - * paper: - *

                - * Chickering (2002) "Optimal structure identification with greedy search" Journal of Machine Learning Research. - *

                - * The version of the score due to Nandy et al. is given in this reference: - *

                - * Nandy, P., Hauser, A., & Maathuis, M. H. (2018). High-dimensional consistency in score-based and hybrid structure - * learning. The Annals of Statistics, 46(6A), 3151-3183. - *

                - * This score may be used anywhere though where a linear, Gaussian score is needed. Anectodally, the score is fairly - * robust to non-Gaussianity, though with some additional unfaithfulness over and above waht the score would give for - * Guassian data, a detriment that can be overcome to an extent by use a permutation algorithm such as SP, GRaSP, or - * BOSS. - *

                - * As for all scores in Tetrad, higher scores mean more dependence, and negative scores indicate independence. - * - * @author josephramsey - * @see edu.cmu.tetrad.search.Fges - * @see edu.cmu.tetrad.search.Sp - * @see edu.cmu.tetrad.search.Grasp - * @see edu.cmu.tetrad.search.Boss - */ -public class SemBicScorePseudoinverse implements Score { - - // The sample size of the covariance matrix. - private final int sampleSize; - // A map from variable names to their indices. - private final Map indexMap; - private final double logN; - private boolean calculateRowSubsets; - // The dataset. - private DataModel dataModel; - // .. as matrix - private Matrix data; - // The correlation matrix. - private ICovarianceMatrix covariances; - // The variables of the covariance matrix. - private List variables; - // True if verbose output should be sent to out. - private boolean verbose; - // The penalty penaltyDiscount, 1 for standard BIC. - private double penaltyDiscount = 1.0; - - // The structure prior, 0 for standard BIC. - private double structurePrior; - - // Equivalent sample size - private Matrix matrix; - - // The rule type to use. - private RuleType ruleType = RuleType.CHICKERING; - - /** - * Constructs the score using a covariance matrix. - */ - public SemBicScorePseudoinverse(ICovarianceMatrix covariances) { - if (covariances == null) { - throw new NullPointerException(); - } - - setCovariances(covariances); - this.variables = covariances.getVariables(); - this.sampleSize = covariances.getSampleSize(); - this.indexMap = indexMap(this.variables); - this.logN = log(sampleSize); - } - - /** - * Constructs the score using a covariance matrix. - */ - public SemBicScorePseudoinverse(DataSet dataSet, boolean precomputeCovariances) { - - if (dataSet == null) { - throw new NullPointerException(); - } - - this.dataModel = dataSet; - this.data = dataSet.getDoubleData(); - - if (!dataSet.existsMissingValue()) { - setCovariances(getCovarianceMatrix(dataSet, precomputeCovariances)); - - this.variables = this.covariances.getVariables(); - this.sampleSize = this.covariances.getSampleSize(); - this.indexMap = indexMap(this.variables); - this.calculateRowSubsets = false; - this.logN = log(sampleSize); - return; - } - - this.variables = dataSet.getVariables(); - this.sampleSize = dataSet.getNumRows(); - this.indexMap = indexMap(this.variables); - this.calculateRowSubsets = true; - this.logN = log(sampleSize); - } - - /** - * Returns the variance of the residual of the regression of the ith variable on its parents. - * - * @param i The index of the variable. - * @param parents The indices of the parents. - * @param covariances The covariance matrix. - * @param calculateRowSubsets True if row subsets should be calculated. - * @return The variance of the residual of the regression of the ith variable on its parents. - */ - public static double getVarRy(int i, int[] parents, Matrix data, ICovarianceMatrix covariances, boolean calculateRowSubsets) - throws SingularMatrixException { - int[] all = SemBicScorePseudoinverse.concat(i, parents); - Matrix cov = SemBicScorePseudoinverse.getCov(SemBicScorePseudoinverse.getRows(i, parents, data, calculateRowSubsets), all, all, data, covariances); - int[] pp = SemBicScorePseudoinverse.indexedParents(parents); - Matrix covxx = cov.getSelection(pp, pp); - Matrix covxy = cov.getSelection(pp, new int[]{0}); - Matrix b = new Matrix(MatrixUtils.pseudoInverse(covxx.toArray())).times(covxy); - Matrix bStar = bStar(b); - return (bStar.transpose().times(cov).times(bStar).get(0, 0)); - } - - @NotNull - private static Matrix bStar(Matrix b) { - Matrix byx = new Matrix(b.getNumRows() + 1, 1); - byx.set(0, 0, 1); - for (int j = 0; j < b.getNumRows(); j++) byx.set(j + 1, 0, -b.get(j, 0)); - return byx; - } - - private static int[] indexedParents(int[] parents) { - int[] pp = new int[parents.length]; - for (int j = 0; j < pp.length; j++) pp[j] = j + 1; - return pp; - } - - private static int[] concat(int i, int[] parents) { - int[] all = new int[parents.length + 1]; - all[0] = i; - System.arraycopy(parents, 0, all, 1, parents.length); - return all; - } - - private static Matrix getCov(List rows, int[] _rows, int[] cols, Matrix data, ICovarianceMatrix covarianceMatrix) { - if (rows == null) { - return covarianceMatrix.getSelection(_rows, cols); - } - - Matrix cov = new Matrix(_rows.length, cols.length); - - for (int i = 0; i < _rows.length; i++) { - for (int j = 0; j < cols.length; j++) { - double mui = 0.0; - double muj = 0.0; - - for (int k : rows) { - mui += data.get(k, _rows[i]); - muj += data.get(k, cols[j]); - } - - mui /= rows.size() - 1; - muj /= rows.size() - 1; - - double _cov = 0.0; - - for (int k : rows) { - _cov += (data.get(k, _rows[i]) - mui) * (data.get(k, cols[j]) - muj); - } - - double mean = _cov / (rows.size()); - cov.set(i, j, mean); - } - } - - return cov; - } - - private static List getRows(int i, int[] parents, Matrix data, boolean calculateRowSubsets) { - if (!calculateRowSubsets) { - return null; - } - - List rows = new ArrayList<>(); - - K: - for (int k = 0; k < data.getNumRows(); k++) { - if (Double.isNaN(data.get(k, i))) continue; - - for (int p : parents) { - if (Double.isNaN(data.get(k, p))) continue K; - } - - rows.add(k); - } - - return rows; - } - - @NotNull - private ICovarianceMatrix getCovarianceMatrix(DataSet dataSet, boolean precomputeCovariances) { - return SimpleDataLoader.getCovarianceMatrix(dataSet, precomputeCovariances); - } - - @Override - public double localScoreDiff(int x, int y, int[] z) { - if (this.ruleType == RuleType.NANDY) { - return nandyBic(x, y, z); - } else { - return localScore(y, append(z, x)) - localScore(y, z); - } - } - - public double nandyBic(int x, int y, int[] z) { - double sp1 = getStructurePrior(z.length + 1); - double sp2 = getStructurePrior(z.length); - - Node _x = this.variables.get(x); - Node _y = this.variables.get(y); - List _z = getVariableList(z); - - List rows = getRows(x, z); - - if (rows != null) { - rows.retainAll(Objects.requireNonNull(getRows(y, z))); - } - - double r = partialCorrelation(_x, _y, _z, rows); - - double c = getPenaltyDiscount(); - - return -this.sampleSize * log(1.0 - r * r) - c * log(this.sampleSize) - - 2.0 * (sp1 - sp2); - } - - /** - * Returns the score for the given node and its parents. - * - * @param i The index of the node. - * @param parents The indices of the node's parents. - * @return The score, or NaN if the score cannot be calculated. - */ - public double localScore(int i, int... parents) { - int k = parents.length; - double lik; - - Arrays.sort(parents); - - try { - double varey = SemBicScorePseudoinverse.getVarRy(i, parents, this.data, this.covariances, this.calculateRowSubsets); - lik = -(double) (this.sampleSize / 2.0) * log(varey); - } catch (SingularMatrixException e) { - System.out.println("Singularity encountered when scoring " + - LogUtilsSearch.getScoreFact(i, parents, variables)); - return Double.NaN; - } - - - double c = getPenaltyDiscount(); - - if (this.ruleType == RuleType.CHICKERING || this.ruleType == RuleType.NANDY) { - - // Standard BIC, with penalty discount and structure prior. - double _score = lik - c * (k / 2.0) * logN - getStructurePrior(k); - - if (Double.isNaN(_score) || Double.isInfinite(_score)) { - return Double.NaN; - } else { - return _score; - } - } else { - throw new IllegalStateException("That rule type is not implemented: " + this.ruleType); - } - } - - /** - * Returns the multiplier on the penalty term for this score. - * - * @return The multiplier on the penalty term for this score. - */ - public double getPenaltyDiscount() { - return this.penaltyDiscount; - } - - /** - * Sets the multiplier on the penalty term for this score. - * - * @param penaltyDiscount The multiplier on the penalty term for this score. - */ - public void setPenaltyDiscount(double penaltyDiscount) { - this.penaltyDiscount = penaltyDiscount; - } - - /** - * Returns the structure prior for this score. - * - * @return The structure prior for this score. - */ - public double getStructurePrior() { - return this.structurePrior; - } - - /** - * Sets the structure prior for this score. - * - * @param structurePrior The structure prior for this score. - */ - public void setStructurePrior(double structurePrior) { - this.structurePrior = structurePrior; - } - - /** - * Returns the covariance matrix. - * - * @return The covariance matrix. - */ - public ICovarianceMatrix getCovariances() { - return this.covariances; - } - - private void setCovariances(ICovarianceMatrix covariances) { - this.covariances = covariances; - this.matrix = this.covariances.getMatrix(); - - this.dataModel = covariances; - - } - - /** - * Returns the sample size. - * - * @return The sample size. - */ - public int getSampleSize() { - return this.sampleSize; - } - - /** - * Returns true if the given bump is an effect edge. - * - * @param bump The bump. - * @return True if the given bump is an effect edge. - */ - @Override - public boolean isEffectEdge(double bump) { - return bump > 0; - } - - /** - * Returns the data model. - * - * @return The data model. - */ - public DataModel getDataModel() { - return this.dataModel; - } - - /** - * Returns true if verbose output should be sent to out. - * - * @return True if verbose output should be sent to out. - */ - public boolean isVerbose() { - return this.verbose; - } - - /** - * Sets whether verbose output should be sent to out. - * - * @param verbose True if verbose output should be sent to out. - */ - public void setVerbose(boolean verbose) { - this.verbose = verbose; - } - - /** - * Returns the variables of the covariance matrix. - * - * @return The variables of the covariance matrix. - */ - @Override - public List getVariables() { - return new ArrayList<>(this.variables); - } - - /** - * Sets the variables of the covariance matrix. - * - * @param variables The variables of the covariance matrix. - */ - public void setVariables(List variables) { - if (this.covariances != null) { - this.covariances.setVariables(variables); - } - - this.variables = variables; - } - - /** - * Returns the maximum degree of the score. - * - * @return The maximum degree of the score. - */ - @Override - public int getMaxDegree() { - return (int) FastMath.ceil(log(this.sampleSize)); - } - - /** - * Returns true is the variables in z determine the variable y. - * - * @param z The set of nodes. - * @param y The node. - * @return True is the variables in z determine the variable y. - */ - @Override - public boolean determines(List z, Node y) { - int i = this.variables.indexOf(y); - - int[] k = new int[z.size()]; - - for (int t = 0; t < z.size(); t++) { - k[t] = this.variables.indexOf(z.get(t)); - } - - try { - localScore(i, k); - } catch (RuntimeException e) { - TetradLogger.getInstance().forceLogMessage(e.getMessage()); - return true; - } - - return false; - } - - /** - * Returns the data model. - * - * @return The data model. - */ - public DataModel getData() { - return this.dataModel; - } - - private double getStructurePrior(int parents) { - if (abs(getStructurePrior()) <= 0) { - return 0; - } else { - double p = (getStructurePrior()) / (this.variables.size()); - return -((parents) * log(p) + (this.variables.size() - (parents)) * log(1.0 - p)); - } - } - - private List getVariableList(int[] indices) { - List variables = new ArrayList<>(); - for (int i : indices) { - variables.add(this.variables.get(i)); - } - return variables; - } - - private Map indexMap(List variables) { - Map indexMap = new HashMap<>(); - - for (int i = 0; variables.size() > i; i++) { - indexMap.put(variables.get(i), i); - } - - return indexMap; - } - - private List getRows(int i, int[] parents) { - if (this.dataModel == null) { - return null; - } - - List rows = new ArrayList<>(); - - DataSet dataSet = (DataSet) this.dataModel; - - K: - for (int k = 0; k < dataSet.getNumRows(); k++) { - if (Double.isNaN(dataSet.getDouble(k, i))) continue; - - for (int p : parents) { - if (Double.isNaN(dataSet.getDouble(k, p))) continue K; - } - - rows.add(k); - } - - return rows; - } - - private double partialCorrelation(Node x, Node y, List z, List rows) { - try { - return StatUtils.partialCorrelation(convertCovToCorr(getCov(rows, indices(x, y, z)))); - } catch (Exception e) { - return NaN; - } - } - - private int[] indices(Node x, Node y, List z) { - int[] indices = new int[z.size() + 2]; - indices[0] = this.indexMap.get(x); - indices[1] = this.indexMap.get(y); - for (int i = 0; i < z.size(); i++) indices[i + 2] = this.indexMap.get(z.get(i)); - return indices; - } - - private Matrix getCov(List rows, int[] cols) { - if (this.dataModel == null) { - return this.matrix.getSelection(cols, cols); - } - - DataSet dataSet = (DataSet) this.dataModel; - - Matrix cov = new Matrix(cols.length, cols.length); - - for (int i = 0; i < cols.length; i++) { - for (int j = i + 1; j < cols.length; j++) { - double mui = 0.0; - double muj = 0.0; - - for (int k : rows) { - mui += dataSet.getDouble(k, cols[i]); - muj += dataSet.getDouble(k, cols[j]); - } - - mui /= rows.size() - 1; - muj /= rows.size() - 1; - - double _cov = 0.0; - - for (int k : rows) { - _cov += (dataSet.getDouble(k, cols[i]) - mui) * (dataSet.getDouble(k, cols[j]) - muj); - } - - double mean = _cov / (rows.size()); - cov.set(i, j, mean); - cov.set(j, i, mean); - } - } - - for (int i = 0; i < cols.length; i++) { - double mui = 0.0; - - for (int k : rows) { - mui += dataSet.getDouble(k, cols[i]); - } - - mui /= rows.size(); - - double _cov = 0.0; - - for (int k : rows) { - _cov += (dataSet.getDouble(k, cols[i]) - mui) * (dataSet.getDouble(k, cols[i]) - mui); - } - - double mean = _cov / (rows.size()); - cov.set(i, i, mean); - } - - return cov; - } - - public void setRuleType(RuleType ruleType) { - this.ruleType = ruleType; - } - - public SemBicScorePseudoinverse subset(List pi2) { - int[] cols = new int[pi2.size()]; - for (int i = 0; i < cols.length; i++) { - cols[i] = variables.indexOf(pi2.get(i)); - } - ICovarianceMatrix cov = getCovariances().getSubmatrix(cols); - return new SemBicScorePseudoinverse(cov); - } - - public String toString() { - return "SEM BIC Score"; - } - - /** - * Gives two options for calculating the BIC score, one describe by Chickering and the other due to Nandy et al. - */ - public enum RuleType {CHICKERING, NANDY} -} - - diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/util/Params.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/util/Params.java index ccc47ac1ec..7b490dce63 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/util/Params.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/util/Params.java @@ -248,6 +248,7 @@ public final class Params { public static final String REMOVE_EFFECT_NODES = "removeEffectNodes"; public static final String SAMPLE_STYLE = "sampleStyle"; public static final String NUM_THREADS = "numThreads"; + public static final String USE_PSEUDOINVERSE = "usePseudoinverse"; public static String MIN_COUNT_PER_CELL = "minCountPerCell"; public static String PC_HEURISTIC = "pcHeuristic"; diff --git a/tetrad-lib/src/main/resources/docs/manual/index.html b/tetrad-lib/src/main/resources/docs/manual/index.html index 55b9dc5eb1..aa64fc87fd 100755 --- a/tetrad-lib/src/main/resources/docs/manual/index.html +++ b/tetrad-lib/src/main/resources/docs/manual/index.html @@ -6022,6 +6022,32 @@

                ia

                id="includePositiveSkewsForBeta_value_type">Boolean
              +

              usePseudoinverse

              +
                +
              • Short Description: + Yes if the pseudoinverse should be used to avoid exceptions +
              • +
              • Long Description: + Yes if the pseudoinverse should be used in place of the regular + inverse in calculating residual variances to avoid singularity + exceptions +
              • +
              • Default Value: false
              • +
              • Lower Bound:
              • +
              • Upper + Bound:
              • +
              • Value + Type: Boolean
              • +
              +

              intervalBetweenRecordings

                Date: Fri, 19 Jan 2024 11:57:40 -0500 Subject: [PATCH 086/163] Adding Knowledge to Markov Checker. In this knowledge, we consider independence facts X _||_ Y | Z. Here, X and Y can range over the variables in the last tier, and Z can range over the variables in previous tiers. --- .../java/edu/cmu/tetrad/search/MarkovCheck.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java index 3e616d46c3..8f2c315504 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java @@ -114,6 +114,11 @@ public AllSubsetsIndependenceFacts getAllSubsetsIndependenceFacts(Graph graph) { while ((list = generator.next()) != null) { Set z = GraphUtils.asSet(list, _other); + if (!(getIndependenceNodes().contains(x) && getIndependenceNodes().contains(y) + && new HashSet<>(getConditioningNodes()).containsAll(z))) { + continue; + } + if (msepTest.isMSeparated(x, y, z)) { msep.add(new IndependenceFact(x, y, z)); } else { @@ -147,7 +152,8 @@ public List getVariables(List graphNodes, List independenceNod /** * Generates all results, for both the local Markov and local Faithfulness checks, for each node in the graph given * the parents of that node. These results are stored in the resultsIndep and resultsDep lists. This should be - * called before any of the results methods. + * called before any of the results methods. Note that only results for X _||_ Y | Z1,..,Zn are generated, where X + * and Y are in the independenceNodes list and Z1,..,Zn are in the conditioningNodes list. * * @see #getResults(boolean) */ @@ -218,6 +224,12 @@ public void generateResults() { for (Node w : other) { if (w == x || w == y) continue; if (z.contains(x) || z.contains(y) || z.contains(w)) continue; + + if (!(getIndependenceNodes().contains(x) && getIndependenceNodes().contains(y) + && new HashSet<>(getConditioningNodes()).containsAll(z))) { + continue; + } + allIndependenceFacts.add(new IndependenceFact(x, y, z)); } } From 45d427b3bd7c6bc50c03ee9e32675df8d536c8d0 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Fri, 19 Jan 2024 14:47:13 -0500 Subject: [PATCH 087/163] Adding Knowledge to Markov Checker. In this knowledge, we consider independence facts X _||_ Y | Z. Here, X and Y can range over the variables in the last tier, and Z can range over the variables in previous tiers. --- .../tetradapp/editor/MarkovCheckEditor.java | 41 +++++++++---------- .../algorithm/oracle/cpdag/Pc.java | 25 ++++------- .../algcomparison/score/SemBicScore.java | 2 + .../edu/cmu/tetrad/search/MarkovCheck.java | 5 +-- .../cmu/tetrad/search/score/SemBicScore.java | 25 ++++++++--- 5 files changed, 52 insertions(+), 46 deletions(-) diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java index 0e0e47e204..a6b0885da4 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java @@ -31,10 +31,7 @@ import edu.cmu.tetrad.search.IndependenceTest; import edu.cmu.tetrad.search.test.IndependenceResult; import edu.cmu.tetrad.search.test.MsepTest; -import edu.cmu.tetrad.util.NumberFormatUtil; -import edu.cmu.tetrad.util.ParamDescription; -import edu.cmu.tetrad.util.ParamDescriptions; -import edu.cmu.tetrad.util.Parameters; +import edu.cmu.tetrad.util.*; import edu.cmu.tetradapp.model.MarkovCheckIndTestModel; import edu.cmu.tetradapp.ui.PaddingPanel; import edu.cmu.tetradapp.ui.model.IndependenceTestModel; @@ -48,6 +45,7 @@ import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.JTableHeader; import java.awt.*; +import java.awt.Point; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.lang.reflect.InvocationTargetException; @@ -83,8 +81,6 @@ public class MarkovCheckEditor extends JPanel { private JLabel fractionDepLabelDep; private JLabel ksLabelDep; private JLabel ksLabelIndep; - // private JLabel masLabelDep; -// private JLabel masLabelIndep; private JLabel binomialPLabelDep; private JLabel binomialPLabelIndep; private JLabel andersonDarlingA2LabelDep; @@ -323,21 +319,22 @@ public void watch() { @NotNull private static String getHelpMessage() { - return "This tool lets you plot statistics for independence tests of a pair of variables given some conditioning calculated for one of those variables, for a given graph and dataset. Two tables are made, one in which the independence facts predicted by the graph using these conditioning sets are tested in the data and the other in which the graph's predicted dependence facts are tested. The first of these sets is a check for \"Markov\" (a check for implied independence facts) for the chosen conditioning sets; the is a check of the \"Dependent Distribution.\" (a check of implied dependence facts)”\n" + - "\n" + - "Each table gives columns for the independence fact being checked, its test result, and its statistic. This statistic is either a p-value, ranging from 0 to 1, where p-values above the alpha level of the test are judged as independent, or a score bump, where this bump is negative for independent judgments and positive for dependent judgments.\n" + - "\n" + - "If the independence test yields a p-value, as for instance, for the Fisher Z test (for the linear, Gaussian case) or else the Chi-Square test (for the multinomial case), then under the null hypothesis of independence and for a consistent test, these p-values should be distributed as Uniform(0, 1). That is, it should be just as likely to see p-values in any range of equal width. If the test is inconsistent or the graph is incorrect (i.e., the parents of some or all of the nodes in the graph are incorrect), then this distribution of p-values will not be Uniform. To visualize this, we display the histogram of the p-values with equally sized bins; the bars in this histogram, for this case, should ideally all be of equal height.\n" + - "\n" + - "If the first bar in this histogram is especially high (for the p-value case), that means that many tests are being judged as dependent. For checking the dependent distribution, one hopes that this list is non-empty, in which case this first bar will be especially high, since high p-values are for examples where the graph is unfaithful to the distribution. These are likely for for cases where paths in the graph cancel unfaithfully. But for checking Markov, one hopes that this first bar will be the same height as all of the other bars.\n" + - "\n" + - "To make it especially clear, we give two statistics in the interface. The first is the percentage of p-values judged dependent on the test. If an alpha level is used in the test, this number should be very close to the alpha level for the Local Markov check since the distribution of p-values under this condition is Uniform. For the second, we test the Uniformity of the p-values using a Kolmogorov-Smirnov test. The p-value returned by this test should be greater than the user’s preferred alpha level if the distribution of p-values is Uniform and less then this alpha level if the distribution of p-values is non-Uniform.\n" + - "\n" + - "If the independence test yields a bump in the score, this score should be negative for independence judgments and positive for dependence judgments. The histogram will reflect this.\n" + - "\n" + - "Feel free to select all of the data in the tables, copy it, and paste it into a text file or into Excel. This will let you analyze the data yourself.\n" + - "\n" + - "A note about Markov Blankets: The \"Markov Blanket\" conditioning set choice implements the Markov blanket calculation in a way that is correct for DAGs, CPDAGs, MAGs, and PAGs. For all of these graph types, the list of m-connecting facts in the Faithfulness tab should be empty, since the Markov blanket should screen off the target from any other variables in the dataset. It's possible that for some other graph types this list may not be empty (i.e., the Markov blanket calculation may not be correct)."; + return """ + This tool lets you plot statistics for independence tests of a pair of variables given some conditioning calculated for one of those variables, for a given graph and dataset. Two tables are made, one in which the independence facts predicted by the graph using these conditioning sets are tested in the data and the other in which the graph's predicted dependence facts are tested. The first of these sets is a check for "Markov" (a check for implied independence facts) for the chosen conditioning sets; the is a check of the "Dependent Distribution." (a check of implied dependence facts)” + + Each table gives columns for the independence fact being checked, its test result, and its statistic. This statistic is either a p-value, ranging from 0 to 1, where p-values above the alpha level of the test are judged as independent, or a score bump, where this bump is negative for independent judgments and positive for dependent judgments. + + If the independence test yields a p-value, as for instance, for the Fisher Z test (for the linear, Gaussian case) or else the Chi-Square test (for the multinomial case), then under the null hypothesis of independence and for a consistent test, these p-values should be distributed as Uniform(0, 1). That is, it should be just as likely to see p-values in any range of equal width. If the test is inconsistent or the graph is incorrect (i.e., the parents of some or all of the nodes in the graph are incorrect), then this distribution of p-values will not be Uniform. To visualize this, we display the histogram of the p-values with equally sized bins; the bars in this histogram, for this case, should ideally all be of equal height. + + If the first bar in this histogram is especially high (for the p-value case), that means that many tests are being judged as dependent. For checking the dependent distribution, one hopes that this list is non-empty, in which case this first bar will be especially high, since high p-values are for examples where the graph is unfaithful to the distribution. These are likely for for cases where paths in the graph cancel unfaithfully. But for checking Markov, one hopes that this first bar will be the same height as all of the other bars. + + To make it especially clear, we give two statistics in the interface. The first is the percentage of p-values judged dependent on the test. If an alpha level is used in the test, this number should be very close to the alpha level for the Local Markov check since the distribution of p-values under this condition is Uniform. For the second, we test the Uniformity of the p-values using a Kolmogorov-Smirnov test. The p-value returned by this test should be greater than the user’s preferred alpha level if the distribution of p-values is Uniform and less then this alpha level if the distribution of p-values is non-Uniform. + + If the independence test yields a bump in the score, this score should be negative for independence judgments and positive for dependence judgments. The histogram will reflect this. + + Feel free to select all of the data in the tables, copy it, and paste it into a text file or into Excel. This will let you analyze the data yourself. + + A note about Markov Blankets: The "Markov Blanket" conditioning set choice implements the Markov blanket calculation in a way that is correct for DAGs, CPDAGs, MAGs, and PAGs. For all of these graph types, the list of m-connecting facts in the Faithfulness tab should be empty, since the Markov blanket should screen off the target from any other variables in the dataset. It's possible that for some other graph types this list may not be empty (i.e., the Markov blanket calculation may not be correct)."""; } private void refreshResult(MarkovCheckIndTestModel model, DoubleTextField percent) { @@ -376,7 +373,7 @@ private void setTest() { repaint(); } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e1) { - e1.printStackTrace(); + TetradLogger.getInstance().forceLogMessage("Error: " + e1.getMessage()); throw new RuntimeException(e1); } } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/Pc.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/Pc.java index af654e4205..b1607fb99d 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/Pc.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/Pc.java @@ -20,6 +20,7 @@ import edu.cmu.tetrad.util.Params; import edu.pitt.dbmi.algo.resampling.GeneralResamplingTest; +import java.io.Serial; import java.util.ArrayList; import java.util.List; @@ -38,6 +39,7 @@ @Bootstrapping public class Pc implements Algorithm, HasKnowledge, TakesIndependenceWrapper, ReturnsBootstrapGraphs { + @Serial private static final long serialVersionUID = 23L; private IndependenceWrapper test; private Knowledge knowledge = new Knowledge(); @@ -63,22 +65,13 @@ public Graph search(DataModel dataModel, Parameters parameters) { knowledge = timeSeries.getKnowledge(); } - PcCommon.ConflictRule conflictRule; - - switch (parameters.getInt(Params.CONFLICT_RULE)) { - case 1: - conflictRule = PcCommon.ConflictRule.PRIORITIZE_EXISTING; - break; - case 2: - conflictRule = PcCommon.ConflictRule.ORIENT_BIDIRECTED; - break; - case 3: - conflictRule = PcCommon.ConflictRule.OVERWRITE_EXISTING; - break; - default: - throw new IllegalArgumentException("Unknown conflict rule: " + parameters.getInt(Params.CONFLICT_RULE)); - - } + PcCommon.ConflictRule conflictRule = switch (parameters.getInt(Params.CONFLICT_RULE)) { + case 1 -> PcCommon.ConflictRule.PRIORITIZE_EXISTING; + case 2 -> PcCommon.ConflictRule.ORIENT_BIDIRECTED; + case 3 -> PcCommon.ConflictRule.OVERWRITE_EXISTING; + default -> + throw new IllegalArgumentException("Unknown conflict rule: " + parameters.getInt(Params.CONFLICT_RULE)); + }; PcCommon.PcHeuristicType pcHeuristicType = switch (parameters.getInt(Params.PC_HEURISTIC)) { case 0 -> PcCommon.PcHeuristicType.NONE; diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/score/SemBicScore.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/score/SemBicScore.java index 214d97f7b6..ab6d0c6bab 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/score/SemBicScore.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/score/SemBicScore.java @@ -10,6 +10,7 @@ import edu.cmu.tetrad.util.Parameters; import edu.cmu.tetrad.util.Params; +import java.io.Serial; import java.util.ArrayList; import java.util.List; @@ -26,6 +27,7 @@ @LinearGaussian public class SemBicScore implements ScoreWrapper { + @Serial private static final long serialVersionUID = 23L; private DataModel dataSet; diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java index 8f2c315504..362faa69aa 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java @@ -82,11 +82,10 @@ public MarkovCheck(Graph graph, IndependenceTest independenceTest, ConditioningS /** * Returns the set of independence facts used in the Markov check, for dsepation and dconnection separately. * - * @param graph The graph. * @return The set of independence facts used in the Markov check, for dsepation and dconnection separately. */ @NotNull - public AllSubsetsIndependenceFacts getAllSubsetsIndependenceFacts(Graph graph) { + public AllSubsetsIndependenceFacts getAllSubsetsIndependenceFacts() { List variables = new ArrayList<>(getVariables(graph.getNodes(), independenceNodes, conditioningNodes)); for (Node node : variables) { @@ -162,7 +161,7 @@ public void generateResults() { resultsDep.clear(); if (setType == ConditioningSetType.GLOBAL_MARKOV) { - AllSubsetsIndependenceFacts result = getAllSubsetsIndependenceFacts(graph); + AllSubsetsIndependenceFacts result = getAllSubsetsIndependenceFacts(); generateResultsAllSubsets(result.msep, result.mconn); generateResultsAllSubsets(result.msep, result.mconn); } else { diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/SemBicScore.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/SemBicScore.java index 6fb7f4a17b..5491490831 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/SemBicScore.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/SemBicScore.java @@ -101,7 +101,7 @@ public class SemBicScore implements Score { private RuleType ruleType = RuleType.CHICKERING; // True iff the pseudo-inverse should be used instead of the inverse to avoid exceptions. - private static boolean usePseudoInverse = false; + private boolean usePseudoInverse = false; /** @@ -158,7 +158,21 @@ public SemBicScore(DataSet dataSet, boolean precomputeCovariances) { * @param calculateRowSubsets True if row subsets should be calculated. * @return The variance of the residual of the regression of the ith variable on its parents. */ - public static double getVarRy(int i, int[] parents, Matrix data, ICovarianceMatrix covariances, boolean calculateRowSubsets) + public static double getVarRy(int i, int[] parents, Matrix data, ICovarianceMatrix covariances, boolean calculateRowSubsets) { + return SemBicScore.getVarRy(i, parents, data, covariances, calculateRowSubsets, false); + } + + /** + * Returns the variance of the residual of the regression of the ith variable on its parents. + * + * @param i The index of the variable. + * @param parents The indices of the parents. + * @param covariances The covariance matrix. + * @param calculateRowSubsets True if row subsets should be calculated. + * @return The variance of the residual of the regression of the ith variable on its parents. + */ + public static double getVarRy(int i, int[] parents, Matrix data, ICovarianceMatrix covariances, + boolean calculateRowSubsets, boolean usePseudoInverse) throws SingularMatrixException { int[] all = SemBicScore.concat(i, parents); Matrix cov = SemBicScore.getCov(SemBicScore.getRows(i, parents, data, calculateRowSubsets), all, all, data, covariances); @@ -256,8 +270,8 @@ private static List getRows(int i, int[] parents, Matrix data, boolean return rows; } - public static void setUsePseudoInverse(boolean usePseudoInverse) { - SemBicScore.usePseudoInverse = usePseudoInverse; + public void setUsePseudoInverse(boolean usePseudoInverse) { + this.usePseudoInverse = usePseudoInverse; } @NotNull @@ -310,7 +324,8 @@ public double localScore(int i, int... parents) { Arrays.sort(parents); try { - double varey = SemBicScore.getVarRy(i, parents, this.data, this.covariances, this.calculateRowSubsets); + double varey = SemBicScore.getVarRy(i, parents, this.data, this.covariances, this.calculateRowSubsets, + usePseudoInverse); lik = -(double) (this.sampleSize / 2.0) * log(varey); } catch (SingularMatrixException e) { System.out.println("Singularity encountered when scoring " + From 97591f7ed06320a83768b12ae51b0fab664591ce Mon Sep 17 00:00:00 2001 From: jdramsey Date: Sat, 20 Jan 2024 06:46:19 -0500 Subject: [PATCH 088/163] Cleanup. --- .../edu/cmu/tetradapp/model/SemEstimatorWrapper.java | 12 ++++++------ .../src/main/java/edu/cmu/tetrad/search/Grasp.java | 4 ++-- .../cmu/tetrad/search/work_in_progress/GraspTol.java | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/SemEstimatorWrapper.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/SemEstimatorWrapper.java index 8f6641861b..40085cb70c 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/SemEstimatorWrapper.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/SemEstimatorWrapper.java @@ -32,6 +32,7 @@ import javax.swing.*; import java.io.IOException; import java.io.ObjectInputStream; +import java.io.Serial; import java.util.LinkedList; import java.util.List; @@ -41,8 +42,7 @@ * @author josephramsey */ public class SemEstimatorWrapper implements SessionModel { - ;//}, Unmarshallable { - + @Serial private static final long serialVersionUID = 23L; private final Parameters params; private final SemPm semPm; @@ -65,8 +65,7 @@ public SemEstimatorWrapper(DataModel dataModel, SemPm semPm, Parameters params) this.params = params; this.semPm = semPm; - if (dataModel instanceof DataSet) { - DataSet dataSet = (DataSet) dataModel; + if (dataModel instanceof DataSet dataSet) { SemEstimator estimator = new SemEstimator(dataSet, semPm, getOptimizer()); estimator.setNumRestarts(getParams().getInt("numRestarts", 1)); estimator.setScoreType((ScoreType) getParams().get("scoreType", ScoreType.Fgls)); @@ -135,7 +134,7 @@ private static boolean containsCovarParam(SemPm semPm) { private boolean degreesOfFreedomCheck(SemPm semPm) { if (semPm.getDof() < 1) { int ret = JOptionPane.showConfirmDialog(JOptionUtils.centeringComp(), - "This model has nonpositive degrees of freedom (DOF = " + "This model has non-positive degrees of freedom (DOF = " + semPm.getDof() + "). " + "\nEstimation will be uninformative. Are you sure you want to proceed?", "Please confirm", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE); @@ -193,9 +192,10 @@ private void log() { * readObject method, and the body of the method must begin with "s.defaultReadObject();". Other than that, any * semantic checks can be specified and do not need to stay the same from version to version. A readObject method of * this form may be added to any class, even if Tetrad sessions were previously saved out using a version of the - * class that didn't include it. (That's what the "s.defaultReadObject();" is for. See J. Bloch, Effective Java, for + * class that didn't include it. (That's what the "s.defaultReadObject();" is for). See J. Bloch, Effective Java, for * help. */ + @Serial private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException { s.defaultReadObject(); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Grasp.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Grasp.java index cf7716c968..4f5c7d1242 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Grasp.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Grasp.java @@ -193,8 +193,8 @@ public Graph getGraph(boolean cpDag) { if (this.scorer == null) throw new IllegalArgumentException("Please run algorithm first."); Graph graph = this.scorer.getGraph(cpDag); - NumberFormat nf = NumberFormatUtil.getInstance().getNumberFormat(); - graph.addAttribute("score ", nf.format(this.scorer.score())); +// NumberFormat nf = NumberFormatUtil.getInstance().getNumberFormat(); +// graph.addAttribute("score ", nf.format(this.scorer.score())); return graph; } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/work_in_progress/GraspTol.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/work_in_progress/GraspTol.java index cf6d3e5f42..f031c8e836 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/work_in_progress/GraspTol.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/work_in_progress/GraspTol.java @@ -384,8 +384,8 @@ public Graph getGraph(boolean cpDag) { if (this.scorer == null) throw new IllegalArgumentException("Please run algorithm first."); Graph graph = this.scorer.getGraph(cpDag); - NumberFormat nf = NumberFormatUtil.getInstance().getNumberFormat(); - graph.addAttribute("score ", nf.format(this.scorer.score())); +// NumberFormat nf = NumberFormatUtil.getInstance().getNumberFormat(); +// graph.addAttribute("score ", nf.format(this.scorer.score())); return graph; } From 6b027b44f5de53f97f48776914dd8da4eba1167b Mon Sep 17 00:00:00 2001 From: jdramsey Date: Sat, 20 Jan 2024 16:38:07 -0500 Subject: [PATCH 089/163] Translated fisher z pseudoinverse code to use the Matrix class (by refactoring the relevant method in SEM BIC and using it). Also, moved the pseudoinverse methods themselves into the fisher Z class and added a parameter to select whether to use them or not. --- .../algcomparison/independence/FisherZ.java | 20 +- .../independence/FisherZPseudoinverse.java | 60 ++++++ .../cmu/tetrad/search/score/SemBicScore.java | 15 +- .../tetrad/search/test/IndTestFisherZ.java | 188 +++++++++++++++++- .../IndTestFisherZPseudoinverse.java | 130 +++++------- 5 files changed, 318 insertions(+), 95 deletions(-) create mode 100644 tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/FisherZPseudoinverse.java diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/FisherZ.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/FisherZ.java index 48c0ab7fc3..ac07b8ccf0 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/FisherZ.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/FisherZ.java @@ -11,6 +11,7 @@ import edu.cmu.tetrad.util.Parameters; import edu.cmu.tetrad.util.Params; +import java.io.Serial; import java.util.ArrayList; import java.util.List; @@ -27,19 +28,25 @@ @LinearGaussian public class FisherZ implements IndependenceWrapper { + @Serial private static final long serialVersionUID = 23L; @Override - public IndependenceTest getTest(DataModel dataSet, Parameters parameters) { + public IndependenceTest getTest(DataModel dataModel, Parameters parameters) { double alpha = parameters.getDouble(Params.ALPHA); - if (dataSet instanceof ICovarianceMatrix) { - return new IndTestFisherZ((ICovarianceMatrix) dataSet, alpha); - } else if (dataSet instanceof DataSet) { - return new IndTestFisherZ((DataSet) dataSet, alpha); + IndTestFisherZ test; + + if (dataModel instanceof ICovarianceMatrix) { + test = new IndTestFisherZ((ICovarianceMatrix) dataModel, alpha); + } else if (dataModel instanceof DataSet) { + test = new IndTestFisherZ((DataSet) dataModel, alpha); + } else { + throw new IllegalArgumentException("Expecting either a dataset or a covariance matrix."); } - throw new IllegalArgumentException("Expecting eithet a data set or a covariance matrix."); + test.setUsePseudoinverse(parameters.getBoolean(Params.USE_PSEUDOINVERSE)); + return test; } @Override @@ -56,6 +63,7 @@ public DataType getDataType() { public List getParameters() { List params = new ArrayList<>(); params.add(Params.ALPHA); + params.add(Params.USE_PSEUDOINVERSE); return params; } } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/FisherZPseudoinverse.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/FisherZPseudoinverse.java new file mode 100644 index 0000000000..b902a7c0ca --- /dev/null +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/FisherZPseudoinverse.java @@ -0,0 +1,60 @@ +package edu.cmu.tetrad.algcomparison.independence; + +import edu.cmu.tetrad.annotation.LinearGaussian; +import edu.cmu.tetrad.annotation.TestOfIndependence; +import edu.cmu.tetrad.data.DataModel; +import edu.cmu.tetrad.data.DataSet; +import edu.cmu.tetrad.data.DataType; +import edu.cmu.tetrad.search.IndependenceTest; +import edu.cmu.tetrad.search.work_in_progress.IndTestFisherZPseudoinverse; +import edu.cmu.tetrad.util.Parameters; +import edu.cmu.tetrad.util.Params; + +import java.io.Serial; +import java.util.ArrayList; +import java.util.List; + +/** + * Wrapper for Fisher Z test. + * + * @author josephramsey + */ +@TestOfIndependence( + name = "Fisher Z Test Pseudoinverse", + command = "fisher-z-test-pseudoinverse", + dataType = {DataType.Continuous} +) +@LinearGaussian +public class FisherZPseudoinverse implements IndependenceWrapper { + + @Serial + private static final long serialVersionUID = 23L; + + @Override + public IndependenceTest getTest(DataModel dataSet, Parameters parameters) { + double alpha = parameters.getDouble(Params.ALPHA); + + if (!(dataSet instanceof DataSet) || !dataSet.isContinuous()) { + throw new IllegalArgumentException("Expecting a tabular continous data set."); + } + + return new IndTestFisherZPseudoinverse((DataSet) dataSet, alpha); + } + + @Override + public String getDescription() { + return "Fisher Z test Pseudoinverse"; + } + + @Override + public DataType getDataType() { + return DataType.Continuous; + } + + @Override + public List getParameters() { + List params = new ArrayList<>(); + params.add(Params.ALPHA); + return params; + } +} diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/SemBicScore.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/SemBicScore.java index 5491490831..5536d1ddcc 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/SemBicScore.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/SemBicScore.java @@ -174,24 +174,31 @@ public static double getVarRy(int i, int[] parents, Matrix data, ICovarianceMatr public static double getVarRy(int i, int[] parents, Matrix data, ICovarianceMatrix covariances, boolean calculateRowSubsets, boolean usePseudoInverse) throws SingularMatrixException { + CovAndCoefs covAndcoefs = getCovAndCoefs(i, parents, data, covariances, calculateRowSubsets, usePseudoInverse); + return (bStar(covAndcoefs.b()).transpose().times(covAndcoefs.cov()).times(bStar(covAndcoefs.b())).get(0, 0)); + } + + @NotNull + public static SemBicScore.CovAndCoefs getCovAndCoefs(int i, int[] parents, Matrix data, ICovarianceMatrix covariances, boolean calculateRowSubsets, boolean usePseudoInverse) { int[] all = SemBicScore.concat(i, parents); Matrix cov = SemBicScore.getCov(SemBicScore.getRows(i, parents, data, calculateRowSubsets), all, all, data, covariances); int[] pp = SemBicScore.indexedParents(parents); Matrix covxx = cov.getSelection(pp, pp); Matrix covxy = cov.getSelection(pp, new int[]{0}); + // The regression coefficient vector. Matrix b; if (usePseudoInverse) { - b = b = new Matrix(MatrixUtils.pseudoInverse(covxx.toArray())).times(covxy); + b = new Matrix(MatrixUtils.pseudoInverse(covxx.toArray())).times(covxy); } else { b = covxx.inverse().times(covxy); } + return new CovAndCoefs(cov, b); + } -// Matrix b = (covxx.inverse().times(covxy)); - Matrix bStar = bStar(b); - return (bStar.transpose().times(cov).times(bStar).get(0, 0)); + public record CovAndCoefs(Matrix cov, Matrix b) { } @NotNull diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java index 1418c1404a..1e0a1c7b85 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java @@ -25,11 +25,10 @@ import edu.cmu.tetrad.graph.IndependenceFact; import edu.cmu.tetrad.graph.Node; import edu.cmu.tetrad.search.IndependenceTest; +import edu.cmu.tetrad.search.score.SemBicScore; import edu.cmu.tetrad.search.utils.LogUtilsSearch; -import edu.cmu.tetrad.util.Matrix; -import edu.cmu.tetrad.util.MatrixUtils; -import edu.cmu.tetrad.util.StatUtils; -import edu.cmu.tetrad.util.TetradLogger; +import edu.cmu.tetrad.util.Vector; +import edu.cmu.tetrad.util.*; import org.apache.commons.math3.distribution.NormalDistribution; import org.apache.commons.math3.linear.SingularMatrixException; import org.apache.commons.math3.util.FastMath; @@ -58,9 +57,13 @@ public final class IndTestFisherZ implements IndependenceTest, RowsSettable { private List variables; private double alpha; private DataSet dataSet; + + // Matrix from of the data. + private Matrix data; private boolean verbose = true; private double r = Double.NaN; private List rows = null; + private boolean usePseudoinverse = false; /** @@ -201,6 +204,10 @@ public IndependenceTest indTestSubset(List vars) { * @see IndependenceResult */ public IndependenceResult checkIndependence(Node x, Node y, Set z) { + if (usePseudoinverse) { + return checkIndependencePseudoinverse(x, y, z); + } + double p; try { @@ -221,11 +228,93 @@ public IndependenceResult checkIndependence(Node x, Node y, Set z) { if (Double.isNaN(p)) { throw new RuntimeException("Undefined p-value encountered in for test: " + LogUtilsSearch.independenceFact(x, y, z)); } else { - return new IndependenceResult(new IndependenceFact(x, y, z), - independent, p, alpha - p); + return new IndependenceResult(new IndependenceFact(x, y, z), independent, p, alpha - p); } } + /** + * Determines whether variable x is independent of variable y given a list of conditioning variables z. + * + * @param xVar the one variable being compared. + * @param yVar the second variable being compared. + * @param _z the list of conditioning variables. + * @return True iff x _||_ y | z. + * @throws RuntimeException if a matrix singularity is encountered. + */ + private IndependenceResult checkIndependencePseudoinverse(Node xVar, Node yVar, Set _z) { + + if (this.data == null) this.data = dataSet.getDoubleData(); + + if (_z == null) { + throw new NullPointerException(); + } + + for (Node node : _z) { + if (node == null) { + throw new NullPointerException(); + } + } + + List z = new ArrayList<>(_z); + Collections.sort(z); + + int size = z.size(); + int[] zCols = new int[size]; + + int xIndex = getVariables().indexOf(xVar); + int yIndex = getVariables().indexOf(yVar); + + for (int i = 0; i < z.size(); i++) { + zCols[i] = getVariables().indexOf(z.get(i)); + } + + edu.cmu.tetrad.util.Vector x = this.data.getColumn(xIndex); + edu.cmu.tetrad.util.Vector y = this.data.getColumn(yIndex); + + CovarianceMatrix cov = new CovarianceMatrix(dataSet); + + SemBicScore.CovAndCoefs covAndCoefsX = SemBicScore.getCovAndCoefs(xIndex, zCols, this.data, + cov, true, true); + SemBicScore.CovAndCoefs covAndCoefsY = SemBicScore.getCovAndCoefs(yIndex, zCols, this.data, + cov, true, true); + + int[] rows = new int[this.data.getNumRows()]; + for (int i = 0; i < rows.length; i++) { + rows[i] = i; + } + + Matrix selection = data.getSelection(rows, zCols); + edu.cmu.tetrad.util.Vector xPred = selection.times(covAndCoefsX.b()).getColumn(0); + edu.cmu.tetrad.util.Vector yPred = selection.times(covAndCoefsY.b()).getColumn(0); + + edu.cmu.tetrad.util.Vector xRes = xPred.minus(x); + Vector yRes = yPred.minus(y); + + // Note that r will be NaN if either xRes or yRes is constant. + double r = StatUtils.correlation(xRes.toArray(), yRes.toArray()); + + double fisherZ = FastMath.sqrt(sampleSize() - z.size() - 3.0) * + 0.5 * (FastMath.log(1.0 + r) - FastMath.log(1.0 - r)); + + double p = 2 * (1.0 - this.normal.cumulativeProbability(fisherZ)); + + if (Double.isNaN(fisherZ)) { + throw new IllegalArgumentException("The Fisher's Z " + + "score for independence fact " + xVar + " _||_ " + yVar + + " | " + z + " is undefined."); + } + + + if (this.verbose) { + if (p > alpha) { + TetradLogger.getInstance().forceLogMessage(LogUtilsSearch.independenceFactMsg(xVar, yVar, _z, p)); + } + } + + return new IndependenceResult(new IndependenceFact(xVar, yVar, _z), p > alpha, p, getAlpha() - p); + } + + /** * Returns the p-value for x _||_ y | z. * @@ -392,6 +481,10 @@ public String toString() { * @param x The conditioned variable. */ public boolean determines(List z, Node x) throws UnsupportedOperationException { + if (usePseudoinverse) { + return determinesPseudoinverse(z, x); + } + int[] parents = new int[z.size()]; for (int j = 0; j < parents.length; j++) { @@ -414,6 +507,85 @@ public boolean determines(List z, Node x) throws UnsupportedOperationExcep return false; } + /** + * Returns true just in case the varialbe in zList determine xVar. + * + * @return True, if so. + */ + public boolean determinesPseudoinverse(List zList, Node xVar) { + if (zList == null) { + throw new NullPointerException(); + } + + if (zList.isEmpty()) { + return false; + } + + for (Node node : zList) { + if (node == null) { + throw new NullPointerException(); + } + } + + int size = zList.size(); + int[] zCols = new int[size]; + + int xIndex = getVariables().indexOf(xVar); + Vector x = this.data.getColumn(xIndex); + + for (int i = 0; i < zList.size(); i++) { + zCols[i] = getVariables().indexOf(zList.get(i)); + } + + CovarianceMatrix cov = new CovarianceMatrix(dataSet); + + SemBicScore.CovAndCoefs covAndCoefsX = SemBicScore.getCovAndCoefs(xIndex, zCols, this.data, + cov, true, true); + + int[] rows = new int[this.data.getNumRows()]; + for (int i = 0; i < rows.length; i++) { + rows[i] = i; + } + + Matrix selection = data.getSelection(rows, zCols); + Vector xPred = selection.times(covAndCoefsX.b()).getColumn(0); + Vector xRes = xPred.minus(x); + + double SSE = 0; + + for (int i = 0; i < xRes.size(); i++) { + SSE += xRes.get(i) * xRes.get(i); + } + + double variance = SSE / (this.data.getNumRows() - (zList.size() + 1)); + + boolean determined = variance < getAlpha(); + + if (determined) { + StringBuilder sb = new StringBuilder(); + sb.append("Determination found: ").append(xVar).append( + " is determined by {"); + + for (int i = 0; i < zList.size(); i++) { + sb.append(zList.get(i)); + + if (i < zList.size() - 1) { + sb.append(", "); + } + } + + sb.append("}"); + + sb.append(" SSE = ").append(NumberFormatUtil.getInstance().getNumberFormat().format(SSE)); + + TetradLogger.getInstance().log("independencies", sb.toString()); + System.out.println(sb); + } + + return determined; + } + + private double partialCorrelation(Node x, Node y, Set _z, List rows) throws SingularMatrixException { List z = new ArrayList<>(_z); Collections.sort(z); @@ -546,6 +718,10 @@ public void setRows(List rows) { this.rows = rows; cor = null; } + + public void setUsePseudoinverse(boolean usePseudoinverse) { + this.usePseudoinverse = usePseudoinverse; + } } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/work_in_progress/IndTestFisherZPseudoinverse.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/work_in_progress/IndTestFisherZPseudoinverse.java index 1c5760108b..f0ab25da4f 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/work_in_progress/IndTestFisherZPseudoinverse.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/work_in_progress/IndTestFisherZPseudoinverse.java @@ -21,16 +21,12 @@ package edu.cmu.tetrad.search.work_in_progress; -import cern.colt.matrix.DoubleMatrix1D; -import cern.colt.matrix.DoubleMatrix2D; -import cern.colt.matrix.impl.DenseDoubleMatrix2D; -import cern.colt.matrix.linalg.Algebra; -import cern.jet.math.Functions; +import edu.cmu.tetrad.data.CovarianceMatrix; import edu.cmu.tetrad.data.DataSet; -import edu.cmu.tetrad.data.DataTransforms; import edu.cmu.tetrad.graph.IndependenceFact; import edu.cmu.tetrad.graph.Node; import edu.cmu.tetrad.search.IndependenceTest; +import edu.cmu.tetrad.search.score.SemBicScore; import edu.cmu.tetrad.search.test.IndependenceResult; import edu.cmu.tetrad.search.utils.LogUtilsSearch; import edu.cmu.tetrad.util.*; @@ -44,38 +40,30 @@ /** * Checks independence of X _||_ Y | Z for variables X and Y and list Z of variables. Partial correlations are - * calculated using pseudoinverses, so linearly dependent variables do not throw exceptions. Must supply a - * continuous data set; don't know how to do this with covariance or correlation matrices. + * calculated using pseudoinverses, so linearly dependent variables do not throw exceptions. Must supply a continuous + * data set; don't know how to do this with covariance or correlation matrices. * * @author josephramsey * @author Frank Wimberly adapted IndTestCramerT for Fisher's Z */ public final class IndTestFisherZPseudoinverse implements IndependenceTest { - /** - * Formats as 0.0000. - */ private static final NumberFormat nf = NumberFormatUtil.getInstance().getNumberFormat(); - /** - * The correlation matrix. - */ - private final DoubleMatrix2D data; - /** - * The variables of the correlation matrix, in order. (Unmodifiable list.) - */ + + private final Matrix data; + + // The variables of the correlation matrix, in order. (Unmodifiable list.) private final List variables; + private final DataSet dataSet; - /** - * The significance level of the independence tests. - */ + + // The significance level of the independence tests. private double alpha; - /** - * The cutoff value for 'alpha' area in the two tails of the partial correlation distribution function. - */ + + // The cutoff value for 'alpha' area in the two tails of the partial correlation distribution function. private double thresh = Double.NaN; - /** - * The value of the Fisher's Z statistic associated with the las calculated partial correlation. - */ + + //The value of the Fisher's Z statistic associated with the last calculated partial correlation. private double fishersZ; private boolean verbose; @@ -95,7 +83,7 @@ public IndTestFisherZPseudoinverse(DataSet dataSet, double alpha) { this.dataSet = dataSet; - this.data = new DenseDoubleMatrix2D(DataTransforms.center(this.dataSet).getDoubleData().toArray()); + this.data = dataSet.getDoubleData(); this.variables = Collections.unmodifiableList(this.dataSet.getVariables()); setAlpha(alpha); } @@ -142,32 +130,27 @@ public IndependenceResult checkIndependence(Node xVar, Node yVar, Set _z) zCols[i] = getVariables().indexOf(z.get(i)); } - int[] zRows = new int[this.data.rows()]; - for (int i = 0; i < this.data.rows(); i++) { - zRows[i] = i; - } + Vector x = this.data.getColumn(xIndex); + Vector y = this.data.getColumn(yIndex); - DoubleMatrix2D Z = this.data.viewSelection(zRows, zCols); - DoubleMatrix1D x = this.data.viewColumn(xIndex); - DoubleMatrix1D y = this.data.viewColumn(yIndex); - DoubleMatrix2D Zt = new Algebra().transpose(Z); - DoubleMatrix2D ZtZ = new Algebra().mult(Zt, Z); - Matrix _ZtZ = new Matrix(ZtZ.toArray()); - Matrix ginverse = _ZtZ.inverse(); - DoubleMatrix2D G = new DenseDoubleMatrix2D(ginverse.toArray()); + CovarianceMatrix cov = new CovarianceMatrix(dataSet); - DoubleMatrix2D Zt2 = Zt.like(); - Zt2.assign(Zt); - DoubleMatrix2D GZt = new Algebra().mult(G, Zt2); + SemBicScore.CovAndCoefs covAndCoefsX = SemBicScore.getCovAndCoefs(xIndex, zCols, this.data, + cov, true, true); + SemBicScore.CovAndCoefs covAndCoefsY = SemBicScore.getCovAndCoefs(yIndex, zCols, this.data, + cov, true, true); - DoubleMatrix1D b_x = new Algebra().mult(GZt, x); - DoubleMatrix1D b_y = new Algebra().mult(GZt, y); + int[] rows = new int[this.data.getNumRows()]; + for (int i = 0; i < rows.length; i++) { + rows[i] = i; + } - DoubleMatrix1D xPred = new Algebra().mult(Z, b_x); - DoubleMatrix1D yPred = new Algebra().mult(Z, b_y); + Matrix selection = data.getSelection(rows, zCols); + Vector xPred = selection.times(covAndCoefsX.b()).getColumn(0); + Vector yPred = selection.times(covAndCoefsY.b()).getColumn(0); - DoubleMatrix1D xRes = xPred.copy().assign(x, Functions.minus); - DoubleMatrix1D yRes = yPred.copy().assign(y, Functions.minus); + Vector xRes = xPred.minus(x); + Vector yRes = yPred.minus(y); // Note that r will be NaN if either xRes or yRes is constant. double r = StatUtils.correlation(xRes.toArray(), yRes.toArray()); @@ -197,10 +180,6 @@ public IndependenceResult checkIndependence(Node xVar, Node yVar, Set _z) boolean indFisher = !(FastMath.abs(this.fishersZ) > this.thresh); - //System.out.println("thresh = " + thresh); - //if(FastMath.abs(fishersZ) > 1.96) indFisher = false; //Two sided with alpha = 0.05 - //Two sided - if (this.verbose) { TetradLogger.getInstance().log("independencies", LogUtilsSearch.independenceFactMsg(xVar, yVar, _z, getPValue())); } @@ -253,11 +232,6 @@ public List getVariables() { return this.variables; } - /** - * @return the variable with the given name. - */ - - public String toString() { return "Fisher's Z - Pseudoinverse, alpha = " + IndTestFisherZPseudoinverse.nf.format(getAlpha()); } @@ -313,34 +287,33 @@ public boolean determines(List zList, Node xVar) { int[] zCols = new int[size]; int xIndex = getVariables().indexOf(xVar); + Vector x = this.data.getColumn(xIndex); for (int i = 0; i < zList.size(); i++) { zCols[i] = getVariables().indexOf(zList.get(i)); } - int[] zRows = new int[this.data.rows()]; - for (int i = 0; i < this.data.rows(); i++) { - zRows[i] = i; + CovarianceMatrix cov = new CovarianceMatrix(dataSet); + + SemBicScore.CovAndCoefs covAndCoefsX = SemBicScore.getCovAndCoefs(xIndex, zCols, this.data, + cov, true, true); + + int[] rows = new int[this.data.getNumRows()]; + for (int i = 0; i < rows.length; i++) { + rows[i] = i; } - DoubleMatrix2D Z = this.data.viewSelection(zRows, zCols); - DoubleMatrix1D x = this.data.viewColumn(xIndex); - DoubleMatrix2D Zt = new Algebra().transpose(Z); - DoubleMatrix2D ZtZ = new Algebra().mult(Zt, Z); + Matrix selection = data.getSelection(rows, zCols); + Vector xPred = selection.times(covAndCoefsX.b()).getColumn(0); + Vector xRes = xPred.minus(x); - Matrix _ZtZ = new Matrix(ZtZ.toArray()); - Matrix ginverse = _ZtZ.inverse(); - DoubleMatrix2D G = new DenseDoubleMatrix2D(ginverse.toArray()); + double SSE = 0; -// DoubleMatrix2D G = MatrixUtils.ginverse(ZtZ); - DoubleMatrix2D Zt2 = Zt.copy(); - DoubleMatrix2D GZt = new Algebra().mult(G, Zt2); - DoubleMatrix1D b_x = new Algebra().mult(GZt, x); - DoubleMatrix1D xPred = new Algebra().mult(Z, b_x); - DoubleMatrix1D xRes = xPred.copy().assign(x, Functions.minus); - double SSE = xRes.aggregate(Functions.plus, Functions.square); + for (int i = 0; i < xRes.size(); i++) { + SSE += xRes.get(i) * xRes.get(i); + } - double variance = SSE / (this.data.rows() - (zList.size() + 1)); + double variance = SSE / (this.data.getNumRows() - (zList.size() + 1)); boolean determined = variance < getAlpha(); @@ -359,7 +332,6 @@ public boolean determines(List zList, Node xVar) { sb.append("}"); -// sb.append(" p = ").append(nf.format(p)); sb.append(" SSE = ").append(IndTestFisherZPseudoinverse.nf.format(SSE)); TetradLogger.getInstance().log("independencies", sb.toString()); @@ -370,7 +342,7 @@ public boolean determines(List zList, Node xVar) { } /** - * Computes that value x such that P(abs(N(0,1) > x) < alpha. Note that this is a two sided test of the null + * Computes that value x such that P(abs(N(0,1) > x) < alpha. Note that this is a two-sided test of the null * hypothesis that the Fisher's Z value, which is distributed as N(0,1) is not equal to 0.0. */ private double cutoffGaussian() { @@ -400,7 +372,7 @@ private double cutoffGaussian() { } private int sampleSize() { - return this.data.rows(); + return this.data.getNumRows(); } } From 15963078174925530154dab8299efc4f9e6b003e Mon Sep 17 00:00:00 2001 From: jdramsey Date: Sat, 20 Jan 2024 16:53:00 -0500 Subject: [PATCH 090/163] Removed the separate pseudoinverse fisher z class. --- .../model/AbstractMBSearchRunner.java | 5 +- .../cmu/tetradapp/model/IndTestChooser.java | 5 +- .../independence/FisherZPseudoinverse.java | 60 --- .../tetrad/search/test/IndTestFisherZ.java | 2 +- .../IndTestFisherZPseudoinverse.java | 382 ------------------ .../TestIndTestFisherGeneralizedInverse.java | 10 +- 6 files changed, 13 insertions(+), 451 deletions(-) delete mode 100644 tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/FisherZPseudoinverse.java delete mode 100644 tetrad-lib/src/main/java/edu/cmu/tetrad/search/work_in_progress/IndTestFisherZPseudoinverse.java diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/AbstractMBSearchRunner.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/AbstractMBSearchRunner.java index eb52f3eb80..51dd8c138d 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/AbstractMBSearchRunner.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/AbstractMBSearchRunner.java @@ -31,7 +31,6 @@ import edu.cmu.tetrad.search.test.IndTestFisherZ; import edu.cmu.tetrad.search.test.IndTestGSquare; import edu.cmu.tetrad.search.test.IndTestRegression; -import edu.cmu.tetrad.search.work_in_progress.IndTestFisherZPseudoinverse; import edu.cmu.tetrad.util.Parameters; import edu.cmu.tetradapp.util.IndTestType; @@ -185,7 +184,9 @@ IndependenceTest getIndependenceTest() { return new IndTestFisherZ(this.source, this.params.getDouble("alpha", 0.001)); } if (IndTestType.FISHER_ZD == type) { - return new IndTestFisherZPseudoinverse(this.source, this.params.getDouble("alpha", 0.001)); + IndTestFisherZ test = new IndTestFisherZ(this.source, this.params.getDouble("alpha", 0.001)); + test.setUsePseudoinverse(true); + return test; } if (IndTestType.LINEAR_REGRESSION == type) { return new IndTestRegression(this.source, this.params.getDouble("alpha", 0.001)); diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/IndTestChooser.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/IndTestChooser.java index 737f2f809a..45d7256c6b 100755 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/IndTestChooser.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/IndTestChooser.java @@ -29,7 +29,6 @@ import edu.cmu.tetrad.search.score.SemBicScore; import edu.cmu.tetrad.search.test.*; import edu.cmu.tetrad.search.utils.ResolveSepsets; -import edu.cmu.tetrad.search.work_in_progress.IndTestFisherZPseudoinverse; import edu.cmu.tetrad.search.work_in_progress.IndTestFisherZPercentIndependent; import edu.cmu.tetrad.search.work_in_progress.IndTestMultinomialLogisticRegression; import edu.cmu.tetrad.util.Parameters; @@ -137,7 +136,9 @@ private IndependenceTest getContinuousTest(DataSet dataSet, return new IndTestFisherZ(dataSet, params.getDouble("alpha", 0.001)); } if (IndTestType.FISHER_ZD == testType) { - return new IndTestFisherZPseudoinverse(dataSet, params.getDouble("alpha", 0.001)); + IndTestFisherZ test = new IndTestFisherZ(dataSet, params.getDouble("alpha", 0.001)); + test.setUsePseudoinverse(true); + return test; } if (IndTestType.SEM_BIC == testType) { return new ScoreIndTest(new SemBicScore(new CovarianceMatrix(dataSet))); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/FisherZPseudoinverse.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/FisherZPseudoinverse.java deleted file mode 100644 index b902a7c0ca..0000000000 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/FisherZPseudoinverse.java +++ /dev/null @@ -1,60 +0,0 @@ -package edu.cmu.tetrad.algcomparison.independence; - -import edu.cmu.tetrad.annotation.LinearGaussian; -import edu.cmu.tetrad.annotation.TestOfIndependence; -import edu.cmu.tetrad.data.DataModel; -import edu.cmu.tetrad.data.DataSet; -import edu.cmu.tetrad.data.DataType; -import edu.cmu.tetrad.search.IndependenceTest; -import edu.cmu.tetrad.search.work_in_progress.IndTestFisherZPseudoinverse; -import edu.cmu.tetrad.util.Parameters; -import edu.cmu.tetrad.util.Params; - -import java.io.Serial; -import java.util.ArrayList; -import java.util.List; - -/** - * Wrapper for Fisher Z test. - * - * @author josephramsey - */ -@TestOfIndependence( - name = "Fisher Z Test Pseudoinverse", - command = "fisher-z-test-pseudoinverse", - dataType = {DataType.Continuous} -) -@LinearGaussian -public class FisherZPseudoinverse implements IndependenceWrapper { - - @Serial - private static final long serialVersionUID = 23L; - - @Override - public IndependenceTest getTest(DataModel dataSet, Parameters parameters) { - double alpha = parameters.getDouble(Params.ALPHA); - - if (!(dataSet instanceof DataSet) || !dataSet.isContinuous()) { - throw new IllegalArgumentException("Expecting a tabular continous data set."); - } - - return new IndTestFisherZPseudoinverse((DataSet) dataSet, alpha); - } - - @Override - public String getDescription() { - return "Fisher Z test Pseudoinverse"; - } - - @Override - public DataType getDataType() { - return DataType.Continuous; - } - - @Override - public List getParameters() { - List params = new ArrayList<>(); - params.add(Params.ALPHA); - return params; - } -} diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java index 1e0a1c7b85..9e3f20de79 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java @@ -296,7 +296,7 @@ private IndependenceResult checkIndependencePseudoinverse(Node xVar, Node yVar, double fisherZ = FastMath.sqrt(sampleSize() - z.size() - 3.0) * 0.5 * (FastMath.log(1.0 + r) - FastMath.log(1.0 - r)); - double p = 2 * (1.0 - this.normal.cumulativeProbability(fisherZ)); + double p = 2 * (1.0 - this.normal.cumulativeProbability(abs(fisherZ))); if (Double.isNaN(fisherZ)) { throw new IllegalArgumentException("The Fisher's Z " + diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/work_in_progress/IndTestFisherZPseudoinverse.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/work_in_progress/IndTestFisherZPseudoinverse.java deleted file mode 100644 index f0ab25da4f..0000000000 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/work_in_progress/IndTestFisherZPseudoinverse.java +++ /dev/null @@ -1,382 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// For information as to what this class does, see the Javadoc, below. // -// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, // -// 2007, 2008, 2009, 2010, 2014, 2015, 2022 by Peter Spirtes, Richard // -// Scheines, Joseph Ramsey, and Clark Glymour. // -// // -// This program is free software; you can redistribute it and/or modify // -// it under the terms of the GNU General Public License as published by // -// the Free Software Foundation; either version 2 of the License, or // -// (at your option) any later version. // -// // -// This program is distributed in the hope that it will be useful, // -// but WITHOUT ANY WARRANTY; without even the implied warranty of // -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // -// GNU General Public License for more details. // -// // -// You should have received a copy of the GNU General Public License // -// along with this program; if not, write to the Free Software // -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // -/////////////////////////////////////////////////////////////////////////////// - -package edu.cmu.tetrad.search.work_in_progress; - -import edu.cmu.tetrad.data.CovarianceMatrix; -import edu.cmu.tetrad.data.DataSet; -import edu.cmu.tetrad.graph.IndependenceFact; -import edu.cmu.tetrad.graph.Node; -import edu.cmu.tetrad.search.IndependenceTest; -import edu.cmu.tetrad.search.score.SemBicScore; -import edu.cmu.tetrad.search.test.IndependenceResult; -import edu.cmu.tetrad.search.utils.LogUtilsSearch; -import edu.cmu.tetrad.util.*; -import org.apache.commons.math3.util.FastMath; - -import java.text.NumberFormat; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Set; - -/** - * Checks independence of X _||_ Y | Z for variables X and Y and list Z of variables. Partial correlations are - * calculated using pseudoinverses, so linearly dependent variables do not throw exceptions. Must supply a continuous - * data set; don't know how to do this with covariance or correlation matrices. - * - * @author josephramsey - * @author Frank Wimberly adapted IndTestCramerT for Fisher's Z - */ -public final class IndTestFisherZPseudoinverse implements IndependenceTest { - - private static final NumberFormat nf = NumberFormatUtil.getInstance().getNumberFormat(); - - private final Matrix data; - - // The variables of the correlation matrix, in order. (Unmodifiable list.) - private final List variables; - - private final DataSet dataSet; - - // The significance level of the independence tests. - private double alpha; - - // The cutoff value for 'alpha' area in the two tails of the partial correlation distribution function. - private double thresh = Double.NaN; - - //The value of the Fisher's Z statistic associated with the last calculated partial correlation. - private double fishersZ; - private boolean verbose; - - //==========================CONSTRUCTORS=============================// - - /** - * Constructs a new Independence test which checks independence facts based on the correlation matrix implied by the - * given data set (must be continuous). The given significance level is used. - * - * @param dataSet A data set containing only continuous columns. - * @param alpha The alpha level of the test. - */ - public IndTestFisherZPseudoinverse(DataSet dataSet, double alpha) { - if (!(alpha >= 0 && alpha <= 1)) { - throw new IllegalArgumentException("Alpha mut be in [0, 1]"); - } - - this.dataSet = dataSet; - - this.data = dataSet.getDoubleData(); - this.variables = Collections.unmodifiableList(this.dataSet.getVariables()); - setAlpha(alpha); - } - - //==========================PUBLIC METHODS=============================// - - /** - * Creates a new IndTestCramerT instance for a subset of the variables. - */ - public IndependenceTest indTestSubset(List vars) { - return null; - } - - /** - * Determines whether variable x is independent of variable y given a list of conditioning variables z. - * - * @param xVar the one variable being compared. - * @param yVar the second variable being compared. - * @param _z the list of conditioning variables. - * @return True iff x _||_ y | z. - * @throws RuntimeException if a matrix singularity is encountered. - */ - public IndependenceResult checkIndependence(Node xVar, Node yVar, Set _z) { - if (_z == null) { - throw new NullPointerException(); - } - - for (Node node : _z) { - if (node == null) { - throw new NullPointerException(); - } - } - - List z = new ArrayList<>(_z); - Collections.sort(z); - - int size = z.size(); - int[] zCols = new int[size]; - - int xIndex = getVariables().indexOf(xVar); - int yIndex = getVariables().indexOf(yVar); - - for (int i = 0; i < z.size(); i++) { - zCols[i] = getVariables().indexOf(z.get(i)); - } - - Vector x = this.data.getColumn(xIndex); - Vector y = this.data.getColumn(yIndex); - - CovarianceMatrix cov = new CovarianceMatrix(dataSet); - - SemBicScore.CovAndCoefs covAndCoefsX = SemBicScore.getCovAndCoefs(xIndex, zCols, this.data, - cov, true, true); - SemBicScore.CovAndCoefs covAndCoefsY = SemBicScore.getCovAndCoefs(yIndex, zCols, this.data, - cov, true, true); - - int[] rows = new int[this.data.getNumRows()]; - for (int i = 0; i < rows.length; i++) { - rows[i] = i; - } - - Matrix selection = data.getSelection(rows, zCols); - Vector xPred = selection.times(covAndCoefsX.b()).getColumn(0); - Vector yPred = selection.times(covAndCoefsY.b()).getColumn(0); - - Vector xRes = xPred.minus(x); - Vector yRes = yPred.minus(y); - - // Note that r will be NaN if either xRes or yRes is constant. - double r = StatUtils.correlation(xRes.toArray(), yRes.toArray()); - - if (Double.isNaN(this.thresh)) { - this.thresh = cutoffGaussian(); - } - - if (Double.isNaN(r)) { - if (this.verbose) { - TetradLogger.getInstance().log("independencies", LogUtilsSearch.independenceFactMsg(xVar, yVar, _z, getPValue())); - } - return new IndependenceResult(new IndependenceFact(xVar, yVar, _z), false, Double.NaN, Double.NaN); - } - - if (r > 1) r = 1; - if (r < -1) r = -1; - - this.fishersZ = FastMath.sqrt(sampleSize() - z.size() - 3.0) * - 0.5 * (FastMath.log(1.0 + r) - FastMath.log(1.0 - r)); - - if (Double.isNaN(this.fishersZ)) { - throw new IllegalArgumentException("The Fisher's Z " + - "score for independence fact " + xVar + " _||_ " + yVar + - " | " + z + " is undefined."); - } - - boolean indFisher = !(FastMath.abs(this.fishersZ) > this.thresh); - - if (this.verbose) { - TetradLogger.getInstance().log("independencies", LogUtilsSearch.independenceFactMsg(xVar, yVar, _z, getPValue())); - } - - if (Double.isNaN(getPValue())) { - throw new RuntimeException("Undefined p-value encountered for test: " + LogUtilsSearch.independenceFact(xVar, yVar, _z)); - } - - if (this.verbose) { - if (indFisher) { - TetradLogger.getInstance().forceLogMessage( - LogUtilsSearch.independenceFactMsg(xVar, yVar, _z, getPValue())); - } - } - - return new IndependenceResult(new IndependenceFact(xVar, yVar, _z), indFisher, getPValue(), getAlpha() - getPValue()); - } - - /** - * @return the probability associated with the most recently computed independence test. - */ - public double getPValue() { - return 2.0 * (1.0 - RandomUtil.getInstance().normalCdf(0, 1, FastMath.abs(this.fishersZ))); - } - - /** - * Gets the getModel significance level. - */ - public double getAlpha() { - return this.alpha; - } - - /** - * Sets the significance level at which independence judgments should be made. Affects the cutoff for partial - * correlations to be considered statistically equal to zero. - */ - public void setAlpha(double alpha) { - if (alpha < 0.0 || alpha > 1.0) { - throw new IllegalArgumentException("Significance out of range."); - } - - this.alpha = alpha; - } - - /** - * @return the list of variables over which this independence checker is capable of determinine independence - * relations-- that is, all the variables in the given graph or the given data set. - */ - public List getVariables() { - return this.variables; - } - - public String toString() { - return "Fisher's Z - Pseudoinverse, alpha = " + IndTestFisherZPseudoinverse.nf.format(getAlpha()); - } - - /** - * Returns the data being analyzed. - * - * @return This data. - */ - public DataSet getData() { - return this.dataSet; - } - - /** - * Returns True just in case verbose output should be printed. - * - * @return This. - */ - public boolean isVerbose() { - return this.verbose; - } - - /** - * Sets whether verbose output should be printed. - * - * @param verbose True, if so. - */ - public void setVerbose(boolean verbose) { - this.verbose = verbose; - } - - /** - * Returns true just in case the varialbe in zList determine xVar. - * - * @return True, if so. - */ - public boolean determines(List zList, Node xVar) { - if (zList == null) { - throw new NullPointerException(); - } - - if (zList.isEmpty()) { - return false; - } - - for (Node node : zList) { - if (node == null) { - throw new NullPointerException(); - } - } - - int size = zList.size(); - int[] zCols = new int[size]; - - int xIndex = getVariables().indexOf(xVar); - Vector x = this.data.getColumn(xIndex); - - for (int i = 0; i < zList.size(); i++) { - zCols[i] = getVariables().indexOf(zList.get(i)); - } - - CovarianceMatrix cov = new CovarianceMatrix(dataSet); - - SemBicScore.CovAndCoefs covAndCoefsX = SemBicScore.getCovAndCoefs(xIndex, zCols, this.data, - cov, true, true); - - int[] rows = new int[this.data.getNumRows()]; - for (int i = 0; i < rows.length; i++) { - rows[i] = i; - } - - Matrix selection = data.getSelection(rows, zCols); - Vector xPred = selection.times(covAndCoefsX.b()).getColumn(0); - Vector xRes = xPred.minus(x); - - double SSE = 0; - - for (int i = 0; i < xRes.size(); i++) { - SSE += xRes.get(i) * xRes.get(i); - } - - double variance = SSE / (this.data.getNumRows() - (zList.size() + 1)); - - boolean determined = variance < getAlpha(); - - if (determined) { - StringBuilder sb = new StringBuilder(); - sb.append("Determination found: ").append(xVar).append( - " is determined by {"); - - for (int i = 0; i < zList.size(); i++) { - sb.append(zList.get(i)); - - if (i < zList.size() - 1) { - sb.append(", "); - } - } - - sb.append("}"); - - sb.append(" SSE = ").append(IndTestFisherZPseudoinverse.nf.format(SSE)); - - TetradLogger.getInstance().log("independencies", sb.toString()); - System.out.println(sb); - } - - return determined; - } - - /** - * Computes that value x such that P(abs(N(0,1) > x) < alpha. Note that this is a two-sided test of the null - * hypothesis that the Fisher's Z value, which is distributed as N(0,1) is not equal to 0.0. - */ - private double cutoffGaussian() { - double upperTail = 1.0 - getAlpha() / 2.0; - final double epsilon = 1e-14; - - // Find an upper bound. - double lowerBound = -1.0; - double upperBound = 0.0; - - while (RandomUtil.getInstance().normalCdf(0, 1, upperBound) < upperTail) { - lowerBound += 1.0; - upperBound += 1.0; - } - - while (upperBound >= lowerBound + epsilon) { - double midPoint = lowerBound + (upperBound - lowerBound) / 2.0; - - if (RandomUtil.getInstance().normalCdf(0, 1, midPoint) <= upperTail) { - lowerBound = midPoint; - } else { - upperBound = midPoint; - } - } - - return lowerBound; - } - - private int sampleSize() { - return this.data.getNumRows(); - } -} - - - - - diff --git a/tetrad-lib/src/test/java/edu/cmu/tetrad/test/TestIndTestFisherGeneralizedInverse.java b/tetrad-lib/src/test/java/edu/cmu/tetrad/test/TestIndTestFisherGeneralizedInverse.java index b8b3469f70..ce0a50e167 100644 --- a/tetrad-lib/src/test/java/edu/cmu/tetrad/test/TestIndTestFisherGeneralizedInverse.java +++ b/tetrad-lib/src/test/java/edu/cmu/tetrad/test/TestIndTestFisherGeneralizedInverse.java @@ -23,9 +23,8 @@ import edu.cmu.tetrad.data.DataSet; import edu.cmu.tetrad.graph.*; -import edu.cmu.tetrad.search.IndependenceTest; +import edu.cmu.tetrad.search.test.IndTestFisherZ; import edu.cmu.tetrad.search.test.IndependenceResult; -import edu.cmu.tetrad.search.work_in_progress.IndTestFisherZPseudoinverse; import edu.cmu.tetrad.sem.SemIm; import edu.cmu.tetrad.sem.SemPm; import edu.cmu.tetrad.util.RandomUtil; @@ -77,8 +76,11 @@ public void testDirections() { DataSet data1 = im1.simulateData(500, false); DataSet data2 = im2.simulateData(500, false); - IndependenceTest test1 = new IndTestFisherZPseudoinverse(data1, 0.05); - IndependenceTest test2 = new IndTestFisherZPseudoinverse(data2, 0.05); + IndTestFisherZ test1 = new IndTestFisherZ(data1, 0.05); + IndTestFisherZ test2 = new IndTestFisherZ(data2, 0.05); + + test1.setUsePseudoinverse(true); + test2.setUsePseudoinverse(true); IndependenceResult result1 = test1.checkIndependence(data1.getVariable(x.getName()), data1.getVariable(y.getName())); double p1 = result1.getPValue(); From 6e692e9a392c5bb361a65eb839a0f2643a0d4df0 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Sat, 20 Jan 2024 17:08:37 -0500 Subject: [PATCH 091/163] Removed the separate pseudoinverse fisher z class. --- .../main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java index 9e3f20de79..f10488a59c 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java @@ -512,7 +512,7 @@ public boolean determines(List z, Node x) throws UnsupportedOperationExcep * * @return True, if so. */ - public boolean determinesPseudoinverse(List zList, Node xVar) { + private boolean determinesPseudoinverse(List zList, Node xVar) { if (zList == null) { throw new NullPointerException(); } From 04b474f193b8eb8c2bc642fb1635c3250ab955c9 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Sat, 20 Jan 2024 17:47:57 -0500 Subject: [PATCH 092/163] Made other tests and scores take the pseudoinverse parameter where possible. --- .../tetrad/algcomparison/independence/GICScoreTests.java | 5 ++++- .../algcomparison/independence/PoissonScoreTest.java | 5 +++++ .../cmu/tetrad/algcomparison/independence/SemBicTest.java | 2 ++ .../edu/cmu/tetrad/algcomparison/score/EbicScore.java | 6 ++++-- .../edu/cmu/tetrad/algcomparison/score/GicScores.java | 5 ++++- .../cmu/tetrad/algcomparison/score/PoissonPriorScore.java | 2 ++ .../tetrad/algcomparison/score/ZhangShenBoundScore.java | 2 ++ .../main/java/edu/cmu/tetrad/search/score/EbicScore.java | 8 +++++++- .../main/java/edu/cmu/tetrad/search/score/GicScores.java | 7 ++++++- .../edu/cmu/tetrad/search/score/PoissonPriorScore.java | 8 +++++++- .../main/java/edu/cmu/tetrad/search/score/ZsbScore.java | 8 ++++++-- 11 files changed, 49 insertions(+), 9 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/GICScoreTests.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/GICScoreTests.java index bd02f7529f..419c15561c 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/GICScoreTests.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/GICScoreTests.java @@ -12,6 +12,7 @@ import edu.cmu.tetrad.util.Parameters; import edu.cmu.tetrad.util.Params; +import java.io.Serial; import java.util.ArrayList; import java.util.List; @@ -28,6 +29,7 @@ @LinearGaussian public class GICScoreTests implements IndependenceWrapper { + @Serial private static final long serialVersionUID = 23L; @Override @@ -71,7 +73,7 @@ public IndependenceTest getTest(DataModel dataSet, Parameters parameters) { score.setRuleType(ruleType); score.setPenaltyDiscount(parameters.getDouble(Params.PENALTY_DISCOUNT)); - + score.setUsePseudoInverse(parameters.getBoolean(Params.USE_PSEUDOINVERSE)); return new ScoreIndTest(score, dataSet); } @@ -92,6 +94,7 @@ public List getParameters() { params.add(Params.SEM_GIC_RULE); params.add(Params.PENALTY_DISCOUNT_ZS); params.add(Params.PRECOMPUTE_COVARIANCES); + params.add(Params.USE_PSEUDOINVERSE); return params; } } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/PoissonScoreTest.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/PoissonScoreTest.java index 7133f58047..011e9ac1c4 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/PoissonScoreTest.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/PoissonScoreTest.java @@ -12,6 +12,7 @@ import edu.cmu.tetrad.util.Parameters; import edu.cmu.tetrad.util.Params; +import java.io.Serial; import java.util.ArrayList; import java.util.List; @@ -28,6 +29,7 @@ @LinearGaussian public class PoissonScoreTest implements IndependenceWrapper { + @Serial private static final long serialVersionUID = 23L; @Override @@ -39,7 +41,9 @@ public IndependenceTest getTest(DataModel dataSet, Parameters parameters) { } else { score = new PoissonPriorScore((DataSet) dataSet, true); } + score.setLambda(parameters.getDouble(Params.POISSON_LAMBDA)); + score.setUsePseudoInverse(parameters.getBoolean(Params.USE_PSEUDOINVERSE)); return new ScoreIndTest(score, dataSet); } @@ -58,6 +62,7 @@ public DataType getDataType() { public List getParameters() { List params = new ArrayList<>(); params.add(Params.POISSON_LAMBDA); + params.add(Params.USE_PSEUDOINVERSE); return params; } } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/SemBicTest.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/SemBicTest.java index 1bd5bd099f..e1ed4f9855 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/SemBicTest.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/SemBicTest.java @@ -43,6 +43,7 @@ public IndependenceTest getTest(DataModel dataSet, Parameters parameters) { } score.setPenaltyDiscount(parameters.getDouble(Params.PENALTY_DISCOUNT)); score.setStructurePrior(parameters.getDouble(Params.STRUCTURE_PRIOR)); + score.setUsePseudoInverse(parameters.getBoolean(Params.USE_PSEUDOINVERSE)); return new ScoreIndTest(score, dataSet); } @@ -63,6 +64,7 @@ public List getParameters() { params.add(Params.PENALTY_DISCOUNT); params.add(Params.STRUCTURE_PRIOR); params.add(Params.PRECOMPUTE_COVARIANCES); + params.add(Params.USE_PSEUDOINVERSE); return params; } } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/score/EbicScore.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/score/EbicScore.java index 3b9e10c94f..83061b8dd8 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/score/EbicScore.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/score/EbicScore.java @@ -10,6 +10,7 @@ import edu.cmu.tetrad.util.Parameters; import edu.cmu.tetrad.util.Params; +import java.io.Serial; import java.util.ArrayList; import java.util.List; @@ -26,6 +27,7 @@ @LinearGaussian public class EbicScore implements ScoreWrapper { + @Serial private static final long serialVersionUID = 23L; private DataModel dataSet; @@ -44,7 +46,7 @@ public Score getScore(DataModel dataSet, Parameters parameters) { } score.setGamma(parameters.getDouble(Params.EBIC_GAMMA)); -// score.setCorrelationThreshold(parameters.getDouble(Params.CORRELATION_THRESHOLD)); + score.setUsePseudoInverse(parameters.getBoolean(Params.USE_PSEUDOINVERSE)); return score; } @@ -62,8 +64,8 @@ public DataType getDataType() { public List getParameters() { List parameters = new ArrayList<>(); parameters.add(Params.EBIC_GAMMA); -// parameters.add(Params.CORRELATION_THRESHOLD); parameters.add(Params.PRECOMPUTE_COVARIANCES); + parameters.add(Params.USE_PSEUDOINVERSE); return parameters; } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/score/GicScores.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/score/GicScores.java index aa169a1ad9..4951ebb7af 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/score/GicScores.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/score/GicScores.java @@ -19,7 +19,7 @@ * @author josephramsey */ @edu.cmu.tetrad.annotation.Score( - name = "Generalied Information Criterion Scores", + name = "Generalized Information Criterion Scores", command = "gic-scores", dataType = {DataType.Continuous, DataType.Covariance} ) @@ -72,6 +72,7 @@ public Score getScore(DataModel dataSet, Parameters parameters) { score.setRuleType(ruleType); score.setPenaltyDiscount(parameters.getDouble(Params.PENALTY_DISCOUNT)); + score.setUsePseudoInverse(parameters.getBoolean(Params.USE_PSEUDOINVERSE)); return score; } @@ -92,6 +93,8 @@ public List getParameters() { parameters.add(Params.SEM_GIC_RULE); parameters.add(Params.PENALTY_DISCOUNT_ZS); parameters.add(Params.PRECOMPUTE_COVARIANCES); + parameters.add(Params.USE_PSEUDOINVERSE); + return parameters; } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/score/PoissonPriorScore.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/score/PoissonPriorScore.java index 124039dd0c..889419e0c3 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/score/PoissonPriorScore.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/score/PoissonPriorScore.java @@ -44,6 +44,7 @@ public Score getScore(DataModel dataSet, Parameters parameters) { } score.setLambda(parameters.getDouble(Params.POISSON_LAMBDA)); + score.setUsePseudoInverse(parameters.getBoolean(Params.USE_PSEUDOINVERSE)); return score; } @@ -63,6 +64,7 @@ public List getParameters() { List parameters = new ArrayList<>(); parameters.add(Params.PRECOMPUTE_COVARIANCES); parameters.add(Params.POISSON_LAMBDA); + parameters.add(Params.USE_PSEUDOINVERSE); return parameters; } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/score/ZhangShenBoundScore.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/score/ZhangShenBoundScore.java index 9f6649fa03..5ec4e0f65b 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/score/ZhangShenBoundScore.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/score/ZhangShenBoundScore.java @@ -47,6 +47,7 @@ public Score getScore(DataModel dataSet, Parameters parameters) { } score.setRiskBound(parameters.getDouble(Params.ZS_RISK_BOUND)); + score.setUsePseudoInverse(parameters.getBoolean(Params.USE_PSEUDOINVERSE)); return score; } @@ -66,6 +67,7 @@ public List getParameters() { List parameters = new ArrayList<>(); parameters.add(Params.ZS_RISK_BOUND); parameters.add(Params.PRECOMPUTE_COVARIANCES); + parameters.add(Params.USE_PSEUDOINVERSE); return parameters; } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/EbicScore.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/EbicScore.java index 6d618b12e1..07b6ceef47 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/EbicScore.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/EbicScore.java @@ -54,6 +54,7 @@ public class EbicScore implements Score { private Matrix data; private boolean calculateRowSubsets; private double gamma = 1; + private boolean usePseudoInverse = false; /** * Constructs the score using a covariance matrix. @@ -116,7 +117,8 @@ public double localScore(int i, int... parents) throws RuntimeException { double varRy; try { - varRy = SemBicScore.getVarRy(i, parents, this.data, this.covariances, this.calculateRowSubsets); + varRy = SemBicScore.getVarRy(i, parents, this.data, this.covariances, this.calculateRowSubsets, + this.usePseudoInverse); } catch (SingularMatrixException e) { throw new RuntimeException("Singularity encountered when scoring " + LogUtilsSearch.getScoreFact(i, parents, variables)); @@ -212,6 +214,10 @@ private int[] indices(List __adj) { for (int t = 0; t < __adj.size(); t++) indices[t] = this.variables.indexOf(__adj.get(t)); return indices; } + + public void setUsePseudoInverse(boolean usePseudoInverse) { + this.usePseudoInverse = usePseudoInverse; + } } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/GicScores.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/GicScores.java index 7e47feae92..df582746ae 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/GicScores.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/GicScores.java @@ -68,6 +68,7 @@ public class GicScores implements Score { private boolean calculateRowSubsets = false; // private boolean calculateSquareEuclideanNorms = false; private double penaltyDiscount = 1; + private boolean usePseudoInverse = false; /** * Constructs the score using a covariance matrix. @@ -128,7 +129,7 @@ public double localScore(int i, int... parents) { double varry; try { - varry = SemBicScore.getVarRy(i, parents, data, covariances, calculateRowSubsets); + varry = SemBicScore.getVarRy(i, parents, data, covariances, calculateRowSubsets, this.usePseudoInverse); } catch (SingularMatrixException e) { throw new RuntimeException("Singularity encountered when scoring " + LogUtilsSearch.getScoreFact(i, parents, variables)); @@ -322,6 +323,10 @@ public String toString() { return "Generalized Information Criterion Score"; } + public void setUsePseudoInverse(boolean usePseudoInverse) { + this.usePseudoInverse = usePseudoInverse; + } + /** * Gives the options for the rules to use for calculating the scores. The "GIC" rules, and RICc, are the rules diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/PoissonPriorScore.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/PoissonPriorScore.java index 99617ec475..d7b422ac50 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/PoissonPriorScore.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/PoissonPriorScore.java @@ -69,6 +69,7 @@ public class PoissonPriorScore implements Score { private boolean calculateRowSubsets; private double lambda = 3.; + private boolean usePseudoInverse = false; /** * Constructs the score using a covariance matrix. @@ -129,7 +130,8 @@ public double localScore(int i, int... parents) throws RuntimeException { double varRy; try { - varRy = SemBicScore.getVarRy(i, parents, this.data, this.covariances, this.calculateRowSubsets); + varRy = SemBicScore.getVarRy(i, parents, this.data, this.covariances, this.calculateRowSubsets, + this.usePseudoInverse); } catch (SingularMatrixException e) { throw new RuntimeException("Singularity encountered when scoring " + LogUtilsSearch.getScoreFact(i, parents, variables)); @@ -223,6 +225,10 @@ private int[] indices(List __adj) { for (int t = 0; t < __adj.size(); t++) indices[t] = this.variables.indexOf(__adj.get(t)); return indices; } + + public void setUsePseudoInverse(boolean usePseudoInverse) { + this.usePseudoInverse = usePseudoInverse; + } } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/ZsbScore.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/ZsbScore.java index 29a7548982..4b550e6252 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/ZsbScore.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/ZsbScore.java @@ -81,7 +81,7 @@ public class ZsbScore implements Score { // The data, if it is set. private Matrix data; - private boolean changed = false; + private boolean usePseudoInverse; /** * Constructs the score using a covariance matrix. @@ -162,7 +162,7 @@ public double localScore(int i, int... parents) { double varRy; try { - varRy = SemBicScore.getVarRy(i, parents, data, covariances, calculateRowSubsets); + varRy = SemBicScore.getVarRy(i, parents, data, covariances, calculateRowSubsets, usePseudoInverse); } catch (SingularMatrixException e) { throw new RuntimeException("Singularity encountered when scoring " + LogUtilsSearch.getScoreFact(i, parents, variables)); @@ -311,6 +311,10 @@ private int[] indices(List __adj) { for (int t = 0; t < __adj.size(); t++) indices[t] = variables.indexOf(__adj.get(t)); return indices; } + + public void setUsePseudoInverse(boolean usePseudoInverse) { + this.usePseudoInverse = usePseudoInverse; + } } From 21d2092bdcb35b152ad2195868f7e17d7067e778 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Sat, 20 Jan 2024 18:02:23 -0500 Subject: [PATCH 093/163] Made other tests and scores take the pseudoinverse parameter where possible. --- .../independence/SemBicTest.java | 2 ++ .../tetrad/algcomparison/score/GicScores.java | 35 ++++++------------- .../score/ZhangShenBoundScore.java | 2 ++ 3 files changed, 15 insertions(+), 24 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/SemBicTest.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/SemBicTest.java index e1ed4f9855..890d77e66f 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/SemBicTest.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/SemBicTest.java @@ -12,6 +12,7 @@ import edu.cmu.tetrad.util.Parameters; import edu.cmu.tetrad.util.Params; +import java.io.Serial; import java.util.ArrayList; import java.util.List; @@ -28,6 +29,7 @@ @LinearGaussian public class SemBicTest implements IndependenceWrapper { + @Serial private static final long serialVersionUID = 23L; @Override diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/score/GicScores.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/score/GicScores.java index 4951ebb7af..997bf06e53 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/score/GicScores.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/score/GicScores.java @@ -10,6 +10,7 @@ import edu.cmu.tetrad.util.Parameters; import edu.cmu.tetrad.util.Params; +import java.io.Serial; import java.util.ArrayList; import java.util.List; @@ -26,6 +27,7 @@ @LinearGaussian public class GicScores implements ScoreWrapper { + @Serial private static final long serialVersionUID = 23L; private DataModel dataSet; @@ -45,30 +47,15 @@ public Score getScore(DataModel dataSet, Parameters parameters) { } int anInt = parameters.getInt((Params.SEM_GIC_RULE)); - edu.cmu.tetrad.search.score.GicScores.RuleType ruleType; - - switch (anInt) { - case 1: - ruleType = edu.cmu.tetrad.search.score.GicScores.RuleType.BIC; - break; - case 2: - ruleType = edu.cmu.tetrad.search.score.GicScores.RuleType.GIC2; - break; - case 3: - ruleType = edu.cmu.tetrad.search.score.GicScores.RuleType.RIC; - break; - case 4: - ruleType = edu.cmu.tetrad.search.score.GicScores.RuleType.RICc; - break; - case 5: - ruleType = edu.cmu.tetrad.search.score.GicScores.RuleType.GIC5; - break; - case 6: - ruleType = edu.cmu.tetrad.search.score.GicScores.RuleType.GIC6; - break; - default: - throw new IllegalArgumentException("Unrecognized rule type: " + anInt); - } + edu.cmu.tetrad.search.score.GicScores.RuleType ruleType = switch (anInt) { + case 1 -> edu.cmu.tetrad.search.score.GicScores.RuleType.BIC; + case 2 -> edu.cmu.tetrad.search.score.GicScores.RuleType.GIC2; + case 3 -> edu.cmu.tetrad.search.score.GicScores.RuleType.RIC; + case 4 -> edu.cmu.tetrad.search.score.GicScores.RuleType.RICc; + case 5 -> edu.cmu.tetrad.search.score.GicScores.RuleType.GIC5; + case 6 -> edu.cmu.tetrad.search.score.GicScores.RuleType.GIC6; + default -> throw new IllegalArgumentException("Unrecognized rule type: " + anInt); + }; score.setRuleType(ruleType); score.setPenaltyDiscount(parameters.getDouble(Params.PENALTY_DISCOUNT)); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/score/ZhangShenBoundScore.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/score/ZhangShenBoundScore.java index 5ec4e0f65b..dd6f85baf6 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/score/ZhangShenBoundScore.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/score/ZhangShenBoundScore.java @@ -11,6 +11,7 @@ import edu.cmu.tetrad.util.Parameters; import edu.cmu.tetrad.util.Params; +import java.io.Serial; import java.util.ArrayList; import java.util.List; @@ -27,6 +28,7 @@ @LinearGaussian public class ZhangShenBoundScore implements ScoreWrapper { + @Serial private static final long serialVersionUID = 23L; private DataModel dataSet; From 06b437c185748e03bccf9da3e95f57149236d4b6 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Tue, 23 Jan 2024 13:10:36 -0500 Subject: [PATCH 094/163] Added caching of independence results for all independence tests (except for Probabilistic test, which has an element of randomness). Also, fixed an issue in GrowShrink. --- .../edu/cmu/tetradapp/editor/DagEditor.java | 1 + .../edu/cmu/tetradapp/editor/GraphEditor.java | 2 + .../editor/SelectBidirectedAction.java | 10 +- .../editor/SelectDirectedAction.java | 8 +- .../tetradapp/editor/SelectLatentsAction.java | 10 +- .../editor/SelectTrianglesAction.java | 93 +++++++++++++++++++ .../editor/SelectUndirectedAction.java | 10 +- .../cmu/tetradapp/editor/SemGraphEditor.java | 4 +- .../tetradapp/editor/search/GraphCard.java | 1 + .../editor/simulation/ParameterTab.java | 2 +- .../algcomparison/independence/Kci.java | 28 +++++- .../simulation/SimulationTypes.java | 10 +- .../edu/cmu/tetrad/search/GrowShrink.java | 69 ++++++++------ .../tetrad/search/test/IndTestChiSquare.java | 18 +++- .../test/IndTestConditionalCorrelation.java | 38 ++++---- .../test/IndTestConditionalGaussianLrt.java | 18 +++- .../test/IndTestDegenerateGaussianLrt.java | 15 ++- .../tetrad/search/test/IndTestFisherZ.java | 30 ++++-- .../IndTestFisherZConcatenateResiduals.java | 36 ++++--- .../test/IndTestFisherZFisherPValue.java | 51 ++++++---- .../tetrad/search/test/IndTestGSquare.java | 60 +++++------- .../cmu/tetrad/search/test/IndTestHsic.java | 18 +++- .../cmu/tetrad/search/test/IndTestMulti.java | 42 +++++---- .../cmu/tetrad/search/test/IndTestMvpLrt.java | 23 ++++- .../search/test/IndTestProbabilistic.java | 84 +++++++++-------- .../tetrad/search/test/IndTestRegression.java | 50 +++++----- .../tetrad/search/test/IndTestTrekSep.java | 34 +++++-- .../java/edu/cmu/tetrad/search/test/Kci.java | 25 +++-- .../edu/cmu/tetrad/search/test/MsepTest.java | 30 +++--- .../cmu/tetrad/search/utils/EstimateRank.java | 4 +- 30 files changed, 551 insertions(+), 273 deletions(-) create mode 100644 tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/SelectTrianglesAction.java diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/DagEditor.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/DagEditor.java index d0caaf38c3..002eeb875a 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/DagEditor.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/DagEditor.java @@ -425,6 +425,7 @@ private JMenu createGraphMenu() { graph.add(new JMenuItem(new SelectDirectedAction(this.workbench))); graph.add(new JMenuItem(new SelectBidirectedAction(this.workbench))); graph.add(new JMenuItem(new SelectUndirectedAction(this.workbench))); + graph.add(new JMenuItem(new SelectTrianglesAction(this.workbench))); graph.add(new JMenuItem(new SelectLatentsAction(this.workbench))); // graph.add(new PagTypeSetter(getWorkbench())); diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/GraphEditor.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/GraphEditor.java index 11ca86bd80..2e205bdeba 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/GraphEditor.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/GraphEditor.java @@ -417,6 +417,7 @@ JMenuBar createGraphMenuBarNoEditing() { graph.add(new JMenuItem(new SelectDirectedAction(this.workbench))); graph.add(new JMenuItem(new SelectBidirectedAction(this.workbench))); graph.add(new JMenuItem(new SelectUndirectedAction(this.workbench))); + graph.add(new JMenuItem(new SelectTrianglesAction(this.workbench))); graph.add(new JMenuItem(new SelectLatentsAction(this.workbench))); // graph.addSeparator(); graph.add(new PagColorer(getWorkbench())); @@ -521,6 +522,7 @@ public void internalFrameClosed(InternalFrameEvent e1) { graph.add(new JMenuItem(new SelectDirectedAction(getWorkbench()))); graph.add(new JMenuItem(new SelectBidirectedAction(getWorkbench()))); graph.add(new JMenuItem(new SelectUndirectedAction(getWorkbench()))); + graph.add(new JMenuItem(new SelectTrianglesAction(getWorkbench()))); graph.add(new JMenuItem(new SelectLatentsAction(getWorkbench()))); graph.add(new PagColorer(getWorkbench())); diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/SelectBidirectedAction.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/SelectBidirectedAction.java index 6c8d558347..9c39e8fd80 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/SelectBidirectedAction.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/SelectBidirectedAction.java @@ -34,7 +34,7 @@ import java.awt.event.ActionEvent; /** - * Copies a selection of session nodes in the frontmost session editor, to the clipboard. + * Highlights all bidirected edges in the given display graph. * * @author josephramsey */ @@ -46,7 +46,9 @@ public class SelectBidirectedAction extends AbstractAction implements ClipboardO private final GraphWorkbench workbench; /** - * Creates a new copy subsession action for the given desktop and clipboard. + * Highlights all bidirected edges in the given display graph. + * + * @param workbench the given workbench. */ public SelectBidirectedAction(GraphWorkbench workbench) { super("Highlight Bidirected Edges"); @@ -59,7 +61,9 @@ public SelectBidirectedAction(GraphWorkbench workbench) { } /** - * Copies a parentally closed selection of session nodes in the frontmost session editor to the clipboard. + * Highlights all bidirected edges in the given display graph. + * + * @param e the event to be processed */ public void actionPerformed(ActionEvent e) { this.workbench.deselectAll(); diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/SelectDirectedAction.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/SelectDirectedAction.java index f7b7cf8a98..4d87a737c3 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/SelectDirectedAction.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/SelectDirectedAction.java @@ -34,7 +34,7 @@ import java.awt.event.ActionEvent; /** - * Copies a selection of session nodes in the frontmost session editor, to the clipboard. + * Selects all directed edges in the given display graph. * * @author josephramsey */ @@ -47,6 +47,8 @@ public class SelectDirectedAction extends AbstractAction implements ClipboardOwn /** * Creates a new copy subsession action for the given desktop and clipboard. + * + * @param workbench the given workbench. */ public SelectDirectedAction(GraphWorkbench workbench) { super("Highlight Directed Edges"); @@ -59,7 +61,9 @@ public SelectDirectedAction(GraphWorkbench workbench) { } /** - * Copies a parentally closed selection of session nodes in the frontmost session editor to the clipboard. + * Selects all directed edges in the given display graph. + * + * @param e the event to be processed */ public void actionPerformed(ActionEvent e) { this.workbench.deselectAll(); diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/SelectLatentsAction.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/SelectLatentsAction.java index 0efae92daa..f61e37e4b9 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/SelectLatentsAction.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/SelectLatentsAction.java @@ -36,7 +36,7 @@ import java.awt.event.ActionEvent; /** - * Copies a selection of session nodes in the frontmost session editor, to the clipboard. + * Highlights all latent variables in the given display graph. * * @author josephramsey */ @@ -48,7 +48,9 @@ public class SelectLatentsAction extends AbstractAction implements ClipboardOwne private final GraphWorkbench workbench; /** - * Creates a new copy subsession action for the given desktop and clipboard. + * Highlights all latent variables in the given display graph. + * + * @param workbench the given workbench. */ public SelectLatentsAction(GraphWorkbench workbench) { super("Highlight Latent Nodes"); @@ -61,7 +63,9 @@ public SelectLatentsAction(GraphWorkbench workbench) { } /** - * Copies a parentally closed selection of session nodes in the frontmost session editor to the clipboard. + * Highlights all latent variables in the given display graph. + * + * @param e the event to be processed */ public void actionPerformed(ActionEvent e) { this.workbench.deselectAll(); diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/SelectTrianglesAction.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/SelectTrianglesAction.java new file mode 100644 index 0000000000..a2c2ee2a15 --- /dev/null +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/SelectTrianglesAction.java @@ -0,0 +1,93 @@ +/////////////////////////////////////////////////////////////////////////////// +// For information as to what this class does, see the Javadoc, below. // +// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, // +// 2007, 2008, 2009, 2010, 2014, 2015, 2022 by Peter Spirtes, Richard // +// Scheines, Joseph Ramsey, and Clark Glymour. // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation; either version 2 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program; if not, write to the Free Software // +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // +/////////////////////////////////////////////////////////////////////////////// + +package edu.cmu.tetradapp.editor; + +import edu.cmu.tetrad.graph.Edge; +import edu.cmu.tetrad.graph.Graph; +import edu.cmu.tetrad.graph.Node; +import edu.cmu.tetradapp.workbench.GraphWorkbench; + +import javax.swing.*; +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.ClipboardOwner; +import java.awt.datatransfer.Transferable; +import java.awt.event.ActionEvent; + +/** + * Highlights all edges in triangle in the given display graph. + * + * @author josephramsey + */ +public class SelectTrianglesAction extends AbstractAction implements ClipboardOwner { + + /** + * The desktop containing the target session editor. + */ + private final GraphWorkbench workbench; + + /** + * Highlights all edges in triangle in the given display graph. + * + * @param workbench the given workbench. + */ + public SelectTrianglesAction(GraphWorkbench workbench) { + super("Highlight Triangles"); + + if (workbench == null) { + throw new NullPointerException("Desktop must not be null."); + } + + this.workbench = workbench; + } + + /** + * Selects all edges in triangle in the given display graph. + * + * @param e the event to be processed + */ + public void actionPerformed(ActionEvent e) { + this.workbench.deselectAll(); + + final Graph graph = this.workbench.getGraph(); + + for (Edge edge : graph.getEdges()) { + for (Node node : graph.getAdjacentNodes(edge.getNode1())) { + if (node == edge.getNode1() || node == edge.getNode2()) { + continue; + } + + if (graph.isAdjacentTo(node, edge.getNode1()) && graph.isAdjacentTo(node, edge.getNode2())) { + this.workbench.selectEdge(edge); + } + } + } + } + + /** + * Required by the AbstractAction interface; does nothing. + */ + public void lostOwnership(Clipboard clipboard, Transferable contents) { + } +} + + + diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/SelectUndirectedAction.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/SelectUndirectedAction.java index a93e547060..3eb259c20d 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/SelectUndirectedAction.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/SelectUndirectedAction.java @@ -34,7 +34,7 @@ import java.awt.event.ActionEvent; /** - * Copies a selection of session nodes in the frontmost session editor, to the clipboard. + * Highlights all undirected edges in the given display graph. * * @author josephramsey */ @@ -46,7 +46,9 @@ public class SelectUndirectedAction extends AbstractAction implements ClipboardO private final GraphWorkbench workbench; /** - * Creates a new copy subsession action for the given desktop and clipboard. + * Highlights all undirected edges in the given display graph. + * + * @param workbench the given workbench. */ public SelectUndirectedAction(GraphWorkbench workbench) { super("Highlight Undirected Edges"); @@ -59,7 +61,9 @@ public SelectUndirectedAction(GraphWorkbench workbench) { } /** - * Copies a parentally closed selection of session nodes in the frontmost session editor to the clipboard. + * Selects all undirected edges in the given display graph. + * + * @param e the event to be processed */ public void actionPerformed(ActionEvent e) { this.workbench.deselectAll(); diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/SemGraphEditor.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/SemGraphEditor.java index 75c83fe070..214c4897a5 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/SemGraphEditor.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/SemGraphEditor.java @@ -504,7 +504,9 @@ public void internalFrameClosed(InternalFrameEvent e1) { graph.add(new JMenuItem(new SelectDirectedAction(this.workbench))); graph.add(new JMenuItem(new SelectBidirectedAction(this.workbench))); - graph.add(new JMenuItem(new SelectUndirectedAction(this.workbench))); + graph.add(new JMenuItem(new SelectUndirectedAction(getWorkbench()))); + graph.add(new JMenuItem(new SelectTrianglesAction(getWorkbench()))); + graph.add(new JMenuItem(new SelectUndirectedAction(getWorkbench()))); graph.add(new JMenuItem(new SelectLatentsAction(this.workbench))); graph.add(new PagColorer(getWorkbench())); diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/search/GraphCard.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/search/GraphCard.java index 669985bd5e..60cf715d5a 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/search/GraphCard.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/search/GraphCard.java @@ -108,6 +108,7 @@ JMenuBar menuBar() { graph.add(new JMenuItem(new SelectDirectedAction(this.workbench))); graph.add(new JMenuItem(new SelectBidirectedAction(this.workbench))); graph.add(new JMenuItem(new SelectUndirectedAction(this.workbench))); + graph.add(new JMenuItem(new SelectTrianglesAction(this.workbench))); graph.add(new JMenuItem(new SelectLatentsAction(this.workbench))); graph.add(new PagColorer(this.workbench)); diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/simulation/ParameterTab.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/simulation/ParameterTab.java index 94b2e49194..a64f4b31b1 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/simulation/ParameterTab.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/simulation/ParameterTab.java @@ -55,8 +55,8 @@ public class ParameterTab extends JPanel { private static final String[] SOURCE_GRAPH_ITEMS = { SimulationTypes.BAYS_NET, SimulationTypes.STRUCTURAL_EQUATION_MODEL, - SimulationTypes.NON_LINEAR_STRUCTURAL_EQUATION_MODEL, SimulationTypes.LINEAR_FISHER_MODEL, + SimulationTypes.NON_LINEAR_STRUCTURAL_EQUATION_MODEL, SimulationTypes.LEE_AND_HASTIE, SimulationTypes.CONDITIONAL_GAUSSIAN, SimulationTypes.TIME_SERIES diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/Kci.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/Kci.java index 1e03b0b752..ab2646b278 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/Kci.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/independence/Kci.java @@ -9,13 +9,12 @@ import edu.cmu.tetrad.util.Parameters; import edu.cmu.tetrad.util.Params; +import java.io.Serial; import java.util.ArrayList; import java.util.List; /** * Wrapper for KCI test. - *

                - * Note that should work with Linear, Gaussian variables but is general. * * @author josephramsey */ @@ -27,9 +26,16 @@ @General public class Kci implements IndependenceWrapper { + @Serial private static final long serialVersionUID = 23L; - + /** + * Returns a KCI test. + * + * @param dataSet The data set to test independence against. + * @param parameters The paramters of the test. + * @return A KCI test. + */ @Override public IndependenceTest getTest(DataModel dataSet, Parameters parameters) { edu.cmu.tetrad.search.test.Kci kci = new edu.cmu.tetrad.search.test.Kci(SimpleDataLoader.getContinuousDataSet(dataSet), @@ -42,16 +48,32 @@ public IndependenceTest getTest(DataModel dataSet, Parameters parameters) { return kci; } + /** + * Returns the name of the test. + * + * @return The name of the test. + */ @Override public String getDescription() { return "KCI"; } + /** + * Returns the data type of the test, which is continuous. + * + * @return The data type of the test, which is continuous. + * @see DataType + */ @Override public DataType getDataType() { return DataType.Continuous; } + /** + * Returns the parameters of the test. + * + * @return The parameters of the test. + */ @Override public List getParameters() { List params = new ArrayList<>(); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/simulation/SimulationTypes.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/simulation/SimulationTypes.java index 7c84ecb1fb..87391af9a4 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/simulation/SimulationTypes.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/simulation/SimulationTypes.java @@ -25,12 +25,12 @@ */ public final class SimulationTypes { - public static final String BAYS_NET = "Bayes Net"; - public static final String STRUCTURAL_EQUATION_MODEL = "Structural Equation Model"; - public static final String NON_LINEAR_STRUCTURAL_EQUATION_MODEL = "Non-Linear Structural Equation Model"; + public static final String BAYS_NET = "Bayes Net (Multinomial)"; + public static final String STRUCTURAL_EQUATION_MODEL = "Linear Structural Equation Model"; public static final String LINEAR_FISHER_MODEL = "Linear Fisher Model"; - public static final String LEE_AND_HASTIE = "Lee & Hastie"; - public static final String CONDITIONAL_GAUSSIAN = "Conditional Gaussian"; + public static final String NON_LINEAR_STRUCTURAL_EQUATION_MODEL = "Non-Linear Structural Equation Model"; + public static final String LEE_AND_HASTIE = "Mixed Lee & Hastie"; + public static final String CONDITIONAL_GAUSSIAN = "Mixed Conditional Gaussian"; public static final String TIME_SERIES = "Time Series"; public static final String STANDARDIZED_STRUCTURAL_EQUATION_MODEL = "Standardized Structural Equation Model"; public static final String GENERAL_STRUCTURAL_EQUATION_MODEL = "General Structural Equation Model"; diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/GrowShrink.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/GrowShrink.java index ad6de83903..e6d3a5b685 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/GrowShrink.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/GrowShrink.java @@ -92,40 +92,57 @@ public GrowShrink(IndependenceTest test) { public Set findMb(Node target) { Set blanket = new HashSet<>(); - boolean changed = true; + List nodes = independenceTest.getVariables(); - while (changed) { - changed = false; - - List remaining = new LinkedList<>(this.variables); - remaining.removeAll(blanket); - remaining.remove(target); - - for (Node node : remaining) { - if (!this.independenceTest.checkIndependence(node, target, blanket).isIndependent()) { - blanket.add(node); - changed = true; - } + for (Node node : nodes) { + if (node == target) continue; + if (!independenceTest.checkIndependence(node, target, blanket).isIndependent()) { + blanket.add(node); } } - changed = true; - - while (changed) { - changed = false; - - for (Node node : new LinkedList<>(blanket)) { - blanket.remove(node); - - if (this.independenceTest.checkIndependence(node, target, blanket).isIndependent()) { - changed = true; - continue; - } - + for (Node node : new LinkedList<>(blanket)) { + HashSet z = new HashSet<>(blanket); + blanket.remove(node); + if (!independenceTest.checkIndependence(node, target, z).isIndependent()) { blanket.add(node); } } +// boolean changed = true; +// +// while (changed) { +// changed = false; +// +// List remaining = new LinkedList<>(this.variables); +// remaining.removeAll(blanket); +// remaining.remove(target); +// +// for (Node node : remaining) { +// if (!this.independenceTest.checkIndependence(node, target, blanket).isIndependent()) { +// blanket.add(node); +// changed = true; +// } +// } +// } +// +// changed = true; +// +// while (changed) { +// changed = false; +// +// for (Node node : new LinkedList<>(blanket)) { +// blanket.remove(node); +// +// if (this.independenceTest.checkIndependence(node, target, blanket).isIndependent()) { +// changed = true; +// continue; +// } +// +// blanket.add(node); +// } +// } + return blanket; } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestChiSquare.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestChiSquare.java index 854f6f1977..5811ee873b 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestChiSquare.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestChiSquare.java @@ -30,10 +30,8 @@ import edu.cmu.tetrad.util.TetradLogger; import java.text.NumberFormat; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Set; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; /** * Checks the conditional independence X _||_ Y | S, where S is a set of discrete variable, and X and Y are discrete @@ -78,6 +76,10 @@ public final class IndTestChiSquare implements IndependenceTest, RowsSettable { private boolean verbose; private List rows = null; + // A cache of results for independence facts. + private final Map facts = new ConcurrentHashMap<>(); + + /** * Constructs a new independence checker to check conditional independence facts for discrete data using a g square * test. @@ -175,6 +177,12 @@ public IndependenceResult checkIndependence(Node x, Node y, Set _z) { List z = new ArrayList<>(_z); Collections.sort(z); + if (this.facts.containsKey(new IndependenceFact(x, y, _z))) { + ChiSquareTest.Result result = this.facts.get(new IndependenceFact(x, y, _z)); + return new IndependenceResult(new IndependenceFact(x, y, _z), result.isIndep(), result.getPValue(), + getAlpha() - result.getPValue()); + } + // For testing x, y given z1,...,zn, set up an array of length // n + 2 containing the indices of these variables in order. int[] testIndices = new int[2 + z.size()]; @@ -195,6 +203,8 @@ public IndependenceResult checkIndependence(Node x, Node y, Set _z) { } ChiSquareTest.Result result = this.chiSquareTest.calcChiSquare(testIndices); + this.facts.put(new IndependenceFact(x, y, _z), result); + this.xSquare = result.getXSquare(); this.df = result.getDf(); double pValue = result.getPValue(); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestConditionalCorrelation.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestConditionalCorrelation.java index 0b5cb3c307..ace5ef2cd4 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestConditionalCorrelation.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestConditionalCorrelation.java @@ -32,7 +32,9 @@ import java.text.NumberFormat; import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; /** * Checks conditional independence of variable in a continuous data set using a conditional correlation test for the @@ -42,31 +44,22 @@ */ public final class IndTestConditionalCorrelation implements IndependenceTest { - /** - * Formats as 0.0000. - */ + // Formats as 0.0000. private static final NumberFormat nf = NumberFormatUtil.getInstance().getNumberFormat(); - /** - * The instance of CCI that is wrapped. - */ + // The instance of CCI that is wrapped. private final ConditionalCorrelationIndependence cci; - /** - * The variables of the covariance data, in order. (Unmodifiable list.) - */ + //The variables of the covariance data, in order. (Unmodifiable list.) private final List variables; - /** - * Stores a reference to the data set passed in through the constructor. - */ + // Stores a reference to the data set passed in through the constructor. private final DataSet dataSet; - /** - * The significance level of the independence tests. - */ + // The significance level of the independence tests. private double alpha; - /** - * True if verbose output should be printed. - */ + // True if verbose output should be printed. private boolean verbose; + // The score of the last test. private double score = Double.NaN; + // A cache of results for independence facts. + private final Map facts = new ConcurrentHashMap<>(); /** @@ -96,6 +89,8 @@ public IndTestConditionalCorrelation(DataSet dataSet, double alpha) { /** + * Constructs a new Independence test which checks independence facts based on the correlation data implied by the + * given data set (must be continuous). The given significance level is used. * @throws UnsupportedOperationException This method is not implemented. */ public IndependenceTest indTestSubset(List vars) { @@ -109,6 +104,9 @@ public IndependenceTest indTestSubset(List vars) { * @see IndependenceResult */ public IndependenceResult checkIndependence(Node x, Node y, Set z) { + if (this.facts.containsKey(new IndependenceFact(x, y, z))) { + return facts.get(new IndependenceFact(x, y, z)); + } double score = this.cci.isIndependent(x, y, z); this.score = score; @@ -128,7 +126,9 @@ public IndependenceResult checkIndependence(Node x, Node y, Set z) { } } - return new IndependenceResult(new IndependenceFact(x, y, z), independent, p, alpha - p); + IndependenceResult result = new IndependenceResult(new IndependenceFact(x, y, z), independent, p, score); + facts.put(new IndependenceFact(x, y, z), result); + return result; } /** diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestConditionalGaussianLrt.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestConditionalGaussianLrt.java index 363ba09130..2b7b9c1c49 100755 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestConditionalGaussianLrt.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestConditionalGaussianLrt.java @@ -35,6 +35,7 @@ import java.text.DecimalFormat; import java.text.NumberFormat; import java.util.*; +import java.util.concurrent.ConcurrentHashMap; /** * Performs a test of conditional independence X _||_ Y | Z1...Zn where all searchVariables are either continuous or @@ -45,13 +46,20 @@ * @author josephramsey */ public class IndTestConditionalGaussianLrt implements IndependenceTest { + // The data set. private final DataSet data; + // A hash of nodes to indices. private final Map nodesHash; // Likelihood function private final ConditionalGaussianLikelihood likelihood; + // The significance level of the independence tests. private double alpha; + // True if verbose output should be printed. private boolean verbose; + // The number of categories to discretize continuous variables into. private int numCategoriesToDiscretize = 3; + // A cache of results for independence facts. + private final Map facts = new ConcurrentHashMap<>(); /** * Constructor. @@ -89,11 +97,16 @@ public IndependenceTest indTestSubset(List vars) { * @see IndependenceResult */ public IndependenceResult checkIndependence(Node x, Node y, Set _z) { + if (this.facts.containsKey(new IndependenceFact(x, y, _z))) { + return facts.get(new IndependenceFact(x, y, _z)); + } + this.likelihood.setNumCategoriesToDiscretize(this.numCategoriesToDiscretize); List z = new ArrayList<>(_z); Collections.sort(z); + List allVars = new ArrayList<>(z); allVars.add(x); allVars.add(y); @@ -145,7 +158,10 @@ public IndependenceResult checkIndependence(Node x, Node y, Set _z) { } } - return new IndependenceResult(new IndependenceFact(x, y, _z), independent, pValue, getAlpha() - pValue); + IndependenceResult result = new IndependenceResult(new IndependenceFact(x, y, _z), independent, + pValue, getAlpha() - pValue); + facts.put(new IndependenceFact(x, y, _z), result); + return result; } /** diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestDegenerateGaussianLrt.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestDegenerateGaussianLrt.java index b8eace3243..953e10cbe6 100755 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestDegenerateGaussianLrt.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestDegenerateGaussianLrt.java @@ -54,9 +54,13 @@ public class IndTestDegenerateGaussianLrt implements IndependenceTest { // A constant. private static final double L2PE = log(2.0 * PI * E); + // The data set. private final BoxDataSet ddata; + // The data set. private final double[][] _ddata; + // A hash of nodes to indices. private final Map nodeHash; + // The data set. private final DataSet dataSet; // The mixed variables of the original dataset. private final List variables; @@ -66,8 +70,12 @@ public class IndTestDegenerateGaussianLrt implements IndependenceTest { private double alpha = 0.001; // The p value. private double pValue = NaN; + // True if verbose output should be printed. private boolean verbose; + // A cache of results for independence facts. + private final Map facts = new ConcurrentHashMap<>(); + /** * Constructs the score using a covariance matrix. * @@ -176,6 +184,9 @@ public IndependenceTest indTestSubset(List vars) { * @see IndependenceResult */ public IndependenceResult checkIndependence(Node x, Node y, Set _z) { + if (facts.containsKey(new IndependenceFact(x, y, _z))) { + return facts.get(new IndependenceFact(x, y, _z)); + } List allNodes = new ArrayList<>(); allNodes.add(x); @@ -238,8 +249,10 @@ public IndependenceResult checkIndependence(Node x, Node y, Set _z) { } } - return new IndependenceResult(new IndependenceFact(x, y, _z), + IndependenceResult result = new IndependenceResult(new IndependenceFact(x, y, _z), independent, pValue, alpha - pValue); + facts.put(new IndependenceFact(x, y, _z), result); + return result; } /** diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java index f10488a59c..223e258b39 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java @@ -49,21 +49,34 @@ * @author Frank Wimberly */ public final class IndTestFisherZ implements IndependenceTest, RowsSettable { + // A hash from variable names to indices. private final Map indexMap; + // A hash from variable names to variables. private final Map nameMap; + // The standard normal distribution. private final NormalDistribution normal = new NormalDistribution(0, 1); + // The variables of the covariance data, in order. (Unmodifiable list.) private final Map nodesHash; + // The correlation matrix. private ICovarianceMatrix cor = null; + // The variables of the covariance data, in order. (Unmodifiable list.) private List variables; + // The significance level of the independence tests. private double alpha; + // Stores a reference to the data set passed in through the constructor. private DataSet dataSet; - // Matrix from of the data. private Matrix data; + // True if verbose output should be printed. private boolean verbose = true; + // The correlation coefficient for the last test. private double r = Double.NaN; + // The rows used in the test. private List rows = null; + // Use pseudoinverse instead of correlation matrix. private boolean usePseudoinverse = false; + // A cache of results for independence facts. + private final Map facts = new ConcurrentHashMap<>(); /** @@ -95,8 +108,6 @@ public IndTestFisherZ(DataSet dataSet, double alpha) { this.nodesHash = nodesHash; } else { -// this.cor = new CorrelationMatrix(dataSet); - if (!(alpha >= 0 && alpha <= 1)) { throw new IllegalArgumentException("Alpha mut be in [0, 1]"); } @@ -165,7 +176,6 @@ public IndTestFisherZ(ICovarianceMatrix covMatrix, double alpha) { this.nodesHash = nodesHash; } - /** * Creates a new independence test instance for a subset of the variables. * @@ -204,8 +214,14 @@ public IndependenceTest indTestSubset(List vars) { * @see IndependenceResult */ public IndependenceResult checkIndependence(Node x, Node y, Set z) { + if (facts.containsKey(new IndependenceFact(x, y, z))) { + return facts.get(new IndependenceFact(x, y, z)); + } + if (usePseudoinverse) { - return checkIndependencePseudoinverse(x, y, z); + IndependenceResult result = checkIndependencePseudoinverse(x, y, z); + facts.put(new IndependenceFact(x, y, z), result); + return result; } double p; @@ -228,7 +244,9 @@ public IndependenceResult checkIndependence(Node x, Node y, Set z) { if (Double.isNaN(p)) { throw new RuntimeException("Undefined p-value encountered in for test: " + LogUtilsSearch.independenceFact(x, y, z)); } else { - return new IndependenceResult(new IndependenceFact(x, y, z), independent, p, alpha - p); + IndependenceResult result = new IndependenceResult(new IndependenceFact(x, y, z), independent, p, alpha - p); + facts.put(new IndependenceFact(x, y, z), result); + return result; } } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZConcatenateResiduals.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZConcatenateResiduals.java index b422a41d22..ed2db1f3a2 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZConcatenateResiduals.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZConcatenateResiduals.java @@ -37,7 +37,9 @@ import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; /** * Calculates independence from pooled residuals using the Fisher Z method. @@ -47,26 +49,17 @@ */ public final class IndTestFisherZConcatenateResiduals implements IndependenceTest { - - /** - * The variables of the covariance matrix, in order. (Unmodifiable list.) - */ + // The variables of the covariance matrix, in order. (Unmodifiable list.) private final List variables; - + // The regressions. private final ArrayList regressions; - + // The data sets. private List dataSets; - - /** - * The significance level of the independence tests. - */ + // The significance level of the independence tests. private double alpha; - /** - * The value of the Fisher's Z statistic associated with the last calculated partial correlation. - */ -// private double fisherZ; - - private double pValue = Double.NaN; + // A cache of results for independence facts. + private final Map facts = new ConcurrentHashMap<>(); + // True if verbose output should be printed. private boolean verbose; /** @@ -117,6 +110,9 @@ public IndependenceTest indTestSubset(List vars) { * @see IndependenceResult */ public IndependenceResult checkIndependence(Node x, Node y, Set _z) { + if (facts.containsKey(new IndependenceFact(x, y, _z))) { + return facts.get(new IndependenceFact(x, y, _z)); + } x = getVariable(this.variables, x.getName()); List z = GraphUtils.replaceNodes(new ArrayList<>(_z), new ArrayList<>(this.variables)); @@ -169,18 +165,18 @@ public IndependenceResult checkIndependence(Node x, Node y, Set _z) { throw new RuntimeException("Undefined p-value encountered for test: " + LogUtilsSearch.independenceFact(x, y, _z)); } - this.pValue = pValue; boolean independent = pValue > this.alpha; if (this.verbose) { if (independent) { TetradLogger.getInstance().forceLogMessage( - LogUtilsSearch.independenceFactMsg(x, y, _z, this.pValue)); + LogUtilsSearch.independenceFactMsg(x, y, _z, pValue)); } } - return new IndependenceResult(new IndependenceFact(x, y, _z), independent, pValue, pValue - getAlpha()); - + IndependenceResult result = new IndependenceResult(new IndependenceFact(x, y, _z), independent, pValue, pValue - getAlpha()); + facts.put(new IndependenceFact(x, y, _z), result); + return result; } /** diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZFisherPValue.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZFisherPValue.java index 59381346e2..42cb008277 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZFisherPValue.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZFisherPValue.java @@ -21,7 +21,10 @@ package edu.cmu.tetrad.search.test; -import edu.cmu.tetrad.data.*; +import edu.cmu.tetrad.data.CovarianceMatrix; +import edu.cmu.tetrad.data.DataSet; +import edu.cmu.tetrad.data.DataTransforms; +import edu.cmu.tetrad.data.ICovarianceMatrix; import edu.cmu.tetrad.graph.IndependenceFact; import edu.cmu.tetrad.graph.Node; import edu.cmu.tetrad.search.IndependenceTest; @@ -33,30 +36,38 @@ import org.apache.commons.math3.linear.SingularMatrixException; import java.util.*; +import java.util.concurrent.ConcurrentHashMap; import static org.apache.commons.math3.util.FastMath.*; /** - *

                Calculates independence from multiple datasets from using the Fisher method - * of pooling independence results. See this paper for details:

                - * - *

                Tillman, R. E., & Eberhardt, F. (2014). Learning causal structure from - * multiple datasets with similar variable sets. Behaviormetrika, 41(1), 41-64.

                + * Calculates independence from multiple datasets from using the Fisher method + * of pooling independence results. See this paper for details: + *

                + * Tillman, R. E., & Eberhardt, F. (2014). Learning causal structure from + * multiple datasets with similar variable sets. Behaviormetrika, 41(1), 41-64. * * @author robertillman * @author josephramsey */ public final class IndTestFisherZFisherPValue implements IndependenceTest { + // The variables of the covariance data, in order. (Unmodifiable list.) private final List variables; + // The number of samples in each dataset. private final int sampleSize; + // The datasets. private final List dataSets; + // The covariance matrices of the datasets. private final List ncov; - private final Map variablesMap; + // A hash of nodes to indices. + private final Map nodesMap; + // A cache of results for independence facts. + private final Map facts = new ConcurrentHashMap<>(); + // The significance level of the independence tests. private double alpha; - private double pValue = Double.NaN; + // True if verbose output should be printed. private boolean verbose; - /** * Constructor. * @@ -74,9 +85,9 @@ public IndTestFisherZFisherPValue(List dataSets, double alpha) { } this.variables = dataSets.get(0).getVariables(); - this.variablesMap = new HashMap<>(); + this.nodesMap = new HashMap<>(); for (int i = 0; i < this.variables.size(); i++) { - this.variablesMap.put(this.variables.get(i), i); + this.nodesMap.put(this.variables.get(i), i); } for (DataSet dataSet : dataSets) { @@ -103,15 +114,19 @@ public IndependenceTest indTestSubset(List vars) { * @throws RuntimeException if a matrix singularity is encountered. */ public IndependenceResult checkIndependence(Node x, Node y, Set _z) { + if (facts.containsKey(new IndependenceFact(x, y, _z))) { + return facts.get(new IndependenceFact(x, y, _z)); + } + try { List z = new ArrayList<>(); Collections.sort(z); int[] all = new int[z.size() + 2]; - all[0] = this.variablesMap.get(x); - all[1] = this.variablesMap.get(y); + all[0] = this.nodesMap.get(x); + all[1] = this.nodesMap.get(y); for (int i = 0; i < z.size(); i++) { - all[i + 2] = this.variablesMap.get(z.get(i)); + all[i + 2] = this.nodesMap.get(z.get(i)); } List pValues = new ArrayList<>(); @@ -152,19 +167,19 @@ public IndependenceResult checkIndependence(Node x, Node y, Set _z) { throw new RuntimeException("Undefined p-value encountered for test: " + LogUtilsSearch.independenceFact(x, y, _z)); } - this.pValue = p; - boolean independent = p > this.alpha; if (this.verbose) { if (independent) { TetradLogger.getInstance().forceLogMessage( - LogUtilsSearch.independenceFactMsg(x, y, _z, this.pValue)); + LogUtilsSearch.independenceFactMsg(x, y, _z, p)); } } - return new IndependenceResult(new IndependenceFact(x, y, _z), independent, p, getAlpha() - p); + IndependenceResult result = new IndependenceResult(new IndependenceFact(x, y, _z), independent, p, getAlpha() - p); + facts.put(new IndependenceFact(x, y, _z), result); + return result; } catch (SingularMatrixException e) { throw new RuntimeException("Singularity encountered when testing " + LogUtilsSearch.independenceFact(x, y, _z)); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestGSquare.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestGSquare.java index a6881d5d8a..21ac1aa0a8 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestGSquare.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestGSquare.java @@ -30,10 +30,8 @@ import edu.cmu.tetrad.util.TetradLogger; import java.text.NumberFormat; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Set; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; /** * Checks the conditional independence X _||_ Y | S, where S is a set of discrete variable, and X and Y are discrete @@ -46,38 +44,31 @@ */ public final class IndTestGSquare implements IndependenceTest, RowsSettable { - /** - * The standard number formatter for Tetrad. - */ + // The standard number formatter for Tetrad. private static final NumberFormat nf = NumberFormatUtil.getInstance().getNumberFormat(); - /** - * The G Square tester. - */ + // The G Square tester. private final ChiSquareTest gSquareTest; - /** - * The variables in the discrete data sets or which conditional independence judgements are desired. - */ + // The variables in the discrete data sets or which conditional independence judgements are desired. private final List variables; - /** - * The dataset of discrete variables. - */ + // The dataset of discrete variables. private final DataSet dataSet; - /** - * The significance level for the test. - */ + // The significance level for the test. private final double alpha; - /** - * The p value associated with the most recent call of isIndependent. - */ + // The p value associated with the most recent call of isIndependent. private double pValue; - /** - * The lower bound of percentages of observation of some category in the data, given some particular combination of - * values of conditioning variables, that coefs as 'determining.' - */ + // The lower bound of percentages of observation of some category in the data, given some particular combination of + // values of conditioning variables, that coefs as 'determining.' private double determinationP = 0.99; + // True if verbose output should be printed. private boolean verbose; + // The minimum expected number of counts per conditional table for chi-square for that table and its degrees of + // freedom to be included in the overall chi-square and degrees of freedom. Note that this should not be too small, + // or the chi-square distribution will not be a good approximation to the distribution of the test statistic. private double minCountPerCell = 1.0; + // The rows to use for the test. If null, all rows are used. private List rows = null; + // A cache of results for independence facts. + private final Map facts = new ConcurrentHashMap<>(); /** * Constructs a new independence checker to check conditional independence facts for discrete data using a g square @@ -150,16 +141,8 @@ public double getPValue() { * @return True iff x _||_ y | z. */ public IndependenceResult checkIndependence(Node x, Node y, Set _z) { - if (x == null) { - throw new NullPointerException(); - } - - if (y == null) { - throw new NullPointerException(); - } - - if (_z == null) { - throw new NullPointerException(); + if (this.facts.containsKey(new IndependenceFact(x, y, _z))) { + return facts.get(new IndependenceFact(x, y, _z)); } for (Node node : _z) { @@ -168,6 +151,7 @@ public IndependenceResult checkIndependence(Node x, Node y, Set _z) { } } + List z = new ArrayList<>(_z); Collections.sort(z); @@ -200,8 +184,10 @@ public IndependenceResult checkIndependence(Node x, Node y, Set _z) { } } - return new IndependenceResult(new IndependenceFact(x, y, _z), + IndependenceResult result1 = new IndependenceResult(new IndependenceFact(x, y, _z), result.isIndep(), result.getPValue(), alpha - result.getPValue()); + facts.put(new IndependenceFact(x, y, _z), result1); + return result1; } /** diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestHsic.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestHsic.java index 5f046e23c8..96db6560d4 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestHsic.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestHsic.java @@ -39,10 +39,8 @@ import org.apache.commons.math3.util.FastMath; import java.text.NumberFormat; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Set; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; /** *

                Checks the conditional independence X _||_ Y | S, where S is a set of continuous variable, @@ -97,6 +95,10 @@ public final class IndTestHsic implements IndependenceTest { * Use incomplete Choleksy decomposition to calculate Gram matrices */ private double useIncompleteCholesky = 1e-18; + + // A cache of results for independence facts. + private final Map facts = new ConcurrentHashMap<>(); + private boolean verbose; @@ -172,6 +174,10 @@ public IndependenceTest indTestSubset(List vars) { * @return True iff x _||_ y | z. */ public IndependenceResult checkIndependence(Node y, Node x, Set _z) { + if (facts.containsKey(new IndependenceFact(x, y, _z))) { + return facts.get(new IndependenceFact(x, y, _z)); + } + List z = new ArrayList<>(_z); Collections.sort(z); @@ -339,7 +345,9 @@ public IndependenceResult checkIndependence(Node y, Node x, Set _z) { } } - return new IndependenceResult(new IndependenceFact(x, y, _z), independent, this.pValue, alpha - pValue); + IndependenceResult result = new IndependenceResult(new IndependenceFact(x, y, _z), independent, this.pValue, alpha - pValue); + facts.put(new IndependenceFact(x, y, _z), result); + return result; } /** diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestMulti.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestMulti.java index 4eb3437c22..9e03158a39 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestMulti.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestMulti.java @@ -31,7 +31,9 @@ import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; /** * Pools together a set of independence tests using a specified method. @@ -40,26 +42,23 @@ */ public final class IndTestMulti implements IndependenceTest { - - /** - * The variables of the covariance matrix, in order. (Unmodifiable list.) - */ + // The variables of the covariance matrix, in order. (Unmodifiable list.) private final List variables; - - /** - * The independence test associated with each data set. - */ + // The independence test associated with each data set. private final List independenceTests; - - /** - * Pooling method - */ + // Pooling method private final ResolveSepsets.Method method; + // A cache of results for independence facts. + private final Map facts = new ConcurrentHashMap<>(); + // True if verbose output should be printed. private boolean verbose; -// private DataSet concatenatedData; - - + /** + * Constructs a new pooled independence test for the given data sets. + * @param independenceTests the independence tests to pool. + * @param method the method to use for pooling. + * @see ResolveSepsets.Method + */ public IndTestMulti(List independenceTests, ResolveSepsets.Method method) { Set nodeNames = new HashSet<>(); for (IndependenceTest independenceTest : independenceTests) { @@ -73,7 +72,9 @@ public IndTestMulti(List independenceTests, ResolveSepsets.Met this.method = method; } - + /** + * @throws UnsupportedOperationException Method not implemented. + */ public IndependenceTest indTestSubset(List vars) { throw new UnsupportedOperationException(); } @@ -88,6 +89,10 @@ public IndependenceTest indTestSubset(List vars) { * @throws RuntimeException if a matrix singularity is encountered. */ public IndependenceResult checkIndependence(Node x, Node y, Set z) { + if (facts.containsKey(new IndependenceFact(x, y, z))) { + return facts.get(new IndependenceFact(x, y, z)); + } + boolean independent = ResolveSepsets.isIndependentPooled(this.method, this.independenceTests, x, y, z); if (independent) { @@ -96,7 +101,10 @@ public IndependenceResult checkIndependence(Node x, Node y, Set z) { TetradLogger.getInstance().log("dependencies", "In aggregate dependent: " + LogUtilsSearch.independenceFact(x, y, z)); } - return new IndependenceResult(new IndependenceFact(x, y, z), independent, Double.NaN, Double.NaN); + IndependenceResult result = new IndependenceResult(new IndependenceFact(x, y, z), independent, + Double.NaN, Double.NaN); + facts.put(new IndependenceFact(x, y, z), result); + return result; } /** diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestMvpLrt.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestMvpLrt.java index ba1e962108..4d168856af 100755 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestMvpLrt.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestMvpLrt.java @@ -33,6 +33,7 @@ import org.apache.commons.math3.util.FastMath; import java.util.*; +import java.util.concurrent.ConcurrentHashMap; /** *

                Performs a test of conditional independence X _||_ Y | Z1...Zn where all @@ -45,12 +46,19 @@ * @author Bryan Andrews */ public class IndTestMvpLrt implements IndependenceTest { + + // The data set. private final DataSet data; + // A hash of nodes to indices. private final Map nodesHash; // Likelihood function private final MvpLikelihood likelihood; + // The significance level of the independence tests. private double alpha; + // True if verbose output should be printed. private boolean verbose; + // A cache of results for independence facts. + private final Map facts = new ConcurrentHashMap<>(); /** * Constructor. @@ -63,9 +71,7 @@ public class IndTestMvpLrt implements IndependenceTest { public IndTestMvpLrt(DataSet data, double alpha, int fDegree, boolean discretize) { this.data = data; this.likelihood = new MvpLikelihood(data, -1, fDegree, discretize); - this.nodesHash = new HashedMap<>(); - List variables = data.getVariables(); for (int i = 0; i < variables.size(); i++) { @@ -92,6 +98,10 @@ public IndependenceTest indTestSubset(List vars) { * @see IndependenceResult */ public IndependenceResult checkIndependence(Node x, Node y, Set _z) { + if (facts.containsKey(new IndependenceFact(x, y, _z))) { + return facts.get(new IndependenceFact(x, y, _z)); + } + List z = new ArrayList<>(_z); Collections.sort(z); @@ -132,12 +142,12 @@ public IndependenceResult checkIndependence(Node x, Node y, Set _z) { try { p_0 = 1.0 - new ChiSquaredDistribution(dof_0).cumulativeProbability(2.0 * lik_0); } catch (Exception e) { - e.printStackTrace(); + TetradLogger.getInstance().forceLogMessage(e.getMessage()); } try { p_1 = 1.0 - new ChiSquaredDistribution(dof_1).cumulativeProbability(2.0 * lik_1); } catch (Exception e) { - e.printStackTrace(); + TetradLogger.getInstance().forceLogMessage(e.getMessage()); } double pValue = FastMath.min(p_0, p_1); @@ -156,7 +166,10 @@ public IndependenceResult checkIndependence(Node x, Node y, Set _z) { } } - return new IndependenceResult(new IndependenceFact(x, y, _z), independent, pValue, alpha - pValue); + IndependenceResult result = new IndependenceResult(new IndependenceFact(x, y, _z), independent, pValue, + alpha - pValue); + facts.put(new IndependenceFact(x, y, _z), result); + return result; } /** diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestProbabilistic.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestProbabilistic.java index 64e7c64172..90baa78a35 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestProbabilistic.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestProbabilistic.java @@ -42,33 +42,27 @@ */ public class IndTestProbabilistic implements IndependenceTest { - /** - * The data set for which conditional independence judgments are requested. - */ + //The data set for which conditional independence judgments are requested. private final DataSet data; - /** - * The nodes of the data set. - */ + // The nodes of the data set. private final List nodes; - /** - * Indices of the nodes. - */ + // Indices of the nodes. private final Map indices; - /** - * A map from independence facts to their probabilities of independence. - */ + // A map from independence facts to their probabilities of independence. private final Map H; + // The BCInference object. private final BCInference bci; - /** - * Calculates probabilities of independence for conditional independence facts. - */ + // True if verbose output should be printed. private boolean threshold; + // The posterior probability of the last independence test. private double posterior; + // True if verbose output should be printed. private boolean verbose; + // The cutoff for the independence test. private double cutoff = 0.5; + // The prior equivalent sample size. private double priorEquivalentSampleSize = 10; - /** * Initializes the test using a discrete data sets. */ @@ -106,35 +100,27 @@ public IndTestProbabilistic(DataSet dataSet) { this.bci = setup(_data); } - private BCInference setup(DataSet dataSet) { - int[] nodeDimensions = new int[dataSet.getNumColumns() + 2]; - - for (int j = 0; j < dataSet.getNumColumns(); j++) { - DiscreteVariable variable = (DiscreteVariable) (dataSet.getVariable(j)); - int numCategories = variable.getNumCategories(); - nodeDimensions[j + 1] = numCategories; - } - - int[][] cases = new int[dataSet.getNumRows() + 1][dataSet.getNumColumns() + 2]; - - for (int i = 0; i < dataSet.getNumRows(); i++) { - for (int j = 0; j < dataSet.getNumColumns(); j++) { - cases[i + 1][j + 1] = dataSet.getInt(i, j) + 1; - } - } - - BCInference bci = new BCInference(cases, nodeDimensions); - bci.setPriorEqivalentSampleSize(this.priorEquivalentSampleSize); - return bci; - } - + /** + * @throws UnsupportedOperationException Method not implemented. + */ @Override public IndependenceTest indTestSubset(List vars) { throw new UnsupportedOperationException(); } + /** + * Returns an independence result that states whether x _||_y | z and what the p-value of the test is. + * @param x The first variable. + * @param y The second variable. + * @param _z The conditioning set. + * @return an independence result (see) + * @see IndependenceResult + */ @Override public IndependenceResult checkIndependence(Node x, Node y, Set _z) { + + // Notice that we do not cache the results of the independence tests here. This is because + // these results have a random component and so caching them would be inappropriate. List z = new ArrayList<>(_z); Collections.sort(z); @@ -300,6 +286,28 @@ public void setPriorEquivalentSampleSize(double priorEquivalentSampleSize) { this.priorEquivalentSampleSize = priorEquivalentSampleSize; } + private BCInference setup(DataSet dataSet) { + int[] nodeDimensions = new int[dataSet.getNumColumns() + 2]; + + for (int j = 0; j < dataSet.getNumColumns(); j++) { + DiscreteVariable variable = (DiscreteVariable) (dataSet.getVariable(j)); + int numCategories = variable.getNumCategories(); + nodeDimensions[j + 1] = numCategories; + } + + int[][] cases = new int[dataSet.getNumRows() + 1][dataSet.getNumColumns() + 2]; + + for (int i = 0; i < dataSet.getNumRows(); i++) { + for (int j = 0; j < dataSet.getNumColumns(); j++) { + cases[i + 1][j + 1] = dataSet.getInt(i, j) + 1; + } + } + + BCInference bci = new BCInference(cases, nodeDimensions); + bci.setPriorEqivalentSampleSize(this.priorEquivalentSampleSize); + return bci; + } + private List getRows(DataSet dataSet, List allVars, Map nodesHash) { List rows = new ArrayList<>(); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestRegression.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestRegression.java index ce6887a15c..08749fe574 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestRegression.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestRegression.java @@ -39,10 +39,8 @@ import edu.cmu.tetrad.util.TetradLogger; import java.text.NumberFormat; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Set; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; /** * Checks independence of X _||_ Y | Z for variables X and Y and list Z of variables by regressing X on {Y} U Z and @@ -53,29 +51,21 @@ */ public final class IndTestRegression implements IndependenceTest { - /** - * The standard number formatter for Tetrad. - */ + // The standard number formatter for Tetrad. private static final NumberFormat nf = NumberFormatUtil.getInstance().getNumberFormat(); - /** - * The correlation matrix. - */ + // The correlation matrix. private final DoubleMatrix2D data; - /** - * The variables of the correlation matrix, in order. (Unmodifiable list.) - */ + // The variables of the correlation matrix, in order. (Unmodifiable list.) private final List variables; + // The data set. private final DataSet dataSet; - /** - * The significance level of the independence tests. - */ + // The significance level of the independence tests. private double alpha; - /** - * The value of the Fisher's Z statistic associated with the las calculated partial correlation. - */ - private double fishersZ; + // The value of the Fisher's Z statistic associated with the las calculated partial correlation. private boolean verbose; + // A cache of results for independence facts. + private final Map facts = new ConcurrentHashMap<>(); /** * Constructs a new Independence test which checks independence facts based on the correlation matrix implied by the @@ -109,12 +99,12 @@ public IndependenceTest indTestSubset(List vars) { * @param xVar the one variable being compared. * @param yVar the second variable being compared. * @param zList the list of conditioning variables. - * @return true iff x _||_ y | z. + * @return The independence result. * @throws RuntimeException if a matrix singularity is encountered. */ public IndependenceResult checkIndependence(Node xVar, Node yVar, Set zList) { - if (zList == null) { - throw new NullPointerException(); + if (facts.containsKey(new IndependenceFact(xVar, yVar, zList))) { + return facts.get(new IndependenceFact(xVar, yVar, zList)); } for (Node node : zList) { @@ -164,8 +154,10 @@ public IndependenceResult checkIndependence(Node xVar, Node yVar, Set zLis } } - return new IndependenceResult(new IndependenceFact(xVar, yVar, zList), + IndependenceResult result1 = new IndependenceResult(new IndependenceFact(xVar, yVar, zList), independent, p, getAlpha() - p); + facts.put(new IndependenceFact(xVar, yVar, zList), result1); + return result1; } /** @@ -268,14 +260,24 @@ public boolean determines(List zList, Node xVar) { return determined; } + /** + * Returns the data used. + * @return the data used. + */ public DataSet getData() { return this.dataSet; } + /** + * Returns true if the test prints verbose output. + */ public boolean isVerbose() { return this.verbose; } + /** + * Sets whether the test prints verbose output. + */ public void setVerbose(boolean verbose) { this.verbose = verbose; } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestTrekSep.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestTrekSep.java index 285ece87c0..a09850d514 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestTrekSep.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestTrekSep.java @@ -41,16 +41,26 @@ * @author Adam Brodie */ public final class IndTestTrekSep implements IndependenceTest { + // The variables of the covariance matrix, in order. (Unmodifiable list.) private static final NumberFormat nf = NumberFormatUtil.getInstance().getNumberFormat(); + // The covariance matrix. private final ICovarianceMatrix covMatrix; + // The latents in order. (Unmodifiable list.) private final List latents; + // The variables clusterings. private final List> clustering; + // A hash of nodes to indices. private final Map indexMap; + // A hash of nodes to names. private final Map nameMap; + // True if verbose output should be printed. private boolean verbose; + // The variables of the covariance matrix, in order. (Unmodifiable list.) private List variables; + // The significance level of the independence tests. private double alpha; - + // A cache of results for independence facts. + private final Map facts = new ConcurrentHashMap<>(); /** * Constructs a new independence test that will determine conditional independence facts using the given correlation @@ -112,29 +122,38 @@ public IndependenceTest indTestSubset(List vars) { * @throws org.apache.commons.math3.linear.SingularMatrixException if a matrix singularity is encountered. */ public IndependenceResult checkIndependence(Node x, Node y, Set z) { + if (facts.containsKey(new IndependenceFact(x, y, z))) { + return facts.get(new IndependenceFact(x, y, z)); + } + int n = sampleSize(); int xi = this.latents.indexOf(x); int yi = this.latents.indexOf(y); int nA = this.clustering.get(xi).size(); int nB = this.clustering.get(yi).size(); + for (Node node : z) { int s = this.latents.indexOf(node); int m = this.clustering.get(s).size() / 2; nA += m; nB += m; } + int[] A = new int[nA]; int[] B = new int[nB]; int a = 0; int b = 0; + for (int i = 0; i < this.clustering.get(xi).size(); i++) { A[i] = this.variables.indexOf(this.clustering.get(xi).get(i)); a++; } + for (int i = 0; i < this.clustering.get(yi).size(); i++) { B[i] = this.variables.indexOf(this.clustering.get(yi).get(i)); b++; } + for (Node node : z) { int s = this.latents.indexOf(node); int m = this.clustering.get(s).size() / 2; @@ -146,16 +165,13 @@ public IndependenceResult checkIndependence(Node x, Node y, Set z) { } } - //With one indicator per latent per set. - double[][] CovMatrix = this.covMatrix.getMatrix().toArray(); - - int rank = new EstimateRank().Estimate(A, B, CovMatrix, n, this.alpha); -// return rank <= z.size(); - + int rank = EstimateRank.estimate(A, B, CovMatrix, n, this.alpha); boolean independent = rank <= z.size(); - return new IndependenceResult(new IndependenceFact(x, y, z), independent, Double.NaN, Double.NaN); + final IndependenceResult result = new IndependenceResult(new IndependenceFact(x, y, z), independent, Double.NaN, Double.NaN); + facts.put(new IndependenceFact(x, y, z), result); + return result; } @@ -214,7 +230,7 @@ public Node getVariable(String name) { } /** - * If isDeterminismAllowed(), defers to IndTestFisherZD; otherwise throws + * If isDeterminismAllowed(), defers to IndTestFisherZD; otherwise throws * UnsupportedOperationException. * * @return True if so diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/Kci.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/Kci.java index 47a333f4ee..a5fd5cb6ea 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/Kci.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/Kci.java @@ -1,6 +1,9 @@ package edu.cmu.tetrad.search.test; -import edu.cmu.tetrad.data.*; +import edu.cmu.tetrad.data.DataModel; +import edu.cmu.tetrad.data.DataSet; +import edu.cmu.tetrad.data.DataTransforms; +import edu.cmu.tetrad.data.ICovarianceMatrix; import edu.cmu.tetrad.graph.IndependenceFact; import edu.cmu.tetrad.graph.Node; import edu.cmu.tetrad.search.IndependenceTest; @@ -45,7 +48,6 @@ public class Kci implements IndependenceTest { // The supplied data set, standardized private final DataSet data; - // Variables in data private final List variables; private final double[] h; @@ -68,9 +70,8 @@ public class Kci implements IndependenceTest { private double widthMultiplier = 1.0; // Epsilon for Propositio 5. private double epsilon = 0.001; - + // True if verbose output should be printed. private boolean verbose; -// private IndependenceFact latestFact = null; /** * Constructor. @@ -80,7 +81,6 @@ public class Kci implements IndependenceTest { */ public Kci(DataSet data, double alpha) { this.data = DataTransforms.standardizeData(data); -// _data = data.getDoubleData().transpose().toArray(); this.variables = data.getVariables(); int n = this.data.getNumRows(); @@ -121,6 +121,10 @@ public IndependenceTest indTestSubset(List vars) { * @see IndependenceResult */ public IndependenceResult checkIndependence(Node x, Node y, Set z) { + if (facts.containsKey(new IndependenceFact(x, y, z))) { + return facts.get(new IndependenceFact(x, y, z)); + } + try { if (Thread.currentThread().isInterrupted()) { @@ -134,7 +138,6 @@ public IndependenceResult checkIndependence(Node x, Node y, Set z) { allVars.addAll(z); IndependenceFact fact = new IndependenceFact(x, y, z); -// this.latestFact = fact; if (facts.containsKey(fact)) { IndependenceResult result = facts.get(fact); @@ -199,7 +202,10 @@ public IndependenceResult checkIndependence(Node x, Node y, Set z) { IndependenceResult result = facts.get(fact); if (this.facts.get(fact) != null) { - return new IndependenceResult(fact, result.isIndependent(), result.getPValue(), getAlpha() - result.getPValue()); + IndependenceResult result1 = new IndependenceResult(fact, result.isIndependent(), + result.getPValue(), getAlpha() - result.getPValue()); + facts.put(fact, result1); + return result1; } else { if (z.isEmpty()) { result = isIndependentUnconditional(x, y, fact, _data, h, N, hash); @@ -219,7 +225,10 @@ public IndependenceResult checkIndependence(Node x, Node y, Set z) { } } - return new IndependenceResult(fact, result.isIndependent(), result.getPValue(), getAlpha() - result.getPValue()); + IndependenceResult result1 = new IndependenceResult(fact, result.isIndependent(), + result.getPValue(), getAlpha() - result.getPValue()); + facts.put(fact, result1); + return result1; } } catch (SingularMatrixException e) { throw new RuntimeException("Singularity encountered when testing " + diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/MsepTest.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/MsepTest.java index 0890aafd3a..b94231c936 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/MsepTest.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/MsepTest.java @@ -32,31 +32,31 @@ import edu.cmu.tetrad.util.TetradLogger; import java.util.*; +import java.util.concurrent.ConcurrentHashMap; /** - *

                Checks independence facts for variables associated with the nodes in a given graph by + * Checks independence facts for variables associated with the nodes in a given graph by * checking m-separation facts on the underlying nodes. We use the IndependenceTest interface here so that this * m-separation test can be used in place of a statistical conditional independence test in algorithms to provide oracle - * information.

                + * information. * * @author josephramsey */ public class MsepTest implements IndependenceTest { + // A cache of results for independence facts. + private final Map facts = new ConcurrentHashMap<>(); private Map> ancestorMap; private IndependenceFacts independenceFacts; - - /** - * The graph for which this is a variable map. - */ + // The graph for which this is a variable map. private Graph graph; - - /** - * The list of observed variables (i.e. variables for observed nodes). - */ + //The list of observed variables (i.e. variables for observed nodes). private List observedVars; + // The list of translated observed variables (i.e. variables for observed nodes). private List _observedVars; + // Whether verbose output should be printed. private boolean verbose = false; + // The "p-value" of the last test (this is 0 or 1). private double pvalue = 0; /** @@ -73,7 +73,7 @@ public MsepTest(Graph graph) { * Constructor. * * @param facts Independence facts to be used for direct calculations of m-separation. - * @param variables The variables for the facts, if different from those that independenceFacts would return. + * @param variables The variables for the facts, if different from those that independence facts would return. * @see IndependenceFacts */ public MsepTest(IndependenceFacts facts, List variables) { @@ -205,6 +205,10 @@ public IndependenceResult checkIndependence(Node x, Node y, Set z) { } } + if (facts.containsKey(new IndependenceFact(x, y, z))) { + return facts.get(new IndependenceFact(x, y, z)); + } + boolean mSeparated; if (graph != null) { @@ -235,7 +239,9 @@ public IndependenceResult checkIndependence(Node x, Node y, Set z) { this.pvalue = pValue; - return new IndependenceResult(new IndependenceFact(x, y, z), mSeparated, pValue, pvalue == 1 ? -1 : 1); + IndependenceResult result = new IndependenceResult(new IndependenceFact(x, y, z), mSeparated, pValue, pvalue == 1 ? -1 : 1); + facts.put(new IndependenceFact(x, y, z), result); + return result; } /** diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/EstimateRank.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/EstimateRank.java index 0f68865558..655ebb2a07 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/EstimateRank.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/EstimateRank.java @@ -65,7 +65,7 @@ public static double[] CanCor(int[] iA, int[] iB, double[][] cov) { /** * Estimate rank from data. */ - public static int Estimate(double[][] A, double[][] B, double alpha) { + public static int estimate(double[][] A, double[][] B, double alpha) { double[] Cors = CanCor(A, B); int rank = 0; boolean reject = true; @@ -90,7 +90,7 @@ public static int Estimate(double[][] A, double[][] B, double alpha) { /** * Estimate rank from covariance matrix. */ - public static int Estimate(int[] iA, int[] iB, double[][] cov, int N, double alpha) { + public static int estimate(int[] iA, int[] iB, double[][] cov, int N, double alpha) { double[] Cors = CanCor(iA, iB, cov); int rank = 0; boolean reject = true; From 4d27c375b94c854a981078cfad3b30a0f5e75480 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Tue, 23 Jan 2024 13:46:07 -0500 Subject: [PATCH 095/163] Cleanup. --- .../cmu/tetrad/search/IndependenceTest.java | 6 +- .../cmu/tetrad/search/score/BdeuScore.java | 15 +++-- .../ConditionalCorrelationIndependence.java | 3 +- .../tetrad/search/test/IndTestChiSquare.java | 11 ++-- .../test/IndTestConditionalCorrelation.java | 5 +- .../test/IndTestConditionalGaussianLrt.java | 4 +- .../test/IndTestDegenerateGaussianLrt.java | 14 ++--- .../tetrad/search/test/IndTestFisherZ.java | 4 +- .../IndTestFisherZConcatenateResiduals.java | 4 +- .../test/IndTestFisherZFisherPValue.java | 8 +-- .../tetrad/search/test/IndTestGSquare.java | 6 +- .../cmu/tetrad/search/test/IndTestHsic.java | 57 ++++++------------- .../cmu/tetrad/search/test/IndTestMulti.java | 3 +- .../cmu/tetrad/search/test/IndTestMvpLrt.java | 15 +++-- .../search/test/IndTestProbabilistic.java | 5 +- .../tetrad/search/test/IndTestTrekSep.java | 7 +-- .../java/edu/cmu/tetrad/search/test/Kci.java | 24 ++++---- .../edu/cmu/tetrad/search/test/MsepTest.java | 7 +-- .../cmu/tetrad/search/test/RowsSettable.java | 5 +- .../cmu/tetrad/search/test/ScoreIndTest.java | 9 +-- .../cmu/tetrad/search/utils/FciOrient.java | 45 +++++++-------- .../tetrad/search/utils/SepsetProducer.java | 3 +- .../tetrad/search/utils/SepsetsGreedy.java | 4 +- 23 files changed, 114 insertions(+), 150 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/IndependenceTest.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/IndependenceTest.java index 35db551a9a..dc51027613 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/IndependenceTest.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/IndependenceTest.java @@ -34,9 +34,9 @@ import java.util.Set; /** - *

                Gives an interface that can be implemented by classes that do conditional - * independence testing. These classes are capable of serving as conditional independence "oracles" for constraint-based - * searches. Many methods are given defaults so that such a test will be easy to implement in Python using JPype.

                + * Gives an interface that can be implemented by classes that do conditional independence testing. These classes are + * capable of serving as conditional independence "oracles" for constraint-based searches. Many methods are given + * defaults so that such a test will be easy to implement in Python using JPype. * * @author josephramsey */ diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/BdeuScore.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/BdeuScore.java index 6fbc77f679..df665edb84 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/BdeuScore.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/BdeuScore.java @@ -32,14 +32,13 @@ import java.util.List; /** - *

                Calculates the BDeu score, which the BDe (Bayes Dirichlet Equivalent) score - * with uniform priors. A good discussion of BD* scores can be found here:

                - * - *

                Heckerman, D., Geiger, D. & Chickering, D.M. Learning Bayesian networks: - * The combination of knowledge and statistical data. Mach Learn 20, 197–243 (1995).

                - * - *

                As for all scores in Tetrad, higher scores mean more dependence, and negative - * scores indicate independence.

                + * Calculates the BDeu score, which the BDe (Bayes Dirichlet Equivalent) score with uniform priors. A good discussion of + * BD* scores can be found here: + *

                + * Heckerman, D., Geiger, D. & Chickering, D.M. Learning Bayesian networks: The combination of knowledge and + * statistical data. Mach Learn 20, 197–243 (1995). + *

                + * As for all scores in Tetrad, higher scores mean more dependence, and negative scores indicate independence. * * @author josephramsey * @see BdeScore diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ConditionalCorrelationIndependence.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ConditionalCorrelationIndependence.java index ef6325de03..7ccdda0c1e 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ConditionalCorrelationIndependence.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ConditionalCorrelationIndependence.java @@ -44,8 +44,7 @@ *

                * This all follows the original Daudin paper, which is this: *

                - * Daudin, J. J. (1980). Partial association measures and ann application to qualitative regression. - * Biometrika, 67(3), + * Daudin, J. J. (1980). Partial association measures and ann application to qualitative regression. Biometrika, 67(3), * 581-590. *

                * We use Nadaraya-Watson kernel regression, though we further restrict the sample size to nearby points. diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestChiSquare.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestChiSquare.java index 5811ee873b..1614e69423 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestChiSquare.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestChiSquare.java @@ -58,27 +58,22 @@ public final class IndTestChiSquare implements IndependenceTest, RowsSettable { * The dataset of discrete variables. */ private final DataSet dataSet; - + // A cache of results for independence facts. + private final Map facts = new ConcurrentHashMap<>(); /** * The G Square value associated with a particular call of isIndependent. Set in that method and not in the * constructor. */ private double xSquare; - /** * The degrees of freedom associated with a particular call of isIndependent. Set in the method and not in the * constructor. */ private int df; - private double minCountPerCell = 1.0; - private boolean verbose; private List rows = null; - // A cache of results for independence facts. - private final Map facts = new ConcurrentHashMap<>(); - /** * Constructs a new independence checker to check conditional independence facts for discrete data using a g square @@ -371,6 +366,7 @@ public void setMinCountPerCell(double minCountPerCell) { /** * Returns the rows used for the test. If null, all rows are used. + * * @return The rows used for the test. Can be null. */ @Override @@ -380,6 +376,7 @@ public List getRows() { /** * Sets the rows to use for the test. If null, all rows are used. + * * @param rows The rows to use for the test. Can be null. */ @Override diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestConditionalCorrelation.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestConditionalCorrelation.java index ace5ef2cd4..1af1e06add 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestConditionalCorrelation.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestConditionalCorrelation.java @@ -52,14 +52,14 @@ public final class IndTestConditionalCorrelation implements IndependenceTest { private final List variables; // Stores a reference to the data set passed in through the constructor. private final DataSet dataSet; + // A cache of results for independence facts. + private final Map facts = new ConcurrentHashMap<>(); // The significance level of the independence tests. private double alpha; // True if verbose output should be printed. private boolean verbose; // The score of the last test. private double score = Double.NaN; - // A cache of results for independence facts. - private final Map facts = new ConcurrentHashMap<>(); /** @@ -91,6 +91,7 @@ public IndTestConditionalCorrelation(DataSet dataSet, double alpha) { /** * Constructs a new Independence test which checks independence facts based on the correlation data implied by the * given data set (must be continuous). The given significance level is used. + * * @throws UnsupportedOperationException This method is not implemented. */ public IndependenceTest indTestSubset(List vars) { diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestConditionalGaussianLrt.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestConditionalGaussianLrt.java index 2b7b9c1c49..da891d5cf1 100755 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestConditionalGaussianLrt.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestConditionalGaussianLrt.java @@ -52,14 +52,14 @@ public class IndTestConditionalGaussianLrt implements IndependenceTest { private final Map nodesHash; // Likelihood function private final ConditionalGaussianLikelihood likelihood; + // A cache of results for independence facts. + private final Map facts = new ConcurrentHashMap<>(); // The significance level of the independence tests. private double alpha; // True if verbose output should be printed. private boolean verbose; // The number of categories to discretize continuous variables into. private int numCategoriesToDiscretize = 3; - // A cache of results for independence facts. - private final Map facts = new ConcurrentHashMap<>(); /** * Constructor. diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestDegenerateGaussianLrt.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestDegenerateGaussianLrt.java index 953e10cbe6..1a96ccd7fa 100755 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestDegenerateGaussianLrt.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestDegenerateGaussianLrt.java @@ -42,11 +42,10 @@ import static org.apache.commons.math3.util.FastMath.*; /** - *

                Implements a degenerate Gaussian score as a LRT. The reference is here:

                - * - *

                Andrews, B., Ramsey, J., & Cooper, G. F. (2019, July). Learning high-dimensional - * directed acyclic graphs with mixed data-types. In The 2019 ACM SIGKDD Workshop on Causal Discovery (pp. 4-21). - * PMLR.

                + * Implements a degenerate Gaussian score as a LRT. The reference is here: + *

                + * Andrews, B., Ramsey, J., & Cooper, G. F. (2019, July). Learning high-dimensional directed acyclic graphs with + * mixed data-types. In The 2019 ACM SIGKDD Workshop on Causal Discovery (pp. 4-21). PMLR. * * @author Bryan Andrews */ @@ -66,6 +65,8 @@ public class IndTestDegenerateGaussianLrt implements IndependenceTest { private final List variables; // The embedding map. private final Map> embedding; + // A cache of results for independence facts. + private final Map facts = new ConcurrentHashMap<>(); // The alpha level. private double alpha = 0.001; // The p value. @@ -73,9 +74,6 @@ public class IndTestDegenerateGaussianLrt implements IndependenceTest { // True if verbose output should be printed. private boolean verbose; - // A cache of results for independence facts. - private final Map facts = new ConcurrentHashMap<>(); - /** * Constructs the score using a covariance matrix. * diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java index 223e258b39..821fdef12e 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java @@ -57,6 +57,8 @@ public final class IndTestFisherZ implements IndependenceTest, RowsSettable { private final NormalDistribution normal = new NormalDistribution(0, 1); // The variables of the covariance data, in order. (Unmodifiable list.) private final Map nodesHash; + // A cache of results for independence facts. + private final Map facts = new ConcurrentHashMap<>(); // The correlation matrix. private ICovarianceMatrix cor = null; // The variables of the covariance data, in order. (Unmodifiable list.) @@ -75,8 +77,6 @@ public final class IndTestFisherZ implements IndependenceTest, RowsSettable { private List rows = null; // Use pseudoinverse instead of correlation matrix. private boolean usePseudoinverse = false; - // A cache of results for independence facts. - private final Map facts = new ConcurrentHashMap<>(); /** diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZConcatenateResiduals.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZConcatenateResiduals.java index ed2db1f3a2..682a73210a 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZConcatenateResiduals.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZConcatenateResiduals.java @@ -53,12 +53,12 @@ public final class IndTestFisherZConcatenateResiduals implements IndependenceTes private final List variables; // The regressions. private final ArrayList regressions; + // A cache of results for independence facts. + private final Map facts = new ConcurrentHashMap<>(); // The data sets. private List dataSets; // The significance level of the independence tests. private double alpha; - // A cache of results for independence facts. - private final Map facts = new ConcurrentHashMap<>(); // True if verbose output should be printed. private boolean verbose; diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZFisherPValue.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZFisherPValue.java index 42cb008277..e6a5830bc4 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZFisherPValue.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZFisherPValue.java @@ -41,11 +41,11 @@ import static org.apache.commons.math3.util.FastMath.*; /** - * Calculates independence from multiple datasets from using the Fisher method - * of pooling independence results. See this paper for details: + * Calculates independence from multiple datasets from using the Fisher method of pooling independence results. See this + * paper for details: *

                - * Tillman, R. E., & Eberhardt, F. (2014). Learning causal structure from - * multiple datasets with similar variable sets. Behaviormetrika, 41(1), 41-64. + * Tillman, R. E., & Eberhardt, F. (2014). Learning causal structure from multiple datasets with similar variable + * sets. Behaviormetrika, 41(1), 41-64. * * @author robertillman * @author josephramsey diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestGSquare.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestGSquare.java index 21ac1aa0a8..16e30aaf39 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestGSquare.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestGSquare.java @@ -54,6 +54,8 @@ public final class IndTestGSquare implements IndependenceTest, RowsSettable { private final DataSet dataSet; // The significance level for the test. private final double alpha; + // A cache of results for independence facts. + private final Map facts = new ConcurrentHashMap<>(); // The p value associated with the most recent call of isIndependent. private double pValue; // The lower bound of percentages of observation of some category in the data, given some particular combination of @@ -67,8 +69,6 @@ public final class IndTestGSquare implements IndependenceTest, RowsSettable { private double minCountPerCell = 1.0; // The rows to use for the test. If null, all rows are used. private List rows = null; - // A cache of results for independence facts. - private final Map facts = new ConcurrentHashMap<>(); /** * Constructs a new independence checker to check conditional independence facts for discrete data using a g square @@ -344,6 +344,7 @@ public void setMinCountPerCell(double minCountPerCell) { /** * Returns the rows used for the test. If null, all rows are used. + * * @return The rows used for the test. Can be null. */ @Override @@ -353,6 +354,7 @@ public List getRows() { /** * Sets the rows to use for the test. If null, all rows are used. + * * @param rows The rows to use for the test. Can be null. */ @Override diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestHsic.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestHsic.java index 96db6560d4..39b7c3fb6f 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestHsic.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestHsic.java @@ -43,12 +43,11 @@ import java.util.concurrent.ConcurrentHashMap; /** - *

                Checks the conditional independence X _||_ Y | S, where S is a set of continuous variable, - * and X and Y are discrete variable not in S, using the Hilbert-Schmidth Independence Criterion (HSIC), a kernel based - * nonparametric test for conditional independence.

                - * - *

                The Kpc algorithm by Tillman had run PC using this test; to run Kpc, simply select this test - * for PC.

                + * Checks the conditional independence X _||_ Y | S, where S is a set of continuous variable, and X and Y are discrete + * variable not in S, using the Hilbert-Schmidth Independence Criterion (HSIC), a kernel based nonparametric test for + * conditional independence. + *

                + * The Kpc algorithm by Tillman had run PC using this test; to run Kpc, simply select this test for PC. * * @author Robert Tillman * @see edu.cmu.tetrad.search.work_in_progress.Kpc @@ -56,49 +55,27 @@ public final class IndTestHsic implements IndependenceTest { - /** - * Formats as 0.0000. - */ + // Number format for printing p-values. private static final NumberFormat nf = NumberFormatUtil.getInstance().getNumberFormat(); - /** - * The variables of the covariance matrix, in order. (Unmodifiable list.) - */ + // The variables of the covariance matrix, in order. (Unmodifiable list.) private final List variables; - /** - * Stores a reference to the dataset being analyzed. - */ + // Stores a reference to the dataset being analyzed. private final DataSet dataSet; - /** - * The significance level of the independence tests. - */ + // A cache of results for independence facts. + private final Map facts = new ConcurrentHashMap<>(); + // The significance level of the independence tests. private double alpha; - /** - * The cutoff value for 'alpha' - */ + // The cutoff value for 'alpha' private double thresh = Double.NaN; - /** - * A stored p value, if the deterministic test was used. - */ + // A stored p value, if the deterministic test was used. private double pValue = Double.NaN; - - /** - * The regularizer - */ + // The regularizer private double regularizer = 0.0001; - - /** - * Number of permutations to approximate the null distribution - */ + // Number of permutations to approximate the null distribution private int perms = 100; - - /** - * Use incomplete Choleksy decomposition to calculate Gram matrices - */ + // Use incomplete Choleksy decomposition to calculate Gram matrices private double useIncompleteCholesky = 1e-18; - - // A cache of results for independence facts. - private final Map facts = new ConcurrentHashMap<>(); - + // Whether to print verbose output. private boolean verbose; diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestMulti.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestMulti.java index 9e03158a39..bc52d099e8 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestMulti.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestMulti.java @@ -55,8 +55,9 @@ public final class IndTestMulti implements IndependenceTest { /** * Constructs a new pooled independence test for the given data sets. + * * @param independenceTests the independence tests to pool. - * @param method the method to use for pooling. + * @param method the method to use for pooling. * @see ResolveSepsets.Method */ public IndTestMulti(List independenceTests, ResolveSepsets.Method method) { diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestMvpLrt.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestMvpLrt.java index 4d168856af..7a46de25eb 100755 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestMvpLrt.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestMvpLrt.java @@ -36,12 +36,11 @@ import java.util.concurrent.ConcurrentHashMap; /** - *

                Performs a test of conditional independence X _||_ Y | Z1...Zn where all - * variables are either continuous or discrete. This test is valid for both ordinal and non-ordinal discrete - * searchVariables.

                - * - *

                Andrews, B., Ramsey, J., & Cooper, G. F. (2018). Scoring Bayesian networks of - * mixed variables. International journal of data science and analytics, 6, 3-18.

                + * Performs a test of conditional independence X _||_ Y | Z1...Zn where all variables are either continuous or discrete. + * This test is valid for both ordinal and non-ordinal discrete searchVariables. + *

                + * Andrews, B., Ramsey, J., & Cooper, G. F. (2018). Scoring Bayesian networks of mixed variables. International + * journal of data science and analytics, 6, 3-18. * * @author Bryan Andrews */ @@ -53,12 +52,12 @@ public class IndTestMvpLrt implements IndependenceTest { private final Map nodesHash; // Likelihood function private final MvpLikelihood likelihood; + // A cache of results for independence facts. + private final Map facts = new ConcurrentHashMap<>(); // The significance level of the independence tests. private double alpha; // True if verbose output should be printed. private boolean verbose; - // A cache of results for independence facts. - private final Map facts = new ConcurrentHashMap<>(); /** * Constructor. diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestProbabilistic.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestProbabilistic.java index 90baa78a35..e73a98642b 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestProbabilistic.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestProbabilistic.java @@ -110,8 +110,9 @@ public IndependenceTest indTestSubset(List vars) { /** * Returns an independence result that states whether x _||_y | z and what the p-value of the test is. - * @param x The first variable. - * @param y The second variable. + * + * @param x The first variable. + * @param y The second variable. * @param _z The conditioning set. * @return an independence result (see) * @see IndependenceResult diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestTrekSep.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestTrekSep.java index a09850d514..9b79820977 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestTrekSep.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestTrekSep.java @@ -53,14 +53,14 @@ public final class IndTestTrekSep implements IndependenceTest { private final Map indexMap; // A hash of nodes to names. private final Map nameMap; + // A cache of results for independence facts. + private final Map facts = new ConcurrentHashMap<>(); // True if verbose output should be printed. private boolean verbose; // The variables of the covariance matrix, in order. (Unmodifiable list.) private List variables; // The significance level of the independence tests. private double alpha; - // A cache of results for independence facts. - private final Map facts = new ConcurrentHashMap<>(); /** * Constructs a new independence test that will determine conditional independence facts using the given correlation @@ -230,8 +230,7 @@ public Node getVariable(String name) { } /** - * If isDeterminismAllowed(), defers to IndTestFisherZD; otherwise throws - * UnsupportedOperationException. + * If isDeterminismAllowed(), defers to IndTestFisherZD; otherwise throws UnsupportedOperationException. * * @return True if so * @throws UnsupportedOperationException If the above condition is not met. diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/Kci.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/Kci.java index a5fd5cb6ea..30c3ec1d5a 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/Kci.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/Kci.java @@ -27,18 +27,18 @@ import static org.apache.commons.math3.util.FastMath.*; /*** - *

                Gives an implementation of the Kernal Independence Test (KCI) by Kun Zhang, which is a - * general test of conditional independence. The reference is here:

                - * - *

                Zhang, K., Peters, J., Janzing, D., and Schölkopf, B. (2012). Kernel-based conditional independence - * test and application in causal discovery. arXiv preprint arXiv:1202.3775.

                - * - *

                Please see that paper, especially Theorem 4 and Proposition 5.

                - * - *

                Using optimal kernel bandwidths suggested by Bowman and Azzalini (1997):

                - * - *

                Bowman, A. W., and Azzalini, A. (1997). Applied smoothing techniques for data analysis: the kernel - * approach with S-Plus illustrations (Vol. 18). OUP Oxford.

                + * Gives an implementation of the Kernal Independence Test (KCI) by Kun Zhang, which is a + * general test of conditional independence. The reference is here: + *

                + * Zhang, K., Peters, J., Janzing, D., and Schölkopf, B. (2012). Kernel-based conditional independence + * test and application in causal discovery. arXiv preprint arXiv:1202.3775. + *

                + * Please see that paper, especially Theorem 4 and Proposition 5. + *

                + * Using optimal kernel bandwidths suggested by Bowman and Azzalini (1997): + *

                + * Bowman, A. W., and Azzalini, A. (1997). Applied smoothing techniques for data analysis: the kernel + * approach with S-Plus illustrations (Vol. 18). OUP Oxford. * * @author kunzhang * @author Vineet Raghu on 7/3/2016 diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/MsepTest.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/MsepTest.java index b94231c936..a50b48a604 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/MsepTest.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/MsepTest.java @@ -35,10 +35,9 @@ import java.util.concurrent.ConcurrentHashMap; /** - * Checks independence facts for variables associated with the nodes in a given graph by - * checking m-separation facts on the underlying nodes. We use the IndependenceTest interface here so that this - * m-separation test can be used in place of a statistical conditional independence test in algorithms to provide oracle - * information. + * Checks independence facts for variables associated with the nodes in a given graph by checking m-separation facts on + * the underlying nodes. We use the IndependenceTest interface here so that this m-separation test can be used in place + * of a statistical conditional independence test in algorithms to provide oracle information. * * @author josephramsey */ diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/RowsSettable.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/RowsSettable.java index e786ba36b8..12386f718d 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/RowsSettable.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/RowsSettable.java @@ -5,14 +5,15 @@ public interface RowsSettable { /** - * Gets the rows to use for the test. These rows over override testwise deletion - * if set. + * Gets the rows to use for the test. These rows over override testwise deletion if set. + * * @return The rows to use for the test. Can be null. */ List getRows(); /** * Sets the rows to use for the test. This will override testwise deletion. + * * @param rows The rows to use for the test. Can be null. */ void setRows(List rows); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ScoreIndTest.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ScoreIndTest.java index de7e21e1f7..5bbd3632cf 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ScoreIndTest.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ScoreIndTest.java @@ -40,14 +40,12 @@ import java.util.Set; /** - *

                Gives a way of interpreting a score as an independence test. The contract is that - * the score returned will be negative for independence and positive for dependence; this simply reports these - * differences.

                + * Gives a way of interpreting a score as an independence test. The contract is that the score returned will be negative + * for independence and positive for dependence; this simply reports these differences. * * @author josephramsey */ public class ScoreIndTest implements IndependenceTest { - private final Score score; private final List variables; private final DataModel data; @@ -94,9 +92,6 @@ public IndependenceResult checkIndependence(Node x, Node y, Set z) { int N = score.getSampleSize(); - // No. -// double p = 5 * exp(-2 * v - 2 * log(N)) / ((N) * log(N)); - boolean independent = v <= 0; if (this.verbose) { diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/FciOrient.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/FciOrient.java index 7cb98280ad..92ed49f382 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/FciOrient.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/FciOrient.java @@ -32,26 +32,23 @@ import java.util.*; /** - *

                Performs the final orientation steps of the FCI algorithms, which - * is a useful tool to use in a variety of FCI-like algorithms.

                - * - *

                There are two versions of these final orientation steps, one due to - * Peter Spirtes (the original, in Causation, Prediction and Search), which is arrow complete, and the other which Jiji - * Zhang worked out in his Ph.D. dissertation, which is both arrow and tail complete. The references for these are as - * follows.

                - * - *

                Spirtes, P., Glymour, C. N., Scheines, R., & Heckerman, D. (2000). - * Causation, prediction, and search. MIT press.

                - * - *

                Zhang, J. (2008). On the completeness of orientation rules for causal - * discovery in the presence of latent confounders and selection bias. Artificial Intelligence, 172(16-17), - * 1873-1896.

                - * - *

                These final rules are used in all algorithms in Tetrad that - * follow and refine the FCI algorithm--for example, the GFCI and RFCI algorihtms.

                - * - *

                We've made the methods for each of the separate rules publicly - * accessible in case someone wants to use the individual rules in the context of their own algorithms.

                + * Performs the final orientation steps of the FCI algorithms, which is a useful tool to use in a variety of FCI-like + * algorithms. + *

                + * There are two versions of these final orientation steps, one due to Peter Spirtes (the original, in Causation, + * Prediction and Search), which is arrow complete, and the other which Jiji Zhang worked out in his Ph.D. dissertation, + * which is both arrow and tail complete. The references for these are as follows. + *

                + * Spirtes, P., Glymour, C. N., Scheines, R., & Heckerman, D. (2000). Causation, prediction, and search. MIT press. + *

                + * Zhang, J. (2008). On the completeness of orientation rules for causal discovery in the presence of latent confounders + * and selection bias. Artificial Intelligence, 172(16-17), 1873-1896. + *

                + * These final rules are used in all algorithms in Tetrad that follow and refine the FCI algorithm--for example, the + * GFCI and RFCI algorihtms. + *

                + * We've made the methods for each of the separate rules publicly accessible in case someone wants to use the individual + * rules in the context of their own algorithms. * * @author Erin Korber, June 2004 * @author Alex Smith, December 2008 @@ -501,8 +498,8 @@ public void ruleR2(Node a, Node b, Node c, Graph graph) { } /** - * Implements the double-triangle orientation rule, which states that if D*-oB, A*->B<-*C and A*-oDo-*C, and !adj(a, - * c), D*-oB, then D*->B. + * Implements the double-triangle orientation rule, which states that if D*-oB, A*->B<-*C and A*-oDo-*C, and + * !adj(a, c), D*-oB, then D*->B. *

                * This is Zhang's rule R3. */ @@ -1174,8 +1171,8 @@ public void setDoDiscriminatingPathTailRule(boolean doDiscriminatingPathTailRule *

                * MAY HAVE WEIRD EFFECTS ON ARBITRARY NODE PAIRS. *

                - * R10: If Ao->C, B-->C<--D, there is an uncovered p.d. path u1=<A,M,...,B> and an uncovered p.d. path u2= - * <A,N,...,D> with M != N and M,N nonadjacent then A-->C. + * R10: If Ao->C, B-->C<--D, there is an uncovered p.d. path u1=<A,M,...,B> and an uncovered p.d. + * path u2= <A,N,...,D> with M != N and M,N nonadjacent then A-->C. * * @param a The node A. * @param c The node C. diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/SepsetProducer.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/SepsetProducer.java index 58efec8aa3..1f61d72964 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/SepsetProducer.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/SepsetProducer.java @@ -27,8 +27,7 @@ import java.util.Set; /** - *

                Provides a covenience interface for classes that can generate and keep - * track of sepsets.

                + * Provides a covenience interface for classes that can generate and keep track of sepsets. * * @author josephramsey * @see SepsetMap diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/SepsetsGreedy.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/SepsetsGreedy.java index 066fa2d78e..9f4e2d3c78 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/SepsetsGreedy.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/SepsetsGreedy.java @@ -37,8 +37,8 @@ import java.util.Set; /** - *

                Provides a SepsetProcuder that selects the first sepset it comes to from - * among the extra sepsets or the adjacents of i or k, or null if none is found.

                + * Provides a SepsetProcuder that selects the first sepset it comes to from among the extra sepsets or the adjacents of + * i or k, or null if none is found. * * @author josephramsey * @see SepsetProducer From b3e85a1c579421c19d904a15d02480944a78dc6f Mon Sep 17 00:00:00 2001 From: jdramsey Date: Tue, 23 Jan 2024 14:29:01 -0500 Subject: [PATCH 096/163] Fixed BIC score stamping for all relevant algorithms, both continuous and discrete. --- .../algorithm/continuous/dag/Dagma.java | 3 ++- .../algorithm/continuous/dag/DirectLingam.java | 1 - .../algcomparison/algorithm/oracle/cpdag/Boss.java | 3 ++- .../algcomparison/algorithm/oracle/cpdag/Fges.java | 3 ++- .../algorithm/oracle/cpdag/Grasp.java | 6 +++--- .../algcomparison/algorithm/oracle/cpdag/Pcd.java | 5 ++++- .../algcomparison/algorithm/oracle/cpdag/Sp.java | 3 ++- .../cmu/tetrad/search/utils/LogUtilsSearch.java | 14 ++++++++------ 8 files changed, 23 insertions(+), 15 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/continuous/dag/Dagma.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/continuous/dag/Dagma.java index a47570bffd..b0530b1f90 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/continuous/dag/Dagma.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/continuous/dag/Dagma.java @@ -13,6 +13,7 @@ import edu.cmu.tetrad.graph.EdgeListGraph; import edu.cmu.tetrad.graph.Graph; import edu.cmu.tetrad.search.score.Score; +import edu.cmu.tetrad.search.utils.LogUtilsSearch; import edu.cmu.tetrad.util.Parameters; import edu.cmu.tetrad.util.Params; import edu.cmu.tetrad.util.TetradLogger; @@ -50,7 +51,7 @@ public Graph search(DataModel dataSet, Parameters parameters) { search.setCpdag(parameters.getBoolean(Params.CPDAG)); Graph graph = search.search(); TetradLogger.getInstance().forceLogMessage(graph.toString()); - + LogUtilsSearch.stampWithBic(graph, dataSet); return graph; } else { Dagma algorithm = new Dagma(); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/continuous/dag/DirectLingam.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/continuous/dag/DirectLingam.java index d30c33400d..339201ff8d 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/continuous/dag/DirectLingam.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/continuous/dag/DirectLingam.java @@ -56,7 +56,6 @@ public Graph search(DataModel dataSet, Parameters parameters) { edu.cmu.tetrad.search.DirectLingam search = new edu.cmu.tetrad.search.DirectLingam(data, score); Graph graph = search.search(); TetradLogger.getInstance().forceLogMessage(graph.toString()); - LogUtilsSearch.stampWithBic(graph, dataSet); return graph; } else { diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/Boss.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/Boss.java index a7c92da553..e15d581b94 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/Boss.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/Boss.java @@ -76,7 +76,8 @@ public Graph search(DataModel dataModel, Parameters parameters) { PermutationSearch permutationSearch = new PermutationSearch(boss); permutationSearch.setKnowledge(this.knowledge); Graph graph = permutationSearch.search(); - LogUtilsSearch.stampWithScores(graph, dataModel, score); + LogUtilsSearch.stampWithScore(graph, score); + LogUtilsSearch.stampWithBic(graph, dataModel); return graph; } else { Boss algorithm = new Boss(this.score); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/Fges.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/Fges.java index b666743328..6b0c020a68 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/Fges.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/Fges.java @@ -104,7 +104,8 @@ public Graph search(DataModel dataModel, Parameters parameters) { graph.addAttribute("BIC", new BicEst().getValue(null, graph, dataModel)); } - LogUtilsSearch.stampWithScores(graph, dataModel, score); + LogUtilsSearch.stampWithScore(graph, score); + LogUtilsSearch.stampWithBic(graph, dataModel); return graph; } else { Fges fges = new Fges(this.score); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/Grasp.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/Grasp.java index f81ea69ba8..13340438fd 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/Grasp.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/Grasp.java @@ -90,10 +90,10 @@ public Graph search(DataModel dataModel, Parameters parameters) { grasp.setKnowledge(this.knowledge); grasp.bestOrder(score.getVariables()); Graph graph = grasp.getGraph(parameters.getBoolean(Params.OUTPUT_CPDAG)); + LogUtilsSearch.stampWithScore(graph, score); + LogUtilsSearch.stampWithBic(graph, dataModel); - if (!(score instanceof GraphScore)) { - LogUtilsSearch.stampWithScores(graph, dataModel, score); - } + LogUtilsSearch.stampWithBic(graph, dataModel); return graph; } else { diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/Pcd.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/Pcd.java index f74f3d8730..91e98402dd 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/Pcd.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/Pcd.java @@ -8,6 +8,7 @@ import edu.cmu.tetrad.graph.Graph; import edu.cmu.tetrad.graph.GraphTransforms; import edu.cmu.tetrad.search.test.ScoreIndTest; +import edu.cmu.tetrad.search.utils.LogUtilsSearch; import edu.cmu.tetrad.search.work_in_progress.SemBicScoreDeterministic; import edu.cmu.tetrad.util.Parameters; import edu.cmu.tetrad.util.Params; @@ -53,7 +54,9 @@ public Graph search(DataModel dataSet, Parameters parameters) { search.setDepth(parameters.getInt(Params.DEPTH)); search.setKnowledge(this.knowledge); search.setVerbose(parameters.getBoolean(Params.VERBOSE)); - return search.search(); + Graph search1 = search.search(); + LogUtilsSearch.stampWithBic(search1, dataSet); + return search1; } else { Pcd algorithm = new Pcd(); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/Sp.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/Sp.java index d61d61584e..3eb33d683f 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/Sp.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/Sp.java @@ -70,7 +70,8 @@ public Graph search(DataModel dataModel, Parameters parameters) { PermutationSearch permutationSearch = new PermutationSearch(new edu.cmu.tetrad.search.Sp(score)); permutationSearch.setKnowledge(this.knowledge); Graph graph = permutationSearch.search(); - LogUtilsSearch.stampWithScores(graph, dataModel, score); + LogUtilsSearch.stampWithScore(graph, score); + LogUtilsSearch.stampWithBic(graph, dataModel); return graph; } else { Sp algorithm = new Sp(this.score); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/LogUtilsSearch.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/LogUtilsSearch.java index 6d1e6c4cc2..e23963caae 100755 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/LogUtilsSearch.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/LogUtilsSearch.java @@ -27,8 +27,10 @@ import edu.cmu.tetrad.graph.Graph; import edu.cmu.tetrad.graph.GraphTransforms; import edu.cmu.tetrad.graph.Node; +import edu.cmu.tetrad.search.score.GraphScore; import edu.cmu.tetrad.search.score.Score; import edu.cmu.tetrad.util.NumberFormatUtil; +import edu.cmu.tetrad.util.TetradLogger; import org.jetbrains.annotations.NotNull; import java.text.NumberFormat; @@ -157,7 +159,9 @@ public static Map buildIndexing(List nodes) { } @NotNull - public static void stampWithScores(Graph graph, DataModel dataModel, Score score) { + public static void stampWithScore(Graph graph, Score score) { + if (score instanceof GraphScore) return; + if (!graph.getAllAttributes().containsKey("Score")) { Graph dag = GraphTransforms.dagFromCpdag(graph); Map hashIndices = buildIndexing(dag.getNodes()); @@ -179,17 +183,15 @@ public static void stampWithScores(Graph graph, DataModel dataModel, Score score graph.addAttribute("Score", _score); } - - stampWithBic(graph, dataModel); } public static void stampWithBic(Graph graph, DataModel dataModel) { - if (dataModel != null && dataModel.isContinuous() && !graph.getAllAttributes().containsKey("BIC")) { + if (dataModel != null && (dataModel.isContinuous() || dataModel.isDiscrete()) + && !graph.getAllAttributes().containsKey("BIC")) { try { graph.addAttribute("BIC", new BicEst().getValue(null, graph, dataModel)); } catch (Exception e) { - e.printStackTrace(); -// throw new RuntimeException(e); + TetradLogger.getInstance().forceLogMessage("Error computing BIC: " + e.getMessage()); } } } From 83c848a55004e91d19ae4959c540ddd9c9433a3b Mon Sep 17 00:00:00 2001 From: jdramsey Date: Tue, 23 Jan 2024 14:58:51 -0500 Subject: [PATCH 097/163] Added a note that BIC is calculated as 2L - k ln N (or 2L - c k ln N) everywhere the term appears in the documentation. --- .../algcomparison/statistic/BicDiff.java | 2 +- .../algcomparison/statistic/BicEst.java | 2 +- .../algcomparison/statistic/BicTrue.java | 2 +- .../main/java/edu/cmu/tetrad/sem/SemIm.java | 3 -- .../src/main/resources/docs/manual/index.html | 29 ++++++++++++------- 5 files changed, 22 insertions(+), 16 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/BicDiff.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/BicDiff.java index 4b5ba79e93..010e1ba9d1 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/BicDiff.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/BicDiff.java @@ -8,7 +8,7 @@ import static org.apache.commons.math3.util.FastMath.tanh; /** - * Difference between the true and estiamted BIC scores. + * Difference between the true and estiamted BIC scores. The BIC is calculated as 2L - k ln N, so "higher is better." * * @author josephramsey */ diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/BicEst.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/BicEst.java index 7d3a9410a8..6f7aca0127 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/BicEst.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/BicEst.java @@ -13,7 +13,7 @@ import static org.apache.commons.math3.util.FastMath.tanh; /** - * Estimated BIC score. + * Estimated BIC score. The BIC is calculated as 2L - k ln N, so "higher is better." * * @author josephramsey */ diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/BicTrue.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/BicTrue.java index f372c1b5f1..99df8b6eb6 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/BicTrue.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/BicTrue.java @@ -8,7 +8,7 @@ import static org.apache.commons.math3.util.FastMath.tanh; /** - * True BIC score. + * True BIC score. The BIC is calculated as 2L - k ln N, so "higher is better." * * @author josephramsey */ diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/sem/SemIm.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/sem/SemIm.java index 6f0a62aca9..47d3d5fe81 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/sem/SemIm.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/sem/SemIm.java @@ -1033,15 +1033,12 @@ public double getTruncLL() { */ public double getBicScore() { int dof = getSemPm().getDof(); -// return getChiSquare() - dof * FastMath.log(sampleSize); - return getChiSquare() - dof * FastMath.log(this.sampleSize); } @Override public double getRmsea() { - double v = getChiSquare() - this.semPm.getDof(); double v1 = this.semPm.getDof() * (getSampleSize() - 1); return sqrt(v) / sqrt(v1); diff --git a/tetrad-lib/src/main/resources/docs/manual/index.html b/tetrad-lib/src/main/resources/docs/manual/index.html index aa64fc87fd..45e483602a 100755 --- a/tetrad-lib/src/main/resources/docs/manual/index.html +++ b/tetrad-lib/src/main/resources/docs/manual/index.html @@ -1706,7 +1706,8 @@

                ML Bayes Estimations

                The Model tab works exactly as it does in a Bayes instantiated model. The Model Statistics tab provides the p-value for a chi square test of the model, degrees of freedom, the chi square value, and the - Bayes Information Criterion (BIC) score of the model.

                + Bayes Information Criterion (BIC) score of the model. Note that BIC + is calculated as 2L -

                Dirichlet Estimations

                @@ -1778,7 +1779,7 @@

                SEM Estimates

                coefficient parameters plus the number of covariance parameters. (Note that the degrees of freedom many be negative, in which case estimation should not be done.) The BIC score is calculated as ch^2 - dof * - log(N).

                + log(N), so "higher is better.".

                You can change which score optimizer Tetrad uses by choosing them from the drop-down menus at the bottom of the window and clicking @@ -1796,7 +1797,8 @@

                SEM Estimates

                noted that while these test statistics are standard, they are not in general correct. See Mathias Drton, 2009, Likelihood ratio tests and singularities. Annals of Statistics 37(2):979-1012. - arXiv:math.ST/0703360.

                + arXiv:math.ST/0703360. Note also that BIC is calculated as 2L - k ln N, + so "higher is better."

                When the EM algorithm is used with latent variable models, we recommend multiple random restarts. The number of restarts can be set in @@ -2697,6 +2699,8 @@

                Description

                continuous data (using the SEM BIC score), all discrete data (using the BDeu score) or a mixture of continuous and discrete data (using the Conditional Gaussian score); these are all decomposable scores. + Note that in all case, BIC is calculated as 2L - k ln N, so "higher + is better."

                Note: If one wants to analyze time series data using this algorithm, @@ -2728,11 +2732,13 @@

                Output Format

                -

                Adjusts the selected score for FGES so +

                + Adjusts the selected score for FGES to allow for multiple datasets as input. The linear, Gaussian BIC scores for each data set are averaged at each step of the algorithm, producing a model for all data sets that assumes they have the same - graphical structure across dataset.

                + graphical structure across dataset. Note that BIC is calculated + as 2L - k ln N, so "higher is better."

                @@ -3089,7 +3095,8 @@

                Description

                increases the BIC score, then also the edge between X1:1 and X2:1 is removed, and so on for additional lags if they exist. When some edge is removed as the result of a score increase, all similar (or - “homologous”) edges are also removed.

                + “homologous”) edges are also removed. Note that BIC is calculated + as 2L - k ln N, so "higher is better."

                Since this algorithm specifically requires time series data, one must set the time lag parameter to a value greater than 0, which @@ -3992,6 +3999,7 @@

                MAG SEM BIC Test

                This gives a BIC score (used as a test here) for a Mixed Ancestral Graph (MAG). + Note that BIC is calculated as 2L - k ln N, so "higher is better."

                @@ -4079,8 +4087,7 @@

                Discrete BIC Test

                directly, and this is penalized as is usual for a BIC score. The only surprising thing perhaps is that we use the formula BIC = 2L - k ln N, where L is the likelihood, k the number of parameters, and N the sample - size, instead of the usual L + k / 2 ln N. So higher BIC scores will - correspond to greater dependence. In the case of independence, the BIC + size, so "higher is better." In the case of independence, the BIC score will be negative, since the likelihood will be zero, and this will be penalized. The test yields a p-value; we simply use alpha - p as the score, where alpha is the cutoff for rejecting the null hypothesis of @@ -4237,7 +4244,8 @@

                Conditional Gaussian BIC Score

                variables. Calculates a BIC score based on likelihood that is calculated using a conditional Gaussian assumption. See Andrews, B., Ramsey, J., & Cooper, G. F. (2018). Scoring Bayesian networks of mixed variables. - International journal of data science and analytics, 6(1), 3-18.

                + International journal of data science and analytics, 6(1), 3-18. + Note that BIC is calculated as 2L - k ln N, so "higher is better."

                Parameters

                @@ -4250,7 +4258,8 @@

                Parameters

                Calculates a BIC score based on likelihood that is calculated using a conditional Gaussian assumption. See Andrews, B., Ramsey, J., & Cooper, G. F. (2019). Learning high-dimensional directed acyclic graphs with - mixed data-types. Proceedings of machine learning research, 104, 4.

                + mixed data-types. Proceedings of machine learning research, 104, 4. + Note that BIC is calculated as 2L - k ln N, so "higher is better."

                Parameters

                From 1be62a1ed0a664c66a52c3f4156238b93803e394 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Tue, 23 Jan 2024 15:49:12 -0500 Subject: [PATCH 098/163] Added knowledge for the Markov check in the interface; for the knowledge, for X _||_ Y | Z, X and Y are constrained to be in the last tier of the knowledge, and the nodes in Z are constrained to be among nodes in all tiers. Additional forbidden or required edges are not allowed. --- .../model/MarkovCheckIndTestModel.java | 164 +++++++++++++++++- .../edu/cmu/tetrad/search/MarkovCheck.java | 14 +- 2 files changed, 173 insertions(+), 5 deletions(-) diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/MarkovCheckIndTestModel.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/MarkovCheckIndTestModel.java index a0dcba9ee0..583501fefb 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/MarkovCheckIndTestModel.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/MarkovCheckIndTestModel.java @@ -23,7 +23,9 @@ import edu.cmu.tetrad.data.DataModel; import edu.cmu.tetrad.data.Knowledge; +import edu.cmu.tetrad.data.KnowledgeBoxInput; import edu.cmu.tetrad.graph.Graph; +import edu.cmu.tetrad.graph.Node; import edu.cmu.tetrad.search.ConditioningSetType; import edu.cmu.tetrad.search.IndependenceTest; import edu.cmu.tetrad.search.MarkovCheck; @@ -32,27 +34,65 @@ import edu.cmu.tetrad.util.Parameters; import edu.cmu.tetrad.util.TetradSerializableUtils; +import java.io.Serial; import java.util.LinkedList; import java.util.List; /** - * Stores a list of independence facts. + * A model for the Markov check. The Markov check for a given graph and dataset checks whether the graph is Markov with + * respect to the dataset. The Markov check can be used to check whether a graph is Markov with respect to a dataset, or + * whether a graph is Markov with respect to a dataset and a set of variables. The Markov check can also be used to + * check whether a graph is Markov with respect to a dataset and a set of variables, given a set of knowledge. For facts + * of the form X _||_ Y | Z, X and Y should be in the last tier of the knowledge, and Z should be in previous tiers. * * @author josephramsey */ -public class MarkovCheckIndTestModel implements SessionModel, GraphSource { +public class MarkovCheckIndTestModel implements SessionModel, GraphSource, KnowledgeBoxInput { + @Serial private static final long serialVersionUID = 23L; + // The data model to check. private final DataModel dataModel; - private final Parameters parameters; + // The graph to check. private final Graph graph; + // The parameters. + private final Parameters parameters; + // The name of this model. private String name = ""; + // The variables to check. private List vars = new LinkedList<>(); + // The Markov check object. private transient MarkovCheck markovCheck = null; + // The knowledge to use. This will be passed to the underlying Markov check object. For facts odf the form + // X _||_ Y | Z, X and Y should be in the last tier, and Z should be in previous tiers. + private Knowledge knowledge; + /** + * Constructs a new Markov checer with the given data model, graph, and parameters. + * + * @param dataModel the data model. + * @param graphSource the graph source. + * @param parameters the parameters. + */ public MarkovCheckIndTestModel(DataWrapper dataModel, GraphSource graphSource, Parameters parameters) { + this(dataModel, graphSource, null, parameters); + } + + /** + * Constructs a new Markov checker with the given data model, graph, and parameters. + * + * @param dataModel the data model. + * @param graphSource the graph source. + * @param parameters the parameters. + */ + public MarkovCheckIndTestModel(DataWrapper dataModel, GraphSource graphSource, KnowledgeBoxModel knowlegeBox, + Parameters parameters) { this.dataModel = dataModel.getSelectedDataModel(); this.graph = graphSource.getGraph(); this.parameters = parameters; + + if (knowlegeBox != null) { + this.knowledge = knowlegeBox.getKnowledge(); + } } /** @@ -64,49 +104,167 @@ public static Knowledge serializableInstance() { return new Knowledge(); } + /** + * Sets the independence test and constructs the underlying MarkovCheck object. + * + * @param test the independence test. + */ public void setIndependenceTest(IndependenceTest test) { this.markovCheck = new MarkovCheck(this.graph, test, this.markovCheck == null ? ConditioningSetType.LOCAL_MARKOV : this.markovCheck.getSetType()); + if (this.knowledge != null) { + this.markovCheck.setKnowledge(this.knowledge); + } } + /** + * Returns the underlying MarkovCheck object. + * + * @return the underlying MarkovCheck object. + */ public MarkovCheck getMarkovCheck() { return this.markovCheck; } + /** + * Returns the graph. + * + * @return the graph. + */ @Override public Graph getGraph() { return this.graph; } + /** + * Returns the data model. + * + * @return the data model. + */ public DataModel getDataModel() { return dataModel; } + /** + * Returns the parameters. + * + * @return the parameters. + */ public Parameters getParameters() { return parameters; } + /** + * Returns the name of this model. + * + * @return the name of this model. + */ @Override public String getName() { return this.name; } + /** + * Sets the name of this model. + * + * @param name the name of this model. + */ @Override public void setName(String name) { this.name = name; } + /** + * Returns the variables to check. + * + * @return the variables to check. + */ public List getVars() { return this.vars; } + /** + * Sets the variables to check. + * + * @param vars the variables to check. + */ public void setVars(List vars) { this.vars = vars; } + /** + * Returns the results of the Markov check. + * + * @param indep whether to return the results for the independence test or the dependence test. + * @return the results of the Markov check. + */ public List getResults(boolean indep) { return markovCheck.getResults(indep); } + + /** + * Returns the knowledge to use. This will be passed to the underlying Markov check object. For facts of the form X + * _||_ Y | Z, X and Y should be in the last tier, and Z should be in previous tiers. + * + * @return the knowledge to use. + */ + public Knowledge getKnowledge() { + return this.knowledge; + } + + /** + * Sets the knowledge to use. This will be passed to the underlying Markov check object. For facts of the form X + * _||_ Y | Z, X and Y should be in the last tier, and Z should be in previous tiers. + * + * @param knowledge a knowledge object. + */ + public void setKnowledge(Knowledge knowledge) { + this.knowledge = knowledge.copy(); + + if (this.markovCheck != null) { + this.markovCheck.setKnowledge(this.knowledge); + } + } + + /** + * Returns the source graph. + * + * @return the source graph. + */ + @Override + public Graph getSourceGraph() { + return null; + } + + /** + * Returns the result graph. + * + * @return the result graph. + */ + @Override + public Graph getResultGraph() { + return null; + } + + /** + * Returns the variables. + * + * @return the variables. + */ + @Override + public List getVariables() { + return null; + } + + /** + * Returns the variable names. + * + * @return the variable names. + */ + @Override + public List getVariableNames() { + return null; + } } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java index 362faa69aa..27f00330af 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java @@ -763,10 +763,20 @@ public void setKnowledge(Knowledge knowledge) { "| Z1,..,Zn."); } - List independenceNames = knowledge.getTier(knowledge.getNumTiers() - 1); + int lastTier = 0; + + for (int t = 0; t < knowledge.getNumTiers(); t++) { + if (!knowledge.getTier(t).isEmpty()) { + lastTier = t; + } + } + + List independenceNames = knowledge.getTier(lastTier); List conditioningNames = new ArrayList<>(); - for (int i = 0; i < knowledge.getNumTiers() - 1; i++) { + + // Assuming all named nodes go into thd conditioning set. + for (int i = 0; i <= lastTier; i++) { conditioningNames.addAll(knowledge.getTier(i)); } From 9eb5e59417191a511d3fe63f73ba00ae357e24a4 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Tue, 23 Jan 2024 16:04:32 -0500 Subject: [PATCH 099/163] cleanup. --- .../edu/cmu/tetrad/search/MarkovCheck.java | 24 ++++++------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java index 27f00330af..d4f8a4f69a 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java @@ -24,7 +24,7 @@ import java.util.concurrent.Future; /** - *

                Checks whether a graph is locally Markov or locally Faithful given a data set. First a lists of m-separation + * Checks whether a graph is locally Markov or locally Faithful given a data set. First a lists of m-separation * predictions are made for each pair of variables in the graph given the parents of one of the variables, one list (for * local Markov) where the m-separation holds and another list (for local Faithfulness) where the m-separation does not * hold. Then the predictions are tested against the data set using the independence test. For the Markov test, since an @@ -32,7 +32,11 @@ * Uniformity using the Kolmogorov-Smirnov test. Also, a fraction of dependent judgments is returned, which should equal * the alpha level of the independence test if the test is Uniform under the null hypothesis. For the Faithfulness test, * the p-values are tested for Uniformity using the Kolmogorov-Smirnov test; these should be dependent. Also, a fraction - * of dependent judgments is returned, which should be maximal./p> + * of dependent judgments is returned, which should be maximal. + *

                + * Knowledge may be supplied to the Markov check. This knowledge is used to specify independence and conditioning + * ranges. For facts of the form X _||_ Y | Z, X and Y should be in the last tier of the knowledge, and Z should be in + * previous tiers. Additional forbidden or required edges are not allowed. * * @author josephramsey */ @@ -716,20 +720,6 @@ private double getBinomialP(List pValues, double alpha) { return (1.0 - bd.cumulativeProbability(independentJudgements)) + (bd.probability(p - independentJudgements)); } - /** - * Returns the chunk size for parallelization. - * - * @param n The number of items to chunk. - * @return The chunk size for parallelization. - */ - private int getChunkSize(int n) { - if (true) return 1; - int numProcessors = Runtime.getRuntime().availableProcessors(); - int chunk = (int) FastMath.ceil((n / ((double) numProcessors))) / 10; - if (chunk < 1) chunk = 1; - return chunk; - } - /** * Returns the list of results for the given condition. * @@ -751,7 +741,7 @@ public Knowledge getKnowledge() { /** * Sets the knowledge object for the Markov checker. The knowledge object should contain the tier knowledge for the * Markov checker. The last tier contains the possible X and Y for X _||_ Y | Z1,..,Zn, and the previous tiers - * contain the possible Z1,..,Zn for X _||_ Y | Z1,..,Zn. + * contain the possible Z1,..,Zn for X _||_ Y | Z1,..,Zn. Additional forbidden or required edges are ignored. * * @param knowledge The knowledge object. */ From da8eac802cb571087a9a43346883d5b1fdf51522 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Tue, 23 Jan 2024 23:00:12 -0500 Subject: [PATCH 100/163] Cleanup,. --- .../edu/cmu/tetrad/search/MarkovCheck.java | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java index d4f8a4f69a..be30165af5 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java @@ -41,31 +41,53 @@ * @author josephramsey */ public class MarkovCheck { + // The graph. private final Graph graph; + // The independence test. private final IndependenceTest independenceTest; + // The results of the Markov check for the independent case. private final List resultsIndep = new ArrayList<>(); + // The results of the Markov check for the dependent case. private final List resultsDep = new ArrayList<>(); + // The type of conditioning sets to use in the Markov check. private ConditioningSetType setType; + // True if the checks should be parallelized. (Not always a good idea.) private boolean parallelized = false; + // The fraction of dependent judgments for the independent case. private double fractionDependentIndep = Double.NaN; + // The fraction of dependent judgments for the dependent case. private double fractionDependentDep = Double.NaN; + // The Kolmogorov-Smirnov p-value for the independent case. private double ksPValueIndep = Double.NaN; + // The Kolmogorov-Smirnov p-value for the dependent case. private double ksPValueDep = Double.NaN; + // The Anderson-Darling A^2 statistic for the independent case. private double aSquaredIndep = Double.NaN; + // The Anderson-Darling A^2 statistic for the dependent case. private double aSquaredDep = Double.NaN; + // The Anderson-Darling A^2* statistic for the independent case. private double aSquaredStarIndep = Double.NaN; + // The Anderson-Darling A^2* statistic for the dependent case. private double aSquaredStarDep = Double.NaN; + // The Anderson-Darling p-value for the independent case. private double andersonDarlingPIndep = Double.NaN; + // The Anderson-Darling p-value for the dependent case. private double andersonDarlingPDep = Double.NaN; + // The Binomial p-value for the independent case. private double binomialPIndep = Double.NaN; + // The Binomial p-value for the dependent case. private double binomialPDep = Double.NaN; + // The percentage of all samples to use when resampling for each conditional independence test. private double percentResample = 0.5; + // The number of tests for the independent case. private int numTestsindep = 0; + // The number of tests for the dependent case. private int numTestsDep = 0; - // A knowledge object to specify independence and conditioning ranges. Empty by default. private Knowledge knowledge = new Knowledge(); + // For X _||_ Y | Z, X and Y must come from this set if knowledge is used. private List independenceNodes; + // For X _||_ Y | Z, the nodes in Z must come from this set if knowledge is used. private List conditioningNodes; /** From 8b93c9e04979e78d161ab0e0c5fb5a1774908833 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Tue, 23 Jan 2024 23:02:31 -0500 Subject: [PATCH 101/163] Cleanup,. --- .../src/main/java/edu/cmu/tetrad/search/MarkovCheck.java | 9 --------- 1 file changed, 9 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java index be30165af5..ac7ef9f8e7 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java @@ -474,7 +474,6 @@ class IndCheckTask implements Callable, Set facts; private final MsepTest msepTest; - private boolean stopThread = false; IndCheckTask(int index, List facts, MsepTest test) { this.index = index; @@ -501,14 +500,6 @@ public Pair, Set> call() { return new Pair<>(msep, mconn); } - - public boolean isStopThread() { - return stopThread; - } - - public void setStopThread(boolean stopThread) { - this.stopThread = stopThread; - } } List, Set>>> tasks = new ArrayList<>(); From 9d7d6c7b04967bfec17d80bac2891b125d08f3a5 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Tue, 23 Jan 2024 23:06:41 -0500 Subject: [PATCH 102/163] Cleanup,. --- .../tetradapp/editor/MarkovCheckEditor.java | 72 +++++-------------- 1 file changed, 17 insertions(+), 55 deletions(-) diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java index a6b0885da4..d870859a02 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java @@ -68,7 +68,6 @@ public class MarkovCheckEditor extends JPanel { private final MarkovCheckIndTestModel model; private final NumberFormat nf = NumberFormatUtil.getInstance().getNumberFormat(); private final JLabel markovTestLabel = new JLabel("(Unspecified Test)"); - // private final JTextArea testDescTextArea = new JTextArea(); private final JComboBox indTestJComboBox = new JComboBox<>(); private final JComboBox conditioningSetTypeJComboBox = new JComboBox<>(); private final JLabel testLabel = new JLabel("(Unspecified Test)"); @@ -273,7 +272,6 @@ public void watch() { box2.add(new JLabel("Conditioning Sets:")); box2.add(conditioningSetTypeJComboBox); box2.add(Box.createHorizontalGlue()); - box.add(box2); JTextArea testDescTextArea = new JTextArea(getHelpMessage()); @@ -283,15 +281,12 @@ public void watch() { JScrollPane scroll = new JScrollPane(testDescTextArea); scroll.setPreferredSize(new Dimension(600, 400)); - JTabbedPane pane = new JTabbedPane(); pane.addTab("Check Markov", indep); pane.addTab("Check Dependent Distribution", dep); pane.addTab("Help", scroll); box.add(pane); -// setPreferredSize(new Dimension(750, 550)); - class MyWatchedProcess extends WatchedProcess { public void watch() { setTest(); @@ -311,9 +306,6 @@ public void watch() { } new MyWatchedProcess(); - -// box.setPreferredSize(new Dimension(750, 550)); - add(box); } @@ -434,12 +426,8 @@ public Object getValueAt(int rowIndex, int columnIndex) { } if (columnIndex == 1) { IndependenceFact fact = model.getResults(false).get(rowIndex).getFact(); - List Z = new ArrayList<>(fact.getZ()); -// Collections.sort(Z); - String z = Z.stream().map(Node::getName).collect(Collectors.joining(", ")); - return "Dep(" + fact.getX() + ", " + fact.getY() + (Z.isEmpty() ? "" : " | " + z) + ")"; } @@ -501,7 +489,6 @@ public Class getColumnClass(int columnIndex) { table.getColumnModel().getColumn(2).setCellRenderer(new Renderer()); table.getColumnModel().getColumn(3).setCellRenderer(new Renderer()); - JTableHeader header = table.getTableHeader(); header.addMouseListener(new MouseAdapter() { @@ -516,7 +503,6 @@ public void mouseClicked(MouseEvent e) { }); JScrollPane scroll = new JScrollPane(table); -// scroll.setPreferredSize(new Dimension(400, 400)); b1.add(scroll); Box b1a = Box.createHorizontalBox(); @@ -571,11 +557,6 @@ public void mouseClicked(MouseEvent e) { b6c.add(andersonDarlingPLabelDep); b0b1.add(b6c); -// Box b7 = Box.createHorizontalBox(); -// b7.add(Box.createHorizontalGlue()); -// b7.add(masLabelDep); -// b0b1.add(b7); - b0b1.add(Box.createVerticalGlue()); b0.add(b0b1); @@ -723,7 +704,6 @@ public void mouseClicked(MouseEvent e) { }); JScrollPane scroll = new JScrollPane(table); -// scroll.setPreferredSize(new Dimension(400, 400)); b1.add(scroll); Box b1a = Box.createHorizontalBox(); @@ -779,11 +759,6 @@ public void mouseClicked(MouseEvent e) { b6c.add(andersonDarlingPLabelIndep); b0b1.add(b6c); -// Box b7 = Box.createHorizontalBox(); -// b7.add(Box.createHorizontalGlue()); -// b7.add(masLabelIndep); -// b0b1.add(b7); - b0.add(b0b1); JPanel panel = new JPanel(); @@ -853,14 +828,6 @@ private void setLabelTexts() { fractionDepLabelDep = new JLabel(); } -// if (masLabelIndep == null) { -// masLabelIndep = new JLabel(); -// } -// -// if (masLabelDep == null) { -// masLabelDep = new JLabel(); -// } - ksLabelIndep.setText("P-value of KS Uniformity Test = " + ((Double.isNaN(model.getMarkovCheck().getKsPValue(true)) ? "-" @@ -903,15 +870,6 @@ private void setLabelTexts() { + ((Double.isNaN(model.getMarkovCheck().getFractionDependent(false)) ? "-" : NumberFormatUtil.getInstance().getNumberFormat().format(model.getMarkovCheck().getFractionDependent(false))))); -// masLabelIndep.setText("Markov Adequacy Score = " -// + ((Double.isNaN(model.getMarkovCheck().getMarkovAdequacyScore(0.01)) -// ? "-" -// : NumberFormatUtil.getInstance().getNumberFormat().format(model.getMarkovCheck().getMarkovAdequacyScore(0.01))))); -// masLabelDep.setText("Markov Adequacy Score = " -// + ((Double.isNaN(model.getMarkovCheck().getMarkovAdequacyScore(0.01)) -// ? "-" -// : NumberFormatUtil.getInstance().getNumberFormat().format(model.getMarkovCheck().getMarkovAdequacyScore(0.01))))); - conditioningLabelIndep.setText("Tests graphical predictions of Indep(X, Y | " + conditioningSetTypeJComboBox.getSelectedItem() + ")"); conditioningLabelDep.setText("Tests graphical predictions of Dep(X, Y | " + conditioningSetTypeJComboBox.getSelectedItem() + ")"); @@ -949,7 +907,23 @@ private Box createHistogramPanel(boolean indep) { return Box.createVerticalBox(); } + HistogramPanel view = getHistogramPanel(results); + + Box box = Box.createHorizontalBox(); + box.add(Box.createHorizontalGlue()); + box.add(view); + box.add(Box.createHorizontalGlue()); + + Box vBox = Box.createVerticalBox(); + vBox.add(Box.createVerticalGlue()); + vBox.add(box); + vBox.add(Box.createVerticalGlue()); + + return vBox; + } + @NotNull + private static HistogramPanel getHistogramPanel(List results) { DataSet dataSet = new BoxDataSet(new VerticalDoubleDataBox(results.size(), 1), Collections.singletonList(new ContinuousVariable("P-Value or Bump"))); @@ -958,25 +932,13 @@ private Box createHistogramPanel(boolean indep) { } Histogram histogram = new Histogram(dataSet, "P-Value or Bump", false); -// histogram.setTarget("P-Value or Bump"); HistogramPanel view = new HistogramPanel(histogram, true); Color fillColor = new Color(113, 165, 210); view.setBarColor(fillColor); view.setPreferredSize(new Dimension(350, 200)); - - Box box = Box.createHorizontalBox(); - box.add(Box.createHorizontalGlue()); - box.add(view); - box.add(Box.createHorizontalGlue()); - - Box vBox = Box.createVerticalBox(); - vBox.add(Box.createVerticalGlue()); - vBox.add(box); - vBox.add(Box.createVerticalGlue()); - - return vBox; + return view; } private DataType getDataType() { From 939b548796efdac741a3a2408c57c6dffdd943cb Mon Sep 17 00:00:00 2001 From: jdramsey Date: Tue, 23 Jan 2024 23:08:38 -0500 Subject: [PATCH 103/163] Cleanup,. --- .../tetradapp/editor/MarkovCheckEditor.java | 51 ++++++++++--------- 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java index d870859a02..202b993b59 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java @@ -44,8 +44,8 @@ import javax.swing.table.AbstractTableModel; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.JTableHeader; -import java.awt.*; import java.awt.Point; +import java.awt.*; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.lang.reflect.InvocationTargetException; @@ -60,7 +60,11 @@ /** - * Lists independence facts specified by user and allows the list to be sorted by independence fact or by p value. + * A model for the Markov check. The Markov check for a given graph and dataset checks whether the graph is Markov with + * respect to the dataset. The Markov check can be used to check whether a graph is Markov with respect to a dataset, or + * whether a graph is Markov with respect to a dataset and a set of variables. The Markov check can also be used to + * check whether a graph is Markov with respect to a dataset and a set of variables, given a set of knowledge. For facts + * of the form X _||_ Y | Z, X and Y should be in the last tier of the knowledge, and Z should be in previous tiers. * * @author josephramsey */ @@ -329,6 +333,27 @@ If the first bar in this histogram is especially high (for the p-value case), th A note about Markov Blankets: The "Markov Blanket" conditioning set choice implements the Markov blanket calculation in a way that is correct for DAGs, CPDAGs, MAGs, and PAGs. For all of these graph types, the list of m-connecting facts in the Faithfulness tab should be empty, since the Markov blanket should screen off the target from any other variables in the dataset. It's possible that for some other graph types this list may not be empty (i.e., the Markov blanket calculation may not be correct)."""; } + @NotNull + private static HistogramPanel getHistogramPanel(List results) { + DataSet dataSet = new BoxDataSet(new VerticalDoubleDataBox(results.size(), 1), + Collections.singletonList(new ContinuousVariable("P-Value or Bump"))); + + for (int i = 0; i < results.size(); i++) { + dataSet.setDouble(i, 0, results.get(i).getPValue()); + } + + Histogram histogram = new Histogram(dataSet, "P-Value or Bump", false); + HistogramPanel view = new HistogramPanel(histogram, true); + + Color fillColor = new Color(113, 165, 210); + view.setBarColor(fillColor); + + view.setPreferredSize(new Dimension(350, 200)); + return view; + } + + //========================PUBLIC METHODS==========================// + private void refreshResult(MarkovCheckIndTestModel model, DoubleTextField percent) { setTest(); model.getMarkovCheck().setPercentResample(percent.getValue()); @@ -346,8 +371,6 @@ private void refreshResult(MarkovCheckIndTestModel model, DoubleTextField percen setLabelTexts(); } - //========================PUBLIC METHODS==========================// - private void setTest() { IndependenceTestModel selectedItem = (IndependenceTestModel) indTestJComboBox.getSelectedItem(); Class clazz = (selectedItem == null) ? null @@ -875,7 +898,6 @@ private void setLabelTexts() { conditioningLabelDep.setText("Tests graphical predictions of Dep(X, Y | " + conditioningSetTypeJComboBox.getSelectedItem() + ")"); } - private int getLastSortCol() { return this.lastSortCol; } @@ -922,25 +944,6 @@ private Box createHistogramPanel(boolean indep) { return vBox; } - @NotNull - private static HistogramPanel getHistogramPanel(List results) { - DataSet dataSet = new BoxDataSet(new VerticalDoubleDataBox(results.size(), 1), - Collections.singletonList(new ContinuousVariable("P-Value or Bump"))); - - for (int i = 0; i < results.size(); i++) { - dataSet.setDouble(i, 0, results.get(i).getPValue()); - } - - Histogram histogram = new Histogram(dataSet, "P-Value or Bump", false); - HistogramPanel view = new HistogramPanel(histogram, true); - - Color fillColor = new Color(113, 165, 210); - view.setBarColor(fillColor); - - view.setPreferredSize(new Dimension(350, 200)); - return view; - } - private DataType getDataType() { DataModel dataSet = model.getDataModel(); From ec149088c6cfac4659c7a34781f8b3922694d06c Mon Sep 17 00:00:00 2001 From: jdramsey Date: Tue, 23 Jan 2024 23:11:58 -0500 Subject: [PATCH 104/163] Cleanup,. --- .../java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java index 202b993b59..c1cef7329e 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java @@ -322,15 +322,16 @@ private static String getHelpMessage() { If the independence test yields a p-value, as for instance, for the Fisher Z test (for the linear, Gaussian case) or else the Chi-Square test (for the multinomial case), then under the null hypothesis of independence and for a consistent test, these p-values should be distributed as Uniform(0, 1). That is, it should be just as likely to see p-values in any range of equal width. If the test is inconsistent or the graph is incorrect (i.e., the parents of some or all of the nodes in the graph are incorrect), then this distribution of p-values will not be Uniform. To visualize this, we display the histogram of the p-values with equally sized bins; the bars in this histogram, for this case, should ideally all be of equal height. - If the first bar in this histogram is especially high (for the p-value case), that means that many tests are being judged as dependent. For checking the dependent distribution, one hopes that this list is non-empty, in which case this first bar will be especially high, since high p-values are for examples where the graph is unfaithful to the distribution. These are likely for for cases where paths in the graph cancel unfaithfully. But for checking Markov, one hopes that this first bar will be the same height as all of the other bars. + If the first bar in this histogram is especially high (for the p-value case), that means that many tests are being judged as dependent. For checking the dependent distribution, one hopes that this list is non-empty, in which case this first bar will be especially high since high p-values are examples where the graph is unfaithful to the distribution. These are possibly for cases where paths in the graph cancel unfaithfully. But for checking Markov, one hopes that this first bar will be the same height as all of the other bars. - To make it especially clear, we give two statistics in the interface. The first is the percentage of p-values judged dependent on the test. If an alpha level is used in the test, this number should be very close to the alpha level for the Local Markov check since the distribution of p-values under this condition is Uniform. For the second, we test the Uniformity of the p-values using a Kolmogorov-Smirnov test. The p-value returned by this test should be greater than the user’s preferred alpha level if the distribution of p-values is Uniform and less then this alpha level if the distribution of p-values is non-Uniform. + To make it especially clear, we give two statistics in the interface. The first is the percentage of p-values judged dependent on the test. If an alpha level is used in the test, this number should be very close to the alpha level for the Local Markov check since the distribution of p-values under this condition is Uniform. For the second, we test the Uniformity of the p-values using a Kolmogorov-Smirnov test. The p-value returned by this test should be greater than the user’s preferred alpha level if the distribution of p-values is Uniform and less than this alpha level if the distribution of p-values is non-uniform. If the independence test yields a bump in the score, this score should be negative for independence judgments and positive for dependence judgments. The histogram will reflect this. Feel free to select all of the data in the tables, copy it, and paste it into a text file or into Excel. This will let you analyze the data yourself. - A note about Markov Blankets: The "Markov Blanket" conditioning set choice implements the Markov blanket calculation in a way that is correct for DAGs, CPDAGs, MAGs, and PAGs. For all of these graph types, the list of m-connecting facts in the Faithfulness tab should be empty, since the Markov blanket should screen off the target from any other variables in the dataset. It's possible that for some other graph types this list may not be empty (i.e., the Markov blanket calculation may not be correct)."""; + A note about Markov Blankets: The "Markov Blanket" conditioning set choice implements the Markov blanket calculation in a way that is correct for DAGs, CPDAGs, MAGs, and PAGs. For all of these graph types, the list of m-connecting facts in the Faithfulness tab should be empty, since the Markov blanket should screen off the target from any other variables in the dataset. It's possible that for some other graph types, this list may not be empty (i.e., the Markov blanket calculation may not be correct). + """; } @NotNull From 7a1729d41524d4f4e3f49c29ad70ca0e9808ed46 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Tue, 23 Jan 2024 23:13:41 -0500 Subject: [PATCH 105/163] Cleanup,. --- .../tetradapp/editor/MarkovCheckEditor.java | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java index c1cef7329e..96472c8769 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java @@ -316,22 +316,24 @@ public void watch() { @NotNull private static String getHelpMessage() { return """ - This tool lets you plot statistics for independence tests of a pair of variables given some conditioning calculated for one of those variables, for a given graph and dataset. Two tables are made, one in which the independence facts predicted by the graph using these conditioning sets are tested in the data and the other in which the graph's predicted dependence facts are tested. The first of these sets is a check for "Markov" (a check for implied independence facts) for the chosen conditioning sets; the is a check of the "Dependent Distribution." (a check of implied dependence facts)” + This tool lets you plot statistics for independence tests of a pair of variables given some conditioning calculated for one of those variables, for a given graph and dataset. Two tables are made, one in which the independence facts predicted by the graph using these conditioning sets are tested in the data and the other in which the graph's predicted dependence facts are tested. The first of these sets is a check for "Markov" (a check for implied independence facts) for the chosen conditioning sets; the is a check of the "Dependent Distribution." (a check of implied dependence facts)” - Each table gives columns for the independence fact being checked, its test result, and its statistic. This statistic is either a p-value, ranging from 0 to 1, where p-values above the alpha level of the test are judged as independent, or a score bump, where this bump is negative for independent judgments and positive for dependent judgments. + Each table gives columns for the independence fact being checked, its test result, and its statistic. This statistic is either a p-value, ranging from 0 to 1, where p-values above the alpha level of the test are judged as independent, or a score bump, where this bump is negative for independent judgments and positive for dependent judgments. - If the independence test yields a p-value, as for instance, for the Fisher Z test (for the linear, Gaussian case) or else the Chi-Square test (for the multinomial case), then under the null hypothesis of independence and for a consistent test, these p-values should be distributed as Uniform(0, 1). That is, it should be just as likely to see p-values in any range of equal width. If the test is inconsistent or the graph is incorrect (i.e., the parents of some or all of the nodes in the graph are incorrect), then this distribution of p-values will not be Uniform. To visualize this, we display the histogram of the p-values with equally sized bins; the bars in this histogram, for this case, should ideally all be of equal height. + If the independence test yields a p-value, as for instance, for the Fisher Z test (for the linear, Gaussian case) or else the Chi-Square test (for the multinomial case), then under the null hypothesis of independence and for a consistent test, these p-values should be distributed as Uniform(0, 1). That is, it should be just as likely to see p-values in any range of equal width. If the test is inconsistent or the graph is incorrect (i.e., the parents of some or all of the nodes in the graph are incorrect), then this distribution of p-values will not be Uniform. To visualize this, we display the histogram of the p-values with equally sized bins; the bars in this histogram, for this case, should ideally all be of equal height. - If the first bar in this histogram is especially high (for the p-value case), that means that many tests are being judged as dependent. For checking the dependent distribution, one hopes that this list is non-empty, in which case this first bar will be especially high since high p-values are examples where the graph is unfaithful to the distribution. These are possibly for cases where paths in the graph cancel unfaithfully. But for checking Markov, one hopes that this first bar will be the same height as all of the other bars. + If the first bar in this histogram is especially high (for the p-value case), that means that many tests are being judged as dependent. For checking the dependent distribution, one hopes that this list is non-empty, in which case this first bar will be especially high since high p-values are examples where the graph is unfaithful to the distribution. These are possibly for cases where paths in the graph cancel unfaithfully. But for checking Markov, one hopes that this first bar will be the same height as all of the other bars. - To make it especially clear, we give two statistics in the interface. The first is the percentage of p-values judged dependent on the test. If an alpha level is used in the test, this number should be very close to the alpha level for the Local Markov check since the distribution of p-values under this condition is Uniform. For the second, we test the Uniformity of the p-values using a Kolmogorov-Smirnov test. The p-value returned by this test should be greater than the user’s preferred alpha level if the distribution of p-values is Uniform and less than this alpha level if the distribution of p-values is non-uniform. + To make it especially clear, we give two statistics in the interface. The first is the percentage of p-values judged dependent on the test. If an alpha level is used in the test, this number should be very close to the alpha level for the Local Markov check since the distribution of p-values under this condition is Uniform. For the second, we test the Uniformity of the p-values using a Kolmogorov-Smirnov test. The p-value returned by this test should be greater than the user’s preferred alpha level if the distribution of p-values is Uniform and less than this alpha level if the distribution of p-values is non-uniform. - If the independence test yields a bump in the score, this score should be negative for independence judgments and positive for dependence judgments. The histogram will reflect this. + If the independence test yields a bump in the score, this score should be negative for independence judgments and positive for dependence judgments. The histogram will reflect this. - Feel free to select all of the data in the tables, copy it, and paste it into a text file or into Excel. This will let you analyze the data yourself. + Feel free to select all of the data in the tables, copy it, and paste it into a text file or into Excel. This will let you analyze the data yourself. - A note about Markov Blankets: The "Markov Blanket" conditioning set choice implements the Markov blanket calculation in a way that is correct for DAGs, CPDAGs, MAGs, and PAGs. For all of these graph types, the list of m-connecting facts in the Faithfulness tab should be empty, since the Markov blanket should screen off the target from any other variables in the dataset. It's possible that for some other graph types, this list may not be empty (i.e., the Markov blanket calculation may not be correct). - """; + A note about Markov Blankets: The "Markov Blanket" conditioning set choice implements the Markov blanket calculation in a way that is correct for DAGs, CPDAGs, MAGs, and PAGs. For all of these graph types, the list of m-connecting facts in the Faithfulness tab should be empty, since the Markov blanket should screen off the target from any other variables in the dataset. It's possible that for some other graph types, this list may not be empty (i.e., the Markov blanket calculation may not be correct). + + Knowledge may be supplied to the Markov Checker. This will be interpreted as follows. For X _||_ Y | Z checked, X and Y will be drawn from the last tier of the knowledge, and the variables in Z will be drawn from all variables in tiers. Additional forbidden or required edges are not allowed. + """; } @NotNull From 65ce8f0fc19e2367a10cad49e6bff7a9e03416af Mon Sep 17 00:00:00 2001 From: jdramsey Date: Tue, 23 Jan 2024 23:16:37 -0500 Subject: [PATCH 106/163] Cleanup,. --- .../main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java index 96472c8769..40bafc1abe 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java @@ -314,7 +314,7 @@ public void watch() { } @NotNull - private static String getHelpMessage() { + public static String getHelpMessage() { return """ This tool lets you plot statistics for independence tests of a pair of variables given some conditioning calculated for one of those variables, for a given graph and dataset. Two tables are made, one in which the independence facts predicted by the graph using these conditioning sets are tested in the data and the other in which the graph's predicted dependence facts are tested. The first of these sets is a check for "Markov" (a check for implied independence facts) for the chosen conditioning sets; the is a check of the "Dependent Distribution." (a check of implied dependence facts)” From 73083737fb8e1ac697bc2f0ddf86e2d5d50fd6cb Mon Sep 17 00:00:00 2001 From: jdramsey Date: Wed, 24 Jan 2024 10:40:00 -0500 Subject: [PATCH 107/163] Caught the event of a desktop being quit in the interface (as with command-Q on a Mac, which could not be handled in earlier versions), now displaying a confirm dialog. Updated the saving/loading code in the interface to be a bit more smooth. --- .../main/java/edu/cmu/tetradapp/Tetrad.java | 19 ++++++++++++++ .../cmu/tetradapp/app/CloseSessionAction.java | 9 +------ .../cmu/tetradapp/app/SaveSessionAction.java | 15 +++++------ .../tetradapp/app/SaveSessionAsAction.java | 25 +++++++------------ .../edu/cmu/tetradapp/app/TetradDesktop.java | 24 +++++++++--------- 5 files changed, 47 insertions(+), 45 deletions(-) diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/Tetrad.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/Tetrad.java index 6341e1a9c1..7da559aa99 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/Tetrad.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/Tetrad.java @@ -23,6 +23,9 @@ import edu.cmu.tetrad.util.JOptionUtils; import edu.cmu.tetrad.util.TetradLogger; import edu.cmu.tetrad.util.Version; +import edu.cmu.tetradapp.app.CloseSessionAction; +import edu.cmu.tetradapp.app.SaveSessionAction; +import edu.cmu.tetradapp.app.SaveSessionAsAction; import edu.cmu.tetradapp.app.TetradDesktop; import edu.cmu.tetradapp.util.DesktopController; import edu.cmu.tetradapp.util.ImageUtils; @@ -198,6 +201,22 @@ public void windowClosing(WindowEvent e) { SplashScreen.hide(); + if (Desktop.isDesktopSupported()) { + Desktop desktop = Desktop.getDesktop(); + desktop.setQuitHandler((e2, response) -> { +// if (!SaveSessionAsAction.saved || !SaveSessionAction.saved) { + int result = JOptionPane.showConfirmDialog(null, + "Are you sure you want to quit? Any unsaved work will be lost.", + "Confirm Quit", JOptionPane.YES_NO_OPTION); + if (result == JOptionPane.YES_OPTION) { + response.performQuit(); + } else { + response.cancelQuit(); + } +// } + }); + } + } /** diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/app/CloseSessionAction.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/app/CloseSessionAction.java index d091485332..221cf4c4fd 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/app/CloseSessionAction.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/app/CloseSessionAction.java @@ -34,9 +34,7 @@ * * @author josephramsey */ -final class CloseSessionAction extends AbstractAction { - - private boolean saved; +public final class CloseSessionAction extends AbstractAction { /** * Creates a new close session action for the given desktop. @@ -70,7 +68,6 @@ public void actionPerformed(ActionEvent e) { if (response == JOptionPane.YES_OPTION) { SaveSessionAction saveSessionAction = new SaveSessionAction(); saveSessionAction.actionPerformed(e); - this.saved = saveSessionAction.isSaved(); } else if (response == JOptionPane.CANCEL_OPTION) { return; } @@ -89,10 +86,6 @@ public void actionPerformed(ActionEvent e) { public String toString() { return "Close session action."; } - - public boolean isSaved() { - return this.saved; - } } diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/app/SaveSessionAction.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/app/SaveSessionAction.java index 34e238a73c..454e7a5bef 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/app/SaveSessionAction.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/app/SaveSessionAction.java @@ -31,6 +31,7 @@ import java.awt.event.ActionEvent; import java.io.IOException; import java.io.ObjectOutputStream; +import java.io.Serial; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -42,11 +43,12 @@ * @author josephramsey * @author Kevin V. Bui (kvb2@pitt.edu) */ -final class SaveSessionAction extends AbstractAction { +public final class SaveSessionAction extends AbstractAction { + @Serial private static final long serialVersionUID = -1812370698394158108L; - private boolean saved; + public static boolean saved = false; public SaveSessionAction() { super("Save Session"); @@ -69,7 +71,7 @@ public void actionPerformed(ActionEvent e) { if (Files.notExists(outputFile) || sessionWrapper.isNewSession()) { SaveSessionAsAction saveSessionAsAction = new SaveSessionAsAction(); saveSessionAsAction.actionPerformed(e); - this.saved = saveSessionAsAction.isSaved(); + saved = SaveSessionAsAction.saved; return; } @@ -80,7 +82,7 @@ public void actionPerformed(ActionEvent e) { if (ret == JOptionPane.NO_OPTION) { SaveSessionAsAction saveSessionAsAction = new SaveSessionAsAction(); saveSessionAsAction.actionPerformed(e); - this.saved = saveSessionAsAction.isSaved(); + saved = SaveSessionAsAction.saved; return; } @@ -110,9 +112,4 @@ public void watch() throws InterruptedException { new MyWatchedProceess(); } - - public boolean isSaved() { - return this.saved; - } - } diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/app/SaveSessionAsAction.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/app/SaveSessionAsAction.java index 4a24898ffb..24e7173c9c 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/app/SaveSessionAsAction.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/app/SaveSessionAsAction.java @@ -33,6 +33,7 @@ import java.io.File; import java.io.IOException; import java.io.ObjectOutputStream; +import java.io.Serial; import java.nio.file.Files; import java.util.prefs.Preferences; @@ -41,11 +42,12 @@ * * @author josephramsey */ -final class SaveSessionAsAction extends AbstractAction { +public final class SaveSessionAsAction extends AbstractAction { + @Serial private static final long serialVersionUID = 2798487128341621686L; - private boolean saved; + public static boolean saved = false; public SaveSessionAsAction() { super("Save Session As..."); @@ -71,14 +73,14 @@ public void actionPerformed(ActionEvent e) { JOptionUtils.centeringComp(), true, "Save Session As...", sessionSaveLocation); if (file == null) { - this.saved = false; + saved = false; return; } if ((DesktopController.getInstance().existsSessionByName( file.getName()) && !(sessionWrapper.getName().equals(file.getName())))) { - this.saved = false; + saved = false; JOptionPane.showMessageDialog(JOptionUtils.centeringComp(), "Another session by that name is currently open. Please " + "\nclose that session first."); @@ -93,20 +95,19 @@ class MyWatchedProceess extends WatchedProcess { @Override public void watch() throws InterruptedException { try (ObjectOutputStream objOut = new ObjectOutputStream(Files.newOutputStream(file.toPath()))) { + saved = false; objOut.writeObject(metadata); objOut.writeObject(sessionWrapper); sessionWrapper.setSessionChanged(false); sessionWrapper.setNewSession(false); - setSaved(true); -// this.saved = true; + saved = true; } catch (IOException exception) { exception.printStackTrace(System.err); JOptionPane.showMessageDialog(JOptionUtils.centeringComp(), "An error occurred while attempting to save the session."); - setSaved(false); -// this.saved = false; + saved = false; } DesktopController.getInstance().putMetadata(sessionWrapper, metadata); @@ -134,12 +135,4 @@ public void watch() throws InterruptedException { // DesktopController.getInstance().putMetadata(sessionWrapper, metadata); // sessionEditor.firePropertyChange("name", null, file.getName()); } - - public boolean isSaved() { - return this.saved; - } - - public void setSaved(boolean saved) { - this.saved = saved; - } } diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/app/TetradDesktop.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/app/TetradDesktop.java index 36118f24ae..9b720d2220 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/app/TetradDesktop.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/app/TetradDesktop.java @@ -449,18 +449,18 @@ public boolean closeAllSessions() { action.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "Dummy close action")); - if (!action.isSaved()) { - int ret2 = JOptionPane - .showConfirmDialog( - JOptionUtils.centeringComp(), - "This session was not saved. Close session and continue anyway?", - "Advise needed...", - JOptionPane.OK_CANCEL_OPTION); - - if (ret2 == JOptionPane.CANCEL_OPTION) { - return false; - } - } +// if (!SaveSessionAction.saved) { +// int ret2 = JOptionPane +// .showConfirmDialog( +// JOptionUtils.centeringComp(), +// "This session was not saved. Close session and continue anyway?", +// "Advise needed...", +// JOptionPane.OK_CANCEL_OPTION); +// +// if (ret2 == JOptionPane.CANCEL_OPTION) { +// return false; +// } +// } closeFrontmostSession(); } From 023bbfb20a74c485a5b1d53dd873c5213fef9bff Mon Sep 17 00:00:00 2001 From: jdramsey Date: Wed, 24 Jan 2024 10:55:41 -0500 Subject: [PATCH 108/163] Cleanup. --- .../main/java/edu/cmu/tetradapp/Tetrad.java | 32 ++++-------- .../cmu/tetradapp/app/SaveSessionAction.java | 2 +- .../tetradapp/app/SaveSessionAsAction.java | 24 ++------- .../edu/cmu/tetradapp/app/TetradDesktop.java | 50 +++++++------------ .../edu/cmu/tetrad/search/MarkovCheck.java | 12 ++--- 5 files changed, 38 insertions(+), 82 deletions(-) diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/Tetrad.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/Tetrad.java index 7da559aa99..eb96d283ea 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/Tetrad.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/Tetrad.java @@ -23,14 +23,10 @@ import edu.cmu.tetrad.util.JOptionUtils; import edu.cmu.tetrad.util.TetradLogger; import edu.cmu.tetrad.util.Version; -import edu.cmu.tetradapp.app.CloseSessionAction; -import edu.cmu.tetradapp.app.SaveSessionAction; -import edu.cmu.tetradapp.app.SaveSessionAsAction; import edu.cmu.tetradapp.app.TetradDesktop; import edu.cmu.tetradapp.util.DesktopController; import edu.cmu.tetradapp.util.ImageUtils; import edu.cmu.tetradapp.util.SplashScreen; -import org.apache.commons.math3.util.FastMath; import javax.swing.*; import java.awt.*; @@ -38,6 +34,7 @@ import java.awt.event.WindowEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; +import java.io.Serial; import java.util.Locale; import java.util.prefs.Preferences; @@ -121,7 +118,7 @@ private static void setLookAndFeel() { UIManager.getSystemLookAndFeelClassName()); } } catch (Exception e) { - e.printStackTrace(); + TetradLogger.getInstance().forceLogMessage("Couldn't set look and feel."); } } @@ -157,15 +154,11 @@ private void launchFrame() { // order are important. jdramsey 12/14/02 this.frame = new JFrame(this.mainTitle) { + @Serial private static final long serialVersionUID = -9077349253115802418L; @Override public Dimension getPreferredSize() { -// Dimension size = Toolkit.getDefaultToolkit().getScreenSize(); -// double minLength = FastMath.min(size.getWidth(), size.getHeight()); -// double height = minLength * 0.8; -// double width = height * (4.0 / 3); -// return new Dimension((int) width, (int) height); return Toolkit.getDefaultToolkit().getScreenSize(); } @@ -204,19 +197,16 @@ public void windowClosing(WindowEvent e) { if (Desktop.isDesktopSupported()) { Desktop desktop = Desktop.getDesktop(); desktop.setQuitHandler((e2, response) -> { -// if (!SaveSessionAsAction.saved || !SaveSessionAction.saved) { - int result = JOptionPane.showConfirmDialog(null, - "Are you sure you want to quit? Any unsaved work will be lost.", - "Confirm Quit", JOptionPane.YES_NO_OPTION); - if (result == JOptionPane.YES_OPTION) { - response.performQuit(); - } else { - response.cancelQuit(); - } -// } + int result = JOptionPane.showConfirmDialog(null, + "Are you sure you want to quit? Any unsaved work will be lost.", + "Confirm Quit", JOptionPane.YES_NO_OPTION); + if (result == JOptionPane.YES_OPTION) { + response.performQuit(); + } else { + response.cancelQuit(); + } }); } - } /** diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/app/SaveSessionAction.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/app/SaveSessionAction.java index 454e7a5bef..0571573b3e 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/app/SaveSessionAction.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/app/SaveSessionAction.java @@ -91,7 +91,7 @@ public void actionPerformed(ActionEvent e) { class MyWatchedProceess extends WatchedProcess { @Override - public void watch() throws InterruptedException { + public void watch() { try (ObjectOutputStream objOut = new ObjectOutputStream(Files.newOutputStream(outputFile))) { sessionWrapper.setNewSession(false); objOut.writeObject(metadata); diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/app/SaveSessionAsAction.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/app/SaveSessionAsAction.java index 24e7173c9c..5e0a85a2ca 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/app/SaveSessionAsAction.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/app/SaveSessionAsAction.java @@ -90,10 +90,10 @@ public void actionPerformed(ActionEvent e) { sessionWrapper.setName(file.getName()); sessionEditor.setName(file.getName()); - class MyWatchedProceess extends WatchedProcess { + class MyWatchedProcess extends WatchedProcess { @Override - public void watch() throws InterruptedException { + public void watch() { try (ObjectOutputStream objOut = new ObjectOutputStream(Files.newOutputStream(file.toPath()))) { saved = false; objOut.writeObject(metadata); @@ -115,24 +115,6 @@ public void watch() throws InterruptedException { } } - new MyWatchedProceess(); - -// try (ObjectOutputStream objOut = new ObjectOutputStream(Files.newOutputStream(file.toPath()))) { -// objOut.writeObject(metadata); -// objOut.writeObject(sessionWrapper); -// -// sessionWrapper.setSessionChanged(false); -// sessionWrapper.setNewSession(false); -// this.saved = true; -// } catch (IOException exception) { -// exception.printStackTrace(System.err); -// -// JOptionPane.showMessageDialog(JOptionUtils.centeringComp(), -// "An error occurred while attempting to save the session."); -// this.saved = false; -// } -// -// DesktopController.getInstance().putMetadata(sessionWrapper, metadata); -// sessionEditor.firePropertyChange("name", null, file.getName()); + new MyWatchedProcess(); } } diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/app/TetradDesktop.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/app/TetradDesktop.java index 9b720d2220..61356c1932 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/app/TetradDesktop.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/app/TetradDesktop.java @@ -40,6 +40,7 @@ import java.awt.event.ActionEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; +import java.io.Serial; import java.util.List; import java.util.*; import java.util.prefs.Preferences; @@ -54,6 +55,7 @@ public final class TetradDesktop extends JPanel implements DesktopControllable, PropertyChangeListener { + @Serial private static final long serialVersionUID = -3415072280557904460L; /** @@ -62,14 +64,14 @@ public final class TetradDesktop extends JPanel implements DesktopControllable, private static final int MARGIN = 0; /** - * The desktop pane in which all of the session editors are located. + * The desktop pane in which all the session editors are located. */ private final JDesktopPane desktopPane; /** * Stores a list of keys for components added to the workbench. */ - private final List sessionNodeKeys; + private final List sessionNodeKeys; /** * A map from components in the desktop to the frames they're embedded in. @@ -190,7 +192,7 @@ public void addSessionEditor(SessionEditorIndirectRef editorRef) { } /** - * Adds the given componet to the given layer. + * Adds the given component to the given layer. */ public void addEditorWindow(EditorWindowIndirectRef windowRef, int layer) { EditorWindow window = (EditorWindow) windowRef; @@ -236,7 +238,7 @@ public void addEditorWindow(EditorWindowIndirectRef windowRef, int layer) { window.setLocation(x, y); window.setPreferredSize(new Dimension(width, height)); - // This line sometimes hangs, so I'm putting it in a watched process + // This line sometimes hangs, so I'm putting it in a watched process, // so it can be stopped by the user. Not ideal. // Window owner = (Window) getTopLevelAncestor(); // @@ -294,8 +296,7 @@ public void closeEmptySessions() { for (JInternalFrame frame : frames) { Object o = frame.getContentPane().getComponents()[0]; - if (o instanceof SessionEditor) { - SessionEditor sessionEditor = (SessionEditor) o; + if (o instanceof SessionEditor sessionEditor) { SessionEditorWorkbench workbench = sessionEditor .getSessionWorkbench(); Graph graph = workbench.getGraph(); @@ -313,9 +314,7 @@ public boolean existsSessionByName(String name) { for (JInternalFrame allFrame : allFrames) { Object o = allFrame.getContentPane().getComponents()[0]; - if (o instanceof SessionEditor) { - SessionEditor editor = (SessionEditor) o; - + if (o instanceof SessionEditor editor) { String editorName = editor.getName(); if (editorName.equals(name)) { return true; @@ -333,9 +332,7 @@ public Session getSessionByName(String name) { for (JInternalFrame allFrame : allFrames) { Object o = allFrame.getContentPane().getComponents()[0]; - if (o instanceof SessionEditor) { - SessionEditor editor = (SessionEditor) o; - + if (o instanceof SessionEditor editor) { String editorName = editor.getName(); if (editorName.equals(name)) { return editor.getSessionWorkbench().getSessionWrapper() @@ -380,14 +377,14 @@ public void propertyChange(PropertyChangeEvent e) { } } } else if ("closeFrame".equals(e.getPropertyName())) { - if (getFramesMap().containsKey(e.getSource())) { - JInternalFrame frame = getFramesMap().get(e.getSource()); + if (getFramesMap().containsKey((SessionEditor) e.getSource())) { + JInternalFrame frame = getFramesMap().get((SessionEditor) e.getSource()); frame.setVisible(false); frame.dispose(); } } else if ("name".equals(e.getPropertyName())) { - if (getFramesMap().containsKey(e.getSource())) { - JInternalFrame frame = getFramesMap().get(e.getSource()); + if (getFramesMap().containsKey((SessionEditor) e.getSource())) { + JInternalFrame frame = getFramesMap().get((SessionEditor) e.getSource()); String _name = (String) (e.getNewValue()); frame.setTitle(_name); setMainTitle(_name); @@ -413,7 +410,7 @@ public JDesktopPane getDesktopPane() { } /** - * Queries the user as to whether they would like to save their sessions. + * Queries the user whether they would like to save their sessions. * * @return true if the transaction was ended successfully, false if not (that is, canceled). */ @@ -449,19 +446,6 @@ public boolean closeAllSessions() { action.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "Dummy close action")); -// if (!SaveSessionAction.saved) { -// int ret2 = JOptionPane -// .showConfirmDialog( -// JOptionUtils.centeringComp(), -// "This session was not saved. Close session and continue anyway?", -// "Advise needed...", -// JOptionPane.OK_CANCEL_OPTION); -// -// if (ret2 == JOptionPane.CANCEL_OPTION) { -// return false; -// } -// } - closeFrontmostSession(); } @@ -495,15 +479,15 @@ public boolean isDisplayLogging() { /** * Sets whether the display log output should be displayed or not. If true then a text area roughly 20% of the * screen size will appear on the bottom and will display any log output, otherwise just the standard tetrad - * workbend is shown. + * workbench is shown. */ public void setDisplayLogging(boolean displayLogging) { if (displayLogging) { try { TetradLogger.getInstance().setNextOutputStream(); } catch (IllegalStateException e2) { - // TetradLogger.getInstance().removeNextOutputStream(); - e2.printStackTrace(); + TetradLogger.getInstance().forceLogMessage( + "Unable to setup logging, please restart Tetrad."); return; } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java index ac7ef9f8e7..c0c6153513 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java @@ -80,7 +80,7 @@ public class MarkovCheck { // The percentage of all samples to use when resampling for each conditional independence test. private double percentResample = 0.5; // The number of tests for the independent case. - private int numTestsindep = 0; + private int numTestsIndep = 0; // The number of tests for the dependent case. private int numTestsDep = 0; // A knowledge object to specify independence and conditioning ranges. Empty by default. @@ -106,9 +106,9 @@ public MarkovCheck(Graph graph, IndependenceTest independenceTest, ConditioningS } /** - * Returns the set of independence facts used in the Markov check, for dsepation and dconnection separately. + * Returns the set of independence facts used in the Markov check, for dseparation and dconnection separately. * - * @return The set of independence facts used in the Markov check, for dsepation and dconnection separately. + * @return The set of independence facts used in the Markov check, for dseparation and dconnection separately. */ @NotNull public AllSubsetsIndependenceFacts getAllSubsetsIndependenceFacts() { @@ -264,7 +264,7 @@ public void generateResults() { generateResults(msep, true); generateResults(mconn, false); - this.numTestsindep = msep.size(); + this.numTestsIndep = msep.size(); this.numTestsDep = mconn.size(); } @@ -424,7 +424,7 @@ public double getBinomialPValue(boolean indep) { */ public int getNumTests(boolean indep) { if (indep) { - return numTestsindep; + return numTestsIndep; } else { return numTestsDep; } @@ -709,7 +709,7 @@ private void generateResultsAllSubsets(Set msep, Set Date: Wed, 24 Jan 2024 11:05:48 -0500 Subject: [PATCH 109/163] Cleanup. --- .../main/java/edu/cmu/tetradapp/Tetrad.java | 30 ++++++++--------- .../tetradapp/editor/MarkovCheckEditor.java | 6 ++-- .../editor/search/AlgorithmCard.java | 32 +++++++++---------- .../tetradapp/ui/model/AlgorithmModel.java | 8 ++--- .../tetradapp/ui/model/AlgorithmModels.java | 6 ++-- .../ui/model/IndependenceTestModel.java | 6 ++-- .../ui/model/IndependenceTestModels.java | 4 +-- .../cmu/tetradapp/ui/model/ScoreModel.java | 6 ++-- .../cmu/tetradapp/ui/model/ScoreModels.java | 4 +-- .../annotation/AbstractAnnotations.java | 4 +-- .../cmu/tetrad/annotation/AnnotatedClass.java | 23 ++++++------- .../annotation/AnnotatedClassUtils.java | 2 +- .../edu/cmu/tetrad/search/MarkovCheck.java | 20 ++++++------ .../tetrad/util/AlgorithmDescriptions.java | 2 +- .../util/IndependenceTestDescriptions.java | 2 +- .../cmu/tetrad/util/ScoreDescriptions.java | 2 +- .../annotation/AlgorithmAnnotationsTest.java | 4 +-- .../annotation/ScoreAnnotationsTest.java | 4 +-- .../TestOfIndependenceAnnotationsTest.java | 4 +-- 19 files changed, 83 insertions(+), 86 deletions(-) diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/Tetrad.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/Tetrad.java index eb96d283ea..35a6b45a03 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/Tetrad.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/Tetrad.java @@ -77,11 +77,11 @@ public Tetrad() { * Launches Tetrad as an application. One way to launch Tetrad IV as an application is the following:> 0 *
                java -cp jarname.jar INSTANCE.Tetrad
                *

                - * where "jarname.jar" is a jar containing all of the classes of Tetrad IV, properly compiled, along with all of the - * auxiliary jar contents and all of the images which Tetrad IV uses, all in their proper relative directories.> + * where "jarname.jar" is a jar containing all the classes of Tetrad IV, properly compiled, along with all the + * auxiliary jar contents and all the images which Tetrad IV uses, all in their proper relative directories.> * 0 * - * @param argv --skip-latest argument will skip checking for latest version. + * @param argv --skip-latest argument will skip checking for the latest version. */ public static void main(String[] argv) { if (argv != null && argv.length > 0) { @@ -96,7 +96,7 @@ public static void main(String[] argv) { // This is needed to get numbers to be parsed and rendered uniformly, especially in the interface. Locale.setDefault(Locale.US); - // Check if we should skip checking for latest version + // Check if we should skip checking for the latest version SplashScreen.show("Loading Tetrad...", 1000); EventQueue.invokeLater(() -> new Tetrad().launchFrame()); @@ -108,12 +108,6 @@ private static void setLookAndFeel() { try { String os = System.getProperties().getProperty("os.name"); if (os.equals("Windows XP")) { - // The only system look and feel that seems to work well is the - // one for Windows XP. When running on Mac the mac look and - // feel is forced. The new look (synth or whatever it's called) - // and feel for linux on 1.5 looks - // pretty bad, so it shouldn't be used. - // By default, linux will use the metal look and feel. UIManager.setLookAndFeel( UIManager.getSystemLookAndFeelClassName()); } @@ -146,12 +140,14 @@ private void launchFrame() { JOptionUtils.setCenteringComp(getDesktop()); DesktopController.setReference(getDesktop()); - // Set up the frame. Note the order in which the next few steps - // happen. First, the frame is given a preferred size, so that if - // someone unmaximizes it, it doesn't shrivel up to the top left - // corner. Next, the content pane is set. Next, it is packed. Finally, - // it is maximized. For some reason, most of the details of this - // order are important. jdramsey 12/14/02 + /* + This sets up the frame. Note the order in which the next few steps + happen. First, the frame is given a preferred size, so that if + someone unmaximizes it, it doesn't shrivel up to the top left + corner. Next, the content pane is set. Next, it is packed. Finally, + it is maximized. For some reason, most of the details of this + order are important. Jdramsey 12/14/02 + */ this.frame = new JFrame(this.mainTitle) { @Serial @@ -166,7 +162,7 @@ public Dimension getPreferredSize() { // Fixing a bug caused by switch to Oracle Java (at least for Mac), although I must say the following // code is what should have worked to begin with. Bug was that sessions would appear only in the lower - // left hand corner of the screen. + // left-hand corner of the screen. this.frame.setPreferredSize(Toolkit.getDefaultToolkit().getScreenSize()); getFrame().setContentPane(getDesktop()); diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java index 40bafc1abe..f36ddbf623 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java @@ -377,7 +377,7 @@ private void refreshResult(MarkovCheckIndTestModel model, DoubleTextField percen private void setTest() { IndependenceTestModel selectedItem = (IndependenceTestModel) indTestJComboBox.getSelectedItem(); Class clazz = (selectedItem == null) ? null - : selectedItem.getIndependenceTest().getClazz(); + : selectedItem.getIndependenceTest().clazz(); IndependenceTest independenceTest; if (clazz != null) { @@ -1007,11 +1007,11 @@ private JPanel createParamsPanel(Set params, Parameters parameters) { } private Map createParameterComponents(Set params, Parameters parameters) { - ParamDescriptions paramDescs = ParamDescriptions.getInstance(); + ParamDescriptions paramDescriptions = ParamDescriptions.getInstance(); return params.stream() .collect(Collectors.toMap( Function.identity(), - e -> createParameterComponent(e, parameters, paramDescs.get(e)), + e -> createParameterComponent(e, parameters, paramDescriptions.get(e)), (u, v) -> { throw new IllegalStateException(String.format("Duplicate key %s.", u)); }, diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/search/AlgorithmCard.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/search/AlgorithmCard.java index ae9fafc127..dcca62b761 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/search/AlgorithmCard.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/search/AlgorithmCard.java @@ -376,9 +376,9 @@ public void saveStates() { * @return Algorithm */ public Algorithm getAlgorithmFromInterface(AlgorithmModel algoModel, IndependenceTestModel indTestModel, ScoreModel scoreModel) { - Class algoClass = algoModel.getAlgorithm().getClazz(); - Class indTestClass = (indTestModel == null) ? null : indTestModel.getIndependenceTest().getClazz(); - Class scoreClass = (scoreModel == null) ? null : scoreModel.getScore().getClazz(); + Class algoClass = algoModel.getAlgorithm().clazz(); + Class indTestClass = (indTestModel == null) ? null : indTestModel.getIndependenceTest().clazz(); + Class scoreClass = (scoreModel == null) ? null : scoreModel.getScore().clazz(); Algorithm algorithm = null; @@ -406,19 +406,19 @@ public boolean isAllValid() { boolean missingScore = algoModel.isRequiredScore() && (scoreModel == null); if (missingTest && missingScore) { String msg = String.format("%s requires both test and score.", - algoModel.getAlgorithm().getAnnotation().name()); + algoModel.getAlgorithm().annotation().name()); JOptionPane.showMessageDialog(this.desktop, msg, "Please Note", JOptionPane.INFORMATION_MESSAGE); return false; } else if (missingTest) { String msg = String.format("%s requires independence test.", - algoModel.getAlgorithm().getAnnotation().name()); + algoModel.getAlgorithm().annotation().name()); JOptionPane.showMessageDialog(this.desktop, msg, "Please Note", JOptionPane.INFORMATION_MESSAGE); return false; } else if (missingScore) { String msg = String.format("%s requires score.", - algoModel.getAlgorithm().getAnnotation().name()); + algoModel.getAlgorithm().annotation().name()); JOptionPane.showMessageDialog(this.desktop, msg, "Please Note", JOptionPane.INFORMATION_MESSAGE); return false; @@ -433,7 +433,7 @@ private void validateAlgorithmOption() { firePropertyChange("algoFwdBtn", null, true); AlgorithmModel algoModel = this.algorithmList.getSelectedValue(); - Class algoClass = algoModel.getAlgorithm().getClazz(); + Class algoClass = algoModel.getAlgorithm().clazz(); if (algoClass.isAnnotationPresent(Nonexecutable.class)) { String msg; @@ -476,7 +476,7 @@ private void validateAlgorithmOption() { } // SVAR (SvarFci, SvarGfci) algorithms need lagged data - String cmd = algoModel.getAlgorithm().getAnnotation().command(); + String cmd = algoModel.getAlgorithm().annotation().command(); if (cmd.equalsIgnoreCase("ts-fci") || cmd.equalsIgnoreCase("ts-gfci") || cmd.equalsIgnoreCase("ts-imgs")) { @@ -502,7 +502,7 @@ private void refreshAlgorithmList() { if ("all".equals(algoType)) { if (this.knowledgeChkBox.isSelected()) { algorithmModels.getModels(this.dataType, this.multiDataAlgo).stream() - .filter(e -> HasKnowledge.class.isAssignableFrom(e.getAlgorithm().getClazz())) + .filter(e -> HasKnowledge.class.isAssignableFrom(e.getAlgorithm().clazz())) .forEach(e -> this.algoModels.addElement(e)); } else { algorithmModels.getModels(this.dataType, this.multiDataAlgo).stream() @@ -511,7 +511,7 @@ private void refreshAlgorithmList() { } else { if (this.knowledgeChkBox.isSelected()) { algorithmModels.getModels(AlgType.valueOf(algoType), this.dataType, this.multiDataAlgo).stream() - .filter(e -> HasKnowledge.class.isAssignableFrom(e.getAlgorithm().getClazz())) + .filter(e -> HasKnowledge.class.isAssignableFrom(e.getAlgorithm().clazz())) .forEach(e -> this.algoModels.addElement(e)); } else { algorithmModels.getModels(AlgType.valueOf(algoType), this.dataType, this.multiDataAlgo).stream() @@ -539,15 +539,15 @@ private void refreshTestList() { List models = IndependenceTestModels.getInstance().getModels(this.dataType); if (this.linearGaussianRadBtn.isSelected()) { models.stream() - .filter(e -> e.getIndependenceTest().getClazz().isAnnotationPresent(LinearGaussian.class)) + .filter(e -> e.getIndependenceTest().clazz().isAnnotationPresent(LinearGaussian.class)) .forEach(e -> this.indTestComboBox.addItem(e)); } else if (this.mixedRadBtn.isSelected()) { models.stream() - .filter(e -> e.getIndependenceTest().getClazz().isAnnotationPresent(Mixed.class)) + .filter(e -> e.getIndependenceTest().clazz().isAnnotationPresent(Mixed.class)) .forEach(e -> this.indTestComboBox.addItem(e)); } else if (this.generalRadBtn.isSelected()) { models.stream() - .filter(e -> e.getIndependenceTest().getClazz().isAnnotationPresent(General.class)) + .filter(e -> e.getIndependenceTest().clazz().isAnnotationPresent(General.class)) .forEach(e -> this.indTestComboBox.addItem(e)); } else if (this.allRadBtn.isSelected()) { models.stream() @@ -590,15 +590,15 @@ private void refreshScoreList() { List models = ScoreModels.getInstance().getModels(this.dataType); if (this.linearGaussianRadBtn.isSelected()) { models.stream() - .filter(e -> e.getScore().getClazz().isAnnotationPresent(LinearGaussian.class)) + .filter(e -> e.getScore().clazz().isAnnotationPresent(LinearGaussian.class)) .forEach(e -> this.scoreComboBox.addItem(e)); } else if (this.mixedRadBtn.isSelected()) { models.stream() - .filter(e -> e.getScore().getClazz().isAnnotationPresent(Mixed.class)) + .filter(e -> e.getScore().clazz().isAnnotationPresent(Mixed.class)) .forEach(e -> this.scoreComboBox.addItem(e)); } else if (this.generalRadBtn.isSelected()) { models.stream() - .filter(e -> e.getScore().getClazz().isAnnotationPresent(General.class)) + .filter(e -> e.getScore().clazz().isAnnotationPresent(General.class)) .forEach(e -> this.scoreComboBox.addItem(e)); } else if (this.allRadBtn.isSelected()) { models.stream() diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/ui/model/AlgorithmModel.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/ui/model/AlgorithmModel.java index 400150317e..38d5ce0518 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/ui/model/AlgorithmModel.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/ui/model/AlgorithmModel.java @@ -47,10 +47,10 @@ public AlgorithmModel(AnnotatedClass algorithm) { } this.algorithm = algorithm; - this.name = algorithm.getAnnotation().name(); - this.description = AlgorithmDescriptions.getInstance().get(algorithm.getAnnotation().command()); - this.requiredScore = UsesScoreWrapper.class.isAssignableFrom(algorithm.getClazz()); - this.requiredTest = TakesIndependenceWrapper.class.isAssignableFrom(algorithm.getClazz()); + this.name = algorithm.annotation().name(); + this.description = AlgorithmDescriptions.getInstance().get(algorithm.annotation().command()); + this.requiredScore = UsesScoreWrapper.class.isAssignableFrom(algorithm.clazz()); + this.requiredTest = TakesIndependenceWrapper.class.isAssignableFrom(algorithm.clazz()); } @Override diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/ui/model/AlgorithmModels.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/ui/model/AlgorithmModels.java index a922911f96..10edcedf46 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/ui/model/AlgorithmModels.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/ui/model/AlgorithmModels.java @@ -68,7 +68,7 @@ private void refreshModels() { } // group by datatype - this.models.forEach(e -> map.get(e.getAlgorithm().getAnnotation().algoType()).add(e)); + this.models.forEach(e -> map.get(e.getAlgorithm().annotation().algoType()).add(e)); // make it unmodifiable map.forEach((k, v) -> map.put(k, Collections.unmodifiableList(v))); @@ -81,9 +81,9 @@ private List filterInclusivelyByAllOrSpecificDataType(List !multiDataSetAlgorithm || algoAnno.takesMultipleDataset(e.getAlgorithm().getClazz())) + .filter(e -> !multiDataSetAlgorithm || algoAnno.takesMultipleDataset(e.getAlgorithm().clazz())) .filter(e -> { - for (DataType dt : e.getAlgorithm().getAnnotation().dataType()) { + for (DataType dt : e.getAlgorithm().annotation().dataType()) { if (dt == DataType.All || dt == dataType) { return true; } diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/ui/model/IndependenceTestModel.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/ui/model/IndependenceTestModel.java index c95bda9237..1025a30544 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/ui/model/IndependenceTestModel.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/ui/model/IndependenceTestModel.java @@ -39,13 +39,13 @@ public class IndependenceTestModel implements Serializable, Comparable independenceTest) { this.independenceTest = independenceTest; - this.name = independenceTest.getAnnotation().name(); - this.description = IndependenceTestDescriptions.getInstance().get(independenceTest.getAnnotation().command()); + this.name = independenceTest.annotation().name(); + this.description = IndependenceTestDescriptions.getInstance().get(independenceTest.annotation().command()); } @Override public int compareTo(IndependenceTestModel other) { - return this.independenceTest.getAnnotation().name().compareTo(other.independenceTest.getAnnotation().name()); + return this.independenceTest.annotation().name().compareTo(other.independenceTest.annotation().name()); } @Override diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/ui/model/IndependenceTestModels.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/ui/model/IndependenceTestModels.java index 7db98b953e..bc59f0fb05 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/ui/model/IndependenceTestModels.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/ui/model/IndependenceTestModels.java @@ -70,7 +70,7 @@ private void initModelMap() { // group by datatype this.models.forEach(e -> { - DataType[] types = e.getIndependenceTest().getAnnotation().dataType(); + DataType[] types = e.getIndependenceTest().annotation().dataType(); for (DataType dataType : types) { this.modelMap.get(dataType).add(e); } @@ -106,7 +106,7 @@ private void initDefaultModelMap() { this.defaultModelMap.put(dataType, list.get(0)); } else { Optional result = list.stream() - .filter(e -> e.getIndependenceTest().getClazz().getName().equals(value)) + .filter(e -> e.getIndependenceTest().clazz().getName().equals(value)) .findFirst(); this.defaultModelMap.put(dataType, result.orElseGet(() -> list.get(0))); } diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/ui/model/ScoreModel.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/ui/model/ScoreModel.java index 148c4aa2ce..029c16ecf1 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/ui/model/ScoreModel.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/ui/model/ScoreModel.java @@ -39,13 +39,13 @@ public class ScoreModel implements Serializable, Comparable { public ScoreModel(AnnotatedClass score) { this.score = score; - this.name = score.getAnnotation().name(); - this.description = ScoreDescriptions.getInstance().get(score.getAnnotation().command()); + this.name = score.annotation().name(); + this.description = ScoreDescriptions.getInstance().get(score.annotation().command()); } @Override public int compareTo(ScoreModel other) { - return this.score.getAnnotation().name().compareTo(other.score.getAnnotation().name()); + return this.score.annotation().name().compareTo(other.score.annotation().name()); } @Override diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/ui/model/ScoreModels.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/ui/model/ScoreModels.java index 7ce33e5867..0bb691f9f4 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/ui/model/ScoreModels.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/ui/model/ScoreModels.java @@ -71,7 +71,7 @@ private void initModelMap() { // group by datatype this.models.forEach(e -> { - DataType[] types = e.getScore().getAnnotation().dataType(); + DataType[] types = e.getScore().annotation().dataType(); for (DataType dataType : types) { this.modelMap.get(dataType).add(e); } @@ -107,7 +107,7 @@ private void initDefaultModelMap() { this.defaultModelMap.put(dataType, list.get(0)); } else { Optional result = list.stream() - .filter(e -> e.getScore().getClazz().getName().equals(value)) + .filter(e -> e.getScore().clazz().getName().equals(value)) .findFirst(); this.defaultModelMap.put(dataType, result.orElseGet(() -> list.get(0))); } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/annotation/AbstractAnnotations.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/annotation/AbstractAnnotations.java index 2ff0a40347..0a4fd09d2c 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/annotation/AbstractAnnotations.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/annotation/AbstractAnnotations.java @@ -75,7 +75,7 @@ public List> filterByAnnotation(List> annoCl } List> list = annoClasses.stream() - .filter(e -> e.getClazz().isAnnotationPresent(type)) + .filter(e -> e.clazz().isAnnotationPresent(type)) .collect(Collectors.toList()); return Collections.unmodifiableList(list); @@ -93,7 +93,7 @@ public List> filterOutByAnnotation(List> ann } List> list = annoClasses.stream() - .filter(e -> !e.getClazz().isAnnotationPresent(type)) + .filter(e -> !e.clazz().isAnnotationPresent(type)) .collect(Collectors.toList()); return Collections.unmodifiableList(list); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/annotation/AnnotatedClass.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/annotation/AnnotatedClass.java index a56a602075..d5ea201e6f 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/annotation/AnnotatedClass.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/annotation/AnnotatedClass.java @@ -18,6 +18,7 @@ */ package edu.cmu.tetrad.annotation; +import java.io.Serial; import java.io.Serializable; import java.lang.annotation.Annotation; @@ -27,37 +28,37 @@ * @param annotation * @author Kevin V. Bui (kvb2@pitt.edu) */ -public class AnnotatedClass implements Serializable { +public record AnnotatedClass(Class clazz, T annotation) implements Serializable { + @Serial private static final long serialVersionUID = 5060798016477163171L; - private final Class clazz; - - private final T annotation; - /** * Creates an annotated class. - * @param clazz class + * + * @param clazz class * @param annotation annotation */ - public AnnotatedClass(Class clazz, T annotation) { - this.clazz = clazz; - this.annotation = annotation; + public AnnotatedClass { } /** * Gets the class. + * * @return class */ - public Class getClazz() { + @Override + public Class clazz() { return this.clazz; } /** * Gets the annotation. + * * @return annotation */ - public T getAnnotation() { + @Override + public T annotation() { return this.annotation; } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/annotation/AnnotatedClassUtils.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/annotation/AnnotatedClassUtils.java index ca4a8180d2..da14acc66a 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/annotation/AnnotatedClassUtils.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/annotation/AnnotatedClassUtils.java @@ -64,7 +64,7 @@ public static List> filterByAnnotations if (annotatedClasses != null && !annotatedClasses.isEmpty()) { annotatedClasses.stream() - .filter(e -> e.getClazz().isAnnotationPresent(annotation)) + .filter(e -> e.clazz().isAnnotationPresent(annotation)) .collect(Collectors.toCollection(() -> list)); } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java index c0c6153513..ed0516e482 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java @@ -24,15 +24,15 @@ import java.util.concurrent.Future; /** - * Checks whether a graph is locally Markov or locally Faithful given a data set. First a lists of m-separation - * predictions are made for each pair of variables in the graph given the parents of one of the variables, one list (for - * local Markov) where the m-separation holds and another list (for local Faithfulness) where the m-separation does not - * hold. Then the predictions are tested against the data set using the independence test. For the Markov test, since an - * independence test yielding p-values should be Uniform under the null hypothesis, these p-values are tested for - * Uniformity using the Kolmogorov-Smirnov test. Also, a fraction of dependent judgments is returned, which should equal - * the alpha level of the independence test if the test is Uniform under the null hypothesis. For the Faithfulness test, - * the p-values are tested for Uniformity using the Kolmogorov-Smirnov test; these should be dependent. Also, a fraction - * of dependent judgments is returned, which should be maximal. + * Checks whether a graph is locally Markov or locally Faithful given a data set. First, a list of m-separation + * predictions are made for each pair of variables in the graph given the parents of one of the variables. One list (for + * local Markov) is for where the m-separation holds and another list (for local Faithfulness) where the m-separation + * does not hold. Then the predictions are tested against the data set using the independence test. For the Markov test, + * since an independence test yielding p-values should be Uniform under the null hypothesis, these p-values are tested + * for Uniformity using the Kolmogorov-Smirnov test. Also, a fraction of dependent judgments is returned, which should + * equal the alpha level of the independence test if the test is Uniform under the null hypothesis. For the Faithfulness + * test, the p-values are tested for Uniformity using the Kolmogorov-Smirnov test; these should be dependent. Also, a + * fraction of dependent judgments is returned, which should be maximal. *

                * Knowledge may be supplied to the Markov check. This knowledge is used to specify independence and conditioning * ranges. For facts of the form X _||_ Y | Z, X and Y should be in the last tier of the knowledge, and Z should be in @@ -177,7 +177,7 @@ public List getVariables(List graphNodes, List independenceNod /** * Generates all results, for both the local Markov and local Faithfulness checks, for each node in the graph given * the parents of that node. These results are stored in the resultsIndep and resultsDep lists. This should be - * called before any of the results methods. Note that only results for X _||_ Y | Z1,..,Zn are generated, where X + * called before any of the result methods. Note that only results for X _||_ Y | Z1,..,Zn are generated, where X * and Y are in the independenceNodes list and Z1,..,Zn are in the conditioningNodes list. * * @see #getResults(boolean) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/util/AlgorithmDescriptions.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/util/AlgorithmDescriptions.java index 46fde7a468..001ba37022 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/util/AlgorithmDescriptions.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/util/AlgorithmDescriptions.java @@ -88,7 +88,7 @@ public String get(String shortName) { private List getShortNames() { // get algorithm from annotations List shortNames = AlgorithmAnnotations.getInstance().getAnnotatedClasses().stream() - .map(e -> e.getAnnotation().command()) + .map(e -> e.annotation().command()) .collect(Collectors.toList()); // add additional shortNames not annotated diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/util/IndependenceTestDescriptions.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/util/IndependenceTestDescriptions.java index dfe11a1694..0dff8a3136 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/util/IndependenceTestDescriptions.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/util/IndependenceTestDescriptions.java @@ -78,7 +78,7 @@ public String get(String shortName) { private List getShortNames() { return TestOfIndependenceAnnotations.getInstance().getAnnotatedClasses().stream() - .map(e -> e.getAnnotation().command()) + .map(e -> e.annotation().command()) .collect(Collectors.toList()); } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/util/ScoreDescriptions.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/util/ScoreDescriptions.java index a158035947..80a06841bc 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/util/ScoreDescriptions.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/util/ScoreDescriptions.java @@ -78,7 +78,7 @@ public String get(String shortName) { private List getShortNames() { return ScoreAnnotations.getInstance().getAnnotatedClasses().stream() - .map(e -> e.getAnnotation().command()) + .map(e -> e.annotation().command()) .collect(Collectors.toList()); } diff --git a/tetrad-lib/src/test/java/edu/cmu/tetrad/annotation/AlgorithmAnnotationsTest.java b/tetrad-lib/src/test/java/edu/cmu/tetrad/annotation/AlgorithmAnnotationsTest.java index e167685b9c..e0fd29a149 100644 --- a/tetrad-lib/src/test/java/edu/cmu/tetrad/annotation/AlgorithmAnnotationsTest.java +++ b/tetrad-lib/src/test/java/edu/cmu/tetrad/annotation/AlgorithmAnnotationsTest.java @@ -37,7 +37,7 @@ public AlgorithmAnnotationsTest() { @Test public void testAnnotatedNameAttributeForUniqueness() { List> algorithms = AlgorithmAnnotations.getInstance().getAnnotatedClasses(); - List values = algorithms.stream().map(e -> e.getAnnotation().name().toLowerCase()).collect(Collectors.toList()); + List values = algorithms.stream().map(e -> e.annotation().name().toLowerCase()).collect(Collectors.toList()); long actual = values.size(); long expected = values.stream().distinct().count(); @@ -47,7 +47,7 @@ public void testAnnotatedNameAttributeForUniqueness() { @Test public void testAnnotatedCommandAttributeForUniqueness() { List> algorithms = AlgorithmAnnotations.getInstance().getAnnotatedClasses(); - List values = algorithms.stream().map(e -> e.getAnnotation().command().toLowerCase()).collect(Collectors.toList()); + List values = algorithms.stream().map(e -> e.annotation().command().toLowerCase()).collect(Collectors.toList()); long actual = values.size(); long expected = values.stream().distinct().count(); diff --git a/tetrad-lib/src/test/java/edu/cmu/tetrad/annotation/ScoreAnnotationsTest.java b/tetrad-lib/src/test/java/edu/cmu/tetrad/annotation/ScoreAnnotationsTest.java index f1bbed8f70..7f303c2af2 100644 --- a/tetrad-lib/src/test/java/edu/cmu/tetrad/annotation/ScoreAnnotationsTest.java +++ b/tetrad-lib/src/test/java/edu/cmu/tetrad/annotation/ScoreAnnotationsTest.java @@ -37,7 +37,7 @@ public ScoreAnnotationsTest() { @Test public void testAnnotatedNameAttributeForUniqueness() { List> scores = ScoreAnnotations.getInstance().getAnnotatedClasses(); - List values = scores.stream().map(e -> e.getAnnotation().name().toLowerCase()).collect(Collectors.toList()); + List values = scores.stream().map(e -> e.annotation().name().toLowerCase()).collect(Collectors.toList()); long actual = values.size(); long expected = values.stream().distinct().count(); @@ -47,7 +47,7 @@ public void testAnnotatedNameAttributeForUniqueness() { @Test public void testAnnotatedCommandAttributeForUniqueness() { List> scores = ScoreAnnotations.getInstance().getAnnotatedClasses(); - List values = scores.stream().map(e -> e.getAnnotation().command().toLowerCase()).collect(Collectors.toList()); + List values = scores.stream().map(e -> e.annotation().command().toLowerCase()).collect(Collectors.toList()); long actual = values.size(); long expected = values.stream().distinct().count(); diff --git a/tetrad-lib/src/test/java/edu/cmu/tetrad/annotation/TestOfIndependenceAnnotationsTest.java b/tetrad-lib/src/test/java/edu/cmu/tetrad/annotation/TestOfIndependenceAnnotationsTest.java index 6a6f8188d7..8fc433dc7e 100644 --- a/tetrad-lib/src/test/java/edu/cmu/tetrad/annotation/TestOfIndependenceAnnotationsTest.java +++ b/tetrad-lib/src/test/java/edu/cmu/tetrad/annotation/TestOfIndependenceAnnotationsTest.java @@ -37,7 +37,7 @@ public TestOfIndependenceAnnotationsTest() { @Test public void testAnnotatedNameAttributeForUniqueness() { List> indTests = TestOfIndependenceAnnotations.getInstance().getAnnotatedClasses(); - List values = indTests.stream().map(e -> e.getAnnotation().name().toLowerCase()).collect(Collectors.toList()); + List values = indTests.stream().map(e -> e.annotation().name().toLowerCase()).collect(Collectors.toList()); long actual = values.size(); long expected = values.stream().distinct().count(); @@ -47,7 +47,7 @@ public void testAnnotatedNameAttributeForUniqueness() { @Test public void testAnnotatedCommandAttributeForUniqueness() { List> indTests = TestOfIndependenceAnnotations.getInstance().getAnnotatedClasses(); - List values = indTests.stream().map(e -> e.getAnnotation().name().toLowerCase()).collect(Collectors.toList()); + List values = indTests.stream().map(e -> e.annotation().name().toLowerCase()).collect(Collectors.toList()); long actual = values.size(); long expected = values.stream().distinct().count(); From d79504ba34b27d5be9b0d4b7b9fec9cc94876f06 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Wed, 24 Jan 2024 11:32:36 -0500 Subject: [PATCH 110/163] Changed the wording of the "Processing..." button to "Processing (click to stop)...". --- .../src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java index 72725b82e6..5a25b6b26b 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java @@ -88,10 +88,10 @@ private void showStopDialog() { dialog = new JDialog(frame, "Stop Process", Dialog.ModalityType.APPLICATION_MODAL); dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); dialog.setUndecorated(true); - dialog.setSize(100, 50); + dialog.setSize(200, 50); dialog.setResizable(false); - JButton stopButton = new JButton("Processing..."); + JButton stopButton = new JButton("Processing (click to stop)..."); stopButton.addActionListener(e -> { stopLongRunningThread(); From 0d019b12ee215c98e3bfa66ee5a16a1876036421 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Wed, 24 Jan 2024 11:36:42 -0500 Subject: [PATCH 111/163] Cleanup. --- .../main/java/edu/cmu/tetradapp/util/WatchedProcess.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java index 5a25b6b26b..166d095f59 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java @@ -1,5 +1,7 @@ package edu.cmu.tetradapp.util; +import edu.cmu.tetrad.util.TetradLogger; + import javax.swing.*; import javax.swing.border.BevelBorder; import java.awt.*; @@ -53,7 +55,7 @@ public WatchedProcess() { private void startLongRunningThread() { longRunningThread = new Thread(() -> { if (Thread.interrupted()) { - // Thread was interrupted, so exit the loop and terminate + // The Thread was interrupted, so exit the loop and terminate System.out.println("Thread was interrupted. Stopping..."); return; } @@ -61,9 +63,7 @@ private void startLongRunningThread() { try { watch(); } catch (InterruptedException e) { - e.printStackTrace(); - // Thread was interrupted while sleeping, so exit the loop and terminate - System.out.println("Thread was interrupted while watching. Stopping..."); + TetradLogger.getInstance().forceLogMessage("Thread was interrupted while watching. Stopping..."); return; } From d368b6ce4bef03bf51922078a307b3da0086e7c9 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Wed, 24 Jan 2024 11:37:42 -0500 Subject: [PATCH 112/163] Cleanup. --- .../edu/cmu/tetradapp/util/WatchedProcess.java | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java index 166d095f59..01f79751ef 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java @@ -7,15 +7,14 @@ import java.awt.*; /** - *

                Runs a long process, watching it with a thread and popping up a Stop button that the user can click to stop the - * process.

                - * - *

                Replacement for the old WatchedProcess, which called the deprecated Thread.stop() method. This method is + * Runs a long process, watching it with a thread and popping up a Stop button that the user can click to stop the + * process. + *

                + * Replacement for the old WatchedProcess, which called the deprecated Thread.stop() method. This method is * deprecated because it can leave the program in an inconsistent state. This class uses Thread.interrupt() instead, - * which is the recommended way to stop a thread.

                - * - *

                Example usage:

                - * + * which is the recommended way to stop a thread. + *

                + * Example usage: *

                  * class MyWatchedProcess extends WatchedProcess {
                  *
                
                From 55981a4a64a1a96637383c96cb928cd0aa39088e Mon Sep 17 00:00:00 2001
                From: jdramsey 
                Date: Wed, 24 Jan 2024 15:43:54 -0500
                Subject: [PATCH 113/163] Cleaned up code and documentation in the score
                 package.
                
                ---
                 .../edu/cmu/tetrad/search/score/BdeScore.java |  32 +--
                 .../cmu/tetrad/search/score/BdeuScore.java    |   8 +
                 .../score/ConditionalGaussianLikelihood.java  |  48 ++--
                 .../score/ConditionalGaussianScore.java       |  36 ++-
                 .../search/score/DegenerateGaussianScore.java |  74 +++++-
                 .../tetrad/search/score/DiscreteBicScore.java |  12 +-
                 .../tetrad/search/score/DiscreteScore.java    |   4 +-
                 .../cmu/tetrad/search/score/EbicScore.java    |  47 +++-
                 .../cmu/tetrad/search/score/GicScores.java    | 195 ++++++++------
                 .../cmu/tetrad/search/score/GraphScore.java   | 101 ++------
                 .../cmu/tetrad/search/score/ImagesScore.java  |  41 ++-
                 .../cmu/tetrad/search/score/IndTestScore.java |  79 ++++--
                 .../tetrad/search/score/MvpLikelihood.java    | 240 ++++++++++--------
                 .../edu/cmu/tetrad/search/score/MvpScore.java |  41 ++-
                 .../search/score/PoissonPriorScore.java       | 106 ++++++--
                 .../cmu/tetrad/search/score/ScoredGraph.java  |  45 ++++
                 .../cmu/tetrad/search/score/SemBicScore.java  | 110 ++++----
                 .../edu/cmu/tetrad/search/score/ZsbScore.java |  58 +++--
                 .../cmu/tetrad/search/score/package-info.java |   2 +-
                 19 files changed, 788 insertions(+), 491 deletions(-)
                
                diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/BdeScore.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/BdeScore.java
                index b847fa57b8..88f534c88b 100644
                --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/BdeScore.java
                +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/BdeScore.java
                @@ -30,19 +30,20 @@
                 import java.util.List;
                 
                 /**
                - * 

                Calculates the BDe score (Bayes Dirichlet Equivalent) score for analyzing - * discrete multinomial data. A good discussion of BD* scores can be found here:

                - * - *

                Heckerman, D., Geiger, D. & Chickering, D.M. Learning Bayesian networks: - * The combination of knowledge and statistical data. Mach Learn 20, 197–243 (1995).

                - * - *

                As for all scores in Tetrad, higher scores mean more dependence, and negative - * scores indicate independence.

                + * Calculates the BDe score (Bayes Dirichlet Equivalent) score for analyzing discrete multinomial data. A good + * discussion of BD* scores can be found here: + *

                + * Heckerman, D., Geiger, D. & Chickering, D.M. Learning Bayesian networks: The combination of knowledge and + * statistical data. Mach Learn 20, 197–243 (1995). + *

                + * As for all scores in Tetrad, higher scores mean more dependence, and negative scores indicate independence. * * @author josephramsey * @see BdeuScore */ public class BdeScore implements DiscreteScore { + + // The discrete dataset. private final DataSet dataSet; /** @@ -72,7 +73,7 @@ public BdeScore(DataSet dataSet) { */ public double localScore(int i, int[] parents) { - // Number of categories for i. + // Number of categories for index i. int r = numCategories(i); // Numbers of categories of parents. @@ -115,10 +116,7 @@ public double localScore(int i, int[] parents) { } int rowIndex = getRowIndex(dims, values); - -// for (int m = 0; m < dataSet().getMultiplier(n); m++) { n_ijk[rowIndex][childValue]++; -// } } // Row sums. @@ -152,12 +150,12 @@ public double localScore(int i, int[] parents) { } /** - * Returns the different between localScore(y | z, x) and localScore(y | z) + * Returns the difference between localScore(y | z, x) and localScore(y | z) * * @param x The index of the x variable * @param y The index of the y variable. * @param z The indices of the z variables - * @return The differnece in scores. + * @return The difference in scores. */ @Override public double localScoreDiff(int x, int y, int[] z) { @@ -185,9 +183,6 @@ private int getRowIndex(int[] dim, int[] values) { } /** - * BDe does not use a structure prior. - * - * @param structurePrior The structure prior (not used). * @throws UnsupportedOperationException Since this method is not implemented for this score. */ public void setStructurePrior(double structurePrior) { @@ -195,9 +190,6 @@ public void setStructurePrior(double structurePrior) { } /** - * BDe does not use a sample prior. - * - * @param samplePrior The structure prior (not used). * @throws UnsupportedOperationException Since this method is not implemented for this score. */ public void setSamplePrior(double samplePrior) { diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/BdeuScore.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/BdeuScore.java index df665edb84..08dde7dfeb 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/BdeuScore.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/BdeuScore.java @@ -44,12 +44,20 @@ * @see BdeScore */ public class BdeuScore implements DiscreteScore { + + // The discrete dataset. private final int[][] data; + // The sample size of the data. private final int sampleSize; + // The number of categories for each variable. private final int[] numCategories; + // The discrete dataset. private final DataSet dataSet; + // The variables of the dataset. private final List variables; + // The sample prior. private double samplePrior = 1d; + // The structure prior. private double structurePrior = 0d; /** diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/ConditionalGaussianLikelihood.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/ConditionalGaussianLikelihood.java index e62624bc15..e2fe86516a 100755 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/ConditionalGaussianLikelihood.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/ConditionalGaussianLikelihood.java @@ -27,6 +27,7 @@ import edu.cmu.tetrad.util.Matrix; import org.apache.commons.math3.stat.correlation.Covariance; import org.apache.commons.math3.util.FastMath; +import org.jetbrains.annotations.Contract; import java.util.ArrayList; import java.util.HashMap; @@ -39,15 +40,14 @@ import static org.apache.commons.math3.util.FastMath.log; /** - *

                Implements a conditional Gaussian likelihood. Please note that this likelihood will be - * maximal only if the continuous variables are jointly Gaussian conditional on the discrete variables; in all other - * cases, it will be less than maximal. The reference is here:

                - * - *

                Andrews, B., Ramsey, J., & Cooper, G. F. (2018). Scoring Bayesian networks of mixed variables. - * International journal of data science and analytics, 6, 3-18.

                - * - *

                As for all scores in Tetrad, higher scores mean more dependence, and negative - * scores indicate independence.

                + * Implements a conditional Gaussian likelihood. Please note that this likelihood will be maximal only if the continuous + * variables are jointly Gaussian conditional on the discrete variables; in all other cases, it will be less than + * maximal. The reference is here: + *

                + * Andrews, B., Ramsey, J., & Cooper, G. F. (2018). Scoring Bayesian networks of mixed variables. International + * journal of data science and analytics, 6, 3-18. + *

                + * As for all scores in Tetrad, higher scores mean more dependence, and negative scores indicate independence. * * @author bryanandrews * @author josephramsey @@ -62,16 +62,12 @@ public class ConditionalGaussianLikelihood { private final DataSet dataSet; // The mixedVariables of the mixed data set. private final List mixedVariables; - // Indices of mixedVariables. private final Map nodesHash; - // Continuous data only. private final double[][] continuousData; // Number of categories to use to discretize continuous mixedVariables. private int numCategoriesToDiscretize = 3; - // Multiplier on degrees of freedom for the continuous portion of those degrees. - private double penaltyDiscount = 1; // "Cell" consisting of all rows. private List rows; // Discretize the parents @@ -79,6 +75,8 @@ public class ConditionalGaussianLikelihood { /** * Constructs the score using a covariance matrix. + * + * @param dataSet The continuous dataset to analyze. */ public ConditionalGaussianLikelihood(DataSet dataSet) { if (dataSet == null) { @@ -117,6 +115,10 @@ public ConditionalGaussianLikelihood(DataSet dataSet) { for (int i = 0; i < dataSet.getNumRows(); i++) this.rows.add(i); } + /** + * Sets the rows to use for the likelihood calculation. If not set, all rows will be used. + * @param rows The rows to use. + */ public void setRows(List rows) { this.rows = rows; } @@ -160,15 +162,6 @@ public Ret getLikelihood(int i, int[] parents) { return new Ret(ret1.getLik() - ret2.getLik(), ret1.getDof() - ret2.getDof()); } - /** - * Sets the penalty discount for this score, which is a multiplier on the panalty term of BIC. - * - * @param penaltyDiscount The penalty discount. - */ - public void setPenaltyDiscount(double penaltyDiscount) { - this.penaltyDiscount = penaltyDiscount; - } - /** * Sets whether to discretize child variables to avoid integration. An optimization. * @@ -180,7 +173,7 @@ public void setDiscretize(boolean discretize) { } /** - * Sets the number of categories to use to discretize child variables to avoid integrationl + * Sets the number of categories to use to discretize child variables to avoid integration * * @param numCategoriesToDiscretize This number. * @see #setDiscretize(boolean) @@ -264,11 +257,11 @@ private Ret likelihoodJoint(List X, List A if (a == 0) continue; - if (A.size() > 0) { + if (!A.isEmpty()) { c1 += a * multinomialLikelihood(a, rows.size()); } - if (X.size() > 0) { + if (!X.isEmpty()) { try { // Determinant will be zero if data are linearly dependent. @@ -358,13 +351,14 @@ private List> partition(List discrete_parents, L } /** - * Gives return value for a conditional Gaussain likelihood, returning a likelihood value and the degrees of freedom + * Gives return value for a conditional Gaussian likelihood, returning a likelihood value and the degrees of freedom * for it. */ - public static class Ret { + public static final class Ret { private final double lik; private final int dof; + @Contract(pure = true) private Ret(double lik, int dof) { this.lik = lik; this.dof = dof; diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/ConditionalGaussianScore.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/ConditionalGaussianScore.java index 18c5cd6ac6..b85c0a1d4f 100755 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/ConditionalGaussianScore.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/ConditionalGaussianScore.java @@ -35,33 +35,30 @@ import java.util.List; /** - *

                Implements a conditional Gaussian BIC score for FGS, which calculates a BIC - * score for mixed discrete/Gaussian data using the conditional Gaussian likelihood function (see). The reference is - * here:

                - * - *

                Andrews, B., Ramsey, J., & Cooper, G. F. (2018). Scoring Bayesian networks of mixed variables. - * International journal of data science and analytics, 6, 3-18.

                - * - *

                As for all scores in Tetrad, higher scores mean more dependence, and negative - * scores indicate independence.

                + * Implements a conditional Gaussian BIC score for FGS, which calculates a BIC score for mixed discrete/Gaussian data + * using the conditional Gaussian likelihood function (see). The reference is here: + *

                + * Andrews, B., Ramsey, J., & Cooper, G. F. (2018). Scoring Bayesian networks of mixed variables. International + * journal of data science and analytics, 6, 3-18. *

                - * * @author josephramsey + * As for all scores in Tetrad, higher scores mean more dependence, and negative scores indicate independence. * + * @author josephramsey * @see ConditionalGaussianLikelihood * @see DegenerateGaussianScore */ public class ConditionalGaussianScore implements Score { - + // The dataset. private final DataSet dataSet; - // The variables of the dataset. private final List variables; - // Likelihood function private final ConditionalGaussianLikelihood likelihood; - + // The penalty discount. private double penaltyDiscount; + // The number of categories to discretize. private int numCategoriesToDiscretize = 3; + // The structure prior. private double structurePrior = 0; /** @@ -72,7 +69,7 @@ public class ConditionalGaussianScore implements Score { * @param penaltyDiscount A multiplier on the penalty term in the BIC score. * @param discretize When a discrete variable is a child of a continuous variable, one (expensive) way to solve * the problem is to do a numerical integration. A less expensive (and often more accurate) - * way to solve the problem is to discretize the child with a certian number of discrete + * way to solve the problem is to discretize the child with a certain number of discrete * categories. if this parameter is set to True, a separate copy of all variables is * maintained that is discretized in this way, and these are substituted for the discrete * children when this sort of problem needs to be solved. This information needs to be known @@ -92,12 +89,11 @@ public ConditionalGaussianScore(DataSet dataSet, double penaltyDiscount, boolean this.likelihood = new ConditionalGaussianLikelihood(dataSet); this.likelihood.setNumCategoriesToDiscretize(this.numCategoriesToDiscretize); - this.likelihood.setPenaltyDiscount(penaltyDiscount); this.likelihood.setDiscretize(discretize); } /** - * Calculates the sample likelihood and BIC score for i given its parents in a simple SEM model. + * Calculates the sample likelihood and BIC score for index i given its parents in a simple SEM model. * * @param i The index of the child. * @param parents The indices of the parents. @@ -133,7 +129,7 @@ public double localScoreDiff(int x, int y, int[] z) { } /** - * Reurns the sample size of the data. + * Returns the sample size of the data. * * @return This size. */ @@ -176,7 +172,7 @@ public int getMaxDegree() { } /** - * Returns the penalty discount for this score, which is a multiplier on the penatly term of the BIC score. + * Returns the penalty discount for this score, which is a multiplier on the penalty term of the BIC score. * * @return This penalty discount. */ @@ -247,8 +243,6 @@ private double getStructurePrior(int[] parents) { return k * FastMath.log(p) + (n - k) * FastMath.log(1.0 - p); } } - - } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/DegenerateGaussianScore.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/DegenerateGaussianScore.java index b29e125155..5d0f853ac9 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/DegenerateGaussianScore.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/DegenerateGaussianScore.java @@ -35,30 +35,32 @@ /** - *

                This implements the degenerate Gaussian BIC score for FGES. The degenerate Gaussian score - * replaces each discrete variable in the data with a list of 0/1 continuous indicator columns for each of the - * categories but one (the last one implied). This data, now all continuous, is given to the SEM BIC score and methods - * used to help determine conditional independence for the mixed continuous/discrete case from this information. The - * references is as follows:

                - * - *

                Andrews, B., Ramsey, J., & Cooper, G. F. (2019, July). Learning high-dimensional - * directed acyclic graphs with mixed data-types. In The 2019 ACM SIGKDD Workshop on Causal Discovery (pp. 4-21). - * PMLR.

                - * - *

                As for all scores in Tetrad, higher scores mean more dependence, and negative - * scores indicate independence.

                + * =This implements the degenerate Gaussian BIC score for FGES. The degenerate Gaussian score replaces each discrete + * variable in the data with a list of 0/1 continuous indicator columns for each of the categories but one (the last one + * implied). This data, now all continuous, is given to the SEM BIC score and methods used to help determine conditional + * independence for the mixed continuous/discrete case from this information. The references is as follows: + *

                + * Andrews, B., Ramsey, J., & Cooper, G. F. (2019, July). Learning high-dimensional directed acyclic graphs with + * mixed data-types. In The 2019 ACM SIGKDD Workshop on Causal Discovery (pp. 4-21). PMLR. + *

                + * As for all scores in Tetrad, higher scores mean more dependence, and negative scores indicate independence. * * @author Bryan Andrews */ public class DegenerateGaussianScore implements Score { // The mixed variables of the original dataset. private final List variables; - // The embedding map. private final Map> embedding; - + // The SEM BIC score. private final SemBicScore bic; + /** + * Constructs the score using a dataset. + * + * @param dataSet The dataset. + * @param precomputeCovariances True if covariances should be precomputed. + */ public DegenerateGaussianScore(DataSet dataSet, boolean precomputeCovariances) { if (dataSet == null) { throw new NullPointerException(); @@ -162,40 +164,84 @@ public double localScore(int i, int... parents) { return score; } + /** + * Calculates localScore(y | z, x) - localScore(z). + * + * @param x A node. + * @param y TAhe node. + * @param z A set of nodes. + * @return The score difference. + */ public double localScoreDiff(int x, int y, int[] z) { return localScore(y, append(z, x)) - localScore(y, z); } + /** + * Returns the list of variables. + * + * @return The list of variables. + */ @Override public List getVariables() { return this.variables; } + /** + * True if an edge with the given bump is an effect edge. + * + * @param bump The bump. + * @return True if so. + */ @Override public boolean isEffectEdge(double bump) { return this.bic.isEffectEdge(bump); } + /** + * Returns the sample sizE. + * + * @return The sample size. + */ @Override public int getSampleSize() { return this.bic.getSampleSize(); } + /** + * Returns the max degree. + * + * @return The max degree. + */ @Override public int getMaxDegree() { return this.bic.getMaxDegree(); } + /** + * Returns a string for this object. + * + * @return The string. + */ @Override public String toString() { NumberFormat nf = new DecimalFormat("0.00"); return "Degenerate Gaussian Score Penalty " + nf.format(this.bic.getPenaltyDiscount()); } + /** + * Returns the penalty discount. + * + * @return The penalty discount. + */ public double getPenaltyDiscount() { return this.bic.getPenaltyDiscount(); } + /** + * Sets the penalty discount. + * + * @param penaltyDiscount The penalty discount. + */ public void setPenaltyDiscount(double penaltyDiscount) { this.bic.setPenaltyDiscount(penaltyDiscount); } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/DiscreteBicScore.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/DiscreteBicScore.java index d6955d5e9d..a15de2fabe 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/DiscreteBicScore.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/DiscreteBicScore.java @@ -45,16 +45,23 @@ * @author josephramsey */ public class DiscreteBicScore implements DiscreteScore { + // The discrete dataset. private final DataSet dataSet; + // The variables of the dataset. private final int[][] data; + // The sample size. private final int sampleSize; + // The number of categories for each variable. private final int[] numCategories; + // The variables of the dataset. private List variables; + // The penalty discount. private double penaltyDiscount = 1; + // The structure prior. private double structurePrior = 0; /** - * Constructor. + * Constructs the score using a dataset. * * @param dataSet The discrete dataset to analyze. */ @@ -206,6 +213,9 @@ public double localScore(int node, int[] parents) { /** * Returns the number of parameters for a node given its parents. + * + * @param node The index of the node. + * @param parents The indices of the node's parents. */ public int numParameters(int node, int[] parents) { if (!(this.variables.get(node) instanceof DiscreteVariable)) { diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/DiscreteScore.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/DiscreteScore.java index 9199dce89e..b90544fc64 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/DiscreteScore.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/DiscreteScore.java @@ -32,19 +32,21 @@ public interface DiscreteScore extends Score { /** * Sets the structure prior. - * @param structurePrior Ibid. * + * @param structurePrior Ibid. */ void setStructurePrior(double structurePrior); /** * Sets the sample prior. + * * @param samplePrior Ibid. */ void setSamplePrior(double samplePrior); /** * Returns the dataset. + * * @return Ibid. */ DataSet getDataSet(); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/EbicScore.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/EbicScore.java index 07b6ceef47..0b97c62805 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/EbicScore.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/EbicScore.java @@ -21,7 +21,10 @@ package edu.cmu.tetrad.search.score; -import edu.cmu.tetrad.data.*; +import edu.cmu.tetrad.data.DataSet; +import edu.cmu.tetrad.data.DataTransforms; +import edu.cmu.tetrad.data.ICovarianceMatrix; +import edu.cmu.tetrad.data.SimpleDataLoader; import edu.cmu.tetrad.graph.Node; import edu.cmu.tetrad.search.Fges; import edu.cmu.tetrad.search.utils.LogUtilsSearch; @@ -36,28 +39,37 @@ import static org.apache.commons.math3.util.FastMath.log; /** - *

                Implements the extended BIC (EBIC) score. The reference is here:

                - * - *

                Chen, J., & Chen, Z. (2008). Extended Bayesian information criteria for - * model selection with large model spaces. Biometrika, 95(3), 759-771.

                - * - *

                As for all scores in Tetrad, higher scores mean more dependence, and negative - * scores indicate independence.

                + * Implements the extended BIC (EBIC) score. The reference is here: + *

                + * Chen, J., & Chen, Z. (2008). Extended Bayesian information criteria for model selection with large model spaces. + * Biometrika, 95(3), 759-771. + *

                + * As for all scores in Tetrad, higher scores mean more dependence, and negative scores indicate independence. * * @author josephramsey */ public class EbicScore implements Score { + // The variables of the covariance matrix. private final List variables; + // The sample size of the covariance matrix. private final int sampleSize; + // The covariance matrix. private ICovarianceMatrix covariances; + // The number of variables. private double N; + // The dataset. private Matrix data; + // True if verbose output should be sent to out. private boolean calculateRowSubsets; + // The gamma parameter. private double gamma = 1; + // True if the pseudo-inverse should be used. private boolean usePseudoInverse = false; /** * Constructs the score using a covariance matrix. + * + * @param covariances The covariance matrix. */ public EbicScore(ICovarianceMatrix covariances) { if (covariances == null) { @@ -98,6 +110,8 @@ public EbicScore(DataSet dataSet, boolean precomputeCovariances) { } /** + * Returns the score of the node at index y, given its parents. + * * @return localScore(y | z, x) - localScore(y | z). */ @Override @@ -106,7 +120,7 @@ public double localScoreDiff(int x, int y, int[] z) { } /** - * Returns the score of the node i given its parents. + * Returns the score of the node at index i, given its parents. * * @param i The index of the node. * @param parents The indices of the node's parents. @@ -160,7 +174,7 @@ public boolean isEffectEdge(double bump) { /** * Returns the variables for this score. * - * @return Thsi list. + * @return This list. */ @Override public List getVariables() { @@ -204,6 +218,15 @@ public void setGamma(double gamma) { this.gamma = gamma; } + /** + * Returns the gamma parameter for EBIC. + * + * @param usePseudoInverse True if the pseudo-inverse should be used. + */ + public void setUsePseudoInverse(boolean usePseudoInverse) { + this.usePseudoInverse = usePseudoInverse; + } + private void setCovariances(ICovarianceMatrix covariances) { this.covariances = covariances; this.N = covariances.getSampleSize(); @@ -214,10 +237,6 @@ private int[] indices(List __adj) { for (int t = 0; t < __adj.size(); t++) indices[t] = this.variables.indexOf(__adj.get(t)); return indices; } - - public void setUsePseudoInverse(boolean usePseudoInverse) { - this.usePseudoInverse = usePseudoInverse; - } } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/GicScores.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/GicScores.java index df582746ae..fc363f9c7b 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/GicScores.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/GicScores.java @@ -35,14 +35,12 @@ import static org.apache.commons.math3.util.FastMath.*; /** - *

                Implements scores motivated by the Generalized Information Criterion (GIC) - * approach as given in Kim et al. (2012).

                - * - *

                Kim, Y., Kwon, S., & Choi, H. (2012). Consistent model selection criteria on - * high dimensions. The Journal of Machine Learning Research, 13(1), 1037-1057.

                - * - *

                As for all scores in Tetrad, higher scores mean more dependence, and negative - * scores indicate independence.

                + * Implements scores motivated by the Generalized Information Criterion (GIC) approach as given in Kim et al. (2012). + *

                + * Kim, Y., Kwon, S., & Choi, H. (2012). Consistent model selection criteria on high dimensions. The Journal of + * Machine Learning Research, 13(1), 1037-1057. + *

                + * As for all scores in Tetrad, higher scores mean more dependence, and negative scores indicate independence. * * @author josephramsey */ @@ -72,8 +70,10 @@ public class GicScores implements Score { /** * Constructs the score using a covariance matrix. + * + * @param covariances The covariance matrix. */ - public GicScores(ICovarianceMatrix covariances/*, double correlationThreshold*/) { + public GicScores(ICovarianceMatrix covariances) { if (covariances == null) { throw new NullPointerException(); } @@ -86,6 +86,9 @@ public GicScores(ICovarianceMatrix covariances/*, double correlationThreshold*/) /** * Constructs the score using a covariance matrix. + * + * @param dataSet The continuous dataset to analyze. + * @param precomputeCovariances Whether the covariances should be precomputed or computed on the fly. True if */ public GicScores(DataSet dataSet, boolean precomputeCovariances) { if (dataSet == null) { @@ -110,12 +113,26 @@ public GicScores(DataSet dataSet, boolean precomputeCovariances) { calculateRowSubsets = true; } + /** + * Calculates the sample likelihood and BIC score for index i given its parents in a simple SEM model. + * + * @param x A node. + * @param y TAhe node. + * @param z A set of nodes. + * @return The score difference. + */ @Override public double localScoreDiff(int x, int y, int[] z) { return localScore(y, append(z, x)) - localScore(y, z); } - + /** + * Calculates the sample likelihood and BIC score for index i given its parents in a simple SEM model. + * + * @param i The node. + * @param parents The parents. + * @return The score. + */ public double localScore(int i, int... parents) { double sn = 12; @@ -165,96 +182,96 @@ public double localScore(int i, int... parents) { } else if (ruleType == RuleType.GIC6) { // Following Kim, Y., Kwon, S., & Choi, H. (2012). Consistent model selection criteria on high dimensions. - // The Journal of Machine Learning Resjearch, 13(1), 1037-1057. + // The Journal of Machine Learning Research, 13(1), 1037-1057. lambda = log(n) * log(pn); } else { throw new IllegalStateException("That lambda rule is not configured: " + ruleType); } -// double c = penaltyDiscount; - - // private double penaltyDiscount; - // private double correlationThreshold = 1.0; - boolean takeLog = true; - if (takeLog) { - return -(n / 2.0) * log(varry) - lambda * getPenaltyDiscount() * k; - } else { - // The true error variance - double trueErrorVariance = 1.0; - return -(n / 2.0) * (varry) - lambda * getPenaltyDiscount() * k * trueErrorVariance; - } - + return -(n / 2.0) * log(varry) - lambda * getPenaltyDiscount() * k; } /** - * Specialized scoring method for a single parent. Used to speed up the effect edges search. + * Returns the sample size. + * + * @return This size. */ - - -// public double getTrueErrorVariance() { -// return trueErrorVariance; -// } public ICovarianceMatrix getCovariances() { return covariances; } + /** + * Sets the covariance matrix. + * + * @param covariances The covariance matrix. + */ private void setCovariances(ICovarianceMatrix covariances) { -// CorrelationMatrix correlations = new CorrelationMatrix(covariances); this.covariances = covariances; -// this.covariances = covariances; - -// boolean exists = false; - -// for (int i = 0; i < correlations.getSize(); i++) { -// for (int j = 0; j < correlations.getSize(); j++) { -// if (i == j) continue; -// double r = correlations.getValue(i, j); -// if (abs(r) > correlationThreshold) { -// System.out.println("Absolute correlation too high: " + r); -// exists = true; -// } -// } -// } - -// if (exists) { -// throw new IllegalArgumentException("Some correlations are too high (> " + correlationThreshold -// + ") in absolute value."); -// } - - this.N = covariances.getSampleSize(); } + /** + * Returns the sample size. + * + * @return This size. + */ public int getSampleSize() { return sampleSize; } + /** + * Returns true if an edge with this bump is an effect edge. + * + * @param bump The bump. + * @return True if so. + */ @Override public boolean isEffectEdge(double bump) { return bump > 0; } -// public void setTrueErrorVariance(double trueErrorVariance) { -// this.trueErrorVariance = trueErrorVariance; -// } - + /** + * Returns the dataset. + * + * @return The dataset. + */ public DataSet getDataSet() { return dataSet; } + /** + * Returns true if verbose output should be sent to out. + * + * @return True if verbose output should be sent to out. + */ public boolean isVerbose() { return verbose; } + /** + * Sets whether verbose output should be sent to out. + * + * @param verbose True if verbose output should be sent to out. + */ public void setVerbose(boolean verbose) { this.verbose = verbose; } + /** + * Returns the variables of the dataset. + * + * @return These variables as list. + */ @Override public List getVariables() { return variables; } + /** + * Sets the variables of the dataset. + * + * @param variables The variables of the dataset. + */ public void setVariables(List variables) { if (covariances != null) { covariances.setVariables(variables); @@ -263,11 +280,23 @@ public void setVariables(List variables) { this.variables = variables; } + /** + * Returns the max degree of the graph for some algorithms. + * + * @return This max degree. + */ @Override public int getMaxDegree() { return (int) FastMath.ceil(log(sampleSize)); } + /** + * Returns a judgment of whether the variable in z determine y exactly. + * + * @param z The set of nodes. + * @param y The node. + * @return This judgment + */ @Override public boolean determines(List z, Node y) { int i = variables.indexOf(y); @@ -283,54 +312,64 @@ public boolean determines(List z, Node y) { return Double.isNaN(v); } -// public RuleType getRuleType() { -// return ruleType; -// } - + /** + * Sets the rule type. + * + * @param ruleType The rule type. + * @see RuleType + */ public void setRuleType(RuleType ruleType) { this.ruleType = ruleType; } -// public void setPenaltyDiscount(double penaltyDiscount) { -// this.penaltyDiscount = penaltyDiscount; -// } - -// public void setCorrelationThreshold(double correlationThreshold) { -// this.correlationThreshold = correlationThreshold; -// } - -// public void setTakeLog(boolean takeLog) { -// this.takeLog = takeLog; -// } - -// public void setCalculateSquareEuclideanNorms(boolean calculateSquareEuclideanNorms) { -// this.calculateSquareEuclideanNorms = calculateSquareEuclideanNorms; -// } - + /** + * Sets the lambda parameter. + * + * @param lambda The lambda parameter. + */ public void setLambda(double lambda) { this.lambda = lambda; } + /** + * Returns the penalty discount. + * + * @return The penalty discount. + */ public double getPenaltyDiscount() { return penaltyDiscount; } + /** + * Sets the penalty discount. + * + * @param penaltyDiscount The penalty discount. + */ public void setPenaltyDiscount(double penaltyDiscount) { this.penaltyDiscount = penaltyDiscount; } + /** + * Returns a string for this object. + * + * @return A string for this object. + */ public String toString() { return "Generalized Information Criterion Score"; } + /** + * Sets whether to use the pseudo-inverse when calculating the score. + * + * @param usePseudoInverse True if so. + */ public void setUsePseudoInverse(boolean usePseudoInverse) { this.usePseudoInverse = usePseudoInverse; } - /** * Gives the options for the rules to use for calculating the scores. The "GIC" rules, and RICc, are the rules - * proposed in the Kim et al. paper for generalized information criteria.' + * proposed in the Kim et al. paper for generalized information criteria. * * @see GicScores */ diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/GraphScore.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/GraphScore.java index 486cc3dffd..31b802f0af 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/GraphScore.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/GraphScore.java @@ -21,8 +21,6 @@ package edu.cmu.tetrad.search.score; -import edu.cmu.tetrad.data.DataModel; -import edu.cmu.tetrad.data.DataSet; import edu.cmu.tetrad.data.IndependenceFacts; import edu.cmu.tetrad.graph.EdgeListGraph; import edu.cmu.tetrad.graph.Graph; @@ -37,24 +35,22 @@ import java.util.Set; /** - *

                Implements a pscudo-"score" that implmenets implements Chickering and Meek's - * (2002) locally consistent score criterion. This is not a true score; rather, a -1 is returned in case mseparation - * holds and a 1 in case mseparation does not hold. This is only meant to be used in the context of FGES, and allows the - * search to follow its path prescribed by the locally consistent scoring criterion. For a reference to the latter, - * pleasee this article:

                - * - *

                Chickering (2002) "Optimal structure identification with greedy search" - * Journal of Machine Learning Research.

                - * - *

                For further discussion of using m-separation in the GES search, see:

                - * - *

                Nandy, P., Hauser, A., & Maathuis, M. H. (2018). High-dimensional consistency - * in score-based and hybrid structure learning. The Annals of Statistics, 46(6A), 3151-3183.

                - * - *

                For more discussion please see:

                - * - *

                Shen, X., Zhu, S., Zhang, J., Hu, S., & Chen, Z. (2022, August). Reframed GES - * with a neural conditional dependence measure. In Uncertainty in Artificial Intelligence (pp. 1782-1791). PMLR.

                + * Implements a pscudo-"score" that implmenets implements Chickering and Meek's (2002) locally consistent score + * criterion. This is not a true score; rather, a -1 is returned in case mseparation holds and a 1 in case mseparation + * does not hold. This is only meant to be used in the context of FGES, and allows the search to follow its path + * prescribed by the locally consistent scoring criterion. For a reference to the latter, pleasee this article: + *

                + * Chickering (2002) "Optimal structure identification with greedy search" Journal of Machine Learning Research. + *

                + * For further discussion of using m-separation in the GES search, see: + *

                + * Nandy, P., Hauser, A., & Maathuis, M. H. (2018). High-dimensional consistency in score-based and hybrid structure + * learning. The Annals of Statistics, 46(6A), 3151-3183. + *

                + * For more discussion please see: + *

                + * Shen, X., Zhu, S., Zhang, J., Hu, S., & Chen, Z. (2022, August). Reframed GES with a neural conditional + * dependence measure. In Uncertainty in Artificial Intelligence (pp. 1782-1791). PMLR. * * @author josephramsey * @see Fges @@ -63,15 +59,13 @@ public class GraphScore implements Score { // The variables of the covariance matrix. private final List variables; + // The DAG, if supplied. private Graph dag; + // The independence facts, if supplied. private IndependenceFacts facts; - // True if verbose output should be sent to out. - private boolean verbose = false; - private Node n = null; - private List prefix = null; /** - * Constructor + * Constructs a GraphScore from a DAG. * * @param dag A directed acyclic graph. */ @@ -82,7 +76,7 @@ public GraphScore(Graph dag) { } /** - * Constructor. + * Constructs a GraphScore from a list of independence facts. * * @param facts A list known independence facts; a lookup will be donw from these facts. * @see IndependenceFacts @@ -99,27 +93,12 @@ public GraphScore(IndependenceFacts facts) { * @return this score. */ public double localScore(int y, int[] z) { - return getPearlParentsTest().size(); - } - - private Set getPearlParentsTest() { - Set mb = new HashSet<>(); - - for (Node z0 : prefix) { - Set cond = new HashSet<>(prefix); - cond.remove(z0); - - if (dag.paths().isMConnectedTo(n, z0, cond)) { - mb.add(z0); - } - } - - return mb; + throw new UnsupportedOperationException(); } - /** - * Returns a "score difference", which amounts to a conditional local scoring criterion results + * Returns a "score difference", which amounts to a conditional local scoring criterion results. Only difference + * methods is implemented, since the other methods don't make sense here. * * @return The "difference". */ @@ -129,9 +108,9 @@ public double localScoreDiff(int x, int y, int[] z) { } /** - * The "unconditional difference." + * The "unconditional difference." Only difference methods is implemented, since the other methods don't make sense here. * - * @return This. + * @return The "difference". */ @Override public double localScoreDiff(int x, int y) { @@ -153,7 +132,7 @@ public double localScore(int i) { } /** - * Returns a judgment for FGES as to whether a score with the bump is for an effect edge. + * Returns a judgment for FGES whether a score with the bump is for an effect edge. * * @param bump The bump * @return True, if so. @@ -164,13 +143,6 @@ public boolean isEffectEdge(double bump) { return bump > 0; } - /** - * @throws UnsupportedOperationException Since the method doesn't make sense here. - */ - public DataSet getDataSet() { - throw new UnsupportedOperationException(); - } - /** * Returns the list of variables. * @@ -192,14 +164,7 @@ public int getMaxDegree() { } /** - * @throws UnsupportedOperationException Since this "score" does not use data. - */ - public DataModel getData() { - throw new UnsupportedOperationException("This score does not use data."); - } - - /** - * @throws UnsupportedOperationException Since this score does not use data. + * @throws UnsupportedOperationException Since the method doesn't make sense here. */ public int getSampleSize() { throw new UnsupportedOperationException("This score does not use data, so no sample size is available."); @@ -242,18 +207,6 @@ private boolean isMSeparatedFrom(Node x, Node y, Set z) { throw new IllegalArgumentException("Expecting either a DAG or an IndependenceFacts object."); } - private boolean isMConnectedTo(Node x, Node y, Set z) { - return !isMSeparatedFrom(x, y, z); - } - - private List getVariableList(int[] indices) { - List variables = new ArrayList<>(); - for (int i : indices) { - variables.add(this.variables.get(i)); - } - return variables; - } - private Set getVariableSet(int[] indices) { Set variables = new HashSet<>(); for (int i : indices) { diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/ImagesScore.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/ImagesScore.java index 5d3a73a2fd..fc15b50c13 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/ImagesScore.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/ImagesScore.java @@ -29,18 +29,16 @@ import java.util.List; /** - *

                Implements a score to average results over multiple scores. This is - * used for the IMaGES algorithm. The idea is that one pick and algorithm that takes (only) a score as input, such as - * FGES or GRaSP or BOSS, and then constructs an ImagesScore (which class) with a list of datasets as input, using same - * object-identical variables, and feeds this Images score to this algorithm through the contructor. One then runs the - * algorithm to get an estimate of the structure.

                - * - *

                Importantly, only the variables from the first score will be returned - * from the getVariables method, so it is up to the user to ensure that all of the scores share the same - * (object-identical) variables.

                - * - *

                As for all scores in Tetrad, higher scores mean more dependence, and - * negative scores indicate independence.

                + * Implements a score to average results over multiple scores. This is used for the IMaGES algorithm. The idea is that + * one pick and algorithm that takes (only) a score as input, such as FGES or GRaSP or BOSS, and then constructs an + * ImagesScore (which class) with a list of datasets as input, using same object-identical variables, and feeds this + * Images score to this algorithm through the constructor. One then runs the algorithm to get an estimate of the + * structure. + *

                + * Importantly, only the variables from the first score will be returned from the getVariables method, so it is up to + * the user to ensure that all the scores share the same (object-identical) variables. + *

                + * As for all scores in Tetrad, higher scores mean more dependence, and negative scores indicate independence. * * @author josephramsey * @see Fges @@ -51,7 +49,6 @@ public class ImagesScore implements Score { // The covariance matrix. private final List scores; - // The variables of the covariance matrix. private final List variables; @@ -124,6 +121,16 @@ public double localScore(int i, int[] parents) { } } + /** + * Returns the (aggregate) local score for a variable given its parents, which is obtained by averaging the local + * such scores obtained from each individual score provided in the constructor, excluding scores that are returned + * as undefined (which are left out of the average). + * + * @param i The variable whose score is needed. + * @param parents The indices of the parents. + * @param index The index of the score to use. + * @return This score. + */ public double localScore(int i, int[] parents, int index) { return localScoreOneDataSet(i, parents, index); } @@ -176,6 +183,12 @@ public double localScore(int i) { return sum / count; } + /** + * Returns a judgment for FGES whether a score with the bump is for an effect edge. + * + * @param bump The bump. + * @return True if so. + */ @Override public boolean isEffectEdge(double bump) { return scores.get(0).isEffectEdge(bump); @@ -214,6 +227,8 @@ public int getMaxDegree() { /** * Returns the 'determines' judgment from the first score. * + * @param z The set of variables. + * @param y The variable. * @return This judgment, true if the 'determine' relations holds. */ @Override diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/IndTestScore.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/IndTestScore.java index b5a300cfc6..4024a4d0f2 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/IndTestScore.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/IndTestScore.java @@ -35,25 +35,24 @@ * Gives a method of interpreting a test as a score. Various independence tests will calculate p-values; they simply * report alpha - p as a score, which will be higher for greater dependence. This class wraps such an independence test * and returns the score reported by that test. - * - *

                As for all scores in Tetrad, higher scores mean more dependence, and negative - * scores indicate independence.

                + *

                + * As for all scores in Tetrad, higher scores mean more dependence, and negative scores indicate independence. * * @author josephramsey * @see IndependenceTest */ public class IndTestScore implements Score { - + // The independence test. private final IndependenceTest test; - // The variables of the covariance matrix. private final List variables; - // True if verbose output should be sent to out. private boolean verbose; /** * Constructs the score using a covariance matrix. + * + * @param test The independence test. */ public IndTestScore(IndependenceTest test) { this.variables = new ArrayList<>(); @@ -69,20 +68,24 @@ public IndTestScore(IndependenceTest test) { /** * Calculates the sample likelihood and BIC score for i, given its parents in a simple SEM model + * + * @param i The index of the variable. + * @param parents The indices of the parents of i. */ public double localScore(int i, int[] parents) { throw new UnsupportedOperationException(); } - private List getVariableList(int[] indices) { - List variables = new ArrayList<>(); - for (int i : indices) { - variables.add(this.variables.get(i)); - } - return variables; - } - + /** + * Returns a "score difference", which amounts to a conditional local scoring criterion results. Only difference + * methods is implemented, since the other methods don't make sense here. + * + * @param x A node. + * @param y TAhe node. + * @param z A set of nodes. + * @return The "difference". + */ @Override public double localScoreDiff(int x, int y, int[] z) { IndependenceResult result = this.test.checkIndependence(this.variables.get(x), this.variables.get(y), new HashSet<>(getVariableList(z))); @@ -90,53 +93,99 @@ public double localScoreDiff(int x, int y, int[] z) { } /** - * Specialized scoring method for a single parent. Used to speed up the effect edges search. + * @throws UnsupportedOperationException if called. */ public double localScore(int i, int parent) { throw new UnsupportedOperationException(); } + /** + * @throws UnsupportedOperationException if called. + */ public double localScore(int i) { throw new UnsupportedOperationException(); } + /** + * Returns true if the edge with the given bump is an effect edge. + * + * @param bump The bump. + * @return True if so. + */ @Override public boolean isEffectEdge(double bump) { return true; } + /** + * Returns the data set. + * @return The data set. + */ public DataSet getDataSet() { throw new UnsupportedOperationException(); } + /** + * Returns true if verbose output should be sent to out. + * @return True if verbose output should be sent to out. + */ public boolean isVerbose() { return this.verbose; } + /** + * Sets whether verbose output should be sent to out. + * @param verbose True if verbose output should be sent to out. + */ public void setVerbose(boolean verbose) { this.verbose = verbose; } + /** + * Returns the list of variables. + * @return The list of variables. + */ @Override public List getVariables() { return this.variables; } + /** + * Returns the sample size. + * @return The sample size. + */ public int getSampleSize() { return 0; } + /** + * Returns the maximum degree, which is set to 1000. + * @return 1000. + */ @Override public int getMaxDegree() { return 1000; } + /** + * Returns the 'determines' judgment from the first score. + * @param z The set of nodes. + * @param y The node. + * @return This judgment, true if the 'determine' relations holds. + */ @Override public boolean determines(List z, Node y) { return false; } + private List getVariableList(int[] indices) { + List variables = new ArrayList<>(); + for (int i : indices) { + variables.add(this.variables.get(i)); + } + return variables; + } } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/MvpLikelihood.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/MvpLikelihood.java index c03360e8fb..731681d709 100755 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/MvpLikelihood.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/MvpLikelihood.java @@ -38,17 +38,17 @@ /** - *

                Calculates Mixed Variables Polynomial likelihood. The reference is here:

                - * - *

                Andrews, B., Ramsey, J., & Cooper, G. F. (2018). Scoring Bayesian networks of - * mixed variables. International journal of data science and analytics, 6, 3-18.

                + * Calculates Mixed Variables Polynomial likelihood. The reference is here: + *

                + * Andrews, B., Ramsey, J., & Cooper, G. F. (2018). Scoring Bayesian networks of mixed variables. International + * journal of data science and analytics, 6, 3-18. * * @author Bryan Andrews */ public class MvpLikelihood { + // The dataset. private final DataSet dataSet; - // The variables of the dataset. private final List variables; // Indices of variables. @@ -68,6 +68,21 @@ public class MvpLikelihood { // The variables of the discrete dataset. private List discreteVariables; + /** + * Constructs the score using a data set. + * + * @param dataSet A dataset with a mixture of continuous and discrete variables. It may be all continuous or + * @param structurePrior The structure prior. + * @param fDegree F-degree + * @param discretize When a discrete variable is a child of a continuous variable, one (expensive) way to solve + * the problem is to do a numerical integration. A less expensive (and often more accurate) + * way to solve the problem is to discretize the child with a certain number of discrete + * categories. if this parameter is set to True, a separate copy of all variables is + * maintained that is discretized in this way, and these are substituted for the discrete + * children when this sort of problem needs to be solved. This information needs to be known + * in the constructor since one needs to know right away whether ot create this separate + * discretized version of the continuous columns. + */ public MvpLikelihood(DataSet dataSet, double structurePrior, int fDegree, boolean discretize) { if (dataSet == null) { @@ -123,8 +138,14 @@ public MvpLikelihood(DataSet dataSet, double structurePrior, int fDegree, boolea } + /** + * Returns the score of the node at index i, given its parents. + * + * @param child_index The index of the child. + * @param parents The indices of the parents. + * @return The score. + */ public double getLik(int child_index, int[] parents) { - double lik = 0; Node c = this.variables.get(child_index); List continuous_parents = new ArrayList<>(); @@ -154,11 +175,9 @@ public double getLik(int child_index, int[] parents) { for (int j = 0; j < p; j++) continuousCols[j] = this.nodesHash.get(continuous_parents.get(j)); for (List cell : cells) { -// for (int[] cell : cells) { int r = cell.size(); -// int r = cell.length; - if (r > 1) { + if (r > 1) { double[] mean = new double[p]; double[] var = new double[p]; for (int i = 0; i < p; i++) { @@ -194,7 +213,6 @@ public double getLik(int child_index, int[] parents) { Vector target = new Vector(r); for (int i = 0; i < r; i++) { target.set(i, this.continuousData[child_index][cell.get(i)]); -// target.set(i, continuousData[child_index][cell[i]]); } lik += multipleRegression(target, subset); } else { @@ -211,101 +229,13 @@ public double getLik(int child_index, int[] parents) { return lik; } - - private double multipleRegression(Vector Y, Matrix X) { - - int n = X.getNumRows(); - Vector r; - if (X.getNumColumns() >= n) { - Vector ones = new Vector(n); - for (int i = 0; i < n; i++) ones.set(i, 1); - r = ones.scalarMult(ones.dotProduct(Y) / (double) n).minus(Y); - } else { - try { - Matrix Xt = X.transpose(); - Matrix XtX = Xt.times(X); - r = X.times(XtX.inverse().times(Xt.times(Y))).minus(Y); - } catch (Exception e) { - Vector ones = new Vector(n); - for (int i = 0; i < n; i++) ones.set(i, 1); - r = ones.scalarMult(ones.dotProduct(Y) / (double) n).minus(Y); - } - } - - double sigma2 = r.dotProduct(r) / n; - double lik; - - if (sigma2 < 0) { - Vector ones = new Vector(n); - for (int i = 0; i < n; i++) ones.set(i, 1); - r = ones.scalarMult(ones.dotProduct(Y) / (double) FastMath.max(n, 2)).minus(Y); - sigma2 = r.dotProduct(r) / n; - lik = -(n / 2.) * (FastMath.log(2 * FastMath.PI) + FastMath.log(sigma2) + 1); - } else if (sigma2 == 0) { - lik = 0; - } else { - lik = -(n / 2.) * (FastMath.log(2 * FastMath.PI) + FastMath.log(sigma2) + 1); - } - - - if (Double.isInfinite(lik) || Double.isNaN(lik)) { - System.out.println(lik); - } - - return lik; - } - - private double approxMultinomialRegression(Matrix Y, Matrix X) { - - int n = X.getNumRows(); - int d = Y.getNumColumns(); - double lik = 0.0; - Matrix P; - - - if (d >= n || X.getNumColumns() >= n) { - Matrix ones = new Matrix(n, 1); - for (int i = 0; i < n; i++) ones.set(i, 0, 1); - P = ones.times(ones.transpose().times(Y).scalarMult(1 / (double) n)); - } else { - try { - Matrix Xt = X.transpose(); - Matrix XtX = Xt.times(X); - P = X.times(XtX.inverse().times(Xt.times(Y))); - } catch (Exception e) { - Matrix ones = new Matrix(n, 1); - for (int i = 0; i < n; i++) ones.set(i, 0, 1); - P = ones.times(ones.transpose().times(Y).scalarMult(1 / (double) n)); - } - - for (int i = 0; i < n; i++) { - double min = 1; - double center = 1 / (double) d; - double bound = 1 / (double) n; - for (int j = 0; j < d; j++) { - min = FastMath.min(min, P.get(i, j)); - } - if (X.getNumColumns() > 1 && min < bound) { - min = (bound - center) / (min - center); - for (int j = 0; j < d; j++) { - P.set(i, j, min * P.get(i, j) + center * (1 - min)); - } - } - } - } - - for (int i = 0; i < n; i++) { - lik += FastMath.log(P.getRow(i).dotProduct(Y.getRow(i))); - } - - if (Double.isInfinite(lik) || Double.isNaN(lik)) { - System.out.println(lik); - } - - return lik; - } - - + /** + * Returns the score of the node at index i, given its parents. + * + * @param child_index The index of the child. + * @param parents The indices of the parents. + * @return The score. + */ public double getDoF(int child_index, int[] parents) { double dof = 0; @@ -351,8 +281,13 @@ public double getDoF(int child_index, int[] parents) { return dof; } + /** + * Returns the structure prior. + * + * @param k The number of edges. + * @return The structure prior. + */ public double getStructurePrior(int k) { - if (this.structurePrior < 0) { return getEBICprior(); } @@ -375,6 +310,50 @@ public double getEBICprior() { } + private double multipleRegression(Vector Y, Matrix X) { + + int n = X.getNumRows(); + Vector r; + if (X.getNumColumns() >= n) { + Vector ones = new Vector(n); + for (int i = 0; i < n; i++) ones.set(i, 1); + r = ones.scalarMult(ones.dotProduct(Y) / (double) n).minus(Y); + } else { + try { + Matrix Xt = X.transpose(); + Matrix XtX = Xt.times(X); + r = X.times(XtX.inverse().times(Xt.times(Y))).minus(Y); + } catch (Exception e) { + Vector ones = new Vector(n); + for (int i = 0; i < n; i++) ones.set(i, 1); + r = ones.scalarMult(ones.dotProduct(Y) / (double) n).minus(Y); + } + } + + double sigma2 = r.dotProduct(r) / n; + double lik; + + if (sigma2 < 0) { + Vector ones = new Vector(n); + for (int i = 0; i < n; i++) ones.set(i, 1); + r = ones.scalarMult(ones.dotProduct(Y) / (double) FastMath.max(n, 2)).minus(Y); + sigma2 = r.dotProduct(r) / n; + lik = -(n / 2.) * (FastMath.log(2 * FastMath.PI) + FastMath.log(sigma2) + 1); + } else if (sigma2 == 0) { + lik = 0; + } else { + lik = -(n / 2.) * (FastMath.log(2 * FastMath.PI) + FastMath.log(sigma2) + 1); + } + + + if (Double.isInfinite(lik) || Double.isNaN(lik)) { + System.out.println(lik); + } + + return lik; + } + + private DataSet useErsatzVariables() { List nodes = new ArrayList<>(); // Number of categories to use to discretize continuous mixedVariables. @@ -417,4 +396,53 @@ private DataSet useErsatzVariables() { return replaced; } + private double approxMultinomialRegression(Matrix Y, Matrix X) { + + int n = X.getNumRows(); + int d = Y.getNumColumns(); + double lik = 0.0; + Matrix P; + + + if (d >= n || X.getNumColumns() >= n) { + Matrix ones = new Matrix(n, 1); + for (int i = 0; i < n; i++) ones.set(i, 0, 1); + P = ones.times(ones.transpose().times(Y).scalarMult(1 / (double) n)); + } else { + try { + Matrix Xt = X.transpose(); + Matrix XtX = Xt.times(X); + P = X.times(XtX.inverse().times(Xt.times(Y))); + } catch (Exception e) { + Matrix ones = new Matrix(n, 1); + for (int i = 0; i < n; i++) ones.set(i, 0, 1); + P = ones.times(ones.transpose().times(Y).scalarMult(1 / (double) n)); + } + + for (int i = 0; i < n; i++) { + double min = 1; + double center = 1 / (double) d; + double bound = 1 / (double) n; + for (int j = 0; j < d; j++) { + min = FastMath.min(min, P.get(i, j)); + } + if (X.getNumColumns() > 1 && min < bound) { + min = (bound - center) / (min - center); + for (int j = 0; j < d; j++) { + P.set(i, j, min * P.get(i, j) + center * (1 - min)); + } + } + } + } + + for (int i = 0; i < n; i++) { + lik += FastMath.log(P.getRow(i).dotProduct(Y.getRow(i))); + } + + if (Double.isInfinite(lik) || Double.isNaN(lik)) { + System.out.println(lik); + } + + return lik; + } } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/MvpScore.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/MvpScore.java index 49c406a812..cbbb83f5d2 100755 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/MvpScore.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/MvpScore.java @@ -28,23 +28,20 @@ import java.util.List; /** - *

                Implements a mixed variable polynomial BIC score. The reference is here:

                - * - *

                Andrews, B., Ramsey, J., & Cooper, G. F. (2018). Scoring Bayesian networks of - * mixed variables. International journal of data science and analytics, 6, 3-18.

                + * Implements a mixed variable polynomial BIC score. The reference is here: + *

                + * Andrews, B., Ramsey, J., & Cooper, G. F. (2018). Scoring Bayesian networks of mixed variables. International + * journal of data science and analytics, 6, 3-18. * * @author Bryan Andrews */ public class MvpScore implements Score { - + // The mixed variables of the original dataset. private final DataSet dataSet; - // The variables of the continuousData set. private final List variables; - // Likelihood function private final MvpLikelihood likelihood; - // Log number of instances private final double logn; @@ -69,6 +66,10 @@ public MvpScore(DataSet dataSet, double structurePrior, int fDegree, boolean dis /** * The local score of the child given its parents. + * + * @param i The child. + * @param parents The parents. + * @return The local score. */ public double localScore(int i, int... parents) { @@ -90,7 +91,12 @@ public double localScore(int i, int... parents) { } /** - * localScore(y | z, x) - localScore(y | z). + * Returns localScore(y | z, x) - localScore(y | z). + * + * @param x A node. + * @param y The node. + * @param z A set of nodes. + * @return The score difference. */ public double localScoreDiff(int x, int y, int[] z) { return localScore(y, append(z, x)) - localScore(y, z); @@ -117,21 +123,36 @@ public boolean isEffectEdge(double bump) { return bump > 0; } + /** + * Returns the list of variables. + * + * @return This list. + */ @Override public List getVariables() { return this.variables; } + /** + * Returns an estimate of the maximum degree of the graph for some algorithms. + * + * @return This maximum. + */ @Override public int getMaxDegree() { return (int) FastMath.ceil(FastMath.log(this.dataSet.getNumRows())); } + /** + * Returns a judgment of whether the variable in z determine y exactly. + * @param z The set of nodes. + * @param y The node. + * @return This judgment. + */ @Override public boolean determines(List z, Node y) { return false; } - } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/PoissonPriorScore.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/PoissonPriorScore.java index d7b422ac50..5055ea0366 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/PoissonPriorScore.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/PoissonPriorScore.java @@ -33,16 +33,15 @@ import static org.apache.commons.math3.util.FastMath.*; /** - *

                Implements Poisson prior score, a novel (unpubished) score that replaces the - * penalty term in BIC by the log of the Poisson distribution. The Poisson distribution has a lambda parameter, which is - * made a parameter of this score and acts like a structure prior for the score.

                - * - *

                Here is the Wikipedia page for the Poisson distribution, for reference:

                - * - *

                https://en.wikipedia.org/wiki/Poisson_distribution

                - * - *

                As for all scores in Tetrad, higher scores mean more dependence, and negative - * scores indicate independence.

                + * Implements Poisson prior score, a novel (unpubished) score that replaces the penalty term in BIC by the log of the + * Poisson distribution. The Poisson distribution has a lambda parameter, which is made a parameter of this score and + * acts like a structure prior for the score. + *

                + * Here is the Wikipedia page for the Poisson distribution, for reference: + *

                + * https://en.wikipedia.org/wiki/Poisson_distribution + *

                + * As for all scores in Tetrad, higher scores mean more dependence, and negative scores indicate independence. * * @author bryanandrews * @author josephramsey @@ -56,23 +55,21 @@ public class PoissonPriorScore implements Score { private DataSet dataSet; // The covariance matrix. private ICovarianceMatrix covariances; - // True if verbose output should be sent to out. - private boolean verbose; - // Sample size or equivalent sample size. private double N; - // The data, if it is set. private Matrix data; - // True if row subsets should be calculated. private boolean calculateRowSubsets; - + // The lambda parameter. private double lambda = 3.; + // True if the pseudo-inverse should be used. private boolean usePseudoInverse = false; /** * Constructs the score using a covariance matrix. + * + * @param covariances The covariance matrix. */ public PoissonPriorScore(ICovarianceMatrix covariances) { if (covariances == null) { @@ -86,6 +83,9 @@ public PoissonPriorScore(ICovarianceMatrix covariances) { /** * Constructs the score using a covariance matrix. + * + * @param dataSet The dataset. + * @param precomputeCovariances Whether the covariances should be precomputed or computed on the fly. True if */ public PoissonPriorScore(DataSet dataSet, boolean precomputeCovariances) { @@ -110,16 +110,22 @@ public PoissonPriorScore(DataSet dataSet, boolean precomputeCovariances) { } - private static double getP(int pn, int m0, double lambda) { - return 2 - pow(1 + (exp(-(lambda - 1) / 2.)) * sqrt(lambda), (double) pn - m0); - } - + /** + * Returns the score difference localScore(y | z, x) - localScore(y | z). + * + * @param x A node. + * @param y TAhe node. + * @param z A set of nodes. + * @return The score difference. + */ @Override public double localScoreDiff(int x, int y, int[] z) { return localScore(y, append(z, x)) - localScore(y, z); } /** + * Returns the score of the node at index i, given its parents. + * * @param i The index of the node. * @param parents The indices of the node's parents. * @return The score, or NaN if the score cannot be calculated. @@ -149,6 +155,11 @@ public double localScore(int i, int... parents) throws RuntimeException { } } + /** + * Returns the covariance matrix. + * + * @return The covariance matrix. + */ public ICovarianceMatrix getCovariances() { return this.covariances; } @@ -180,29 +191,53 @@ private void setCovariances(ICovarianceMatrix covariances) { this.N = covariances.getSampleSize(); } + /** + * Returns the sample size. + * + * @return This size. + */ public int getSampleSize() { return this.sampleSize; } + /** + * Returns true if the edge with the given bump is an effect edge. + * + * @param bump The bump. + * @return True if so. + */ @Override public boolean isEffectEdge(double bump) { return bump > 0; } - public void setVerbose(boolean verbose) { - this.verbose = verbose; - } - + /** + * Returns the variables. + * + * @return This list. + */ @Override public List getVariables() { return this.variables; } + /** + * Returns the max degree. + * + * @return This maximum. + */ @Override public int getMaxDegree() { return (int) ceil(log(this.sampleSize)); } + /** + * Returns true if z determines y. + * + * @param z The set of nodes. + * @param y The node. + * @return True if z determines y. + */ @Override public boolean determines(List z, Node y) { int i = this.variables.indexOf(y); @@ -211,24 +246,39 @@ public boolean determines(List z, Node y) { return Double.isNaN(v); } + /** + * Returns the data set. + * + * @return The data set. + */ public DataModel getData() { return this.dataSet; } + /** + * Sets the lambda parameter. + * + * @param lambda The lambda parameter. + */ public void setLambda(double lambda) { if (lambda < 1.0) throw new IllegalArgumentException("Poisso lambda can't be < 1: " + lambda); this.lambda = lambda; } + /** + * Sets whether the pseudo-inverse should be used. + * + * @param usePseudoInverse True if the pseudo-inverse should be used. + */ + public void setUsePseudoInverse(boolean usePseudoInverse) { + this.usePseudoInverse = usePseudoInverse; + } + private int[] indices(List __adj) { int[] indices = new int[__adj.size()]; for (int t = 0; t < __adj.size(); t++) indices[t] = this.variables.indexOf(__adj.get(t)); return indices; } - - public void setUsePseudoInverse(boolean usePseudoInverse) { - this.usePseudoInverse = usePseudoInverse; - } } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/ScoredGraph.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/ScoredGraph.java index e8e9f2260f..3af7d35c4c 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/ScoredGraph.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/ScoredGraph.java @@ -26,6 +26,8 @@ import edu.cmu.tetrad.util.TetradSerializable; import org.jetbrains.annotations.NotNull; +import java.io.Serial; + /** * Stores a graph with a score for the graph. The equals, hashcode, and compare methods are overridden so that it will * be easy to put these stored graphs into sets and lists. @@ -33,31 +35,67 @@ * @author josephramsey */ public class ScoredGraph implements Comparable, TetradSerializable { + @Serial private static final long serialVersionUID = 23L; + + // The graph. private final Graph graph; + // The score. private final Double score; + /** + * Constructs a scored graph. + * + * @param graph The graph. + * @param score The score. + */ public ScoredGraph(Graph graph, Double score) { this.graph = graph; this.score = score; } + /** + * Returns a serializable instance of this class. + * + * @return A serializable instance of this class. + */ public static ScoredGraph serializableInstance() { return new ScoredGraph(new EdgeListGraph(), 0.0); } + /** + * Returns the graph. + * + * @return The graph. + */ public Graph getGraph() { return this.graph; } + /** + * Returns the score. + * + * @return The score. + */ public double getScore() { return this.score; } + /** + * Return s the hashcode of the score. + * + * @return The hashcode of the score. + */ public int hashCode() { return this.score.hashCode(); } + /** + * Returns true if the scoreed graph and this scored graph are equal. + * + * @param o The other scored graph. + * @return True if the score and graph are equal. + */ public boolean equals(ScoredGraph o) { if (!this.score.equals(o.getScore())) { return false; @@ -66,6 +104,13 @@ public boolean equals(ScoredGraph o) { return this.graph.equals(o.getGraph()); } + /** + * Returns a compare value for this scored graph compared ot the given scored graph. + * + * @param o the object to be compared. + * @return a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than + * the specified object. + */ public int compareTo(@NotNull ScoredGraph o) { Double thisScore = getScore(); Double otherScore = o.getScore(); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/SemBicScore.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/SemBicScore.java index 5536d1ddcc..2289c9dab3 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/SemBicScore.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/SemBicScore.java @@ -57,9 +57,9 @@ * Nandy, P., Hauser, A., & Maathuis, M. H. (2018). High-dimensional consistency in score-based and hybrid structure * learning. The Annals of Statistics, 46(6A), 3151-3183. *

                - * This score may be used anywhere though where a linear, Gaussian score is needed. Anectodally, the score is fairly - * robust to non-Gaussianity, though with some additional unfaithfulness over and above waht the score would give for - * Guassian data, a detriment that can be overcome to an extent by use a permutation algorithm such as SP, GRaSP, or + * This score may be used anywhere though where a linear, Gaussian score is needed. Anecdotally, the score is fairly + * robust to non-Gaussianity, though with some additional unfaithfulness over and above what the score would give for + * Gaussian data, a detriment that can be overcome to an extent by use a permutation algorithm such as SP, GRaSP, or * BOSS. *

                * As for all scores in Tetrad, higher scores mean more dependence, and negative scores indicate independence. @@ -76,7 +76,9 @@ public class SemBicScore implements Score { private final int sampleSize; // A map from variable names to their indices. private final Map indexMap; + // The log of the sample size. private final double logN; + // True if row subsets should be calculated. private boolean calculateRowSubsets; // The dataset. private DataModel dataModel; @@ -90,22 +92,19 @@ public class SemBicScore implements Score { private boolean verbose; // The penalty penaltyDiscount, 1 for standard BIC. private double penaltyDiscount = 1.0; - // The structure prior, 0 for standard BIC. private double structurePrior; - - // Equivalent sample size + // The covariance matrix. private Matrix matrix; - // The rule type to use. private RuleType ruleType = RuleType.CHICKERING; - // True iff the pseudo-inverse should be used instead of the inverse to avoid exceptions. private boolean usePseudoInverse = false; - /** * Constructs the score using a covariance matrix. + * + * @param covariances The covariance matrix. */ public SemBicScore(ICovarianceMatrix covariances) { if (covariances == null) { @@ -121,6 +120,9 @@ public SemBicScore(ICovarianceMatrix covariances) { /** * Constructs the score using a covariance matrix. + * + * @param dataSet The dataset. + * @param precomputeCovariances Whether the covariances should be precomputed or computed on the fly. True if */ public SemBicScore(DataSet dataSet, boolean precomputeCovariances) { @@ -158,26 +160,26 @@ public SemBicScore(DataSet dataSet, boolean precomputeCovariances) { * @param calculateRowSubsets True if row subsets should be calculated. * @return The variance of the residual of the regression of the ith variable on its parents. */ - public static double getVarRy(int i, int[] parents, Matrix data, ICovarianceMatrix covariances, boolean calculateRowSubsets) { - return SemBicScore.getVarRy(i, parents, data, covariances, calculateRowSubsets, false); + public static double getVarRy(int i, int[] parents, Matrix data, ICovarianceMatrix covariances, + boolean calculateRowSubsets, boolean usePseudoInverse) + throws SingularMatrixException { + CovAndCoefs covAndcoefs = getCovAndCoefs(i, parents, data, covariances, calculateRowSubsets, usePseudoInverse); + return (bStar(covAndcoefs.b()).transpose().times(covAndcoefs.cov()).times(bStar(covAndcoefs.b())).get(0, 0)); } /** - * Returns the variance of the residual of the regression of the ith variable on its parents. + * Returns the covariance matrix of the regression of the ith variable on its parents and the regression + * coefficients. * * @param i The index of the variable. * @param parents The indices of the parents. + * @param data The data matrix. * @param covariances The covariance matrix. * @param calculateRowSubsets True if row subsets should be calculated. - * @return The variance of the residual of the regression of the ith variable on its parents. + * @param usePseudoInverse True if the pseudo-inverse should be used instead of the inverse to avoid exceptions. + * @return The covariance matrix of the regression of the ith variable on its parents and the regression + * coefficients. */ - public static double getVarRy(int i, int[] parents, Matrix data, ICovarianceMatrix covariances, - boolean calculateRowSubsets, boolean usePseudoInverse) - throws SingularMatrixException { - CovAndCoefs covAndcoefs = getCovAndCoefs(i, parents, data, covariances, calculateRowSubsets, usePseudoInverse); - return (bStar(covAndcoefs.b()).transpose().times(covAndcoefs.cov()).times(bStar(covAndcoefs.b())).get(0, 0)); - } - @NotNull public static SemBicScore.CovAndCoefs getCovAndCoefs(int i, int[] parents, Matrix data, ICovarianceMatrix covariances, boolean calculateRowSubsets, boolean usePseudoInverse) { int[] all = SemBicScore.concat(i, parents); @@ -198,9 +200,6 @@ public static SemBicScore.CovAndCoefs getCovAndCoefs(int i, int[] parents, Matri return new CovAndCoefs(cov, b); } - public record CovAndCoefs(Matrix cov, Matrix b) { - } - @NotNull private static Matrix bStar(Matrix b) { Matrix byx = new Matrix(b.getNumRows() + 1, 1); @@ -277,15 +276,16 @@ private static List getRows(int i, int[] parents, Matrix data, boolean return rows; } + /** + * Returns the covariance matrix of the regression of the ith variable on its parents and the regression + * coefficients. + * + * @param usePseudoInverse True if the pseudo-inverse should be used instead of the inverse to avoid exceptions. + */ public void setUsePseudoInverse(boolean usePseudoInverse) { this.usePseudoInverse = usePseudoInverse; } - @NotNull - private ICovarianceMatrix getCovarianceMatrix(DataSet dataSet, boolean precomputeCovariances) { - return SimpleDataLoader.getCovarianceMatrix(dataSet, precomputeCovariances); - } - @Override public double localScoreDiff(int x, int y, int[] z) { if (this.ruleType == RuleType.NANDY) { @@ -527,6 +527,40 @@ public DataModel getData() { return this.dataModel; } + /** + * Sets the rule type to use. + * + * @param ruleType The rule type to use. + * @see RuleType + */ + public void setRuleType(RuleType ruleType) { + this.ruleType = ruleType; + } + + /** + * Returns a SEM BIC score for the given subset of variables. + * + * @param subset The subset of variables. + * @return A SEM BIC score for the given subset of variables. + */ + public SemBicScore subset(List subset) { + int[] cols = new int[subset.size()]; + for (int i = 0; i < cols.length; i++) { + cols[i] = variables.indexOf(subset.get(i)); + } + ICovarianceMatrix cov = getCovariances().getSubmatrix(cols); + return new SemBicScore(cov); + } + + /** + * Returns a string representation of this score. + * + * @return A string representation of this score. + */ + public String toString() { + return "SEM BIC Score"; + } + private double getStructurePrior(int parents) { if (abs(getStructurePrior()) <= 0) { return 0; @@ -649,27 +683,17 @@ private Matrix getCov(List rows, int[] cols) { return cov; } - public void setRuleType(RuleType ruleType) { - this.ruleType = ruleType; - } - - public SemBicScore subset(List pi2) { - int[] cols = new int[pi2.size()]; - for (int i = 0; i < cols.length; i++) { - cols[i] = variables.indexOf(pi2.get(i)); - } - ICovarianceMatrix cov = getCovariances().getSubmatrix(cols); - return new SemBicScore(cov); - } - - public String toString() { - return "SEM BIC Score"; + private ICovarianceMatrix getCovarianceMatrix(DataSet dataSet, boolean precomputeCovariances) { + return SimpleDataLoader.getCovarianceMatrix(dataSet, precomputeCovariances); } /** * Gives two options for calculating the BIC score, one describe by Chickering and the other due to Nandy et al. */ public enum RuleType {CHICKERING, NANDY} + + public record CovAndCoefs(Matrix cov, Matrix b) { + } } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/ZsbScore.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/ZsbScore.java index 4b550e6252..0212777053 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/ZsbScore.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/ZsbScore.java @@ -37,26 +37,24 @@ import static org.apache.commons.math3.util.FastMath.*; /** - *

                Implements an unpublished score based on a risk bound due to - * Zhang and Shen. It adapts Theorem 1 in the following reference:

                - * - *

                Zhang, Y., & Shen, X. (2010). Model selection procedure for - * high‐dimensional data. Statistical Analysis and Data Mining: The ASA Data Science Journal, 3(5), 350-358

                - * - *

                The score uses Theorem 1 in the above to numerically search - * for a lambda value that is bounded by a given probability risk, between 0 and 1, if outputting a local false positive - * parent for a variable. There is a parameter m0, which is a maximum number of parents for a particular variable, which - * is free. The solution of this score is to increase m0 from 0 upward, re-evaluating with each scoring that is done - * using that variable as a target node. Thus, over time, a lower bound on m0 is estimated with more and more precision. - * So as the score is used in the context of FGES or GRaSP, for instance, so long as the score for a given node is - * visited more than once, the scores output by the procedure can be expected to improve, though setting m0 to 0 for all - * variables does not give bad results even by itself.

                - * - *

                This score is conservative for large, dense models and faster - * than other available scores in this package. The risk bound is easily interpreted.

                - * - *

                As for all scores in Tetrad, higher scores mean more dependence, - * and negative scores indicate independence.

                + * Implements an unpublished score based on a risk bound due to Zhang and Shen. It adapts Theorem 1 in the following + * reference: + *

                + * Zhang, Y., & Shen, X. (2010). Model selection procedure for high‐dimensional data. Statistical Analysis and Data + * Mining: The ASA Data Science Journal, 3(5), 350-358 + *

                + * The score uses Theorem 1 in the above to numerically search for a lambda value that is bounded by a given probability + * risk, between 0 and 1, if outputting a local false positive parent for a variable. There is a parameter m0, which is + * a maximum number of parents for a particular variable, which is free. The solution of this score is to increase m0 + * from 0 upward, re-evaluating with each scoring that is done using that variable as a target node. Thus, over time, a + * lower bound on m0 is estimated with more and more precision. So as the score is used in the context of FGES or GRaSP, + * for instance, so long as the score for a given node is visited more than once, the scores output by the procedure can + * be expected to improve, though setting m0 to 0 for all variables does not give bad results even by itself. + *

                + * This score is conservative for large, dense models and faster than other available scores in this package. The risk + * bound is easily interpreted. + *

                + * As for all scores in Tetrad, higher scores mean more dependence, and negative scores indicate independence. * * @author josephramsey */ @@ -80,7 +78,7 @@ public class ZsbScore implements Score { private List lambdas; // The data, if it is set. private Matrix data; - + // True if the pseudo-inverse should be used. private boolean usePseudoInverse; /** @@ -194,6 +192,11 @@ public double localScoreDiff(int x, int y, int[] z) { return localScore(y, append(z, x)) - localScore(y, z); } + /** + * Returns the covariance matrix. + * + * @return The covariance matrix. + */ public ICovarianceMatrix getCovariances() { return covariances; } @@ -291,6 +294,15 @@ public void setRiskBound(double riskBound) { this.riskBound = riskBound; } + /** + * Sets whether to use the pseudo-inverse in place of the inverse in the score. + * + * @param usePseudoInverse True if the pseudo-inverse should be used. + */ + public void setUsePseudoInverse(boolean usePseudoInverse) { + this.usePseudoInverse = usePseudoInverse; + } + private double getLambda(int m0, int pn) { if (lambdas == null) { lambdas = new ArrayList<>(); @@ -311,10 +323,6 @@ private int[] indices(List __adj) { for (int t = 0; t < __adj.size(); t++) indices[t] = variables.indexOf(__adj.get(t)); return indices; } - - public void setUsePseudoInverse(boolean usePseudoInverse) { - this.usePseudoInverse = usePseudoInverse; - } } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/package-info.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/package-info.java index df4cb0efd7..4e731ff2d1 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/package-info.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/package-info.java @@ -1,4 +1,4 @@ /** - * Contains classes for various various sorts of scores for running score-based algorithms. + * Contains classes for various sorts of scores for running score-based algorithms. */ package edu.cmu.tetrad.search.score; From 78e12628ea77810b4f73370da14a563122db9473 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Wed, 24 Jan 2024 15:53:54 -0500 Subject: [PATCH 114/163] Cleaned up code and documentation in the score package. --- .../java/edu/cmu/tetrad/search/score/DiscreteBicScore.java | 5 ++--- .../src/main/java/edu/cmu/tetrad/search/score/ZsbScore.java | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/DiscreteBicScore.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/DiscreteBicScore.java index a15de2fabe..9fcdc82f0c 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/DiscreteBicScore.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/DiscreteBicScore.java @@ -38,9 +38,8 @@ * 1)) for all conditional probability tables in the model, where rows summing to zero are discounted, as their marginal * probabilities cannot be calcualted. Then the BIC score is calculated as 2L - ck ln N, where c is a multiplier on the * penalty ("penalty discount"). - * - *

                As for all scores in Tetrad, higher scores mean more dependence, and negative - * scores indicate independence.

                + *

                + * As for all scores in Tetrad, higher scores mean more dependence, and negative scores indicate independence. * * @author josephramsey */ diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/ZsbScore.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/ZsbScore.java index 0212777053..f7d52e4dad 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/ZsbScore.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/ZsbScore.java @@ -40,8 +40,8 @@ * Implements an unpublished score based on a risk bound due to Zhang and Shen. It adapts Theorem 1 in the following * reference: *

                - * Zhang, Y., & Shen, X. (2010). Model selection procedure for high‐dimensional data. Statistical Analysis and Data - * Mining: The ASA Data Science Journal, 3(5), 350-358 + * Zhang, Y., & Shen, X. (2010). Model selection procedure for high‐dimensional data. Statistical Analysis and Data + * Mining: The ASA Data Science Journal, 3(5), 350-358 *

                * The score uses Theorem 1 in the above to numerically search for a lambda value that is bounded by a given probability * risk, between 0 and 1, if outputting a local false positive parent for a variable. There is a parameter m0, which is From 240d2e0fad7076ae618e85d4ddd38cb6e91fba23 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Wed, 24 Jan 2024 15:57:26 -0500 Subject: [PATCH 115/163] Cleaned up code and documentation in the score package. --- .../main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java index 9d03127aac..aa37527a04 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java @@ -46,16 +46,12 @@ public class ChiSquareTest { // The data set this test uses. private final DataSet dataSet; - // The number of values for each variable in the data. private final int[] dims; - // Stores the data in the form of a cell table. private final CellTable cellTable; - // The type of test to perform. private final TestType testType; - // The significance level of the test. private double alpha; From 7c8470dd1271fb09e570700d4da3b45615207b57 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Thu, 25 Jan 2024 02:28:28 -0500 Subject: [PATCH 116/163] Cleaned up the search.util package. --- .../cmu/tetrad/search/utils/AdLeafTree.java | 1 - .../tetrad/search/utils/BayesImParser.java | 3 +- .../java/edu/cmu/tetrad/search/utils/Bes.java | 37 +++++++----- .../tetrad/search/utils/BesPermutation.java | 19 +++--- .../tetrad/search/utils/BpcAlgorithmType.java | 7 +++ .../search/utils/ClusterSignificance.java | 54 +++++++++++++++-- .../cmu/tetrad/search/utils/ClusterUtils.java | 60 ++++++++++++++++++- .../search/utils/DagInCpcagIterator.java | 13 ++-- .../cmu/tetrad/search/utils/DagIterator.java | 10 ++-- .../cmu/tetrad/search/utils/DagSepsets.java | 2 +- 10 files changed, 162 insertions(+), 44 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/AdLeafTree.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/AdLeafTree.java index a4c96872b2..c8eb64b54c 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/AdLeafTree.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/AdLeafTree.java @@ -60,7 +60,6 @@ public AdLeafTree(DataSet dataSet) { Node v = dataSet.getVariable(j); this.nodesHash.put(v, j); } - } /** diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/BayesImParser.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/BayesImParser.java index 605a6ba104..428fde9518 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/BayesImParser.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/BayesImParser.java @@ -43,6 +43,7 @@ */ public class BayesImParser { + // Whether to use display names. private boolean useDisplayNames; /** @@ -61,7 +62,7 @@ public void setUseDisplayNames(boolean useDisplayNames) { } /** - * Takes an xml representation of a Bayes IM and reinstantiates the IM + * Takes an xml representation of a Bayes IM and reinstantiates the IM. * * @param element the xml of the IM * @return the BayesIM diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/Bes.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/Bes.java index bbc0753016..f0a0bf85eb 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/Bes.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/Bes.java @@ -20,16 +20,14 @@ /** - *

                Extracts the backward step of GES for use GES but also in other - * algorithms. The GES algorithm consists of a forward phase (FES = Forward Equivalence Search) and a backward phase - * (BES = Backward Equivalence Search). We find the BES step by itself is useful in a number of algorithms, so we - * extract this step and give as a separate algorithm.

                - * - *

                The idea of the backward search is to start with a model that is - * Markov and removed edges from it and do the corresponding reorientations, improving the score each time, until the - * score can no longer be improved.

                - *

                We use the optimized implementation used in the FGES implementation - * of GES.

                + * Extracts the backward step of GES for use GES but also in other algorithms. The GES algorithm consists of a forward + * phase (FES = Forward Equivalence Search) and a backward phase (BES = Backward Equivalence Search). We find the BES + * step by itself is useful in a number of algorithms, so we extract this step and give as a separate algorithm. + *

                + * The idea of the backward search is to start with a model that is Markov and removed edges from it and do the + * corresponding reorientations, improving the score each time, until the score can no longer be improved. + *

                + * We use the optimized implementation used in the FGES implementation of GES. * * @author bryanandrews * @author josephramsey @@ -37,12 +35,23 @@ * @see Boss */ public class Bes { + + // The variables being searched over. private final List variables; + // The score. private final Score score; + // The knowledge. private Knowledge knowledge = new Knowledge(); + // True if verbose output should be printed. private boolean verbose = true; + // The depth of the search. private int depth = 4; + /** + * Constructs the search. + * + * @param score The score. + */ public Bes(@NotNull Score score) { this.score = score; this.variables = score.getVariables(); @@ -139,10 +148,6 @@ public void bes(Graph graph, List variables) { } } - private Knowledge getKnowledge() { - return knowledge; - } - /** * Sets the knowledge for the search. * @@ -153,6 +158,10 @@ public void setKnowledge(Knowledge knowledge) { this.knowledge = new Knowledge((Knowledge) knowledge); } + private Knowledge getKnowledge() { + return knowledge; + } + private void delete(Node x, Node y, Set H, double bump, Set naYX, Graph graph) { Edge oldxy = graph.getEdge(x, y); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/BesPermutation.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/BesPermutation.java index 0242ddaa16..25c6a89d47 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/BesPermutation.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/BesPermutation.java @@ -37,11 +37,14 @@ * @see Boss */ public class BesPermutation { + // The variables. private final List variables; + // The score. private final Score score; + // The knowledge. private Knowledge knowledge = new Knowledge(); + // Whether verbose output should be printed. private boolean verbose = true; - private int depth = -1; /** * Constructor. @@ -81,15 +84,11 @@ private void buildIndexing(List nodes, Map hashIndices) { } } -// public void setDepth(int depth) { -// if (depth < -1) throw new IllegalArgumentException("Depth should be >= -1."); -// this.depth = depth; -// } - /** * Runs BES. - * @param graph The graph. - * @param order The order. + * + * @param graph The graph. + * @param order The order. * @param suborder The suborder. */ public void bes(Graph graph, List order, List suborder) { @@ -238,7 +237,7 @@ public Knowledge getKnowledge() { * @param knowledge This knowledge. */ public void setKnowledge(Knowledge knowledge) { - this.knowledge = new Knowledge((Knowledge) knowledge); + this.knowledge = new Knowledge(knowledge); } private Set revertToCPDAG(Graph graph) { @@ -442,6 +441,8 @@ private void calculateArrowsBackward(Node a, Node b, Graph if (storedConfig != null && storedConfig.equals(config)) return; arrowsMapBackward.put(directedEdge(a, b), new ArrowConfigBackward(naYX, parents)); + // The depth. + int depth = -1; int _depth = min(depth, _naYX.size()); final SublistGenerator gen = new SublistGenerator(_naYX.size(), _depth);//_naYX.size()); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/BpcAlgorithmType.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/BpcAlgorithmType.java index a130741bb5..c2f34dd8a3 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/BpcAlgorithmType.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/BpcAlgorithmType.java @@ -25,6 +25,8 @@ /** * Enumerates the algorithm types for BuildPureClusters, and Purify. + * + * @author josephramsey */ public enum BpcAlgorithmType implements TetradSerializable { BUILD_PURE_CLUSTERS, @@ -41,6 +43,11 @@ public static BpcAlgorithmType serializableInstance() { return BpcAlgorithmType.BUILD_PURE_CLUSTERS; } + /** + * Returns the algorithm descriptions. + * + * @return The algorithm descriptions. + */ public static BpcAlgorithmType[] getAlgorithmDescriptions() { return new BpcAlgorithmType[]{ BpcAlgorithmType.BUILD_PURE_CLUSTERS, diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/ClusterSignificance.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/ClusterSignificance.java index 4d000327a9..d96e16496c 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/ClusterSignificance.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/ClusterSignificance.java @@ -25,11 +25,19 @@ * @author josephramsey */ public class ClusterSignificance { - + // The variables in the model. private final List variables; + // The data model. private final DataModel dataModel; + // The type of check to perform. private CheckType checkType = CheckType.Clique; + /** + * Constructs a new cluster significance object. + * + * @param variables The variables in the model. + * @param dataModel The data model. + */ public ClusterSignificance(List variables, DataModel dataModel) { if (variables == null) throw new NullPointerException("Variable null."); if (dataModel == null) throw new NullPointerException("Data model null."); @@ -37,6 +45,13 @@ public ClusterSignificance(List variables, DataModel dataModel) { this.dataModel = dataModel; } + /** + * Converts a list of indices into a list of Nodes representing a cluster. + * + * @param cluster The indices of the variables. + * @param variables The variables. + * @return The extracted node list. + */ public static List variablesForIndices(List cluster, List variables) { List _cluster = new ArrayList<>(); @@ -47,6 +62,13 @@ public static List variablesForIndices(List cluster, List v return _cluster; } + /** + * Converts a list of indices into a list of Nodes representing a cluster. + * + * @param clusters The indices of the variables. + * @param _variables The variables. + * @return The extracted node list. + */ public static List> variablesForIndices2(Set> clusters, List _variables) { List> variables = new ArrayList<>(); @@ -75,10 +97,15 @@ private static int dofHarman(int n) { return dof; } - public void printClusterPValues(Set> out) { + /** + * Prints the p-values for the given clusters. + * + * @param clusters The clusters. + */ + public void printClusterPValues(Set> clusters) { NumberFormat nf = new DecimalFormat("0.000"); - for (List _out : out) { + for (List _out : clusters) { ClusterSignificance clusterSignificance = new ClusterSignificance(variables, dataModel); try { @@ -92,10 +119,23 @@ public void printClusterPValues(Set> out) { } } + /** + * Sets the type of check to perform. + * + * @param checkType The type of check. + * @see CheckType + */ public void setCheckType(CheckType checkType) { this.checkType = checkType; } + /** + * Returns the p-value for the given cluster. + * + * @param cluster The cluster. + * @param alpha The alpha level. + * @return The p-value. + */ public boolean significant(List cluster, double alpha) { if (checkType == CheckType.None) { return true; @@ -108,6 +148,12 @@ public boolean significant(List cluster, double alpha) { } } + /** + * Returns the p-value for the given cluster. + * + * @param clusters The clusters. + * @return The p-value. + */ public double getModelPValue(List> clusters) { SemIm im = estimateModel(clusters); return im.getPValue(); @@ -250,6 +296,4 @@ private SemIm estimateModel(List> clusters) { * or could check to see if the cluster is a clique, or could not do the check. */ public enum CheckType {Significance, Clique, None} - - } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/ClusterUtils.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/ClusterUtils.java index fb6ad4e8cb..e6e7591c40 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/ClusterUtils.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/ClusterUtils.java @@ -31,15 +31,24 @@ import java.util.Set; /** - *

                Provides some general utilities for dealing with clustering input and output.

                - *

                The method of this class are used only internally and so are not documented - * for public use.

                + * Provides some general utilities for dealing with clustering input and output. + *

                + * The method of this class are used only internally and so are not documented for public use. * * @author josephramsey */ public class ClusterUtils { + + // The prefix for latent variables. public static final String LATENT_PREFIX = "_L"; + /** + * Converts a list of indices into a list of Nodes representing a cluster. + * + * @param partition The indices of the variables. + * @param nodes The variables. + * @return The extracted node list. + */ public static List convertListToInt(List> partition, List nodes) { List _partition = new ArrayList<>(); @@ -60,6 +69,13 @@ public static List convertListToInt(List> partition, List> convertIntToList(List partition, List nodes) { List> _partition = new ArrayList<>(); @@ -76,6 +92,13 @@ static List> convertIntToList(List partition, List nodes return _partition; } + /** + * Converts a list of indices into a list of Nodes representing a cluster. + * + * @param clusters The indices of the variables. + * @param variables The variables. + * @return The extracted node list. + */ public static List> clustersToPartition(Clusters clusters, List variables) { List> inputPartition = new ArrayList<>(); @@ -96,6 +119,12 @@ public static List> clustersToPartition(Clusters clusters, List return inputPartition; } + /** + * Converts a list of indices into a list of Nodes representing a cluster. + * + * @param partition The indices of the variables. + * @return The extracted node list. + */ public static Clusters partitionToClusters(List> partition) { Clusters clusters = new Clusters(); @@ -110,6 +139,13 @@ public static Clusters partitionToClusters(List> partition) { return clusters; } + /** + * Converts a list of indices into a list of Nodes representing a cluster. + * + * @param clusters The indices of the variables. + * @param varNames The variables. + * @return The extracted node list. + */ public static Graph convertSearchGraph(List clusters, String[] varNames) { List nodes = new ArrayList<>(); @@ -153,6 +189,12 @@ public static Graph convertSearchGraph(List clusters, String[] varNames) return graph; } + /** + * Converts a list of indices into a list of Nodes representing a cluster. + * + * @param mim The graph to convert. + * @return The extracted node list. + */ public static Clusters mimClusters(Graph mim) { List latents = new ArrayList<>(); @@ -180,6 +222,12 @@ public static Clusters mimClusters(Graph mim) { } + /** + * Logs the clusters. + * + * @param clusters The clusters. + * @param variables The variables. + */ public static void logClusters(Set> clusters, List variables) { int num = 1; StringBuilder buf = new StringBuilder(); @@ -206,6 +254,12 @@ public static void logClusters(Set> clusters, List variables) TetradLogger.getInstance().log("clusters", buf.toString()); } + /** + * Generates a list of latent variable names. + * + * @param total The number of latent variables to generate. + * @return The list of latent variable names. + */ public static List generateLatentNames(int total) { List output = new ArrayList<>(); for (int i = 0; i < total; i++) { diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/DagInCpcagIterator.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/DagInCpcagIterator.java index 67c24ca356..03d97e9061 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/DagInCpcagIterator.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/DagInCpcagIterator.java @@ -34,14 +34,16 @@ */ public class DagInCpcagIterator { - /** - * The stack of graphs, with annotations as to the arbitrary undirected edges chosen in them and whether or not - * these edges have already been oriented left and/or right. - */ + // The stack of graphs, with annotations as to the arbitrary undirected edges chosen in them and whether + // these edges have already been oriented left and/or right. private final LinkedList decoratedGraphs = new LinkedList<>(); + // The set of colliders in the original CPDAG. private final LinkedList colliders; + // Whether to allow new colliders in the graphs. private final boolean allowNewColliders; + // The graph to be returned by next() if it is not null. private Graph storedGraph; + // Whether the first graph has been returned. private boolean returnedOne; /** @@ -154,6 +156,8 @@ public Graph next() { } /** + * Returns true just in case there is still a DAG remaining in the enumeration of DAGs for this CPDAG. + * * @return true just in case there is still a DAG remaining in the enumeration of DAGs for this CPDAG. */ public boolean hasNext() { @@ -313,7 +317,6 @@ public void setChangedEdges(Map> changedEdges) { public boolean isAllowArbitraryOrientation() { return this.allowArbitraryOrientation; } - } } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/DagIterator.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/DagIterator.java index 8353c6ce4d..905269b748 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/DagIterator.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/DagIterator.java @@ -36,11 +36,10 @@ */ public class DagIterator { - /** - * The stack of graphs, with annotations as to the arbitrary undirected edges chosen in them and whether or not - * these edges have already been oriented left and/or right. - */ + // The stack of graphs, with annotations as to the arbitrary undirected edges chosen in them and whether + //these edges have already been oriented left and/or right. private final LinkedList decoratedGraphs = new LinkedList<>(); + // The DAG that is returned by the next() method. private Graph storedDag; /** @@ -135,6 +134,8 @@ public Graph next() { } /** + * Returns true just in case there is still a DAG remaining in the enumeration of DAGs for this pattern. + * * @return true just in case there is still a DAG remaining in the enumeration of DAGs for this pattern. */ public boolean hasNext() { @@ -145,7 +146,6 @@ public boolean hasNext() { return this.storedDag != null; } - private static class DecoratedGraph { private Graph graph; private Edge edge; diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/DagSepsets.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/DagSepsets.java index a1cddfe9aa..dd172802e6 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/DagSepsets.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/DagSepsets.java @@ -35,6 +35,7 @@ * @author josephramsey */ public class DagSepsets implements SepsetProducer { + // The DAG being analyzed. private final EdgeListGraph dag; /** @@ -72,7 +73,6 @@ public boolean isUnshieldedCollider(Node i, Node j, Node k) { return sepset != null && !sepset.contains(j); } - /** * Not implemented; required for an interface. * From 60e5194bbe4a87586376f08e32c16f4b5149271a Mon Sep 17 00:00:00 2001 From: jdramsey Date: Thu, 25 Jan 2024 02:29:58 -0500 Subject: [PATCH 117/163] Cleaned up the search.util package. --- .../main/java/edu/cmu/tetrad/search/work_in_progress/README.txt | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 tetrad-lib/src/main/java/edu/cmu/tetrad/search/work_in_progress/README.txt diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/work_in_progress/README.txt b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/work_in_progress/README.txt deleted file mode 100644 index 429e929595..0000000000 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/work_in_progress/README.txt +++ /dev/null @@ -1,2 +0,0 @@ -These classes are put here in the "Work In Progress" directory because -they're either old (but not disposable) or require more work. \ No newline at end of file From 972a0ef34aae47c5ac2297d60abe1f82e61a1ac6 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Thu, 25 Jan 2024 03:45:54 -0500 Subject: [PATCH 118/163] Adding code to allow the WatchProcess dialog to follow the Tetrad interface app if the app is moved to a different monitor. --- .../main/java/edu/cmu/tetradapp/Tetrad.java | 2 +- .../cmu/tetradapp/util/WatchedProcess.java | 42 ++++++++++++++++++- 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/Tetrad.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/Tetrad.java index 35a6b45a03..411d4610cf 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/Tetrad.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/Tetrad.java @@ -60,7 +60,7 @@ public final class Tetrad implements PropertyChangeListener { /** * The launch frame. */ - private JFrame frame; + public static JFrame frame; /** * The desktop placed into the launch frame. */ diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java index 01f79751ef..b0d8645999 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java @@ -1,10 +1,13 @@ package edu.cmu.tetradapp.util; import edu.cmu.tetrad.util.TetradLogger; +import edu.cmu.tetradapp.Tetrad; import javax.swing.*; import javax.swing.border.BevelBorder; import java.awt.*; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; /** * Runs a long process, watching it with a thread and popping up a Stop button that the user can click to stop the @@ -31,7 +34,7 @@ * @author ChatGPT */ public abstract class WatchedProcess { - private final JFrame frame; + private JFrame frame; private Thread longRunningThread; private JDialog dialog; @@ -39,7 +42,19 @@ public abstract class WatchedProcess { * Constructor. */ public WatchedProcess() { - frame = new JFrame("Hidden Frame"); + + // The frame is used to center the dialog on the screen. Use the Tetrad frame if it exists, otherwise create a + // hidden frame. + frame = Tetrad.frame; + + if (frame == null) { + // Create a hidden frame + frame = new JFrame("Hidden Frame"); + frame.setUndecorated(true); + frame.setSize(0, 0); + frame.setVisible(true); + } + startLongRunningThread(); } @@ -106,5 +121,28 @@ private void showStopDialog() { dialog.setLocationRelativeTo(frame); dialog.setVisible(true); + + frame.addComponentListener(new ComponentAdapter() { + @Override + public void componentMoved(ComponentEvent e) { + moveDialogToSameScreen(frame, dialog); + } + }); + } + + private static void moveDialogToSameScreen(JFrame frame, JDialog dialog) { + Point frameLocation = frame.getLocation(); + GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); + GraphicsDevice[] screens = ge.getScreenDevices(); + + for (GraphicsDevice screen : screens) { + Rectangle bounds = screen.getDefaultConfiguration().getBounds(); + if (bounds.contains(frameLocation)) { + Point dialogLocation = dialog.getLocation(); + dialogLocation.translate(bounds.x - frameLocation.x, bounds.y - frameLocation.y); + dialog.setLocation(dialogLocation); + break; + } + } } } From 721e79a5b6ff81176b1e151177c1a912760563fe Mon Sep 17 00:00:00 2001 From: jdramsey Date: Thu, 25 Jan 2024 04:15:13 -0500 Subject: [PATCH 119/163] Adding code to allow the WatchProcess dialog to follow the Tetrad interface app if the app is moved to a different monitor. --- .../cmu/tetradapp/util/WatchedProcess.java | 42 +++++++++---------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java index b0d8645999..bbd2cddf3d 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java @@ -76,6 +76,8 @@ private void startLongRunningThread() { try { watch(); + + } catch (InterruptedException e) { TetradLogger.getInstance().forceLogMessage("Thread was interrupted while watching. Stopping..."); return; @@ -88,7 +90,6 @@ private void startLongRunningThread() { }); longRunningThread.start(); - showStopDialog(); } @@ -105,6 +106,15 @@ private void showStopDialog() { dialog.setSize(200, 50); dialog.setResizable(false); + frame.addComponentListener(new ComponentAdapter() { + @Override + public void componentMoved(ComponentEvent e) { + if (dialog != null) { + positionDialogAboveFrameCenter(frame, dialog); + } + } + }); + JButton stopButton = new JButton("Processing (click to stop)..."); stopButton.addActionListener(e -> { @@ -121,28 +131,16 @@ private void showStopDialog() { dialog.setLocationRelativeTo(frame); dialog.setVisible(true); - - frame.addComponentListener(new ComponentAdapter() { - @Override - public void componentMoved(ComponentEvent e) { - moveDialogToSameScreen(frame, dialog); - } - }); } - private static void moveDialogToSameScreen(JFrame frame, JDialog dialog) { - Point frameLocation = frame.getLocation(); - GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); - GraphicsDevice[] screens = ge.getScreenDevices(); - - for (GraphicsDevice screen : screens) { - Rectangle bounds = screen.getDefaultConfiguration().getBounds(); - if (bounds.contains(frameLocation)) { - Point dialogLocation = dialog.getLocation(); - dialogLocation.translate(bounds.x - frameLocation.x, bounds.y - frameLocation.y); - dialog.setLocation(dialogLocation); - break; - } - } + private static void positionDialogAboveFrameCenter(JFrame frame, JDialog dialog) { + // Calculate the new position for the dialog + Point newDialogPosition = new Point( + frame.getX() + frame.getWidth() / 2 - dialog.getWidth() / 2, // Centered horizontally + frame.getY() + frame.getHeight() / 2 - dialog.getHeight() / 2 // Centered vertically + ); + + // Set the dialog's new position + dialog.setLocation(newDialogPosition); } } From 4fb5c26276fa92615efbef3251778fe0bedd904b Mon Sep 17 00:00:00 2001 From: jdramsey Date: Thu, 25 Jan 2024 04:21:08 -0500 Subject: [PATCH 120/163] Added code to center the Processing... dialog above the Tetrad interface app frame even if the app is moved to a different monitor. --- .../src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java index bbd2cddf3d..6717307636 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java @@ -76,8 +76,6 @@ private void startLongRunningThread() { try { watch(); - - } catch (InterruptedException e) { TetradLogger.getInstance().forceLogMessage("Thread was interrupted while watching. Stopping..."); return; From 54c999aa2ab36bdb7266b4e76f50f4e0c8da5091 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Thu, 25 Jan 2024 04:34:52 -0500 Subject: [PATCH 121/163] Added code to center the Processing... dialog above the Tetrad interface app frame even if the app is moved to a different monitor. --- .../src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java | 1 + 1 file changed, 1 insertion(+) diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java index 6717307636..bb8d1d0ac0 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java @@ -103,6 +103,7 @@ private void showStopDialog() { dialog.setUndecorated(true); dialog.setSize(200, 50); dialog.setResizable(false); + dialog.setModalityType(Dialog.ModalityType.APPLICATION_MODAL); frame.addComponentListener(new ComponentAdapter() { @Override From 532d0646d2d42b22f855d1d86eb3d207df25cdd7 Mon Sep 17 00:00:00 2001 From: Joseph Ramsey Date: Thu, 25 Jan 2024 12:23:44 -0500 Subject: [PATCH 122/163] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0352dec0cb..e335ed5514 100644 --- a/README.md +++ b/README.md @@ -10,11 +10,11 @@ See out insructions for [Installing the Tetrad Application](https://github.com/c ## Tetrad in Python -We have a project, [py-tetrad](https://github.com/cmu-phil/py-tetrad), that allows you to incorporate arbitrary Tetrad code into a Python workflow. It's new, and the installation is still nonstandard, but it had a good response. This requires Python 3.5+. and Java JDK 9+. +We have a project, [py-tetrad](https://github.com/cmu-phil/py-tetrad), that allows you to incorporate arbitrary Tetrad code into a Python workflow. It's new, and the installation is still nonstandard, but it had a good response. This requires Python 3.5+. and Java JDK 17+. ## Tetrad in R -We also have a project, [rpy-tetrad](https://github.com/cmu-phil/py-tetrad/tree/main/pytetrad/R), that allows you to incorporate _some_ Tetrad functionality in R. It's also new, and the installation for it is also still nonstandard, but has gotten good feedback. This requires Python 3.5+ and Java JDK 9+. +We also have a project, [rpy-tetrad](https://github.com/cmu-phil/py-tetrad/tree/main/pytetrad/R), that allows you to incorporate _some_ Tetrad functionality in R. It's also new, and the installation for it is also still nonstandard, but has gotten good feedback. This requires Python 3.5+ and Java JDK 17+. Please see our [description](https://sites.google.com/view/tetradcausal/tetrad-in-r?authuser=0). From 2a41a1dca81e4cdb6672f0ed556e386f939254f3 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Thu, 25 Jan 2024 22:56:43 -0500 Subject: [PATCH 123/163] Cleanup and added try-catch clause around exit handler so it doesn't print an exception on Windows. --- .../main/java/edu/cmu/tetradapp/Tetrad.java | 32 +++++++++++-------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/Tetrad.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/Tetrad.java index 411d4610cf..2c51468f16 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/Tetrad.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/Tetrad.java @@ -148,7 +148,7 @@ private void launchFrame() { it is maximized. For some reason, most of the details of this order are important. Jdramsey 12/14/02 */ - this.frame = new JFrame(this.mainTitle) { + frame = new JFrame(this.mainTitle) { @Serial private static final long serialVersionUID = -9077349253115802418L; @@ -163,14 +163,13 @@ public Dimension getPreferredSize() { // Fixing a bug caused by switch to Oracle Java (at least for Mac), although I must say the following // code is what should have worked to begin with. Bug was that sessions would appear only in the lower // left-hand corner of the screen. - this.frame.setPreferredSize(Toolkit.getDefaultToolkit().getScreenSize()); + frame.setPreferredSize(Toolkit.getDefaultToolkit().getScreenSize()); getFrame().setContentPane(getDesktop()); getFrame().pack(); getFrame().setLocationRelativeTo(null); // This doesn't let the user resize the main window. -// getFrame().setExtendedState(Frame.MAXIMIZED_BOTH); Image image = ImageUtils.getImage(this, "tyler16.png"); getFrame().setIconImage(image); @@ -192,16 +191,21 @@ public void windowClosing(WindowEvent e) { if (Desktop.isDesktopSupported()) { Desktop desktop = Desktop.getDesktop(); - desktop.setQuitHandler((e2, response) -> { - int result = JOptionPane.showConfirmDialog(null, - "Are you sure you want to quit? Any unsaved work will be lost.", - "Confirm Quit", JOptionPane.YES_NO_OPTION); - if (result == JOptionPane.YES_OPTION) { - response.performQuit(); - } else { - response.cancelQuit(); - } - }); + + try { + desktop.setQuitHandler((e2, response) -> { + int result = JOptionPane.showConfirmDialog(null, + "Are you sure you want to quit? Any unsaved work will be lost.", + "Confirm Quit", JOptionPane.YES_NO_OPTION); + if (result == JOptionPane.YES_OPTION) { + response.performQuit(); + } else { + response.cancelQuit(); + } + }); + } catch (Exception e) { + TetradLogger.getInstance().forceLogMessage("Could not set quit handler."); + } } } @@ -227,7 +231,7 @@ private void exitApplication() { } private JFrame getFrame() { - return this.frame; + return frame; } private TetradDesktop getDesktop() { From 55164dfbb1be67ffa0270e47554906da3aa33166 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Thu, 25 Jan 2024 23:01:04 -0500 Subject: [PATCH 124/163] Cleanup and added try-catch clause around exit handler so it doesn't print an exception on Windows. --- tetrad-gui/src/main/java/edu/cmu/tetradapp/Tetrad.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/Tetrad.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/Tetrad.java index 2c51468f16..af6ad34134 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/Tetrad.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/Tetrad.java @@ -204,7 +204,7 @@ public void windowClosing(WindowEvent e) { } }); } catch (Exception e) { - TetradLogger.getInstance().forceLogMessage("Could not set quit handler."); + TetradLogger.getInstance().forceLogMessage("Could not set quit handler on this platform.."); } } } From c30dc69d12f82aa989c21c57ef24002d147286b6 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Thu, 25 Jan 2024 23:04:42 -0500 Subject: [PATCH 125/163] Cleanup. --- .../main/java/edu/cmu/tetrad/search/BFci.java | 28 ++-- .../main/java/edu/cmu/tetrad/search/Boss.java | 137 +++++++++--------- 2 files changed, 81 insertions(+), 84 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/BFci.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/BFci.java index e001129de8..740aa93adf 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/BFci.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/BFci.java @@ -36,21 +36,19 @@ import static edu.cmu.tetrad.graph.GraphUtils.gfciExtraEdgeRemovalStep; /** - *

                Uses BOSS in place of FGES for the initial step in the GFCI algorithm. - * This tends to produce a accurate PAG than GFCI as a result, for the latent variables case. This is a simple - * substitution; the reference for GFCI is here:

                - * - *

                J.M. Ogarrio and P. Spirtes and J. Ramsey, "A Hybrid Causal Search Algorithm - * for Latent Variable Models," JMLR 2016. Here, BOSS has been substituted for FGES.

                - * - *

                BOSS is a an algorithm that is currently being written up for publication, - * so we don't yet have a reference for it.

                - * - *

                For BOSS only a score is needed, but there are steps in GFCI that require - * a test, so for this method, both a test and a score need to be given.

                - * - *

                This class is configured to respect knowledge of forbidden and required - * edges, including knowledge of temporal tiers.

                + * Uses BOSS in place of FGES for the initial step in the GFCI algorithm. This tends to produce a accurate PAG than GFCI + * as a result, for the latent variables case. This is a simple substitution; the reference for GFCI is here: + *

                + * J.M. Ogarrio and P. Spirtes and J. Ramsey, "A Hybrid Causal Search Algorithm for Latent Variable Models," JMLR 2016. + * Here, BOSS has been substituted for FGES. + *

                + * BOSS is a an algorithm that is currently being written up for publication, so we don't yet have a reference for it. + *

                + * For BOSS only a score is needed, but there are steps in GFCI that require a test, so for this method, both a test and + * a score need to be given. + *

                + * This class is configured to respect knowledge of forbidden and required edges, including knowledge of temporal + * tiers. * * @author josephramsey * @author bryan andrews diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Boss.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Boss.java index d2ca4feeb0..50a3acbed4 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Boss.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Boss.java @@ -8,35 +8,35 @@ import edu.cmu.tetrad.search.utils.GrowShrinkTree; import java.util.*; -import java.util.concurrent.*; +import java.util.concurrent.Callable; +import java.util.concurrent.ForkJoinPool; import static edu.cmu.tetrad.util.RandomUtil.shuffle; /** - *

                Implements Best Order Score Search (BOSS). The following references are relevant:

                - * - *

                Lam, W. Y., Andrews, B., & Ramsey, J. (2022, August). Greedy relaxations of the sparsest permutation algorithm. - * In Uncertainty in Artificial Intelligence (pp. 1052-1062). PMLR.

                - * - *

                Teyssier, M., & Koller, D. (2012). Ordering-based search: A simple and effective algorithm for learning Bayesian - * networks. arXiv preprint arXiv:1207.1429.

                - * - *

                Solus, L., Wang, Y., & Uhler, C. (2021). Consistency guarantees for greedy permutation-based causal inference - * algorithms. Biometrika, 108(4), 795-814.

                - * - *

                The BOSS algorithm is based on the idea that implied DAGs for permutations are most optimal in their BIC scores - * when the variables in the permutations are ordered causally--that is, so that that causes in the models come before - * effects in a topological order.

                - * - *

                This algorithm is implemented as a "plugin-in" algorithm to a PermutationSearch object (see), which deals with - * certain details of knowledge handling that are common to different permutation searches.

                - * - *

                BOSS, like GRaSP (see), is characterized by high adjacency and orientation precision (especially) and recall for + * Implements Best Order Score Search (BOSS). The following references are relevant: + *

                + * Lam, W. Y., Andrews, B., & Ramsey, J. (2022, August). Greedy relaxations of the sparsest permutation algorithm. + * In Uncertainty in Artificial Intelligence (pp. 1052-1062). PMLR. + *

                + * Teyssier, M., & Koller, D. (2012). Ordering-based search: A simple and effective algorithm for learning Bayesian + * networks. arXiv preprint arXiv:1207.1429. + *

                + * Solus, L., Wang, Y., & Uhler, C. (2021). Consistency guarantees for greedy permutation-based causal inference + * algorithms. Biometrika, 108(4), 795-814. + *

                + * The BOSS algorithm is based on the idea that implied DAGs for permutations are most optimal in their BIC scores when + * the variables in the permutations are ordered causally--that is, so that that causes in the models come before + * effects in a topological order. + *

                + * This algorithm is implemented as a "plugin-in" algorithm to a PermutationSearch object (see), which deals with + * certain details of knowledge handling that are common to different permutation searches. + *

                + * BOSS, like GRaSP (see), is characterized by high adjacency and orientation precision (especially) and recall for * moderate sample sizes. BOSS scales up currently further than GRaSP to larger variable sets and denser graphs and so - * is currently preferable from a practical standpoint, though performance is essentially identical.

                - * - *

                The algorithm works as follows:

                - * + * is currently preferable from a practical standpoint, though performance is essentially identical. + *

                + * The algorithm works as follows: *

                  *
                1. Start with an arbitrary ordering.
                2. *
                3. Run the permutation search to find a better ordering.
                4. @@ -44,24 +44,24 @@ *
                5. Optionally, Run BES this CPDAG. *
                6. Return this CPDAG.
                7. *
                - * - *

                The optional BES step is needed for correctness, though with large + *

                + * The optional BES step is needed for correctness, though with large * models is has very little effect on the output, since nearly all edges - * are already oriented, so a parameter is included to turn that step off.

                - * - *

                Knowledge can be used with this search. If tiered knowledge is used, + * are already oriented, so a parameter is included to turn that step off. + *

                + * Knowledge can be used with this search. If tiered knowledge is used, * then the procedure is carried out for each tier separately, given the * variables preceding that tier, which allows the Boss algorithm to address * tiered (e.g., time series) problems with larger numbers of variables. * However, knowledge of required and forbidden edges is correctly implemented - * for arbitrary such knowledge.

                - * - *

                A parameter is included to restart the search a certain number of time. + * for arbitrary such knowledge. + *

                + * A parameter is included to restart the search a certain number of time. * The idea is that the goal is to optimize a BIC score, so if several runs * are done of the algorithm for the same data, the model with the highest - * BIC score should be returned and the others ignored.

                - * - *

                This class is meant to be used in the context of the PermutationSearch + * BIC score should be returned and the others ignored. + *

                + * This class is meant to be used in the context of the PermutationSearch * class (see). * * @author bryanandrews @@ -129,8 +129,8 @@ public void searchSuborder(List prefix, List suborder, Map 0 && this.resetAfterRS) { - for (Node root: suborder) { - this.gsts.get(root).reset(); + for (Node root : suborder) { + this.gsts.get(root).reset(); } } @@ -219,7 +219,7 @@ public void setResetAfterBM(boolean reset) { } public void setResetAfterRS(boolean reset) { - this.resetAfterRS = reset; + this.resetAfterRS = reset; } public void setVerbose(boolean verbose) { @@ -253,7 +253,7 @@ public List getTimes() { return this.times; } - /** + /** * True if the order of the variables in the data should be used for an initial best-order search, false if a random * permutation should be used. (Subsequence automatic best order runs will use random permutations.) This is * included so that the algorithm will be capable of outputting the same results with the same data without any @@ -297,14 +297,14 @@ private boolean betterMutationAsync(List prefix, List suborder, Node if (this.resetAfterBM) this.gsts.get(x).reset(); double runningScore = 0; - for (i = with.length - 1 ; i >= 0 ; i--) { + for (i = with.length - 1; i >= 0; i--) { runningScore += with[i]; scores[i] += runningScore; } runningScore = 0; - for (i = 0 ; i < without.length ; i++) { + for (i = 0; i < without.length; i++) { runningScore += without[i]; scores[i + 1] += runningScore; } @@ -323,30 +323,6 @@ private boolean betterMutationAsync(List prefix, List suborder, Node return true; } - private static class Trace implements Callable { - private final GrowShrinkTree gst; - private final Set all; - private final Set prefix; - private final double[] scores; - private final int index; - - Trace(GrowShrinkTree gst, Set all, Set prefix, double[] scores, int index) { - this.gst = gst; - this.all = all; - this.prefix = new HashSet<>(prefix); - this.scores = scores; - this.index = index; - } - - @Override - public Void call() { - double score = gst.trace(this.prefix, this.all); - this.scores[index] = score; - - return null; - } - } - private boolean betterMutation(List prefix, List suborder, Node x) { ListIterator itr = suborder.listIterator(); double[] scores = new double[suborder.size() + 1]; @@ -423,10 +399,6 @@ private double update(List prefix, List suborder) { return score; } - - // alter this code so that it roughly obeys tiers. - - private void makeValidKnowledgeOrder(List order) { if (this.knowledge.isEmpty()) return; @@ -462,4 +434,31 @@ private void makeValidKnowledgeOrder(List order) { } } } + + + // alter this code so that it roughly obeys tiers. + + private static class Trace implements Callable { + private final GrowShrinkTree gst; + private final Set all; + private final Set prefix; + private final double[] scores; + private final int index; + + Trace(GrowShrinkTree gst, Set all, Set prefix, double[] scores, int index) { + this.gst = gst; + this.all = all; + this.prefix = new HashSet<>(prefix); + this.scores = scores; + this.index = index; + } + + @Override + public Void call() { + double score = gst.trace(this.prefix, this.all); + this.scores[index] = score; + + return null; + } + } } \ No newline at end of file From 140559a0efa4ddbf6dd1b5bd14d0f8e86feb51db Mon Sep 17 00:00:00 2001 From: jdramsey Date: Thu, 25 Jan 2024 23:56:13 -0500 Subject: [PATCH 126/163] Cleanup. --- .../edu/cmu/tetrad/search/BossLingam.java | 35 ++- .../main/java/edu/cmu/tetrad/search/Bpc.java | 64 +++--- .../main/java/edu/cmu/tetrad/search/Ccd.java | 28 +-- .../main/java/edu/cmu/tetrad/search/Cfci.java | 11 +- .../edu/cmu/tetrad/search/CheckKnowledge.java | 12 +- .../java/edu/cmu/tetrad/search/Cstar.java | 35 ++- .../java/edu/cmu/tetrad/search/Dagma.java | 39 ++-- .../java/edu/cmu/tetrad/search/Demixer.java | 32 +-- .../edu/cmu/tetrad/search/DirectLingam.java | 20 +- .../edu/cmu/tetrad/search/FactorAnalysis.java | 60 ++--- .../main/java/edu/cmu/tetrad/search/Fas.java | 58 +++-- .../main/java/edu/cmu/tetrad/search/Fasd.java | 24 +- .../main/java/edu/cmu/tetrad/search/Fask.java | 212 +++++++++--------- .../java/edu/cmu/tetrad/search/FastIca.java | 42 ++-- .../main/java/edu/cmu/tetrad/search/Fci.java | 46 ++-- .../java/edu/cmu/tetrad/search/FciMax.java | 37 ++- .../main/java/edu/cmu/tetrad/search/Fges.java | 63 +++--- .../java/edu/cmu/tetrad/search/FgesMb.java | 126 +++++------ .../main/java/edu/cmu/tetrad/search/Fofc.java | 26 +-- .../main/java/edu/cmu/tetrad/search/Ftfc.java | 23 +- .../main/java/edu/cmu/tetrad/search/GFci.java | 41 ++-- .../java/edu/cmu/tetrad/search/Grasp.java | 57 +++-- .../java/edu/cmu/tetrad/search/GraspFci.java | 32 ++- .../edu/cmu/tetrad/search/GrowShrink.java | 42 ++-- .../java/edu/cmu/tetrad/search/IcaLingD.java | 51 +++-- .../java/edu/cmu/tetrad/search/IcaLingam.java | 65 +++--- .../edu/cmu/tetrad/search/IndTestIod.java | 21 +- .../main/java/edu/cmu/tetrad/search/Lofs.java | 23 +- .../java/edu/cmu/tetrad/search/Mimbuild.java | 20 +- .../edu/cmu/tetrad/search/MimbuildTrek.java | 6 +- .../main/java/edu/cmu/tetrad/search/Pc.java | 55 +++-- .../main/java/edu/cmu/tetrad/search/PcMb.java | 23 +- .../main/java/edu/cmu/tetrad/search/Pcd.java | 10 +- .../cmu/tetrad/search/PermutationSearch.java | 23 +- .../main/java/edu/cmu/tetrad/search/Rfci.java | 21 +- .../main/java/edu/cmu/tetrad/search/Sp.java | 42 ++-- .../java/edu/cmu/tetrad/search/SpFci.java | 43 ++-- .../edu/cmu/tetrad/search/SuborderSearch.java | 6 +- .../java/edu/cmu/tetrad/search/SvarFas.java | 39 ++-- .../java/edu/cmu/tetrad/search/SvarFci.java | 39 ++-- .../java/edu/cmu/tetrad/search/SvarFges.java | 35 ++- .../java/edu/cmu/tetrad/search/SvarGfci.java | 35 ++- 42 files changed, 821 insertions(+), 901 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/BossLingam.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/BossLingam.java index ed9758a42a..505e2baa56 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/BossLingam.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/BossLingam.java @@ -39,24 +39,21 @@ import java.util.List; /** - *

                Implements the BOSS-LiNGAM algorithm which first finds a CPDAG for the variables - * and then uses a non-Gaussian orientation method to orient the undirected edges. The reference is as follows: - * - *

                >Hoyer et al., "Causal discovery of linear acyclic models with arbitrary - * distributions," UAI 2008.

                - * - *

                The test for normality used for residuals is Anderson-Darling, following 'ad.test' - * in the nortest package of R. The default alpha level is 0.05--that is, p values from AD below 0.05 are taken to - * indicate nongaussianity.

                - * - *

                It is assumed that the CPDAG is the result of a CPDAG search such as PC or GES. In any - * case, it is important that the residuals be independent for ICA to work.

                - * - *

                This may be replaced by a more general algorithm that allows alternatives for the - * CPDAG search and for the the non-Gaussian orientation method.

                - * - *

                This class is not configured to respect knowledge of forbidden and required - * edges.

                + * Implements the BOSS-LiNGAM algorithm which first finds a CPDAG for the variables and then uses a non-Gaussian + * orientation method to orient the undirected edges. The reference is as follows: + *

                + * Hoyer et al., "Causal discovery of linear acyclic models with arbitrary distributions," UAI 2008. + *

                + * The test for normality used for residuals is Anderson-Darling, following 'ad.test' in the nortest package of R. The + * default alpha level is 0.05--that is, p values from AD below 0.05 are taken to indicate nongaussianity. + *

                + * It is assumed that the CPDAG is the result of a CPDAG search such as PC or GES. In any case, it is important that the + * residuals be independent for ICA to work. + *

                + * This may be replaced by a more general algorithm that allows alternatives for the CPDAG search and for the the + * non-Gaussian orientation method. + *

                + * This class is not configured to respect knowledge of forbidden and required edges. * * @author peterspirtes * @author patrickhoyer @@ -113,7 +110,7 @@ public Graph search() { int i = nodes.indexOf(X); int j = nodes.indexOf(Y); - double lr = Fask.faskLeftRightV2(_data[i], _data[j], true, 0); + double lr = Fask.faskLeftRightV2(_data[i], _data[j], true, 0); if (lr > 0.0) { toOrient.removeEdge(edge); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Bpc.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Bpc.java index bca013898f..b14c9c7a04 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Bpc.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Bpc.java @@ -34,39 +34,37 @@ /** - *

                Implements the Build Pure Clusters (BPC) algorithm, which allows one to identify - * clusters of measured variables in a dataset that are explained by a single latent. The algorithm outputs these - * clusters, which can then be used for further analysis, such as inferring structure over the latents. For the latter, - * see for instance the MimBuild algorithm.

                - * - *

                The reference for BPC is this:

                - * - *

                Silva, R., Scheines, R., Glymour, C., Spirtes, P., & Chickering, D. M. (2006). - * Learning the Structure of Linear Latent Variable Models. Journal of Machine Learning Research, 7(2).

                - * - *

                For a more detailed description of the algorithm, see the paper above. The - * algorithm is based on the idea of finding cliques in the graph of the covariance matrix. The algorithm is initialized - * by finding all maximal cliques in the graph of the covariance matrix. Then, the algorithm iterates over the cliques, - * and for each clique, it tests whether the clique is explained by a single latent. If so, the clique is added to the - * set of clusters. If not, the clique is partitioned into smaller cliques, and the process is repeated for each of the - * smaller cliques. The algorithm stops when all cliques have been tested.

                - * - *

                Some more References:

                - * - *

                Silva, R.; Scheines, R.; Spirtes, P.; Glymour, C. (2003). "Learning measurement models". - * Technical report CMU-CALD-03-100, Center for Automated Learning and Discovery, Carnegie Mellon University.

                - * - *

                Bollen, K. (1990). "Outlier screening and distribution-free test for vanishing tetrads." - * Sociological Methods and Research 19, 80-92.

                - * - *

                Wishart, J. (1928). "Sampling errors in the theory of two factors". British Journal of - * Psychology 19, 180-187.

                - * - *

                Bron, C. and Kerbosch, J. (1973) "Algorithm 457: Finding all cliques of an undirected graph". - * Communications of ACM 16, 575-577.

                - * - *

                This class is not configured to respect knowledge of forbidden and required - * edges.

                + * Implements the Build Pure Clusters (BPC) algorithm, which allows one to identify clusters of measured variables in a + * dataset that are explained by a single latent. The algorithm outputs these clusters, which can then be used for + * further analysis, such as inferring structure over the latents. For the latter, see for instance the MimBuild + * algorithm. + *

                + * The reference for BPC is this: + *

                + * Silva, R., Scheines, R., Glymour, C., Spirtes, P., & Chickering, D. M. (2006). Learning the Structure of Linear + * Latent Variable Models. Journal of Machine Learning Research, 7(2). + *

                + * For a more detailed description of the algorithm, see the paper above. The algorithm is based on the idea of finding + * cliques in the graph of the covariance matrix. The algorithm is initialized by finding all maximal cliques in the + * graph of the covariance matrix. Then, the algorithm iterates over the cliques, and for each clique, it tests whether + * the clique is explained by a single latent. If so, the clique is added to the set of clusters. If not, the clique is + * partitioned into smaller cliques, and the process is repeated for each of the smaller cliques. The algorithm stops + * when all cliques have been tested. + *

                + * Some more References: + *

                + * Silva, R.; Scheines, R.; Spirtes, P.; Glymour, C. (2003). "Learning measurement models". Technical report + * CMU-CALD-03-100, Center for Automated Learning and Discovery, Carnegie Mellon University. + *

                + * Bollen, K. (1990). "Outlier screening and distribution-free test for vanishing tetrads." Sociological Methods and + * Research 19, 80-92. + *

                + * Wishart, J. (1928). "Sampling errors in the theory of two factors". British Journal of Psychology 19, 180-187. + *

                + * Bron, C. and Kerbosch, J. (1973) "Algorithm 457: Finding all cliques of an undirected graph". Communications of ACM + * 16, 575-577. + *

                + * This class is not configured to respect knowledge of forbidden and required edges. * * @author Ricardo Silva * @see Fofc diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Ccd.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Ccd.java index 4c98673ad6..018d8a51f4 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Ccd.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Ccd.java @@ -32,22 +32,18 @@ import java.util.*; /** - *

                Implemented the Cyclic Causal Discovery (CCD) algorithm by Thomas Richardson. - * A reference for this is here:

                - * - *

                Richardson, T. S. (2013). A discovery algorithm for directed cyclic graphs. arXiv - * preprint arXiv:1302.3599.

                - * - *

                See also Chapter 7 of:

                - * - *

                Glymour, C. N., & Cooper, G. F. (Eds.). (1999). Computation, causation, and - * discovery. Aaai Press.

                - * - *

                The graph takes continuous data from a cyclic model as input and returns a cyclic - * PAG graphs, with various types of underlining, that represents a Markov equivalence of the true DAG.

                - * - *

                This class is not configured to respect knowledge of forbidden and required - * edges.

                + * Implemented the Cyclic Causal Discovery (CCD) algorithm by Thomas Richardson. A reference for this is here: + *

                + * Richardson, T. S. (2013). A discovery algorithm for directed cyclic graphs. arXiv preprint arXiv:1302.3599. + *

                + * See also Chapter 7 of: + *

                + * Glymour, C. N., & Cooper, G. F. (Eds.). (1999). Computation, causation, and discovery. Aaai Press. + *

                + * The graph takes continuous data from a cyclic model as input and returns a cyclic PAG graphs, with various types of + * underlining, that represents a Markov equivalence of the true DAG. + *

                + * This class is not configured to respect knowledge of forbidden and required edges. * * @author Frank C. Wimberly * @author josephramsey diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Cfci.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Cfci.java index 69e575f82f..d6d6bc3954 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Cfci.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Cfci.java @@ -34,12 +34,11 @@ /** - *

                Adjusts FCI (see) to use conservative orientation as in CPC (see). Because the - * collider orientation is conservative, there may be ambiguous triples; these may be retrieved using that accessor - * method.

                - * - *

                This class is configured to respect knowledge of forbidden and required - * edges, including knowledge of temporal tiers.

                + * Adjusts FCI (see) to use conservative orientation as in CPC (see). Because the collider orientation is conservative, + * there may be ambiguous triples; these may be retrieved using that accessor method. + *

                + * This class is configured to respect knowledge of forbidden and required edges, including knowledge of temporal + * tiers. * * @author josephramsey * @see Fci diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/CheckKnowledge.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/CheckKnowledge.java index f0dfc1296d..8889df82dd 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/CheckKnowledge.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/CheckKnowledge.java @@ -6,7 +6,6 @@ import edu.cmu.tetrad.graph.Edges; import edu.cmu.tetrad.graph.Graph; import edu.cmu.tetrad.graph.Node; -import org.apache.commons.math3.util.Pair; import java.util.ArrayList; import java.util.Collections; @@ -14,9 +13,8 @@ import java.util.List; /** - *

                Identifies violations of knowledge for a given graph. Both forbidden and required - * knowledge is checked, by separate methods. Sorted lists of edges violating knowledge - * are returned.

                + * Identifies violations of knowledge for a given graph. Both forbidden and required knowledge is checked, by separate + * methods. Sorted lists of edges violating knowledge are returned. * * @author josephramsey */ @@ -30,7 +28,8 @@ private CheckKnowledge() { /** * Returns a sorted list of edges that violate the given knowledge. - * @param graph the graph. + * + * @param graph the graph. * @param knowledge the knowledge. * @return a sorted list of edges that violate the given knowledge. */ @@ -55,7 +54,8 @@ public static List forbiddenViolations(Graph graph, Knowledge knowledge) { /** * Returns a sorted list of edges that are required by knowledge but which do not appear in the graph. - * @param graph the graph. + * + * @param graph the graph. * @param knowledge the knowledge. * @return a sorted list of edges that are required by knowledge but which do not appear in the graph. */ diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Cstar.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Cstar.java index df608c89e7..d2971f4a1f 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Cstar.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Cstar.java @@ -16,33 +16,32 @@ import java.util.concurrent.*; /** - *

                Implements the CStaR algorithm (Stekhoven et al., 2012), which finds a CPDAG of that - * data and then tries all orientations of the undirected edges about a variable in the CPDAG to estimate a minimum - * bound on the effect for a given edge. Some references include the following:

                - * - *

                Stekhoven, D. J., Moraes, I., Sveinbjörnsson, G., Hennig, L., Maathuis, M. H., and - * Bühlmann, P. (2012). Causal stability ranking. Bioinformatics, 28(21), 2819-2823.

                - * - *

                Meinshausen, N., and Bühlmann, P. (2010). Stability selection. Journal of the Royal - * Statistical Society: Series B (Statistical Methodology), 72(4), 417-473.

                - * - *

                Colombo, D., and Maathuis, M. H. (2014). Order-independent constraint-based causal - * structure learning. The Journal of Machine Learning Research, 15(1), 3741-3782.

                - * - *

                This class is not configured to respect knowledge of forbidden and required - * edges.

                + * Implements the CStaR algorithm (Stekhoven et al., 2012), which finds a CPDAG of that data and then tries all + * orientations of the undirected edges about a variable in the CPDAG to estimate a minimum bound on the effect for a + * given edge. Some references include the following: + *

                + * Stekhoven, D. J., Moraes, I., Sveinbjörnsson, G., Hennig, L., Maathuis, M. H., and Bühlmann, P. (2012). Causal + * stability ranking. Bioinformatics, 28(21), 2819-2823. + *

                + * Meinshausen, N., and Bühlmann, P. (2010). Stability selection. Journal of the Royal Statistical Society: Series B + * (Statistical Methodology), 72(4), 417-473. + *

                + * Colombo, D., and Maathuis, M. H. (2014). Order-independent constraint-based causal structure learning. The Journal of + * Machine Learning Research, 15(1), 3741-3782. + *

                + * This class is not configured to respect knowledge of forbidden and required edges. * * @author josephramsey * @see Ida */ public class Cstar { + private final IndependenceWrapper test; + private final ScoreWrapper score; + private final Parameters parameters; private boolean parallelized = false; private int numSubsamples = 30; private int topBracket = 5; private double selectionAlpha = 0.0; - private final IndependenceWrapper test; - private final ScoreWrapper score; - private final Parameters parameters; private CpdagAlgorithm cpdagAlgorithm = CpdagAlgorithm.PC_STABLE; private SampleStyle sampleStyle = SampleStyle.SUBSAMPLE; private boolean verbose; diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Dagma.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Dagma.java index dc717c05c0..56be90398c 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Dagma.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Dagma.java @@ -26,34 +26,24 @@ import edu.cmu.tetrad.graph.Graph; import edu.cmu.tetrad.graph.Node; import edu.cmu.tetrad.search.utils.MeekRules; -import org.apache.commons.math3.linear.RealMatrix; import org.apache.commons.math3.linear.LUDecomposition; +import org.apache.commons.math3.linear.RealMatrix; -import java.util.*; +import java.util.List; import static org.apache.commons.math3.linear.MatrixUtils.*; import static org.apache.commons.math3.util.FastMath.*; /** - *

                Implements the DAGMA algorithm. The reference is here:

                - * - *

                NEEDS DOCUMENTATION

                + * Implements the DAGMA algorithm. The reference is here: + *

                + * NEEDS DOCUMENTATION * * @author bryanandrews */ public class Dagma { - private RealMatrix cov; - private List variables; - private RealMatrix I; - private int d; - - private double lambda1; - private double wThreshold; - private boolean cpdag; - private final double[] T; - private final double muInit; private final double muFactor; private final int warmIter; @@ -63,6 +53,13 @@ public class Dagma { private final double b1; private final double b2; private final double tol; + private final RealMatrix cov; + private final List variables; + private final RealMatrix I; + private final int d; + private double lambda1; + private double wThreshold; + private boolean cpdag; /** @@ -80,7 +77,7 @@ public Dagma(DataSet dataset) { this.cpdag = true; // M-matrix s values - this.T = new double[] {1.0, .9, .8, .7}; + this.T = new double[]{1.0, .9, .8, .7}; // central path coefficient and decay factor this.muInit = 1.0; @@ -91,8 +88,8 @@ public Dagma(DataSet dataset) { this.maxIter = 70000; this.lr = 3e-4; this.checkpoint = 1000; - this.b1=0.99; - this.b2=0.999; + this.b1 = 0.99; + this.b2 = 0.999; this.tol = 1e-6; } @@ -266,10 +263,10 @@ private RealMatrix getMMatrix(RealMatrix W, double s) { RealMatrix M = this.I.scalarMultiply(s); for (int i = 0; i < this.d; i++) { - for (int j = 0; j < this.d; j++) { - M.addToEntry(i, j, -W.getEntry(i, j) * W.getEntry(i, j)); - } + for (int j = 0; j < this.d; j++) { + M.addToEntry(i, j, -W.getEntry(i, j) * W.getEntry(i, j)); } + } return M; } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Demixer.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Demixer.java index b3854ed823..1b27819f46 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Demixer.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Demixer.java @@ -61,6 +61,22 @@ public Demixer(DataSet data, int k) { } } + static double getVar(int i, int v, int v2, int numCases, double[][] gammaArray, double[][] dataArray, double[][] meansArray) { + double varNumerator; + double varDivisor; + double var; + varNumerator = 0; + varDivisor = 0; + + for (int j = 0; j < numCases; j++) { + varNumerator += gammaArray[i][j] * (dataArray[j][v] - meansArray[i][v]) * (dataArray[j][v2] - meansArray[i][v2]); + varDivisor += gammaArray[i][j]; + } + + var = varNumerator / varDivisor; + return var; + } + /* * Runs the E-M algorithm iteratively until the weights array converges. Returns a MixtureModel object containing * the final values of the means, covariance matrices, weights, and gammas arrays. @@ -203,22 +219,6 @@ private void maximization() { } - static double getVar(int i, int v, int v2, int numCases, double[][] gammaArray, double[][] dataArray, double[][] meansArray) { - double varNumerator; - double varDivisor; - double var; - varNumerator = 0; - varDivisor = 0; - - for (int j = 0; j < numCases; j++) { - varNumerator += gammaArray[i][j] * (dataArray[j][v] - meansArray[i][v]) * (dataArray[j][v2] - meansArray[i][v2]); - varDivisor += gammaArray[i][j]; - } - - var = varNumerator / varDivisor; - return var; - } - /* * For an input case and model, returns the value of the model's normal PDF for that case, using the current * estimations of the means and covariance matrix diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/DirectLingam.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/DirectLingam.java index 70675a83d2..5d77cb2554 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/DirectLingam.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/DirectLingam.java @@ -34,16 +34,16 @@ import static org.apache.commons.math3.util.FastMath.*; /** - *

                Implements the Direct-LiNGAM algorithm. The reference is here:

                - * - *

                S. Shimizu, T. Inazumi, Y. Sogawa, A. Hyvärinen, Y. Kawahara, T. Washio, P. O. Hoyer and K. Bollen. - * DirectLiNGAM: A direct method for learning a linear non-Gaussian structural equation model. Journal of Machine - * Learning Research, 12(Apr): 1225–1248, 2011.

                - * - *

                A. Hyvärinen and S. M. Smith. Pairwise likelihood ratios for estimation of non-Gaussian - * structural evaluation models. Journal of Machine Learning Research 14:111-152, 2013.

                - * - *

                NEEDS DOCUMENTATION

                + * Implements the Direct-LiNGAM algorithm. The reference is here: + *

                + * S. Shimizu, T. Inazumi, Y. Sogawa, A. Hyvärinen, Y. Kawahara, T. Washio, P. O. Hoyer and K. Bollen. DirectLiNGAM: A + * direct method for learning a linear non-Gaussian structural equation model. Journal of Machine Learning Research, + * 12(Apr): 1225–1248, 2011. + *

                + * A. Hyvärinen and S. M. Smith. Pairwise likelihood ratios for estimation of non-Gaussian structural evaluation models. + * Journal of Machine Learning Research 14:111-152, 2013. + *

                + * NEEDS DOCUMENTATION * * @author bryanandrews */ diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/FactorAnalysis.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/FactorAnalysis.java index 0fa17ed559..16eddfda65 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/FactorAnalysis.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/FactorAnalysis.java @@ -33,18 +33,15 @@ import static org.apache.commons.math3.util.FastMath.abs; /** - *

                Implements the classical Factor Analysis algorithm. Some references include:

                - *

                Horst, P. (1965). Factor analysis of data matrices. Holt, Rinehart and Winston. - * This work has good specifications and explanations of factor analysis algorithm and methods of communality - * estimation.

                - * - *

                Rummel, R. J. (1988). Applied factor analysis. Northwestern University Press. This - * book is a good companion to the book listed above. While it doesn't specify any actual algorithm, it has a great - * introduction to the subject that gives the reader a good appreciation of the philosophy and the mathematics behind - * factor analysis.

                - * - *

                This class is not configured to respect knowledge of forbidden and required - * edges.

                + * Implements the classical Factor Analysis algorithm. Some references include: Horst, P. (1965). Factor analysis of + * data matrices. Holt, Rinehart and Winston. This work has good specifications and explanations of factor analysis + * algorithm and methods of communality estimation. + *

                + * Rummel, R. J. (1988). Applied factor analysis. Northwestern University Press. This book is a good companion to the + * book listed above. While it doesn't specify any actual algorithm, it has a great introduction to the subject that + * gives the reader a good appreciation of the philosophy and the mathematics behind factor analysis. + *

                + * This class is not configured to respect knowledge of forbidden and required edges. * * @author Mike Freenor */ @@ -118,37 +115,30 @@ private static Matrix matrixExp(Matrix matrix, double exponent) { /** * Successive method with residual matrix. *

                - * This algorithm makes use of a helper algorithm. - * Together, they solve for an unrotated factor loading matrix. + * This algorithm makes use of a helper algorithm. Together, they solve for an unrotated factor loading matrix. *

                * This method calls upon its helper to find column vectors, with which it constructs its factor loading matrix. * Upon receiving each successive column vector from its helper method, it makes sure that we want to keep this - * vector instead of discarding it. - * After keeping a vector, a residual matrix is calculated, upon which solving for + * vector instead of discarding it. After keeping a vector, a residual matrix is calculated, upon which solving for * the next column vector is directly dependent. *

                * We stop looking for new vectors either when we've accounted for close to all the variance in the original * correlation matrix, or when the "d scalar" for a new vector is less than 1 (the d-scalar is the corresponding * diagonal for the factor loading matrix -- thus, when it's less than 1, the vector we've solved for barely - * accounts for any more variance). - * This means we've already "pulled out" all the variance we can from the - * residual matrix, and we should stop as further factors don't explain much more - * (and serve to complicate the - * model). + * accounts for any more variance). This means we've already "pulled out" all the variance we can from the residual + * matrix, and we should stop as further factors don't explain much more (and serve to complicate the model). *

                * PSEUDO-CODE: *

                * 0th Residual Matrix = Original Correlation Matrix Ask helper for the 1st factor (first column vector in our - * factor loading vector) Add 1st factor's d-scalar - * (for i'th factor, call its d-scalar the i'th d-scalar) to a list + * factor loading vector) Add 1st factor's d-scalar (for i'th factor, call its d-scalar the i'th d-scalar) to a list * of d-scalars. *

                * While the ratio of the sum of d-scalars to the trace of the original correlation matrix is less than .99 (in * other words, while we haven't accounted for practically all the variance): *

                * i'th residual matrix = (i - 1)'th residual matrix SUBTRACT the major product moment of (i - 1)'th factor loading - * vector Ask helper for i'th factor If i'th factor's d-value is less than 1, throw it out and end loop. - * Otherwise, + * vector Ask helper for i'th factor If i'th factor's d-value is less than 1, throw it out and end loop. Otherwise, * add it to the factor loading matrix and continue loop. *

                * END PSEUDO-CODE @@ -316,20 +306,15 @@ public Matrix getResidual() { } /** - * Helper method for the basic structure successive factor method above. - * Takes a residual matrix and an approximation - * vector, and finds both the factor loading vector and the "d scalar" - * which is used to determine the amount of - * total variance accounted for so far. + * Helper method for the basic structure successive factor method above. Takes a residual matrix and an + * approximation vector, and finds both the factor loading vector and the "d scalar" which is used to determine the + * amount of total variance accounted for so far. *

                - * The helper takes, to begin with, the unit vector as its approximation to the factor column vector. - * With each - * iteration, it approximates a bit closer -- - * the d-scalar for each successive step eventually converges to a value + * The helper takes, to begin with, the unit vector as its approximation to the factor column vector. With each + * iteration, it approximates a bit closer -- the d-scalar for each successive step eventually converges to a value * (provably). *

                - * Thus, the ratio between the last iteration's d-scalar and this iteration's d-scalar should approach 1. - * When this + * Thus, the ratio between the last iteration's d-scalar and this iteration's d-scalar should approach 1. When this * ratio gets sufficiently close to 1, the algorithm halts and returns its getModel approximation. *

                * Important to note: the residual matrix stays fixed for this entire algorithm. @@ -346,8 +331,7 @@ public Matrix getResidual() { * times yet, a failsafe): *

                * i'th U Vector = residual matrix * (i - 1)'th factor loading i'th L Scalar = transpose((i - 1)'th factor loading) - * * i'th U Vector i'th D Scalar = square root(i'th L Scalar) - * i'th factor loading = i'th U Vector / i'th D Scalar + * * i'th U Vector i'th D Scalar = square root(i'th L Scalar) i'th factor loading = i'th U Vector / i'th D Scalar *

                * Return the final i'th factor loading as our best approximation. */ diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fas.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fas.java index d851f690ec..7bd62dc513 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fas.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fas.java @@ -34,27 +34,25 @@ import java.util.*; /** - *

                Implements the Fast Adjacency Search (FAS), which is the adjacency search of the PC algorithm (see). This is a - * useful algorithm in many contexts, including as the first step of FCI (see).

                - * - *

                The idea of FAS is that at a given stage of the search, an edge X*-*Y is removed from the - * graph if X _||_ Y | S, where S is a subset of size d either of adj(X) or of adj(Y), where d is the depth of the - * search. The fast adjacency search performs this procedure for each pair of adjacent edges in the graph and for each - * depth d = 0, 1, 2, ..., d1, where d1 is either the maximum depth or else the first such depth at which no edges can - * be removed. The interpretation of this adjacency search is different for different algorithm, depending on the - * assumptions of the algorithm. A mapping from {x, y} to S({x, y}) is returned for edges x *-* y that have been - * removed.

                - * - *

                FAS may optionally use a heuristic from Causation, Prediction and Search, which (like PC-Stable) - * renders the output invariant to the order of the input variables.

                - * - *

                This algorithm was described in the earlier edition of this book:

                - * - *

                Spirtes, P., Glymour, C. N., Scheines, R., & Heckerman, D. (2000). Causation, prediction, and search. MIT - * press.

                - * - *

                This class is configured to respect knowledge of forbidden and required edges, including knowledge of temporal - * tiers.

                + * Implements the Fast Adjacency Search (FAS), which is the adjacency search of the PC algorithm (see). This is a useful + * algorithm in many contexts, including as the first step of FCI (see). + *

                + * The idea of FAS is that at a given stage of the search, an edge X*-*Y is removed from the graph if X _||_ Y | S, + * where S is a subset of size d either of adj(X) or of adj(Y), where d is the depth of the search. The fast adjacency + * search performs this procedure for each pair of adjacent edges in the graph and for each depth d = 0, 1, 2, ..., d1, + * where d1 is either the maximum depth or else the first such depth at which no edges can be removed. The + * interpretation of this adjacency search is different for different algorithm, depending on the assumptions of the + * algorithm. A mapping from {x, y} to S({x, y}) is returned for edges x *-* y that have been removed. + *

                + * FAS may optionally use a heuristic from Causation, Prediction and Search, which (like PC-Stable) renders the output + * invariant to the order of the input variables. + *

                + * This algorithm was described in the earlier edition of this book: + *

                + * Spirtes, P., Glymour, C. N., Scheines, R., & Heckerman, D. (2000). Causation, prediction, and search. MIT press. + *

                + * This class is configured to respect knowledge of forbidden and required edges, including knowledge of temporal + * tiers. * * @author peterspirtes * @author clarkglymour @@ -99,10 +97,10 @@ public Graph search() { /** * Discovers all adjacencies in data. The procedure is to remove edges in the graph which connect pairs of - * variables which are independent, conditional on some other set of variables in the graph (the "sepset"). These are - * removed in tiers. First, edges which are independent conditional on zero other variables are removed, then edges - * which are independent conditional on one other variable are removed, then two, then three, and so on, until no - * more edges can be removed from the graph. The edges which remain in the graph after this procedure are the + * variables which are independent, conditional on some other set of variables in the graph (the "sepset"). These + * are removed in tiers. First, edges which are independent conditional on zero other variables are removed, then + * edges which are independent conditional on one other variable are removed, then two, then three, and so on, until + * no more edges can be removed from the graph. The edges which remain in the graph after this procedure are the * adjacencies in the data. * * @param nodes A list of nodes to search over. @@ -323,11 +321,11 @@ public void setPcHeuristicType(PcCommon.PcHeuristicType pcHeuristic) { } /** - *

                Sets whether the stable adjacency search should be used. Default is false. Default is false. See the - * following reference for this:

                - * - *

                Colombo, D., & Maathuis, M. H. (2014). Order-independent constraint-based causal structure learning. J. Mach. - * Learn. Res., 15(1), 3741-3782.

                + * Sets whether the stable adjacency search should be used. Default is false. Default is false. See the following + * reference for this: + *

                + * Colombo, D., & Maathuis, M. H. (2014). Order-independent constraint-based causal structure learning. J. Mach. + * Learn. Res., 15(1), 3741-3782. * * @param stable True iff the case. */ diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fasd.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fasd.java index faaea6f313..007ef3313c 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fasd.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fasd.java @@ -35,12 +35,12 @@ import java.util.*; /** - *

                Adjusts FAS (see) for the deterministic case by refusing to removed edges - * based on conditional independence tests that are judged to be deterministic. That is, if X _||_ Y | Z, but Z - * determines X or Y, then the edge X---Y is not removed.

                - * - *

                This class is configured to respect knowledge of forbidden and required - * edges, including knowledge of temporal tiers.

                + * Adjusts FAS (see) for the deterministic case by refusing to removed edges based on conditional independence tests + * that are judged to be deterministic. That is, if X _||_ Y | Z, but Z determines X or Y, then the edge X---Y is not + * removed. + *

                + * This class is configured to respect knowledge of forbidden and required edges, including knowledge of temporal + * tiers. * * @author peterspirtes * @author josephramsey. @@ -59,8 +59,8 @@ public class Fasd implements IFas { private final TetradLogger logger = TetradLogger.getInstance(); private final NumberFormat nf = new DecimalFormat("0.00E0"); /** - * The search graph. It is assumed going in that all the true adjacencies of x are in this graph for every node - * x. It is hoped (i.e., true in the large sample limit) that true adjacencies are never removed. + * The search graph. It is assumed going in that all the true adjacencies of x are in this graph for every node x. + * It is hoped (i.e., true in the large sample limit) that true adjacencies are never removed. */ private final Graph graph; /** @@ -104,10 +104,10 @@ public Fasd(IndependenceTest test) { /** * Discovers all adjacencies in data. The procedure is to remove edges in the graph which connect pairs of - * variables which are independent, conditional on some other set of variables in the graph (the "sepset"). These are - * removed in tiers. First, edges which are independent conditional on zero other variables are removed, then edges - * which are independent conditional on one other variable are removed, then two, then three, and so on, until no - * more edges can be removed from the graph. The edges which remain in the graph after this procedure are the + * variables which are independent, conditional on some other set of variables in the graph (the "sepset"). These + * are removed in tiers. First, edges which are independent conditional on zero other variables are removed, then + * edges which are independent conditional on one other variable are removed, then two, then three, and so on, until + * no more edges can be removed from the graph. The edges which remain in the graph after this procedure are the * adjacencies in the data. * * @return a graph which indicates which variables are independent conditional on which other variables diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fask.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fask.java index 3abc85bf77..569575f466 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fask.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fask.java @@ -44,29 +44,28 @@ import static org.apache.commons.math3.util.FastMath.*; /** - *

                Implements the FASK (Fast Adjacency Skewness) algorithm, which makes decisions for adjacency - * and orientation using a combination of conditional independence testing, judgments of nonlinear adjacency, and - * pairwise orientation due to non-Gaussianity. The reference is this:

                - * - *

                Sanchez-Romero, R., Ramsey, J. D., Zhang, K., Glymour, M. R., Huang, B., and Glymour, C. - * (2019). Estimating feedforward and feedback effective connections from fMRI time series: Assessments of statistical - * methods. Network Neuroscience, 3(2), 274-30

                - * - *

                Some adjustments have been made in some ways from that version, and some additional pairwise options - * have been added from this reference:

                - * - *

                Hyvärinen, A., and Smith, S. M. (2013). Pairwise likelihood ratios for estimation of non-Gaussian structural - * equation models. Journal of Machine Learning Research, 14(Jan), 111-152.

                - * - *

                This method (and the Hyvarinen and Smith methods) make the assumption that the data are generated by - * a linear, non-Gaussian causal process and attempts to recover the causal graph for that process. They do not attempt - * to recover the parametrization of this graph; for this a separate estimation algorithm would be needed, such as - * linear regression regressing each node onto its parents. A further assumption is made, that there are no latent - * common causes of the algorithm. This is not a constraint on the pairwise orientation methods, since they orient with - * respect only to the two variables at the endpoints of an edge and so are happy with all other variables being - * considered latent with respect to that single edge. However, if the built-in adjacency search is used (FAS-Stable), - * the existence of latents will throw this method off.

                - * + * Implements the FASK (Fast Adjacency Skewness) algorithm, which makes decisions for adjacency and orientation using a + * combination of conditional independence testing, judgments of nonlinear adjacency, and pairwise orientation due to + * non-Gaussianity. The reference is this: + *

                + * Sanchez-Romero, R., Ramsey, J. D., Zhang, K., Glymour, M. R., Huang, B., and Glymour, C. (2019). Estimating + * feedforward and feedback effective connections from fMRI time series: Assessments of statistical methods. Network + * Neuroscience, 3(2), 274-30 + *

                + * Some adjustments have been made in some ways from that version, and some additional pairwise options have been added + * from this reference: + *

                + * Hyvärinen, A., and Smith, S. M. (2013). Pairwise likelihood ratios for estimation of non-Gaussian structural equation + * models. Journal of Machine Learning Research, 14(Jan), 111-152. + *

                + * This method (and the Hyvarinen and Smith methods) make the assumption that the data are generated by a linear, + * non-Gaussian causal process and attempts to recover the causal graph for that process. They do not attempt to recover + * the parametrization of this graph; for this a separate estimation algorithm would be needed, such as linear + * regression regressing each node onto its parents. A further assumption is made, that there are no latent common + * causes of the algorithm. This is not a constraint on the pairwise orientation methods, since they orient with respect + * only to the two variables at the endpoints of an edge and so are happy with all other variables being considered + * latent with respect to that single edge. However, if the built-in adjacency search is used (FAS-Stable), the + * existence of latents will throw this method off. *

                * As was shown in the Hyvarinen and Smith paper above, FASK works quite well even if the graph contains feedback loops * in most configurations, including 2-cycles. 2-cycles can be detected fairly well if the FASK left-right rule is @@ -124,10 +123,9 @@ * concat_BOLDfslfilter_60_FullMacaque.txt --prefix Fask_Test_MacaqueFull --algorithm fask --faskAdjacencyMethod 1 * --depth -1 --test sem-bic-test --score sem-bic-score --semBicRule 1 --penaltyDiscount 2 --skewEdgeThreshold 0.3 * --faskLeftRightRule 1 --faskDelta -0.3 --twoCycleScreeningThreshold 0 --orientationAlpha 0.1 -structurePrior 0 - *

                - * - *

                This class is configured to respect knowledge of forbidden and required - * edges, including knowledge of temporal tiers.

                + *

                + * This class is configured to respect knowledge of forbidden and required edges, including knowledge of temporal + * tiers. * * @author josephramsey * @author rubensanchez @@ -237,6 +235,84 @@ private static double correxp(double[] x, double[] y, double[] z) { return Fask.E(x, y, z) / sqrt(Fask.E(x, x, z) * Fask.E(y, y, z)); } + public static double faskLeftRightV2(double[] x, double[] y, boolean empirical, double delta) { + double sx = skewness(x); + double sy = skewness(y); + double r = correlation(x, y); + double lr = Fask.correxp(x, y, x) - Fask.correxp(x, y, y); + + if (empirical) { + lr *= signum(sx) * signum(sy); + } + + if (r < delta) { + lr *= -1; + } + + return lr; + } + + public static double faskLeftRightV1(double[] x, double[] y, boolean empirical, double delta) { + double left = Fask.cu(x, y, x) / (sqrt(Fask.cu(x, x, x) * Fask.cu(y, y, x))); + double right = Fask.cu(x, y, y) / (sqrt(Fask.cu(x, x, y) * Fask.cu(y, y, y))); + double lr = left - right; + + double r = correlation(x, y); + double sx = skewness(x); + double sy = skewness(y); + + if (empirical) { + r *= signum(sx) * signum(sy); + } + + lr *= signum(r); + if (r < delta) lr *= -1; + + return lr; + } + + public static double robustSkew(double[] x, double[] y, boolean empirical) { + + if (empirical) { + x = correctSkewness(x, skewness(x)); + y = correctSkewness(y, skewness(y)); + } + + double[] lr = new double[x.length]; + + for (int i = 0; i < x.length; i++) { + lr[i] = g(x[i]) * y[i] - x[i] * g(y[i]); + } + + return correlation(x, y) * mean(lr); + } + + public static double skew(double[] x, double[] y, boolean empirical) { + + if (empirical) { + x = correctSkewness(x, skewness(x)); + y = correctSkewness(y, skewness(y)); + } + + double[] lr = new double[x.length]; + + for (int i = 0; i < x.length; i++) { + lr[i] = x[i] * x[i] * y[i] - x[i] * y[i] * y[i]; + } + + return correlation(x, y) * mean(lr); + } + + public static double g(double x) { + return log(cosh(FastMath.max(x, 0))); + } + + public static double[] correctSkewness(double[] data, double sk) { + double[] data2 = new double[data.length]; + for (int i = 0; i < data.length; i++) data2[i] = data[i] * signum(sk); + return data2; + } + /** * Runs the search on the concatenated data, returning a graph, possibly cyclic, possibly with two-cycles. Runs the * fast adjacency search (FAS, Spirtes et al., 2000) followed by a modification of the robust skew rule (Pairwise @@ -469,8 +545,8 @@ public double[][] getB() { } /** - * Returns a matrix of left-right scores for the search. If lr = getLrScores(), then lr[i][j] - * is the left right scores leftRight(data[i], data[j]); + * Returns a matrix of left-right scores for the search. If lr = getLrScores(), then lr[i][j] is the left right + * scores leftRight(data[i], data[j]); * * @return This matrix as a double[][] array. */ @@ -631,74 +707,6 @@ public double leftRight(double[] x, double[] y) { throw new IllegalStateException("Left right rule not configured: " + this.leftRight); } - public static double faskLeftRightV2(double[] x, double[] y, boolean empirical, double delta) { - double sx = skewness(x); - double sy = skewness(y); - double r = correlation(x, y); - double lr = Fask.correxp(x, y, x) - Fask.correxp(x, y, y); - - if (empirical) { - lr *= signum(sx) * signum(sy); - } - - if (r < delta) { - lr *= -1; - } - - return lr; - } - - public static double faskLeftRightV1(double[] x, double[] y, boolean empirical, double delta) { - double left = Fask.cu(x, y, x) / (sqrt(Fask.cu(x, x, x) * Fask.cu(y, y, x))); - double right = Fask.cu(x, y, y) / (sqrt(Fask.cu(x, x, y) * Fask.cu(y, y, y))); - double lr = left - right; - - double r = correlation(x, y); - double sx = skewness(x); - double sy = skewness(y); - - if (empirical) { - r *= signum(sx) * signum(sy); - } - - lr *= signum(r); - if (r < delta) lr *= -1; - - return lr; - } - - public static double robustSkew(double[] x, double[] y, boolean empirical) { - - if (empirical) { - x = correctSkewness(x, skewness(x)); - y = correctSkewness(y, skewness(y)); - } - - double[] lr = new double[x.length]; - - for (int i = 0; i < x.length; i++) { - lr[i] = g(x[i]) * y[i] - x[i] * g(y[i]); - } - - return correlation(x, y) * mean(lr); - } - - public static double skew(double[] x, double[] y, boolean empirical) { - - if (empirical) { - x = correctSkewness(x, skewness(x)); - y = correctSkewness(y, skewness(y)); - } - - double[] lr = new double[x.length]; - - for (int i = 0; i < x.length; i++) { - lr[i] = x[i] * x[i] * y[i] - x[i] * y[i] * y[i]; - } - - return correlation(x, y) * mean(lr); - } - private double tanh(double[] x, double[] y, boolean empirical) { if (empirical) { @@ -715,10 +723,6 @@ private double tanh(double[] x, double[] y, boolean empirical) { return correlation(x, y) * mean(lr); } - public static double g(double x) { - return log(cosh(FastMath.max(x, 0))); - } - private boolean knowledgeOrients(Node X, Node Y) { return this.knowledge.isForbidden(Y.getName(), X.getName()) || this.knowledge.isRequired(X.getName(), Y.getName()); } @@ -727,12 +731,6 @@ private boolean edgeForbiddenByKnowledge(Node X, Node Y) { return this.knowledge.isForbidden(Y.getName(), X.getName()) && this.knowledge.isForbidden(X.getName(), Y.getName()); } - public static double[] correctSkewness(double[] data, double sk) { - double[] data2 = new double[data.length]; - for (int i = 0; i < data.length; i++) data2[i] = data[i] * signum(sk); - return data2; - } - private boolean twoCycleTest(int i, int j, double[][] D, Graph G0, List V) { Node X = V.get(i); Node Y = V.get(j); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/FastIca.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/FastIca.java index 7692028629..56d40b8580 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/FastIca.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/FastIca.java @@ -31,21 +31,22 @@ import static org.apache.commons.math3.util.FastMath.*; /** - *

                Translates a version of the FastICA algorithm used in R from Fortran - * into Java for use in Tetrad. This can be used in various algorithms that assume linearity and non-gaussianity, as for - * example LiNGAM and LiNG-D. There is one difference from the R, in that in R FastICA can operate over complex numbers, - * whereas here it is restricted to real numbers. A useful reference is this:

                - * - *

                Oja, E., & Hyvarinen, A. (2000). Independent component analysis: - * algorithms and applications. Neural networks, 13(4-5), 411-430.

                - * - *

                The documentation of the R version is as follows, all of which is true of this - * translation (so far as I know) except for its being in R and its allowing complex values. + * Translates a version of the FastICA algorithm used in R from Fortran into Java for use in Tetrad. This can be used in + * various algorithms that assume linearity and non-gaussianity, as for example LiNGAM and LiNG-D. There is one + * difference from the R, in that in R FastICA can operate over complex numbers, whereas here it is restricted to real + * numbers. A useful reference is this: + *

                + * Oja, E., & Hyvarinen, A. (2000). Independent component analysis: algorithms and applications. Neural networks, + * 13(4-5), 411-430. + *

                + * The documentation of the R version is as follows, all of which is true of this translation (so far as I know) except + * for its being in R and its allowing complex values. *

                * Description: *

                * This is an R and C code implementation of the FastICA algorithm of Aapo Hyvarinen et al. (URL: - * http://www.cis.hut.fi/aapo/) to perform Independent Component Analysis (ICA) and Projection Pursuit. + * http://www.cis.hut.fi/aapo/) to perform Independent Component Analysis + * (ICA) and Projection Pursuit. *

                * Usage: *

                @@ -98,8 +99,7 @@ * First, the data is centered by subtracting the mean of each column of the data matrix X. *

                * The data matrix is then `whitened' by projecting the data onto it's principle component directions i.e. X -> XK - * where K is a pre-whitening matrix. - * The user can specify the number of components. + * where K is a pre-whitening matrix. The user can specify the number of components. *

                * The ICA algorithm then estimates a matrix W s.t XKW = S . W is chosen to maximize the neg-entropy approximation under * the constraints that W is an orthonormal matrix. This constraint ensures that the estimated components are @@ -120,7 +120,6 @@ *

                * A. Hyvarinen and E. Oja (2000) Independent Component Analysis: Algorithms and Applications, _Neural Networks_, * *13(4-5)*:411-430 - *

                * * @author josephramsey */ @@ -157,8 +156,8 @@ public class FastIca { private int numComponents; /** - * If algorithmType == PARALLEL, the components are extracted simultaneously (the default). - * if algorithmType == DEFLATION, the components are extracted one at a time. + * If algorithmType == PARALLEL, the components are extracted simultaneously (the default). if algorithmType == + * DEFLATION, the components are extracted one at a time. */ private int algorithmType = FastIca.PARALLEL; @@ -195,7 +194,8 @@ public class FastIca { private boolean verbose; /** - * Initial un-mixing matrix of dimension (n.comp,n.comp). If null (default), then a matrix of normal r.v.'s is used. + * Initial un-mixing matrix of dimension (n.comp,n.comp). If null (default), then a matrix of normal r.v.'s is + * used. */ private Matrix wInit; @@ -213,8 +213,8 @@ public FastIca(Matrix X, int numComponents) { /** - * If algorithmType == PARALLEL, the components are extracted simultaneously (the default). - * if algorithmType == DEFLATION, the components are extracted one at a time. + * If algorithmType == PARALLEL, the components are extracted simultaneously (the default). if algorithmType == + * DEFLATION, the components are extracted one at a time. * * @param algorithmType This type. */ @@ -297,8 +297,8 @@ public void setVerbose(boolean verbose) { } /** - * Sets the initial un-mixing matrix of dimension (n.comp,n.comp). - * If NULL (default), then a random matrix of normal r.v.'s is used. + * Sets the initial un-mixing matrix of dimension (n.comp,n.comp). If NULL (default), then a random matrix of normal + * r.v.'s is used. * * @param wInit This matrix. */ diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fci.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fci.java index fee0ed8e8a..d41c29f0df 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fci.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fci.java @@ -38,28 +38,26 @@ import java.util.Set; /** - *

                Implements the Fast Causal Inference (FCI) algorithm due to Peter Spirtes, which addressed - * the case where latent common causes cannot be assumed not to exist with respect to the data set being analyzed. That - * is, it is assumed that there may be variables that are not included in the data that nonetheless may be causes of two - * or more variables that are included in data.

                - * - *

                Two alternatives are provided for doing the final orientation step, one due to Peter Spirtes, - * which is arrow complete, and another due to Jiji Zhang, which is arrow and tail complete.

                - * - *

                This algorithm, with the Spirtes final orientation rules, was given in an earlier version of - * this book:

                - * - *

                Spirtes, P., Glymour, C. N., Scheines, R., & Heckerman, D. (2000). Causation, - * prediction, and search. MIT press.

                - * - *

                The algorithm with the Zhang final orientation rules was given in this reference:

                - * - *

                Zhang, J. (2008). On the completeness of orientation rules for causal discovery in the presence - * of latent confounders and selection bias. Artificial Intelligence, 172(16-17), 1873-1896.

                - * - * - *

                This class is configured to respect knowledge of forbidden and required - * edges, including knowledge of temporal tiers.

                + * Implements the Fast Causal Inference (FCI) algorithm due to Peter Spirtes, which addressed the case where latent + * common causes cannot be assumed not to exist with respect to the data set being analyzed. That is, it is assumed that + * there may be variables that are not included in the data that nonetheless may be causes of two or more variables that + * are included in data. + *

                + * Two alternatives are provided for doing the final orientation step, one due to Peter Spirtes, which is arrow + * complete, and another due to Jiji Zhang, which is arrow and tail complete. + *

                + * This algorithm, with the Spirtes final orientation rules, was given in an earlier version of this book: + *

                + * Spirtes, P., Glymour, C. N., Scheines, R., & Heckerman, D. (2000). Causation, prediction, and search. MIT press. + *

                + * The algorithm with the Zhang final orientation rules was given in this reference: + *

                + * Zhang, J. (2008). On the completeness of orientation rules for causal discovery in the presence of latent confounders + * and selection bias. Artificial Intelligence, 172(16-17), 1873-1896. + *

                + *

                + * This class is configured to respect knowledge of forbidden and required edges, including knowledge of temporal + * tiers. * * @author peterspirtes * @author clarkglymour @@ -246,8 +244,8 @@ public void setKnowledge(Knowledge knowledge) { } /** - * Sets whether the Zhang complete rule set should be used; false if only R1-R4 (the rule set of the original - * FCI) should be used. False by default. + * Sets whether the Zhang complete rule set should be used; false if only R1-R4 (the rule set of the original FCI) + * should be used. False by default. * * @param completeRuleSetUsed True for the complete Zhang rule set. */ diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/FciMax.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/FciMax.java index 8d8e72f01a..242919b27e 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/FciMax.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/FciMax.java @@ -39,25 +39,24 @@ import java.util.concurrent.RecursiveTask; /** - *

                Modifies FCI to do orientation of unshielded colliders (X*-*Y*-*Z with X and Z - * not adjacent) using the max-P rule (see the PC-Max algorithm). This reference is relevant:

                - * - *

                Raghu, V. K., Zhao, W., Pu, J., Leader, J. K., Wang, R., Herman, J., ... & - * Wilson, D. O. (2019). Feasibility of lung cancer prediction from low-dose CT scan and smoking factors using causal - * models. Thorax, 74(7), 643-649.

                - * - *

                Max-P triple orientation is a method for orienting unshielded triples - * X*=-*Y*-*Z as one of the following: (a) Collider, X->Y<-Z, or (b) Noncollider, X-->Y-->Z, or X<-Y<-Z, or X<-Y->Z. One - * does this by conditioning on subsets of adj(X) or adj(Z). One first checks conditional independence of X and Z - * conditional on each of these subsets, and lists the p-values for each test. Then, one chooses the conditioning set - * out of all of these that maximizes the p-value. If this conditioning set contains Y, then the triple is judged to be - * a noncollider; otherwise, it is judged to be a collider.

                - * - *

                All unshielded triples in the graph given by FAS are judged as colliders - * or non-colliders and the colliders oriented. Then the final FCI orientation rules are applied, as in FCI.

                - * - *

                This class is configured to respect knowledge of forbidden and required - * edges, including knowledge of temporal tiers.

                + * Modifies FCI to do orientation of unshielded colliders (X*-*Y*-*Z with X and Z not adjacent) using the max-P rule + * (see the PC-Max algorithm). This reference is relevant: + *

                + * Raghu, V. K., Zhao, W., Pu, J., Leader, J. K., Wang, R., Herman, J., ... & Wilson, D. O. (2019). Feasibility of + * lung cancer prediction from low-dose CT scan and smoking factors using causal models. Thorax, 74(7), 643-649. + *

                + * Max-P triple orientation is a method for orienting unshielded triples X*=-*Y*-*Z as one of the following: (a) + * Collider, X->Y<-Z, or (b) Noncollider, X-->Y-->Z, or X<-Y<-Z, or X<-Y->Z. One does this by + * conditioning on subsets of adj(X) or adj(Z). One first checks conditional independence of X and Z conditional on each + * of these subsets, and lists the p-values for each test. Then, one chooses the conditioning set out of all of these + * that maximizes the p-value. If this conditioning set contains Y, then the triple is judged to be a noncollider; + * otherwise, it is judged to be a collider. + *

                + * All unshielded triples in the graph given by FAS are judged as colliders or non-colliders and the colliders oriented. + * Then the final FCI orientation rules are applied, as in FCI. + *

                + * This class is configured to respect knowledge of forbidden and required edges, including knowledge of temporal + * tiers. * * @author josephramsey * @see Fci diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fges.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fges.java index a8b7353ab0..3ff6cac8d7 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fges.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fges.java @@ -43,37 +43,34 @@ import static org.apache.commons.math3.util.FastMath.min; /** - *

                Implements the Fast Greedy Equivalence Search (FGES) algorithm. This is - * an implementation of the Greedy Equivalence Search algorithm, originally due to Chris Meek but developed - * significantly by Max Chickering. FGES uses with some optimizations that allow it to scale accurately to thousands of - * variables accurately for the sparse case. The reference for FGES is this:

                - * - *

                Ramsey, J., Glymour, M., Sanchez-Romero, R., & Glymour, C. (2017). - * A million variables and more: the fast greedy equivalence search algorithm for learning high-dimensional graphical - * causal models, with an application to functional magnetic resonance images. International journal of data science and - * analytics, 3, 121-129.

                - * - *

                The reference for Chickering's GES is this:

                - * - *

                Chickering (2002) "Optimal structure identification with greedy search" - * Journal of Machine Learning Research.

                - * - *

                FGES works for the continuous case, the discrete case, and the mixed - * continuous/discrete case, so long as a BIC score is available for the type of data in question.

                - * - *

                To speed things up, it has been assumed that variables X and Y with zero - * correlation do not correspond to edges in the graph. This is a restricted form of the heuristic speedup assumption, - * something GES does not assume. This heuristic speedup assumption needs to be explicitly turned on using - * setHeuristicSpeedup(true).

                - * - *

                Also, edges to be added or remove from the graph in the forward or - * backward phase, respectively are cached, together with the ancillary information needed to do the additions or - * removals, to reduce rescoring.

                - * - *

                A number of other optimizations were also. See code for details.

                - * - *

                This class is configured to respect knowledge of forbidden and required - * edges, including knowledge of temporal tiers.

                + * Implements the Fast Greedy Equivalence Search (FGES) algorithm. This is an implementation of the Greedy Equivalence + * Search algorithm, originally due to Chris Meek but developed significantly by Max Chickering. FGES uses with some + * optimizations that allow it to scale accurately to thousands of variables accurately for the sparse case. The + * reference for FGES is this: + *

                + * Ramsey, J., Glymour, M., Sanchez-Romero, R., & Glymour, C. (2017). A million variables and more: the fast greedy + * equivalence search algorithm for learning high-dimensional graphical causal models, with an application to functional + * magnetic resonance images. International journal of data science and analytics, 3, 121-129. + *

                + * The reference for Chickering's GES is this: + *

                + * Chickering (2002) "Optimal structure identification with greedy search" Journal of Machine Learning Research. + *

                + * FGES works for the continuous case, the discrete case, and the mixed continuous/discrete case, so long as a BIC score + * is available for the type of data in question. + *

                + * To speed things up, it has been assumed that variables X and Y with zero correlation do not correspond to edges in + * the graph. This is a restricted form of the heuristic speedup assumption, something GES does not assume. This + * heuristic speedup assumption needs to be explicitly turned on using setHeuristicSpeedup(true). + *

                + * Also, edges to be added or remove from the graph in the forward or backward phase, respectively are cached, together + * with the ancillary information needed to do the additions or removals, to reduce rescoring. + *

                + * A number of other optimizations were also. See code for de + * tails. + *

                + * This class is configured to respect knowledge of forbidden and required edges, including knowledge of temporal + * tiers. * * @author Ricardo Silva * @author josephramsey @@ -195,8 +192,8 @@ private static Node traverseSemiDirected(Node node, Edge edge) { } /** - * Greedy equivalence search: Start from the empty graph, add edges till the model is significant. - * Then start deleting edges till a minimum is achieved. + * Greedy equivalence search: Start from the empty graph, add edges till the model is significant. Then start + * deleting edges till a minimum is achieved. * * @return the resulting Pattern. */ diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/FgesMb.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/FgesMb.java index b200507c35..8e14453805 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/FgesMb.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/FgesMb.java @@ -43,37 +43,33 @@ import static org.apache.commons.math3.util.FastMath.min; /** - *

                Implements the Fast Greedy Equivalence Search (FGES) algorithm. This is - * an implementation of the Greedy Equivalence Search algorithm, originally due to Chris Meek but developed - * significantly by Max Chickering. FGES uses with some optimizations that allow it to scale accurately to thousands of - * variables accurately for the sparse case. The reference for FGES is this:

                - * - *

                Ramsey, J., Glymour, M., Sanchez-Romero, R., & Glymour, C. (2017). - * A million variables and more: the fast greedy equivalence search algorithm for learning high-dimensional graphical - * causal models, with an application to functional magnetic resonance images. International journal of data science and - * analytics, 3, 121-129.

                - * - *

                The reference for Chickering's GES is this:

                - * - *

                Chickering (2002) "Optimal structure identification with greedy search" - * Journal of Machine Learning Research.

                - * - *

                FGES works for the continuous case, the discrete case, and the mixed - * continuous/discrete case, so long as a BIC score is available for the type of data in question.

                - * - *

                To speed things up, it has been assumed that variables X and Y with zero - * correlation do not correspond to edges in the graph. This is a restricted form of the heuristic speedup assumption, - * something GES does not assume. This heuristic speedup assumption needs to be explicitly turned on using - * setHeuristicSpeedup(true).

                - * - *

                Also, edges to be added or remove from the graph in the forward or - * backward phase, respectively are cached, together with the ancillary information needed to do the additions or - * removals, to reduce rescoring.

                - * - *

                A number of other optimizations were also. See code for details.

                - * - *

                This class is configured to respect knowledge of forbidden and required - * edges, including knowledge of temporal tiers.

                + * Implements the Fast Greedy Equivalence Search (FGES) algorithm. This is an implementation of the Greedy Equivalence + * Search algorithm, originally due to Chris Meek but developed significantly by Max Chickering. FGES uses with some + * optimizations that allow it to scale accurately to thousands of variables accurately for the sparse case. The + * reference for FGES is this: + *

                + * Ramsey, J., Glymour, M., Sanchez-Romero, R., & Glymour, C. (2017). A million variables and more: the fast greedy + * equivalence search algorithm for learning high-dimensional graphical causal models, with an application to functional + * magnetic resonance images. International journal of data science and analytics, 3, 121-129. + *

                + * The reference for Chickering's GES is this: + *

                + * Chickering (2002) "Optimal structure identification with greedy search" Journal of Machine Learning Research. + *

                + * FGES works for the continuous case, the discrete case, and the mixed continuous/discrete case, so long as a BIC score + * is available for the type of data in question. + *

                + * To speed things up, it has been assumed that variables X and Y with zero correlation do not correspond to edges in + * the graph. This is a restricted form of the heuristic speedup assumption, something GES does not assume. This + * heuristic speedup assumption needs to be explicitly turned on using setHeuristicSpeedup(true). + *

                + * Also, edges to be added or remove from the graph in the forward or backward phase, respectively are cached, together + * with the ancillary information needed to do the additions or removals, to reduce rescoring. + *

                + * A number of other optimizations were also. See code for details. + *

                + * This class is configured to respect knowledge of forbidden and required edges, including knowledge of temporal + * tiers. * * @author Ricardo Silva * @author josephramsey @@ -83,39 +79,29 @@ * @see Knowledge */ public final class FgesMb implements DagScorer { - public enum TrimmingStyle { - NONE, ADJACENT_TO_TARGETS, MARKOV_BLANKET_GRAPH, SEMIDIRECTED_PATHS_TO_TARGETS - } - + //===internal===// + private final Set emptySet = new HashSet<>(); + private final int[] count = new int[1]; + private final int depth = 10000; + //The top n graphs found by the algorithm, where n is numPatternsToStore. + private final LinkedList topGraphs = new LinkedList<>(); + // Potential arrows sorted by bump high to low. The first one is a candidate for adding to the graph. + private final SortedSet sortedArrows = new ConcurrentSkipListSet<>(); + private final TetradLogger logger = TetradLogger.getInstance(); + private final Map arrowsMap = new ConcurrentHashMap<>(); + List targets = new ArrayList<>(); // The number of times the forward phase is iterated to expand to new adjacencies. private int numExpansions = 2; - // The style of trimming to use. private int trimmingStyle = 3; // default MB trimming. - // Bounds the degree of the graph. private int maxDegree = -1; - // Whether one-edge faithfulness is assumed (less general but faster). private boolean faithfulnessAssumed = false; - // The knowledge to use in the search. private Knowledge knowledge = new Knowledge(); - // True, if FGES should run in a single thread, no if parallelized. private boolean parallelized = false; - - //===internal===// - private final Set emptySet = new HashSet<>(); - private final int[] count = new int[1]; - private final int depth = 10000; - //The top n graphs found by the algorithm, where n is numPatternsToStore. - private final LinkedList topGraphs = new LinkedList<>(); - // Potential arrows sorted by bump high to low. The first one is a candidate for adding to the graph. - private final SortedSet sortedArrows = new ConcurrentSkipListSet<>(); - private final TetradLogger logger = TetradLogger.getInstance(); - private final Map arrowsMap = new ConcurrentHashMap<>(); - List targets = new ArrayList<>(); private List variables; private Graph initialGraph; private Graph boundGraph = null; @@ -138,12 +124,10 @@ public enum TrimmingStyle { private double modelScore; // Internal. private Mode mode = Mode.heuristicSpeedup; - // True if the first step of adding an edge to an empty graph should be scored in both directions // for each edge with the maximum score chosen. private boolean symmetricFirstStep = false; private ArrayList allTargets; - /** * Constructor. Construct a Score and pass it in here. The totalScore should return a positive value in case of * conditional dependence and a negative values in case of conditional independence. See Chickering (2002), locally @@ -161,6 +145,21 @@ public FgesMb(Score score) { this.graph = new EdgeListGraph(getVariables()); } + // Used to find semidirected paths for cycle checking. + private static Node traverseSemiDirected(Node node, Edge edge) { + if (node == edge.getNode1()) { + if (edge.getEndpoint1() == Endpoint.TAIL) { + return edge.getNode2(); + } + } else if (node == edge.getNode2()) { + if (edge.getEndpoint2() == Endpoint.TAIL) { + return edge.getNode1(); + } + } + + return null; + } + public void setTrimmingStyle(int trimmingStyle) { this.trimmingStyle = trimmingStyle; } @@ -396,21 +395,6 @@ public double getModelScore() { return modelScore; } - // Used to find semidirected paths for cycle checking. - private static Node traverseSemiDirected(Node node, Edge edge) { - if (node == edge.getNode1()) { - if (edge.getEndpoint1() == Endpoint.TAIL) { - return edge.getNode2(); - } - } else if (node == edge.getNode2()) { - if (edge.getEndpoint2() == Endpoint.TAIL) { - return edge.getNode1(); - } - } - - return null; - } - //Sets the discrete scoring function to use. private void setScore(Score score) { this.score = score; @@ -1093,6 +1077,10 @@ public void setNumExpansions(int numExpansions) { this.numExpansions = numExpansions; } + public enum TrimmingStyle { + NONE, ADJACENT_TO_TARGETS, MARKOV_BLANKET_GRAPH, SEMIDIRECTED_PATHS_TO_TARGETS + } + /** * Internal. */ diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fofc.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fofc.java index db99e653de..220126cb0d 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fofc.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fofc.java @@ -37,20 +37,18 @@ /** - *

                Implements the Find One Factor Clusters (FOFC) algorithm by Erich Kummerfeld, which - * uses reasoning about vanishing tetrads of algorithms to infer clusters of the measured variables in a dataset that - * each be explained by a single latent variable. A reference is the following

                - * - *

                Kummerfeld, E., & Ramsey, J. (2016, August). Causal clustering for 1-factor measurement - * models. In Proceedings of the 22nd ACM SIGKDD international conference on knowledge discovery and data mining (pp. - * 1655-1664).

                - * - *

                The algorithm employs tests of vanishing tetrads (list of 4 variables that follow - * a certain pattern in the exchangeability of latent paths with respect to the data). The notion of vanishing tetrads is - * old one but is explained in this book:

                - * - *

                Spirtes, P., Glymour, C. N., Scheines, R., & Heckerman, D. (2000). Causation, - * prediction, and search. MIT press.

                + * Implements the Find One Factor Clusters (FOFC) algorithm by Erich Kummerfeld, which uses reasoning about vanishing + * tetrads of algorithms to infer clusters of the measured variables in a dataset that each be explained by a single + * latent variable. A reference is the following + *

                + * Kummerfeld, E., & Ramsey, J. (2016, August). Causal clustering for 1-factor measurement models. In Proceedings of + * the 22nd ACM SIGKDD international conference on knowledge discovery and data mining (pp. 1655-1664). + *

                + * The algorithm employs tests of vanishing tetrads (list of 4 variables that follow a certain pattern in the + * exchangeability of latent paths with respect to the data). The notion of vanishing tetrads is old one but is + * explained in this book: + *

                + * Spirtes, P., Glymour, C. N., Scheines, R., & Heckerman, D. (2000). Causation, prediction, and search. MIT press. * * @author peterspirtes * @author erichkummerfeld diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Ftfc.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Ftfc.java index 0e4886ceda..a67da120c8 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Ftfc.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Ftfc.java @@ -44,18 +44,17 @@ /** - *

                Implements the Find Two Factor Clusters (FOFC) algorithm, which uses reasoning - * about vanishing tetrads of algorithms to infer clusters of the measured variables in a dataset that each be explained - * by a single latent variable. The reference is as follows:

                - * - *

                Kummerfeld, E. & Ramsey, J. & Yang, R. & Spirtes, P. & Scheines, R. (2014). - * Causal Clustering for 2-Factor Measurement Models. In T. Calders, F. Esposito, E. Hullermeier, and R. Meo, editors, - * Machine Learning and Knowledge Discovery in Databases, volume 8725 of Lecture Notes in Computer Science, pages 34-49. - * Springer Berlin Heidelberg.

                - * - *

                The two-factor version of the algorithm substitutes sextad tests for - * tetrad tests and searches for clusters of at least 6 variables that can be explained by two latent factors by - * calculating vanishing sextads.

                + * Implements the Find Two Factor Clusters (FOFC) algorithm, which uses reasoning about vanishing tetrads of algorithms + * to infer clusters of the measured variables in a dataset that each be explained by a single latent variable. The + * reference is as follows: + *

                + * Kummerfeld, E. & Ramsey, J. & Yang, R. & Spirtes, P. & Scheines, R. (2014). Causal Clustering for + * 2-Factor Measurement Models. In T. Calders, F. Esposito, E. Hullermeier, and R. Meo, editors, Machine Learning and + * Knowledge Discovery in Databases, volume 8725 of Lecture Notes in Computer Science, pages 34-49. Springer Berlin + * Heidelberg. + *

                + * The two-factor version of the algorithm substitutes sextad tests for tetrad tests and searches for clusters of at + * least 6 variables that can be explained by two latent factors by calculating vanishing sextads. * * @author peterspirtes * @author erichkummerfeld diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/GFci.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/GFci.java index 8e966cb006..b8a2d053b8 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/GFci.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/GFci.java @@ -37,28 +37,25 @@ import static edu.cmu.tetrad.graph.GraphUtils.gfciExtraEdgeRemovalStep; /** - *

                Implements a modification of FCI that started by running the FGES algorithm and - * then fixes that result to be correct for latent variables models. First, colliders from the FGES results are copied - * into the final circle-circle graph, and some independence reasoning is used to add the remaining colliders into the - * graph. Then, the FCI final orientation rules are applied. The reference is here:

                - * - *

                Ogarrio, J. M., Spirtes, P., & Ramsey, J. (2016, August). A hybrid causal - * search algorithm for latent variable models. In Conference on probabilistic graphical models (pp. 368-379). - * PMLR.

                - * - *

                Because the method both runs FGES (a score-based algorithm) and does - * additional checking of conditional independencies, both as part of its collider orientation step and also as part of - * the the definite discriminating path step in the final FCI orientation rules, both a score and a test need to be used - * to construct a GFCI algorithm.

                - * - *

                Note that various score-based algorithms could be used in place of FGES - * for the initial step; in this repository we give three other options, GRaSP-FCI, BFCI (BOSS FCI), and SP-FCI - * (see).

                - * - *

                For more information on the algorithm, see the reference above.

                - * - *

                This class is configured to respect knowledge of forbidden and required - * edges, including knowledge of temporal tiers.

                + * Implements a modification of FCI that started by running the FGES algorithm and then fixes that result to be correct + * for latent variables models. First, colliders from the FGES results are copied into the final circle-circle graph, + * and some independence reasoning is used to add the remaining colliders into the graph. Then, the FCI final + * orientation rules are applied. The reference is here: + *

                + * Ogarrio, J. M., Spirtes, P., & Ramsey, J. (2016, August). A hybrid causal search algorithm for latent variable + * models. In Conference on probabilistic graphical models (pp. 368-379). PMLR. + *

                + * Because the method both runs FGES (a score-based algorithm) and does additional checking of conditional + * independencies, both as part of its collider orientation step and also as part of the the definite discriminating + * path step in the final FCI orientation rules, both a score and a test need to be used to construct a GFCI algorithm. + *

                + * Note that various score-based algorithms could be used in place of FGES for the initial step; in this repository we + * give three other options, GRaSP-FCI, BFCI (BOSS FCI), and SP-FCI (see). + *

                + * For more information on the algorithm, see the reference above. + *

                + * This class is configured to respect knowledge of forbidden and required edges, including knowledge of temporal + * tiers. * * @author Juan Miguel Ogarrio * @author peterspirtes diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Grasp.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Grasp.java index 4f5c7d1242..4891f4cd8c 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Grasp.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Grasp.java @@ -7,12 +7,10 @@ import edu.cmu.tetrad.search.score.Score; import edu.cmu.tetrad.search.utils.TeyssierScorer; import edu.cmu.tetrad.util.MillisecondTimes; -import edu.cmu.tetrad.util.NumberFormatUtil; import edu.cmu.tetrad.util.RandomUtil; import edu.cmu.tetrad.util.TetradLogger; import org.jetbrains.annotations.NotNull; -import java.text.NumberFormat; import java.util.*; import static java.lang.Double.NEGATIVE_INFINITY; @@ -20,35 +18,32 @@ /** - *

                Implements the GRaSP algorithms, which uses a certain procedure to search - * in the space of permutations of variables for ones that imply CPDAGs that are especially close to the CPDAG of the - * true model. The reference is here:

                - * - *

                Lam, W. Y., Andrews, B., & Ramsey, J. (2022, August). Greedy relaxations of - * the sparsest permutation algorithm. In Uncertainty in Artificial Intelligence (pp. 1052-1062). PMLR.

                - * - *

                GRaSP can use either a score or an independence test; you can provide - * both, though if you do you need to use the parameters to choose which one will be used. The score options is more - * scalable and accurate, though the independence option is perhaps a little easier ot deal with theoretically and are - * useful for generating unit test results.

                - * - *

                As shown the reference above, GRaSP generates results for the linear, Gaussian - * case for N = 1000 with precisions for adjacencies and arrowheads near 1 and recalls of about 0.85, when the linear, - * Gaussian BIC score is used with a penalty of 2. For N = 10,000 recalls also rise up to about 1, so it can be an - * extraordinarily accurate search for the linear, Gaussian case. But in principle, it can be used with any sort of - * data, so long as a BIC score is available for that data. So it can be used for the discrete case and for the mixed - * continuous/discrete case as well.

                - * - *

                The version of GRaSP described in the above reference is limited to about 100 - * variables in execution time, after which it become impracticably slow. Recent optimizations allow it to scale further - * than that; hopefully these will be written up soon and made available.

                - * - *

                Knowledge can be used with this search. If tiered knowledge is used, then - * the procedure is carried out for each tier separately, given the variable preceding that tier, which allows the SP - * algorithm to address tiered (e.g., time series) problems with larger numbers of variables.

                - * - *

                This class is configured to respect knowledge of forbidden and required - * edges, including knowledge of temporal tiers.

                + * Implements the GRaSP algorithms, which uses a certain procedure to search in the space of permutations of variables + * for ones that imply CPDAGs that are especially close to the CPDAG of the true model. The reference is here: + *

                + * Lam, W. Y., Andrews, B., & Ramsey, J. (2022, August). Greedy relaxations of the sparsest permutation algorithm. + * In Uncertainty in Artificial Intelligence (pp. 1052-1062). PMLR. + *

                + * GRaSP can use either a score or an independence test; you can provide both, though if you do you need to use the + * parameters to choose which one will be used. The score options is more scalable and accurate, though the independence + * option is perhaps a little easier ot deal with theoretically and are useful for generating unit test results. + *

                + * As shown the reference above, GRaSP generates results for the linear, Gaussian case for N = 1000 with precisions for + * adjacencies and arrowheads near 1 and recalls of about 0.85, when the linear, Gaussian BIC score is used with a + * penalty of 2. For N = 10,000 recalls also rise up to about 1, so it can be an extraordinarily accurate search for the + * linear, Gaussian case. But in principle, it can be used with any sort of data, so long as a BIC score is available + * for that data. So it can be used for the discrete case and for the mixed continuous/discrete case as well. + *

                + * The version of GRaSP described in the above reference is limited to about 100 variables in execution time, after + * which it become impracticably slow. Recent optimizations allow it to scale further than that; hopefully these will be + * written up soon and made available. + *

                + * Knowledge can be used with this search. If tiered knowledge is used, then the procedure is carried out for each tier + * separately, given the variable preceding that tier, which allows the SP algorithm to address tiered (e.g., time + * series) problems with larger numbers of variables. + *

                + * This class is configured to respect knowledge of forbidden and required edges, including knowledge of temporal + * tiers. * * @author bryanandrews * @author josephramsey diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/GraspFci.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/GraspFci.java index c5b5405fc4..809260a4ef 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/GraspFci.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/GraspFci.java @@ -36,23 +36,21 @@ import static edu.cmu.tetrad.graph.GraphUtils.gfciExtraEdgeRemovalStep; /** - *

                Uses GRaSP in place of FGES for the initial step in the GFCI algorithm. - * This tends to produce a accurate PAG than GFCI as a result, for the latent variables case. This is a simple - * substitution; the reference for GFCI is here:

                - *

                J.M. Ogarrio and P. Spirtes and J. Ramsey, "A Hybrid Causal Search Algorithm - * for Latent Variable Models," JMLR 2016. Here, BOSS has been substituted for FGES.

                - * - *

                For the first step, the GRaSP algorithm is used, with the same - * modifications as in the GFCI algorithm.

                - * - *

                For the second step, the FCI final orientation algorithm is used, with the same - * modifications as in the GFCI algorithm.

                - * - *

                For GRaSP only a score is needed, but there are steps in GFCI that require - * a test, so for this method, both a test and a score need to be given.

                - * - *

                This class is configured to respect knowledge of forbidden and required - * edges, including knowledge of temporal tiers.

                + * Uses GRaSP in place of FGES for the initial step in the GFCI algorithm. This tends to produce a accurate PAG than + * GFCI as a result, for the latent variables case. This is a simple substitution; the reference for GFCI is here: J.M. + * Ogarrio and P. Spirtes and J. Ramsey, "A Hybrid Causal Search Algorithm for Latent Variable Models," JMLR 2016. Here, + * BOSS has been substituted for FGES. + *

                + * For the first step, the GRaSP algorithm is used, with the same modifications as in the GFCI algorithm. + *

                + * For the second step, the FCI final orientation algorithm is used, with the same modifications as in the GFCI + * algorithm. + *

                + * For GRaSP only a score is needed, but there are steps in GFCI that require a test, so for this method, both a test + * and a score need to be given. + *

                + * This class is configured to respect knowledge of forbidden and required edges, including knowledge of temporal + * tiers. * * @author josephramsey * @author bryanandrews diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/GrowShrink.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/GrowShrink.java index e6d3a5b685..dec7605616 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/GrowShrink.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/GrowShrink.java @@ -29,29 +29,27 @@ import java.util.Set; /** - *

                Implements the Grow-Shrink algorithm of Margaritis and Thrun, a simple yet - * correct and useful Markov blanket search.

                + * Implements the Grow-Shrink algorithm of Margaritis and Thrun, a simple yet correct and useful Markov blanket search. + *

                + * Margaritis, D., & Thrun, S. (1999). Bayesian network induction via local neighborhoods. Advances in neural + * information processing systems, 12. + *

                + * Grow-Shrink learns the Markov blanket of a node, given a conditional independence test over a list of possible nodes. + * The Markov blanket is a set of nodes (or, in this case a list of distinct nodes), conditional on which every other + * node in the set is independent of X. In this case, a minimal Markov blanket is learned, which is to say, a Markov + * boundary of X. + *

                + * Graphically, in a DAG, the Markov blanket of X is the set of parents, children, and parents of children of X; + * GrowShrink will, for a faithful test, learn this set for X. However, a graph over the nodes together with X is not + * learned; other algorithms are available to do that (see, e.g., FgesMb, PcMb). + *

                + * We include GrowShrink in our algorithm suite mainly because it is a CMU algorithm (see the above reference). Markov + * blanket search has been explored in some detail in the literature and several algorithms are available. See for + * instance the BNLEARN package in R: * - *

                Margaritis, D., & Thrun, S. (1999). Bayesian network induction via local - * neighborhoods. Advances in neural information processing systems, 12.

                - * - *

                Grow-Shrink learns the Markov blanket of a node, given a conditional independence - * test over a list of possible nodes. The Markov blanket is a set of nodes (or, in this case a list of distinct nodes), - * conditional on which every other node in the set is independent of X. In this case, a minimal Markov blanket is - * learned, which is to say, a Markov boundary of X.

                - * - *

                Graphically, in a DAG, the Markov blanket of X is the set of parents, children, and - * parents of children of X; GrowShrink will, for a faithful test, learn this set for X. However, a graph over the nodes - * together with X is not learned; other algorithms are available to do that (see, e.g., FgesMb, PcMb).

                - * - *

                We include GrowShrink in our algorithm suite mainly because it is a CMU algorithm - * (see the above reference). Markov blanket search has been explored in some detail in the literature and several - * algorithms are available. See for instance the BNLEARN package in R:

                - * - *

                https://www.bnlearn.com

                - * - *

                This class is not configured to respect knowledge of forbidden and required - * edges.

                + * https://www.bnlearn.com + *

                + * This class is not configured to respect knowledge of forbidden and required edges. * * @author josephramsey * @see FgesMb diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/IcaLingD.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/IcaLingD.java index 39c5ec9db1..4b11055d1a 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/IcaLingD.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/IcaLingD.java @@ -45,50 +45,49 @@ import static org.apache.commons.math3.util.FastMath.*; /** - *

                Implements the ICA-LiNG-D algorithm as well as a number of ancillary methods for - * LiNG-D and LiNGAM. The reference is here:

                - * - *

                Lacerda, G., Spirtes, P. L., Ramsey, J., & Hoyer, P. O. (2012). Discovering - * cyclic causal models by independent components analysis. arXiv preprint arXiv:1206.3273.

                - * - *

                ICA-LING-D is a method for estimating a possible cyclic linear models graph - * from a dataset. It is based on the assumption that the data are generated by a linear model with non-Gaussian noise. - * The method is based on the following assumptions:

                - * + * Implements the ICA-LiNG-D algorithm as well as a number of ancillary methods for LiNG-D and LiNGAM. The reference is + * here: + *

                + * Lacerda, G., Spirtes, P. L., Ramsey, J., & Hoyer, P. O. (2012). Discovering cyclic causal models by independent + * components analysis. arXiv preprint arXiv:1206.3273. + *

                + * ICA-LING-D is a method for estimating a possible cyclic linear models graph from a dataset. It is based on the + * assumption that the data are generated by a linear model with non-Gaussian noise. The method is based on the + * following assumptions: *

                  *
                1. The data are generated by a linear model with non-Gaussian noise.
                2. *
                3. The noise is independent across variables.
                4. *
                5. The noises for all but possibly one variable are non-Gaussian.
                6. *
                7. There is no unobserved confounding.
                8. *
                - * - *

                lower bound of the absolute value of the coefficients in the W matrix.

                - * - *

                Under these assumptions, the method estimates a matrix W such that WX = e, where + *

                + * lower bound of the absolute value of the coefficients in the W matrix. + *

                + * Under these assumptions, the method estimates a matrix W such that WX = e, where * X is the data matrix, e is a matrix of noise, and W is a matrix of coefficients. * The matrix W is then used to estimate a matrix B Hat, where B Hat is the matrix * of coefficients in the linear model that generated the data. The graph is then - * estimated by finding edges in B Hat.

                - * - *

                We use the N Rooks algorithm to find alternative diagonals for + * estimated by finding edges in B Hat. + *

                + * We use the N Rooks algorithm to find alternative diagonals for * permutations of the W matrix. The parameter that N Rooks requires is a * threshold for entries in W to be included in possible diagonals, which * is the lowest number in absolute value that a W matrix entry can take * to be part of a diagonal; the implied permutations is the permutations * that permutes rows so that these combination lies along the their * respective diagonals in W, which are then scaled, and the separate - * satisfactory B Hat matrices reported.

                - * - *

                ICA-LiNG-D, which takes this W as an impute, is a method for estimating + * satisfactory B Hat matrices reported. + *

                + * ICA-LiNG-D, which takes this W as an impute, is a method for estimating * a directed graph (DG) from a dataset. The graph is estimated by finding a * permutation of the columns of the dataset so that the resulting matrix has * a strong diagonal. This permutation is then used to estimate a DG. The method * is an relaxation of LiNGAM, which estimates a DAG from a dataset using * independent components analysis (ICA). LiNG-D is particularly useful when the - * underlying data may have multiple consistent cyclic models.

                - * - *

                This class is not configured to respect knowledge of forbidden and required - * edges.

                + * underlying data may have multiple consistent cyclic models. + *

                + * This class is not configured to respect knowledge of forbidden and required + * edges. * * @author peterspirtes * @author gustavolacerda @@ -196,8 +195,8 @@ public static PermutationMatrixPair hungarianDiagonal(Matrix W) { } /** - * Whether the BHat matrix represents a stable model. - * The eigenvalues are checked to make sure they are all less than 1 in modulus. + * Whether the BHat matrix represents a stable model. The eigenvalues are checked to make sure they are all less + * than 1 in modulus. * * @param bHat The bHat matrix. * @return True iff the model is stable. diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/IcaLingam.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/IcaLingam.java index a7de3704cb..43b21f55dd 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/IcaLingam.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/IcaLingam.java @@ -32,19 +32,18 @@ import static org.apache.commons.math3.util.FastMath.abs; /** - *

                Implements the ICA-LiNGAM algorithm. The reference is here:

                - * - *

                Shimizu, S., Hoyer, P. O., Hyvärinen, A., Kerminen, A., & Jordan, M. (2006). - * A linear non-Gaussian acyclic model for causal discovery. Journal of Machine Learning Research, 7(10).

                - * - *

                The focus for this implementation was to make a version of ICA-LiNGAM that - * would be compatible with LiNG-D (see). There are two parameters, one to choose whether an acyclic result will be - * guaranteed, and another to set a threshold on the lower bound of the absolute value of the coefficients in the B Hat - * matrix. The latter is used to find edges in the final graph.

                - * - *

                ICA-LiNGAM is a method for estimating a causal graph from a dataset. It is based on - * the assumption that the data are generated by a linear model with non-Gaussian noise. The method is based on the - * following assumptions:

                + * Implements the ICA-LiNGAM algorithm. The reference is here: + *

                + * Shimizu, S., Hoyer, P. O., Hyvärinen, A., Kerminen, A., & Jordan, M. (2006). A linear non-Gaussian acyclic model + * for causal discovery. Journal of Machine Learning Research, 7(10). + *

                + * The focus for this implementation was to make a version of ICA-LiNGAM that would be compatible with LiNG-D (see). + * There are two parameters, one to choose whether an acyclic result will be guaranteed, and another to set a threshold + * on the lower bound of the absolute value of the coefficients in the B Hat matrix. The latter is used to find edges in + * the final graph. + *

                + * ICA-LiNGAM is a method for estimating a causal graph from a dataset. It is based on the assumption that the data are + * generated by a linear model with non-Gaussian noise. The method is based on the following assumptions: * *

                  *
                1. The data are generated by a linear model with non-Gaussian noise.
                2. @@ -52,27 +51,27 @@ *
                3. The noises for all but possibly one variable are non-Gaussian.
                4. *
                5. There is no unobserved confounding.
                6. *
                - * - *

                Under these assumptions, the method estimates a matrix W such that WX = e, where + *

                + * Under these assumptions, the method estimates a matrix W such that WX = e, where * X is the data matrix, e is a matrix of noise, and W is a matrix of coefficients. * The matrix W is then used to estimate a matrix B Hat, where B Hat is the matrix * of coefficients in the linear model that generated the data. The graph is then - * estimated by finding edges in B Hat.

                - * - *

                There is an option to guarantee the acyclicity of the output, which will set + * estimated by finding edges in B Hat. + *

                + * There is an option to guarantee the acyclicity of the output, which will set * small coefficients to zero until an acyclic model is achieved. If this option * is not selected, coefficients below the selected threshold will be set to - * zero, which allows for certain cyclic structures to be recovered.

                - * - *

                There are two methods for estimating W. The first is the default method, + * zero, which allows for certain cyclic structures to be recovered. + *

                + * There are two methods for estimating W. The first is the default method, * which is to use the ICA-LiNG-D algorithm to estimate W. The second is to provide * a W matrix estimated by some other method. The latter method is useful for - * comparing the performance of ICA-LiNGAM to other methods.

                - * - *

                There is an option to set a threshold on the coefficients in B Hat. This - * threshold is used to find edges in the final graph.

                - * - *

                The method is implemented as follows:

                + * comparing the performance of ICA-LiNGAM to other methods. + *

                + * There is an option to set a threshold on the coefficients in B Hat. This + * threshold is used to find edges in the final graph. + *

                + * The method is implemented as follows: * *

                  *
                1. Estimate W using LiNG-D or using a user-provided W matrix.
                2. @@ -82,12 +81,12 @@ *
                3. If acyclicity is guaranteed, set small coefficients to zero until an acyclic * model is achieved.
                4. *
                - * - *

                We are using the Hungarian Algorithm to solve the linear assignment problem - * for finding the best diagonal for W.

                - * - *

                This class is not configured to respect knowledge of forbidden and required - * edges.

                + *

                + * We are using the Hungarian Algorithm to solve the linear assignment problem + * for finding the best diagonal for W. + *

                + * This class is not configured to respect knowledge of forbidden and required + * edges. * * @author josephramsey * @see IcaLingD diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/IndTestIod.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/IndTestIod.java index bd5cd3e3e0..eb68e3b77d 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/IndTestIod.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/IndTestIod.java @@ -33,19 +33,18 @@ /** - *

                Checks independence result by listing all tests with those variables, testing each one, and returning the - * resolution of these test results. The reference is here:

                - * - *

                Tillman, R., & Spirtes, P. (2011, June). Learning equivalence classes of acyclic models with latent and selection + * Checks independence result by listing all tests with those variables, testing each one, and returning the resolution + * of these test results. The reference is here: + *

                + * Tillman, R., & Spirtes, P. (2011, June). Learning equivalence classes of acyclic models with latent and selection * variables from multiple datasets with overlapping variables. In Proceedings of the Fourteenth International - * Conference on Artificial Intelligence and Statistics (pp. 3-15). JMLR Workshop and Conference Proceedings.

                - * - *

                The idea of this implementation is that one initializes this test with multiple independence tests (for multiple + * Conference on Artificial Intelligence and Statistics (pp. 3-15). JMLR Workshop and Conference Proceedings. + *

                + * The idea of this implementation is that one initializes this test with multiple independence tests (for multiple * datasets), then a call to the independence check method for X _||_ Y | Z list the independence tests from among - * these, calls each and gets a p-value, then uses a resolution method (such as Fisher's) to resolve these - * p-values.

                - * - *

                Based on work by Rob Tillman, Peter Spirtes, and referencing earlier work by David Danks.

                + * these, calls each and gets a p-value, then uses a resolution method (such as Fisher's) to resolve these p-values. + *

                + * Based on work by Rob Tillman, Peter Spirtes, and referencing earlier work by David Danks. * * @author josephramsey */ diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Lofs.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Lofs.java index 7cee5b015a..9db0a96400 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Lofs.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Lofs.java @@ -41,18 +41,17 @@ import static org.apache.commons.math3.util.FastMath.*; /** - *

                Implements a number of methods which take a fixed graph as input and use linear, - * non-Gaussian methods to orient the edges in the graph. where the acronym stands for linear, non-Gaussian Orientation - * with a Fixed graph Structure (LOFS). The options for different types of scores are given in the enum Lofs.Score. The - * options for rules to use to do the orientations are given in the enum, Lofs.Rule. Most of these are taken from the - * literature and can be googled, though we should certainly give this reference for several of them, to which we are - * indebted:

                - * - *

                Hyvärinen, A., & Smith, S. M. (2013). Pairwise likelihood ratios for estimation - * of non-Gaussian structural equation models. The Journal of Machine Learning Research, 14(1), 111-152.

                - * - *

                This class is configured to respect knowledge of forbidden and required - * edges, including knowledge of temporal tiers.

                + * Implements a number of methods which take a fixed graph as input and use linear, non-Gaussian methods to orient the + * edges in the graph. where the acronym stands for linear, non-Gaussian Orientation with a Fixed graph Structure + * (LOFS). The options for different types of scores are given in the enum Lofs.Score. The options for rules to use to + * do the orientations are given in the enum, Lofs.Rule. Most of these are taken from the literature and can be googled, + * though we should certainly give this reference for several of them, to which we are indebted: + *

                + * Hyvärinen, A., & Smith, S. M. (2013). Pairwise likelihood ratios for estimation of non-Gaussian structural + * equation models. The Journal of Machine Learning Research, 14(1), 111-152. + *

                + * This class is configured to respect knowledge of forbidden and required edges, including knowledge of temporal + * tiers. * * @author josephramsey * @see Score diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Mimbuild.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Mimbuild.java index 69ef425743..92bbe4c78e 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Mimbuild.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Mimbuild.java @@ -42,23 +42,23 @@ import java.util.List; /** - *

                Provides an implementation of Mimbuild, an algorithm that takes a clustering + * Provides an implementation of Mimbuild, an algorithm that takes a clustering * of variables, each of which is explained by a single latent, then forms the implied covariance matrix over the latent - * variables, then runs a CPDAG search to in the structure over the latent themselves.

                + * variables, then runs a CPDAG search to in the structure over the latent themselves. * - *

                Specifically, the search will first infer the covariance matrix over the + * Specifically, the search will first infer the covariance matrix over the * latents and then will use the GRaSP algorithm (see) to infer the structure graph over the latents, using the SEM Bic - * score with the given penalty discount (default 2).

                + * score with the given penalty discount (default 2). * - *

                One may wish to obtain the implied correlation matrix over the latents and + * One may wish to obtain the implied correlation matrix over the latents and * run one's own choice of CPDAG algorithm on it with one's own test or score; a method is available to return this - * covariance matrix.

                + * covariance matrix. * - *

                A suitable clustering for Mimbuild may be obtained using the BPC or FOFC - * algorithm (see).

                + * A suitable clustering for Mimbuild may be obtained using the BPC or FOFC + * algorithm (see). * - *

                This class is configured to respect the knowledge of forbidden and required - * edges, including knowledge of temporal tiers.

                + * This class is configured to respect the knowledge of forbidden and required + * edges, including knowledge of temporal tiers. * * @author josephramsey * @see Bpc diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MimbuildTrek.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MimbuildTrek.java index 44bcbf59a0..91549470d5 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MimbuildTrek.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MimbuildTrek.java @@ -43,9 +43,9 @@ /** * Implements Mimbuild using the theory of treks and ranks. - * - *

                This class is configured to respect knowledge of forbidden and required - * edges, including knowledge of temporal tiers.

                + *

                + * This class is configured to respect knowledge of forbidden and required edges, including knowledge of temporal + * tiers. * * @author adambrodie * @see Knowledge diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Pc.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Pc.java index 0c2c65b4f7..09aa7ca802 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Pc.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Pc.java @@ -37,26 +37,23 @@ import java.util.Set; /** - *

                Implements the Peter/Clark (PC) algorithm, which uses conditional independence testing as an oracle to first of - * all remove extraneous edges from a complete graph, then to orient the unshielded colliders in the graph, and finally - * to make any additional orientations that are capable of avoiding additional unshielded colliders in the graph. An + * Implements the Peter/Clark (PC) algorithm, which uses conditional independence testing as an oracle to first of all + * remove extraneous edges from a complete graph, then to orient the unshielded colliders in the graph, and finally to + * make any additional orientations that are capable of avoiding additional unshielded colliders in the graph. An * version of this algorithm was proposed earlier than this, but the standard reference for the algorithm is in Chapter - * 6 of the following book:

                - * - *

                Spirtes, P., Glymour, C. N., Scheines, R., & Heckerman, D. (2000). Causation, - * prediction, and search. MIT press.

                - * - *

                A modified rule set capable of dealing effectively with knowledge of required - * and forbidden edges is due to Chris Meek, with this reference: - * - *

                Meek, C. (1995), "Causal inference and causal explanation with background - * knowledge."

                - * - *

                See setter methods for "knobs" you can turn to control the output of PC and - * their defaults.

                - * - *

                This class is configured to respect knowledge of forbidden and required - * edges, including knowledge of temporal tiers.

                + * 6 of the following book: + *

                + * Spirtes, P., Glymour, C. N., Scheines, R., & Heckerman, D. (2000). Causation, prediction, and search. MIT press. + *

                + * A modified rule set capable of dealing effectively with knowledge of required and forbidden edges is due to Chris + * Meek, with this reference: + *

                + * Meek, C. (1995), "Causal inference and causal explanation with background knowledge." + *

                + * See setter methods for "knobs" you can turn to control the output of PC and their defaults. + *

                + * This class is configured to respect knowledge of forbidden and required edges, including knowledge of temporal + * tiers. * * @author peterspirtes * @author chrismeek @@ -336,11 +333,11 @@ public void setVerbose(boolean verbose) { } /** - *

                Sets whether the stable adjacency search should be used. Default is false. Default is false. See the - * following reference for this:

                - * - *

                Colombo, D., & Maathuis, M. H. (2014). Order-independent constraint-based causal structure learning. J. Mach. - * Learn. Res., 15(1), 3741-3782.

                + * Sets whether the stable adjacency search should be used. Default is false. Default is false. See the following + * reference for this: + *

                + * Colombo, D., & Maathuis, M. H. (2014). Order-independent constraint-based causal structure learning. J. Mach. + * Learn. Res., 15(1), 3741-3782. * * @param stable True iff the case. */ @@ -360,11 +357,11 @@ public void setConflictRule(PcCommon.ConflictRule conflictRule) { } /** - *

                Sets whether the max-p heuristic should be used for collider discovery. Default is true. See the following - * reference for this:

                - * - *

                Ramsey, J. (2016). Improving accuracy and scalability of the pc algorithm by maximizing p-value. arXiv - * preprint arXiv:1610.00378.

                + * Sets whether the max-p heuristic should be used for collider discovery. Default is true. See the following + * reference for this: + *

                + * Ramsey, J. (2016). Improving accuracy and scalability of the pc algorithm by maximizing p-value. arXiv preprint + * arXiv:1610.00378. * * @param useMaxPHeuristic True, if so. */ diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/PcMb.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/PcMb.java index bd29fbeb07..e1c3ca3158 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/PcMb.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/PcMb.java @@ -32,16 +32,15 @@ import java.util.*; /** - *

                Searches for a CPDAG representing all the Markov blankets for a given target T consistent - * with the given independence information. This CPDAG may be used to generate the actual list of DAG's that might be - * Markov blankets. Note that this code has been converted to be consistent with the CPC algorithm. The reference is - * here:

                - * - *

                Bai, X., Padman, R., Ramsey, J., & Spirtes, P. (2008). Tabu search-enhanced graphical models - * for classification in high dimensions. INFORMS Journal on Computing, 20(3), 423-437.

                - * - *

                This class is configured to respect knowledge of forbidden and required - * edges, including knowledge of temporal tiers.

                + * Searches for a CPDAG representing all the Markov blankets for a given target T consistent with the given independence + * information. This CPDAG may be used to generate the actual list of DAG's that might be Markov blankets. Note that + * this code has been converted to be consistent with the CPC algorithm. The reference is here: + *

                + * Bai, X., Padman, R., Ramsey, J., & Spirtes, P. (2008). Tabu search-enhanced graphical models for classification + * in high dimensions. INFORMS Journal on Computing, 20(3), 423-437. + *

                + * This class is configured to respect knowledge of forbidden and required edges, including knowledge of temporal + * tiers. * * @author josephramsey * @see FgesMb @@ -557,8 +556,8 @@ private void prune(Node node, Graph graph) { } /** - * Tries to remove the edge node---from using adjacent nodes of node 'from.' then tries to remove each other - * edge adjacent node 'from' using remaining edges adjacent node 'from.' If the edge 'node' is removed, the method + * Tries to remove the edge node---from using adjacent nodes of node 'from.' then tries to remove each other edge + * adjacent node 'from' using remaining edges adjacent node 'from.' If the edge 'node' is removed, the method * immediately returns. * * @param node The node about which pruning it to take place. diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Pcd.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Pcd.java index f3fc53ac4e..b96e706cc8 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Pcd.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Pcd.java @@ -39,11 +39,11 @@ import java.util.Set; /** - *

                Modifies the PC algorithm to handle the deterministic case. Edges removals - * or orientations based on conditional independence test involving deterministic relationships are not done.

                - * - *

                This class is configured to respect knowledge of forbidden and required - * edges, including knowledge of temporal tiers.

                + * Modifies the PC algorithm to handle the deterministic case. Edges removals or orientations based on conditional + * independence test involving deterministic relationships are not done. + *

                + * This class is configured to respect knowledge of forbidden and required edges, including knowledge of temporal + * tiers. * * @author peterspirtes * @author josephramsey. diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/PermutationSearch.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/PermutationSearch.java index 48846acf30..ec54d8db43 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/PermutationSearch.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/PermutationSearch.java @@ -11,16 +11,16 @@ import java.util.*; /** - *

                Implements common elements of a permutation search. The specific parts - * for each permutation search are implemented as a SuborderSearch.

                - * - *

                This class specifically handles an optimization for tiered knowledge, whereby - * tiers in the knowledge can be searched one at a time in order from the lowest to highest, taking all variables from - * previous tiers as a fixed for a later tier. This allows these permutation searches to search over many more - * variables than otherwise, so long as tiered knowledge is available to organize the search.

                - * - *

                This class is configured to respect the knowledge of forbidden and required - * edges, including knowledge of temporal tiers.

                + * Implements common elements of a permutation search. The specific parts for each permutation search are implemented as + * a SuborderSearch. + *

                + * This class specifically handles an optimization for tiered knowledge, whereby tiers in the knowledge can be searched + * one at a time in order from the lowest to highest, taking all variables from previous tiers as a fixed for a later + * tier. This allows these permutation searches to search over many more variables than otherwise, so long as tiered + * knowledge is available to organize the search. + *

                + * This class is configured to respect the knowledge of forbidden and required edges, including knowledge of temporal + * tiers. * * @author bryanandrews * @see SuborderSearch @@ -123,7 +123,8 @@ public Graph search() { this.order.add(node); if (!this.knowledge.isTierForbiddenWithin(i)) continue; suborder = this.order.subList(start++, this.order.size()); - this.suborderSearch.searchSuborder(prefix, suborder, this.gsts);; + this.suborderSearch.searchSuborder(prefix, suborder, this.gsts); + ; } if (this.knowledge.isTierForbiddenWithin(i)) continue; diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Rfci.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Rfci.java index de529b3972..4b9697325b 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Rfci.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Rfci.java @@ -34,17 +34,16 @@ /** - *

                Implements the Really Fast Causal Inference (RFCI) algorithm, which aims to - * do a correct inference of inferrable causal structure under the assumption that unmeasured common causes of variables - * in the data may exist. The graph returned is slightly different from the partial ancestral graph (PAG) returned by - * the FCI algorithm. The goal of of the algorithm is to avoid certain expensive steps in the FCI procedure in a correct - * way. This was introduced here:

                - * - *

                Colombo, D., Maathuis, M. H., Kalisch, M., & Richardson, T. S. (2012). Learning - * high-dimensional directed acyclic graphs with latent and selection variables. The Annals of Statistics, 294-321.

                - * - *

                This class is configured to respect knowledge of forbidden and required - * edges, including knowledge of temporal tiers.

                + * Implements the Really Fast Causal Inference (RFCI) algorithm, which aims to do a correct inference of inferrable + * causal structure under the assumption that unmeasured common causes of variables in the data may exist. The graph + * returned is slightly different from the partial ancestral graph (PAG) returned by the FCI algorithm. The goal of of + * the algorithm is to avoid certain expensive steps in the FCI procedure in a correct way. This was introduced here: + *

                + * Colombo, D., Maathuis, M. H., Kalisch, M., & Richardson, T. S. (2012). Learning high-dimensional directed acyclic + * graphs with latent and selection variables. The Annals of Statistics, 294-321. + *

                + * This class is configured to respect knowledge of forbidden and required edges, including knowledge of temporal + * tiers. * * @author Erin Korber, June 2004 * @author Alex Smith, December 2008 diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Sp.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Sp.java index ab1eae7a44..b2a2178065 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Sp.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Sp.java @@ -8,27 +8,27 @@ import java.util.*; /** - *

                Implements the SP (Sparsest Permutation) algorithm. This procedure goes through every - * permutation of the variables (so can be slow for more than 11 variables with no knowledge) looking for a permutation - * such that when a DAG is built it has the fewest number of edges (i.e., is a most 'frugal' or a 'sparsest' DAG). The - * procedure can in principle return all such sparsest permutations and their corresponding DAGs, but in this version it - * return one of them, and converts the result into a CPDAG.

                - * - *

                Note that SP considers all permutations of the algorithm, which is exponential in the - * number of variables. So SP without knowledge is limited to about 10 variables per knowledge tier.

                - * - *

                However, notably, tiered Knowledge can be used with this search. If tiered knowledge - * is used, then the procedure is carried out for each tier separately, given the variable preceding that tier, which - * allows the SP algorithm to address tiered (e.g., time series) problems with more than 11 variables.

                - * - *

                This class is meant to be used in the context of the PermutationSearch class (see). - * the proper use is PermutationSearch search = new PermutationSearch(new Sp(score));

                - * - *

                Raskutti, G., & Uhler, C. (2018). Learning directed acyclic graph models based on - * sparsest permutations. Stat, 7(1), e183.

                - * - *

                This class is configured to respect knowledge of forbidden and required - * edges, including knowledge of temporal tiers.

                + * Implements the SP (Sparsest Permutation) algorithm. This procedure goes through every permutation of the variables + * (so can be slow for more than 11 variables with no knowledge) looking for a permutation such that when a DAG is built + * it has the fewest number of edges (i.e., is a most 'frugal' or a 'sparsest' DAG). The procedure can in principle + * return all such sparsest permutations and their corresponding DAGs, but in this version it return one of them, and + * converts the result into a CPDAG. + *

                + * Note that SP considers all permutations of the algorithm, which is exponential in the number of variables. So SP + * without knowledge is limited to about 10 variables per knowledge tier. + *

                + * However, notably, tiered Knowledge can be used with this search. If tiered knowledge is used, then the procedure is + * carried out for each tier separately, given the variable preceding that tier, which allows the SP algorithm to + * address tiered (e.g., time series) problems with more than 11 variables. + *

                + * This class is meant to be used in the context of the PermutationSearch class (see). the proper use is + * PermutationSearch search = new PermutationSearch(new Sp(score)); + *

                + * Raskutti, G., & Uhler, C. (2018). Learning directed acyclic graph models based on sparsest permutations. Stat, + * 7(1), e183. + *

                + * This class is configured to respect knowledge of forbidden and required edges, including knowledge of temporal + * tiers. * * @author bryanandrews * @author josephramsey diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SpFci.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SpFci.java index bb93f354e3..120f59ffe5 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SpFci.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SpFci.java @@ -39,26 +39,25 @@ import static edu.cmu.tetrad.graph.GraphUtils.gfciExtraEdgeRemovalStep; /** - *

                Uses SP in place of FGES for the initial step in the GFCI algorithm. - * This tends to produce a accurate PAG than GFCI as a result, for the latent variables case. This is a simple - * substitution; the reference for GFCI is here:

                - * - *

                J.M. Ogarrio and P. Spirtes and J. Ramsey, "A Hybrid Causal Search Algorithm - * for Latent Variable Models," JMLR 2016. Here, SP has been substituted for FGES.

                - * - *

                The reference for the SP algorithm is here:

                - * - *

                Raskutti, G., & Uhler, C. (2018). Learning directed acyclic graph models based - * on sparsest permutations. Stat, 7(1), e183.

                - * - *

                For SP only a score is needed, but there are steps in GFCI that require - * a test, so for this method, both a test and a score need to be given.

                - * - *

                Note that SP considers all permutations of the algorithm, which is - * exponential in the number of variables. So SP is limited to about 10 variables.

                - * - *

                This class is configured to respect knowledge of forbidden and required - * edges, including knowledge of temporal tiers.

                + * Uses SP in place of FGES for the initial step in the GFCI algorithm. This tends to produce a accurate PAG than GFCI + * as a result, for the latent variables case. This is a simple substitution; the reference for GFCI is here: + *

                + * J.M. Ogarrio and P. Spirtes and J. Ramsey, "A Hybrid Causal Search Algorithm for Latent Variable Models," JMLR 2016. + * Here, SP has been substituted for FGES. + *

                + * The reference for the SP algorithm is here: + *

                + * Raskutti, G., & Uhler, C. (2018). Learning directed acyclic graph models based on sparsest permutations. Stat, + * 7(1), e183. + *

                + * For SP only a score is needed, but there are steps in GFCI that require a test, so for this method, both a test and a + * score need to be given. + *

                + * Note that SP considers all permutations of the algorithm, which is exponential in the number of variables. So SP is + * limited to about 10 variables. + *

                + * This class is configured to respect knowledge of forbidden and required edges, including knowledge of temporal + * tiers. * * @author josephramsey * @author bryan andrews @@ -74,14 +73,14 @@ public final class SpFci implements IGraphSearch { private final TetradLogger logger = TetradLogger.getInstance(); // The score. private final Score score; + // The conditional independence test. + private final IndependenceTest independenceTest; // The sample size. int sampleSize; // The PAG being constructed. private Graph graph; // The background knowledge. private Knowledge knowledge = new Knowledge(); - // The conditional independence test. - private final IndependenceTest independenceTest; // Flag for complete rule set, true if you should use complete rule set, false otherwise. private boolean completeRuleSetUsed = true; // The maximum length for any discriminating path. -1 if unlimited; otherwise, a positive integer. diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SuborderSearch.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SuborderSearch.java index ca60755df1..4dcef3ddfb 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SuborderSearch.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SuborderSearch.java @@ -15,9 +15,9 @@ * x1a,...,x1n as a prefix. This is used by PermutationSearch to form a complete permutation search algorithm, where * PermutationSearch handles an optimization for tiered knowledge where each tier can be searched separately in order. * (See the documentation for that class.) - * - *

                This class is configured to respect knowledge of forbidden and required - * edges, including knowledge of temporal tiers.

                + *

                + * This class is configured to respect knowledge of forbidden and required edges, including knowledge of temporal + * tiers. * * @author bryanandrews * @see PermutationSearch diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SvarFas.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SvarFas.java index 8e317044c4..a6e0853301 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SvarFas.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SvarFas.java @@ -36,22 +36,21 @@ import java.util.*; /** - *

                Adapts FAS for the time series setting, assuming the data is generated by a - * SVAR (structural vector autoregression). The main difference is that time order is imposed, and if an edge is - * removed, it will also remove all homologous edges to preserve the time-repeating structure assumed by SvarFCI. Based - * on (but not identical to) code by Entner and Hoyer for their 2010 paper. Modified by dmalinsky 4/21/2016.

                - * - *

                The references are as follows:

                - * - *

                Malinsky, D., & Spirtes, P. (2018, August). Causal structure learning from multivariate - * time series in settings with unmeasured confounding. In Proceedings of 2018 ACM SIGKDD workshop on causal discovery - * (pp. 23-47). PMLR.

                - * - *

                Entner, D., & Hoyer, P. O. (2010). On causal discovery from time series data using FCI. Probabilistic - * graphical models, 121-128.

                - * - *

                This class is configured to respect knowledge of forbidden and required - * edges, including knowledge of temporal tiers.

                + * Adapts FAS for the time series setting, assuming the data is generated by a SVAR (structural vector autoregression). + * The main difference is that time order is imposed, and if an edge is removed, it will also remove all homologous + * edges to preserve the time-repeating structure assumed by SvarFCI. Based on (but not identical to) code by Entner and + * Hoyer for their 2010 paper. Modified by dmalinsky 4/21/2016. + *

                + * The references are as follows: + *

                + * Malinsky, D., & Spirtes, P. (2018, August). Causal structure learning from multivariate time series in settings + * with unmeasured confounding. In Proceedings of 2018 ACM SIGKDD workshop on causal discovery (pp. 23-47). PMLR. + *

                + * Entner, D., & Hoyer, P. O. (2010). On causal discovery from time series data using FCI. Probabilistic graphical + * models, 121-128. + *

                + * This class is configured to respect knowledge of forbidden and required edges, including knowledge of temporal + * tiers. * * @author dmalinsky * @see Fas @@ -113,10 +112,10 @@ public SvarFas(IndependenceTest test) { /** * Discovers all adjacencies in data. The procedure is to remove edges in the graph which connect pairs of - * variables which are independent, conditional on some other set of variables in the graph (the "sepset"). These are - * removed in tiers. First, edges which are independent conditional on zero other variables are removed, then edges - * which are independent conditional on one other variable are removed, then two, then three, and so on, until no - * more edges can be removed from the graph. The edges which remain in the graph after this procedure are the + * variables which are independent, conditional on some other set of variables in the graph (the "sepset"). These + * are removed in tiers. First, edges which are independent conditional on zero other variables are removed, then + * edges which are independent conditional on one other variable are removed, then two, then three, and so on, until + * no more edges can be removed from the graph. The edges which remain in the graph after this procedure are the * adjacencies in the data. * * @return a SepSet, which indicates which variables are independent conditional on which other variables diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SvarFci.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SvarFci.java index 22a33d1a72..30a9f28911 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SvarFci.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SvarFci.java @@ -37,26 +37,25 @@ import java.util.Set; /** - *

                Adapts FCI for the time series setting, assuming the data is generated by a - * SVAR (structural vector autoregression). The main difference is that time order is imposed, and if an edge is - * removed, it will also remove all homologous edges to preserve the time-repeating structure assumed by SvarFCI. Based - * on (but not identical to) code by Entner and Hoyer for their 2010 paper. Modified by dmalinsky 4/21/2016.

                - * - *

                This class is based off a copy of FCI.java taken from the repository on 2008/12/16, revision 7306. The extension - * is done by extending doFinalOrientation() with methods for Zhang's rules R5-R10 which implements the augmented - * search. (By a remark of Zhang's, the rule applications can be staged in this way.)

                - * - *

                The references are as follows:

                - * - *

                Malinsky, D., & Spirtes, P. (2018, August). Causal structure learning from multivariate - * time series in settings with unmeasured confounding. In Proceedings of 2018 ACM SIGKDD workshop on causal discovery - * (pp. 23-47). PMLR.

                - * - *

                Entner, D., & Hoyer, P. O. (2010). On causal discovery from time series data using FCI. Probabilistic - * graphical models, 121-128.

                - * - *

                This class is configured to respect knowledge of forbidden and required - * edges, including knowledge of temporal tiers.

                + * Adapts FCI for the time series setting, assuming the data is generated by a SVAR (structural vector autoregression). + * The main difference is that time order is imposed, and if an edge is removed, it will also remove all homologous + * edges to preserve the time-repeating structure assumed by SvarFCI. Based on (but not identical to) code by Entner and + * Hoyer for their 2010 paper. Modified by dmalinsky 4/21/2016. + *

                + * This class is based off a copy of FCI.java taken from the repository on 2008/12/16, revision 7306. The extension is + * done by extending doFinalOrientation() with methods for Zhang's rules R5-R10 which implements the augmented search. + * (By a remark of Zhang's, the rule applications can be staged in this way.) + *

                + * The references are as follows: + *

                + * Malinsky, D., & Spirtes, P. (2018, August). Causal structure learning from multivariate time series in settings + * with unmeasured confounding. In Proceedings of 2018 ACM SIGKDD workshop on causal discovery (pp. 23-47). PMLR. + *

                + * Entner, D., & Hoyer, P. O. (2010). On causal discovery from time series data using FCI. Probabilistic graphical + * models, 121-128. + *

                + * This class is configured to respect knowledge of forbidden and required edges, including knowledge of temporal + * tiers. * * @author danielmalinsky * @see Fci diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SvarFges.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SvarFges.java index 092342ba34..b389ceceb7 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SvarFges.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SvarFges.java @@ -39,22 +39,21 @@ import java.util.concurrent.*; /** - *

                Adapts FGES for the time series setting, assuming the data is generated by a - * SVAR (structural vector autoregression). The main difference is that time order is imposed, and if an edge is - * removed, it will also remove all homologous edges to preserve the time-repeating structure assumed by SvarFCI. Based - * on (but not identical to) code by Entner and Hoyer for their 2010 paper. Modified by dmalinsky 4/21/2016.

                - * - *

                The references are as follows:

                - * - *

                Malinsky, D., & Spirtes, P. (2018, August). Causal structure learning from multivariate - * time series in settings with unmeasured confounding. In Proceedings of 2018 ACM SIGKDD workshop on causal discovery - * (pp. 23-47). PMLR.

                - * - *

                Entner, D., & Hoyer, P. O. (2010). On causal discovery from time series data using FCI. Probabilistic - * graphical models, 121-128.

                - * - *

                This class is configured to respect knowledge of forbidden and required - * edges, including knowledge of temporal tiers.

                + * Adapts FGES for the time series setting, assuming the data is generated by a SVAR (structural vector autoregression). + * The main difference is that time order is imposed, and if an edge is removed, it will also remove all homologous + * edges to preserve the time-repeating structure assumed by SvarFCI. Based on (but not identical to) code by Entner and + * Hoyer for their 2010 paper. Modified by dmalinsky 4/21/2016. + *

                + * The references are as follows: + *

                + * Malinsky, D., & Spirtes, P. (2018, August). Causal structure learning from multivariate time series in settings + * with unmeasured confounding. In Proceedings of 2018 ACM SIGKDD workshop on causal discovery (pp. 23-47). PMLR. + *

                + * Entner, D., & Hoyer, P. O. (2010). On causal discovery from time series data using FCI. Probabilistic graphical + * models, 121-128. + *

                + * This class is configured to respect knowledge of forbidden and required edges, including knowledge of temporal + * tiers. * * @author danielmalinsky * @see Fges @@ -167,8 +166,8 @@ private static Node traverseSemiDirected(Node node, Edge edge) { } /** - * Greedy equivalence search: Start from the empty graph, add edges till the model is significant. Then start deleting - * edges till a minimum is achieved. + * Greedy equivalence search: Start from the empty graph, add edges till the model is significant. Then start + * deleting edges till a minimum is achieved. * * @return the resulting CPDAG. */ diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SvarGfci.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SvarGfci.java index 1d7c36e730..8c6d7383d6 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SvarGfci.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SvarGfci.java @@ -40,22 +40,21 @@ /** - *

                Adapts GFCI for the time series setting, assuming the data is generated by a - * SVAR (structural vector autoregression). The main difference is that time order is imposed, and if an edge is - * removed, it will also remove all homologous edges to preserve the time-repeating structure assumed by SvarFCI. Based - * on (but not identical to) code by Entner and Hoyer for their 2010 paper. Modified by dmalinsky 4/21/2016.

                - * - *

                The references are as follows:

                - * - *

                Malinsky, D., & Spirtes, P. (2018, August). Causal structure learning from multivariate - * time series in settings with unmeasured confounding. In Proceedings of 2018 ACM SIGKDD workshop on causal discovery - * (pp. 23-47). PMLR.

                - * - *

                Entner, D., & Hoyer, P. O. (2010). On causal discovery from time series data using FCI. Probabilistic - * graphical models, 121-128.

                - * - *

                This class is configured to respect knowledge of forbidden and required - * edges, including knowledge of temporal tiers.

                + * Adapts GFCI for the time series setting, assuming the data is generated by a SVAR (structural vector autoregression). + * The main difference is that time order is imposed, and if an edge is removed, it will also remove all homologous + * edges to preserve the time-repeating structure assumed by SvarFCI. Based on (but not identical to) code by Entner and + * Hoyer for their 2010 paper. Modified by dmalinsky 4/21/2016. + *

                + * The references are as follows: + *

                + * Malinsky, D., & Spirtes, P. (2018, August). Causal structure learning from multivariate time series in settings + * with unmeasured confounding. In Proceedings of 2018 ACM SIGKDD workshop on causal discovery (pp. 23-47). PMLR. + *

                + * Entner, D., & Hoyer, P. O. (2010). On causal discovery from time series data using FCI. Probabilistic graphical + * models, 121-128. + *

                + * This class is configured to respect knowledge of forbidden and required edges, including knowledge of temporal + * tiers. * * @author danielmalinsky * @see GFci @@ -66,14 +65,14 @@ public final class SvarGfci implements IGraphSearch { // The logger to use. private final TetradLogger logger = TetradLogger.getInstance(); + // The conditional independence test. + private final IndependenceTest independenceTest; // The covariance matrix being searched over. Assumes continuous data. ICovarianceMatrix covarianceMatrix; // The PAG being constructed. private Graph graph; // The background knowledge. private Knowledge knowledge = new Knowledge(); - // The conditional independence test. - private final IndependenceTest independenceTest; // Flag for the complete rule set, true if one should use the complete rule set, false otherwise. private boolean completeRuleSetUsed; // The maximum length for any discriminating path. -1 if unlimited; otherwise, a positive integer. From 0ec58eece54a7f3f091ab38f4758ed5dbbbc4c85 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Thu, 25 Jan 2024 23:58:33 -0500 Subject: [PATCH 127/163] Cleanup. --- tetrad-lib/src/main/java/edu/cmu/tetrad/search/SvarGfci.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SvarGfci.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SvarGfci.java index 8c6d7383d6..2c3134496e 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SvarGfci.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SvarGfci.java @@ -79,10 +79,9 @@ public final class SvarGfci implements IGraphSearch { private int maxPathLength = -1; // True iff verbose output should be printed. private boolean verbose; - // The score. private Score score; - + // The sepsets. private SepsetProducer sepsets; From b97a5a845e1fb6a2dc1856276100b48b6776ce27 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Fri, 26 Jan 2024 01:47:00 -0500 Subject: [PATCH 128/163] Fixed a bug im the Markov checker where it was failing to test some independencies and dependencies. --- .../edu/cmu/tetrad/search/MarkovCheck.java | 27 +++++++------------ .../tetrad/search/test/IndTestFisherZ.java | 2 +- 2 files changed, 10 insertions(+), 19 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java index ed0516e482..e62a18eaab 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java @@ -212,8 +212,6 @@ public void generateResults() { Node x = nodes.get(i); Node y = nodes.get(j); - if (graph.isAdjacentTo(x, y)) continue; - Set z; switch (setType) { @@ -242,21 +240,14 @@ public void generateResults() { throw new IllegalArgumentException("Unknown separation set type: " + setType); } - List other = new ArrayList<>(graph.getNodes()); - Collections.sort(other); - other.removeAll(z); - - for (Node w : other) { - if (w == x || w == y) continue; - if (z.contains(x) || z.contains(y) || z.contains(w)) continue; + if (x == y || z.contains(x) || z.contains(y)) continue; - if (!(getIndependenceNodes().contains(x) && getIndependenceNodes().contains(y) - && new HashSet<>(getConditioningNodes()).containsAll(z))) { - continue; - } - - allIndependenceFacts.add(new IndependenceFact(x, y, z)); + if (!(getIndependenceNodes().contains(x) && getIndependenceNodes().contains(y) + && new HashSet<>(getConditioningNodes()).containsAll(z))) { + continue; } + + allIndependenceFacts.add(new IndependenceFact(x, y, z)); } } @@ -522,9 +513,9 @@ public Pair, Set> call() { for (Future, Set>> future : theseResults) { try { - Pair, Set> setSetPair = future.get(); - msep.addAll(setSetPair.getFirst()); - mconn.addAll(setSetPair.getSecond()); + Pair, Set> setPair = future.get(); + msep.addAll(setPair.getFirst()); + mconn.addAll(setPair.getSecond()); } catch (InterruptedException | ExecutionException e) { throw new RuntimeException(e); } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java index 821fdef12e..a7b1ccfba4 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java @@ -724,7 +724,7 @@ public List getRows() { */ public void setRows(List rows) { if (dataSet == null) { - throw new IllegalStateException("Cannot set rows without a data set."); + return; } for (Integer row : rows) { From 3d2e1221e61caa9cc911bb2e1e1aac24c92f0295 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Fri, 26 Jan 2024 02:02:43 -0500 Subject: [PATCH 129/163] Cleanup. --- .../java/edu/cmu/tetrad/search/MarkovCheck.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java index e62a18eaab..379507ac66 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java @@ -177,8 +177,8 @@ public List getVariables(List graphNodes, List independenceNod /** * Generates all results, for both the local Markov and local Faithfulness checks, for each node in the graph given * the parents of that node. These results are stored in the resultsIndep and resultsDep lists. This should be - * called before any of the result methods. Note that only results for X _||_ Y | Z1,..,Zn are generated, where X - * and Y are in the independenceNodes list and Z1,..,Zn are in the conditioningNodes list. + * called before any of the result methods. Note that only results for X _||_ Y | Z1,...,Zn are generated, where X + * and Y are in the independenceNodes list and Z1,...,Zn are in the conditioningNodes list. * * @see #getResults(boolean) */ @@ -744,8 +744,8 @@ public Knowledge getKnowledge() { /** * Sets the knowledge object for the Markov checker. The knowledge object should contain the tier knowledge for the - * Markov checker. The last tier contains the possible X and Y for X _||_ Y | Z1,..,Zn, and the previous tiers - * contain the possible Z1,..,Zn for X _||_ Y | Z1,..,Zn. Additional forbidden or required edges are ignored. + * Markov checker. The last tier contains the possible X and Y for X _||_ Y | Z1,...,Zn, and the previous tiers + * contain the possible Z1,...,Zn for X _||_ Y | Z1,...,Zn. Additional forbidden or required edges are ignored. * * @param knowledge The knowledge object. */ @@ -797,18 +797,18 @@ public void setKnowledge(Knowledge knowledge) { } /** - * Returns the nodes that are possible X and Y for X _||_ Y | Z1,..,Zn. + * Returns the nodes that are possible X and Y for X _||_ Y | Z1,...,Zn. * - * @return The nodes that are possible X and Y for X _||_ Y | Z1,..,Zn. + * @return The nodes that are possible X and Y for X _||_ Y | Z1,...,Zn. */ public List getIndependenceNodes() { return independenceNodes; } /** - * Returns the nodes that are possible Z1,..,Zn for X _||_ Y | Z1,..,Zn. + * Returns the nodes that are possible Z1,...,Zn for X _||_ Y | Z1,...,Zn. * - * @return The nodes that are possible Z1,..,Zn for X _||_ Y | Z1,..,Zn. + * @return The nodes that are possible Z1,...,Zn for X _||_ Y | Z1,...,Zn. */ public List getConditioningNodes() { return conditioningNodes; From 264f094f55f97d763c2bcf2332be61e0276ea678 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Fri, 26 Jan 2024 09:40:57 -0500 Subject: [PATCH 130/163] Cleanup. --- .../cmu/tetradapp/util/WatchedProcess.java | 41 +++++++++---------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java index bb8d1d0ac0..d21377fced 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java @@ -13,9 +13,9 @@ * Runs a long process, watching it with a thread and popping up a Stop button that the user can click to stop the * process. *

                - * Replacement for the old WatchedProcess, which called the deprecated Thread.stop() method. This method is - * deprecated because it can leave the program in an inconsistent state. This class uses Thread.interrupt() instead, - * which is the recommended way to stop a thread. + * Replacement for the old WatchedProcess, which called the deprecated Thread.stop() method. This method is deprecated + * because it can leave the program in an inconsistent state. This class uses Thread.interrupt() instead, which is the + * recommended way to stop a thread. *

                * Example usage: *

                @@ -48,16 +48,26 @@ public WatchedProcess() {
                         frame = Tetrad.frame;
                 
                         if (frame == null) {
                -            // Create a hidden frame
                -            frame = new JFrame("Hidden Frame");
                -            frame.setUndecorated(true);
                -            frame.setSize(0, 0);
                -            frame.setVisible(true);
                +            throw new RuntimeException("Tetrad frame is null. Cannot create WatchedProcess.");
                +//            frame = new JFrame("Hidden Frame");
                +//            frame.setUndecorated(true);
                +//            frame.setSize(0, 0);
                         }
                 
                         startLongRunningThread();
                     }
                 
                +    private static void positionDialogAboveFrameCenter(JFrame frame, JDialog dialog) {
                +        // Calculate the new position for the dialog
                +        Point newDialogPosition = new Point(
                +                frame.getX() + frame.getWidth() / 2 - dialog.getWidth() / 2, // Centered horizontally
                +                frame.getY() + frame.getHeight() / 2 - dialog.getHeight() / 2 // Centered vertically
                +        );
                +
                +        // Set the dialog's new position
                +        dialog.setLocation(newDialogPosition);
                +    }
                +
                     /**
                      * This is the method that will be called in a separate thread. It should be a long-running process that can be
                      * interrupted by the user.
                @@ -127,19 +137,8 @@ public void componentMoved(ComponentEvent e) {
                         panel.add(stopButton);
                 
                         dialog.getContentPane().add(panel);
                -
                -        dialog.setLocationRelativeTo(frame);
                +//        dialog.setLocationRelativeTo(frame);
                +        positionDialogAboveFrameCenter(frame, dialog);
                         dialog.setVisible(true);
                     }
                -
                -    private static void positionDialogAboveFrameCenter(JFrame frame, JDialog dialog) {
                -        // Calculate the new position for the dialog
                -        Point newDialogPosition = new Point(
                -                frame.getX() + frame.getWidth() / 2 - dialog.getWidth() / 2, // Centered horizontally
                -                frame.getY() + frame.getHeight() / 2 - dialog.getHeight() / 2 // Centered vertically
                -        );
                -
                -        // Set the dialog's new position
                -        dialog.setLocation(newDialogPosition);
                -    }
                 }
                
                From edfc74c4356db7d9210f6488bb3fb9f8276a7234 Mon Sep 17 00:00:00 2001
                From: jdramsey 
                Date: Fri, 26 Jan 2024 09:44:34 -0500
                Subject: [PATCH 131/163] Cleanup.
                
                ---
                 .../main/java/edu/cmu/tetradapp/Tetrad.java   | 46 +++++++++----------
                 .../cmu/tetradapp/util/WatchedProcess.java    |  6 +--
                 2 files changed, 23 insertions(+), 29 deletions(-)
                
                diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/Tetrad.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/Tetrad.java
                index af6ad34134..a7dda0e129 100644
                --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/Tetrad.java
                +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/Tetrad.java
                @@ -50,30 +50,29 @@
                  */
                 public final class Tetrad implements PropertyChangeListener {
                 
                +    // The experimental option
                     private static final String EXP_OPT = "--experimental";
                +    // Whether to enable experimental features
                     public static boolean enableExperimental;
                -    /**
                -     * The main application title.
                -     */
                +    // The main application title.
                     private final String mainTitle
                             = "Tetrad " + Version.currentViewableVersion();
                -    /**
                -     * The launch frame.
                -     */
                +    // The launch frame.
                     public static JFrame frame;
                -    /**
                -     * The desktop placed into the launch frame.
                -     */
                +    // The desktop placed into the launch frame.
                     private TetradDesktop desktop;
                 
                     //==============================CONSTRUCTORS===========================//
                +
                +    /**
                +     * Constructs a new Tetrad instance.
                +     */
                     public Tetrad() {
                     }
                 
                     //==============================PUBLIC METHODS=========================//
                 
                     /**
                -     * 

                * Launches Tetrad as an application. One way to launch Tetrad IV as an application is the following:> 0 *

                java -cp jarname.jar INSTANCE.Tetrad
                *

                @@ -103,6 +102,18 @@ public static void main(String[] argv) { Tetrad.enableExperimental = Preferences.userRoot().getBoolean("enableExperimental", false); } + /** + * Responds to "exitProgram" property change events by disposing of the Tetrad IV frame and exiting if possible. + * + * @param e the property change event + */ + @Override + public void propertyChange(PropertyChangeEvent e) { + if ("exitProgram".equals(e.getPropertyName())) { + exitApplication(); + } + } + //===============================PRIVATE METHODS=======================// private static void setLookAndFeel() { try { @@ -116,17 +127,6 @@ private static void setLookAndFeel() { } } - /** - * Responds to "exitProgram" property change events by disposing of the Tetrad IV frame and exiting if possible. - * - * @param e the property change event - */ - @Override - public void propertyChange(PropertyChangeEvent e) { - if ("exitProgram".equals(e.getPropertyName())) { - exitApplication(); - } - } /** * Launches the frame. (This is left as a separate method in case we ever want to launch it as an applet.) @@ -209,9 +209,7 @@ public void windowClosing(WindowEvent e) { } } - /** - * Exits the application gracefully. - */ + // Exits the application gracefully. private void exitApplication() { boolean succeeded = getDesktop().closeAllSessions(); diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java index d21377fced..448d714c04 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java @@ -43,15 +43,11 @@ public abstract class WatchedProcess { */ public WatchedProcess() { - // The frame is used to center the dialog on the screen. Use the Tetrad frame if it exists, otherwise create a - // hidden frame. + // Get the Tetrad frame. frame = Tetrad.frame; if (frame == null) { throw new RuntimeException("Tetrad frame is null. Cannot create WatchedProcess."); -// frame = new JFrame("Hidden Frame"); -// frame.setUndecorated(true); -// frame.setSize(0, 0); } startLongRunningThread(); From 4570252f1a4daf791682beac79993210ef3aa402 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Fri, 26 Jan 2024 09:49:22 -0500 Subject: [PATCH 132/163] Cleanup. --- tetrad-gui/src/main/java/edu/cmu/tetradapp/Tetrad.java | 4 +--- .../src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/Tetrad.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/Tetrad.java index a7dda0e129..c04d1a5efa 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/Tetrad.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/Tetrad.java @@ -128,9 +128,7 @@ private static void setLookAndFeel() { } - /** - * Launches the frame. (This is left as a separate method in case we ever want to launch it as an applet.) - */ + // Launches the frame. (This is left as a separate method in case we ever want to launch it as an applet.) private void launchFrame() { System.setProperty("java.util.Arrays.useLegacyMergeSort", "true"); diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java index 448d714c04..d68a810bae 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java @@ -34,7 +34,7 @@ * @author ChatGPT */ public abstract class WatchedProcess { - private JFrame frame; + private final JFrame frame; private Thread longRunningThread; private JDialog dialog; From aac588d0c9e7d02bc3de4e1c6ac4fd5fd48532f4 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Fri, 26 Jan 2024 10:11:12 -0500 Subject: [PATCH 133/163] Resolved a problem with WatchedProcess sometimes hanging when the dialog was set to visible. --- .../main/java/edu/cmu/tetradapp/util/WatchedProcess.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java index d68a810bae..0608028aee 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java @@ -133,8 +133,12 @@ public void componentMoved(ComponentEvent e) { panel.add(stopButton); dialog.getContentPane().add(panel); -// dialog.setLocationRelativeTo(frame); positionDialogAboveFrameCenter(frame, dialog); - dialog.setVisible(true); + + SwingUtilities.invokeLater(new Runnable() { + public void run() { + dialog.setVisible(true); + } + }); } } From 5b8d72bd0e5fa00b672b9502bb815a0d0fff2c4f Mon Sep 17 00:00:00 2001 From: jdramsey Date: Fri, 26 Jan 2024 10:11:53 -0500 Subject: [PATCH 134/163] Resolved a problem with WatchedProcess sometimes hanging when the dialog was set to visible. --- .../main/java/edu/cmu/tetradapp/util/WatchedProcess.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java index 0608028aee..c4d1b6a207 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java @@ -135,10 +135,6 @@ public void componentMoved(ComponentEvent e) { dialog.getContentPane().add(panel); positionDialogAboveFrameCenter(frame, dialog); - SwingUtilities.invokeLater(new Runnable() { - public void run() { - dialog.setVisible(true); - } - }); + SwingUtilities.invokeLater(() -> dialog.setVisible(true)); } } From dc23ad097957bac23f822726090475e1b543a23b Mon Sep 17 00:00:00 2001 From: jdramsey Date: Sat, 27 Jan 2024 06:41:54 -0500 Subject: [PATCH 135/163] Resolved a problem with WatchedProcess sometimes hanging when the dialog was set to visible. --- INSTALL_APPLICATION.md | 2 +- README.md | 6 ++---- .../java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java | 8 ++++---- .../src/main/java/edu/cmu/tetrad/search/MarkovCheck.java | 2 +- .../main/java/edu/cmu/tetrad/search/score/GicScores.java | 1 + 5 files changed, 9 insertions(+), 10 deletions(-) diff --git a/INSTALL_APPLICATION.md b/INSTALL_APPLICATION.md index 7db8efcdf6..3158b22fd5 100644 --- a/INSTALL_APPLICATION.md +++ b/INSTALL_APPLICATION.md @@ -6,7 +6,7 @@ Please use a recent Java JDK. See [Setting up Java for Tetrad](https://github.co To download the Tetrad jar, please click the following link (which will always be updated to the latest version): -https://s01.oss.sonatype.org/content/repositories/releases/io/github/cmu-phil/tetrad-gui/7.6.1/tetrad-gui-7.6.1-launch.jar +https://s01.oss.sonatype.org/content/repositories/releases/io/github/cmu-phil/tetrad-gui/7.6.0/tetrad-gui-7.6.0-launch.jar You may be able to launch this jar by double-clicking the jar file name. However, on a Mac, this presents some security challenges. On all platforms, the jar may be launched at the command line (with a specification of the amount of RAM you will allow it to use) using this command: diff --git a/README.md b/README.md index e335ed5514..96f161e71a 100644 --- a/README.md +++ b/README.md @@ -2,19 +2,17 @@ Please visit our [Tetrad web page](https://sites.google.com/view/tetradcausal) for current links, a list of contributors, some history, documentation, descriptions, links for our various projects, Javadocs, and more. -Note: Starting 1/14/2024, the Tetrad codebase will target language level 17, and all jars will be compiled using Corretto's JDK 17. - ## Tetrad Application See out insructions for [Installing the Tetrad Application](https://github.com/cmu-phil/tetrad/blob/development/INSTALL_APPLICATION.md). ## Tetrad in Python -We have a project, [py-tetrad](https://github.com/cmu-phil/py-tetrad), that allows you to incorporate arbitrary Tetrad code into a Python workflow. It's new, and the installation is still nonstandard, but it had a good response. This requires Python 3.5+. and Java JDK 17+. +We have a project, [py-tetrad](https://github.com/cmu-phil/py-tetrad), that allows you to incorporate arbitrary Tetrad code into a Python workflow. It's new, and the installation is still nonstandard, but it had a good response. This requires Python 3.5+. and Java JDK 9+. ## Tetrad in R -We also have a project, [rpy-tetrad](https://github.com/cmu-phil/py-tetrad/tree/main/pytetrad/R), that allows you to incorporate _some_ Tetrad functionality in R. It's also new, and the installation for it is also still nonstandard, but has gotten good feedback. This requires Python 3.5+ and Java JDK 17+. +We also have a project, [rpy-tetrad](https://github.com/cmu-phil/py-tetrad/tree/main/pytetrad/R), that allows you to incorporate _some_ Tetrad functionality in R. It's also new, and the installation for it is also still nonstandard, but has gotten good feedback. This requires Python 3.5+ and Java JDK 9+. Please see our [description](https://sites.google.com/view/tetradcausal/tetrad-in-r?authuser=0). diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java index f36ddbf623..49e64d6dce 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java @@ -881,13 +881,13 @@ private void setLabelTexts() { ? "-" : NumberFormatUtil.getInstance().getNumberFormat().format(model.getMarkovCheck().getAndersonDarlingP(false))))); binomialPLabelIndep.setText("P-value of Binomial Test = " - + ((Double.isNaN(model.getMarkovCheck().getBinomialPValue(true)) + + ((Double.isNaN(model.getMarkovCheck().getBinomialP(true)) ? "-" - : NumberFormatUtil.getInstance().getNumberFormat().format(model.getMarkovCheck().getBinomialPValue(true))))); + : NumberFormatUtil.getInstance().getNumberFormat().format(model.getMarkovCheck().getBinomialP(true))))); binomialPLabelDep.setText("P-value of Binomial Test = " - + ((Double.isNaN(model.getMarkovCheck().getBinomialPValue(false)) + + ((Double.isNaN(model.getMarkovCheck().getBinomialP(false)) ? "-" - : NumberFormatUtil.getInstance().getNumberFormat().format(model.getMarkovCheck().getBinomialPValue(false))))); + : NumberFormatUtil.getInstance().getNumberFormat().format(model.getMarkovCheck().getBinomialP(false))))); fractionDepLabelIndep.setText("% dependent = " + ((Double.isNaN(model.getMarkovCheck().getFractionDependent(true)) ? "-" diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java index 379507ac66..f5427cad65 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MarkovCheck.java @@ -399,7 +399,7 @@ public double getAndersonDarlingP(boolean indep) { * @param indep True if for implied independencies, false if for implied dependencies. * @return The Binomial p-value for the given list of results. */ - public double getBinomialPValue(boolean indep) { + public double getBinomialP(boolean indep) { if (indep) { return binomialPIndep; } else { diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/GicScores.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/GicScores.java index fc363f9c7b..e81c7c61d7 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/GicScores.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/GicScores.java @@ -66,6 +66,7 @@ public class GicScores implements Score { private boolean calculateRowSubsets = false; // private boolean calculateSquareEuclideanNorms = false; private double penaltyDiscount = 1; + // True if the pseudo-inverse should be used. private boolean usePseudoInverse = false; /** From 01fe5109ee882701169152f4d073f0b921389d1d Mon Sep 17 00:00:00 2001 From: jdramsey Date: Sat, 27 Jan 2024 07:13:25 -0500 Subject: [PATCH 136/163] Fixing some UI issues for Markov checker. --- .../tetradapp/editor/MarkovCheckEditor.java | 60 ++++++++++--------- 1 file changed, 33 insertions(+), 27 deletions(-) diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java index 49e64d6dce..d1f067aef8 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java @@ -77,6 +77,7 @@ public class MarkovCheckEditor extends JPanel { private final JLabel testLabel = new JLabel("(Unspecified Test)"); private final JLabel conditioningLabelDep = new JLabel("(Unspecified)"); private final JLabel conditioningLabelIndep = new JLabel("(Unspecified)"); + private DoubleTextField percent = null; boolean updatingTestModels = true; private AbstractTableModel tableModelIndep; private AbstractTableModel tableModelDep; @@ -235,22 +236,25 @@ public void watch() { box1.add(indTestJComboBox); JButton params = new JButton("Params"); box1.add(params); - JButton refresh = new JButton("Refresh"); - box1.add(refresh); - DoubleTextField percent = new DoubleTextField(0.5, 4, new DecimalFormat("0.0")); - box1.add(new JLabel("% Sample:")); - box1.add(percent); - box1.add(Box.createHorizontalGlue()); + JButton recalculate = new JButton("Recalculate"); + box1.add(recalculate); - refresh.addActionListener(e -> refreshResult(model, percent)); + if (!(model.getMarkovCheck().getIndependenceTest().getData() instanceof CovarianceMatrix)) { + this.percent = new DoubleTextField(0.5, 4, new DecimalFormat("0.0###")); + box1.add(new JLabel("% Sample:")); + box1.add(percent); + box1.add(Box.createHorizontalGlue()); - percent.setFilter((value, oldValue) -> { - if (value < 0.0 || value > 1.0) { - return oldValue; - } else { - return value; - } - }); + recalculate.addActionListener(e -> refreshResult(model, percent)); + + percent.setFilter((value, oldValue) -> { + if (value < 0.0 || value > 1.0) { + return oldValue; + } else { + return value; + } + }); + } setLabelTexts(); @@ -316,24 +320,24 @@ public void watch() { @NotNull public static String getHelpMessage() { return """ - This tool lets you plot statistics for independence tests of a pair of variables given some conditioning calculated for one of those variables, for a given graph and dataset. Two tables are made, one in which the independence facts predicted by the graph using these conditioning sets are tested in the data and the other in which the graph's predicted dependence facts are tested. The first of these sets is a check for "Markov" (a check for implied independence facts) for the chosen conditioning sets; the is a check of the "Dependent Distribution." (a check of implied dependence facts)” + This tool lets you plot statistics for independence tests of a pair of variables given some conditioning calculated for one of those variables, for a given graph and dataset. Two tables are made, one in which the independence facts predicted by the graph using these conditioning sets are tested in the data and the other in which the graph's predicted dependence facts are tested. The first of these sets is a check for "Markov" (a check for implied independence facts) for the chosen conditioning sets; the is a check of the "Dependent Distribution." (a check of implied dependence facts)” - Each table gives columns for the independence fact being checked, its test result, and its statistic. This statistic is either a p-value, ranging from 0 to 1, where p-values above the alpha level of the test are judged as independent, or a score bump, where this bump is negative for independent judgments and positive for dependent judgments. + Each table gives columns for the independence fact being checked, its test result, and its statistic. This statistic is either a p-value, ranging from 0 to 1, where p-values above the alpha level of the test are judged as independent, or a score bump, where this bump is negative for independent judgments and positive for dependent judgments. - If the independence test yields a p-value, as for instance, for the Fisher Z test (for the linear, Gaussian case) or else the Chi-Square test (for the multinomial case), then under the null hypothesis of independence and for a consistent test, these p-values should be distributed as Uniform(0, 1). That is, it should be just as likely to see p-values in any range of equal width. If the test is inconsistent or the graph is incorrect (i.e., the parents of some or all of the nodes in the graph are incorrect), then this distribution of p-values will not be Uniform. To visualize this, we display the histogram of the p-values with equally sized bins; the bars in this histogram, for this case, should ideally all be of equal height. + If the independence test yields a p-value, as for instance, for the Fisher Z test (for the linear, Gaussian case) or else the Chi-Square test (for the multinomial case), then under the null hypothesis of independence and for a consistent test, these p-values should be distributed as Uniform(0, 1). That is, it should be just as likely to see p-values in any range of equal width. If the test is inconsistent or the graph is incorrect (i.e., the parents of some or all of the nodes in the graph are incorrect), then this distribution of p-values will not be Uniform. To visualize this, we display the histogram of the p-values with equally sized bins; the bars in this histogram, for this case, should ideally all be of equal height. - If the first bar in this histogram is especially high (for the p-value case), that means that many tests are being judged as dependent. For checking the dependent distribution, one hopes that this list is non-empty, in which case this first bar will be especially high since high p-values are examples where the graph is unfaithful to the distribution. These are possibly for cases where paths in the graph cancel unfaithfully. But for checking Markov, one hopes that this first bar will be the same height as all of the other bars. + If the first bar in this histogram is especially high (for the p-value case), that means that many tests are being judged as dependent. For checking the dependent distribution, one hopes that this list is non-empty, in which case this first bar will be especially high since high p-values are examples where the graph is unfaithful to the distribution. These are possibly for cases where paths in the graph cancel unfaithfully. But for checking Markov, one hopes that this first bar will be the same height as all of the other bars. - To make it especially clear, we give two statistics in the interface. The first is the percentage of p-values judged dependent on the test. If an alpha level is used in the test, this number should be very close to the alpha level for the Local Markov check since the distribution of p-values under this condition is Uniform. For the second, we test the Uniformity of the p-values using a Kolmogorov-Smirnov test. The p-value returned by this test should be greater than the user’s preferred alpha level if the distribution of p-values is Uniform and less than this alpha level if the distribution of p-values is non-uniform. + To make it especially clear, we give two statistics in the interface. The first is the percentage of p-values judged dependent on the test. If an alpha level is used in the test, this number should be very close to the alpha level for the Local Markov check since the distribution of p-values under this condition is Uniform. For the second, we test the Uniformity of the p-values using a Kolmogorov-Smirnov test. The p-value returned by this test should be greater than the user’s preferred alpha level if the distribution of p-values is Uniform and less than this alpha level if the distribution of p-values is non-uniform. - If the independence test yields a bump in the score, this score should be negative for independence judgments and positive for dependence judgments. The histogram will reflect this. + If the independence test yields a bump in the score, this score should be negative for independence judgments and positive for dependence judgments. The histogram will reflect this. - Feel free to select all of the data in the tables, copy it, and paste it into a text file or into Excel. This will let you analyze the data yourself. + Feel free to select all of the data in the tables, copy it, and paste it into a text file or into Excel. This will let you analyze the data yourself. - A note about Markov Blankets: The "Markov Blanket" conditioning set choice implements the Markov blanket calculation in a way that is correct for DAGs, CPDAGs, MAGs, and PAGs. For all of these graph types, the list of m-connecting facts in the Faithfulness tab should be empty, since the Markov blanket should screen off the target from any other variables in the dataset. It's possible that for some other graph types, this list may not be empty (i.e., the Markov blanket calculation may not be correct). - - Knowledge may be supplied to the Markov Checker. This will be interpreted as follows. For X _||_ Y | Z checked, X and Y will be drawn from the last tier of the knowledge, and the variables in Z will be drawn from all variables in tiers. Additional forbidden or required edges are not allowed. - """; + A note about Markov Blankets: The "Markov Blanket" conditioning set choice implements the Markov blanket calculation in a way that is correct for DAGs, CPDAGs, MAGs, and PAGs. For all of these graph types, the list of m-connecting facts in the Faithfulness tab should be empty, since the Markov blanket should screen off the target from any other variables in the dataset. It's possible that for some other graph types, this list may not be empty (i.e., the Markov blanket calculation may not be correct). + + Knowledge may be supplied to the Markov Checker. This will be interpreted as follows. For X _||_ Y | Z checked, X and Y will be drawn from the last tier of the knowledge, and the variables in Z will be drawn from all variables in tiers. Additional forbidden or required edges are not allowed. + """; } @NotNull @@ -359,11 +363,13 @@ private static HistogramPanel getHistogramPanel(List results private void refreshResult(MarkovCheckIndTestModel model, DoubleTextField percent) { setTest(); - model.getMarkovCheck().setPercentResample(percent.getValue()); + + if (percent != null) { + model.getMarkovCheck().setPercentResample(percent.getValue()); + } model.getMarkovCheck().generateResults(); tableModelIndep.fireTableDataChanged(); tableModelDep.fireTableDataChanged(); - histogramPanelDep.removeAll(); histogramPanelIndep.removeAll(); histogramPanelDep.add(createHistogramPanel(false), BorderLayout.CENTER); histogramPanelIndep.add(createHistogramPanel(true), BorderLayout.CENTER); From 8e8ca6a7d4ff6d69ab0aae29756f19ca877ee973 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Sat, 27 Jan 2024 09:45:18 -0500 Subject: [PATCH 137/163] Still working on issues where the WatchedProcess dialog was hanging--I think I've solved that now. Also, starting to look at cases where clicking the stop button doesn't stop the algorithm--I just fixed for BOSS but I'll need to go through all the other algorithms. Also trying another way to handle covariance matrices for the MarkovCheckEditor, which seems to be working better. --- .../tetradapp/editor/MarkovCheckEditor.java | 34 ++++++++++--------- .../cmu/tetradapp/util/WatchedProcess.java | 31 +++++++---------- .../main/java/edu/cmu/tetrad/search/Boss.java | 2 ++ 3 files changed, 32 insertions(+), 35 deletions(-) diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java index d1f067aef8..4f831e93b3 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java @@ -77,8 +77,8 @@ public class MarkovCheckEditor extends JPanel { private final JLabel testLabel = new JLabel("(Unspecified Test)"); private final JLabel conditioningLabelDep = new JLabel("(Unspecified)"); private final JLabel conditioningLabelIndep = new JLabel("(Unspecified)"); - private DoubleTextField percent = null; boolean updatingTestModels = true; + private final DoubleTextField percent; private AbstractTableModel tableModelIndep; private AbstractTableModel tableModelDep; private JLabel fractionDepLabelIndep; @@ -239,22 +239,26 @@ public void watch() { JButton recalculate = new JButton("Recalculate"); box1.add(recalculate); - if (!(model.getMarkovCheck().getIndependenceTest().getData() instanceof CovarianceMatrix)) { - this.percent = new DoubleTextField(0.5, 4, new DecimalFormat("0.0###")); + this.percent = new DoubleTextField(0.5, 4, new DecimalFormat("0.0###")); + + if (model.getMarkovCheck().getIndependenceTest().getData() != null) { box1.add(new JLabel("% Sample:")); box1.add(percent); - box1.add(Box.createHorizontalGlue()); + } else { + box1.add(new JLabel("(Not tabular data)")); + } - recalculate.addActionListener(e -> refreshResult(model, percent)); + box1.add(Box.createHorizontalGlue()); - percent.setFilter((value, oldValue) -> { - if (value < 0.0 || value > 1.0) { - return oldValue; - } else { - return value; - } - }); - } + recalculate.addActionListener(e -> refreshResult(model, percent)); + + percent.setFilter((value, oldValue) -> { + if (value < 0.0 || value > 1.0) { + return oldValue; + } else { + return value; + } + }); setLabelTexts(); @@ -364,9 +368,7 @@ private static HistogramPanel getHistogramPanel(List results private void refreshResult(MarkovCheckIndTestModel model, DoubleTextField percent) { setTest(); - if (percent != null) { - model.getMarkovCheck().setPercentResample(percent.getValue()); - } + model.getMarkovCheck().setPercentResample(percent.getValue()); model.getMarkovCheck().generateResults(); tableModelIndep.fireTableDataChanged(); tableModelDep.fireTableDataChanged(); diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java index c4d1b6a207..e5fccb5d12 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/WatchedProcess.java @@ -53,7 +53,7 @@ public WatchedProcess() { startLongRunningThread(); } - private static void positionDialogAboveFrameCenter(JFrame frame, JDialog dialog) { + private void positionDialogAboveFrameCenter(JFrame frame, JDialog dialog) { // Calculate the new position for the dialog Point newDialogPosition = new Point( frame.getX() + frame.getWidth() / 2 - dialog.getWidth() / 2, // Centered horizontally @@ -74,33 +74,21 @@ private static void positionDialogAboveFrameCenter(JFrame frame, JDialog dialog) private void startLongRunningThread() { longRunningThread = new Thread(() -> { - if (Thread.interrupted()) { - // The Thread was interrupted, so exit the loop and terminate - System.out.println("Thread was interrupted. Stopping..."); - return; - } - try { watch(); } catch (InterruptedException e) { TetradLogger.getInstance().forceLogMessage("Thread was interrupted while watching. Stopping..."); - return; + } catch (Exception e) { + TetradLogger.getInstance().forceLogMessage("Exception while watching: " + e.getMessage()); } if (dialog != null) { - dialog.dispose(); - dialog = null; + SwingUtilities.invokeLater(() -> dialog.dispose()); } }); - longRunningThread.start(); showStopDialog(); - } - - private void stopLongRunningThread() { - if (longRunningThread != null && longRunningThread.isAlive()) { - longRunningThread.interrupt(); - } + longRunningThread.start(); } private void showStopDialog() { @@ -123,8 +111,13 @@ public void componentMoved(ComponentEvent e) { JButton stopButton = new JButton("Processing (click to stop)..."); stopButton.addActionListener(e -> { - stopLongRunningThread(); - dialog.dispose(); + if (longRunningThread != null) { + SwingUtilities.invokeLater(() -> longRunningThread.interrupt()); + } + + if (dialog != null) { + SwingUtilities.invokeLater(() -> dialog.dispose()); + } }); JPanel panel = new JPanel(); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Boss.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Boss.java index 50a3acbed4..1611b05b9a 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Boss.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Boss.java @@ -333,6 +333,8 @@ private boolean betterMutation(List prefix, List suborder, Node x) { int curr = 0; while (itr.hasNext()) { + if (Thread.currentThread().isInterrupted()) return false; + Node z = itr.next(); if (this.knowledge.isRequired(x.getName(), z.getName())) { From 4e8db6e18514e6258174f92cc048c2af053812d0 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Sun, 28 Jan 2024 23:40:21 -0500 Subject: [PATCH 138/163] Trying to fix some issues in the MarkovCheckEditor, but I can't it to resize properly in Swing if the user make it bigger. I did though get GRaSP to stop the thread when the stop butto is pushed. --- .../cmu/tetradapp/editor/HistogramPanel.java | 36 +-- .../tetradapp/editor/MarkovCheckEditor.java | 292 ++++++++---------- .../java/edu/cmu/tetrad/search/Grasp.java | 3 + 3 files changed, 131 insertions(+), 200 deletions(-) diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/HistogramPanel.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/HistogramPanel.java index cc5fc797b9..131012869d 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/HistogramPanel.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/HistogramPanel.java @@ -22,15 +22,11 @@ package edu.cmu.tetradapp.editor; import edu.cmu.tetrad.data.Histogram; -import edu.cmu.tetrad.graph.Node; import org.apache.commons.math3.util.FastMath; import javax.swing.*; import java.awt.*; import java.awt.event.MouseEvent; -import java.text.DecimalFormat; -import java.text.NumberFormat; -import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; @@ -44,10 +40,9 @@ public class HistogramPanel extends JPanel { "septile", "octile", "nontile", "decile"}; private static final Color LINE_COLOR = Color.GRAY.darker(); private final Histogram histogram; - private final NumberFormat format = new DecimalFormat("0.#");// NumberFormatUtil.getInstance().getNumberFormat(); private final Map rectMap = new LinkedHashMap<>(); - private boolean drawAxes = true; - private int paddingX; + private final boolean drawAxes; + private final int paddingX; private Color barColor = Color.RED.darker(); /** @@ -104,7 +99,7 @@ public String getToolTipText(MouseEvent evt) { */ public void paintComponent(Graphics graphics) { int paddingY = drawAxes ? 15 : 5; - int height = drawAxes ? getHeight() - 2 : getHeight() - 2; + int height = getHeight() - 2; int width = getWidth() - (drawAxes ? 4 : 2); int displayedHeight = (int) (height - paddingY); int space = drawAxes ? 2 : 1; @@ -144,8 +139,6 @@ public void paintComponent(Graphics graphics) { // draw the buttom line g2d.setColor(HistogramPanel.LINE_COLOR); - Node target = histogram.getTargetNode(); - // Draw axes. if (drawAxes) { // draw the side line @@ -175,32 +168,11 @@ public void setBarColor(Color barColor) { this.barColor = barColor; } - private Map pickGoodPointsAndValues(double minValue, double maxValue) { - double range = maxValue - minValue; - int powerOfTen = (int) FastMath.floor(FastMath.log(range) / FastMath.log(10)); - Map points = new HashMap<>(); - - int low = (int) FastMath.floor(minValue / FastMath.pow(10, powerOfTen)); - int high = (int) FastMath.ceil(maxValue / FastMath.pow(10, powerOfTen)); - - for (int i = low; i < high; i++) { - double realValue = i * FastMath.pow(10, powerOfTen); - Integer intValue = translateToInt(minValue, maxValue, realValue); - - if (intValue == null) { - continue; - } - - points.put(intValue, realValue); - } - - return points; - } - private Integer translateToInt(double minValue, double maxValue, double value) { if (minValue >= maxValue) { throw new IllegalArgumentException(); } + if (paddingX >= 332) { throw new IllegalArgumentException(); } diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java index 4f831e93b3..03e4e22eba 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java @@ -77,8 +77,8 @@ public class MarkovCheckEditor extends JPanel { private final JLabel testLabel = new JLabel("(Unspecified Test)"); private final JLabel conditioningLabelDep = new JLabel("(Unspecified)"); private final JLabel conditioningLabelIndep = new JLabel("(Unspecified)"); - boolean updatingTestModels = true; private final DoubleTextField percent; + boolean updatingTestModels = true; private AbstractTableModel tableModelIndep; private AbstractTableModel tableModelDep; private JLabel fractionDepLabelIndep; @@ -234,6 +234,7 @@ public void watch() { box1.add(Box.createHorizontalStrut(20)); box1.add(new JLabel("Test:")); box1.add(indTestJComboBox); + box1.add(Box.createHorizontalGlue()); JButton params = new JButton("Params"); box1.add(params); JButton recalculate = new JButton("Recalculate"); @@ -359,7 +360,7 @@ private static HistogramPanel getHistogramPanel(List results Color fillColor = new Color(113, 165, 210); view.setBarColor(fillColor); - view.setPreferredSize(new Dimension(350, 200)); + view.setMaximumSize(new Dimension(300, 200)); return view; } @@ -407,29 +408,20 @@ private void setTest() { } - /** - * Performs the action of opening a session from a file. - */ - private JPanel buildGuiDep() { - - Box b1 = Box.createVerticalBox(); - Box b2 = Box.createHorizontalBox(); + private JPanel buildGuiIndep() { + Box a1 = Box.createVerticalBox(); + Box a2 = Box.createHorizontalBox(); String setType = (String) conditioningSetTypeJComboBox.getSelectedItem(); - conditioningLabelDep.setText("Tests graphical predictions of Dep(X, Y | " + setType + ")"); - b2.add(conditioningLabelDep); - b2.add(Box.createHorizontalGlue()); - b1.add(b2); + conditioningLabelIndep.setText("Tests graphical predictions of Indep(X, Y | " + setType + ")"); + a2.add(conditioningLabelIndep); + a2.add(Box.createHorizontalGlue()); + a1.add(a2); markovTestLabel.setText(model.getMarkovCheck().getIndependenceTest().toString()); testLabel.setText(model.getMarkovCheck().getIndependenceTest().toString()); - Box b2a = Box.createHorizontalBox(); - b2a.add(Box.createHorizontalGlue()); - b1.add(b2a); - b1.add(Box.createVerticalStrut(5)); - - this.tableModelDep = new AbstractTableModel() { + this.tableModelIndep = new AbstractTableModel() { public String getColumnName(int column) { if (column == 0) { return "Index"; @@ -438,35 +430,37 @@ public String getColumnName(int column) { } else if (column == 2) { return "Test Result"; } else if (column == 3) { - return "P-Value or Bump"; + return "P-value or Bump"; } return null; } public int getColumnCount() { - return 4;//2 + MarkovFactsEditor.this.indTestProducers.size(); + return 4; } public int getRowCount() { - return model.getResults(false).size(); + List results = model.getResults(true); + return results.size(); } public Object getValueAt(int rowIndex, int columnIndex) { - if (rowIndex > model.getResults(false).size()) return null; + if (rowIndex > model.getResults(true).size()) return null; if (columnIndex == 0) { return rowIndex + 1; } + + IndependenceResult result = model.getResults(true).get(rowIndex); + if (columnIndex == 1) { - IndependenceFact fact = model.getResults(false).get(rowIndex).getFact(); + IndependenceFact fact = model.getResults(true).get(rowIndex).getFact(); List Z = new ArrayList<>(fact.getZ()); String z = Z.stream().map(Node::getName).collect(Collectors.joining(", ")); - return "Dep(" + fact.getX() + ", " + fact.getY() + (Z.isEmpty() ? "" : " | " + z) + ")"; + return "Ind(" + fact.getX() + ", " + fact.getY() + (Z.isEmpty() ? "" : " | " + z) + ")"; } - IndependenceResult result = model.getResults(false).get(rowIndex); - if (columnIndex == 2) { if (model.getMarkovCheck().getIndependenceTest() instanceof MsepTest) { if (result.isIndependent()) { @@ -502,9 +496,9 @@ public Class getColumnClass(int columnIndex) { } }; - JTable table = new JTable(tableModelDep); + JTable table = new JTable(tableModelIndep); - tableModelDep.addTableModelListener(e -> { + tableModelIndep.addTableModelListener(e -> { if (e.getColumn() == 2) { table.revalidate(); table.repaint(); @@ -532,98 +526,86 @@ public void mouseClicked(MouseEvent e) { int col = header.columnAtPoint(point); int sortCol = header.getTable().convertColumnIndexToModel(col); - MarkovCheckEditor.this.sortByColumn(sortCol, false); + MarkovCheckEditor.this.sortByColumn(sortCol, true); } }); JScrollPane scroll = new JScrollPane(table); - b1.add(scroll); + a1.add(scroll); - Box b1a = Box.createHorizontalBox(); + Box a3 = Box.createHorizontalBox(); JLabel label = new JLabel("Table contents can be selected and copied in to, e.g., Excel."); - b1a.add(label); - b1a.add(Box.createHorizontalGlue()); - b1.add(b1a); - - Box b4 = Box.createHorizontalBox(); - b4.add(Box.createGlue()); - b4.add(Box.createHorizontalStrut(10)); - - b4.add(Box.createHorizontalGlue()); - - Box b5 = Box.createHorizontalBox(); - b5.add(Box.createGlue()); + a3.add(label); + a3.add(Box.createHorizontalGlue()); + a1.add(a3); setLabelTexts(); - Box b0 = Box.createHorizontalBox(); - b0.add(b1); - b0.add(Box.createHorizontalStrut(10)); - - Box b0b1 = Box.createVerticalBox(); - b0b1.add(Box.createVerticalGlue()); - histogramPanelDep = new JPanel(); - histogramPanelDep.setLayout(new BorderLayout()); - histogramPanelDep.setBorder(new EmptyBorder(10, 10, 10, 10)); - histogramPanelIndep.add(createHistogramPanel(false), BorderLayout.CENTER); + Box a4 = Box.createVerticalBox(); + histogramPanelIndep = new JPanel(); + histogramPanelIndep.setLayout(new BorderLayout()); + histogramPanelIndep.setBorder(new EmptyBorder(10, 10, 10, 10)); + histogramPanelIndep.add(createHistogramPanel(true), BorderLayout.CENTER); + a4.add(histogramPanelIndep); - b0b1.add(histogramPanelDep); - b5.add(fractionDepLabelDep); - b0b1.add(b5); + Box a5 = Box.createHorizontalBox(); + a5.add(Box.createHorizontalGlue()); + a5.add(fractionDepLabelIndep); + a4.add(a5); - Box b6 = Box.createHorizontalBox(); - b6.add(Box.createHorizontalGlue()); - b6.add(ksLabelDep); - b0b1.add(b6); + Box a6 = Box.createHorizontalBox(); + a6.add(Box.createHorizontalGlue()); + a6.add(ksLabelIndep); + a4.add(a6); - Box b6a = Box.createHorizontalBox(); - b6a.add(Box.createHorizontalGlue()); - b6a.add(binomialPLabelDep); - b0b1.add(b6a); + Box a7 = Box.createHorizontalBox(); + a7.add(Box.createHorizontalGlue()); + a7.add(binomialPLabelIndep); + a4.add(a7); - Box b6b = Box.createHorizontalBox(); - b6b.add(Box.createHorizontalGlue()); - b6b.add(andersonDarlingA2LabelDep); - b0b1.add(b6b); + Box a8 = Box.createHorizontalBox(); + a8.add(Box.createHorizontalGlue()); + a8.add(andersonDarlingA2LabelIndep); + a4.add(a8); - Box b6c = Box.createHorizontalBox(); - b6c.add(Box.createHorizontalGlue()); - b6c.add(andersonDarlingPLabelDep); - b0b1.add(b6c); + Box a9 = Box.createHorizontalBox(); + a9.add(Box.createHorizontalGlue()); + a9.add(andersonDarlingPLabelIndep); + a4.add(a9); - b0b1.add(Box.createVerticalGlue()); - b0.add(b0b1); + Box a11 = Box.createHorizontalBox(); + a11.add(a1); + a11.add(a4); JPanel panel = new JPanel(); panel.setLayout(new BorderLayout()); - panel.add(b0, BorderLayout.CENTER); + panel.add(a11, BorderLayout.CENTER); + panel.setBorder(new EmptyBorder(10, 10, 10, 10)); return panel; } - private JPanel buildGuiIndep() { - - Box b1 = Box.createVerticalBox(); - - Box b2 = Box.createHorizontalBox(); + /** + * Performs the action of opening a session from a file. + */ + private JPanel buildGuiDep() { + Box a1 = Box.createVerticalBox(); + Box a2 = Box.createHorizontalBox(); String setType = (String) conditioningSetTypeJComboBox.getSelectedItem(); - conditioningLabelIndep.setText("Tests graphical predictions of Indep(X, Y | " + setType + ")"); - b2.add(conditioningLabelIndep); - b2.add(Box.createHorizontalGlue()); - b1.add(b2); + conditioningLabelDep.setText("Tests graphical predictions of Dep(X, Y | " + setType + ")"); + + a2.add(conditioningLabelDep); + a2.add(Box.createHorizontalGlue()); + a1.add(a2); markovTestLabel.setText(model.getMarkovCheck().getIndependenceTest().toString()); testLabel.setText(model.getMarkovCheck().getIndependenceTest().toString()); - Box b2a = Box.createHorizontalBox(); - b2a.add(Box.createHorizontalGlue()); - b1.add(b2a); - - b1.add(Box.createVerticalStrut(5)); +// a1.add(Box.createVerticalStrut(5)); - this.tableModelIndep = new AbstractTableModel() { + this.tableModelDep = new AbstractTableModel() { public String getColumnName(int column) { if (column == 0) { return "Index"; @@ -639,7 +621,7 @@ public String getColumnName(int column) { } public int getColumnCount() { - return 4;//2 + MarkovFactsEditor.this.indTestProducers.size(); + return 4; } public int getRowCount() { @@ -658,25 +640,21 @@ public Object getValueAt(int rowIndex, int columnIndex) { if (columnIndex == 1) { IndependenceFact fact = model.getResults(true).get(rowIndex).getFact(); - List Z = new ArrayList<>(fact.getZ()); -// Collections.sort(Z); - String z = Z.stream().map(Node::getName).collect(Collectors.joining(", ")); - return "Ind(" + fact.getX() + ", " + fact.getY() + (Z.isEmpty() ? "" : " | " + z) + ")"; } if (columnIndex == 2) { if (model.getMarkovCheck().getIndependenceTest() instanceof MsepTest) { - if (result.isIndependent()) { + if (result.isDependent()) { return "M-SEPARATED"; } else { return "m-connected"; } } else { - if (result.isIndependent()) { - return "INDEPENDENT"; + if (result.isDependent()) { + return "DepENDENT"; } else { return "dependent"; } @@ -702,9 +680,9 @@ public Class getColumnClass(int columnIndex) { } }; - JTable table = new JTable(tableModelIndep); + JTable table = new JTable(tableModelDep); - tableModelIndep.addTableModelListener(e -> { + tableModelDep.addTableModelListener(e -> { if (e.getColumn() == 2) { table.revalidate(); table.repaint(); @@ -723,7 +701,6 @@ public Class getColumnClass(int columnIndex) { table.getColumnModel().getColumn(2).setCellRenderer(new Renderer()); table.getColumnModel().getColumn(3).setCellRenderer(new Renderer()); - JTableHeader header = table.getTableHeader(); header.addMouseListener(new MouseAdapter() { @@ -733,71 +710,60 @@ public void mouseClicked(MouseEvent e) { int col = header.columnAtPoint(point); int sortCol = header.getTable().convertColumnIndexToModel(col); - MarkovCheckEditor.this.sortByColumn(sortCol, true); + MarkovCheckEditor.this.sortByColumn(sortCol, false); } }); JScrollPane scroll = new JScrollPane(table); - b1.add(scroll); + a1.add(scroll); - Box b1a = Box.createHorizontalBox(); + Box a3 = Box.createHorizontalBox(); JLabel label = new JLabel("Table contents can be selected and copied in to, e.g., Excel."); - b1a.add(label); - b1a.add(Box.createHorizontalGlue()); - b1.add(b1a); - - Box b4 = Box.createHorizontalBox(); - b4.add(Box.createGlue()); - b4.add(Box.createHorizontalStrut(10)); - - b4.add(Box.createHorizontalGlue()); - - Box b5 = Box.createHorizontalBox(); - b5.add(Box.createGlue()); + a3.add(label); + a3.add(Box.createHorizontalGlue()); + a1.add(a3); setLabelTexts(); - Box b0 = Box.createHorizontalBox(); - b0.add(b1); - b0.add(Box.createHorizontalStrut(10)); - - Box b0b1 = Box.createVerticalBox(); - b0b1.add(Box.createVerticalGlue()); - histogramPanelIndep = new JPanel(); - histogramPanelIndep.setLayout(new BorderLayout()); - histogramPanelIndep.setBorder(new EmptyBorder(10, 10, 10, 10)); - histogramPanelIndep.add(createHistogramPanel(true), BorderLayout.CENTER); - b0b1.add(histogramPanelIndep); - b0b1.add(Box.createVerticalGlue()); - - b5.add(fractionDepLabelIndep); - b0b1.add(b5); - - Box b6 = Box.createHorizontalBox(); - b6.add(Box.createHorizontalGlue()); - b6.add(ksLabelIndep); - b0b1.add(b6); - - Box b6a = Box.createHorizontalBox(); - b6a.add(Box.createHorizontalGlue()); - b6a.add(binomialPLabelIndep); - b0b1.add(b6a); - - Box b6b = Box.createHorizontalBox(); - b6b.add(Box.createHorizontalGlue()); - b6b.add(andersonDarlingA2LabelIndep); - b0b1.add(b6b); - - Box b6c = Box.createHorizontalBox(); - b6c.add(Box.createHorizontalGlue()); - b6c.add(andersonDarlingPLabelIndep); - b0b1.add(b6c); - - b0.add(b0b1); + Box a4 = Box.createVerticalBox(); + histogramPanelDep = new JPanel(); + histogramPanelDep.setLayout(new BorderLayout()); + histogramPanelDep.setBorder(new EmptyBorder(10, 10, 10, 10)); + histogramPanelDep.add(createHistogramPanel(true), BorderLayout.CENTER); + a4.add(histogramPanelDep); + + Box a5 = Box.createHorizontalBox(); + a5.add(Box.createHorizontalGlue()); + a5.add(fractionDepLabelDep); + a4.add(a5); + + Box a6 = Box.createHorizontalBox(); + a6.add(Box.createHorizontalGlue()); + a6.add(ksLabelDep); + a4.add(a6); + + Box a7 = Box.createHorizontalBox(); + a7.add(Box.createHorizontalGlue()); + a7.add(binomialPLabelDep); + a4.add(a7); + + Box a8 = Box.createHorizontalBox(); + a8.add(Box.createHorizontalGlue()); + a8.add(andersonDarlingA2LabelDep); + a4.add(a8); + + Box a9 = Box.createHorizontalBox(); + a9.add(Box.createHorizontalGlue()); + a9.add(andersonDarlingPLabelDep); + a4.add(a9); + + Box a11 = Box.createHorizontalBox(); + a11.add(a1); + a11.add(a4); JPanel panel = new JPanel(); panel.setLayout(new BorderLayout()); - panel.add(b0, BorderLayout.CENTER); + panel.add(a11, BorderLayout.CENTER); panel.setBorder(new EmptyBorder(10, 10, 10, 10)); return panel; @@ -941,31 +907,21 @@ private Box createHistogramPanel(boolean indep) { } HistogramPanel view = getHistogramPanel(results); - - Box box = Box.createHorizontalBox(); - box.add(Box.createHorizontalGlue()); + Box box = Box.createVerticalBox(); box.add(view); - box.add(Box.createHorizontalGlue()); - - Box vBox = Box.createVerticalBox(); - vBox.add(Box.createVerticalGlue()); - vBox.add(box); - vBox.add(Box.createVerticalGlue()); - - return vBox; + return box; } private DataType getDataType() { DataModel dataSet = model.getDataModel(); if (dataSet.isContinuous() && !(dataSet instanceof ICovarianceMatrix)) { - // covariance dataset is continuous at the same time - Zhou return DataType.Continuous; } else if (dataSet.isDiscrete()) { return DataType.Discrete; } else if (dataSet.isMixed()) { return DataType.Mixed; - } else if (dataSet instanceof ICovarianceMatrix) { // Better to add an isCovariance() - Zhou + } else if (dataSet instanceof ICovarianceMatrix) { return DataType.Covariance; } else { return null; diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Grasp.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Grasp.java index 4891f4cd8c..d545f942fb 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Grasp.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Grasp.java @@ -156,6 +156,8 @@ public List bestOrder(@NotNull List order) { } } + if (bestPerm == null) return null; + this.scorer.score(bestPerm); long stop = MillisecondTimes.timeMillis(); @@ -434,6 +436,7 @@ private void graspDfs(@NotNull TeyssierScorer scorer, double sOld, int[] depth, } for (Node x : parents) { + if (Thread.currentThread().isInterrupted()) return; boolean covered = scorer.coveredEdge(x, y); boolean singular = true; From 3e89d4e06e5ff57d93712b43840b7de332efa5a0 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Mon, 29 Jan 2024 01:00:35 -0500 Subject: [PATCH 139/163] Cleared up documentation in the search package. --- .../main/java/edu/cmu/tetrad/search/BFci.java | 20 ++ .../main/java/edu/cmu/tetrad/search/Boss.java | 40 ++++ .../edu/cmu/tetrad/search/BossLingam.java | 7 +- .../main/java/edu/cmu/tetrad/search/Ccd.java | 3 + .../main/java/edu/cmu/tetrad/search/Cfci.java | 50 ++--- .../java/edu/cmu/tetrad/search/Demixer.java | 29 ++- .../edu/cmu/tetrad/search/DirectLingam.java | 13 +- .../edu/cmu/tetrad/search/FactorAnalysis.java | 87 ++++---- .../main/java/edu/cmu/tetrad/search/Fas.java | 12 +- .../main/java/edu/cmu/tetrad/search/Fasd.java | 48 ++--- .../main/java/edu/cmu/tetrad/search/Fask.java | 72 ++++--- .../java/edu/cmu/tetrad/search/FastIca.java | 66 ++---- .../main/java/edu/cmu/tetrad/search/Fci.java | 21 +- .../java/edu/cmu/tetrad/search/FciMax.java | 41 ++-- .../main/java/edu/cmu/tetrad/search/Fges.java | 50 ++--- .../java/edu/cmu/tetrad/search/FgesMb.java | 40 ++-- .../main/java/edu/cmu/tetrad/search/Fofc.java | 22 +- .../main/java/edu/cmu/tetrad/search/Ftfc.java | 6 +- .../main/java/edu/cmu/tetrad/search/GFci.java | 14 +- .../java/edu/cmu/tetrad/search/Grasp.java | 22 +- .../java/edu/cmu/tetrad/search/GraspFci.java | 63 +++++- .../edu/cmu/tetrad/search/GrowShrink.java | 46 +--- .../java/edu/cmu/tetrad/search/IcaLingD.java | 2 + .../java/edu/cmu/tetrad/search/IcaLingam.java | 2 + .../main/java/edu/cmu/tetrad/search/Ida.java | 54 ++++- .../edu/cmu/tetrad/search/IndTestIod.java | 3 + .../main/java/edu/cmu/tetrad/search/Lofs.java | 17 +- .../java/edu/cmu/tetrad/search/Mimbuild.java | 33 ++- .../edu/cmu/tetrad/search/MimbuildTrek.java | 41 ++-- .../edu/cmu/tetrad/search/MixtureModel.java | 32 ++- .../main/java/edu/cmu/tetrad/search/Pc.java | 15 +- .../main/java/edu/cmu/tetrad/search/PcMb.java | 82 +++----- .../main/java/edu/cmu/tetrad/search/Pcd.java | 132 ++++++------ .../main/java/edu/cmu/tetrad/search/Rfci.java | 39 +--- .../main/java/edu/cmu/tetrad/search/Sp.java | 64 ++++-- .../java/edu/cmu/tetrad/search/SvarFas.java | 46 ++-- .../java/edu/cmu/tetrad/search/SvarFci.java | 35 +-- .../java/edu/cmu/tetrad/search/SvarFges.java | 199 ++++++------------ .../java/edu/cmu/tetrad/search/SvarGfci.java | 4 +- 39 files changed, 806 insertions(+), 766 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/BFci.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/BFci.java index 740aa93adf..13c973f84c 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/BFci.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/BFci.java @@ -193,18 +193,38 @@ public IndependenceTest getIndependenceTest() { return this.independenceTest; } + /** + * Returns the number of times to restart the search. + * + * @param numStarts The number of times to restart the search. + */ public void setNumStarts(int numStarts) { this.numStarts = numStarts; } + /** + * Sets the depth of the search (for the constraint-based step). + * + * @param depth The depth of the search. + */ public void setDepth(int depth) { this.depth = depth; } + /** + * Sets whether the discriminating path rule should be used. + * + * @param doDiscriminatingPathRule True if the discriminating path rule should be used, false otherwise. + */ public void setDoDiscriminatingPathRule(boolean doDiscriminatingPathRule) { this.doDiscriminatingPathRule = doDiscriminatingPathRule; } + /** + * Sets whether the BES should be used. + * + * @param useBes True if the BES should be used, false otherwise. + */ public void setBossUseBes(boolean useBes) { this.bossUseBes = useBes; } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Boss.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Boss.java index 1611b05b9a..d9c08c567a 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Boss.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Boss.java @@ -71,21 +71,40 @@ * @see Knowledge */ public class Boss implements SuborderSearch { + // The score. private final Score score; + // The variables. private final List variables; + // The parents. private final Map> parents; + // The grow-shrink trees. private Map gsts; + // The set of all variables. private Set all; + // The pool for parallelism. private ForkJoinPool pool; + // The knowledge. private Knowledge knowledge = new Knowledge(); + // The BES algorithm. private BesPermutation bes = null; + // The number of random starts to use. private int numStarts = 1; + // True if the order of the variables in the data should be used for an initial best-order search, false if a random + // permutation should be used. (Subsequence automatic best order runs will use random permutations.) This is + // included so that the algorithm will be capable of outputting the same results with the same data without any + // randomness. private boolean useDataOrder = true; + // True if the grow-shrink trees should be reset after each best-mutation step. private boolean resetAfterBM = false; + // True if the grow-shrink trees should be reset after each restart. private boolean resetAfterRS = true; + // The number of threads to use. private int numThreads = 1; + // True if verbose output should be printed. private List bics; + // The BIC scores. private List times; + // True if verbose output should be printed. private boolean verbose = false; @@ -103,6 +122,15 @@ public Boss(Score score) { } } + /** + * Searches a suborder of the variables. The prefix is the set of variables that must precede the suborder. The + * suborder is the set of variables to be ordered. The gsts is a map from variables to GrowShrinkTrees, which are + * used to cache scores for the variables. The searchSuborder method will update the suborder to be the best + * ordering found. + * @param prefix The prefix of the suborder. + * @param suborder The suborder. + * @param gsts The GrowShrinkTree being used to do caching of scores. + */ @Override public void searchSuborder(List prefix, List suborder, Map gsts) { assert this.numStarts > 0; @@ -196,6 +224,10 @@ public void setUseBes(boolean use) { } } + /** + * Sets the knowledge to be used for the search. + * @param knowledge This knowledge. If null, no knowledge will be used. + */ @Override public void setKnowledge(Knowledge knowledge) { this.knowledge = knowledge; @@ -214,10 +246,18 @@ public void setNumStarts(int numStarts) { this.numStarts = numStarts; } + /** + * Sets whether the grow-shrink trees should be reset after each best-mutation step. + * @param reset True if so. + */ public void setResetAfterBM(boolean reset) { this.resetAfterBM = reset; } + /** + * Sets whether the grow-shrink trees should be reset after each restart. + * @param reset True if so. + */ public void setResetAfterRS(boolean reset) { this.resetAfterRS = reset; } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/BossLingam.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/BossLingam.java index 505e2baa56..047a6684e6 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/BossLingam.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/BossLingam.java @@ -60,11 +60,12 @@ * @author josephramsey */ public class BossLingam { + // The CPDAG whose unoriented edges are to be oriented. private final Graph cpdag; + // The dataset to use. private final DataSet dataSet; + // The p-values of the search. private double[] pValues; - private double alpha = 0.05; - /** * Constructor. @@ -145,7 +146,7 @@ public void setAlpha(double alpha) { throw new IllegalArgumentException("Alpha is in range [0, 1]"); } - this.alpha = alpha; + // The alpha level for the search. } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Ccd.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Ccd.java index 018d8a51f4..5792fc2c45 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Ccd.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Ccd.java @@ -49,8 +49,11 @@ * @author josephramsey */ public final class Ccd implements IGraphSearch { + // The independence test to be used. private final IndependenceTest independenceTest; + // The nodes in the graph. private final List nodes; + // Whether the R1 rule should be applied. private boolean applyR1; /** diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Cfci.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Cfci.java index d6d6bc3954..5476d18a1b 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Cfci.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Cfci.java @@ -48,55 +48,33 @@ */ public final class Cfci implements IGraphSearch { - /** - * The SepsetMap being constructed. - */ + // The SepsetMap being constructed. private final SepsetMap sepsets = new SepsetMap(); - /** - * The variables to search over (optional) - */ + // The variables to search over (optional) private final List variables = new ArrayList<>(); - /** - * The independence test. - */ + // The independence test. private final IndependenceTest independenceTest; - /** - * The logger to use. - */ + // The logger to use. private final TetradLogger logger = TetradLogger.getInstance(); - /** - * The PAG being constructed. - */ + // The PAG being constructed. private Graph graph; - /** - * The background knowledge. - */ + // The background knowledge. private Knowledge knowledge = new Knowledge(); - /** - * Flag for complete rule set, true if you should use complete rule set, false otherwise. - */ + // Flag for complete rule set, true if you should use complete rule set, false otherwise. private boolean completeRuleSetUsed = true; - /** - * True iff the possible msep search is done. - */ + // True iff the possible msep search is done. private boolean possibleMsepSearchDone = true; - /** - * The maximum length for any discriminating path. -1 if unlimited; otherwise, a positive integer. - */ + // The maximum length for any discriminating path. -1 if unlimited; otherwise, a positive integer. private int maxReachablePathLength = -1; - /** - * Set of ambiguous unshielded triples. - */ + // Set of ambiguous unshielded triples. private Set ambiguousTriples; - /** - * The depth for the fast adjacency search. - */ + // The depth for the fast adjacency search. private int depth = -1; - /** - * Elapsed time of last search. - */ + // Elapsed time of last search. private long elapsedTime; + // Whether verbose output (about independencies) is output. private boolean verbose; + // Whether to do the discriminating path rule. private boolean doDiscriminatingPathRule; diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Demixer.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Demixer.java index 1b27819f46..f8acaa5af5 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Demixer.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Demixer.java @@ -16,19 +16,34 @@ * @author Madelyn Glymour */ public class Demixer { - + // number of variables in the data set private final int numVars; + // number of cases in the data set private final int numCases; - private final int numClusters; // number of clusters + // number of clusters + private final int numClusters; + // the data set private final DataSet data; - private final double[][] dataArray; // v-by-n data matrix + // the data set as a double array + private final double[][] dataArray; + // the means of each variable for each model private final Matrix[] variances; - private final double[][] meansArray; // k-by-v matrix representing means for each variable for each of k models - private final Matrix[] variancesArray; // k-by-v-by-v matrix representing covariance matrix for each of k models - private final double[] weightsArray; // array of length k representing weights for each model - private final double[][] gammaArray; // k-by-n matrix representing gamma for each data case in each model + // the means of each variable for each model + private final double[][] meansArray; + // the variances of each variable for each model + private final Matrix[] variancesArray; + // the weights of each model + private final double[] weightsArray; + // the gamma values for each case in each model + private final double[][] gammaArray; + // whether the algorithm has been run private boolean demixed = false; + /** + * Constructor. Initializes the means, weights, and covariance matrices for each model. + * @param data the data set + * @param k the number of models + */ public Demixer(DataSet data, int k) { this.numClusters = k; this.data = data; diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/DirectLingam.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/DirectLingam.java index 5d77cb2554..5155f8d529 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/DirectLingam.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/DirectLingam.java @@ -42,19 +42,22 @@ *

                * A. Hyvärinen and S. M. Smith. Pairwise likelihood ratios for estimation of non-Gaussian structural evaluation models. * Journal of Machine Learning Research 14:111-152, 2013. - *

                - * NEEDS DOCUMENTATION * * @author bryanandrews */ public class DirectLingam { - + // the data set private final DataSet dataset; + // the variables private final List variables; + // the grow-shrink trees private final Map gsts; /** * Constructor. + * + * @param dataset the data set + * @param score the score */ public DirectLingam(DataSet dataset, Score score) { this.dataset = dataset; @@ -70,7 +73,9 @@ public DirectLingam(DataSet dataset, Score score) { } /** - * NEEDS DOCUMENTATION + * Performs the search. Returns a graph. + * + * @return a graph */ public Graph search() { List U = new ArrayList<>(this.variables); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/FactorAnalysis.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/FactorAnalysis.java index 16eddfda65..73986adb59 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/FactorAnalysis.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/FactorAnalysis.java @@ -46,12 +46,15 @@ * @author Mike Freenor */ public class FactorAnalysis { + // the covariance matrix private final CovarianceMatrix covariance; - // method-specific fields that get used private LinkedList factorLoadingVectors; + // the threshold for the algorithm private double threshold = 0.001; + // the number of factors to find private int numFactors = 2; + // the residual matrix private Matrix residual; /** @@ -72,46 +75,6 @@ public FactorAnalysis(DataSet dataSet) { this.covariance = new CovarianceMatrix(dataSet); } - - //designed for normalizing a vector. - //as usual, vectors are treated as matrices to simplify operations elsewhere - private static Matrix normalizeRows(Matrix matrix) { - LinkedList normalizedRows = new LinkedList<>(); - for (int i = 0; i < matrix.getNumRows(); i++) { - Vector vector = matrix.getRow(i); - Matrix colVector = new Matrix(matrix.getNumColumns(), 1); - for (int j = 0; j < matrix.getNumColumns(); j++) - colVector.set(j, 0, vector.get(j)); - - normalizedRows.add(FactorAnalysis.normalizeVector(colVector)); - } - - Matrix result = new Matrix(matrix.getNumRows(), matrix.getNumColumns()); - for (int i = 0; i < matrix.getNumRows(); i++) { - Matrix normalizedRow = normalizedRows.get(i); - for (int j = 0; j < matrix.getNumColumns(); j++) { - result.set(i, j, normalizedRow.get(j, 0)); - } - } - - return result; - } - - private static Matrix normalizeVector(Matrix vector) { - double scalar = FastMath.sqrt(vector.transpose().times(vector).get(0, 0)); - return vector.scalarMult(1.0 / scalar); - } - - private static Matrix matrixExp(Matrix matrix, double exponent) { - Matrix result = new Matrix(matrix.getNumRows(), matrix.getNumColumns()); - for (int i = 0; i < matrix.getNumRows(); i++) { - for (int j = 0; j < matrix.getNumColumns(); j++) { - result.set(i, j, FastMath.pow(matrix.get(i, j), exponent)); - } - } - return result; - } - /** * Successive method with residual matrix. *

                @@ -276,8 +239,6 @@ public Matrix successiveFactorVarimax(Matrix factorLoadingMatrix) { return result; } - // ------------------Private methods-------------------// - /** * Sets the threshold. * @@ -305,6 +266,46 @@ public Matrix getResidual() { return this.residual; } + + //designed for normalizing a vector. + //as usual, vectors are treated as matrices to simplify operations elsewhere + private static Matrix normalizeRows(Matrix matrix) { + LinkedList normalizedRows = new LinkedList<>(); + for (int i = 0; i < matrix.getNumRows(); i++) { + Vector vector = matrix.getRow(i); + Matrix colVector = new Matrix(matrix.getNumColumns(), 1); + for (int j = 0; j < matrix.getNumColumns(); j++) + colVector.set(j, 0, vector.get(j)); + + normalizedRows.add(FactorAnalysis.normalizeVector(colVector)); + } + + Matrix result = new Matrix(matrix.getNumRows(), matrix.getNumColumns()); + for (int i = 0; i < matrix.getNumRows(); i++) { + Matrix normalizedRow = normalizedRows.get(i); + for (int j = 0; j < matrix.getNumColumns(); j++) { + result.set(i, j, normalizedRow.get(j, 0)); + } + } + + return result; + } + + private static Matrix normalizeVector(Matrix vector) { + double scalar = FastMath.sqrt(vector.transpose().times(vector).get(0, 0)); + return vector.scalarMult(1.0 / scalar); + } + + private static Matrix matrixExp(Matrix matrix, double exponent) { + Matrix result = new Matrix(matrix.getNumRows(), matrix.getNumColumns()); + for (int i = 0; i < matrix.getNumRows(); i++) { + for (int j = 0; j < matrix.getNumColumns(); j++) { + result.set(i, j, FastMath.pow(matrix.get(i, j), exponent)); + } + } + return result; + } + /** * Helper method for the basic structure successive factor method above. Takes a residual matrix and an * approximation vector, and finds both the factor loading vector and the "d scalar" which is used to determine the diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fas.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fas.java index 7bd62dc513..b14950acb5 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fas.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fas.java @@ -62,19 +62,29 @@ * @see Knowledge */ public class Fas implements IFas { + // The test to be used for conditional independence tests. private final IndependenceTest test; + // The logger. private final TetradLogger logger = TetradLogger.getInstance(); + // The knowledge. private Knowledge knowledge = new Knowledge(); + // The number of independence tests that were done. private int numIndependenceTests; + // The sepsets that were discovered in the search. private SepsetMap sepset = new SepsetMap(); + // The heuristic to use. private PcCommon.PcHeuristicType heuristic = PcCommon.PcHeuristicType.NONE; + // The depth of the search. private int depth = 1000; + // Whether the stable adjacency search should be used. private boolean stable = true; + // The elapsed time of the search. private long elapsedTime = 0L; + // Whether verbose output should be printed. private PrintStream out = System.out; + // Whether verbose output should be printed. private boolean verbose = false; - /** * Constructor. * diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fasd.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fasd.java index 007ef3313c..79277d689a 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fasd.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fasd.java @@ -27,10 +27,10 @@ import edu.cmu.tetrad.search.utils.LogUtilsSearch; import edu.cmu.tetrad.search.utils.SepsetMap; import edu.cmu.tetrad.util.ChoiceGenerator; +import edu.cmu.tetrad.util.NumberFormatUtil; import edu.cmu.tetrad.util.TetradLogger; import java.io.PrintStream; -import java.text.DecimalFormat; import java.text.NumberFormat; import java.util.*; @@ -49,49 +49,31 @@ */ public class Fasd implements IFas { - /** - * The independence test. This should be appropriate to the types - */ + // The independence test. This should be appropriate to the types private final IndependenceTest test; - /** - * The logger, by default the empty logger. - */ + // The logger, by default the empty logger. private final TetradLogger logger = TetradLogger.getInstance(); - private final NumberFormat nf = new DecimalFormat("0.00E0"); - /** - * The search graph. It is assumed going in that all the true adjacencies of x are in this graph for every node x. - * It is hoped (i.e., true in the large sample limit) that true adjacencies are never removed. - */ + // The number formatter. + private final NumberFormat nf = NumberFormatUtil.getInstance().getNumberFormat(); + // The search graph. It is assumed going in that all the true adjacencies of x are in this graph for every node x. + // It is hoped (i.e., true in the large sample limit) that true adjacencies are never removed. private final Graph graph; - /** - * Specification of which edges are forbidden or required. - */ + // Specification of which edges are forbidden or required. private Knowledge knowledge = new Knowledge(); - /** - * The maximum number of variables conditioned on in any conditional independence test. If the depth is -1, it will - * be taken to be the maximum value, which is 1000. Otherwise, it should be set to a non-negative integer. - */ + // The maximum number of variables conditioned on in any conditional independence test. If the depth is -1, it will + // be taken to be the maximum value, which is 1000. Otherwise, it should be set to a non-negative integer. private int depth = 1000; - /** - * The number of independence tests. - */ + // The number of independence tests. private int numIndependenceTests; - /** - * The sepsets found during the search. - */ + // The sepsets found during the search. private SepsetMap sepset = new SepsetMap(); - /** - * The depth 0 graph, specified initially. - */ + // The depth 0 graph, specified initially. private Graph externalGraph; - /** - * True iff verbose output should be printed. - */ + // True iff verbose output should be printed. private boolean verbose; - + // The output stream. private PrintStream out = System.out; - /** * Constructs a new FastAdjacencySearch. * diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fask.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fask.java index 569575f466..b8026db1d9 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fask.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fask.java @@ -199,41 +199,6 @@ public Fask(DataSet dataSet, Score score, IndependenceTest test) { this.orientationAlpha = 0.01; } - private static double cu(double[] x, double[] y, double[] condition) { - double exy = 0.0; - - int n = 0; - - for (int k = 0; k < x.length; k++) { - if (condition[k] > 0) { - exy += x[k] * y[k]; - n++; - } - } - - return exy / n; - } - - // Returns E(XY | Z > 0); Z is typically either X or Y. - private static double E(double[] x, double[] y, double[] z) { - double exy = 0.0; - int n = 0; - - for (int k = 0; k < x.length; k++) { - if (z[k] > 0) { - exy += x[k] * y[k]; - n++; - } - } - - return exy / n; - } - - - // Returns E(XY | Z > 0) / sqrt(E(XX | Z > 0) * E(YY | Z > 0)). Z is typically either X or Y. - private static double correxp(double[] x, double[] y, double[] z) { - return Fask.E(x, y, z) / sqrt(Fask.E(x, x, z) * Fask.E(y, y, z)); - } public static double faskLeftRightV2(double[] x, double[] y, boolean empirical, double delta) { double sx = skewness(x); @@ -707,6 +672,43 @@ public double leftRight(double[] x, double[] y) { throw new IllegalStateException("Left right rule not configured: " + this.leftRight); } + + private static double cu(double[] x, double[] y, double[] condition) { + double exy = 0.0; + + int n = 0; + + for (int k = 0; k < x.length; k++) { + if (condition[k] > 0) { + exy += x[k] * y[k]; + n++; + } + } + + return exy / n; + } + + // Returns E(XY | Z > 0); Z is typically either X or Y. + private static double E(double[] x, double[] y, double[] z) { + double exy = 0.0; + int n = 0; + + for (int k = 0; k < x.length; k++) { + if (z[k] > 0) { + exy += x[k] * y[k]; + n++; + } + } + + return exy / n; + } + + + // Returns E(XY | Z > 0) / sqrt(E(XX | Z > 0) * E(YY | Z > 0)). Z is typically either X or Y. + private static double correxp(double[] x, double[] y, double[] z) { + return Fask.E(x, y, z) / sqrt(Fask.E(x, x, z) * Fask.E(y, y, z)); + } + private double tanh(double[] x, double[] y, boolean empirical) { if (empirical) { diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/FastIca.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/FastIca.java index 56d40b8580..9026f5bf9e 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/FastIca.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/FastIca.java @@ -125,81 +125,52 @@ */ public class FastIca { - /** - * The algorithm type where all components are extracted simultaneously. - */ + // The algorithm type where all components are extracted simultaneously. public static int PARALLEL; - /** - * The algorithm type where the components are extracted one at a time. - */ + // The algorithm type where the components are extracted one at a time. public static int DEFLATION = 1; - /** - * One of the function types that can be used to approximate negative entropy. - */ + // One of the function types that can be used to approximate negative entropy. public static int LOGCOSH = 2; - /** - * The other function type that can be used to approximate negative entropy. - */ + // The other function type that can be used to approximate negative entropy. public static int EXP = 3; - /** - * A data matrix with n rows representing observations and p columns representing variables. - */ + // A data matrix with n rows representing observations and p columns representing variables. private final Matrix X; - /** - * The number of independent components to be extracted. - */ + // The number of independent components to be extracted. private int numComponents; - /** - * If algorithmType == PARALLEL, the components are extracted simultaneously (the default). if algorithmType == - * DEFLATION, the components are extracted one at a time. - */ + // If algorithmType == PARALLEL, the components are extracted simultaneously (the default). if algorithmType == + // DEFLATION, the components are extracted one at a time. private int algorithmType = FastIca.PARALLEL; - /** - * The function type to be used, either LOGCOSH or EXP. - */ + // The function type to be used, either LOGCOSH or EXP. private int function = FastIca.LOGCOSH; - /** - * Constant in range [1, 2] used in approximation to neg-entropy when 'fun == "logcosh". Default = 1.0. - */ + // Constant in range [1, 2] used in approximation to neg-entropy when 'fun == "logcosh". Default = 1.0. private double alpha = 1.1; - /** - * A logical value indicating whether rows of the data matrix 'X' should be standardized beforehand. Default = - * false. - */ + // A logical value indicating whether rows of the data matrix 'X' should be standardized beforehand. Default = + // false. private boolean rowNorm; - /** - * Maximum number of iterations to perform. Default = 200. - */ + // Maximum number of iterations to perform. Default = 200. private int maxIterations = 200; - /** - * A positive scalar giving the tolerance at which the un-mixing matrix is considered to have converged. Default = - * 1e-04. - */ + // A positive scalar giving the tolerance at which the un-mixing matrix is considered to have converged. Default = + // 1e-04. private double tolerance = 1e-04; - /** - * A logical value indicating the level of output as the algorithm runs. Default = false. - */ + // A logical value indicating the level of output as the algorithm runs. Default = false. private boolean verbose; - /** - * Initial un-mixing matrix of dimension (n.comp,n.comp). If null (default), then a matrix of normal r.v.'s is - * used. - */ + // Initial un-mixing matrix of dimension (n.comp,n.comp). If null (default), then a matrix of normal r.v.'s is + // used. private Matrix wInit; - /** * Constructs an instance of the Fast ICA algorithm, taking as arguments the two arguments that cannot be defaulted: * the data matrix itself and the number of components to be extracted. @@ -211,7 +182,6 @@ public FastIca(Matrix X, int numComponents) { this.numComponents = numComponents; } - /** * If algorithmType == PARALLEL, the components are extracted simultaneously (the default). if algorithmType == * DEFLATION, the components are extracted one at a time. diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fci.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fci.java index d41c29f0df..ca13626c78 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fci.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fci.java @@ -70,22 +70,35 @@ * @see Knowledge */ public final class Fci implements IGraphSearch { + // The variables to search over. private final List variables = new ArrayList<>(); + // The independence test to use. private final IndependenceTest independenceTest; + // The logger. private final TetradLogger logger = TetradLogger.getInstance(); + // The sepsets from FAS. private SepsetMap sepsets; + // The background knowledge. private Knowledge knowledge = new Knowledge(); + // Whether the Zhang complete rule set should be used. private boolean completeRuleSetUsed = true; + // Whether the possible msep step should be done. private boolean possibleMsepSearchDone = true; + // The maximum length of any discriminating path. private int maxPathLength = -1; + // The depth of search. private int depth = -1; + // The elapsed time of search. private long elapsedTime; + // Whether verbose output should be printed. private boolean verbose; + // The PC heuristic type to use. private PcCommon.PcHeuristicType heuristic = PcCommon.PcHeuristicType.NONE; + // Whether the stable options should be used. private boolean stable = true; + // Whether the discriminating path rule should be used. private boolean doDiscriminatingPathRule = true; - /** * Constructor. * @@ -134,7 +147,11 @@ public Fci(IndependenceTest independenceTest, List searchVars) { this.variables.removeAll(remVars); } - + /** + * Performs the search. + * + * @return The graph. + */ public Graph search() { long start = MillisecondTimes.timeMillis(); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/FciMax.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/FciMax.java index 242919b27e..16fd4af3e8 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/FciMax.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/FciMax.java @@ -65,21 +65,33 @@ * @see Knowledge */ public final class FciMax implements IGraphSearch { + // The independence test. private final IndependenceTest independenceTest; + // The logger. private final TetradLogger logger = TetradLogger.getInstance(); + // The sepsets from the FAS search. private SepsetMap sepsets; + // The background knowledge. private Knowledge knowledge = new Knowledge(); + // The elapsed time of search. private long elapsedTime; + // The PC heuristic from PC used in search. private PcCommon.PcHeuristicType pcHeuristicType = PcCommon.PcHeuristicType.NONE; + // Whether the stable option will be used for search. private boolean stable = false; + // Whether the discriminating path rule will be used in search. private boolean completeRuleSetUsed = true; + // Whether the discriminating path rule will be used in search. private boolean doDiscriminatingPathRule = false; + // Whether the discriminating path rule will be used in search. private boolean possibleMsepSearchDone = true; + // The maximum length of any discriminating path, or -1 if unlimited. private int maxPathLength = -1; + // The maximum number of variables conditioned in any test. private int depth = -1; + // Whether verbose output should be printed. private boolean verbose = false; - /** * Constructor. */ @@ -91,7 +103,6 @@ public FciMax(IndependenceTest independenceTest) { this.independenceTest = independenceTest; } - /** * Performs the search and returns the PAG. * @@ -142,19 +153,6 @@ public Graph search() { return graph; } - @NotNull - private FciOrient getFciOrient() { - FciOrient fciOrient = new FciOrient(new SepsetsSet(this.sepsets, this.independenceTest)); - - fciOrient.setCompleteRuleSetUsed(this.completeRuleSetUsed); - fciOrient.setMaxPathLength(this.maxPathLength); - fciOrient.setDoDiscriminatingPathColliderRule(this.doDiscriminatingPathRule); - fciOrient.setDoDiscriminatingPathTailRule(this.doDiscriminatingPathRule); - fciOrient.setVerbose(this.verbose); - fciOrient.setKnowledge(this.knowledge); - return fciOrient; - } - /** * Sets the maximum nubmer of variables conditioned in any test. * @@ -287,6 +285,19 @@ public void setDoDiscriminatingPathRule(boolean doDiscriminatingPathRule) { this.doDiscriminatingPathRule = doDiscriminatingPathRule; } + @NotNull + private FciOrient getFciOrient() { + FciOrient fciOrient = new FciOrient(new SepsetsSet(this.sepsets, this.independenceTest)); + + fciOrient.setCompleteRuleSetUsed(this.completeRuleSetUsed); + fciOrient.setMaxPathLength(this.maxPathLength); + fciOrient.setDoDiscriminatingPathColliderRule(this.doDiscriminatingPathRule); + fciOrient.setDoDiscriminatingPathTailRule(this.doDiscriminatingPathRule); + fciOrient.setVerbose(this.verbose); + fciOrient.setKnowledge(this.knowledge); + return fciOrient; + } + private void addColliders(Graph graph) { Map scores = new ConcurrentHashMap<>(); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fges.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fges.java index 3ff6cac8d7..e3324f03e6 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fges.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fges.java @@ -66,8 +66,7 @@ * Also, edges to be added or remove from the graph in the forward or backward phase, respectively are cached, together * with the ancillary information needed to do the additions or removals, to reduce rescoring. *

                - * A number of other optimizations were also. See code for de - * tails. + * A number of other optimizations were also. See code for de tails. *

                * This class is configured to respect knowledge of forbidden and required edges, including knowledge of temporal * tiers. @@ -80,17 +79,16 @@ * @see Knowledge */ public final class Fges implements IGraphSearch, DagScorer { + // Used to find semidirected paths for cycle checking. private final Set emptySet = new HashSet<>(); + // Used to find semidirected paths for cycle checking. private final int[] count = new int[1]; + // Used to find semidirected paths for cycle checking. private final int depth = 10000; - /** - * The logger for this class. The config needs to be set. - */ + // The logger for this class. The config needs to be set. private final TetradLogger logger = TetradLogger.getInstance(); - /** - * The top n graphs found by the algorithm, where n is numPatternsToStore. - */ + // The top n graphs found by the algorithm, where n is numPatternsToStore. private final LinkedList topGraphs = new LinkedList<>(); // Potential arrows sorted by bump high to low. The first one is a candidate for adding to the graph. private final SortedSet sortedArrows = new ConcurrentSkipListSet<>(); @@ -98,63 +96,41 @@ public final class Fges implements IGraphSearch, DagScorer { private final Map arrowsMap = new ConcurrentHashMap<>(); // private final Map arrowsMapBackward = new ConcurrentHashMap<>(); private boolean faithfulnessAssumed = false; - /** - * Specification of forbidden and required edges. - */ + // Specification of forbidden and required edges. private Knowledge knowledge = new Knowledge(); - /** - * List of variables in the data set, in order. - */ + // List of variables in the data set, in order. private List variables; - /** - * An initial graph to start from. - */ + // An initial graph to start from. private Graph initialGraph; - /** - * If non-null, edges not adjacent in this graph will not be added. - */ + // If non-null, edges not adjacent in this graph will not be added. private Graph boundGraph = null; - /** - * Elapsed time of the most recent search. - */ + // Elapsed time of the most recent search. private long elapsedTime; - /** - * The totalScore for discrete searches. - */ + // The totalScore for discrete searches. private Score score; - /** - * True if verbose output should be printed. - */ + // True if verbose output should be printed. private boolean verbose = false; private boolean meekVerbose = false; // Map from variables to their column indices in the data set. private ConcurrentMap hashIndices; // A graph where X--Y means that X and Y have non-zero total effect on one another. private Graph effectEdgesGraph; - // Where printed output is sent. private PrintStream out = System.out; - // The graph being constructed. private Graph graph; - // Arrows with the same totalScore are stored in this list to distinguish their order in sortedArrows. // The ordering doesn't matter; it just has to be transitive. private int arrowIndex = 0; - // The score of the model. private double modelScore; - // Internal. private Mode mode = Mode.heuristicSpeedup; - // Bounds the degree of the graph. private int maxDegree = -1; - // True if the first step of adding an edge to an empty graph should be scored in both directions // for each edge with the maximum score chosen. private boolean symmetricFirstStep = false; - // True, if FGES should run in a single thread, no if parallelized. private boolean parallelized = false; diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/FgesMb.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/FgesMb.java index 8e14453805..cf3940d42c 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/FgesMb.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/FgesMb.java @@ -102,12 +102,19 @@ public final class FgesMb implements DagScorer { private Knowledge knowledge = new Knowledge(); // True, if FGES should run in a single thread, no if parallelized. private boolean parallelized = false; + // The variables to use in the search. private List variables; + // The initial graph. private Graph initialGraph; + // The graph to which the search is bound. private Graph boundGraph = null; + // The elapsed time of the search. private long elapsedTime; + // The score of the graph. private Score score; + // Whether verbose output should be produced. private boolean verbose = false; + // Whether verbose output should be produced for the Meek rules. private boolean meekVerbose = false; // Map from variables to their column indices in the data set. private ConcurrentMap hashIndices; @@ -127,7 +134,9 @@ public final class FgesMb implements DagScorer { // True if the first step of adding an edge to an empty graph should be scored in both directions // for each edge with the maximum score chosen. private boolean symmetricFirstStep = false; + // The list of all targets. private ArrayList allTargets; + /** * Constructor. Construct a Score and pass it in here. The totalScore should return a positive value in case of * conditional dependence and a negative values in case of conditional independence. See Chickering (2002), locally @@ -145,21 +154,6 @@ public FgesMb(Score score) { this.graph = new EdgeListGraph(getVariables()); } - // Used to find semidirected paths for cycle checking. - private static Node traverseSemiDirected(Node node, Edge edge) { - if (node == edge.getNode1()) { - if (edge.getEndpoint1() == Endpoint.TAIL) { - return edge.getNode2(); - } - } else if (node == edge.getNode2()) { - if (edge.getEndpoint2() == Endpoint.TAIL) { - return edge.getNode1(); - } - } - - return null; - } - public void setTrimmingStyle(int trimmingStyle) { this.trimmingStyle = trimmingStyle; } @@ -385,7 +379,6 @@ public void setSymmetricFirstStep(boolean symmetricFirstStep) { this.symmetricFirstStep = symmetricFirstStep; } - /** * Returns the score of the final search model. * @@ -395,6 +388,21 @@ public double getModelScore() { return modelScore; } + // Used to find semidirected paths for cycle checking. + private static Node traverseSemiDirected(Node node, Edge edge) { + if (node == edge.getNode1()) { + if (edge.getEndpoint1() == Endpoint.TAIL) { + return edge.getNode2(); + } + } else if (node == edge.getNode2()) { + if (edge.getEndpoint2() == Endpoint.TAIL) { + return edge.getNode1(); + } + } + + return null; + } + //Sets the discrete scoring function to use. private void setScore(Score score) { this.score = score; diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fofc.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fofc.java index 220126cb0d..c946077d0a 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fofc.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fofc.java @@ -173,6 +173,17 @@ public void setCheckType(ClusterSignificance.CheckType checkType) { this.checkType = checkType; } + /** + * The clusters that are output by the algorithm from the last call to search(). + */ + public List> getClusters() { + return this.clusters; + } + + public void setVerbose(boolean verbose) { + this.verbose = verbose; + } + // renjiey private int findFrequentestIndex(Integer[] outliers) { Map map = new HashMap<>(); @@ -944,17 +955,6 @@ private boolean zeroCorr(List cluster) { return count >= 1; } - /** - * The clusters that are output by the algorithm from the last call to search(). - */ - public List> getClusters() { - return this.clusters; - } - - public void setVerbose(boolean verbose) { - this.verbose = verbose; - } - private boolean vanishes(int x, int y, int z, int w) { if (this.testType == BpcTestType.TETRAD_DELTA) { Tetrad t1 = new Tetrad(this.variables.get(x), this.variables.get(y), this.variables.get(z), this.variables.get(w)); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Ftfc.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Ftfc.java index a67da120c8..ecf51b231f 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Ftfc.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Ftfc.java @@ -63,7 +63,7 @@ * @see Bpc */ public class Ftfc { - + // The correlation matrix. private final CorrelationMatrix corr; // The list of all variables. private final List variables; @@ -73,9 +73,11 @@ public class Ftfc { private final DeltaSextadTest test; // The data. private final transient DataModel dataModel; + // The algorithm used. private final Algorithm algorithm; + // The clusters found. private List> clusters; - + // Whether verbose output should be printed. private boolean verbose; /** diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/GFci.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/GFci.java index b8a2d053b8..4c9c8d55c0 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/GFci.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/GFci.java @@ -69,18 +69,29 @@ * @see Knowledge */ public final class GFci implements IGraphSearch { + // The independence test used in search. private final IndependenceTest independenceTest; + // The logger. private final TetradLogger logger = TetradLogger.getInstance(); + // The score used in search. private final Score score; + // The knowledge used in search. private Knowledge knowledge = new Knowledge(); + // Whether Zhang's complete rules are used. private boolean completeRuleSetUsed = true; + // The maximum path length for the discriminating path rule. private int maxPathLength = -1; + // The maximum degree of the output graph. private int maxDegree = -1; + // Whether verbose output should be printed. private boolean verbose; + // The print stream used for output. private PrintStream out = System.out; + // Whether one-edge faithfulness is assumed. private boolean faithfulnessAssumed = true; + // Whether the discriminating path rule should be used. private boolean doDiscriminatingPathRule = true; - private boolean possibleMsepSearchDone = true; + // The depth of the search for the possible m-sep search. private int depth = -1; @@ -252,7 +263,6 @@ public void setDoDiscriminatingPathRule(boolean doDiscriminatingPathRule) { * @param possibleMsepSearchDone True, if so. */ public void setPossibleMsepSearchDone(boolean possibleMsepSearchDone) { - this.possibleMsepSearchDone = possibleMsepSearchDone; } /** diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Grasp.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Grasp.java index d545f942fb..f22e4c0215 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Grasp.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Grasp.java @@ -53,21 +53,37 @@ * @see Knowledge */ public class Grasp { + // The variables to be permuted. private final List variables; + // The score or test to be used. private Score score; + // The test to be used. private IndependenceTest test; + // The knowledge to be used. private Knowledge knowledge = new Knowledge(); + // The scorer to be used. private TeyssierScorer scorer; + // The time at which the algorithm started. private long start; + // Whether to use the score or the test. private boolean useScore = true; + // Whether to use the Raskutti-Uhler method or the Verma-Pearl method. private boolean useRaskuttiUhler; + // Whether to impose an ordering on the three GRaSP algorithms. private boolean ordered = false; + // Whether to use verbose output. private boolean verbose; + // The maximum depth of the depth-first search for tucks. private int uncoveredDepth = 1; + // The maximum depth of the depth-first search for uncovered tucks. private int nonSingularDepth = 1; + // Whether to use the data order or a random order for the initial permutation. private boolean useDataOrder = true; + // The maximum depth of the depth-first search for singular tucks. private int depth = 3; + // The number of times to run the algorithm with different starting permutations. private int numStarts = 1; + // Whether to allow internal randomness in the algorithm. private boolean allowInternalRandomness = false; /** @@ -188,11 +204,7 @@ public int getNumEdges() { @NotNull public Graph getGraph(boolean cpDag) { if (this.scorer == null) throw new IllegalArgumentException("Please run algorithm first."); - Graph graph = this.scorer.getGraph(cpDag); - -// NumberFormat nf = NumberFormatUtil.getInstance().getNumberFormat(); -// graph.addAttribute("score ", nf.format(this.scorer.score())); - return graph; + return this.scorer.getGraph(cpDag); } /** diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/GraspFci.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/GraspFci.java index 809260a4ef..ca9ddd6f21 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/GraspFci.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/GraspFci.java @@ -75,16 +75,32 @@ public final class GraspFci implements IGraphSearch { private int maxPathLength = -1; // True iff verbose output should be printed. private boolean verbose; + // The number of starts for GRaSP. private int numStarts = 1; - private int depth = -1; + + // Whether to use Raskutti and Uhler's modification of GRaSP. private boolean useRaskuttiUhler = false; + // Whether to use data order. private boolean useDataOrder = true; + // Whether to use score. private boolean useScore = true; + // Whether to use the discriminating path rule. private boolean doDiscriminatingPathRule = true; + // Whether to use the ordered version of GRaSP. private boolean ordered = false; + // The depth for GRaSP. + private int depth = -1; + // The depth for singular variables. private int uncoveredDepth = 1; + // The depth for non-singular variables. private int nonSingularDepth = 1; + /** + * Constructs a new GraspFci object. + * + * @param test The independence test. + * @param score + */ public GraspFci(IndependenceTest test, Score score) { if (score == null) { throw new NullPointerException(); @@ -193,40 +209,85 @@ public void setVerbose(boolean verbose) { this.verbose = verbose; } + /** + * Sets the number of starts for GRaSP. + * + * @param numStarts The number of starts. + */ public void setNumStarts(int numStarts) { this.numStarts = numStarts; } + /** + * Sets the depth for GRaSP. + * + * @param depth The depth. + */ public void setDepth(int depth) { this.depth = depth; } + /** + * Sets whether to use Raskutti and Uhler's modification of GRaSP. + * + * @param useRaskuttiUhler True, if so. + */ public void setUseRaskuttiUhler(boolean useRaskuttiUhler) { this.useRaskuttiUhler = useRaskuttiUhler; } + /** + * Sets whether to use data order for GRaSP (as opposed to random order) for the first step of GRaSP + * + * @param useDataOrder True, if so. + */ public void setUseDataOrder(boolean useDataOrder) { this.useDataOrder = useDataOrder; } + /** + * Sets whether to use score for GRaSP (as opposed to independence test) for GRaSP. + * + * @param useScore True, if so. + */ public void setUseScore(boolean useScore) { this.useScore = useScore; } + /** + * Sets whether to use the discriminating path rule for GRaSP. + * + * @param doDiscriminatingPathRule True, if so. + */ public void setDoDiscriminatingPathRule(boolean doDiscriminatingPathRule) { this.doDiscriminatingPathRule = doDiscriminatingPathRule; } + /** + * Sets depth for singular tucks. + * + * @param uncoveredDepth The depth for singular tucks. + */ public void setSingularDepth(int uncoveredDepth) { if (uncoveredDepth < -1) throw new IllegalArgumentException("Uncovered depth should be >= -1."); this.uncoveredDepth = uncoveredDepth; } + /** + * Sets depth for non-singular tucks. + * + * @param nonSingularDepth The depth for non-singular tucks. + */ public void setNonSingularDepth(int nonSingularDepth) { if (nonSingularDepth < -1) throw new IllegalArgumentException("Non-singular depth should be >= -1."); this.nonSingularDepth = nonSingularDepth; } + /** + * Sets whether to use the ordered version of GRaSP. + * + * @param ordered True, if so. + */ public void setOrdered(boolean ordered) { this.ordered = ordered; } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/GrowShrink.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/GrowShrink.java index dec7605616..93f8138f1c 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/GrowShrink.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/GrowShrink.java @@ -57,16 +57,9 @@ */ public class GrowShrink implements IMbSearch { - /** - * The independence test used to perform the search. - */ + // The independence test used to perform the search. private final IndependenceTest independenceTest; - /** - * The list of variables being searched over. Must contain the target. - */ - private final List variables; - /** * Constructs a new search. * @@ -78,7 +71,8 @@ public GrowShrink(IndependenceTest test) { } this.independenceTest = test; - this.variables = test.getVariables(); + // The list of variables being searched over. Must contain the target. + List variables = test.getVariables(); } /** @@ -107,40 +101,6 @@ public Set findMb(Node target) { } } -// boolean changed = true; -// -// while (changed) { -// changed = false; -// -// List remaining = new LinkedList<>(this.variables); -// remaining.removeAll(blanket); -// remaining.remove(target); -// -// for (Node node : remaining) { -// if (!this.independenceTest.checkIndependence(node, target, blanket).isIndependent()) { -// blanket.add(node); -// changed = true; -// } -// } -// } -// -// changed = true; -// -// while (changed) { -// changed = false; -// -// for (Node node : new LinkedList<>(blanket)) { -// blanket.remove(node); -// -// if (this.independenceTest.checkIndependence(node, target, blanket).isIndependent()) { -// changed = true; -// continue; -// } -// -// blanket.add(node); -// } -// } - return blanket; } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/IcaLingD.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/IcaLingD.java index 4b11055d1a..5def17ef13 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/IcaLingD.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/IcaLingD.java @@ -96,7 +96,9 @@ * @see IcaLingam */ public class IcaLingD { + // The threshold for the spine of the W matrix. private double spineThreshold = 0.5; + // The threshold to use for set small elements to zero in the B Hat matrices. private double bThreshold = 0.1; /** diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/IcaLingam.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/IcaLingam.java index 43b21f55dd..5d07a078fc 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/IcaLingam.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/IcaLingam.java @@ -93,7 +93,9 @@ * @see edu.cmu.tetrad.search.utils.HungarianAlgorithm */ public class IcaLingam { + // The threshold to use for set small elements to zero in the B Hat matrices. private double bThreshold = 0.1; + // Whether the ICA-LiNGAM algorithm is guaranteed to produce an acyclic graph. private boolean acyclicityGuaranteed = true; /** diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Ida.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Ida.java index 383d495ba0..ce897e3353 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Ida.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Ida.java @@ -33,10 +33,15 @@ * @see NodeEffects */ public class Ida { + // The dataset being searched over. private final DataSet dataSet; - private final Graph pattern; + // The CPDAG (found, e.g., by running PC, or some other CPDAG producing algorithm. + private final Graph cpdag; + // The possible causes to be considered. private final List possibleCauses; + // A map from node names to indices in the covariance matrix. private final Map nodeIndices; + // The covariance matrix for the dataset. private final ICovarianceMatrix allCovariances; /** @@ -48,7 +53,7 @@ public class Ida { */ public Ida(DataSet dataSet, Graph cpdag, List possibleCauses) { this.dataSet = DataTransforms.convertNumericalDiscreteToContinuous(dataSet); - this.pattern = cpdag; + this.cpdag = cpdag; possibleCauses = GraphUtils.replaceNodes(possibleCauses, dataSet.getVariables()); this.possibleCauses = possibleCauses; @@ -146,10 +151,10 @@ public double distance(LinkedList effects, double trueEffect) { * @return a list of the possible effects of X on Y. */ private LinkedList getEffects(Node x, Node y) { - List parents = this.pattern.getParents(x); - List children = this.pattern.getChildren(x); + List parents = this.cpdag.getParents(x); + List children = this.cpdag.getChildren(x); - List siblings = new ArrayList<>(this.pattern.getAdjacentNodes(x)); + List siblings = new ArrayList<>(this.cpdag.getAdjacentNodes(x)); siblings.removeAll(parents); siblings.removeAll(children); @@ -169,14 +174,14 @@ private LinkedList getEffects(Node x, Node y) { while ((choice2 = gen2.next()) != null) { List adj = GraphUtils.asList(choice2, sibbled); - if (!this.pattern.isAdjacentTo(adj.get(0), adj.get(1))) continue CHOICE; + if (!this.cpdag.isAdjacentTo(adj.get(0), adj.get(1))) continue CHOICE; } } if (!sibbled.isEmpty()) { for (Node p : parents) { for (Node s : sibbled) { - if (!this.pattern.isAdjacentTo(p, s)) continue CHOICE; + if (!this.cpdag.isAdjacentTo(p, s)) continue CHOICE; } } } @@ -211,7 +216,7 @@ public Map calculateMinimumEffectsOnY(Node y) { SortedMap minEffects = new TreeMap<>(); for (Node x : this.possibleCauses) { - if (!(this.pattern.containsNode(x) && this.pattern.containsNode(y))) continue; + if (!(this.cpdag.containsNode(x) && this.cpdag.containsNode(y))) continue; LinkedList effects = getEffects(x, y); minEffects.put(x, effects.getFirst()); @@ -251,30 +256,63 @@ private double getBeta(List regressors, Node child) { * @author josephramsey */ public static class NodeEffects { + // The nodes. private List nodes; + // The effects. private LinkedList effects; + /** + * Constructor. + * + * @param nodes The nodes. + * @param effects The effects. + */ NodeEffects(List nodes, LinkedList effects) { this.setNodes(nodes); this.setEffects(effects); } + /** + * Returns the nodes. + * + * @return The nodes. + */ public List getNodes() { return this.nodes; } + /** + * Sets the nodes. + * + * @param nodes The nodes. + */ public void setNodes(List nodes) { this.nodes = nodes; } + /** + * Returns the effects. + * + * @return The effects. + */ public LinkedList getEffects() { return this.effects; } + /** + * Sets the effects. + * + * @param effects The effects. + */ public void setEffects(LinkedList effects) { this.effects = effects; } + /** + * Returns a string representation of this object. + * + * @return A string representation of this object. + */ public String toString() { StringBuilder b = new StringBuilder(); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/IndTestIod.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/IndTestIod.java index eb68e3b77d..bd8d625afe 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/IndTestIod.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/IndTestIod.java @@ -49,8 +49,11 @@ * @author josephramsey */ public class IndTestIod implements IndependenceTest { + // The list of nodes over which this independence checker is capable of determining independence relations. private final List nodeList; + // The list of independence tests. private final List tests; + // Whether the test is verbose. private boolean verbose; /** diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Lofs.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Lofs.java index 9db0a96400..27f6769d37 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Lofs.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Lofs.java @@ -59,22 +59,37 @@ * @see Knowledge */ public class Lofs { - + // The graph to be oriented. private final Graph cpdag; + // The square root of 2 * pi. private final double SQRT = sqrt(2. * PI); + // The data to use to do the orientation. Matrix _data; + // The data to use to do the orientation. private List dataSets; + // The matrices to use to do the orientation. private List matrices; + // The alpha to use, where applicable. private double alpha = 1.1; + // The regressions to use to do the orientation. private List regressions; + // The variables to use to do the orientation. private List variables; + // Whether orientation should be done in the stronger direction, where applicable. private boolean orientStrongerDirection; + // For R2, whether cycles should be oriented. private boolean r2Orient2Cycles = true; + // The (LoFS) score to use. private Lofs.Score score = Lofs.Score.andersonDarling; + // The self-loop strength, if applicable. private double epsilon = 1.0; + // The knowledge to use to do the orientation. private Knowledge knowledge = new Knowledge(); + // The rule to use to do the orientation. private Rule rule = Rule.R1; + // The number of variables. private double selfLoopStrength; + // The number of variables. private double[] col; /** diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Mimbuild.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Mimbuild.java index 92bbe4c78e..a93065d59a 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Mimbuild.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Mimbuild.java @@ -68,37 +68,28 @@ * @see Knowledge */ public class Mimbuild { - - /** - * The clustering from BPC or equivalent. Small clusters are removed. - */ + // The clustering from BPC or equivalent. Small clusters are removed. private List> clustering; - - /** - * The graph over the latents. - */ + // The graph over the latents. private Graph structureGraph; - - /** - * Background knowledge for CPC. - */ + // Background knowledge for CPC. private Knowledge knowledge = new Knowledge(); - + // The covariance matrix over the latent variables. private ICovarianceMatrix latentsCov; - - /** - * The minimum function (Fgsl) value achieved. - */ + // The minimum function (Fgsl) value achieved. private double minimum; - - /** - * The p value of the optimization. - */ + // The p value of the optimization. private double pValue; + // The latents. private List latents; + // The penalty discount of the score used to infer the structure graph. private double penaltyDiscount = 1; + // jf Clusters smaller than this size will be tossed out. private int minClusterSize = 3; + /** + * Constructs a new Mimbuild search. + */ public Mimbuild() { } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MimbuildTrek.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MimbuildTrek.java index 91549470d5..466adb3531 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MimbuildTrek.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MimbuildTrek.java @@ -52,48 +52,31 @@ * @see Mimbuild */ public class MimbuildTrek { - - /** - * The clustering from BPC or equivalent. Small clusters are removed. - */ + // The clustering from BPC or equivalent. Small clusters are removed. private List> clustering; - - /** - * The graph over the latents. - */ + // The graph over the latents. private Graph structureGraph; - - /** - * The alpha level used for CPC - */ + // The alpha level used for CPC private double alpha = 0.001; - - /** - * Background knowledge for CPC. - */ + // Background knowledge for CPC. private Knowledge knowledge = new Knowledge(); - - /** - * The estimated covariance matrix over the latents. - */ + // The estimated covariance matrix over the latents. private ICovarianceMatrix latentsCov; - - /** - * The minimum function (Fgsl) value achieved. - */ + // The minimum function (Fgsl) value achieved. private double minimum; - - /** - * The p value of the optimization. - */ + // The p value of the optimization. private double pValue; + // The latents. private List latents; + // The minimum cluster size. private int minClusterSize = 3; + /** + * Empty constructor. + */ public MimbuildTrek() { } - /** * Does the search and returns the graph. * diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MixtureModel.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MixtureModel.java index 8a1516ef38..f110a32cc8 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MixtureModel.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/MixtureModel.java @@ -14,16 +14,36 @@ * @author Madelyn Glymour */ public class MixtureModel { + // The mixed data set private final DataSet data; + // The individual data sets private final int[] cases; + // The number of cases in each individual data set private final int[] caseCounts; - private final double[][] dataArray; // v-by-n data matrix - private final double[][] meansArray; // k-by-v matrix representing means for each variable for each of k models - private final double[] weightsArray; // array of length k representing weights for each model - private final double[][] gammaArray; // k-by-n matrix representing gamma for each data case in each model - private final Matrix[] variancesArray; // k-by-v-by-v matrix representing covariance matrix for each of k models - private final int numModels; // number of models in mixture + // The data set in array form + private final double[][] dataArray; + // The means matrix + private final double[][] meansArray; + // The weights array + private final double[] weightsArray; + // The gamma matrix + private final double[][] gammaArray; + // The variance matrix + private final Matrix[] variancesArray; + // The number of models in the mixture + private final int numModels; + /** + * Constructs a mixture model from a mixed data set, a means matrix, a weights array, a variance matrix, and a gamma + * matrix. + * + * @param data the mixed data set + * @param dataArray the mixed data set in array form + * @param meansArray the means matrix + * @param weightsArray the weights array + * @param variancesArray the variance matrix + * @param gammaArray the gamma matrix + */ public MixtureModel(DataSet data, double[][] dataArray, double[][] meansArray, double[] weightsArray, Matrix[] variancesArray, double[][] gammaArray) { this.data = data; this.dataArray = dataArray; diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Pc.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Pc.java index 09aa7ca802..9d4cacc354 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Pc.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Pc.java @@ -63,22 +63,35 @@ * @see Knowledge */ public class Pc implements IGraphSearch { + // The oracle for conditional independence facts. private final IndependenceTest independenceTest; + // The logger. private final TetradLogger logger = TetradLogger.getInstance(); + // The knowledge specification. private Knowledge knowledge = new Knowledge(); + // The sepset map from the most recent search. private SepsetMap sepsets; + // The depth of the search. private int depth = 1000; + // The graph from the most recent search. private Graph graph; + // The elapsed time of the most recent search. private long elapsedTime; + // The number of independence tests performed in the most recent search. private int numIndependenceTests; + // Whether the search is verbose. private boolean verbose = false; + // The rule to use for resolving collider orientation conflicts. private PcCommon.ConflictRule conflictRule = PcCommon.ConflictRule.PRIORITIZE_EXISTING; + // Whether the stable adjacency search should be used. private boolean stable = true; + // Whether cycles should be checked in the Meek rules. private boolean meekPreventCycles = true; + // Whether the max-p heuristic should be used for collider discovery. private boolean useMaxPHeuristic = false; + // The PC heuristic type. private PcCommon.PcHeuristicType pcHeuristicType = PcCommon.PcHeuristicType.NONE; - /** * Constructs a new PC search using the given independence test as oracle. * diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/PcMb.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/PcMb.java index e1c3ca3158..d64af8b2cf 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/PcMb.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/PcMb.java @@ -48,63 +48,37 @@ */ public final class PcMb implements IMbSearch, IGraphSearch { - /** - * The independence test used to perform the search. - */ + // The independence test used to perform the search. private final IndependenceTest test; - /** - * The logger for this class. The config needs to be set. - */ + // The logger for this class. The config needs to be set. private final TetradLogger logger = TetradLogger.getInstance(); - /** - * The list of variables being searched over. Must contain the target. - */ + // The list of variables being searched over. Must contain the target. private List variables; - /** - * The target variable. - */ + // The target variable. private List targets; - /** - * The depth to which independence tests should be performed--i.e., the maximum number of conditioning variables for - * any independence test. - */ + // The depth to which independence tests should be performed--i.e., the maximum number of conditioning variables for + // any independence test. private int depth; - /** - * The CPDAG output by the most recent search. This is saved in case the user wants to generate the list of MB - * DAGs. - */ + // The CPDAG output by the most recent search. This is saved in case the user wants to generate the list of MB + // DAGs. private Graph resultGraph; - /** - * A count of the number of independence tests performed in the course of the most recent search. - */ + // A count of the number of independence tests performed in the course of the most recent search. private int numIndependenceTests; - /** - * Information to help understand what part of the search is taking the most time. - */ + // Information to help understand what part of the search is taking the most time. private int[] maxRemainingAtDepth; - /** - * The set of nodes that edges should not be drawn to in the addDepthZeroAssociates method. - */ + // The set of nodes that edges should not be drawn to in the addDepthZeroAssociates method. private Set a; - /** - * Elapsed time for the last run of the algorithm. - */ + // Elapsed time for the last run of the algorithm. private long elapsedTime; - /** - * Knowledge. - */ + // Knowledge. private Knowledge knowledge = new Knowledge(); - /** - * Set of ambiguous unshielded triples. - */ + // Set of ambiguous unshielded triples. private Set ambiguousTriples; - /** - * True if cycles are to be prevented. Maybe expensive for large graphs (but also useful for large graphs). - */ + // True if cycles are to be prevented. Maybe expensive for large graphs (but also useful for large graphs). private boolean meekPreventCycles; + // True if the search should return the MB, not the MB CPDAG. private boolean findMb = false; - /** * Constructs a new search. * @@ -129,17 +103,6 @@ public PcMb(IndependenceTest test, int depth) { this.variables = test.getVariables(); } - - private static boolean isArrowheadAllowed1(Node from, Node to, - Knowledge knowledge) { - if (knowledge == null) { - return true; - } - - return !knowledge.isRequired(to.toString(), from.toString()) && - !knowledge.isForbidden(from.toString(), to.toString()); - } - /** * Sets whether cycles should be prevented, using a cycle checker. * @@ -348,8 +311,6 @@ public Graph search() { this.maxRemainingAtDepth = new int[20]; Arrays.fill(this.maxRemainingAtDepth, -1); -// logger.info("target = " + getTarget()); - Graph graph = new EdgeListGraph(); // Each time the addDepthZeroAssociates method is called for a node @@ -510,6 +471,17 @@ public void setKnowledge(Knowledge knowledge) { this.knowledge = new Knowledge(knowledge); } + private static boolean isArrowheadAllowed1(Node from, Node to, + Knowledge knowledge) { + if (knowledge == null) { + return true; + } + + return !knowledge.isRequired(to.toString(), from.toString()) && + !knowledge.isForbidden(from.toString(), to.toString()); + } + + private Set getA() { return this.a; } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Pcd.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Pcd.java index b96e706cc8..f1925815e3 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Pcd.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Pcd.java @@ -53,58 +53,33 @@ */ public class Pcd implements IGraphSearch { - /** - * The independence test used for the PC search. - */ + // The independence test used for the PC search. private final IndependenceTest independenceTest; - /** - * The logger for this class. The config needs to be set. - */ + // The logger for this class. The config needs to be set. private final TetradLogger logger = TetradLogger.getInstance(); - /** - * Forbidden and required edges for the search. - */ + // Forbidden and required edges for the search. private Knowledge knowledge = new Knowledge(); - /** - * Sepset information accumulated in the search. - */ + // Sepset information accumulated in the search. private SepsetMap sepsets; - /** - * The maximum number of nodes conditioned on in the search. The default it 1000. - */ + // The maximum number of nodes conditioned on in the search. The default it 1000. private int depth = 1000; - /** - * The graph that's constructed during the search. - */ + // The graph that's constructed during the search. private Graph graph; - /** - * Elapsed time of the most recent search. - */ + // Elapsed time of the most recent search. private long elapsedTime; - /** - * True if cycles are to be prevented. Maybe expensive for large graphs (but also useful for large graphs). - */ + // True if cycles are to be prevented. Maybe expensive for large graphs (but also useful for large graphs). private boolean meekPreventCycles; - /** - * In an enumeration of triple types, these are the collider triples. - */ + // In an enumeration of triple types, these are the collider triples. private Set unshieldedColliders; - - /** - * In an enumeration of triple types, these are the noncollider triples. - */ + // In an enumeration of triple types, these are the noncollider triples. private Set unshieldedNoncolliders; - - /** - * The number of independence tests in the last search. - */ + // The number of independence tests in the last search. private int numIndependenceTests; - + // True iff the algorithm should be run with verbose output. private boolean verbose; - + // True iff the algorithm should be run with False Discovery Rate tests. private boolean fdr; - /** * Constructs a new PC search using the given independence test as oracle. * @@ -290,10 +265,64 @@ public Set getUnshieldedNoncolliders() { return this.unshieldedNoncolliders; } + /** + * @return the graph returned by search(). Non-null after search is called. + */ public Set getAdjacencies() { return new HashSet<>(this.graph.getEdges()); } + /** + * @return the number of independence tests performed in the last search. + */ + public int getNumIndependenceTests() { + return this.numIndependenceTests; + } + + /** + * @return the list of nodes in the graph returned by search(). Non-null after search is + * called. + */ + public List getNodes() { + return this.graph.getNodes(); + } + + /** + * True iff the algorithm should be run with verbose output. + * + * @return True, if so. + */ + public boolean isVerbose() { + return this.verbose; + } + + /** + * Sets whether this test will print verbose output. + * + * @param verbose True, if so. + */ + public void setVerbose(boolean verbose) { + this.verbose = verbose; + } + + /** + * True iff the algorithm should be run with False Discovery Rate tests. + * + * @return True, if so. + */ + public boolean isFdr() { + return this.fdr; + } + + /** + * Sets whether this test will run with False Discovery Rate tests. + * + * @param fdr True, if so. + */ + public void setFdr(boolean fdr) { + this.fdr = fdr; + } + private void enumerateTriples() { this.unshieldedColliders = new HashSet<>(); this.unshieldedNoncolliders = new HashSet<>(); @@ -328,33 +357,6 @@ private void enumerateTriples() { } } } - - public int getNumIndependenceTests() { - return this.numIndependenceTests; - } - - public List getNodes() { - return this.graph.getNodes(); - } - - public boolean isVerbose() { - return this.verbose; - } - - public void setVerbose(boolean verbose) { - this.verbose = verbose; - } - - /** - * True iff the algorithm should be run with False Discovery Rate tests. - */ - public boolean isFdr() { - return this.fdr; - } - - public void setFdr(boolean fdr) { - this.fdr = fdr; - } } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Rfci.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Rfci.java index 4b9697325b..ce45162a86 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Rfci.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Rfci.java @@ -53,46 +53,27 @@ * @see Knowledge */ public final class Rfci implements IGraphSearch { - - /** - * The variables to search over (optional) - */ + // The variables to search over (optional) private final List variables = new ArrayList<>(); + // The independence test to use. private final IndependenceTest independenceTest; - /** - * The logger to use. - */ + // The logger to use. private final TetradLogger logger = TetradLogger.getInstance(); - /** - * The RFCI-PAG being constructed. - */ + // The RFCI-PAG being constructed. private Graph graph; - /** - * The SepsetMap being constructed. - */ + // The SepsetMap being constructed. private SepsetMap sepsets; - /** - * The background knowledge. - */ + // The background knowledge. private Knowledge knowledge = new Knowledge(); - /** - * The maximum length for any discriminating path. -1 if unlimited; otherwise, a positive integer. - */ + // The maximum length for any discriminating path. -1 if unlimited; otherwise, a positive integer. private int maxPathLength = -1; - /** - * The depth for the fast adjacency search. - */ + // The depth for the fast adjacency search. private int depth = -1; - /** - * Elapsed time of last search. - */ + // Elapsed time of last search. private long elapsedTime; - /** - * True iff verbose output should be printed. - */ + // True iff verbose output should be printed. private boolean verbose; - /** * Constructs a new RFCI search for the given independence test and background knowledge. */ diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Sp.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Sp.java index b2a2178065..0fb827d062 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Sp.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Sp.java @@ -38,10 +38,15 @@ * @see Knowledge */ public class Sp implements SuborderSearch { + // The score to use. private final Score score; + // The variables to search over. private final List variables; + // The parents of each variable. private final Map> parents; + // The GrowShrinkTree for each variable. private Map gsts; + // The knowledge. private Knowledge knowledge = new Knowledge(); /** @@ -106,6 +111,46 @@ public void searchSuborder(List prefix, List suborder, Map getVariables() { + return variables; + } + + /** + * Returns the parents of each variable. + * + * @return The parents of each variable. + */ + @Override + public Map> getParents() { + return parents; + } + + /** + * Returns the score being used. + * + * @return The score being used. + */ + @Override + public Score getScore() { + return score; + } + + /** + * Returns the knowledge being used. + * + * @return The knowledge being used. + */ + @Override + public void setKnowledge(Knowledge knowledge) { + this.knowledge = knowledge; + } + private void makeValidKnowledgeOrder(List order) { if (!this.knowledge.isEmpty()) { order.sort((a, b) -> { @@ -131,10 +176,6 @@ private boolean violatesKnowledge(List suborder, Map> requ return false; } - @Override - public void setKnowledge(Knowledge knowledge) { - this.knowledge = knowledge; - } private double update(List prefix, List suborder) { double score = 0; @@ -153,21 +194,6 @@ private double update(List prefix, List suborder) { return score; } - @Override - public List getVariables() { - return variables; - } - - @Override - public Map> getParents() { - return parents; - } - - @Override - public Score getScore() { - return score; - } - static class SwapIterator implements Iterator { private final int n; diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SvarFas.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SvarFas.java index a6e0853301..c3cb31c0c8 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SvarFas.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SvarFas.java @@ -59,51 +59,35 @@ */ public class SvarFas implements IFas { - /** - * The search graph. It is assumed going in that all the true adjacencies of x are in this graph for every node x. - * It is hoped (i.e., true in the large sample limit) that true adjacencies are never removed. - */ + // The search graph. It is assumed going in that all the true adjacencies of x are in this graph for every node x. + // It is hoped (i.e., true in the large sample limit) that true adjacencies are never removed. private final Graph graph; - - /** - * The independence test. This should be appropriate to the types - */ + //The independence test. This should be appropriate to the types private final IndependenceTest test; - /** - * The logger, by default the empty logger. - */ + // The logger, by default the empty logger. private final TetradLogger logger = TetradLogger.getInstance(); + // The number formatter. private final NumberFormat nf = new DecimalFormat("0.00E0"); - /** - * Specification of which edges are forbidden or required. - */ + // Specification of which edges are forbidden or required. private Knowledge knowledge = new Knowledge(); - /** - * The maximum number of variables conditioned on in any conditional independence test. If the depth is -1, it will - * be taken to be the maximum value, which is 1000. Otherwise, it should be set to a non-negative integer. - */ + // The maximum number of variables conditioned on in any conditional independence test. If the depth is -1, it will + // be taken to be the maximum value, which is 1000. Otherwise, it should be set to a non-negative integer. private int depth = 1000; - /** - * The number of independence tests. - */ + // The number of independence tests. private int numIndependenceTests; - /** - * The sepsets found during the search. - */ + // The sepsets found during the search. private SepsetMap sepset = new SepsetMap(); - /** - * The depth 0 graph, specified initially. - */ + // The depth 0 graph, specified initially. private Graph externalGraph; - /** - * True iff verbose output should be printed. - */ + // True iff verbose output should be printed. private boolean verbose; - + // The output stream for printing. private PrintStream out = System.out; /** * Constructs a new FastAdjacencySearch. + * + * @param test The independence test. */ public SvarFas(IndependenceTest test) { this.graph = new EdgeListGraph(test.getVariables()); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SvarFci.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SvarFci.java index 30a9f28911..d8543867e6 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SvarFci.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SvarFci.java @@ -62,42 +62,25 @@ * @see Knowledge */ public final class SvarFci implements IGraphSearch { - + // The independence test to use. private final IndependenceTest independenceTest; - /** - * The logger to use. - */ + // The logger to use. private final TetradLogger logger = TetradLogger.getInstance(); - /** - * The PAG being constructed. - */ + // The PAG being constructed. private Graph graph; - /** - * The SepsetMap being constructed. - */ + // The SepsetMap being constructed. private SepsetMap sepsets; - /** - * The background knowledge. - */ + // The background knowledge. private Knowledge knowledge = new Knowledge(); - /** - * flag for the complete rule set, true if it should use the complete rule set, false otherwise. - */ + // flag for the complete rule set, true if it should use the complete rule set, false otherwise. private boolean completeRuleSetUsed; - /** - * The maximum length for any discriminating path. -1 if unlimited; otherwise, a positive integer. - */ + // The maximum length for any discriminating path. -1 if unlimited; otherwise, a positive integer. private int maxPathLength = -1; - /** - * The depth for the fast adjacency search. - */ + // The depth for the fast adjacency search. private int depth = -1; - /** - * True iff verbose output should be printed. - */ + // True iff verbose output should be printed. private boolean verbose; - /** * Constructs a new FCI search for the given independence test and background knowledge. */ diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SvarFges.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SvarFges.java index b389ceceb7..38beed4064 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SvarFges.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SvarFges.java @@ -62,54 +62,37 @@ */ public final class SvarFges implements IGraphSearch, DagScorer { + // The number of threads to use. final int maxThreads = ForkJoinPoolInstance.getInstance().getPool().getParallelism(); - /** - * The logger for this class. The config needs to be set. - */ + // The logger for this class. The config needs to be set. private final TetradLogger logger = TetradLogger.getInstance(); - /** - * The top n graphs found by the algorithm, where n is numCPDAGsToStore. - */ + // The top n graphs found by the algorithm, where n is numCPDAGsToStore. private final LinkedList topGraphs = new LinkedList<>(); // The static ForkJoinPool instance. private final ForkJoinPool pool = ForkJoinPoolInstance.getInstance().getPool(); + // The number of graphs searched. private final int[] count = new int[1]; // Arrows with the same totalScore are stored in this list to distinguish their order in sortedArrows. // The ordering doesn't matter; it just has to be transitive. - int arrowIndex; - Set removedEdges = new HashSet<>(); - /** - * Specification of forbidden and required edges. - */ + private int arrowIndex; + // The set of removed edges. + private Set removedEdges = new HashSet<>(); + // Specification of forbidden and required edges. private Knowledge knowledge = new Knowledge(); - /** - * List of variables in the data set, in order. - */ + // List of variables in the data set, in order. private List variables; - /** - * The true graph, if known. If this is provided, asterisks will be printed out next to false positive added edges - * (that is, edges added that aren't adjacencies in the true graph). - */ + // The true graph, if known. If this is provided, asterisks will be printed out next to false positive added edges + // (that is, edges added that aren't adjacencies in the true graph). private Graph trueGraph; - /** - * An initial graph to start from. - */ + // An initial graph to start from. private Graph externalGraph; - /** - * Elapsed time of the most recent search. - */ + // Elapsed time of the most recent search. private long elapsedTime; - /** - * The totalScore for discrete searches. - */ + // The totalScore for discrete searches. private Score score; - /** - * The number of top CPDAGs to store. - */ + // The number of top CPDAGs to store. private int numCPDAGsToStore; - /** - * True if verbose output should be printed. - */ + // True if verbose output should be printed. private boolean verbose; // Potential arrows sorted by bump high to low. The first one is a candidate for adding to the graph. private SortedSet sortedArrows; @@ -131,14 +114,11 @@ public final class SvarFges implements IGraphSearch, DagScorer { private Graph graph; // Internal. private Mode mode = Mode.heuristicSpeedup; - /** - * True if one-edge faithfulness is assumed. Speeds the algorithm up. - */ + // True if one-edge faithfulness is assumed. Speeds the algorithm up. private boolean faithfulnessAssumed = false; // Bounds the indegree of the graph. private int maxIndegree = -1; - /** * Construct a Score and pass it in here. The totalScore should return a positive value in case of conditional * dependence and a negative values in case of conditional independence. See Chickering (2002), locally consistent @@ -150,7 +130,6 @@ public SvarFges(Score score) { this.graph = new EdgeListGraph(getVariables()); } - // Used to find semidirected paths for cycle checking. private static Node traverseSemiDirected(Node node, Edge edge) { if (node == edge.getNode1()) { @@ -261,12 +240,18 @@ public long getElapsedTime() { /** * If the true graph is set, asterisks will be printed in log output for the true edges. + * + * @param trueGraph the true graph. + * @return the true graph. */ public void setTrueGraph(Graph trueGraph) { this.trueGraph = trueGraph; } /** + * Returns the score of the given DAG. + * + * @param dag the dag to score. * @return the totalScore of the given DAG, up to a constant. */ public double getScore(Graph dag) { @@ -300,6 +285,8 @@ public Graph getExternalGraph() { /** * Sets the initial graph. + * + * @param externalGraph the initial graph. */ public void setExternalGraph(Graph externalGraph) { if (externalGraph != null) { @@ -320,6 +307,7 @@ public void setExternalGraph(Graph externalGraph) { /** * Sets whether verbose output should be produced. + * @param verbose true if verbose output should be produced. */ public void setVerbose(boolean verbose) { this.verbose = verbose; @@ -334,6 +322,7 @@ public PrintStream getOut() { /** * Sets the output stream that output (except for log output) should be sent to. By detault System.out. + * @param out the output stream. */ public void setOut(PrintStream out) { this.out = out; @@ -348,53 +337,12 @@ public Graph getAdjacencies() { /** * Sets the set of preset adjacencies for the algorithm; edges not in this adjacencies graph will not be added. + * @param adjacencies the adjacencies graph. */ public void setAdjacencies(Graph adjacencies) { this.adjacencies = adjacencies; } - /** - * For BIC totalScore, a multiplier on the penalty term. For continuous searches. - * - * @deprecated Use the getters on the individual scores instead. - */ - public double getPenaltyDiscount() { - if (this.score instanceof HasPenaltyDiscount) { - return ((HasPenaltyDiscount) this.score).getPenaltyDiscount(); - } else { - return 2.0; - } - } - - /** - * For BIC totalScore, a multiplier on the penalty term. For continuous searches. - * - * @deprecated Use the setters on the individual scores instead. - */ - public void setPenaltyDiscount(double penaltyDiscount) { - if (this.score instanceof HasPenaltyDiscount) { - ((HasPenaltyDiscount) this.score).setPenaltyDiscount(penaltyDiscount); - } - } - - /** - * @deprecated Use the setters on the individual scores instead. - */ - public void setSamplePrior(double samplePrior) { - if (this.score instanceof DiscreteScore) { - ((DiscreteScore) this.score).setSamplePrior(samplePrior); - } - } - - /** - * @deprecated Use the setters on the individual scores instead. - */ - public void setStructurePrior(double expectedNumParents) { - if (this.score instanceof DiscreteScore) { - ((DiscreteScore) this.score).setStructurePrior(expectedNumParents); - } - } - /** * The maximum of parents any nodes can have in the output pattern. * @@ -414,13 +362,42 @@ public void setMaxIndegree(int maxIndegree) { this.maxIndegree = maxIndegree; } - + /** + * @return the graph being constructed. + */ public int getMinChunk(int n) { // The minimum number of operations to do before parallelizing. int minChunk = 100; return FastMath.max(n / this.maxThreads, minChunk); } + /** + * Scores the given DAG, up to a constant. + */ + public double scoreDag(Graph dag) { + buildIndexing(dag.getNodes()); + + double _score = 0.0; + + for (Node y : dag.getNodes()) { + Set parents = new HashSet<>(dag.getParents(y)); + int[] parentIndices = new int[parents.size()]; + Iterator pi = parents.iterator(); + int count = 0; + + while (pi.hasNext()) { + Node nextParent = pi.next(); + parentIndices[count++] = this.hashIndices.get(nextParent); + } + + int yIndex = this.hashIndices.get(y); + _score += this.score.localScore(yIndex, parentIndices); + } + + return _score; + } + + //Sets the discrete scoring function to use. private void setScore(Score totalScore) { this.score = totalScore; @@ -460,8 +437,7 @@ protected Boolean compute() { int numNodesPerTask = FastMath.max(100, nodes.size() / SvarFges.this.maxThreads); for (int i = 0; i < nodes.size(); i += numNodesPerTask) { - NodeTaskEmptyGraph task = new NodeTaskEmptyGraph(i, FastMath.min(nodes.size(), i + numNodesPerTask), - nodes, emptySet); + NodeTaskEmptyGraph task = new NodeTaskEmptyGraph(i, FastMath.min(nodes.size(), i + numNodesPerTask), nodes, emptySet); tasks.add(task); task.fork(); @@ -1040,8 +1016,7 @@ class BackwardTask extends RecursiveTask { private final int from; private final int to; - public BackwardTask(Node r, List adj, int chunk, int from, int to, - Map hashIndices) { + public BackwardTask(Node r, List adj, int chunk, int from, int to, Map hashIndices) { this.adj = adj; this.hashIndices = hashIndices; this.chunk = chunk; @@ -1091,8 +1066,7 @@ protected Boolean compute() { for (Node r : toProcess) { this.neighbors.put(r, getNeighbors(r)); List adjacentNodes = new ArrayList<>(this.graph.getAdjacentNodes(r)); - this.pool.invoke(new BackwardTask(r, adjacentNodes, getMinChunk(adjacentNodes.size()), 0, - adjacentNodes.size(), this.hashIndices)); + this.pool.invoke(new BackwardTask(r, adjacentNodes, getMinChunk(adjacentNodes.size()), 0, adjacentNodes.size(), this.hashIndices)); } } @@ -1180,8 +1154,7 @@ private Set getNeighbors(Node y) { } // Evaluate the Insert(X, Y, T) operator (Definition 12 from Chickering, 2002). - private double insertEval(Node x, Node y, Set t, Set naYX, - Map hashIndices) { + private double insertEval(Node x, Node y, Set t, Set naYX, Map hashIndices) { Set set = new HashSet<>(naYX); set.addAll(t); set.addAll(this.graph.getParents(y)); @@ -1189,8 +1162,7 @@ private double insertEval(Node x, Node y, Set t, Set naYX, } // Evaluate the Delete(X, Y, T) operator (Definition 12 from Chickering, 2002). - private double deleteEval(Node x, Node y, Set diff, - Map hashIndices) { + private double deleteEval(Node x, Node y, Set diff, Map hashIndices) { Set set = new HashSet<>(diff); set.addAll(this.graph.getParents(y)); set.remove(x); @@ -1218,8 +1190,7 @@ private boolean insert(Node x, Node y, Set T, double bump) { if (this.verbose) { String label = this.trueGraph != null && trueEdge != null ? "*" : ""; - TetradLogger.getInstance().log("insertedEdges", this.graph.getNumEdges() + ". INSERT " + this.graph.getEdge(x, y) + - " " + T + " " + bump + " " + label); + TetradLogger.getInstance().log("insertedEdges", this.graph.getNumEdges() + ". INSERT " + this.graph.getEdge(x, y) + " " + T + " " + bump + " " + label); } int numEdges = this.graph.getNumEdges(); @@ -1228,10 +1199,7 @@ private boolean insert(Node x, Node y, Set T, double bump) { if (this.verbose) { String label = this.trueGraph != null && trueEdge != null ? "*" : ""; - this.out.println(this.graph.getNumEdges() + ". INSERT " + this.graph.getEdge(x, y) + - " " + T + " " + bump + " " + label - + " degree = " + GraphUtils.getDegree(this.graph) - + " indegree = " + GraphUtils.getIndegree(this.graph)); + this.out.println(this.graph.getNumEdges() + ". INSERT " + this.graph.getEdge(x, y) + " " + T + " " + bump + " " + label + " degree = " + GraphUtils.getDegree(this.graph) + " indegree = " + GraphUtils.getIndegree(this.graph)); } for (Node _t : T) { @@ -1283,8 +1251,7 @@ private boolean delete(Node x, Node y, Set H, double bump, Set naYX) if (this.verbose) { String label = this.trueGraph != null && trueEdge != null ? "*" : ""; - String message = (this.graph.getNumEdges()) + ". DELETE " + x + "-->" + y + - " H = " + H + " NaYX = " + naYX + " diff = " + diff + " (" + bump + ") " + label; + String message = (this.graph.getNumEdges()) + ". DELETE " + x + "-->" + y + " H = " + H + " NaYX = " + naYX + " diff = " + diff + " (" + bump + ") " + label; TetradLogger.getInstance().log("deletedEdges", message); this.out.println(message); } @@ -1303,8 +1270,7 @@ private boolean delete(Node x, Node y, Set H, double bump, Set naYX) // **/ if (this.verbose) { - TetradLogger.getInstance().log("directedEdges", "--- Directing " + oldyh + " to " + - this.graph.getEdge(y, h)); + TetradLogger.getInstance().log("directedEdges", "--- Directing " + oldyh + " to " + this.graph.getEdge(y, h)); this.out.println("--- Directing " + oldyh + " to " + this.graph.getEdge(y, h)); } @@ -1321,8 +1287,7 @@ private boolean delete(Node x, Node y, Set H, double bump, Set naYX) // **/ if (this.verbose) { - TetradLogger.getInstance().log("directedEdges", "--- Directing " + oldxh + " to " + - this.graph.getEdge(x, h)); + TetradLogger.getInstance().log("directedEdges", "--- Directing " + oldxh + " to " + this.graph.getEdge(x, h)); this.out.println("--- Directing " + oldxh + " to " + this.graph.getEdge(x, h)); } } @@ -1568,34 +1533,8 @@ private void addLookupArrow(Node i, Node j, Arrow arrow) { arrows.add(arrow); } - /** - * Scores the given DAG, up to a constant. - */ - public double scoreDag(Graph dag) { - buildIndexing(dag.getNodes()); - - double _score = 0.0; - - for (Node y : dag.getNodes()) { - Set parents = new HashSet<>(dag.getParents(y)); - int[] parentIndices = new int[parents.size()]; - Iterator pi = parents.iterator(); - int count = 0; - - while (pi.hasNext()) { - Node nextParent = pi.next(); - parentIndices[count++] = this.hashIndices.get(nextParent); - } - - int yIndex = this.hashIndices.get(y); - _score += this.score.localScore(yIndex, parentIndices); - } - - return _score; - } - private double scoreGraphChange(Node y, Set parents, - Node x, Map hashIndices) { + private double scoreGraphChange(Node y, Set parents, Node x, Map hashIndices) { int yIndex = hashIndices.get(y); if (parents.contains(x)) return Double.NaN;//throw new IllegalArgumentException(); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SvarGfci.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SvarGfci.java index 2c3134496e..895758de19 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SvarGfci.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SvarGfci.java @@ -62,7 +62,6 @@ * @see SvarFci */ public final class SvarGfci implements IGraphSearch { - // The logger to use. private final TetradLogger logger = TetradLogger.getInstance(); // The conditional independence test. @@ -87,6 +86,9 @@ public final class SvarGfci implements IGraphSearch { /** * Constructs a new GFCI search for the given independence test and background knowledge. + * + * @param test The independence test. + * @param score The score. */ public SvarGfci(IndependenceTest test, Score score) { if (score == null) { From c97b96e752877f19de946724ca94166fc56ff8b1 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Mon, 29 Jan 2024 03:42:36 -0500 Subject: [PATCH 140/163] Got the pseudoinverse option to work in Fisher Z with subsetting, but it's behaving unintuitively to me, in that if you subsample 50% you get a overabundance of dependencies, which you don't with the non-pseudoinverse option. --- .../tetradapp/editor/IndTestMenuItems.java | 2 +- .../tetradapp/editor/MarkovCheckEditor.java | 6 +-- .../model/AbstractMBSearchRunner.java | 10 ++-- .../cmu/tetradapp/model/IndTestChooser.java | 10 ++-- .../edu/cmu/tetradapp/util/IndTestType.java | 4 +- .../cmu/tetrad/search/score/SemBicScore.java | 19 ++++++- .../tetrad/search/test/IndTestFisherZ.java | 49 +++++++++++++------ .../cmu/tetrad/search/test/RowsSettable.java | 5 ++ 8 files changed, 73 insertions(+), 32 deletions(-) diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/IndTestMenuItems.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/IndTestMenuItems.java index c50a94c805..db1c7850b6 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/IndTestMenuItems.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/IndTestMenuItems.java @@ -72,7 +72,7 @@ static void addIndependenceTestChoices(JMenu test, IndTestTypeSetter setter) { static void addContinuousTestMenuItems(JMenu test, IndTestTypeSetter setter) { IndTestType testType = setter.getTestType(); if (testType != IndTestType.FISHER_Z && - testType != IndTestType.FISHER_ZD && +// testType != IndTestType.FISHER_ZD && testType != IndTestType.SEM_BIC && testType != IndTestType.CONDITIONAL_CORRELATION && testType != IndTestType.LINEAR_REGRESSION && diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java index 03e4e22eba..21dc4656dd 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java @@ -647,14 +647,14 @@ public Object getValueAt(int rowIndex, int columnIndex) { if (columnIndex == 2) { if (model.getMarkovCheck().getIndependenceTest() instanceof MsepTest) { - if (result.isDependent()) { + if (result.isIndependent()) { return "M-SEPARATED"; } else { return "m-connected"; } } else { - if (result.isDependent()) { - return "DepENDENT"; + if (result.isIndependent()) { + return "INDEPENDENT"; } else { return "dependent"; } diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/AbstractMBSearchRunner.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/AbstractMBSearchRunner.java index 51dd8c138d..f5d211aca9 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/AbstractMBSearchRunner.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/AbstractMBSearchRunner.java @@ -183,11 +183,11 @@ IndependenceTest getIndependenceTest() { if (IndTestType.FISHER_Z == type) { return new IndTestFisherZ(this.source, this.params.getDouble("alpha", 0.001)); } - if (IndTestType.FISHER_ZD == type) { - IndTestFisherZ test = new IndTestFisherZ(this.source, this.params.getDouble("alpha", 0.001)); - test.setUsePseudoinverse(true); - return test; - } +// if (IndTestType.FISHER_ZD == type) { +// IndTestFisherZ test = new IndTestFisherZ(this.source, this.params.getDouble("alpha", 0.001)); +//// test.setUsePseudoinverse(true); +// return test; +// } if (IndTestType.LINEAR_REGRESSION == type) { return new IndTestRegression(this.source, this.params.getDouble("alpha", 0.001)); } else { diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/IndTestChooser.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/IndTestChooser.java index 45d7256c6b..de5ccde1a4 100755 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/IndTestChooser.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/IndTestChooser.java @@ -135,11 +135,11 @@ private IndependenceTest getContinuousTest(DataSet dataSet, if (IndTestType.FISHER_Z == testType) { return new IndTestFisherZ(dataSet, params.getDouble("alpha", 0.001)); } - if (IndTestType.FISHER_ZD == testType) { - IndTestFisherZ test = new IndTestFisherZ(dataSet, params.getDouble("alpha", 0.001)); - test.setUsePseudoinverse(true); - return test; - } +// if (IndTestType.FISHER_ZD == testType) { +// IndTestFisherZ test = new IndTestFisherZ(dataSet, params.getDouble("alpha", 0.001)); +//// test.setUsePseudoinverse(true); +// return test; +// } if (IndTestType.SEM_BIC == testType) { return new ScoreIndTest(new SemBicScore(new CovarianceMatrix(dataSet))); } diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/IndTestType.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/IndTestType.java index 3b38986a4a..601c44be12 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/IndTestType.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/util/IndTestType.java @@ -25,6 +25,7 @@ import edu.cmu.tetrad.util.TetradSerializable; import java.io.ObjectStreamException; +import java.io.Serial; /** * A typesafe enumeration of the types of independence tests that are used for basic search algorithm in this package. @@ -60,10 +61,11 @@ public final class IndTestType implements TetradSerializable { new IndTestType("Fisher Z Pooled Residuals", DataType.Continuous); public static final IndTestType FISHER = new IndTestType("Fisher (Fisher Z)", DataType.Continuous); public static final IndTestType TIPPETT = new IndTestType("Tippett (Fisher Z)", DataType.Continuous); + @Serial private static final long serialVersionUID = 23L; private static final IndTestType[] TYPES = {IndTestType.DEFAULT, IndTestType.CORRELATION_T, IndTestType.FISHER_Z, IndTestType.LINEAR_REGRESSION, IndTestType.CONDITIONAL_CORRELATION, IndTestType.SEM_BIC, IndTestType.LOGISTIC_REGRESSION, - IndTestType.MIXED_MLR, IndTestType.FISHER_ZD, + IndTestType.MIXED_MLR, //IndTestType.FISHER_ZD, IndTestType.G_SQUARE, IndTestType.CHI_SQUARE, IndTestType.M_SEPARATION, IndTestType.TIME_SERIES, diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/SemBicScore.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/SemBicScore.java index 2289c9dab3..5fc7e9ae7a 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/SemBicScore.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/score/SemBicScore.java @@ -182,8 +182,25 @@ public static double getVarRy(int i, int[] parents, Matrix data, ICovarianceMatr */ @NotNull public static SemBicScore.CovAndCoefs getCovAndCoefs(int i, int[] parents, Matrix data, ICovarianceMatrix covariances, boolean calculateRowSubsets, boolean usePseudoInverse) { + List rows = SemBicScore.getRows(i, parents, data, calculateRowSubsets); + return getCovAndCoefs(i, parents, data, covariances, usePseudoInverse, rows); + } + + /** + * Returns the covariance matrix of the regression of the ith variable on its parents and the regression + * + * @param i The index of the variable. + * @param parents The indices of the parents. + * @param data The data matrix. + * @param covariances The covariance matrix. + * @param usePseudoInverse True if the pseudo-inverse should be used instead of the inverse to avoid exceptions. + * @param rows The rows to use. + * @return The covariance matrix of the regression of the ith variable on its parents and the regression + */ + @NotNull + public static CovAndCoefs getCovAndCoefs(int i, int[] parents, Matrix data, ICovarianceMatrix covariances, boolean usePseudoInverse, List rows) { int[] all = SemBicScore.concat(i, parents); - Matrix cov = SemBicScore.getCov(SemBicScore.getRows(i, parents, data, calculateRowSubsets), all, all, data, covariances); + Matrix cov = SemBicScore.getCov(rows, all, all, data, covariances); int[] pp = SemBicScore.indexedParents(parents); Matrix covxx = cov.getSelection(pp, pp); Matrix covxy = cov.getSelection(pp, new int[]{0}); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java index a7b1ccfba4..c18709870f 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java @@ -286,26 +286,35 @@ private IndependenceResult checkIndependencePseudoinverse(Node xVar, Node yVar, zCols[i] = getVariables().indexOf(z.get(i)); } - edu.cmu.tetrad.util.Vector x = this.data.getColumn(xIndex); - edu.cmu.tetrad.util.Vector y = this.data.getColumn(yIndex); + int[] rows; + + if (this.rows == null) { + rows = new int[this.data.getNumRows()]; + for (int i = 0; i < rows.length; i++) { + rows[i] = i; + } + } else { + rows = new int[this.rows.size()]; + for (int i = 0; i < rows.length; i++) { + rows[i] = this.rows.get(i); + } + } + + Vector x = this.data.getSelection(rows, new int[]{xIndex}).getColumn(0); + Vector y = this.data.getSelection(rows, new int[]{yIndex}).getColumn(0); CovarianceMatrix cov = new CovarianceMatrix(dataSet); SemBicScore.CovAndCoefs covAndCoefsX = SemBicScore.getCovAndCoefs(xIndex, zCols, this.data, - cov, true, true); + cov, true, this.rows); SemBicScore.CovAndCoefs covAndCoefsY = SemBicScore.getCovAndCoefs(yIndex, zCols, this.data, - cov, true, true); - - int[] rows = new int[this.data.getNumRows()]; - for (int i = 0; i < rows.length; i++) { - rows[i] = i; - } + cov, true, this.rows); Matrix selection = data.getSelection(rows, zCols); edu.cmu.tetrad.util.Vector xPred = selection.times(covAndCoefsX.b()).getColumn(0); edu.cmu.tetrad.util.Vector yPred = selection.times(covAndCoefsY.b()).getColumn(0); - edu.cmu.tetrad.util.Vector xRes = xPred.minus(x); + Vector xRes = xPred.minus(x); Vector yRes = yPred.minus(y); // Note that r will be NaN if either xRes or yRes is constant. @@ -332,7 +341,6 @@ private IndependenceResult checkIndependencePseudoinverse(Node xVar, Node yVar, return new IndependenceResult(new IndependenceFact(xVar, yVar, _z), p > alpha, p, getAlpha() - p); } - /** * Returns the p-value for x _||_ y | z. * @@ -557,14 +565,23 @@ private boolean determinesPseudoinverse(List zList, Node xVar) { CovarianceMatrix cov = new CovarianceMatrix(dataSet); - SemBicScore.CovAndCoefs covAndCoefsX = SemBicScore.getCovAndCoefs(xIndex, zCols, this.data, - cov, true, true); + int[] rows; - int[] rows = new int[this.data.getNumRows()]; - for (int i = 0; i < rows.length; i++) { - rows[i] = i; + if (this.rows == null) { + rows = new int[this.data.getNumRows()]; + for (int i = 0; i < rows.length; i++) { + rows[i] = i; + } + } else { + rows = new int[this.rows.size()]; + for (int i = 0; i < rows.length; i++) { + rows[i] = this.rows.get(i); + } } + SemBicScore.CovAndCoefs covAndCoefsX = SemBicScore.getCovAndCoefs(xIndex, zCols, this.data, + cov, true, this.rows); + Matrix selection = data.getSelection(rows, zCols); Vector xPred = selection.times(covAndCoefsX.b()).getColumn(0); Vector xRes = xPred.minus(x); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/RowsSettable.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/RowsSettable.java index 12386f718d..43de224774 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/RowsSettable.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/RowsSettable.java @@ -2,6 +2,11 @@ import java.util.List; +/** + * Interface for tests that can have their rows set on the fly. + * + * @author josephramsey + */ public interface RowsSettable { /** From 79dab0868454fea98e6fd7782f5a19a8bfaf15eb Mon Sep 17 00:00:00 2001 From: jdramsey Date: Mon, 29 Jan 2024 03:48:40 -0500 Subject: [PATCH 141/163] Nevermind, figured it out--the sample size in the fisher Z formula should have been the sampled rows size. --- .../main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java index c18709870f..604f92cd15 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java @@ -320,7 +320,7 @@ private IndependenceResult checkIndependencePseudoinverse(Node xVar, Node yVar, // Note that r will be NaN if either xRes or yRes is constant. double r = StatUtils.correlation(xRes.toArray(), yRes.toArray()); - double fisherZ = FastMath.sqrt(sampleSize() - z.size() - 3.0) * + double fisherZ = FastMath.sqrt(rows.length - z.size() - 3.0) * 0.5 * (FastMath.log(1.0 + r) - FastMath.log(1.0 - r)); double p = 2 * (1.0 - this.normal.cumulativeProbability(abs(fisherZ))); From aa907932f041a1eae01d845dafdf1510cce85559 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Mon, 29 Jan 2024 12:41:47 -0500 Subject: [PATCH 142/163] Nevermind, figured it out--the sample size in the fisher Z formula should have been the sampled rows size. --- .../tetrad/search/test/IndTestFisherZ.java | 70 ++++++++++--------- 1 file changed, 36 insertions(+), 34 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java index 604f92cd15..04bbe5379b 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestFisherZ.java @@ -222,31 +222,32 @@ public IndependenceResult checkIndependence(Node x, Node y, Set z) { IndependenceResult result = checkIndependencePseudoinverse(x, y, z); facts.put(new IndependenceFact(x, y, z), result); return result; - } + } else { // Use inverse. - double p; + double p; - try { - p = getPValue(x, y, z); - } catch (SingularMatrixException e) { - throw new RuntimeException("Singular matrix encountered for test: " + LogUtilsSearch.independenceFact(x, y, z)); - } + try { + p = getPValue(x, y, z); + } catch (SingularMatrixException e) { + throw new RuntimeException("Singular matrix encountered for test: " + LogUtilsSearch.independenceFact(x, y, z)); + } - boolean independent = p > this.alpha; + boolean independent = p > this.alpha; - if (this.verbose) { - if (independent) { - TetradLogger.getInstance().forceLogMessage( - LogUtilsSearch.independenceFactMsg(x, y, z, p)); + if (this.verbose) { + if (independent) { + TetradLogger.getInstance().forceLogMessage( + LogUtilsSearch.independenceFactMsg(x, y, z, p)); + } } - } - if (Double.isNaN(p)) { - throw new RuntimeException("Undefined p-value encountered in for test: " + LogUtilsSearch.independenceFact(x, y, z)); - } else { - IndependenceResult result = new IndependenceResult(new IndependenceFact(x, y, z), independent, p, alpha - p); - facts.put(new IndependenceFact(x, y, z), result); - return result; + if (Double.isNaN(p)) { + throw new RuntimeException("Undefined p-value encountered in for test: " + LogUtilsSearch.independenceFact(x, y, z)); + } else { + IndependenceResult result = new IndependenceResult(new IndependenceFact(x, y, z), independent, p, alpha - p); + facts.put(new IndependenceFact(x, y, z), result); + return result; + } } } @@ -509,28 +510,29 @@ public String toString() { public boolean determines(List z, Node x) throws UnsupportedOperationException { if (usePseudoinverse) { return determinesPseudoinverse(z, x); - } + } else { - int[] parents = new int[z.size()]; + int[] parents = new int[z.size()]; - for (int j = 0; j < parents.length; j++) { - parents[j] = indexMap.get(z.get(j).getName()); - } + for (int j = 0; j < parents.length; j++) { + parents[j] = indexMap.get(z.get(j).getName()); + } - if (parents.length > 0) { + if (parents.length > 0) { - // Regress z onto i, yielding regression coefficients b. - Matrix Czz = this.cor.getSelection(parents, parents); + // Regress z onto i, yielding regression coefficients b. + Matrix Czz = this.cor.getSelection(parents, parents); - try { - Czz.inverse(); - } catch (SingularMatrixException e) { - System.out.println(LogUtilsSearch.determinismDetected(new HashSet<>(z), x)); - return true; + try { + Czz.inverse(); + } catch (SingularMatrixException e) { + System.out.println(LogUtilsSearch.determinismDetected(new HashSet<>(z), x)); + return true; + } } - } - return false; + return false; + } } /** From 7ba8600c65d69dd177a2df5e45290cc7ac9e4410 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Mon, 29 Jan 2024 13:53:56 -0500 Subject: [PATCH 143/163] Nevermind, figured it out--the sample size in the fisher Z formula should have been the sampled rows size. --- .../main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java index 21dc4656dd..b7718d5cd0 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java @@ -31,6 +31,7 @@ import edu.cmu.tetrad.search.IndependenceTest; import edu.cmu.tetrad.search.test.IndependenceResult; import edu.cmu.tetrad.search.test.MsepTest; +import edu.cmu.tetrad.search.test.RowsSettable; import edu.cmu.tetrad.util.*; import edu.cmu.tetradapp.model.MarkovCheckIndTestModel; import edu.cmu.tetradapp.ui.PaddingPanel; @@ -245,6 +246,9 @@ public void watch() { if (model.getMarkovCheck().getIndependenceTest().getData() != null) { box1.add(new JLabel("% Sample:")); box1.add(percent); + } else if (!(model.getMarkovCheck().getIndependenceTest() instanceof RowsSettable)) { + box1.add(new JLabel("(Test cannot be subsampled)")); + box1.add(percent); } else { box1.add(new JLabel("(Not tabular data)")); } From 980cdc595a7a9a1cb70a3b06ad45fb366ba82388 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Tue, 30 Jan 2024 00:02:30 -0500 Subject: [PATCH 144/163] Cleanup. Plus, added caching for IndTestProbabilistic for the case where threshold = false. --- .../search/test/IndTestProbabilistic.java | 80 ++++++++++++++++++- 1 file changed, 76 insertions(+), 4 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestProbabilistic.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestProbabilistic.java index e73a98642b..d2520b96e2 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestProbabilistic.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestProbabilistic.java @@ -34,6 +34,7 @@ import edu.pitt.dbmi.algo.bayesian.constraint.inference.BCInference; import java.util.*; +import java.util.concurrent.ConcurrentHashMap; /** * Uses BCInference by Cooper and Bui to calculate probabilistic conditional independence judgments. @@ -42,6 +43,8 @@ */ public class IndTestProbabilistic implements IndependenceTest { + // A cache of results for independence facts. + private final Map facts = new ConcurrentHashMap<>(); //The data set for which conditional independence judgments are requested. private final DataSet data; // The nodes of the data set. @@ -52,7 +55,7 @@ public class IndTestProbabilistic implements IndependenceTest { private final Map H; // The BCInference object. private final BCInference bci; - // True if verbose output should be printed. + // True if the independence test should be thresholded, false if it should be randomized. private boolean threshold; // The posterior probability of the last independence test. private double posterior; @@ -119,6 +122,9 @@ public IndependenceTest indTestSubset(List vars) { */ @Override public IndependenceResult checkIndependence(Node x, Node y, Set _z) { + if (!threshold && facts.containsKey(new IndependenceFact(x, y, _z))) { + return facts.get(new IndependenceFact(x, y, _z)); + } // Notice that we do not cache the results of the independence tests here. This is because // these results have a random component and so caching them would be inappropriate. @@ -127,9 +133,20 @@ public IndependenceResult checkIndependence(Node x, Node y, Set _z) { Node[] nodes = new Node[z.size()]; for (int i = 0; i < z.size(); i++) nodes[i] = z.get(i); - return checkIndependence(x, y, nodes); + IndependenceResult independenceResult = checkIndependence(x, y, nodes); + if (!threshold) facts.put(new IndependenceFact(x, y, _z), independenceResult); + return independenceResult; } + /** + * Returns an independence result that states whether x _||_y | z and what the p-value of the test is. + * + * @param x The first variable. + * @param y The second variable. + * @param z The conditioning set. + * @return an independence result (see) + * @see IndependenceResult + */ @Override public IndependenceResult checkIndependence(Node x, Node y, Node... z) { IndependenceFact key = new IndependenceFact(x, y, z); @@ -209,6 +226,17 @@ public IndependenceResult checkIndependence(Node x, Node y, Node... z) { } + /** + * Returns the probability of the constraint x op y | z. + * + * @param bci The BCInference object. + * @param op The operator. + * @param x The first variable. + * @param y The second variable. + * @param z The conditioning set. + * @param indices A map from nodes to their indices. + * @return The probability. + */ public double probConstraint(BCInference bci, BCInference.OP op, Node x, Node y, Node[] z, Map indices) { int _x = indices.get(x) + 1; @@ -223,11 +251,18 @@ public double probConstraint(BCInference bci, BCInference.OP op, Node x, Node y, return bci.probConstraint(op, _x, _y, _z); } + /** + * Returns the variables of the data set. + * @return The variables. + */ @Override public List getVariables() { return this.nodes; } + /** + * Returns the variable with the given name. + */ @Override public Node getVariable(String name) { for (Node node : this.nodes) { @@ -237,48 +272,85 @@ public Node getVariable(String name) { return null; } + /** + * @throws UnsupportedOperationException Method not implemented. + */ @Override public boolean determines(Set z, Node y) { throw new UnsupportedOperationException(); } + /** + * @throws UnsupportedOperationException Method not implemented. + */ @Override public double getAlpha() { throw new UnsupportedOperationException("The Probabiistic Test doesn't use an alpha parameter"); } + /** + * @throws UnsupportedOperationException Method not implemented. + */ @Override public void setAlpha(double alpha) { throw new UnsupportedOperationException(); } + /** + * Returns the data set for which conditional independence judgments are requested. + * @return The data set. + */ @Override public DataModel getData() { return this.data; } + /** + * Returns a map from independence facts to their probabilities of independence. + * @return The map. + */ public Map getH() { return new HashMap<>(this.H); } + /** + * Returns the posterior probability of the last independence test. + * @return The posterior probability. + */ public double getPosterior() { return this.posterior; } + /** + * Returns true if verbose output should be printed. + * @return True, if so. + */ @Override public boolean isVerbose() { return this.verbose; } + /** + * Sets whether verbose output should be printed. + * @param verbose True, if so. + */ @Override public void setVerbose(boolean verbose) { this.verbose = verbose; } - public void setThreshold(boolean noRandomizedGeneratingConstraints) { - this.threshold = noRandomizedGeneratingConstraints; + /** + * Sets whether the independence test should be thresholded (true) or randomized (false). + * @param threshold true if the independence test should be thresholded, false if it should be randomized. + */ + public void setThreshold(boolean threshold) { + this.threshold = threshold; } + /** + * Sets the cutoff for the independence test. + * @param cutoff the cutoff for the independence test. + */ public void setCutoff(double cutoff) { this.cutoff = cutoff; } From 387cbb52bbb9a858ff5f33adb67367ec9d1d111e Mon Sep 17 00:00:00 2001 From: jdramsey Date: Tue, 30 Jan 2024 00:05:18 -0500 Subject: [PATCH 145/163] Cleanup. Plus, added caching for IndTestProbabilistic for the case where threshold = false. --- .../java/edu/cmu/tetrad/search/test/IndTestProbabilistic.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestProbabilistic.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestProbabilistic.java index d2520b96e2..0d567239f8 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestProbabilistic.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/IndTestProbabilistic.java @@ -43,7 +43,7 @@ */ public class IndTestProbabilistic implements IndependenceTest { - // A cache of results for independence facts. + // A cache of results for independence facts, used only if threshold is false. private final Map facts = new ConcurrentHashMap<>(); //The data set for which conditional independence judgments are requested. private final DataSet data; From 65674e9bcaf1a3bb2310d1b8be182b781a9f0941 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Wed, 31 Jan 2024 17:08:47 -0500 Subject: [PATCH 146/163] Cleanup. --- .../algorithm/ReturnsBootstrapGraphs.java | 5 + .../algorithm/oracle/pag/Bfci.java | 6 + .../algcomparison/score/ScoreWrapper.java | 2 + .../algcomparison/statistic/BicDiff.java | 29 ++++ .../algcomparison/statistic/BicEst.java | 34 ++++ .../algcomparison/statistic/BicTrue.java | 30 ++++ .../statistic/utils/BidirectedConfusion.java | 26 +++ .../utils/TakesIndependenceWrapper.java | 14 +- .../algcomparison/utils/UsesScoreWrapper.java | 11 ++ .../edu/cmu/tetrad/bayes/BayesProperties.java | 100 ++---------- .../edu/cmu/tetrad/bayes/BayesUpdater.java | 2 +- .../edu/cmu/tetrad/bayes/BdeMetricCache.java | 68 ++++++-- .../main/java/edu/cmu/tetrad/search/Fci.java | 1 - .../main/java/edu/cmu/tetrad/search/Sp.java | 4 +- .../java/edu/cmu/tetrad/search/SvarFges.java | 3 +- .../tetrad/search/utils/BesPermutation.java | 5 + .../gene/algorithm/biolingua/Biolingua.java | 37 +++-- .../algorithm/biolingua/BiolinguaDigraph.java | 2 + .../algorithm/biolingua/BiolinguaRunner.java | 5 + .../gene/algorithm/biolingua/Digraph.java | 17 +- .../tetrad/gene/history/BooleanFunction.java | 66 ++++---- .../gene/history/BooleanGlassFunction.java | 152 ++++++++---------- .../tetrad/gene/history/UpdateFunction.java | 24 +-- .../inference/BCCausalInference.java | 85 +++++++--- 24 files changed, 437 insertions(+), 291 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/ReturnsBootstrapGraphs.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/ReturnsBootstrapGraphs.java index f7375fad5c..8d6b19d258 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/ReturnsBootstrapGraphs.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/ReturnsBootstrapGraphs.java @@ -6,6 +6,11 @@ public interface ReturnsBootstrapGraphs { + /** + * Returns the bootstrap graphs. + * + * @return the bootstrap graphs. + */ List getBootstrapGraphs(); } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/pag/Bfci.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/pag/Bfci.java index 53a25cc689..c8c4f34f5c 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/pag/Bfci.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/pag/Bfci.java @@ -59,6 +59,12 @@ public Bfci() { // Used for reflection; do not delete. } + /** + * Constructs a new BFCI algorithm using the given test and score. + * + * @param test the independence test to use + * @param score the score to use + */ public Bfci(IndependenceWrapper test, ScoreWrapper score) { this.test = test; this.score = score; diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/score/ScoreWrapper.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/score/ScoreWrapper.java index 686dad09ea..ef145249b4 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/score/ScoreWrapper.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/score/ScoreWrapper.java @@ -50,7 +50,9 @@ public interface ScoreWrapper extends HasParameters, TetradSerializable { /** * Returns the variable with the given name. + * * @param name the name. + * @return the variable. */ Node getVariable(String name); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/BicDiff.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/BicDiff.java index 010e1ba9d1..64660110c4 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/BicDiff.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/BicDiff.java @@ -16,16 +16,34 @@ public class BicDiff implements Statistic { private static final long serialVersionUID = 23L; private boolean precomputeCovariances = true; + /** + * Returns the name of the statistic. + * + * @return the name of the statistic. + */ @Override public String getAbbreviation() { return "BicDiff"; } + /** + * Returns the description of the statistic. + * + * @return the description of the statistic. + */ @Override public String getDescription() { return "Difference between the true and estimated BIC scores"; } + /** + * Returns the value of the statistic. + * + * @param trueGraph The true graph (DAG, CPDAG, PAG_of_the_true_DAG). + * @param estGraph The estimated graph (same type). + * @param dataModel The data model. + * @return The value of the statistic. + */ @Override public double getValue(Graph trueGraph, Graph estGraph, DataModel dataModel) { double _true = SemBicScorer.scoreDag(GraphTransforms.dagFromCpdag(trueGraph, null), dataModel, precomputeCovariances); @@ -33,11 +51,22 @@ public double getValue(Graph trueGraph, Graph estGraph, DataModel dataModel) { return (_true - est); } + /** + * Returns the normalized value of the statistic. + * + * @param value The value of the statistic. + * @return The normalized value of the statistic. + */ @Override public double getNormValue(double value) { return tanh(value / 1e6); } + /** + * Returns the precompute covariances flag. + * + * @param precomputeCovariances The precompute covariances flag. + */ public void setPrecomputeCovariances(boolean precomputeCovariances) { this.precomputeCovariances = precomputeCovariances; } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/BicEst.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/BicEst.java index 6f7aca0127..646b2d23ff 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/BicEst.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/BicEst.java @@ -8,6 +8,7 @@ import edu.cmu.tetrad.search.score.DiscreteBicScore; import edu.cmu.tetrad.search.score.SemBicScorer; +import java.io.Serial; import java.util.List; import static org.apache.commons.math3.util.FastMath.tanh; @@ -18,23 +19,45 @@ * @author josephramsey */ public class BicEst implements Statistic { + @Serial private static final long serialVersionUID = 23L; private boolean precomputeCovariances = true; + /** + * No-arg constructor. Used for reflection; do not delete. + */ public BicEst() { } + /** + * Returns the name of the statistic. + * + * @return the name of the statistic. + */ @Override public String getAbbreviation() { return "BicEst"; } + /** + * Returns the description of the statistic. + * + * @return the description of the statistic. + */ @Override public String getDescription() { return "BIC of the estimated CPDAG (depends only on the estimated DAG and the data)"; } + /** + * Returns the value of the statistic. + * + * @param trueGraph The true graph (DAG, CPDAG, PAG_of_the_true_DAG). + * @param estGraph The estimated graph (same type). + * @param dataModel The data model. + * @return The value of the statistic. + */ @Override public double getValue(Graph trueGraph, Graph estGraph, DataModel dataModel) { if (dataModel.isDiscrete()) { @@ -66,11 +89,22 @@ public double getValue(Graph trueGraph, Graph estGraph, DataModel dataModel) { } } + /** + * Returns the normalized value of the statistic. + * + * @param value The value of the statistic. + * @return The normalized value of the statistic. + */ @Override public double getNormValue(double value) { return tanh(value / 1e6); } + /** + * Returns the precompute covariances flag. + * + * @param precomputeCovariances The precompute covariances flag. + */ public void setPrecomputeCovariances(boolean precomputeCovariances) { this.precomputeCovariances = precomputeCovariances; } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/BicTrue.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/BicTrue.java index 99df8b6eb6..2933466d06 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/BicTrue.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/BicTrue.java @@ -5,6 +5,8 @@ import edu.cmu.tetrad.graph.GraphTransforms; import edu.cmu.tetrad.search.score.SemBicScorer; +import java.io.Serial; + import static org.apache.commons.math3.util.FastMath.tanh; /** @@ -13,30 +15,58 @@ * @author josephramsey */ public class BicTrue implements Statistic { + @Serial private static final long serialVersionUID = 23L; private boolean precomputeCovariances = true; + /** + * No-arg constructor. Used for reflection; do not delete. + */ @Override public String getAbbreviation() { return "BicTrue"; } + /** + * Returns the description of the statistic. + * + * @return + */ @Override public String getDescription() { return "BIC of the true model"; } + /** + * Returns the value of the statistic. + * + * @param trueGraph The true graph (DAG, CPDAG, PAG_of_the_true_DAG). + * @param estGraph The estimated graph (same type). + * @param dataModel The data model. + * @return The value of the statistic. + */ @Override public double getValue(Graph trueGraph, Graph estGraph, DataModel dataModel) { // double est = SemBicScorer.scoreDag(SearchGraphUtils.dagFromCPDAG(estGraph), dataModel); return SemBicScorer.scoreDag(GraphTransforms.dagFromCpdag(trueGraph, null), dataModel, precomputeCovariances); } + /** + * Returns the normalized value of the statistic. + * + * @param value The value of the statistic. + * @return The normalized value of the statistic. + */ @Override public double getNormValue(double value) { return tanh(value); } + /** + * Returns whether to precompute covariances. + * + * @param precomputeCovariances whether to precompute covariances. + */ public void setPrecomputeCovariances(boolean precomputeCovariances) { this.precomputeCovariances = precomputeCovariances; } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/utils/BidirectedConfusion.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/utils/BidirectedConfusion.java index 452b4c6b01..7a78f8d24b 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/utils/BidirectedConfusion.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/utils/BidirectedConfusion.java @@ -18,6 +18,12 @@ public class BidirectedConfusion { private int fp; private int fn; + /** + * Constructs a new confusion matrix for bidirected edges. + * + * @param truth The true graph. + * @param est The estimated graph. + */ public BidirectedConfusion(Graph truth, Graph est) { this.tp = 0; this.fp = 0; @@ -56,18 +62,38 @@ public BidirectedConfusion(Graph truth, Graph est) { this.tn = all - this.fn - this.fp - this.fn; } + /** + * Returns the number of true positives. + * + * @return The number of true positives. + */ public int getTp() { return this.tp; } + /** + * Returns the number of false positives. + * + * @return The number of false positives. + */ public int getFp() { return this.fp; } + /** + * Returns the number of false negatives. + * + * @return The number of false negatives. + */ public int getFn() { return this.fn; } + /** + * Returns the number of true negatives. + * + * @return The number of true negatives. + */ public int getTn() { return this.tn; } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/utils/TakesIndependenceWrapper.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/utils/TakesIndependenceWrapper.java index 5c35194606..de9911ec94 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/utils/TakesIndependenceWrapper.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/utils/TakesIndependenceWrapper.java @@ -3,12 +3,24 @@ import edu.cmu.tetrad.algcomparison.independence.IndependenceWrapper; /** - * Author : Jeremy Espino MD Created 7/13/17 2:25 PM + * Tags an algorithm as using an independence wrapper. + * + * @author Jeremy Espino MD Created 7/13/17 2:25 PM */ public interface TakesIndependenceWrapper { + /** + * Returns the independence wrapper. + * + * @return the independence wrapper. + */ IndependenceWrapper getIndependenceWrapper(); + /** + * Sets the independence wrapper. + * + * @param independenceWrapper the independence wrapper. + */ void setIndependenceWrapper(IndependenceWrapper independenceWrapper); } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/utils/UsesScoreWrapper.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/utils/UsesScoreWrapper.java index d03016493f..be853c9dc2 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/utils/UsesScoreWrapper.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/utils/UsesScoreWrapper.java @@ -3,11 +3,22 @@ import edu.cmu.tetrad.algcomparison.score.ScoreWrapper; /** + * Tags an algorithm as using a score wrapper. + *

                * Author : Jeremy Espino MD Created 7/6/17 2:19 PM */ public interface UsesScoreWrapper { + /** + * Returns the score wrapper. + * @return the score wrapper. + */ ScoreWrapper getScoreWrapper(); + /** + * Sets the score wrapper. + * + * @param score the score wrapper. + */ void setScoreWrapper(ScoreWrapper score); } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/bayes/BayesProperties.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/bayes/BayesProperties.java index 37a811b5ff..1502801d06 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/bayes/BayesProperties.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/bayes/BayesProperties.java @@ -41,7 +41,6 @@ public final class BayesProperties { private final DataSet dataSet; private final List variables; - private final int[][] data; private final int sampleSize; private final int[] numCategories; private double chisq; @@ -49,6 +48,10 @@ public final class BayesProperties { private double bic; private double likelihood; + /** + * Constructs a new BayesProperties object for the given data set. + * @param dataSet The data set. + */ public BayesProperties(DataSet dataSet) { if (dataSet == null) { throw new NullPointerException(); @@ -56,6 +59,7 @@ public BayesProperties(DataSet dataSet) { this.dataSet = dataSet; + int[][] data; if (dataSet instanceof BoxDataSet) { DataBox dataBox = ((BoxDataSet) dataSet).getDataBox(); @@ -63,19 +67,18 @@ public BayesProperties(DataSet dataSet) { VerticalIntDataBox box = new VerticalIntDataBox(dataBox); - this.data = box.getVariableVectors(); + box.getVariableVectors(); } else { - this.data = new int[dataSet.getNumColumns()][]; + data = new int[dataSet.getNumColumns()][]; this.variables = dataSet.getVariables(); for (int j = 0; j < dataSet.getNumColumns(); j++) { - this.data[j] = new int[dataSet.getNumRows()]; + data[j] = new int[dataSet.getNumRows()]; for (int i = 0; i < dataSet.getNumRows(); i++) { - this.data[j][i] = dataSet.getInt(i, j); + data[j][i] = dataSet.getInt(i, j); } } - } this.sampleSize = dataSet.getNumRows(); @@ -103,6 +106,7 @@ private static int getRowIndex(int[] dim, int[] values) { * Calculates the p-value of the graph with respect to the given data. * * @param graph The graph. + * @return The p-value. */ public LikelihoodRet getLikelihoodRatioP(Graph graph) { @@ -282,90 +286,11 @@ private int getDof2(Graph graph) { } private Ret getLikelihoodNode(int node, int[] parents) { - DiscreteBicScore bic = new DiscreteBicScore(dataSet); double lik = bic.localScore(node, parents); int dof = (numCategories[node] - 1) * parents.length; -// int d = ; -// -// for (int childValue = 0; childValue < c; childValue++) { -// d++; -// } - - -// // Number of categories for node. -// int c = this.numCategories[node]; -// -// // Numbers of categories of parents. -// int[] dims = new int[parents.length]; -// -// for (int p = 0; p < parents.length; p++) { -// dims[p] = this.numCategories[parents[p]]; -// } -// -// // Number of parent states. -// int r = 1; -// -// for (int p = 0; p < parents.length; p++) { -// r *= dims[p]; -// } -// -// // Conditional cell coefs of data for node given parents(node). -// int[][] n_jk = new int[r][c]; -// int[] n_j = new int[r]; -// -// int[] parentValues = new int[parents.length]; -// -// int[][] myParents = new int[parents.length][]; -// for (int i = 0; i < parents.length; i++) { -// myParents[i] = this.data[parents[i]]; -// } -// -// int[] myChild = this.data[node]; -// -// for (int i = 0; i < this.sampleSize; i++) { -// for (int p = 0; p < parents.length; p++) { -// parentValues[p] = myParents[p][i]; -// } -// -// int childValue = myChild[i]; -// -// if (childValue == -99) { -// throw new IllegalStateException("Please remove or impute missing " + -// "values (record " + i + " column " + i + ")"); -// } -// -// int rowIndex = BayesProperties.getRowIndex(dims, parentValues); -// -// n_jk[rowIndex][childValue]++; -// n_j[rowIndex]++; -// } - -// //Finally, compute the score -// double lik = 0.0; -// int dof = 0; -// -// for (int rowIndex = 0; rowIndex < r; rowIndex++) { -// if (rowIndex == 0) continue; -// -// if (Thread.interrupted()) break; -// -// int d = 0; -// -// for (int childValue = 0; childValue < c; childValue++) { -// int cellCount = n_jk[rowIndex][childValue]; -// int rowCount = n_j[rowIndex]; -// -// if (cellCount == 0) continue; -// lik += cellCount * FastMath.log(cellCount / (double) rowCount); -// d++; -// } -// -// if (d > 0) dof += c - 1; -// } - return new Ret(lik, dof); } @@ -431,7 +356,10 @@ public int getDof() { } } - public class LikelihoodRet { + /** + * Returns the number of categories for the given variable. + */ + public static class LikelihoodRet { public double p; public double bic; public double chiSq; diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/bayes/BayesUpdater.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/bayes/BayesUpdater.java index 4dbfa13c2f..10cbac9479 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/bayes/BayesUpdater.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/bayes/BayesUpdater.java @@ -28,7 +28,7 @@ * evidence), where evidence takes the form of a Proposition over the variables in the Bayes net, possibly with * additional information about which variables in the Bayes net have been manipulated. Some updaters may be able to * calculate joint marginals as well--that is, P(AND_i{Xi = xi'} | evidence). Also, not all updaters can take - * manipulation information into account. See implementations for details. + * manipulation information into account. See implementations for details.) * * @author josephramsey * @see Evidence diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/bayes/BdeMetricCache.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/bayes/BdeMetricCache.java index 4f1541073d..e016038a43 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/bayes/BdeMetricCache.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/bayes/BdeMetricCache.java @@ -34,32 +34,36 @@ /** *

                Provides a method for computing the score of a model, called the BDe * metric (Bayesian Dirchlet likelihood equivalence), given a dataset (assumes no missing values) and a Bayes - * parameterized network (assumes no latent variables).> 0

                This version has a method that computes the score for a - * given factor of a model, where a factor is determined by a node and its parents. It stores scores in a map whose - * argument is an ordered pair consisting of 1) a node and 2) set of parents. The score for the entire model is the - * product of the scores of its factors. Since the log of the gamma function is used here the sum of the logs is - * computed as the score. Compare this with the score method in the BdeMetric class which computes the score for the - * entire model in one pass. The advantage of the approach in this class is that it is more efficient in the context of - * a search algorithm where different models are scored but where many of them will have the same factors. This class - * stores the score (relative to the dataset) for any [node, set of parents] pair and thus avoids the expensive log - * gamma function calls. Instead it looks in the map scores to see if it has already computed the score and, if so, - * returns the previously computed value.> 0

                See "Learning Bayesian Networks: The Combination of Knowledge and - * Statistical Data" by David Heckerman, Dan Geiger, and David M. Chickering. Microsoft Technical Report - * MSR-TR-94-09.> 0 + * parameterized network (assumes no latent variables).> 0 + *

                + * This version has a method that computes the score for a given factor of a model, where a factor is determined by a + * node and its parents. It stores scores in a map whose argument is an ordered pair consisting of 1) a node and 2) set + * of parents. The score for the entire model is the product of the scores of its factors. Since the log of the gamma + * function is used here the sum of the logs is computed as the score. Compare this with the score method in the + * BdeMetric class which computes the score for the entire model in one pass. The advantage of the approach in this + * class is that it is more efficient in the context of a search algorithm where different models are scored but where + * many of them will have the same factors. This class stores the score (relative to the dataset) for any [node, set of + * parents] pair and thus avoids the expensive log gamma function calls. Instead, it looks in the map scores to see if + * it has already computed the score and, if so, returns the previously computed value.> 0

                See "Learning Bayesian + * Networks: The Combination of Knowledge and Statistical Data" by David Heckerman, Dan Geiger, and David M. + * Chickering. Microsoft Technical Report MSR-TR-94-09.> 0 * * @author Frank Wimberly */ public final class BdeMetricCache { private final DataSet dataSet; private final List variables; - private final BayesPm bayesPm; //Determines the list of variables (nodes) - private final Map scores; private final Map scoreCounts; - private double[][] observedCounts; + /** + * Constructs a BdeMetricCache object for a given dataset and BayesPm. + * + * @param dataSet The dataset for which the BDe metric is to be computed. + * @param bayesPm The BayesPm that determines the list of variables (nodes) and the structure of the graph. + */ public BdeMetricCache(DataSet dataSet, BayesPm bayesPm) { this.bayesPm = bayesPm; this.dataSet = dataSet; @@ -71,6 +75,12 @@ public BdeMetricCache(DataSet dataSet, BayesPm bayesPm) { /** * Computes the BDe score, using the logarithm of the gamma function, relative to the data, of the factor determined * by a node and its parents. + * + * @param node The node of the factor. + * @param parents The parents of the node. + * @param bayesPmMod The BayesPm that determines the list of variables (nodes) and the structure of the graph. + * @param bayesIm The BayesIm that determines the observed counts. + * @return The score of the factor. */ public double scoreLnGam(Node node, Set parents, BayesPm bayesPmMod, BayesIm bayesIm) { @@ -441,6 +451,11 @@ private int getVarIndex(String name) { /** * This method is used in testing and debugging and not in the BDe metric calculations. + * + * @param node The node for which the observed counts are to be returned. + * @param bayesPm The BayesPm that determines the list of variables (nodes) and the structure of the graph. + * @param bayesIm The BayesIm that determines the observed counts. + * @return The observed counts for the given node. */ public double[][] getObservedCounts(Node node, BayesPm bayesPm, BayesIm bayesIm) { @@ -461,6 +476,10 @@ public double[][] getObservedCounts(Node node, BayesPm bayesPm, /** * This is just for testing the operation of the inner class and the map from nodes and parent sets to scores. + * + * @param node The node of the factor. + * @param parents The parents of the node. + * @return The score of the factor. */ public int getScoreCount(Node node, Set parents) { NodeParentsPair nodeParents = new NodeParentsPair(node, parents); @@ -488,16 +507,29 @@ private static final class NodeParentsPair { private final Node node; private final Set parents; + + /** + * Constructs a NodeParentsPair object for a given node and set of parents. + * + * @param node The node of the pair. + * @param parents The parents of the node. + */ public NodeParentsPair(Node node, Set parents) { this.node = node; this.parents = parents; } + /** + * @return The number of elements in the set of parents plus 1. + */ public int calcCount() { return this.parents.size() + 1; } + /** + * @return The node of the pair. + */ public int hashCode() { int hash = 91; hash = 43 * hash + this.node.hashCode(); @@ -506,6 +538,12 @@ public int hashCode() { return hash; } + /** + * Equals method for NodeParentsPair. + * + * @param other The other object to compare to. + * @return True if the other object is a NodeParentsPair and has the same node and parents as this one. + */ public boolean equals(Object other) { if (other == this) { return true; diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fci.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fci.java index ca13626c78..fc16f74b6b 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fci.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fci.java @@ -55,7 +55,6 @@ * Zhang, J. (2008). On the completeness of orientation rules for causal discovery in the presence of latent confounders * and selection bias. Artificial Intelligence, 172(16-17), 1873-1896. *

                - *

                * This class is configured to respect knowledge of forbidden and required edges, including knowledge of temporal * tiers. * diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Sp.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Sp.java index 0fb827d062..6caf9967ba 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Sp.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Sp.java @@ -142,9 +142,7 @@ public Score getScore() { } /** - * Returns the knowledge being used. - * - * @return The knowledge being used. + * Set the knowledge to used. */ @Override public void setKnowledge(Knowledge knowledge) { diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SvarFges.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SvarFges.java index 38beed4064..a214b5105d 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SvarFges.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/SvarFges.java @@ -239,10 +239,9 @@ public long getElapsedTime() { } /** - * If the true graph is set, asterisks will be printed in log output for the true edges. + * Sets the true graph, which will result in some edges in output graphs being marked with asterisks. * * @param trueGraph the true graph. - * @return the true graph. */ public void setTrueGraph(Graph trueGraph) { this.trueGraph = trueGraph; diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/BesPermutation.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/BesPermutation.java index 25c6a89d47..08b7106682 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/BesPermutation.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/BesPermutation.java @@ -227,6 +227,11 @@ private double scoreGraphChange(Node x, Node y, Set parents, Map Count the # of predictions that agree with the input correlation matrix given to Biolingua, as * well as the # of errors (erroneous predictions) After checking all undirectedPaths, compute the evaluation * metric + * @return the evaluation metric for the current model */ private static float evalCurrentModel() { int annotations = 0; @@ -287,7 +290,7 @@ private static float evalCurrentModel() { // Determine the predicted sign according to all undirectedPaths // between these variables int predictedSign = - ((Biolingua.pos == Biolingua.neg) ? 0 : (Biolingua.pos > Biolingua.neg ? 1 : -1)); + (Integer.compare(Biolingua.pos, Biolingua.neg)); // Value of edge between vi and vj in the correlation matrix float correlValue = Biolingua.cm.getValue(vi, vj); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/study/gene/tetrad/gene/algorithm/biolingua/BiolinguaDigraph.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/study/gene/tetrad/gene/algorithm/biolingua/BiolinguaDigraph.java index e5c2606894..6ba3aefc81 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/study/gene/tetrad/gene/algorithm/biolingua/BiolinguaDigraph.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/study/gene/tetrad/gene/algorithm/biolingua/BiolinguaDigraph.java @@ -92,6 +92,7 @@ public Object clone() { * * @param p the parent node * @param c the child node + * @return true if node p is parent of node c. */ public boolean isParent(int p, int c) { return (this.getEdges().getDoubleValue(p, c) != 0.0); @@ -100,6 +101,7 @@ public boolean isParent(int p, int c) { /** * Returns a string with the indexes of all parents of node i separated by spaces (useful for printouts) * @param i the node whose parents are requested + * @return a string with the indexes of all parents of node i separated by spaces */ public String strOfParents(int i) { int[] ap = this.getParents(i); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/study/gene/tetrad/gene/algorithm/biolingua/BiolinguaRunner.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/study/gene/tetrad/gene/algorithm/biolingua/BiolinguaRunner.java index 95e101dc01..a34c6d095e 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/study/gene/tetrad/gene/algorithm/biolingua/BiolinguaRunner.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/study/gene/tetrad/gene/algorithm/biolingua/BiolinguaRunner.java @@ -81,6 +81,11 @@ static void bailout(String errorMsg, int exitCode) { System.exit(exitCode); } + /** + * Main method, runs the Biolingua algorithm + * + * @param args command line arguments + */ public static void main(String[] args) { if ((args.length > 0) && (args[0].equals("/?"))) { // Help invoked, or no arguments -> show usage info diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/study/gene/tetrad/gene/algorithm/biolingua/Digraph.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/study/gene/tetrad/gene/algorithm/biolingua/Digraph.java index 94fb87fa9f..65c385acc5 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/study/gene/tetrad/gene/algorithm/biolingua/Digraph.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/study/gene/tetrad/gene/algorithm/biolingua/Digraph.java @@ -51,7 +51,7 @@ public class Digraph extends BasicGraph { /** * Creates a OldDigraph with gName name, and n nodes. * - * @param gName the name of the graph + * @param gName the name of the graph * @param nNodes the number of nodes */ public Digraph(String gName, int nNodes) { @@ -69,6 +69,8 @@ public Digraph(String fname) throws IOException { /** * Copy constructor. + * + * @param digraph the graph to copy. */ public Digraph(Digraph digraph) { this("Clone_of_[" + digraph + "]", digraph.nNodes); @@ -82,6 +84,7 @@ public Digraph(Digraph digraph) { /** * Returns a clone of this graph + * @return a clone of this graph */ public Object clone() { Digraph g2 = @@ -105,8 +108,9 @@ protected void initializeEdges() { /** * Sets a value of edge between nodes i and j - * @param i the first node - * @param j the second node + * + * @param i the first node + * @param j the second node * @param value the value of the edge */ public void setEdge(int i, int j, double value) { @@ -125,8 +129,10 @@ public void setEdge(int i, int j, double value) { /** * Returns the value of edge between nodes i and j + * * @param i the first node * @param j the second node + * @return the value of edge between nodes i and j */ public double getEdge(int i, int j) { return this.getEdges().getDoubleValue(i, j); @@ -134,6 +140,7 @@ public double getEdge(int i, int j) { /** * Returns a string representation of the set of edges in this graph + * * @return a string representation of the set of edges in this graph. */ public String EdgesToString() { @@ -154,6 +161,7 @@ public String EdgesToString() { /** * Returns the number of parents of node i. + * * @param i the node * @return the number of parents of node i. */ @@ -167,7 +175,9 @@ public int getNumParents(int i) { /** * Returns an array with the indexes of the parents of node i. If node i has no parents it returns an array of size * 0 (e.g. not null) + * * @param j the index of the node + * @return */ public int[] getParents(int j) { if ((j < 0) || (j >= this.nNodes)) { @@ -186,6 +196,7 @@ public int[] getParents(int j) { /** * Returns the edge matrix. + * * @return the edge matrix. */ public MatrixF getEdges() { diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/study/gene/tetrad/gene/history/BooleanFunction.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/study/gene/tetrad/gene/history/BooleanFunction.java index 1c2db5b9e2..11d05df60c 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/study/gene/tetrad/gene/history/BooleanFunction.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/study/gene/tetrad/gene/history/BooleanFunction.java @@ -26,6 +26,7 @@ import java.io.IOException; import java.io.ObjectInputStream; +import java.io.Serial; /** * Stores a boolean function from a set of boolean-valued parents to a single boolean-valued column. @@ -33,21 +34,14 @@ * @author josephramsey */ public class BooleanFunction implements TetradSerializable { + @Serial private static final long serialVersionUID = 23L; - /** - * The array of parents for the stored boolean function. - * - * @serial - */ + // The array of parents for the stored boolean function. private final IndexedParent[] parents; - /** - * The stored boolean function. The order of the rows (for the given parents array, for two parents) is 00, 01, 10, - * 11, and so on for higher numbers of parents. - * - * @serial - */ + // The stored boolean function. The order of the rows (for the given parents array, for two parents) is 00, 01, 10, + // 11, and so on for higher numbers of parents. private final boolean[] lookupTable; //==============================CONSTRUCTORS=========================// @@ -81,6 +75,7 @@ public BooleanFunction(IndexedParent[] parents) { /** * Generates a simple exemplar of this class to test serialization. + * @return a simple exemplar of this class to test serialization. */ public static BooleanFunction serializableInstance() { IndexedParent[] parents = new IndexedParent[2]; @@ -105,6 +100,8 @@ public Object[] getParents() { * values, use the method * getRow * + * @param row the row of the table. + * @return the value in the table. * @see #getRow */ public boolean getValue(int row) { @@ -116,6 +113,8 @@ public boolean getValue(int row) { * values, use the method * getRow * + * @param row the row of the table. + * @param value the value to set. * @see #getRow */ public void setValue(int row, boolean value) { @@ -133,6 +132,7 @@ public void setValue(int row, boolean value) { * * @param parentValues an array of parent values. Should be in the same order as the parents, as returned by * getParents. + * @return the row of the table. * @see #getParents */ public int getRow(boolean[] parentValues) { @@ -148,14 +148,15 @@ public int getRow(boolean[] parentValues) { } /** - * Returns the number of rows in the table. + * @return the number of rows in the table. */ public int getNumRows() { return this.lookupTable.length; } /** - * Returns the combination of parent values represented by a given row in the table. + * @param row the row of the table. + * @return the combination of parent values represented by a given row in the table. */ public boolean[] getParentValues(int row) { @@ -188,6 +189,8 @@ public void randomize() { * "I define as a canalyzing Boolean function any Boolean function having the property that it has at least one * input having at least one value (1 or 0) which suffices to guarantee that the regulated element assumes a * specific value (1 or 0)" (page 203-4). + * + * @return true if the getModel function is canalyzing, false if not. */ public boolean isCanalyzing() { @@ -210,23 +213,19 @@ public boolean isCanalyzing() { int value = this.lookupTable[row] ? 1 : 0; int parentValue = (row / jump) % 2 == 0 ? 1 : 0; - if (-2 == lastValues[parentValue]) { - - // The pattern's already been broken for this - // value. - } else if (value == lastValues[parentValue]) { + if (-2 != lastValues[parentValue]) { + if (value != lastValues[parentValue]) { + if (-1 == lastValues[parentValue]) { - // We're in the middle of a pattern for this - // value; keep going. - } else if (-1 == lastValues[parentValue]) { + // We're encountering this parent value for the + // first time. + lastValues[parentValue] = value; + } else { - // We're encountering this parent value for the - // first time. - lastValues[parentValue] = value; - } else { - - // The pattern has just been broken. - lastValues[parentValue] = -2; + // The pattern has just been broken. + lastValues[parentValue] = -2; + } + } } } @@ -301,19 +300,12 @@ public String toString() { * semantic checks can be specified and do not need to stay the same from version to version. A readObject method of * this form may be added to any class, even if Tetrad sessions were previously saved out using a version of the * class that didn't include it. (That's what the "s.defaultReadObject();" is for. See J. Bloch, Effective Java, for - * help. + * help.) */ + @Serial private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException { s.defaultReadObject(); - - if (this.parents == null) { - throw new NullPointerException(); - } - - if (this.lookupTable == null) { - throw new NullPointerException(); - } } } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/study/gene/tetrad/gene/history/BooleanGlassFunction.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/study/gene/tetrad/gene/history/BooleanGlassFunction.java index 562dcfa3d1..3a94ff69c2 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/study/gene/tetrad/gene/history/BooleanGlassFunction.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/study/gene/tetrad/gene/history/BooleanGlassFunction.java @@ -27,85 +27,51 @@ import java.io.IOException; import java.io.ObjectInputStream; +import java.io.Serial; import java.util.ArrayList; import java.util.List; /** - *

                Updates a gene given a history using the formula Gi.0 = max(Gi.1 - - * decayRate * -Gi.1 + booleanInfluenceRate * F(Parents(Gi) in the graph \ Gi.1), lowerBound), as described in Edwards - * and Glass, (2000), "Combinatorial explosion in model gene networks", American Institute of Physics. F is a function - * from R^n to R, where each input to the function is sent to -1.0 if it is < 0.0 and +1.0 if is it >= 0.0 and the - * combination of -1.0's and +1.0's is then used to look up a value in a boolean table. The output of the function is - * -1.0 or 1.0. A random boolean Glass fuction is a boolean Glass function in which the boolean lookup table is chosen - * randomly. The procedure used here is as follows. For each factor fi, the lag graph supplied in the constructor - * specifies a set of causal parents among the lagged factors. If fi:1 appears as a causal parent, it is removed from - * the set. The result is a set of n causal parents. A random boolean function is constructed for these n causal - * parents (with 2^n rows) for which each causal parent is "effective"--that is, for which there is some combination of - * the other causal parents for which the lookup table maps either to true or to false depending on the value of the - * given causal parent.

                The basal expression level is used in these functions as a threshold, above which a lookup - * value of true is used for the boolean tables and below which a lookup value of false is - * used. A return value of - * true from the boolean lookup is then mapped to some double - * value, which we call the the "true value," and a return value of - * false is mapped to some other (lesser) double value, which we - * call the "false value." The authors allow for the possibility of setting the basal expression to 0.5 and using 0.0 as - * the false value and 1.0 as the true value. Generalizing, we include a constructor to allow the basalExpression, true - * value and false value to be set by the user, with the only condition being that the false value must be less than the - * true value. + * Updates a gene given a history using the formula Gi.0 = max(Gi.1 - decayRate * -Gi.1 + booleanInfluenceRate * + * F(Parents(Gi) in the graph \ Gi.1), lowerBound), as described in Edwards and Glass, (2000), "Combinatorial explosion + * in model gene networks", American Institute of Physics. F is a function from R^n to R, where each input to the + * function is sent to -1.0 if it is < 0.0 and +1.0 if is it >= 0.0 and the combination of -1.0's and +1.0's is + * then used to look up a value in a boolean table. The output of the function is -1.0 or 1.0. A random boolean Glass + * fuction is a boolean Glass function in which the boolean lookup table is chosen randomly. The procedure used here is + * as follows. For each factor fi, the lag graph supplied in the constructor specifies a set of causal parents among + * the lagged factors. If fi:1 appears as a causal parent, it is removed from the set. The result is a set of n causal + * parents. A random boolean function is constructed for these n causal parents (with 2^n rows) for which each causal + * parent is "effective"--that is, for which there is some combination of the other causal parents for which the lookup + * table maps either to true or to false depending on the value of the given causal parent. + *

                + * The basal expression level is used in these functions as a threshold, above which a lookup value of true is used for + * the boolean tables and below which a lookup value of false is used. A return value of true from the boolean lookup is + * then mapped to some double value, which we call the "true value," and a return value of false is mapped to some + * other (lesser) double value, which we call the "false value." The authors allow for the possibility of setting the + * basal expression to 0.5 and using 0.0 as the false value and 1.0 as the true value. Generalizing, we include a + * constructor to allow the basalExpression, true value and false value to be set by the user, with the only condition + * being that the false value must be less than the true value. * * @author josephramsey */ public class BooleanGlassFunction implements UpdateFunction { - private static final long serialVersionUID = 23L; - /** - * The indexed connectivity "snapshot" of the lag graph. - * - * @serial - */ + @Serial + private static final long serialVersionUID = 23L; + // The indexed connectivity "snapshot" of the lag graph. private final IndexedLagGraph connectivity; - - /** - * Stores a boolean function for each factor from a preselected set of lagged factors to the given factor. - * - * @serial - */ + // Stores a boolean function for each factor from a preselected set of lagged factors to the given factor. private final BooleanFunction[] booleanFunctions; - - /** - * Error distributions from which errors are drawn for each of the factors. - * - * @serial - */ + // Error distributions from which errors are drawn for each of the factors. private final Distribution[] errorDistributions; - - /** - * The lower bound for expression levels. Expression levels that wander below this bound will be set to this bound. - * - * @serial - */ + // The lower bound for expression levels. Expression levels that wander below this bound will be set to this bound. private double lowerBound; - - /** - * The basalExpression for determining whether history expression levels should be mapped to "true" or "false" for - * purposes of looking up output values in the Boolean function table. - * - * @serial - */ + // The basalExpression for determining whether history expression levels should be mapped to "true" or "false" for + // purposes of looking up output values in the Boolean function table. private double basalExpression; - - /** - * The rate at which expression levels for a gene tend to return to basal level. - * - * @serial - */ + // The rate at which expression levels for a gene tend to return to basal level. private double decayRate; - - /** - * The rate at which the F function (with outputs -1 and +1) affects the update for a gene. - * - * @serial - */ + // The rate at which the F function (with outputs -1 and +1) affects the update for a gene. private double booleanInfluenceRate; //=============================CONSTRUCTORS=========================// @@ -170,13 +136,13 @@ public BooleanGlassFunction(LagGraph lagGraph, double lowerBound, // The parents of the boolean function have to be // IndexedParent's and cannot include the factor // itself one time step back. - List parentList = new ArrayList(); + List parentList = new ArrayList<>(); for (int j = 0; j < this.connectivity.getNumParents(i); j++) { IndexedParent parent = this.connectivity.getParent(i, j); parentList.add(parent); } - IndexedParent[] parents = (IndexedParent[]) parentList.toArray( + IndexedParent[] parents = parentList.toArray( new IndexedParent[0]); this.booleanFunctions[i] = new BooleanFunction(parents); @@ -200,17 +166,15 @@ public static BooleanGlassFunction serializableInstance() { return new BooleanGlassFunction(BasicLagGraph.serializableInstance()); } - //===============================PUBLIC METHODS========================// - /** - * Returns the indexed connectivity. + * @return the indexed connectivity. */ public IndexedLagGraph getIndexedLagGraph() { return this.connectivity; } /** - * Returns the basalExpression. + * @return the basalExpression. */ public double getBasalExpression() { return this.basalExpression; @@ -218,6 +182,8 @@ public double getBasalExpression() { /** * Sets the basalExpression. + * + * @param basalExpression the new basalExpression. */ public void setBasalExpression(double basalExpression) { this.basalExpression = basalExpression; @@ -225,6 +191,10 @@ public void setBasalExpression(double basalExpression) { /** * Returns the value of the function. + * + * @param factor the index of the factor to calculate a new value for. + * @param history the history using which the new value is to be calculated. + * @return the value of the function. */ public double getValue(int factor, double[][] history) { // 2/15/02: Cutuff expression levels at the low @@ -274,18 +244,18 @@ public double getFValue(int factor, double[][] history) { // We return 1.0 and -1.0 because we use a basalExpression of // 0.0. (If the basalExpression were 1/2, we would use 1 and 0.) - /** - * The real number that is returned if the value from the Boolean lookup - * table is "true". Must be > basalExpression. - * - * @serial + /* + The real number that is returned if the value from the Boolean lookup + table is "true". Must be > basalExpression. + + @serial */ double trueValue = 1.0; - /** - * The real number that is returned if the value from the Boolean lookup - * table is "false". Must be < basalExpression. - * - * @serial + /* + The real number that is returned if the value from the Boolean lookup + table is "false". Must be < basalExpression. + + @serial */ double falseValue = -1.0; return functionValue ? trueValue : falseValue; @@ -293,14 +263,15 @@ public double getFValue(int factor, double[][] history) { } /** - * Returns the boolean function for the given factor. + * @param factor the index of the factor to calculate a new value for. + * @return the boolean function for the given factor. */ public BooleanFunction getSubFunction(int factor) { return this.booleanFunctions[factor]; } /** - * Returns the rate at which expression levels tend to return to equilibrium. + * @return the rate at which expression levels tend to return to equilibrium. */ public double getDecayRate() { return this.decayRate; @@ -308,6 +279,8 @@ public double getDecayRate() { /** * Sets the rate at which expression levels tend to return to equilibrium. Must be > 0.0 and <= 1.0. + * + * @param decayRate the new decay rate. */ public void setDecayRate(double decayRate) { @@ -321,7 +294,7 @@ public void setDecayRate(double decayRate) { } /** - * Returns the rate at which Boolean Glass subfunctions tend to affect the update. + * @return the rate at which Boolean Glass subfunctions tend to affect the update. */ public double getBooleanInfluenceRate() { return this.booleanInfluenceRate; @@ -330,6 +303,8 @@ public double getBooleanInfluenceRate() { /** * Sets the rate at which the output of the Glass function influences the change in expression level of a gene. Must * be > 0.0. + * + * @param booleanInfluenceRate the new boolean influence rate. */ public void setBooleanInfluenceRate(double booleanInfluenceRate) { @@ -350,10 +325,10 @@ public void setLowerBound(double lowerBound) { } /** - * Method setIntenalNoiseModel + * Sets the error distribution for the factor'th factor. * - * @param factor - * @param distribution + * @param factor the factor in question. + * @param distribution the error distribution for factor. */ public void setErrorDistribution(int factor, Distribution distribution) { @@ -375,14 +350,14 @@ public Distribution getErrorDistribution(int factor) { } /** - * Returns the number of factors in the history. This is used to set up the initial history array. + * @return the number of factors in the history. This is used to set up the initial history array. */ public int getNumFactors() { return this.connectivity.getNumFactors(); } /** - * Returns the max lag of the history. This is used to set up the initial history array. + * @return the max lag of the history. This is used to set up the initial history array. */ public int getMaxLag() { int maxLag = 0; @@ -405,6 +380,7 @@ public int getMaxLag() { * class that didn't include it. (That's what the "s.defaultReadObject();" is for. See J. Bloch, Effective Java, for * help. */ + @Serial private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException { s.defaultReadObject(); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/study/gene/tetrad/gene/history/UpdateFunction.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/study/gene/tetrad/gene/history/UpdateFunction.java index de9a3a077b..1d9a79a3ac 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/study/gene/tetrad/gene/history/UpdateFunction.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/study/gene/tetrad/gene/history/UpdateFunction.java @@ -24,15 +24,15 @@ import edu.cmu.tetrad.util.TetradSerializable; /** - *

                Implements a function from the previous time steps of a history array to - * the getModel time step. The function is implemented factor by factor; for each factor, the indexed connectivity - * specifies a specific set of parents (IndexedParents) that the function is permitted to depend on for that factor; the - * getLabel method returns the value for that set of parents in the history. The update function may optionally be - * associated with an IndexedLagGraph to provide information about the intended graphical structure of the - * function (say, from a causal point of view). This IndexedLagGraph gives information about the string names and order - * of the factors and the number and order of the parents (IndexedParent's) for each factor. This information should be - * encoded in the function itself, but there is no requirement that the function be checked against the graph explicitly - * to make sure the graph is actually implemented. + * Implements a function from the previous time steps of a history array to the getModel time step. The function is + * implemented factor by factor; for each factor, the indexed connectivity specifies a specific set of parents + * (IndexedParents) that the function is permitted to depend on for that factor; the getLabel method returns the value + * for that set of parents in the history. The update function may optionally be associated with an IndexedLagGraph to + * provide information about the intended graphical structure of the function (say, from a causal point of view). + * This IndexedLagGraph gives information about the string names and order of the factors and the number and order of + * the parents (IndexedParent's) for each factor. This information should be encoded in the function itself, but there + * is no requirement that the function be checked against the graph explicitly to make sure the graph is actually + * implemented. * * @author josephramsey */ @@ -40,7 +40,7 @@ public interface UpdateFunction extends TetradSerializable { long serialVersionUID = 23L; /** - * Returns the indexed lag graph, if one is available. + * @return the indexed lag graph, if one is available. */ IndexedLagGraph getIndexedLagGraph(); @@ -54,12 +54,12 @@ public interface UpdateFunction extends TetradSerializable { double getValue(int factorIndex, double[][] history); /** - * Returns the number of factors in the history. This is used to set up the initial history array. + * @return the number of factors in the history. This is used to set up the initial history array. */ int getNumFactors(); /** - * Returns the max lag of the gene history. This is used to set up the initial history array. + * @return the max lag of the gene history. This is used to set up the initial history array. */ int getMaxLag(); } diff --git a/tetrad-lib/src/main/java/edu/pitt/dbmi/algo/bayesian/constraint/inference/BCCausalInference.java b/tetrad-lib/src/main/java/edu/pitt/dbmi/algo/bayesian/constraint/inference/BCCausalInference.java index c713d17e40..1c23193d78 100644 --- a/tetrad-lib/src/main/java/edu/pitt/dbmi/algo/bayesian/constraint/inference/BCCausalInference.java +++ b/tetrad-lib/src/main/java/edu/pitt/dbmi/algo/bayesian/constraint/inference/BCCausalInference.java @@ -30,7 +30,6 @@ * @author Kevin V. Bui (kvb2@pitt.edu) */ public class BCCausalInference { - private static final double PESS_VALUE = 1.0; private final int numberOfNodes; private final int numberOfCases; @@ -44,6 +43,13 @@ public class BCCausalInference { private final int[] nodeDimension; private final int[][] cases; + /** + * Constructor + * + * @param nodeDimension nodeDimension[0] is the number of nodes, nodeDimension[1] is the number of cases, and the + * rest are the dimensions of the nodes. + * @param cases cases[0] is the number of cases, and the rest are the cases. + */ public BCCausalInference(int[] nodeDimension, int[][] cases) { this.nodeDimension = nodeDimension; this.cases = cases; @@ -74,9 +80,7 @@ private static double lnXpluslnY(double lnX, double lnY) { double lnYminusLnX = lnY - lnX; - return (lnYminusLnX < Double.MIN_EXPONENT) - ? lnX - : FastMath.log1p(FastMath.exp(lnYminusLnX)) + lnX; + return (lnYminusLnX < Double.MIN_EXPONENT) ? lnX : FastMath.log1p(FastMath.exp(lnYminusLnX)) + lnX; } /** @@ -206,10 +210,12 @@ private double scoreNode(int node, int whichList, CountsTracker countsTracker) { } /** - * @param node - * @param instancePtr + * This function scores a node using the first scoring function. + * + * @param node is the node being scored. + * @param instancePtr is the pointer to the first instance of the node. * @param q is the number of possible joint instantiation of the parents of the parents of the node. - * @return + * @return the score of the node. */ private double scoringFn1(int node, int instancePtr, double q, CountsTracker countsTracker) { int[] counts = countsTracker.counts; @@ -232,9 +238,9 @@ private double scoringFn1(int node, int instancePtr, double q, CountsTracker cou /** * Computes the K2 score. * - * @param node - * @param instancePtr - * @return + * @param node is the node being scored. + * @param instancePtr is the pointer to the first instance of the node. + * @return the score of the node. */ private double scoringFn2(int node, int instancePtr, CountsTracker countsTracker) { int[] counts = countsTracker.counts; @@ -252,6 +258,13 @@ private double scoringFn2(int node, int instancePtr, CountsTracker countsTracker return scoreNI; } + /** + * This function files a case for a node. + * + * @param node is the node being filed. + * @param casei is the case being filed. + * @param countsTracker is the tracker for the counts. + */ private void fileCase(int node, int casei, CountsTracker countsTracker) { int nodeDim = (node > this.numberOfNodes) ? countsTracker.xyDim : this.nodeDimension[node]; @@ -338,6 +351,12 @@ private void fileCase(int node, int casei, CountsTracker countsTracker) { counts[cPtr + nodeValue - 1]++; } + /** + * This function creates a tracker for the counts. + * + * @param z is the set of nodes. + * @return the tracker for the counts. + */ private CountsTracker createCountsTracker(int[] z) { CountsTracker tracker = new CountsTracker(); tracker.numOfNodes = this.numberOfNodes; @@ -367,15 +386,22 @@ private CountsTracker createCountsTracker(int[] z) { * prior of 0.5. It can be revised to return an informative prior. The code that calls priorIndependent() currently * assumes that it returns a value in (0, 1), and thus, does not return 0 or 1. * - * @param x - * @param y - * @param z - * @return + * @param x is the node x + * @param y is the node y + * @param z is the set of nodes + * @return the prior probability that X independent Y given Z */ private double priorIndependent(int x, int y, int[] z) { return 0.5; // currently assumes uniform priors } + /** + * This function computes the log of the factorial of the numbers from 1 to maxCases + maxValues. + * + * @param maxCases is the maximum number of cases + * @param maxValues is the maximum number of values + * @return the log of the factorial of the numbers from 1 to maxCases + maxValues + */ private double[] computeLogFactorial(int maxCases, int maxValues) { int size = (2 * maxCases) + maxValues; double[] logFact = new double[size + 1]; @@ -386,6 +412,12 @@ private double[] computeLogFactorial(int maxCases, int maxValues) { return logFact; } + /** + * This function computes the log of the gamma function. + * + * @param xx is the value for which the log of the gamma function is computed. + * @return the log of the gamma function. + */ private double gammln(double xx) { if (xx == 1) { return 0; // this is a correction to a bug that used to be here @@ -399,20 +431,18 @@ private double gammln(double xx) { } } + /** + * This function computes the log of the gamma function for values greater than 1. + * + * @param xx is the value for which the log of the gamma function is computed. + * @return the log of the gamma function. + */ private double gammlnCore(double xx) { final double stp = 2.50662827465; final double half = 0.5; final double one = 1.0; final double fpf = 5.5; - double[] cof = { - 0, - 76.18009173, - -86.50532033, - 24.01409822, - -1.231739516, - 0.120858003E-2, - -0.536382E-5 - }; + double[] cof = {0, 76.18009173, -86.50532033, 24.01409822, -1.231739516, 0.120858003E-2, -0.536382E-5}; double x = xx - one; double tmp = x + fpf; @@ -426,11 +456,16 @@ private double gammlnCore(double xx) { return tmp + FastMath.log(stp * ser); } + /** + * An enum for the type of operation. + */ public enum OP { - DEPENDENT, - INDEPENDENT + DEPENDENT, INDEPENDENT } + /** + * This class is a tracker for the counts. + */ private static class CountsTracker { int numOfNodes; From a83a0541808c3673041e37f62da96c1f9222a71a Mon Sep 17 00:00:00 2001 From: jdramsey Date: Wed, 31 Jan 2024 20:02:51 -0500 Subject: [PATCH 147/163] Cleanup. --- .../java/edu/cmu/tetrad/data/DataSet.java | 33 +++++++- .../java/edu/cmu/tetrad/data/IDataReader.java | 7 -- .../constraint/inference/BCInference.java | 11 ++- .../BayesianConstraintInference.java | 1 + .../BayesianConstraintInferenceTest.java | 1 + .../constraint/search/PagSamplingRfci.java | 56 +++++++++++++ .../bayesian/constraint/search/RfciBsc.java | 72 +++++++++++++++++ .../resampling/GeneralResamplingSearch.java | 81 ++++++++++++++++++- .../resampling/GeneralResamplingTest.java | 57 +++++++++++++ .../edu/pitt/isp/sverchkov/data/AdTree.java | 8 +- .../pitt/isp/sverchkov/data/AdTreeHelper.java | 4 +- .../pitt/isp/sverchkov/data/AdTreeTest.java | 5 +- .../pitt/isp/sverchkov/data/DataTable.java | 13 +++ .../isp/sverchkov/data/DataTableImpl.java | 17 +++- .../pitt/isp/sverchkov/data/DataTools.java | 16 +++- .../src/main/java/jgpml/CsvtoMatrix.java | 8 +- .../src/main/java/jgpml/GaussianProcess.java | 25 +----- .../jgpml/covariancefunctions/CovLINard.java | 5 ++ .../jgpml/covariancefunctions/CovLINone.java | 6 ++ .../jgpml/covariancefunctions/CovNNone.java | 16 ++-- .../covariancefunctions/CovNNoneNoise.java | 8 ++ .../jgpml/covariancefunctions/CovSEiso.java | 29 ++----- .../jgpml/covariancefunctions/CovSum.java | 6 +- .../CovarianceFunction.java | 3 + .../covariancefunctions/MatrixOperations.java | 2 - 25 files changed, 408 insertions(+), 82 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/data/DataSet.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/data/DataSet.java index 0a5e5e0efa..f650a64492 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/data/DataSet.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/data/DataSet.java @@ -40,12 +40,16 @@ public interface DataSet extends DataModel { /** * Adds the given variable to the data set. * + * @param variable The variable to add. * @throws IllegalArgumentException if the variable is neither continuous nor discrete. */ void addVariable(Node variable); /** * Adds the given variable at the given index. + * + * @param index The index at which to add the variable. + * @param variable The variable to add. */ void addVariable(int index, Node variable); @@ -53,6 +57,8 @@ public interface DataSet extends DataModel { * Changes the variable for the given column from from to * to. Supported currently only for discrete variables. * + * @param from The variable to change. + * @param to The variable to change to. * @throws IllegalArgumentException if the given change is not supported. */ void changeVariable(Node from, Node to); @@ -66,20 +72,26 @@ public interface DataSet extends DataModel { * Ensures that the dataset has at least columns columns. Used for pasting data into the dataset. When * creating new columns, names in the excludedVarialbeNames list may not be used. The purpose of this * is to allow these names to be set later by the calling class, without incurring conflicts. + * + * @param columns The number of columns to ensure. + * @param excludedVariableNames The names of variables that should not be used for new columns. */ void ensureColumns(int columns, List excludedVariableNames); /** - * Returns true if and only if this data set contains at least one missing value. + * @return true if and only if this data set contains at least one missing value. */ boolean existsMissingValue(); /** * Ensures that the dataset has at least rows rows. Used for pasting data into the dataset. + * + * @param rows The number of rows to ensure. */ void ensureRows(int rows); /** + * @param variable The variable to check. * @return the column index of the given variable. */ int getColumn(Node variable); @@ -99,6 +111,8 @@ public interface DataSet extends DataModel { Matrix getCovarianceMatrix(); /** + * @param row The index of the case. + * @param column The index of the variable. * @return the value at the given row and column as a double. For discrete data, returns the integer value cast to a * double. */ @@ -147,11 +161,13 @@ public interface DataSet extends DataModel { int[] getSelectedIndices(); /** + * @param column The index of the variable. * @return the variable at the given column. */ Node getVariable(int column); /** + * @param name The name of the variable. * @return the variable with the given name. */ Node getVariable(String name); @@ -185,27 +201,36 @@ public interface DataSet extends DataModel { boolean isMixed(); /** + * @param variable The variable to check. * @return true iff the given column has been marked as selected. */ boolean isSelected(Node variable); /** * Removes the variable (and data) at the given index. + * + * @param index The index of the variable to remove. */ void removeColumn(int index); /** * Removes the given variable, along with all of its data. + * + * @param variable The variable to remove. */ void removeColumn(Node variable); /** * Removes the given columns from the data set. + * + * @param selectedCols The indices of the columns to remove. */ void removeCols(int[] selectedCols); /** * Removes the given rows from the data set. + * + * @param selectedRows The indices of the rows to remove. */ void removeRows(int[] selectedRows); @@ -215,6 +240,7 @@ public interface DataSet extends DataModel { * * @param row The index of the case. * @param column The index of the variable. + * @param value The value to set. */ void setDouble(int row, int column, double value); @@ -222,8 +248,9 @@ public interface DataSet extends DataModel { * Sets the value at the given (row, column) to the given int value, assuming the variable for the column is * discrete. * - * @param row The index of the case. - * @param col The index of the variable. + * @param row The index of the case. + * @param col The index of the variable. + * @param value The value to set. */ void setInt(int row, int col, int value); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/data/IDataReader.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/data/IDataReader.java index 38f66cc916..b2040105b4 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/data/IDataReader.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/data/IDataReader.java @@ -13,13 +13,6 @@ public interface IDataReader { */ void setDelimiter(DelimiterType delimiterType); - /** - * True if case IDs are provided in the first column of the data. - * - * @deprecated - */ - void setIdsSupplied(boolean caseIdsPresent); - /** * The String identifier of the case ID column. * diff --git a/tetrad-lib/src/main/java/edu/pitt/dbmi/algo/bayesian/constraint/inference/BCInference.java b/tetrad-lib/src/main/java/edu/pitt/dbmi/algo/bayesian/constraint/inference/BCInference.java index 5adf9035ce..8d8063789b 100644 --- a/tetrad-lib/src/main/java/edu/pitt/dbmi/algo/bayesian/constraint/inference/BCInference.java +++ b/tetrad-lib/src/main/java/edu/pitt/dbmi/algo/bayesian/constraint/inference/BCInference.java @@ -324,6 +324,7 @@ private double scoreNode(int node) { /** * @param q is the number of possible joint instantiation of the parents of the parents of the node. * @param pess is the prior equivalent sample size + * @return the score of the node */ private double scoringFn1(int node, int instancePtr, double q, double pess) { int Nij = 0; @@ -509,14 +510,20 @@ private int findMaxValue(int[] nodeDimension) { return maxValue; } + /** + * Sets the prior equivalent sample size. + * + * @param priorEquivalentSampleSize the prior equivalent sample size + */ public void setPriorEqivalentSampleSize(double priorEquivalentSampleSize) { this.priorEquivalentSampleSize = priorEquivalentSampleSize; } + /** + * Enum for the type of constraint. + */ public enum OP { - independent, dependent - } } diff --git a/tetrad-lib/src/main/java/edu/pitt/dbmi/algo/bayesian/constraint/inference/BayesianConstraintInference.java b/tetrad-lib/src/main/java/edu/pitt/dbmi/algo/bayesian/constraint/inference/BayesianConstraintInference.java index 937009d1b6..834e37763f 100644 --- a/tetrad-lib/src/main/java/edu/pitt/dbmi/algo/bayesian/constraint/inference/BayesianConstraintInference.java +++ b/tetrad-lib/src/main/java/edu/pitt/dbmi/algo/bayesian/constraint/inference/BayesianConstraintInference.java @@ -51,6 +51,7 @@ public BayesianConstraintInference() { /** * Main method. + * * @param args the command line arguments */ public static void main(String[] args) { diff --git a/tetrad-lib/src/main/java/edu/pitt/dbmi/algo/bayesian/constraint/inference/BayesianConstraintInferenceTest.java b/tetrad-lib/src/main/java/edu/pitt/dbmi/algo/bayesian/constraint/inference/BayesianConstraintInferenceTest.java index dbd9f81274..81b298e1b8 100644 --- a/tetrad-lib/src/main/java/edu/pitt/dbmi/algo/bayesian/constraint/inference/BayesianConstraintInferenceTest.java +++ b/tetrad-lib/src/main/java/edu/pitt/dbmi/algo/bayesian/constraint/inference/BayesianConstraintInferenceTest.java @@ -36,6 +36,7 @@ public BayesianConstraintInferenceTest() { /** * Main method. + * * @param args the command line arguments */ public static void main(String[] args) { diff --git a/tetrad-lib/src/main/java/edu/pitt/dbmi/algo/bayesian/constraint/search/PagSamplingRfci.java b/tetrad-lib/src/main/java/edu/pitt/dbmi/algo/bayesian/constraint/search/PagSamplingRfci.java index 83166d181d..2b5255f7be 100644 --- a/tetrad-lib/src/main/java/edu/pitt/dbmi/algo/bayesian/constraint/search/PagSamplingRfci.java +++ b/tetrad-lib/src/main/java/edu/pitt/dbmi/algo/bayesian/constraint/search/PagSamplingRfci.java @@ -37,10 +37,20 @@ public class PagSamplingRfci implements IGraphSearch { */ private Knowledge knowledge; + /** + * Constructor. + * + * @param dataSet the data set. + */ public PagSamplingRfci(DataSet dataSet) { this.dataSet = dataSet; } + /** + * Search for a PAG. + * + * @return a PAG. + */ @Override public Graph search() { List graphs = runSearches(); @@ -48,6 +58,12 @@ public Graph search() { return GraphSampling.createGraphWithHighProbabilityEdges(graphs); } + /** + * Create tasks for parallel execution. + * + * @param numOfTasks the number of tasks. + * @return a list of callable tasks. + */ List> createTasks(int numOfTasks) { List> callableTasks = new LinkedList<>(); @@ -105,34 +121,74 @@ private void shutdownAndAwaitTermination(ExecutorService pool) { } } + /** + * Set the number of randomized search models. + * + * @param numRandomizedSearchModels the number of randomized search models. + */ public void setNumRandomizedSearchModels(int numRandomizedSearchModels) { this.numRandomizedSearchModels = numRandomizedSearchModels; } + /** + * Set the verbose flag. + * + * @param verbose the verbose flag. + */ public void setVerbose(boolean verbose) { this.verbose = verbose; } + /** + * Set the depth. + * + * @param depth the depth. + */ public void setDepth(int depth) { this.depth = depth; } + /** + * Set the maximum path length. + * + * @param maxPathLength the maximum path length. + */ public void setMaxPathLength(int maxPathLength) { this.maxPathLength = maxPathLength; } + /** + * Set the threshold. + * + * @param threshold the threshold. + */ public void setThreshold(boolean threshold) { this.threshold = threshold; } + /** + * Set the cutoff. + * + * @param cutoff the cutoff. + */ public void setCutoff(double cutoff) { this.cutoff = cutoff; } + /** + * Set the prior equivalent sample size. + * + * @param priorEquivalentSampleSize the prior equivalent sample size. + */ public void setPriorEquivalentSampleSize(double priorEquivalentSampleSize) { this.priorEquivalentSampleSize = priorEquivalentSampleSize; } + /** + * Set the knowledge. + * + * @param knowledge the knowledge. + */ public void setKnowledge(Knowledge knowledge) { this.knowledge = knowledge; } diff --git a/tetrad-lib/src/main/java/edu/pitt/dbmi/algo/bayesian/constraint/search/RfciBsc.java b/tetrad-lib/src/main/java/edu/pitt/dbmi/algo/bayesian/constraint/search/RfciBsc.java index c2066e294e..669a1a1d77 100644 --- a/tetrad-lib/src/main/java/edu/pitt/dbmi/algo/bayesian/constraint/search/RfciBsc.java +++ b/tetrad-lib/src/main/java/edu/pitt/dbmi/algo/bayesian/constraint/search/RfciBsc.java @@ -220,6 +220,11 @@ private static double getLnProb(Graph pag, Map H) { return lnQ; } + /** + * Performs the search. + * + * @return the graph that was learned. + */ @Override public Graph search() { long stop = 0; @@ -246,6 +251,9 @@ class SearchPagTask implements Callable { private final IndTestProbabilistic test; private final Rfci rfci; + /** + * Constructor. + */ public SearchPagTask() { this.test = new IndTestProbabilistic(dataSet); this.test.setThreshold(RfciBsc.this.thresholdNoRandomDataSearch); @@ -256,6 +264,11 @@ public SearchPagTask() { this.rfci = new Rfci(this.test); } + /** + * Performs the search. + * @return true if the search was successful. + * @throws Exception if an error occurred. + */ @Override public Boolean call() throws Exception { @@ -338,6 +351,9 @@ class BootstrapDepDataTask implements Callable { private final IndTestProbabilistic bsTest; + /** + * Constructor. + */ public BootstrapDepDataTask(int row_index, int rows) { this.row_index = row_index; @@ -349,6 +365,12 @@ public BootstrapDepDataTask(int row_index, int rows) { } } + /** + * Performs the search. + * + * @return true if the search was successful. + * @throws Exception if an error occurred. + */ @Override public Boolean call() throws Exception { for (IndependenceFact f : hCopy.keySet()) { @@ -651,38 +673,74 @@ private List getProbability(Node node1, Node node2) { return edgeTypeProbabilities; } + /** + * Sets the number of randomized search models. + * @param numRandomizedSearchModels the number of randomized search models. + */ public void setNumRandomizedSearchModels(int numRandomizedSearchModels) { this.numRandomizedSearchModels = numRandomizedSearchModels; } + /** + * Sets the number of bootstrap samples. + * @param numBscBootstrapSamples the number of bootstrap samples. + */ public void setNumBscBootstrapSamples(int numBscBootstrapSamples) { this.numBscBootstrapSamples = numBscBootstrapSamples; } + /** + * Sets the lower bound. + * @param lowerBound the lower bound. + */ public void setLowerBound(double lowerBound) { this.lowerBound = lowerBound; } + /** + * Sets the upper bound. + * @param upperBound the upper bound. + */ public void setUpperBound(double upperBound) { this.upperBound = upperBound; } + /** + * Sets whether the output should be RBD. + * @param outputRBD true if the output should be RBD. + */ public void setOutputRBD(boolean outputRBD) { this.outputRBD = outputRBD; } + /** + * Returns the graph that was learned using the BSC-D method. + * @return + */ public Graph getGraphRBD() { return this.graphRBD; } + /** + * Returns the graph that was learned using the BSC-I method. + * @return the graph that was learned using the BSC-I method. + */ public Graph getGraphRBI() { return this.graphRBI; } + /** + * Returns the BSC-D score. + * @return the BSC-D score. + */ public double getBscD() { return this.bscD; } + /** + * Returns the BSC-I score. + * @return the BSC-I score. + */ public double getBscI() { return this.bscI; } @@ -708,6 +766,7 @@ private void shutdownAndAwaitTermination(ExecutorService pool) { /** * Sets whether verbose output should be produced. + * @param verbose true if verbose output should be produced. */ public void setVerbose(boolean verbose) { this.verbose = verbose; @@ -722,23 +781,36 @@ public PrintStream getOut() { /** * Sets the output stream that output (except for log output) should be sent to. By detault System.out. + * @param out the output stream that output (except for log output) should be sent to. */ public void setOut(PrintStream out) { this.out = out; } + /** + * @param thresholdNoRandomDataSearch the thresholdNoRandomDataSearch to set + */ public void setThresholdNoRandomDataSearch(boolean thresholdNoRandomDataSearch) { this.thresholdNoRandomDataSearch = thresholdNoRandomDataSearch; } + /** + * @param cutoffDataSearch the cutoffDataSearch to set + */ public void setCutoffDataSearch(double cutoffDataSearch) { this.cutoffDataSearch = cutoffDataSearch; } + /** + * @param thresholdNoRandomConstrainSearch the thresholdNoRandomConstrainSearch to set + */ public void setThresholdNoRandomConstrainSearch(boolean thresholdNoRandomConstrainSearch) { this.thresholdNoRandomConstrainSearch = thresholdNoRandomConstrainSearch; } + /** + * @param cutoffConstrainSearch the cutoffConstrainSearch to set + */ public void setCutoffConstrainSearch(double cutoffConstrainSearch) { this.cutoffConstrainSearch = cutoffConstrainSearch; } diff --git a/tetrad-lib/src/main/java/edu/pitt/dbmi/algo/resampling/GeneralResamplingSearch.java b/tetrad-lib/src/main/java/edu/pitt/dbmi/algo/resampling/GeneralResamplingSearch.java index ec22cd56a9..ea803a9981 100644 --- a/tetrad-lib/src/main/java/edu/pitt/dbmi/algo/resampling/GeneralResamplingSearch.java +++ b/tetrad-lib/src/main/java/edu/pitt/dbmi/algo/resampling/GeneralResamplingSearch.java @@ -3,7 +3,10 @@ import edu.cmu.tetrad.algcomparison.algorithm.Algorithm; import edu.cmu.tetrad.algcomparison.algorithm.MultiDataSetAlgorithm; import edu.cmu.tetrad.algcomparison.score.ScoreWrapper; -import edu.cmu.tetrad.data.*; +import edu.cmu.tetrad.data.DataModel; +import edu.cmu.tetrad.data.DataSet; +import edu.cmu.tetrad.data.DataTransforms; +import edu.cmu.tetrad.data.Knowledge; import edu.cmu.tetrad.graph.Graph; import edu.cmu.tetrad.util.Parameters; import edu.cmu.tetrad.util.Params; @@ -58,48 +61,100 @@ public class GeneralResamplingSearch { private int numNograph = 0; private ScoreWrapper scoreWrapper; + /** + * Constructor. + * + * @param data the data set. + * @param numberResampling the number of resampling. + */ public GeneralResamplingSearch(DataSet data, int numberResampling) { this.data = data; this.pool = ForkJoinPool.commonPool(); this.numberResampling = numberResampling; } + /** + * Constructor. + * + * @param dataSets the data sets. + * @param numberResampling the number of resampling. + */ public GeneralResamplingSearch(List dataSets, int numberResampling) { this.dataSets = dataSets; this.pool = ForkJoinPool.commonPool(); this.numberResampling = numberResampling; } + /** + * Constructor. + * + * @param algorithm the algorithm. + */ public void setAlgorithm(Algorithm algorithm) { this.algorithm = algorithm; this.multiDataSetAlgorithm = null; } + /** + * Constructor. + * + * @param multiDataSetAlgorithm the multi data set algorithm. + */ public void setMultiDataSetAlgorithm(MultiDataSetAlgorithm multiDataSetAlgorithm) { this.multiDataSetAlgorithm = multiDataSetAlgorithm; this.algorithm = null; } + /** + * Sets the number of resampling. + * + * @param percentResampleSize the resampling size. + */ public void setPercentResampleSize(double percentResampleSize) { this.percentResampleSize = percentResampleSize; } + /** + * Sets the resampling with replacement. + * + * @param resamplingWithReplacement the resampling with replacement. + */ public void setResamplingWithReplacement(boolean resamplingWithReplacement) { this.resamplingWithReplacement = resamplingWithReplacement; } + /** + * Sets whether to run in parallel. + * + * @param runParallel whether to run in parallel. + */ public void setRunParallel(boolean runParallel) { this.runParallel = runParallel; } + /** + * Sets whether to add the original dataset. + * + * @param addOriginalDataset whether to add the original dataset. + */ public void setAddOriginalDataset(boolean addOriginalDataset) { this.addOriginalDataset = addOriginalDataset; } + /** + * Sets whether to be verbose. + * + * @param verbose whether to be verbose. + */ public void setVerbose(boolean verbose) { this.verbose = verbose; } + /** + * Sets the data set. + * + * @param data the data set. + */ public void setData(DataSet data) { this.data = data; } @@ -113,6 +168,11 @@ public void setKnowledge(Knowledge knowledge) { this.knowledge = new Knowledge((Knowledge) knowledge); } + /** + * Sets the external graph. + * + * @param externalGraph the external graph. + */ public void setExternalGraph(Graph externalGraph) { this.externalGraph = externalGraph; } @@ -126,15 +186,26 @@ public PrintStream getOut() { /** * Sets the output stream that output (except for log output) should be sent to. By default System.out. + * @param out the output stream. */ public void setOut(PrintStream out) { this.out = out; } + /** + * Sets the parameters. + * + * @param parameters the parameters. + */ public void setParameters(Parameters parameters) { this.parameters = parameters; } + /** + * Performs the search. + * + * @return the list of graphs. + */ public List search() { this.graphs.clear(); @@ -259,10 +330,18 @@ public List search() { return this.graphs; } + /** + * Returns the number of no graph. + * + * @return the number of no graph. + */ public int getNumNograph() { return numNograph; } + /** + * Returns the score wrapper. + */ public void setScoreWrapper(ScoreWrapper scoreWrapper) { this.scoreWrapper = scoreWrapper; } diff --git a/tetrad-lib/src/main/java/edu/pitt/dbmi/algo/resampling/GeneralResamplingTest.java b/tetrad-lib/src/main/java/edu/pitt/dbmi/algo/resampling/GeneralResamplingTest.java index 634af00838..aa9806243a 100644 --- a/tetrad-lib/src/main/java/edu/pitt/dbmi/algo/resampling/GeneralResamplingTest.java +++ b/tetrad-lib/src/main/java/edu/pitt/dbmi/algo/resampling/GeneralResamplingTest.java @@ -39,6 +39,17 @@ public class GeneralResamplingTest { */ private Graph externalGraph; + /** + * Constructor. + * + * @param data the data set. + * @param algorithm the algorithm. + * @param numberResampling the number of resampling. + * @param percentResamplingSize the percent resampling size. + * @param resamplingWithReplacement whether resampling with replacement. + * @param edgeEnsemble the edge ensemble. + * @param addOriginalDataset whether to add the original dataset. + */ public GeneralResamplingTest( DataSet data, Algorithm algorithm, @@ -69,6 +80,17 @@ public GeneralResamplingTest( } } + /** + * Constructor. + * + * @param dataSets the data sets. + * @param multiDataSetAlgorithm the multi data set algorithm. + * @param numberResampling the number of resampling. + * @param percentResamplingSize the percent resampling size. + * @param resamplingWithReplacement whether resampling with replacement. + * @param edgeEnsemble the edge ensemble. + * @param addOriginalDataset whether to add the original dataset. + */ public GeneralResamplingTest( List dataSets, MultiDataSetAlgorithm multiDataSetAlgorithm, int numberResampling, @@ -99,6 +121,12 @@ public GeneralResamplingTest( } } + /** + * Constructor. + * + * @param truth the true graph. + * @param estimate the estimated graph. + */ public static int[][] getAdjConfusionMatrix(Graph truth, Graph estimate) { Graph complete = new EdgeListGraph(estimate.getNodes()); complete.fullyConnect(Endpoint.TAIL); @@ -134,6 +162,12 @@ private static void countAdjConfMatrix(int[][] adjAr, List edges, Graph tr } } + /** + * Constructor. + * + * @param truth the true graph. + * @param estimate the estimated graph. + */ public static int[][] getEdgeTypeConfusionMatrix(Graph truth, Graph estimate) { Graph complete = new EdgeListGraph(estimate.getNodes()); complete.fullyConnect(Endpoint.TAIL); @@ -227,6 +261,8 @@ private static void countEdgeTypeConfMatrix(int[][] edgeAr, List edges, Gr /** * Sets whether verbose output should be produced. + * + * @param verbose whether verbose output should be produced. */ public void setVerbose(boolean verbose) { this.verbose = verbose; @@ -241,11 +277,18 @@ public PrintStream getOut() { /** * Sets the output stream that output (except for log output) should be sent to. By default System.out. + * + * @param out the output stream that output (except for log output) should be sent to. */ public void setOut(PrintStream out) { this.out = out; } + /** + * Sets the parameters. + * + * @param parameters the parameters. + */ public void setParameters(Parameters parameters) { this.parameters = parameters; Object obj = parameters.get(Params.PRINT_STREAM); @@ -270,6 +313,11 @@ public void setExternalGraph(Graph externalGraph) { this.externalGraph = externalGraph; } + /** + * Runs the resampling test. + * + * @return the graph. + */ public Graph search() { long start, stop; @@ -329,10 +377,19 @@ public Graph search() { return graph; } + /** + * Sets the score wrapper. + * + * @param scoreWrapper the score wrapper. + */ public void setScoreWrapper(ScoreWrapper scoreWrapper) { this.scoreWrapper = scoreWrapper; } + /** + * Sets the independence wrapper. + * @param independenceWrapper the independence wrapper. + */ public void setIndTestWrapper(IndependenceWrapper independenceWrapper) { this.independenceWrapper = independenceWrapper; } diff --git a/tetrad-lib/src/main/java/edu/pitt/isp/sverchkov/data/AdTree.java b/tetrad-lib/src/main/java/edu/pitt/isp/sverchkov/data/AdTree.java index 96e4bb5557..c019ab2e55 100644 --- a/tetrad-lib/src/main/java/edu/pitt/isp/sverchkov/data/AdTree.java +++ b/tetrad-lib/src/main/java/edu/pitt/isp/sverchkov/data/AdTree.java @@ -49,6 +49,7 @@ public class AdTree extends AdTreeHelper { /** * Constructs an AD tree for the given data set. + * * @param data The data set. */ public AdTree(DataTable data) { @@ -108,6 +109,7 @@ public AdTree(DataTable data) { /** * Returns the number of rows in the data set. + * * @param attribute The attribute to count. * @return The number of rows in the data set. */ @@ -119,6 +121,7 @@ public List values(A attribute) { /** * Returns the number of rows in the data set. + * * @param assignment The assignment to count. * @return The number of rows in the data set. */ @@ -135,7 +138,8 @@ public int count(Map assignment) { /** * Returns the number of rows in the data set. - * @param attribute The attribute to count. + * + * @param attribute The attribute to count. * @param assignment The assignment to count. * @return The number of rows in the data set. */ @@ -154,6 +158,7 @@ public Map counts(A attribute, Map assignment) { /** * Converts to XML. + * * @return The XML document. * @throws ParserConfigurationException if something goes wrong */ @@ -163,6 +168,7 @@ public Document toXML() throws ParserConfigurationException { /** * Converts to XML. + * * @param builder The builder. * @return The XML document. */ diff --git a/tetrad-lib/src/main/java/edu/pitt/isp/sverchkov/data/AdTreeHelper.java b/tetrad-lib/src/main/java/edu/pitt/isp/sverchkov/data/AdTreeHelper.java index 7ccf40b8aa..2605c77445 100644 --- a/tetrad-lib/src/main/java/edu/pitt/isp/sverchkov/data/AdTreeHelper.java +++ b/tetrad-lib/src/main/java/edu/pitt/isp/sverchkov/data/AdTreeHelper.java @@ -26,7 +26,7 @@ import java.util.List; /** - * @author user + * @author jdramsey */ class AdTreeHelper implements Serializable { @@ -132,7 +132,7 @@ private VaryNode(int attr, int[][] array) { for (int i = 0; i < airity; i++) if (i != this.mcv) { List indexes = childArrayIndexes.get(i); - if (indexes.size() > 0) { + if (!indexes.isEmpty()) { int[][] childArray = new int[indexes.size()][]; int j = 0; for (int index : indexes) diff --git a/tetrad-lib/src/main/java/edu/pitt/isp/sverchkov/data/AdTreeTest.java b/tetrad-lib/src/main/java/edu/pitt/isp/sverchkov/data/AdTreeTest.java index 66208cdc4f..8a2c35ad6b 100644 --- a/tetrad-lib/src/main/java/edu/pitt/isp/sverchkov/data/AdTreeTest.java +++ b/tetrad-lib/src/main/java/edu/pitt/isp/sverchkov/data/AdTreeTest.java @@ -36,8 +36,9 @@ import java.util.TreeMap; /** - *

                A test of the AD tree implementation.

                - * Author : Jeremy Espino MD Created 6/24/15 3:32 PM + * A test of the AD tree implementation. + * + * @author Jeremy Espino MD Created 6/24/15 3:32 PM */ public class AdTreeTest { diff --git a/tetrad-lib/src/main/java/edu/pitt/isp/sverchkov/data/DataTable.java b/tetrad-lib/src/main/java/edu/pitt/isp/sverchkov/data/DataTable.java index dc30dac4f8..de92acb6c6 100644 --- a/tetrad-lib/src/main/java/edu/pitt/isp/sverchkov/data/DataTable.java +++ b/tetrad-lib/src/main/java/edu/pitt/isp/sverchkov/data/DataTable.java @@ -31,12 +31,25 @@ * @author YUS24 */ public interface DataTable extends Iterable> { + + /** + * @return The names of the variables in the table + */ List variables(); + /** + * @return The number of columns in the table + */ int columnCount(); + /** + * @return The number of rows in the table + */ int rowCount(); + /** + * @param row The index of the row to retrieve + */ void addRow(List row); } diff --git a/tetrad-lib/src/main/java/edu/pitt/isp/sverchkov/data/DataTableImpl.java b/tetrad-lib/src/main/java/edu/pitt/isp/sverchkov/data/DataTableImpl.java index 3864c502df..5f847f628d 100644 --- a/tetrad-lib/src/main/java/edu/pitt/isp/sverchkov/data/DataTableImpl.java +++ b/tetrad-lib/src/main/java/edu/pitt/isp/sverchkov/data/DataTableImpl.java @@ -29,35 +29,50 @@ /** * Data table implementation. * - * @author YUS24 * @param Type of variable names * @param Type of variable values + * @author YUS24 */ public class DataTableImpl implements DataTable { private final List variables; private final List> rows; + /** + * @param vars The names of the variables in the table + */ public DataTableImpl(List vars) { this.variables = Collections.unmodifiableList(new ArrayList<>(vars)); this.rows = new ArrayList<>(); } + /** + * @return The variables in the table + */ @Override public List variables() { return this.variables; } + /** + * @return The number of columns in the table + */ @Override public int columnCount() { return this.variables.size(); } + /** + * @return The number of rows in the table + */ @Override public int rowCount() { return this.rows.size(); } + /** + * @param row The index of the row to retrieve + */ @Override public void addRow(List row) { int diff --git a/tetrad-lib/src/main/java/edu/pitt/isp/sverchkov/data/DataTools.java b/tetrad-lib/src/main/java/edu/pitt/isp/sverchkov/data/DataTools.java index b02f6ab4d6..1f8024f3d7 100644 --- a/tetrad-lib/src/main/java/edu/pitt/isp/sverchkov/data/DataTools.java +++ b/tetrad-lib/src/main/java/edu/pitt/isp/sverchkov/data/DataTools.java @@ -32,11 +32,17 @@ * @author YUS24 */ public class DataTools { - public static final String NEWLINE = System.getProperty("line.separator"); public static final String DELIMITER_REGEX = " *, *"; public static final String DELIMITER = ", "; + /** + * Reads a data table from a file. + * + * @param file The file to read from + * @return The data table + * @throws FileNotFoundException if the file is not found + */ public static DataTable dataTableFromFile(File file) throws FileNotFoundException { DataTable data = null; try (Scanner in = new Scanner(file)) { @@ -47,6 +53,14 @@ public static DataTable dataTableFromFile(File file) throws File return data; } + /** + * Saves a data table to a file. + * + * @param data The data table to save + * @param dest The file to save to + * @param headers Whether to include headers + * @throws IOException if something goes wrong + */ public static void saveCSV(DataTable data, File dest, boolean headers) throws IOException { try (BufferedWriter out = new BufferedWriter(new FileWriter(dest))) { diff --git a/tetrad-lib/src/main/java/jgpml/CsvtoMatrix.java b/tetrad-lib/src/main/java/jgpml/CsvtoMatrix.java index ee159f9797..4944787bd3 100644 --- a/tetrad-lib/src/main/java/jgpml/CsvtoMatrix.java +++ b/tetrad-lib/src/main/java/jgpml/CsvtoMatrix.java @@ -39,6 +39,8 @@ /** * Simple Class to load the example data from files straight into Matrices. + * + * @author jdramsey */ public class CsvtoMatrix { @@ -46,8 +48,8 @@ public class CsvtoMatrix { * Load data * * @param filename data file - * @param sizeofInputs - * @param sizeofOutputs + * @param sizeofInputs number of input variables + * @param sizeofOutputs number of output variables * @return [X, Y] */ public static Matrix[] load(String filename, int sizeofInputs, int sizeofOutputs) { @@ -124,7 +126,7 @@ public static Matrix[] load(String filename, int sizeofInputs, int sizeofOutputs /** * Simple example of how to use this class. * - * @param args + * @param args ignored */ public static void main(String[] args) { diff --git a/tetrad-lib/src/main/java/jgpml/GaussianProcess.java b/tetrad-lib/src/main/java/jgpml/GaussianProcess.java index ff6557f362..7321feaec5 100644 --- a/tetrad-lib/src/main/java/jgpml/GaussianProcess.java +++ b/tetrad-lib/src/main/java/jgpml/GaussianProcess.java @@ -38,6 +38,8 @@ /** * Main class of the package, contains the objects that constitutes a Gaussian Process as well as the algorithm to train * the Hyperparameters and to do predictions. + * + * @author jdramsey */ public class GaussianProcess { @@ -167,7 +169,7 @@ private static boolean hasInvalidNumbers(double[] array) { /** * A simple test * - * @param args + * @param args ignored */ public static void main(String[] args) { @@ -188,17 +190,8 @@ public static void main(String[] args) { gp.train(X, Y, params0, -20); - -// int size = 100; -// Matrix Xtrain = new Matrix(size, 1); -// Matrix Ytrain = new Matrix(size, 1); -// -// Matrix Xtest = new Matrix(size, 1); -// Matrix Ytest = new Matrix(size, 1); - // half of the sinusoid uses points very close to each other and the other half uses // more sparse data - Matrix[] datastar = CsvtoMatrix.load("../armdatastar.csv", 6, 1); Matrix Xstar = datastar[0]; Matrix Ystar = datastar[1]; @@ -260,15 +253,6 @@ public double negativeLogLikelihood(Matrix logtheta, Matrix x, Matrix y, Matrix // alpha = L'\(L\y); this.alpha = GaussianProcess.bSubstitutionWithTranspose(this.L, GaussianProcess.fSubstitution(this.L, y)); -// double[][] yarr = y.getArray(); -// double[][] alphaarr = alpha.getArray(); -// double lml =0; -// for(int i=0; iCovLINone CovarianceFunction + */ public CovLINone() { } + /** + * Main method for testing purposes + */ public static void main(String[] args) { CovLINone cf = new CovLINone(); diff --git a/tetrad-lib/src/main/java/jgpml/covariancefunctions/CovNNone.java b/tetrad-lib/src/main/java/jgpml/covariancefunctions/CovNNone.java index 96919159f4..3b28b8f82e 100644 --- a/tetrad-lib/src/main/java/jgpml/covariancefunctions/CovNNone.java +++ b/tetrad-lib/src/main/java/jgpml/covariancefunctions/CovNNone.java @@ -47,26 +47,24 @@ public class CovNNone implements CovarianceFunction { double[][] k; double[][] q; + /** + * Creates a new CovNNone CovarianceFunction + */ public CovNNone() { } + /** + * Main method for testing purposes + * @param args command line arguments + */ public static void main(String[] args) { CovNNone cf = new CovNNone(); Matrix X = Matrix.identity(6, 6); Matrix logtheta = new Matrix(new double[][]{{0.1}, {0.2}}); - - Matrix z = new Matrix(new double[][]{{1, 2, 3, 4, 5, 6}, {1, 2, 3, 4, 5, 6}}); - -// System.out.println("") -// -// long start = edu.cmu.tetrad.util.Timer.currentThreadCpuTimeMilliseconds() - Matrix d = cf.computeDerivatives(logtheta, X, 1); - d.print(d.getColumnDimension(), 8); - } /** diff --git a/tetrad-lib/src/main/java/jgpml/covariancefunctions/CovNNoneNoise.java b/tetrad-lib/src/main/java/jgpml/covariancefunctions/CovNNoneNoise.java index 947762534c..0f15e1cc31 100644 --- a/tetrad-lib/src/main/java/jgpml/covariancefunctions/CovNNoneNoise.java +++ b/tetrad-lib/src/main/java/jgpml/covariancefunctions/CovNNoneNoise.java @@ -50,9 +50,17 @@ public class CovNNoneNoise implements CovarianceFunction { double[][] k; double[][] q; + /** + * Creates a new CovNNoneNoise CovarianceFunction + */ public CovNNoneNoise() { } + /** + * Main method for testing purposes + * + * @param args command line arguments + */ public static void main(String[] args) { CovarianceFunction cf = new CovNNoneNoise(); diff --git a/tetrad-lib/src/main/java/jgpml/covariancefunctions/CovSEiso.java b/tetrad-lib/src/main/java/jgpml/covariancefunctions/CovSEiso.java index e0131512c4..58d2813987 100644 --- a/tetrad-lib/src/main/java/jgpml/covariancefunctions/CovSEiso.java +++ b/tetrad-lib/src/main/java/jgpml/covariancefunctions/CovSEiso.java @@ -47,6 +47,9 @@ public class CovSEiso implements CovarianceFunction { + /** + * Creates a new CovSEiso CovarianceFunction + */ public CovSEiso() { } @@ -74,6 +77,10 @@ private static Matrix squareDist(Matrix a, Matrix b) { return C; } + /** + * Main method for testing purposes + * @param args ignored + */ public static void main(String[] args) { CovSEiso cf = new CovSEiso(); @@ -168,25 +175,3 @@ public Matrix computeDerivatives(Matrix loghyper, Matrix X, int index) { return A; } } - -// private static Matrix squareDist(Matrix a, Matrix b, Matrix Q){ -// -// if(a.getColumnDimension()!=Q.getRowDimension() || b.getColumnDimension()!=Q.getColumnDimension()) -// throw new IllegalArgumentException("Wrong size of for Q "+Q.getRowDimension()+"x"+Q.getColumnDimension()+" instead of "+a.getColumnDimension()+"x"+b.getColumnDimension()); -// -// Matrix C = new Matrix(D,1); -// -// for (int i=0; iCovarianceFunction as sum of the @@ -126,6 +126,4 @@ public Matrix computeDerivatives(Matrix loghyper, Matrix X, int index) { index -= this.idx[whichf]; return this.f[whichf].computeDerivatives(loghyperi, X, index); } - - } diff --git a/tetrad-lib/src/main/java/jgpml/covariancefunctions/CovarianceFunction.java b/tetrad-lib/src/main/java/jgpml/covariancefunctions/CovarianceFunction.java index b0703d911b..48b2e60260 100644 --- a/tetrad-lib/src/main/java/jgpml/covariancefunctions/CovarianceFunction.java +++ b/tetrad-lib/src/main/java/jgpml/covariancefunctions/CovarianceFunction.java @@ -30,6 +30,9 @@ import Jama.Matrix; +/** + * Interface for covariance functions + */ public interface CovarianceFunction { /** diff --git a/tetrad-lib/src/main/java/jgpml/covariancefunctions/MatrixOperations.java b/tetrad-lib/src/main/java/jgpml/covariancefunctions/MatrixOperations.java index 2457783ebe..5e3e5f51fb 100644 --- a/tetrad-lib/src/main/java/jgpml/covariancefunctions/MatrixOperations.java +++ b/tetrad-lib/src/main/java/jgpml/covariancefunctions/MatrixOperations.java @@ -193,7 +193,5 @@ public static Matrix std(Matrix A) { return M; } } - - } From d8ef7c1884f2d6b6fac3e05a45513cdc96074a82 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Wed, 31 Jan 2024 23:52:27 -0500 Subject: [PATCH 148/163] Cleanup. --- .../src/main/java/edu/cmu/tetrad/data/DataSet.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/data/DataSet.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/data/DataSet.java index f650a64492..b147c07053 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/data/DataSet.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/data/DataSet.java @@ -70,7 +70,7 @@ public interface DataSet extends DataModel { /** * Ensures that the dataset has at least columns columns. Used for pasting data into the dataset. When - * creating new columns, names in the excludedVarialbeNames list may not be used. The purpose of this + * creating new columns, names in the excludedVariableNames list may not be used. The purpose of this * is to allow these names to be set later by the calling class, without incurring conflicts. * * @param columns The number of columns to ensure. @@ -183,20 +183,20 @@ public interface DataSet extends DataModel { List getVariables(); /** - * @return true if this is a continuous data set--that is, if it contains at least one column and all of the columns + * @return true if this is a continuous data set--that is, if it contains at least one column and all the columns * are continuous. */ boolean isContinuous(); /** - * @return true if this is a discrete data set--that is, if it contains at least one column and all of the columns + * @return true if this is a discrete data set--that is, if it contains at least one column and all the columns * are discrete. */ boolean isDiscrete(); /** * @return true if this is a continuous data set--that is, if it contains at least one continuous column and one - * discrete columnn. + * discrete column. */ boolean isMixed(); @@ -277,13 +277,13 @@ public interface DataSet extends DataModel { DataSet subsetColumns(List vars); /** - * @return a new data set in which the the column at indices[i] is placed at index i, for i = 0 to indices.length - + * @return a new data set in which the column at indices[i] is placed at index i, for i = 0 to indices.length - * 1. (View instead?) */ DataSet subsetColumns(int[] columns); /** - * @return a new data set in which the the row at indices[i] is placed at index i, for i = 0 to indices.length - 1. + * @return a new data set in which the row at indices[i] is placed at index i, for i = 0 to indices.length - 1. * (View instead?) */ DataSet subsetRows(int[] rows); From 8643e523b5b2920b6a44e792c484cc33cae311fe Mon Sep 17 00:00:00 2001 From: jdramsey Date: Thu, 1 Feb 2024 00:33:33 -0500 Subject: [PATCH 149/163] Cleanup. --- .../model/AbstractAlgorithmRunner.java | 178 ++- .../cmu/tetradapp/model/AlgorithmRunner.java | 3 + .../edu/cmu/tetradapp/model/DagWrapper.java | 20 +- .../edu/cmu/tetradapp/model/DataWrapper.java | 161 ++- .../edu/cmu/tetradapp/model/GraphSource.java | 7 + .../tetradapp/model/KnowledgeEditable.java | 2 + .../model/MarkovBlanketSearchRunner.java | 3 +- .../java/edu/cmu/tetrad/test/TestFges.java | 1060 ++--------------- 8 files changed, 378 insertions(+), 1056 deletions(-) diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/AbstractAlgorithmRunner.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/AbstractAlgorithmRunner.java index 397c075340..81e5df7ec3 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/AbstractAlgorithmRunner.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/AbstractAlgorithmRunner.java @@ -33,6 +33,7 @@ import java.io.IOException; import java.io.ObjectInputStream; +import java.io.Serial; import java.util.*; /** @@ -43,45 +44,16 @@ */ public abstract class AbstractAlgorithmRunner implements AlgorithmRunner, ParamsResettable, Unmarshallable { + @Serial private static final long serialVersionUID = 23L; final Map paramSettings = new LinkedHashMap<>(); private DataWrapper dataWrapper; - /** - * @serial Can be null. - */ private String name; - /** - * The parameters guiding this search (when executed). - * - * @serial Cannot be null. - */ private Parameters params; - /** - * Keeps a reference to the dataModel source that has been provided (hopefully either a dataModel model or a - * graph). - * - * @serial Can be null. - */ private transient DataModel dataModel; - /** - * Keeps a reference to the source graph, if there is one. - * - * @serial Can be null. - */ private Graph sourceGraph; - /** - * Keeps a reference to the result graph for the algorithm. - * - * @serial Can be null. - */ private Graph resultGraph = new EdgeListGraph(); - /** - * The initial graph for the algorithm, if feasible. - */ private Graph externalGraph; - /** - * A series of graphs that the search algorithm might search over, if it's that kind of algorithm. - */ private List graphs; private Map allParamSettings; @@ -90,6 +62,10 @@ public abstract class AbstractAlgorithmRunner /** * Constructs a wrapper for the given DataWrapper. The DatWrapper must contain a DataSet that is either a DataSet or * a DataSet or a DataList containing either a DataSet or a DataSet as its selected model. + * + * @param dataWrapper the data wrapper + * @param params the parameters + * @param knowledgeBoxModel the knowledge box model */ public AbstractAlgorithmRunner(DataWrapper dataWrapper, Parameters params, KnowledgeBoxModel knowledgeBoxModel) { @@ -120,6 +96,11 @@ public AbstractAlgorithmRunner(DataWrapper dataWrapper, /** * Constructs a wrapper for the given DataWrapper. The DatWrapper must contain a DataSet that is either a DataSet or * a DataSet or a DataList containing either a DataSet or a DataSet as its selected model. + * + * @param dataWrapper the data wrapper + * @param params the parameters + * @param knowledgeBoxModel the knowledge box model + * @param facts the independence facts model */ public AbstractAlgorithmRunner(DataWrapper dataWrapper, Parameters params, KnowledgeBoxModel knowledgeBoxModel, IndependenceFactsModel facts) { @@ -149,6 +130,13 @@ public AbstractAlgorithmRunner(DataWrapper dataWrapper, transferVarNamesToParams(names); } + /** + * Constructs a wrapper for the given DataWrapper. The DatWrapper must contain a DataSet that is either a DataSet or + * a DataSet or a DataList containing either a DataSet or a DataSet as its selected model. + * + * @param dataWrapper the data wrapper + * @param params the parameters + */ public AbstractAlgorithmRunner(DataWrapper dataWrapper, Parameters params) { if (dataWrapper == null) { throw new NullPointerException(); @@ -170,6 +158,9 @@ public AbstractAlgorithmRunner(DataWrapper dataWrapper, Parameters params) { /** * Constructs a wrapper for the given graph. + * + * @param sourceGraph the source graph + * @param params the parameters */ public AbstractAlgorithmRunner(Graph sourceGraph, Parameters params) { if (sourceGraph == null) { @@ -185,6 +176,13 @@ public AbstractAlgorithmRunner(Graph sourceGraph, Parameters params) { this.sourceGraph = sourceGraph; } + /** + * Constructs a wrapper for the given graph. + * + * @param graph the graph + * @param params the parameters + * @param knowledgeBoxModel the knowledge box model + */ public AbstractAlgorithmRunner(Graph graph, Parameters params, KnowledgeBoxModel knowledgeBoxModel) { this(graph, params); @@ -193,11 +191,24 @@ public AbstractAlgorithmRunner(Graph graph, Parameters params, } } + /** + * Constructs a wrapper for the given graph. + * + * @param params the parameters + * @param graphs the graphs + */ public AbstractAlgorithmRunner(Parameters params, Graph... graphs) { this.graphs = Arrays.asList(graphs); this.params = params; } + /** + * Constructs a wrapper for the given graph. + * + * @param params the parameters + * @param knowledgeBoxModel the knowledge box model + * @param graphs the graphs + */ public AbstractAlgorithmRunner(Parameters params, KnowledgeBoxModel knowledgeBoxModel, Graph... graphs) { this.graphs = Arrays.asList(graphs); this.params = params; @@ -206,6 +217,13 @@ public AbstractAlgorithmRunner(Parameters params, KnowledgeBoxModel knowledgeBox } } + /** + * Constructs a wrapper for the given graph. + * + * @param model the model + * @param params the parameters + * @param knowledgeBoxModel the knowledge box model + */ public AbstractAlgorithmRunner(IndependenceFactsModel model, Parameters params, KnowledgeBoxModel knowledgeBoxModel) { if (model == null) { @@ -228,6 +246,14 @@ public AbstractAlgorithmRunner(IndependenceFactsModel model, this.dataModel = dataSource; } + /** + * Constructs a wrapper for the given graph. + * + * @param graph the graph + * @param params the parameters + * @param knowledgeBoxModel the knowledge box model + * @param facts the independence facts model + */ public AbstractAlgorithmRunner(Graph graph, Parameters params, KnowledgeBoxModel knowledgeBoxModel, IndependenceFacts facts) { this(graph, params); @@ -242,40 +268,78 @@ public AbstractAlgorithmRunner(Graph graph, Parameters params, //============================PUBLIC METHODS==========================// + /** + * Returns the graph that was the result of the algorithm's execution. + */ public final Graph getResultGraph() { return this.resultGraph; } + /** + * Sets the graph that was the result of the algorithm's execution. + */ public final void setResultGraph(Graph resultGraph) { this.resultGraph = resultGraph; } /** * By default, algorithm do not support knowledge. Those that do will speak up. + * + * @return true if the algorithm supports knowledge. */ public boolean supportsKnowledge() { return false; } + /** + * By default, algorithm do not support Meek rules. Those that do will speak up. + * + * @return null + */ public MeekRules getMeekRules() { return null; } + /** + * By default, algorithm do not support independence facts. Those that do will speak up. + * + * @return the external graph + */ public Graph getExternalGraph() { return this.externalGraph; } + /** + * Sets the external graph for the algorithm. + * + * @param graph the graph + */ public void setExternalGraph(Graph graph) { this.externalGraph = graph; } + /** + * Returns the algorithm's name. + * + * @return + */ @Override public abstract String getAlgorithmName(); + /** + * Returns the source graph. + * + * @return the source graph + */ public final Graph getSourceGraph() { return this.sourceGraph; } + /** + * Returns the data model. + * + * @return the data model + */ public final DataModel getDataModel() { if (this.dataWrapper != null) { DataModelList dataModelList = this.dataWrapper.getDataModelList(); @@ -294,19 +358,39 @@ public final DataModel getDataModel() { } } + /** + * Returns the data model list. + * + * @return the data model list + */ final DataModelList getDataModelList() { if (this.dataWrapper == null) return null; return this.dataWrapper.getDataModelList(); } + /** + * Returns the search parameters. + * + * @return the search parameters + */ public final Parameters getParams() { return this.params; } + /** + * Returns the pameters. + * + * @return the parameters + */ public Object getResettableParams() { return this.getParams(); } + /** + * Resets the parameters. + * + * @param params the parameters + */ public void resetParams(Object params) { this.params = (Parameters) params; } @@ -325,9 +409,7 @@ private DataModel getSelectedDataModel(DataWrapper dataWrapper) { DataModel dataModel = dataWrapper.getSelectedDataModel(); - if (dataModel instanceof DataSet) { - DataSet dataSet = (DataSet) dataModel; - + if (dataModel instanceof DataSet dataSet) { if (dataSet.isDiscrete()) { return dataSet; } else if (dataSet.isContinuous()) { @@ -378,29 +460,59 @@ private void readObject(ObjectInputStream s) } + /** + * Returns the name of the algorithm. + * + * @return the name + */ public String getName() { return this.name; } + /** + * Sets the name of the algorithm. + * + * @param name the name + */ public void setName(String name) { this.name = name; } + /** + * Returns the list of graphs. + * + * @return the graphs + */ public List getGraphs() { return this.graphs; } + /** + * Returns the param settings. + * + * @return the param settings + */ @Override public Map getParamSettings() { this.paramSettings.put("Algorithm", getAlgorithmName()); return this.paramSettings; } + /** + * Returns all param settings. + * + * @return all param settings + */ public Map getAllParamSettings() { return this.allParamSettings; } + /** + * Sets all param settings. + * + * @param allParamSettings the all param settings map. + */ public void setAllParamSettings(Map allParamSettings) { this.allParamSettings = allParamSettings; } diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/AlgorithmRunner.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/AlgorithmRunner.java index 1eacbd66b0..f7bd1152ea 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/AlgorithmRunner.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/AlgorithmRunner.java @@ -82,6 +82,9 @@ public interface AlgorithmRunner extends SessionModel, Executable, GraphSource, */ void setExternalGraph(Graph graph); + /** + * @return the name of the algorithm. + */ String getAlgorithmName(); } diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/DagWrapper.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/DagWrapper.java index a2e649a833..18e024479e 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/DagWrapper.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/DagWrapper.java @@ -31,19 +31,21 @@ import java.io.IOException; import java.io.ObjectInputStream; +import java.io.Serial; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** - * Holds a tetrad dag with all of the constructors necessary for it to serve as a model for the tetrad application. + * Holds a tetrad dag with all the constructors necessary for it to serve as a model for the tetrad application. * * @author josephramsey */ public class DagWrapper implements GraphSource, KnowledgeBoxInput, IndTestProducer, SimulationParamsSource, MultipleGraphSource { + @Serial private static final long serialVersionUID = 23L; private int numModels = 1; private int modelIndex; @@ -60,7 +62,6 @@ public class DagWrapper implements GraphSource, KnowledgeBoxInput, IndTestProduc private List dags; private Map allParamSettings; private Parameters parameters; - private Dag graph; //=============================CONSTRUCTORS==========================// public DagWrapper(Dag graph) { @@ -85,8 +86,9 @@ public DagWrapper(Parameters params) { } public DagWrapper(GraphSource graphSource, Parameters parameters) { - if (graphSource instanceof Simulation) { - Simulation simulation = (Simulation) graphSource; + this.parameters = new Parameters(parameters); + + if (graphSource instanceof Simulation simulation) { List graphs = simulation.getGraphs(); this.dags = new ArrayList<>(); @@ -110,9 +112,7 @@ public DagWrapper(AbstractAlgorithmRunner wrapper) { } public DagWrapper(DataWrapper wrapper) { - if (wrapper instanceof Simulation) { - Simulation simulation = (Simulation) wrapper; - + if (wrapper instanceof Simulation simulation) { List graphs = simulation.getGraphs(); this.dags = new ArrayList<>(); @@ -196,10 +196,10 @@ private void log() { * semantic checks can be specified and do not need to stay the same from version to version. A readObject method of * this form may be added to any class, even if Tetrad sessions were previously saved out using a version of the * class that didn't include it. (That's what the "s.defaultReadObject();" is for. See J. Bloch, Effective Java, for - * help. + * help.) */ - private void readObject(ObjectInputStream s) - throws IOException, ClassNotFoundException { + @Serial + private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException { s.defaultReadObject(); } diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/DataWrapper.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/DataWrapper.java index 892fbef860..2927006b2f 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/DataWrapper.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/DataWrapper.java @@ -32,6 +32,7 @@ import java.io.IOException; import java.io.ObjectInputStream; +import java.io.Serial; import java.util.*; /** @@ -105,9 +106,13 @@ public DataWrapper(Simulation wrapper, Parameters parameters) { /** * Copy constructor. + * + * @param wrapper the data wrapper to copy. + * @param parameters the parameters to use. */ public DataWrapper(DataWrapper wrapper, Parameters parameters) { this.name = wrapper.name; + this.parameters = new Parameters(parameters); DataModelList dataModelList = new DataModelList(); int selected = -1; @@ -144,16 +149,26 @@ public DataWrapper(DataWrapper wrapper, Parameters parameters) { /** * Constructs a data wrapper using a new DataSet as data model. + * + * @param dataSet the data set to use. */ public DataWrapper(DataSet dataSet) { setDataModel(dataSet); } + /** + * Constructs a data wrapper using a new DataSet as data model. + * + * @param graph the graph to use. + * @param parameters the parameters to use. + */ public DataWrapper(Graph graph, Parameters parameters) { if (graph == null) { throw new NullPointerException(); } + this.parameters = new Parameters(parameters); + List nodes = graph.getNodes(); List variables = new LinkedList<>(); @@ -173,28 +188,69 @@ public DataWrapper(Graph graph, Parameters parameters) { this.dataModelList = dataModelList; } + /** + * Constructs a data wrapper using a new DataSet as data model. + * + * @param dagWrapper the DAG to use. + * @param parameters the parameters to use. + */ public DataWrapper(DagWrapper dagWrapper, Parameters parameters) { this(dagWrapper.getDag(), parameters); } + /** + * Constructs a data wrapper using a new DataSet as data model. + * + * @param wrapper the SEM graph to use. + * @param parameters the parameters to use. + */ public DataWrapper(SemGraphWrapper wrapper, Parameters parameters) { this(wrapper.getGraph(), parameters); } + /** + * Constructs a data wrapper using a new DataSet as data model. + * + * @param wrapper the SEM graph to use. + * @param parameters the parameters to use. + */ public DataWrapper(GraphWrapper wrapper, Parameters parameters) { this(wrapper.getGraph(), parameters); } + /** + * Constructs a data wrapper using a new DataSet as data model. + * + * @param regression the regression to use. + * @param wrapper the data model to use. + * @param parameters the parameters to use. + */ public DataWrapper(RegressionRunner regression, DataWrapper wrapper, Parameters parameters) { - this(regression.getResult(), (DataSet) wrapper.getDataModelList().getSelectedModel(), parameters); + this(regression.getResult(), (DataSet) Objects.requireNonNull(wrapper.getDataModelList().getSelectedModel()), + parameters); } + /** + * Constructs a data wrapper using a new DataSet as data model. + * + * @param regression the regression to use. + * @param wrapper the data model to use. + * @param parameters the parameters to use. + */ public DataWrapper(RegressionRunner regression, Simulation wrapper, Parameters parameters) { - this(regression.getResult(), (DataSet) wrapper.getDataModelList().getSelectedModel(), parameters); + this(regression.getResult(), (DataSet) Objects.requireNonNull(wrapper.getDataModelList().getSelectedModel()), + parameters); } - // Computes regression predictions. + /** + * Constructs a data wrapper using a new DataSet as data model. + * + * @param result the regression result to use. + * @param data the data to use. + * @param parameters the parameters to use. + */ public DataWrapper(RegressionResult result, DataSet data, Parameters parameters) { + this.parameters = new Parameters(parameters); DataSet data2 = data.copy(); String predictedVariable = nextVariableName("Pred", data); @@ -229,7 +285,15 @@ public DataWrapper(RegressionResult result, DataSet data, Parameters parameters) this.dataModelList = dataModelList; } + /** + * Constructs a data wrapper using a new DataSet as data model. + * + * @param mimBuild the mim build to use. + * @param parameters the parameters to use. + */ public DataWrapper(MimBuildRunner mimBuild, Parameters parameters) { + this.parameters = new Parameters(parameters); + ICovarianceMatrix cov = mimBuild.getCovMatrix(); DataModelList dataModelList = new DataModelList(); @@ -279,8 +343,6 @@ private String nextVariableName(String base, DataSet data) { return name; } - //==============================PUBLIC METHODS========================// - /** * Stores a reference to the data model being wrapped. * @@ -290,6 +352,11 @@ public DataModelList getDataModelList() { return this.dataModelList; } + /** + * Set the data model list. + * + * @param dataModelList the data model list to set. + */ public void setDataModelList(DataModelList dataModelList) { if (dataModelList == null) { throw new NullPointerException("Data model list not provided."); @@ -297,12 +364,15 @@ public void setDataModelList(DataModelList dataModelList) { this.dataModelList = dataModelList; } + /** + * @return the data model for this wrapper. + */ public List getDataModels() { return new ArrayList<>(this.dataModelList); } /** - * @return the data model for this wrapper. + * @return the selected data model for this wrapper. */ public DataModel getSelectedDataModel() { DataModelList modelList = getDataModelList(); @@ -311,6 +381,8 @@ public DataModel getSelectedDataModel() { /** * Sets the data model. + * + * @param dataModel the data model to set. */ public void setDataModel(DataModel dataModel) { if (dataModel == null) { @@ -326,20 +398,31 @@ public void setDataModel(DataModel dataModel) { } } + /** + * @return the knowledge for this wrapper. + */ public Knowledge getKnowledge() { - return getSelectedDataModel().getKnowledge(); + return getSelectedDataModel().getKnowledge().copy(); } + /** + * Sets knowledge to a copy of the given object. + * + * @param knowledge the knowledge to set. + */ public void setKnowledge(Knowledge knowledge) { - getSelectedDataModel().setKnowledge(knowledge); + getSelectedDataModel().setKnowledge(knowledge.copy()); } + /** + * @return the variable names of the selected data model. + */ public List getVarNames() { return getSelectedDataModel().getVariableNames(); } /** - * @return the source workbench, if there is one. + * @return the source graph. */ public Graph getSourceGraph() { return this.sourceGraph; @@ -347,29 +430,27 @@ public Graph getSourceGraph() { /** * Sets the source graph. + * + * @param sourceGraph the source graph to set. */ protected void setSourceGraph(Graph sourceGraph) { this.sourceGraph = sourceGraph; } + /** + * @return the result graph. + */ public Graph getResultGraph() { return getSourceGraph(); } /** - * @return the variable names, in order. + * @return the variables, in order. */ public List getVariables() { return this.getSelectedDataModel().getVariables(); } - /** - * // * Sets the source graph. // - */ - public Map getDiscretizationSpecs() { - return this.discretizationSpecs; - } - /** * Adds semantic checks to the default deserialization method. This method must have the standard signature for a * readObject method, and the body of the method must begin with "s.defaultReadObject();". Other than that, any @@ -378,32 +459,51 @@ public Map getDiscretizationSpecs() { * class that didn't include it. (That's what the "s.defaultReadObject();" is for. See J. Bloch, Effective Java, for * help. */ + @Serial private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException { s.defaultReadObject(); } + /** + * @return the name of the data wrapper. + */ public String getName() { return this.name; } + /** + * Sets the name of the data wrapper. + * + * @param name the name to set. + */ public void setName(String name) { this.name = name; } /** - * This method is overridden by classes that can identify parameters. + * Returns the parameters being edited. * - * @return null + * @return the parameters being edited. */ public Parameters getParams() { return this.parameters; } + /** + * Sets the parameters being edited. + * + * @param parameters the parameters to set. + */ public void setParameters(Parameters parameters) { this.parameters = parameters; } + /** + * Returns the variable names. + * + * @return the variable names. + */ public List getVariableNames() { List variableNames = new ArrayList<>(); for (Node n : getVariables()) { @@ -412,6 +512,11 @@ public List getVariableNames() { return variableNames; } + /** + * Returns the parameter setting map. + * + * @return the parameter setting map. + */ @Override public Map getParamSettings() { Map paramSettings = new HashMap<>(); @@ -426,14 +531,10 @@ public Map getParamSettings() { DataModel dataModel = this.dataModelList.get(0); if (dataModel instanceof CovarianceMatrix) { - if (!paramSettings.containsKey("# Nodes")) { - paramSettings.put("# Vars", Integer.toString(((CovarianceMatrix) dataModel).getDimension())); - } + paramSettings.put("# Vars", Integer.toString(((CovarianceMatrix) dataModel).getDimension())); paramSettings.put("N", Integer.toString(((CovarianceMatrix) dataModel).getSampleSize())); } else { - if (!paramSettings.containsKey("# Nodes")) { - paramSettings.put("# Vars", Integer.toString(((DataSet) dataModel).getNumColumns())); - } + paramSettings.put("# Vars", Integer.toString(((DataSet) dataModel).getNumColumns())); paramSettings.put("N", Integer.toString(((DataSet) dataModel).getNumRows())); } } @@ -441,11 +542,21 @@ public Map getParamSettings() { return paramSettings; } + /** + * Returns the parameter setting map. + * + * @return the parameter setting map. + */ @Override public Map getAllParamSettings() { return this.allParamSettings; } + /** + * Sets the parameter setting map. + * + * @param paramSettings the parameter setting map to set. + */ @Override public void setAllParamSettings(Map paramSettings) { this.allParamSettings = paramSettings; diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/GraphSource.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/GraphSource.java index 628417ea55..420d4b892e 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/GraphSource.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/GraphSource.java @@ -29,8 +29,15 @@ * @author josephramsey */ public interface GraphSource { + + /** + * @return the graph produced by this source. + */ Graph getGraph(); + /** + * @return the name of the graph produced by this source. + */ String getName(); } diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/KnowledgeEditable.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/KnowledgeEditable.java index 6db0ceb7ad..784089d35e 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/KnowledgeEditable.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/KnowledgeEditable.java @@ -40,6 +40,8 @@ public interface KnowledgeEditable { /** * Sets knowledge to a copy of the given object. + * + * @param knowledge the knowledge to set. */ void setKnowledge(Knowledge knowledge); diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/MarkovBlanketSearchRunner.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/MarkovBlanketSearchRunner.java index b4d8120180..01ea7351e6 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/MarkovBlanketSearchRunner.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/MarkovBlanketSearchRunner.java @@ -43,7 +43,7 @@ public interface MarkovBlanketSearchRunner extends Executable { /** - * Return the source for the search. + * @return the source for the search. */ DataSet getSource(); @@ -68,6 +68,7 @@ public interface MarkovBlanketSearchRunner extends Executable { /** * Sets the search name. + * @param n the name of the search. */ void setSearchName(String n); diff --git a/tetrad-lib/src/test/java/edu/cmu/tetrad/test/TestFges.java b/tetrad-lib/src/test/java/edu/cmu/tetrad/test/TestFges.java index 872c4a5817..56654a8b64 100644 --- a/tetrad-lib/src/test/java/edu/cmu/tetrad/test/TestFges.java +++ b/tetrad-lib/src/test/java/edu/cmu/tetrad/test/TestFges.java @@ -22,7 +22,6 @@ package edu.cmu.tetrad.test; import edu.cmu.tetrad.algcomparison.algorithm.Algorithm; -import edu.cmu.tetrad.algcomparison.algorithm.oracle.cpdag.Cpc; import edu.cmu.tetrad.algcomparison.algorithm.oracle.cpdag.Fges; import edu.cmu.tetrad.algcomparison.graph.RandomForward; import edu.cmu.tetrad.algcomparison.graph.RandomGraph; @@ -31,7 +30,8 @@ import edu.cmu.tetrad.algcomparison.score.ScoreWrapper; import edu.cmu.tetrad.algcomparison.simulation.LinearFisherModel; import edu.cmu.tetrad.algcomparison.simulation.Simulation; -import edu.cmu.tetrad.algcomparison.statistic.*; +import edu.cmu.tetrad.algcomparison.statistic.AdjacencyPrecision; +import edu.cmu.tetrad.algcomparison.statistic.AdjacencyRecall; import edu.cmu.tetrad.bayes.BayesIm; import edu.cmu.tetrad.bayes.BayesPm; import edu.cmu.tetrad.bayes.MlBayesIm; @@ -40,24 +40,21 @@ import edu.cmu.tetrad.search.FgesMb; import edu.cmu.tetrad.search.IndependenceTest; import edu.cmu.tetrad.search.Pc; -import edu.cmu.tetrad.search.score.*; +import edu.cmu.tetrad.search.score.BdeScore; +import edu.cmu.tetrad.search.score.GraphScore; +import edu.cmu.tetrad.search.score.SemBicScore; import edu.cmu.tetrad.search.test.MsepTest; -import edu.cmu.tetrad.search.utils.GraphSearchUtils; -import edu.cmu.tetrad.search.utils.MeekRules; -import edu.cmu.tetrad.sem.GeneralizedSemIm; -import edu.cmu.tetrad.sem.GeneralizedSemPm; import edu.cmu.tetrad.sem.SemIm; import edu.cmu.tetrad.sem.SemPm; -import edu.cmu.tetrad.util.*; -import edu.pitt.csb.mgm.Mgm; -import edu.pitt.csb.mgm.MixedUtils; -import org.apache.commons.math3.util.FastMath; +import edu.cmu.tetrad.util.Parameters; +import edu.cmu.tetrad.util.Params; +import edu.cmu.tetrad.util.RandomUtil; +import edu.cmu.tetrad.util.TetradLogger; +import org.jetbrains.annotations.NotNull; import org.junit.Test; import java.io.IOException; import java.io.PrintStream; -import java.text.DecimalFormat; -import java.text.NumberFormat; import java.util.*; import static junit.framework.TestCase.assertFalse; @@ -68,9 +65,8 @@ * @author josephramsey */ public class TestFges { - boolean precomputeCovariances = true; - private final PrintStream out = System.out; + boolean precomputeCovariances = true; // private OutputStream out = private HashMap hashIndices; @@ -117,9 +113,6 @@ public static void main(String... args) { Graph out1 = alg.search(sim.getDataModel(0), parameters); System.out.println(out1); } - - } else { - new TestFges().test9(); } } @@ -141,13 +134,6 @@ public void explore1() { } Graph dag = edu.cmu.tetrad.graph.RandomGraph.randomGraphRandomForwardEdges(vars, 0, numEdges, 30, 15, 15, false, true); -// printDegreeDistribution(dag, System.out); - - int[] causalOrdering = new int[vars.size()]; - - for (int i = 0; i < vars.size(); i++) { - causalOrdering[i] = i; - } SemPm pm = new SemPm(dag); SemIm im = new SemIm(pm); @@ -175,25 +161,6 @@ public void explore1() { double ar = new AdjacencyRecall().getValue(trueCPDAG, estCPDAG, data); System.out.println("ap = " + ap + " ar = " + ar); - - -// int[][] counts = SearchGraphUtils.graphComparison(estCPDAG, trueCPDAG, null); -// -// int[][] expectedCounts = { -// {2, 0, 0, 0, 0, 0}, -// {0, 0, 0, 0, 0, 0}, -// {0, 0, 0, 0, 0, 0}, -// {0, 0, 0, 0, 0, 0}, -// {0, 0, 0, 8, 0, 0}, -// {0, 0, 0, 0, 0, 0}, -// {0, 0, 0, 0, 0, 0}, -// {0, 0, 0, 0, 0, 0}, -// }; -// -// for (int i = 0; i < counts.length; i++) { -// assertTrue(Arrays.equals(counts[i], expectedCounts[i])); -// } - } @Test @@ -203,8 +170,6 @@ public void explore2() { final int numVars = 10; final double edgeFactor = 1.0; final int numCases = 1000; - final double structurePrior = 1; - final double samplePrior = 1; List vars = new ArrayList<>(); @@ -214,37 +179,16 @@ public void explore2() { Graph dag = edu.cmu.tetrad.graph.RandomGraph.randomGraphRandomForwardEdges(vars, 0, (int) (numVars * edgeFactor), 30, 15, 15, false, true); -// printDegreeDistribution(dag, out); BayesPm pm = new BayesPm(dag, 2, 3); BayesIm im = new MlBayesIm(pm, MlBayesIm.RANDOM); DataSet data = im.simulateData(numCases, false); -// out.println("Finishing simulation"); - BdeScore score = new BdeScore(data); edu.cmu.tetrad.search.Fges ges = new edu.cmu.tetrad.search.Fges(score); ges.setVerbose(false); ges.setFaithfulnessAssumed(false); - - Graph estCPDAG = ges.search(); - - Graph trueCPDAG = GraphTransforms.cpdagForDag(dag); - - int[][] counts = GraphSearchUtils.graphComparison(trueCPDAG, estCPDAG, null); - - int[][] expectedCounts = { - {2, 0, 0, 0, 0, 1}, - {0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0}, - {2, 0, 0, 13, 0, 3}, - {0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0}, - }; - } @Test @@ -344,81 +288,33 @@ public void testFromGraphSimpleFgesMb() { assertEquals(mb1, mb2); } - // @Test - public void testFgesMbFromGraph() { - RandomUtil.getInstance().setSeed(1450184147770L); - - final int numNodes = 20; - final int numIterations = 2; - - for (int i = 0; i < numIterations; i++) { - System.out.println("Iteration " + (i + 1)); - Graph dag = edu.cmu.tetrad.graph.RandomGraph.randomDag(numNodes, 0, numNodes, 10, 10, 10, false); - GraphScore fgesScore = new GraphScore(dag); - - edu.cmu.tetrad.search.Fges fges = new edu.cmu.tetrad.search.Fges(fgesScore); - Graph CPDAG1 = fges.search(); - - Node x1 = fgesScore.getVariable("X1"); - - Set mb = new HashSet<>(); - mb.add(x1); - - mb.addAll(CPDAG1.getAdjacentNodes(x1)); - - for (Node child : CPDAG1.getChildren(x1)) { - mb.addAll(CPDAG1.getParents(child)); - } - - Graph mb1 = CPDAG1.subgraph(new ArrayList<>(mb)); - - FgesMb fgesMb = new FgesMb(fgesScore); - Graph mb2 = fgesMb.search(Collections.singletonList(x1)); - - assertEquals(mb1, mb2); - } - } + @Test + public void clarkTest() { + RandomGraph randomGraph = new RandomForward(); - private void printDegreeDistribution(Graph dag, PrintStream out) { - int max = 0; + Simulation simulation = new LinearFisherModel(randomGraph); - for (Node node : dag.getNodes()) { - int degree = dag.getAdjacentNodes(node).size(); - if (degree > max) max = degree; - } + Parameters parameters = getParameters(); - int[] counts = new int[max + 1]; - Map> names = new HashMap<>(); + simulation.createData(parameters, false); - for (int i = 0; i <= max; i++) { - names.put(i, new ArrayList<>()); - } + DataSet dataSet = (DataSet) simulation.getDataModel(0); + Graph trueGraph = simulation.getTrueGraph(0); - for (Node node : dag.getNodes()) { - int degree = dag.getAdjacentNodes(node).size(); - counts[degree]++; - names.get(degree).add(node); - } + ScoreWrapper score = new edu.cmu.tetrad.algcomparison.score.SemBicScore(); + IndependenceWrapper test = new FisherZ(); - for (int k = 0; k < counts.length; k++) { - if (counts[k] == 0) continue; + Algorithm fges = new Fges(score); - out.print(k + " " + counts[k]); + Graph fgesGraph = fges.search(dataSet, parameters); - for (Node node : names.get(k)) { - out.print(" " + node.getName()); - } + clarkTestForAlpha(0.05, parameters, dataSet, trueGraph, fgesGraph, test); + clarkTestForAlpha(0.01, parameters, dataSet, trueGraph, fgesGraph, test); - out.println(); - } } - @Test - public void clarkTest() { - RandomGraph randomGraph = new RandomForward(); - - Simulation simulation = new LinearFisherModel(randomGraph); - + @NotNull + private static Parameters getParameters() { Parameters parameters = new Parameters(); parameters.set(Params.NUM_MEASURES, 10); @@ -440,24 +336,7 @@ public void clarkTest() { parameters.set(Params.VERBOSE, false); parameters.set(Params.ALPHA, 0.01); - - simulation.createData(parameters, false); - - DataSet dataSet = (DataSet) simulation.getDataModel(0); - Graph trueGraph = simulation.getTrueGraph(0); - -// trueGraph = SearchGraphUtils.CPDAGForDag(trueGraph); - - ScoreWrapper score = new edu.cmu.tetrad.algcomparison.score.SemBicScore(); - IndependenceWrapper test = new FisherZ(); - - Algorithm fges = new Fges(score); - - Graph fgesGraph = fges.search(dataSet, parameters); - - clarkTestForAlpha(0.05, parameters, dataSet, trueGraph, fgesGraph, test); - clarkTestForAlpha(0.01, parameters, dataSet, trueGraph, fgesGraph, test); - + return parameters; } private void clarkTestForAlpha(double alpha, Parameters parameters, DataSet dataSet, Graph trueGraph, @@ -593,19 +472,50 @@ public void testSearch5() { @Test public void testCites() { - final String citesString = "164\n" + - "ABILITY\tGPQ\tPREPROD\tQFJ\tSEX\tCITES\tPUBS\n" + - "1.0\n" + - ".62\t1.0\n" + - ".25\t.09\t1.0\n" + - ".16\t.28\t.07\t1.0\n" + - "-.10\t.00\t.03\t.10\t1.0\n" + - ".29\t.25\t.34\t.37\t.13\t1.0\n" + - ".18\t.15\t.19\t.41\t.43\t.55\t1.0"; + final String citesString = """ + 164 + ABILITY\tGPQ\tPREPROD\tQFJ\tSEX\tCITES\tPUBS + 1.0 + .62\t1.0 + .25\t.09\t1.0 + .16\t.28\t.07\t1.0 + -.10\t.00\t.03\t.10\t1.0 + .29\t.25\t.34\t.37\t.13\t1.0 + .18\t.15\t.19\t.41\t.43\t.55\t1.0"""; char[] citesChars = citesString.toCharArray(); ICovarianceMatrix cov = SimpleDataLoader.loadCovarianceMatrix(citesChars, "//", DelimiterType.WHITESPACE, '\"', "*"); + Graph CPDAG = getGraph(cov); + + System.out.println(CPDAG); + + final String trueString = """ + Graph Nodes: + Graph Nodes: + Graph Nodes:;ABILITY;GPQ;PREPROD;QFJ;SEX;CITES;PUBS + + Graph Edges: + 1. ABILITY --> GPQ + 2. ABILITY --> PREPROD + 3. ABILITY --> PUBS + 4. GPQ --> QFJ + 5. PREPROD --> CITES + 6. PUBS --> CITES + 7. QFJ --> CITES + 8. QFJ --> PUBS + 9. SEX --> PUBS"""; + + try { + Graph trueGraph = GraphSaveLoadUtils.readerToGraphTxt(trueString); + CPDAG = GraphUtils.replaceNodes(CPDAG, trueGraph.getNodes()); + assertEquals(trueGraph, CPDAG); + } catch (IOException e) { + TetradLogger.getInstance().forceLogMessage("Error in testCites"); + } + } + + private static Graph getGraph(ICovarianceMatrix cov) { Knowledge knowledge = new Knowledge(); knowledge.addToTier(1, "ABILITY"); @@ -622,36 +532,7 @@ public void testCites() { fges.setVerbose(true); - Graph CPDAG = fges.search(); - - System.out.println(CPDAG); - - final String trueString = "Graph Nodes:\n" + - "Graph Nodes:\n" + - "Graph Nodes:;ABILITY;GPQ;PREPROD;QFJ;SEX;CITES;PUBS\n" + - "\n" + - "Graph Edges:\n" + - "1. ABILITY --> GPQ\n" + - "2. ABILITY --> PREPROD\n" + - "3. ABILITY --> PUBS\n" + - "4. GPQ --> QFJ\n" + - "5. PREPROD --> CITES\n" + - "6. PUBS --> CITES\n" + - "7. QFJ --> CITES\n" + - "8. QFJ --> PUBS\n" + - "9. SEX --> PUBS"; - - Graph trueGraph = null; - - - try { - trueGraph = GraphSaveLoadUtils.readerToGraphTxt(trueString); - CPDAG = GraphUtils.replaceNodes(CPDAG, trueGraph.getNodes()); - assertEquals(trueGraph, CPDAG); - } catch (IOException e) { - e.printStackTrace(); - } - + return fges.search(); } /** @@ -677,7 +558,7 @@ private void checkSearch(String inputGraph, String outputGraph) { resultGraph = GraphUtils.replaceNodes(resultGraph, trueGraph.getNodes()); // Do test. - assertTrue(resultGraph.equals(trueGraph)); + assertEquals(resultGraph, trueGraph); } /** @@ -701,14 +582,7 @@ private void checkWithKnowledge(String inputGraph, String answerGraph, // Build comparison graph. Graph answer = GraphUtils.convert(answerGraph); answer = GraphUtils.replaceNodes(answer, input.getNodes()); -// Graph answer = new PC(new IndTestMSep(input)).search(); - -// System.out.println("Input = " + input); -// System.out.println("Knowledge = " + knowledge); -// System.out.println("Answer = " + answer); -// System.out.println("Result graph = " + result); - // Do test. assertEquals(answer, result); } @@ -730,67 +604,6 @@ public void testFromGraph() { } } - // @Test - public void testFromData() { - final int numIterations = 1; - - Parameters params = new Parameters(); - - int[] nodeOptions = {5, 10, 20, 30, 40, 50, 75, 100}; - int[] avgDegreeOptions = {2, 4, 6}; - int[] sampleSizeOptions = {100, 500, 1000, 10000, 100000}; - - int numRowsInTable = nodeOptions.length * avgDegreeOptions.length * sampleSizeOptions.length; - - TextTable table = new TextTable(numRowsInTable + 1, 5); - - table.setToken(0, 0, "# Nodes"); - table.setToken(0, 1, "Avg Degree"); - table.setToken(0, 2, "# Samples"); - table.setToken(0, 3, "True # edges"); - table.setToken(0, 4, "Est # Edges"); - - int count = 0; - - for (int numNodes : nodeOptions) { - for (int avgDegree : avgDegreeOptions) { - for (int sampleSize : sampleSizeOptions) { - for (int q = 0; q < 1; q++) { - for (int i = 0; i < numIterations; i++) { - Graph dag = edu.cmu.tetrad.graph.RandomGraph.randomDag(numNodes, 0, - (avgDegree * numNodes) / 2, 100, 100, 100, false); - SemPm pm = new SemPm(dag); - SemIm im = new SemIm(pm, params); - DataSet data = im.simulateData(sampleSize, false); - SemBicScore score = new SemBicScore(data, precomputeCovariances); - score.setPenaltyDiscount(.5); - edu.cmu.tetrad.search.Fges fges = new edu.cmu.tetrad.search.Fges(score); - fges.setFaithfulnessAssumed(false); - fges.setVerbose(false); - Graph CPDAG1 = fges.search(); - System.out.println("num nodes = " + numNodes + " avg degree = " + avgDegree - + " sample size = " + sampleSize - + " true # edges = " + dag.getNumEdges() - + " est # edges = " + CPDAG1.getNumEdges()); - - count++; - table.setToken(count, 0, "" + numNodes); - table.setToken(count, 1, "" + avgDegree); - table.setToken(count, 2, "" + sampleSize); - table.setToken(count, 3, "" + dag.getNumEdges()); - table.setToken(count, 4, "" + CPDAG1.getNumEdges()); - - } - } - } - } - } - - System.out.println("\n==========================\n"); - System.out.println(table); - - } - @Test public void testFromGraphWithForbiddenKnowledge() { final int numNodes = 10; @@ -819,9 +632,6 @@ public void testFromGraphWithForbiddenKnowledge() { assertFalse(CPDAG1.isParentOf(x, y)); } - - // This sometimes fails if the following cycle check is uncommented. -// assertFalse(CPDAG1.existsDirectedCycle()); } } @@ -891,735 +701,12 @@ private Knowledge requiredKnowledge(Graph graph) { return knowledge; } - private Graph getSubgraph(Graph graph, boolean discrete1, boolean discrete2, DataSet dataSet) { - Graph newGraph = new EdgeListGraph(graph.getNodes()); - - for (Edge edge : graph.getEdges()) { - Node node1 = dataSet.getVariable(edge.getNode1().getName()); - Node node2 = dataSet.getVariable(edge.getNode2().getName()); - - if (discrete1 && node1 instanceof DiscreteVariable) { - if (discrete2 && node2 instanceof DiscreteVariable) { - newGraph.addEdge(edge); - } - } else if (!discrete1 && node1 instanceof ContinuousVariable) { - if (!discrete2 && node2 instanceof ContinuousVariable) { - newGraph.addEdge(edge); - } - } else if ((discrete1 && !discrete2) || (!discrete1 && discrete2)) { - if (node1 instanceof ContinuousVariable && node2 instanceof DiscreteVariable) { - newGraph.addEdge(edge); - } else if (node1 instanceof DiscreteVariable && node2 instanceof ContinuousVariable) { - newGraph.addEdge(edge); - } - } - } - - return newGraph; - } - - private Graph searchSemFges(DataSet Dk) { - Dk = DataTransforms.convertNumericalDiscreteToContinuous(Dk); - SemBicScore score = new SemBicScore(new CovarianceMatrix(Dk)); - score.setPenaltyDiscount(2.0); - edu.cmu.tetrad.search.Fges fges = new edu.cmu.tetrad.search.Fges(score); - return fges.search(); - } - - private Graph searchBdeuFges(DataSet Dk, int k) { - Discretizer discretizer = new Discretizer(Dk); - List nodes = Dk.getVariables(); - - for (Node node : nodes) { - if (node instanceof ContinuousVariable) { - discretizer.equalIntervals(node, k); - } - } - - Dk = discretizer.discretize(); - - BdeuScore score = new BdeuScore(Dk); - score.setSamplePrior(1.0); - score.setStructurePrior(1.0); - edu.cmu.tetrad.search.Fges fges = new edu.cmu.tetrad.search.Fges(score); - return fges.search(); - } - - private Graph searchMixedFges(DataSet dk) { - ConditionalGaussianScore score = new ConditionalGaussianScore(dk, 2.0, true); - score.setPenaltyDiscount(2.0); - score.setStructurePrior(0.0); - edu.cmu.tetrad.search.Fges fges = new edu.cmu.tetrad.search.Fges(score); - return fges.search(); - } - - public Graph searchMGMFges(DataSet ds, double penalty) { - Mgm m = new Mgm(ds, new double[]{0.1, 0.1, 0.1}); - //m.setVerbose(this.verbose); - Graph gm = m.search(); - DataSet dataSet = MixedUtils.makeContinuousData(ds); - SemBicScore score = new SemBicScore(new CovarianceMatrix(dataSet)); - score.setPenaltyDiscount(penalty); - edu.cmu.tetrad.search.Fges fg = new edu.cmu.tetrad.search.Fges(score); - fg.setBoundGraph(gm); - fg.setVerbose(false); - return fg.search(); - } - - public DataSet getMixedDataAjStyle(Graph g, int k, int samps) { - - HashMap nd = new HashMap<>(); - - List nodes = g.getNodes(); - - RandomUtil.shuffle(nodes); - - for (int i = 0; i < nodes.size(); i++) { - if (i < nodes.size() / 2) { - nd.put(nodes.get(i).getName(), k); - } else { - nd.put(nodes.get(i).getName(), 0); - } - } - - g = MixedUtils.makeMixedGraph(g, nd); - - - GeneralizedSemPm pm = MixedUtils.GaussianCategoricalPm(g, "Split(-1.5,-.5,.5,1.5)"); -// System.out.println(pm); - - GeneralizedSemIm im = MixedUtils.GaussianCategoricalIm(pm); -// System.out.println(im); - - DataSet ds = im.simulateDataFisher(samps); - return MixedUtils.makeMixedData(ds, nd); - } - - // @Test - public void testBestAlgorithms() { - String[] algorithms = {"SemFGES", "BDeuFGES", "MixedFGES", "PC", "PCS", "CPC", "MGMFges", "MGMPcs"}; - String[] statLabels = {"AP", "AR", "OP", "OR", "SUM", "McAdj", "McOr", "F1Adj", "F1Or", "E"}; - - final int numMeasures = 10; - final int numEdges = 10; - - final int numRuns = 50; - final int maxCategories = 5; - final int sampleSize = 1000; - final double penaltyDiscount = 4.0; - final double ofInterestCutoff = 0.05; - - double[][][][] allAllRet = new double[maxCategories][][][]; - int latentIndex = -1; - - for (int numCategories = 2; numCategories <= maxCategories; numCategories++) { - latentIndex++; - - System.out.println(); - - System.out.println("num categories = " + numCategories); - System.out.println("num measures = " + numMeasures); - System.out.println("num edges = " + numEdges); - System.out.println("sample size = " + sampleSize); - System.out.println("penaltyDiscount = " + penaltyDiscount); - System.out.println("num runs = " + numRuns); - - double[][][] allRet = new double[algorithms.length][][]; - - for (int t = 0; t < algorithms.length; t++) { - allRet[t] = printStats(algorithms, t, - numCategories); - } - - allAllRet[latentIndex] = allRet; - } - - System.out.println(); - System.out.println("======="); - System.out.println(); - System.out.println("Algorithms with max = " + ofInterestCutoff + "*(max - min) < stat <= max."); - System.out.println(); - System.out.println("AP = Average Adj Precision; AR = Average Adj Recall"); - System.out.println("OP = Average orientation (arrow) Precision; OR = Average orientation (arrow) recall"); - System.out.println("McAdj = Mathew's correlation for adjacencies; McOr = Mathew's correlatin for orientatons"); - System.out.println("F1Adj = F1 score for adjacencies; F1Or = F1 score for orientations"); - System.out.println("E = Averaged Elapsed Time (ms), AP/P"); - System.out.println(); - System.out.println("num categories = 2 to " + maxCategories); - System.out.println("sample size = " + sampleSize); - System.out.println("penaltyDiscount = " + penaltyDiscount); - System.out.println("num runs = " + numRuns); - System.out.println(); - System.out.println("num measures = " + numMeasures); - System.out.println("num edges = " + numEdges); - - printBestStats(allAllRet, algorithms, statLabels); - } - - private double[][] printStats(String[] algorithms, int t, - int numCategories) { - NumberFormat nf = new DecimalFormat("0.00"); - - double[] sumAdjPrecision = new double[4]; - double[] sumAdjRecall = new double[4]; - double[] sumArrowPrecision = new double[4]; - double[] sumArrowRecall = new double[4]; - double[] sumSum = new double[4]; - double[] sumMcAdj = new double[4]; - double[] sumMcOr = new double[4]; - double[] sumF1Adj = new double[4]; - double[] sumF1Or = new double[4]; - double totalElapsed = 0.0; - - int[] countAP = new int[4]; - int[] countAR = new int[4]; - int[] countOP = new int[4]; - int[] countOR = new int[4]; - int[] countSum = new int[4]; - int[] countMcAdj = new int[4]; - int[] countMcOr = new int[4]; - int[] countF1Adj = new int[4]; - int[] countF1Or = new int[4]; - - for (int i = 0; i < 50; i++) { - List nodes = new ArrayList<>(); - - for (int r = 0; r < 30; r++) { - String name = "X" + (r + 1); - nodes.add(new ContinuousVariable(name)); - } - - Graph dag = edu.cmu.tetrad.graph.RandomGraph.randomGraphRandomForwardEdges(nodes, 0, 60, - 10, 10, 10, false); - DataSet data = getMixedDataAjStyle(dag, numCategories, 1000); - - Graph out; - final double penalty = 2; - - long start = MillisecondTimes.timeMillis(); - - switch (t) { - case 0: - out = searchSemFges(data); - break; - case 1: - out = searchBdeuFges(data, numCategories); - break; - case 2: - out = searchMixedFges(data); - break; - case 3: - out = searchMGMFges(data, penalty); - break; - default: - throw new IllegalStateException(); - } - - out = GraphUtils.replaceNodes(out, dag.getNodes()); - - Graph[] est = new Graph[4]; - - est[0] = out; - est[1] = getSubgraph(out, true, true, data); - est[2] = getSubgraph(out, true, false, data); - est[3] = getSubgraph(out, false, false, data); - - Graph[] truth = new Graph[4]; - - truth[0] = dag; - truth[1] = getSubgraph(dag, true, true, data); - truth[2] = getSubgraph(dag, true, false, data); - truth[3] = getSubgraph(dag, false, false, data); - - long stop = MillisecondTimes.timeMillis(); - - long elapsed = stop - start; - totalElapsed += elapsed; - - for (int u = 0; u < 4; u++) { - int adjTp = 0; - int adjFp = 0; - int adjTn; - int adjFn = 0; - int arrowsTp = 0; - int arrowsFp = 0; - int arrowsTn = 0; - int arrowsFn = 0; - - for (Edge edge : est[u].getEdges()) { - if (truth[u].isAdjacentTo(edge.getNode1(), edge.getNode2())) { - adjTp++; - } else { - adjFp++; - } - - if (edge.isDirected()) { - Edge _edge = truth[u].getEdge(edge.getNode1(), edge.getNode2()); - - if (edge != null && edge.equals(_edge)) { - arrowsTp++; - } else { - arrowsFp++; - } - } - } - - List nodes1 = truth[u].getNodes(); - - for (int w = 0; w < nodes1.size(); w++) { - for (int s = w + 1; w < nodes1.size(); w++) { - Node W = nodes1.get(w); - Node S = nodes1.get(s); - - if (truth[u].isAdjacentTo(W, S)) { - if (!est[u].isAdjacentTo(W, S)) { - adjFn++; - } - - Edge e1 = truth[u].getEdge(W, S); - Edge e2 = est[u].getEdge(W, S); - - if (!(e2 != null && e2.equals(e1))) { - arrowsFn++; - } - } - - Edge e1 = truth[u].getEdge(W, S); - Edge e2 = est[u].getEdge(W, S); - - if (!(e1 != null && e2 == null) || (e1 != null && e2 != null && !e1.equals(e2))) { - arrowsFn++; - } - } - } - - int allEdges = truth[u].getNumNodes() * (truth[u].getNumNodes() - 1); - - adjTn = allEdges / 2 - (adjFn + adjFp + adjTp); - arrowsTn = allEdges - (arrowsFn + arrowsFp + arrowsTp); - - double adjPrecision = adjTp / (double) (adjTp + adjFp); - double adjRecall = adjTp / (double) (adjTp + adjFn); - - double arrowPrecision = arrowsTp / (double) (arrowsTp + arrowsFp); - double arrowRecall = arrowsTp / (double) (arrowsTp + arrowsFn); - - if (!Double.isNaN(adjPrecision)) { - sumAdjPrecision[u] += adjPrecision; - countAP[u]++; - } - - if (!Double.isNaN(adjRecall)) { - sumAdjRecall[u] += adjRecall; - countAR[u]++; - } - - if (!Double.isNaN(arrowPrecision)) { - sumArrowPrecision[u] += arrowPrecision; - countOP[u]++; - } - - if (!Double.isNaN(arrowRecall)) { - sumArrowRecall[u] += arrowRecall; - countOR[u]++; - } - - double sum = adjPrecision + adjRecall + arrowPrecision + arrowRecall; - double mcAdj = (adjTp * adjTn - adjFp * adjFn) / - FastMath.sqrt((adjTp + adjFp) * (adjTp + adjFn) * (adjTn + adjFp) * (adjTn + adjFn)); - double mcOr = (arrowsTp * arrowsTn - arrowsFp * arrowsFn) / - FastMath.sqrt((arrowsTp + arrowsFp) * (arrowsTp + arrowsFn) * - (arrowsTn + arrowsFp) * (arrowsTn + arrowsFn)); - double f1Adj = 2 * (adjPrecision * adjRecall) / (adjPrecision + adjRecall); - double f1Arrows = 2 * (arrowPrecision * arrowRecall) / (arrowPrecision + arrowRecall); - - if (f1Arrows < 0) { - System.out.println(); - } - - if (!Double.isNaN(sum)) { - sumSum[u] += sum; - countSum[u]++; - } - - if (!Double.isNaN(mcAdj)) { - sumMcAdj[u] += mcAdj; - countMcAdj[u]++; - } - - if (!Double.isNaN(mcOr)) { - sumMcOr[u] += mcOr; - countMcOr[u]++; - } - - if (!Double.isNaN(f1Adj)) { - sumF1Adj[u] += f1Adj; - countF1Adj[u]++; - } - - if (!Double.isNaN(f1Arrows)) { - sumF1Or[u] += f1Arrows; - countF1Or[u]++; - } - } - } - - double[] avgAdjPrecision = new double[4]; - double[] avgAdjRecall = new double[4]; - double[] avgArrowPrecision = new double[4]; - double[] avgArrowRecall = new double[4]; - double[] avgSum = new double[4]; - double[] avgMcAdj = new double[4]; - double[] avgMcOr = new double[4]; - double[] avgF1Adj = new double[4]; - double[] avgF1Or = new double[4]; - double[] avgElapsed = new double[4]; - - for (int u = 0; u < 4; u++) { - avgAdjPrecision[u] = sumAdjPrecision[u] / (double) countAP[u]; - avgAdjRecall[u] = sumAdjRecall[u] / (double) countAR[u]; - avgArrowPrecision[u] = sumArrowPrecision[u] / (double) countOP[u]; - avgArrowRecall[u] = sumArrowRecall[u] / (double) countOR[u]; - avgSum[u] = sumSum[u] / (double) countSum[u]; - avgMcAdj[u] = sumMcAdj[u] / (double) countMcAdj[u]; - avgMcOr[u] = sumMcOr[u] / (double) countMcOr[u]; - avgF1Adj[u] = sumF1Adj[u] / (double) countF1Adj[u]; - avgF1Or[u] = sumF1Or[u] / (double) countF1Or[u]; - avgElapsed[u] = -totalElapsed / (double) 50; - } - - double[][] ret = { - avgAdjPrecision, - avgAdjRecall, - avgArrowPrecision, - avgArrowRecall, - avgSum, - avgMcAdj, - avgMcOr, - avgF1Adj, - avgF1Or, - avgElapsed - }; - - System.out.println(); - - for (int u = 0; u < 4; u++) { - String header = getHeader(u); - - System.out.println("\n" + header + "\n"); - - System.out.println(algorithms[t] + " adj precision " + nf.format(avgAdjPrecision[u])); - System.out.println(algorithms[t] + " adj recall " + nf.format(avgAdjRecall[u])); - System.out.println(algorithms[t] + " arrow precision " + nf.format(avgArrowPrecision[u])); - System.out.println(algorithms[t] + " arrow recall " + nf.format(avgArrowRecall[u])); - System.out.println(algorithms[t] + " sum " + nf.format(avgSum[u])); - System.out.println(algorithms[t] + " McAdj " + nf.format(avgMcAdj[u])); - System.out.println(algorithms[t] + " McOr " + nf.format(avgMcOr[u])); - System.out.println(algorithms[t] + " F1adj " + nf.format(avgF1Adj[u])); - System.out.println(algorithms[t] + " F1Or " + nf.format(avgF1Or[u])); - System.out.println(algorithms[t] + " avg elapsed " + nf.format(avgElapsed[u])); - } - - - return ret; - } - - private String getHeader(int u) { - String header; - - switch (u) { - case 0: - header = "All edges"; - break; - case 1: - header = "Discrete-discrete"; - break; - case 2: - header = "Discrete-continuous"; - break; - case 3: - header = "Continuous-continuous"; - break; - default: - throw new IllegalStateException(); - } - return header; - } - - private void printBestStats(double[][][][] allAllRet, String[] algorithms, String[] statLabels) { - TextTable table = new TextTable(allAllRet.length + 1, allAllRet[0][0].length + 1); - - - class Pair { - private final String algorithm; - private final double stat; - - public Pair(String algorithm, double stat) { - this.algorithm = algorithm; - this.stat = stat; - } - - public String getAlgorithm() { - return this.algorithm; - } - - public double getStat() { - return this.stat; - } - } - - - System.out.println(); - System.out.println("And the winners are... !"); - - for (int u = 0; u < 4; u++) { - for (int numCategories = 2; numCategories <= 5; numCategories++) { - - table.setToken(numCategories - 1, 0, numCategories + ""); - - for (int statIndex = 0; statIndex < allAllRet[numCategories - 2][0].length; statIndex++) { -// double maxStat = Double.NaN; - String maxAlg = "-"; - - List algStats = new ArrayList<>(); - - for (int t = 0; t < algorithms.length; t++) { - double stat = allAllRet[numCategories - 2][t][statIndex][u]; - if (!Double.isNaN(stat)) { - algStats.add(new Pair(algorithms[t], stat)); - } - } - - if (algStats.isEmpty()) { - maxAlg = "-"; - } else { - Collections.sort(algStats, new Comparator() { - - @Override - public int compare(Pair o1, Pair o2) { - return -Double.compare(o1.getStat(), o2.getStat()); - } - }); - - double maxStat = algStats.get(0).getStat(); - maxAlg = algStats.get(0).getAlgorithm(); - - double minStat = algStats.get(algStats.size() - 1).getStat(); - - double diff = maxStat - minStat; - double ofInterest = maxStat - 0.05 * (diff); - - for (int i = 1; i < algStats.size(); i++) { - if (algStats.get(i).getStat() >= ofInterest) { - maxAlg += "," + algStats.get(i).getAlgorithm(); - } - } - } - - table.setToken(numCategories - 1, statIndex + 1, maxAlg); - } - } - - for (int j = 0; j < statLabels.length; j++) { - table.setToken(0, j + 1, statLabels[j]); - } - - System.out.println(); - System.out.println(getHeader(u)); - System.out.println(); - - System.out.println(table); - } - - - NumberFormat nf = new DecimalFormat("0.00"); - - System.out.println(); - System.out.println("Details:"); - System.out.println(); - System.out.println("Average statistics"); - - for (int u = 0; u < 4; u++) { - System.out.println(); - System.out.println(getHeader(u)); - System.out.println(); - - for (int numCategories = 2; numCategories <= 5; numCategories++) { - System.out.println("\n# categories = " + numCategories); - - for (int t = 0; t < algorithms.length; t++) { - String algorithm = algorithms[t]; - - System.out.println("\nAlgorithm = " + algorithm); - System.out.println(); - - for (int statIndex = 0; statIndex < allAllRet[numCategories - 2][0].length; statIndex++) { - String statLabel = statLabels[statIndex]; - double stat = allAllRet[numCategories - 2][t][statIndex][u]; - System.out.println("\tAverage" + statLabel + " = " + nf.format(stat)); - } - } - } - } - - } - - // @Test - public void test7() { - for (int i = 0; i < 10; i++) { - - Graph graph = edu.cmu.tetrad.graph.RandomGraph.randomGraph(10, 0, - 10, 10, 10, 10, false); - SemPm semPm = new SemPm(graph); - SemIm semIm = new SemIm(semPm); - DataSet dataSet = semIm.simulateData(1000, false); - - edu.cmu.tetrad.search.Fges fges = new edu.cmu.tetrad.search.Fges(new SemBicScore(new CovarianceMatrix(dataSet))); - Graph CPDAG = fges.search(); - - Graph dag = dagFromCPDAG(CPDAG); - - assertFalse(dag.paths().existsDirectedCycle()); - } - } - - private Graph dagFromCPDAG(Graph CPDAG) { - Graph dag = new EdgeListGraph(CPDAG); - - MeekRules rules = new MeekRules(); - - WHILE: - while (true) { - List edges = new ArrayList<>(dag.getEdges()); - - for (Edge edge : edges) { - if (Edges.isUndirectedEdge(edge)) { - Node x = edge.getNode1(); - Node y = edge.getNode2(); - - List okx = dag.getAdjacentNodes(x); - okx.removeAll(dag.getChildren(x)); - okx.remove(y); - - List oky = dag.getAdjacentNodes(y); - oky.removeAll(dag.getChildren(y)); - oky.remove(x); - - if (!okx.isEmpty()) { - Node other = okx.iterator().next(); - dag.removeEdge(other, x); - dag.removeEdge(y, x); - dag.addDirectedEdge(other, x); - dag.addDirectedEdge(y, x); - } else if (!oky.isEmpty()) { - Node other = oky.iterator().next(); - dag.removeEdge(other, y); - dag.removeEdge(x, y); - dag.addDirectedEdge(other, y); - dag.addDirectedEdge(x, y); - } else { - dag.removeEdge(x, y); - dag.addDirectedEdge(x, y); - } - - rules.orientImplied(dag); - continue WHILE; - } - } - - break; - } - - return dag; - } - - public void test9() { - - Parameters parameters = new Parameters(); - - parameters.set(Params.NUM_MEASURES, 50); - parameters.set(Params.NUM_LATENTS, 0); - parameters.set(Params.AVG_DEGREE, 2); - parameters.set(Params.MAX_DEGREE, 20); - parameters.set(Params.MAX_INDEGREE, 20); - parameters.set(Params.MAX_OUTDEGREE, 20); - parameters.set(Params.CONNECTED, false); - - parameters.set(Params.COEF_LOW, 0.2); - parameters.set(Params.COEF_HIGH, 0.9); - parameters.set(Params.VAR_LOW, 1); - parameters.set(Params.VAR_HIGH, 3); - parameters.set(Params.VERBOSE, false); - parameters.set(Params.COEF_SYMMETRIC, true); - parameters.set(Params.NUM_RUNS, 1); - parameters.set(Params.PERCENT_DISCRETE, 0); - parameters.set(Params.NUM_CATEGORIES, 3); - parameters.set(Params.DIFFERENT_GRAPHS, true); - parameters.set(Params.SAMPLE_SIZE, 500); - parameters.set(Params.INTERVAL_BETWEEN_SHOCKS, 10); - parameters.set(Params.INTERVAL_BETWEEN_RECORDINGS, 10); - parameters.set(Params.FISHER_EPSILON, 0.001); - parameters.set(Params.RANDOMIZE_COLUMNS, true); - - RandomGraph graph = new RandomForward(); - LinearFisherModel sim = new LinearFisherModel(graph); - sim.createData(parameters, false); - Graph previous = null; - int prevDiff = Integer.MAX_VALUE; - -// for (int l = 7; l >= 1; l--) { - for (int i = 2; i <= 20; i++) { - parameters.set(Params.PENALTY_DISCOUNT, i / (double) 10); - - ScoreWrapper score = new edu.cmu.tetrad.algcomparison.score.SemBicScore(); - Algorithm alg = new Cpc(new FisherZ()); - - Graph out = alg.search(sim.getDataModel(0), parameters); -// Graph out = GraphUtils.undirectedGraph(alg.search(sim.getDataModel(0), parameters)); - - Set edges1 = out.getEdges(); - - int numEdges = edges1.size(); - - if (previous != null) { - Set edges2 = previous.getEdges(); - edges2.removeAll(edges1); - int diff = edges2.size(); -// - System.out.println("Penalty discount =" + parameters.getDouble(Params.PENALTY_DISCOUNT) - + " # edges = " + numEdges - + " # additional = " + diff); - - previous = out; - if (diff > prevDiff) break; - prevDiff = diff; - } else { - previous = out; - } - } - - Graph estGraph = previous; - Graph trueGraph = sim.getTrueGraph(0); - - estGraph = GraphUtils.replaceNodes(estGraph, trueGraph.getNodes()); - - Statistic ap = new AdjacencyPrecision(); - Statistic ar = new AdjacencyRecall(); - Statistic ahp = new ArrowheadPrecision(); - Statistic ahr = new ArrowheadRecall(); - - System.out.println("AP = " + ap.getValue(trueGraph, estGraph, null)); - System.out.println("AR = " + ar.getValue(trueGraph, estGraph, null)); - System.out.println("AHP = " + ahp.getValue(trueGraph, estGraph, null)); - System.out.println("AHR = " + ahr.getValue(trueGraph, estGraph, null)); - } - @Test public void testSemBicDiffs() { final int N = 1000; final int numCond = 3; - Graph graph = edu.cmu.tetrad.graph.RandomGraph.randomGraph(10, 0, 20, 100, + Graph graph = edu.cmu.tetrad.graph.RandomGraph.randomGraph(10, 0, 10, 100, 100, 100, false); List nodes = graph.getNodes(); buildIndexing(nodes); @@ -1646,8 +733,8 @@ public void testSemBicDiffs() { double diff = scoreGraphChange(x, y, z, this.hashIndices, score); boolean diffNegative = diff < 0; - if (!_msep && _msep != diffNegative) { - System.out.println(count++ + "\t" + (_msep ? "msep" : "mconn") + "\t" + (diffNegative ? "indep" : "dep") + "\tdiff = " + diff); + if (!_msep && diffNegative) { + System.out.println(count++ + "\t" + "mconn" + "\t" + "indep" + "\tdiff = " + diff); } } @@ -1688,7 +775,6 @@ private void buildIndexing(List nodes) { this.hashIndices.put(n, ++i); } } - } From 47ec4ceddf1d5288ce52cb1bfecffb02f23d0bb3 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Thu, 1 Feb 2024 01:20:46 -0500 Subject: [PATCH 150/163] Cleanup. --- .../pitt/dbmi/data/reader/ContinuousData.java | 10 ++++ .../edu/pitt/dbmi/data/reader/DataColumn.java | 10 ++-- .../pitt/dbmi/data/reader/DataColumns.java | 7 +++ .../pitt/dbmi/data/reader/DataFileReader.java | 20 ++++++- .../edu/pitt/dbmi/data/reader/DataReader.java | 4 +- .../dbmi/data/reader/DataReaderException.java | 3 + .../dbmi/data/reader/DatasetFileReader.java | 11 ++++ .../pitt/dbmi/data/reader/DatasetReader.java | 2 +- .../edu/pitt/dbmi/data/reader/Delimiter.java | 21 +++++++ .../pitt/dbmi/data/reader/DiscreteData.java | 10 ++++ .../dbmi/data/reader/DiscreteDataColumn.java | 24 ++++++++ .../edu/pitt/dbmi/data/reader/MixedData.java | 20 +++++++ .../reader/covariance/CovarianceData.java | 9 +++ .../covariance/CovarianceDataReader.java | 6 ++ .../LowerCovarianceDataFileReader.java | 25 ++++++-- .../data/reader/metadata/ColumnMetadata.java | 60 +++++++++++++++++++ .../reader/metadata/InterventionalColumn.java | 34 +++++++++++ .../dbmi/data/reader/metadata/Metadata.java | 35 ++++++++++- .../reader/metadata/MetadataFileReader.java | 11 ++++ .../reader/metadata/MetadataFileWriter.java | 15 ++++- .../data/reader/metadata/MetadataReader.java | 6 ++ .../data/reader/metadata/MetadataWriter.java | 7 +++ .../reader/preview/AbstractDataPreviewer.java | 5 ++ .../reader/preview/BasicDataPreviewer.java | 18 +++++- .../data/reader/preview/DataPreviewer.java | 9 +++ .../AbstractTabularColumnFileReader.java | 6 ++ .../reader/tabular/ContinuousTabularData.java | 16 +++++ .../ContinuousTabularDatasetFileReader.java | 6 ++ .../tabular/DiscreteTabularDataColumn.java | 39 ++++++++++++ .../data/reader/tabular/MixedTabularData.java | 28 +++++++++ .../tabular/MixedTabularDataColumn.java | 39 ++++++++++++ .../MixedTabularDatasetFileReader.java | 35 +++++++++++ .../tabular/TabularColumnFileReader.java | 39 +++++++++++- .../reader/tabular/TabularColumnReader.java | 30 ++++++++++ .../reader/tabular/TabularDataColumn.java | 45 ++++++++++++++ .../reader/tabular/TabularDataFileReader.java | 34 ++++++----- .../reader/tabular/TabularDataReader.java | 23 ++++++- .../reader/tabular/TabularDatasetReader.java | 25 ++++++++ .../tabular/VerticalDiscreteTabularData.java | 16 +++++ ...ticalDiscreteTabularDatasetFileReader.java | 36 +++++++++++ .../pitt/dbmi/data/reader/util/Columns.java | 12 +++- .../data/reader/validation/Validation.java | 3 + .../reader/validation/ValidationResult.java | 49 +++++++++++++++ .../covariance/CovarianceValidation.java | 5 ++ .../LowerCovarianceDataFileValidation.java | 11 ++++ .../tabular/TabularColumnFileValidation.java | 34 ++++++++++- .../tabular/TabularColumnValidation.java | 17 ++++++ .../tabular/TabularDataFileValidation.java | 13 ++++ .../tabular/TabularDataValidation.java | 7 +++ 49 files changed, 906 insertions(+), 44 deletions(-) diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/ContinuousData.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/ContinuousData.java index ac78ff2ba3..47e19a5c5b 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/ContinuousData.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/ContinuousData.java @@ -25,8 +25,18 @@ */ public interface ContinuousData extends Data { + /** + * Get the data columns. + * + * @return the data columns. + */ DataColumn[] getDataColumns(); + /** + * Get the data. + * + * @return the data. + */ double[][] getData(); } diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/DataColumn.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/DataColumn.java index 93e4367813..c8759b5b59 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/DataColumn.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/DataColumn.java @@ -28,35 +28,35 @@ public interface DataColumn { /** * Get the column's name. * - * @return + * @return the column's name. */ String getName(); /** * Get the column's number. * - * @return + * @return the column's number. */ int getColumnNumber(); /** * True if this column was not read in from source such as file. * - * @return + * @return true if this column was not read in from source such as file. */ boolean isGenerated(); /** * True if the datatype is discrete. * - * @return + * @return true if the datatype is discrete. */ boolean isDiscrete(); /** * Set true for discrete datatype. * - * @param discrete + * @param discrete true for discrete datatype. */ void setDiscrete(boolean discrete); diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/DataColumns.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/DataColumns.java index 13470ed23f..c9ddc90fdc 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/DataColumns.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/DataColumns.java @@ -38,6 +38,13 @@ public final class DataColumns { private DataColumns() { } + /** + * Update data columns with metadata. + * + * @param dataColumns data columns + * @param metadata metadata + * @return updated data columns + */ public static DataColumn[] update(DataColumn[] dataColumns, Metadata metadata) { Map columnMetadataMap = DataColumns.getColumnMetadataMap(metadata); diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/DataFileReader.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/DataFileReader.java index 84bd8fdfae..1520378dac 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/DataFileReader.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/DataFileReader.java @@ -41,6 +41,12 @@ public abstract class DataFileReader implements DataReader { protected byte quoteCharacter; protected String commentMarker; + /** + * Constructor. + * + * @param dataFile the data file + * @param delimiter the delimiter + */ public DataFileReader(Path dataFile, Delimiter delimiter) { this.dataFile = dataFile; this.delimiter = delimiter; @@ -52,7 +58,7 @@ public DataFileReader(Path dataFile, Delimiter delimiter) { * Counts number of column from the first non-blank line. * * @return the number of column from the first non-blank line - * @throws IOException + * @throws IOException if an I/O error occurs */ protected int countNumberOfColumns() throws IOException { int count = 0; @@ -148,7 +154,7 @@ protected int countNumberOfColumns() throws IOException { * Counts number of non-blank lines. * * @return the number of non-blank and non-commented lines - * @throws IOException + * @throws IOException if an I/O error occurs */ protected int countNumberOfLines() throws IOException { int count = 0; @@ -214,6 +220,11 @@ protected int countNumberOfLines() throws IOException { return count; } + /** + * Sets the quote character. + * + * @param quoteCharacter the quote character + */ @Override public void setQuoteCharacter(char quoteCharacter) { this.quoteCharacter = Character.isDefined(quoteCharacter) @@ -221,6 +232,11 @@ public void setQuoteCharacter(char quoteCharacter) { : (byte) -1; } + /** + * Sets the comment marker. + * + * @param commentMarker the comment marker + */ @Override public void setCommentMarker(String commentMarker) { this.commentMarker = (commentMarker == null) diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/DataReader.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/DataReader.java index eca120b5b5..010c999fe8 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/DataReader.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/DataReader.java @@ -28,14 +28,14 @@ public interface DataReader { /** * Set the character that is used to group multiple words as one. * - * @param quoteCharacter + * @param quoteCharacter the quote character. */ void setQuoteCharacter(char quoteCharacter); /** * Set the value to indicate a line is a comment to be ignored. * - * @param commentMarker + * @param commentMarker the comment marker. */ void setCommentMarker(String commentMarker); diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/DataReaderException.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/DataReaderException.java index 97ab03732f..8750ca886b 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/DataReaderException.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/DataReaderException.java @@ -18,6 +18,8 @@ */ package edu.pitt.dbmi.data.reader; +import java.io.Serial; + /** * Nov 6, 2018 2:26:59 PM * @@ -25,6 +27,7 @@ */ public class DataReaderException extends RuntimeException { + @Serial private static final long serialVersionUID = 1123054334542973950L; /** diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/DatasetFileReader.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/DatasetFileReader.java index fe451b58ce..7dbf33e487 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/DatasetFileReader.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/DatasetFileReader.java @@ -29,12 +29,23 @@ public abstract class DatasetFileReader extends DataFileReader implements Datase protected String missingDataMarker; + /** + * Constructor. + * + * @param dataFile the data file + * @param delimiter the delimiter + */ public DatasetFileReader(Path dataFile, Delimiter delimiter) { super(dataFile, delimiter); this.missingDataMarker = ""; } + /** + * Get the missing data marker. + * + * @param missingDataMarker the missing data marker + */ @Override public void setMissingDataMarker(String missingDataMarker) { this.missingDataMarker = (missingDataMarker == null) diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/DatasetReader.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/DatasetReader.java index dd3d1cf3a1..638a339155 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/DatasetReader.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/DatasetReader.java @@ -32,7 +32,7 @@ public interface DatasetReader extends DataReader { /** * Set the value to indicate missing data. * - * @param missingDataMarker + * @param missingDataMarker the missing data marker. */ void setMissingDataMarker(String missingDataMarker); diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/Delimiter.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/Delimiter.java index 7f38b8159e..bdde12d9d4 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/Delimiter.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/Delimiter.java @@ -37,20 +37,41 @@ public enum Delimiter { private final char value; private final byte byteValue; + /** + * Constructor. + * + * @param name the name of the delimiter. + * @param value the value of the delimiter. + */ Delimiter(String name, char value) { this.name = name; this.value = value; this.byteValue = (byte) value; } + /** + * Get the name of the delimiter. + * + * @return the name of the delimiter. + */ public String getName() { return this.name; } + /** + * Get the value of the delimiter. + * + * @return the value of the delimiter. + */ public char getValue() { return this.value; } + /** + * Get the byte value of the delimiter. + * + * @return the byte value of the delimiter. + */ public byte getByteValue() { return this.byteValue; } diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/DiscreteData.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/DiscreteData.java index e2ca7bbeb8..8fa7fb3074 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/DiscreteData.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/DiscreteData.java @@ -25,8 +25,18 @@ */ public interface DiscreteData extends Data { + /** + * Get the discrete data columns. + * + * @return the discrete data columns. + */ DiscreteDataColumn[] getDataColumns(); + /** + * Get the discrete data. + * + * @return the discrete data. + */ int[][] getData(); } diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/DiscreteDataColumn.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/DiscreteDataColumn.java index 4f496e66c9..6b3e56a2f0 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/DiscreteDataColumn.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/DiscreteDataColumn.java @@ -27,14 +27,38 @@ */ public interface DiscreteDataColumn { + /** + * Get the encode value. + * + * @param value the value. + * @return the encode value. + */ Integer getEncodeValue(String value); + /** + * Recategorize the data. + */ void recategorize(); + /** + * Get the categories. + * + * @return the categories. + */ List getCategories(); + /** + * Get the data column. + * + * @return the data column. + */ DataColumn getDataColumn(); + /** + * Set the value. + * + * @param value the value. + */ void setValue(String value); } diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/MixedData.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/MixedData.java index 0d160d8cc1..463a59fdf9 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/MixedData.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/MixedData.java @@ -25,12 +25,32 @@ */ public interface MixedData extends Data { + /** + * Get the number of rows. + * + * @return the number of rows. + */ int getNumOfRows(); + /** + * Get the data columns. + * + * @return the data columns. + */ DiscreteDataColumn[] getDataColumns(); + /** + * Get the continuous data. + * + * @return the continuous data. + */ double[][] getContinuousData(); + /** + * Get the discrete data. + * + * @return the discrete data. + */ int[][] getDiscreteData(); } diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/covariance/CovarianceData.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/covariance/CovarianceData.java index 205c80833f..19cd379949 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/covariance/CovarianceData.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/covariance/CovarianceData.java @@ -29,10 +29,19 @@ */ public interface CovarianceData extends Data { + /** + * @return the number of cases in the data. + */ int getNumberOfCases(); + /** + * @return the number of variables in the data. + */ List getVariables(); + /** + * @return the data in a 2D array. + */ double[][] getData(); } diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/covariance/CovarianceDataReader.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/covariance/CovarianceDataReader.java index 13418c4582..81b6cc3bc6 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/covariance/CovarianceDataReader.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/covariance/CovarianceDataReader.java @@ -29,6 +29,12 @@ */ public interface CovarianceDataReader extends DataReader { + /** + * Reads in the covariance data. + * + * @return the covariance data. + * @throws IOException if an I/O error occurs. + */ CovarianceData readInData() throws IOException; } diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/covariance/LowerCovarianceDataFileReader.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/covariance/LowerCovarianceDataFileReader.java index a418bf6783..c08a072884 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/covariance/LowerCovarianceDataFileReader.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/covariance/LowerCovarianceDataFileReader.java @@ -37,12 +37,22 @@ */ public class LowerCovarianceDataFileReader extends DataFileReader implements CovarianceDataReader { -// private static final Logger LOGGER = LoggerFactory.getLogger(LowerCovarianceDataFileReader.class); - + /** + * Constructs a lower triangular covariance data file reader. + * + * @param dataFile the data file. + * @param delimiter the delimiter. + */ public LowerCovarianceDataFileReader(Path dataFile, Delimiter delimiter) { super(dataFile, delimiter); } + /** + * Reads in the covariance data. + * + * @return the covariance data. + * @throws IOException if an I/O error occurs. + */ @Override public CovarianceData readInData() throws IOException { int numOfCases = getNumberOfCases(); @@ -513,21 +523,28 @@ private LowerCovarianceData(int numberOfCases, List variables, double[][ this.data = data; } + /** + * @return the number of cases in the data. + */ @Override public int getNumberOfCases() { return this.numberOfCases; } + /** + * @return the number of variables in the data. + */ @Override public List getVariables() { return this.variables; } + /** + * @return the data in a 2D array. + */ @Override public double[][] getData() { return this.data; } - } - } diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/metadata/ColumnMetadata.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/metadata/ColumnMetadata.java index b7f165acae..b925b3d7ad 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/metadata/ColumnMetadata.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/metadata/ColumnMetadata.java @@ -27,53 +27,113 @@ */ public class ColumnMetadata { + /** + * The name of the column. + */ private String name; + /** + * Indicates whether the column is discrete. + */ private boolean discrete; + /** + * The column number. + */ @JsonIgnore private int columnNumber; + /** + * Default constructor. + */ public ColumnMetadata() { this.discrete = true; } + /** + * Constructor. + * + * @param name the name of the column. + * @param discrete indicates whether the column is discrete. + */ public ColumnMetadata(String name, boolean discrete) { this.name = name; this.discrete = discrete; } + /** + * Constructor. + * + * @param name the name of the column. + * @param columnNumber the column number. + * @param discrete indicates whether the column is discrete. + */ public ColumnMetadata(String name, int columnNumber, boolean discrete) { this.name = name; this.columnNumber = columnNumber; this.discrete = discrete; } + /** + * Return a string representation of the column metadata. + * + * @return a string representation of the column metadata. + */ @Override public String toString() { return "ColumnMetadata{" + "name=" + this.name + ", discrete=" + this.discrete + ", columnNumber=" + this.columnNumber + '}'; } + /** + * Return the name of the column. + * + * @return the name of the column. + */ public String getName() { return this.name; } + /** + * Set the name of the column. + * + * @param name the name of the column. + */ public void setName(String name) { this.name = name; } + /** + * Return whether the column is discrete. + * + * @return whether the column is discrete. + */ public boolean isDiscrete() { return this.discrete; } + /** + * Set whether the column is discrete. + * + * @param discrete whether the column is discrete. + */ public void setDiscrete(boolean discrete) { this.discrete = discrete; } + /** + * Return the column number. + * + * @return the column number. + */ public int getColumnNumber() { return this.columnNumber; } + /** + * Set the column number. + * + * @param columnNumber the column number. + */ public void setColumnNumber(int columnNumber) { this.columnNumber = columnNumber; } diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/metadata/InterventionalColumn.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/metadata/InterventionalColumn.java index b437402a58..aebfc66993 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/metadata/InterventionalColumn.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/metadata/InterventionalColumn.java @@ -33,31 +33,65 @@ public class InterventionalColumn { @JsonProperty("status") private ColumnMetadata statusColumn; + /** + * Default constructor. + */ public InterventionalColumn() { } + /** + * Constructor. + * + * @param valueColumn The value column. + * @param statusColumn The status column. + */ public InterventionalColumn(ColumnMetadata valueColumn, ColumnMetadata statusColumn) { this.valueColumn = valueColumn; this.statusColumn = statusColumn; } + /** + * Returns a string representation of this object. + * + * @return a string representation of this object. + */ @Override public String toString() { return "InterventionalColumn{" + "valueColumn=" + this.valueColumn + ", statusColumn=" + this.statusColumn + '}'; } + /** + * Returns the value column. + * + * @return the value column. + */ public ColumnMetadata getValueColumn() { return this.valueColumn; } + /** + * Sets the value column. + * + * @param valueColumn the value column. + */ public void setValueColumn(ColumnMetadata valueColumn) { this.valueColumn = valueColumn; } + /** + * Returns the status column. + * + * @return the status column. + */ public ColumnMetadata getStatusColumn() { return this.statusColumn; } + /** + * Sets the status column. + * + * @param statusColumn the status column. + */ public void setStatusColumn(ColumnMetadata statusColumn) { this.statusColumn = statusColumn; } diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/metadata/Metadata.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/metadata/Metadata.java index 9f888ce669..dd268afcfa 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/metadata/Metadata.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/metadata/Metadata.java @@ -36,9 +36,18 @@ public class Metadata { @JsonProperty("interventions") private List interventionalColumns = new LinkedList<>(); + /** + * Default constructor. + */ public Metadata() { } + /** + * Constructor. + * + * @param domainColumnns The domain columns. + * @param interventionalColumns The interventional columns. + */ public Metadata(List domainColumnns, List interventionalColumns) { if (domainColumnns != null) { this.domainColumnns.addAll(domainColumnns); @@ -48,25 +57,49 @@ public Metadata(List domainColumnns, List } } + /** + * Returns a string representation of this object. + * + * @return a string representation of this object. + */ @Override public String toString() { return "Metadata{" + "domainColumnns=" + this.domainColumnns + ", interventionalColumns=" + this.interventionalColumns + '}'; } + /** + * Returns the domain columns. + * + * @return the domain columns. + */ public List getDomainColumnns() { return this.domainColumnns; } + /** + * Sets the domain columns. + * + * @param domainColumnns the domain columns. + */ public void setDomainColumnns(List domainColumnns) { this.domainColumnns = domainColumnns; } + /** + * Returns the interventional columns. + * + * @return the interventional columns. + */ public List getInterventionalColumns() { return this.interventionalColumns; } + /** + * Sets the interventional columns. + * + * @param interventionalColumns the interventional columns. + */ public void setInterventionalColumns(List interventionalColumns) { this.interventionalColumns = interventionalColumns; } - } diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/metadata/MetadataFileReader.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/metadata/MetadataFileReader.java index bfb1e7ccf4..1d6f241000 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/metadata/MetadataFileReader.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/metadata/MetadataFileReader.java @@ -34,10 +34,21 @@ public class MetadataFileReader implements MetadataReader { protected final Path metadataFile; + /** + * Constructor. + * + * @param metadataFile The metadata file. + */ public MetadataFileReader(Path metadataFile) { this.metadataFile = metadataFile; } + /** + * Reads in the metadata. + * + * @return the metadata. + * @throws IOException if an I/O error occurs. + */ @Override public Metadata read() throws IOException { try (BufferedReader reader = Files.newBufferedReader(this.metadataFile)) { diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/metadata/MetadataFileWriter.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/metadata/MetadataFileWriter.java index cc34664e7d..ab123207f5 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/metadata/MetadataFileWriter.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/metadata/MetadataFileWriter.java @@ -34,6 +34,13 @@ */ public class MetadataFileWriter implements MetadataWriter { + /** + * Writes the metadata as a string. + * + * @param metadata The metadata. + * @return the metadata as a string. + * @throws JsonProcessingException if an error occurs while processing the JSON. + */ @Override public String writeAsString(Metadata metadata) throws JsonProcessingException { return new ObjectMapper() @@ -42,6 +49,13 @@ public String writeAsString(Metadata metadata) throws JsonProcessingException { .writeValueAsString(metadata); } + /** + * Writes the metadata to a file. + * + * @param metadata The metadata. + * @param outputFile The output file. + * @throws IOException if an I/O error occurs. + */ @Override public void write(Metadata metadata, Path outputFile) throws IOException { ObjectWriter writer = new ObjectMapper().writer().withDefaultPrettyPrinter(); @@ -53,5 +67,4 @@ public void write(Metadata metadata, Path outputFile) throws IOException { Files.write(outputFile, writer.writeValueAsBytes(metadata), StandardOpenOption.CREATE); } } - } diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/metadata/MetadataReader.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/metadata/MetadataReader.java index e4b8a3cee9..5a09df5570 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/metadata/MetadataReader.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/metadata/MetadataReader.java @@ -27,6 +27,12 @@ */ public interface MetadataReader { + /** + * Reads in the metadata. + * + * @return the metadata. + * @throws IOException if an I/O error occurs. + */ Metadata read() throws IOException; } diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/metadata/MetadataWriter.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/metadata/MetadataWriter.java index b5614f333a..e42976576f 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/metadata/MetadataWriter.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/metadata/MetadataWriter.java @@ -30,6 +30,13 @@ */ public interface MetadataWriter { + /** + * Writes the metadata as a string. + * + * @param metadata The metadata. + * @return the metadata as a string. + * @throws JsonProcessingException if an error occurs while processing the JSON. + */ String writeAsString(Metadata metadata) throws JsonProcessingException; void write(Metadata metadata, Path outputFile) throws IOException; diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/preview/AbstractDataPreviewer.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/preview/AbstractDataPreviewer.java index 391bce36f5..34f342f98e 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/preview/AbstractDataPreviewer.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/preview/AbstractDataPreviewer.java @@ -34,6 +34,11 @@ public abstract class AbstractDataPreviewer { protected final Path dataFile; + /** + * Constructor. + * + * @param dataFile The data file. + */ public AbstractDataPreviewer(Path dataFile) { this.dataFile = dataFile; } diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/preview/BasicDataPreviewer.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/preview/BasicDataPreviewer.java index d1b9efdfc8..bf399c616a 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/preview/BasicDataPreviewer.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/preview/BasicDataPreviewer.java @@ -38,14 +38,26 @@ */ public class BasicDataPreviewer extends AbstractDataPreviewer implements DataPreviewer { -// private static final Logger LOGGER = LoggerFactory.getLogger(BasicDataPreviewer.class); - + /** + * Constructor. + * + * @param dataFile The data file. + */ public BasicDataPreviewer(Path dataFile) { super(dataFile); } + /** + * Get the previews of the data file. + * + * @param fromLine The starting line number. + * @param toLine The ending line number. + * @param numOfCharacters The number of characters to preview. + * @return the previews. + * @throws IOException if an I/O error occurs. + */ @Override - public List getPreviews(int fromLine, int toLine, int numOfCharacters) throws IOException { + public List getPreviews(int fromLine, int toLine, int numOfCharacters) throws IOException { // parameter validations checkLineNumberParameter(fromLine, toLine); checkCharacterNumberParameter(numOfCharacters); diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/preview/DataPreviewer.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/preview/DataPreviewer.java index 4960c6bd77..2e2889ba08 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/preview/DataPreviewer.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/preview/DataPreviewer.java @@ -28,6 +28,15 @@ */ public interface DataPreviewer { + /** + * Get the previews of the data file. + * + * @param fromLine The starting line number. + * @param toLine The ending line number. + * @param numOfCharacters The number of characters to preview. + * @return the previews. + * @throws IOException if an I/O error occurs. + */ List getPreviews(int fromLine, int toLine, int numOfCharacters) throws IOException; } diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/AbstractTabularColumnFileReader.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/AbstractTabularColumnFileReader.java index ac163c3f66..0ce0aa3c78 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/AbstractTabularColumnFileReader.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/AbstractTabularColumnFileReader.java @@ -37,6 +37,12 @@ */ public abstract class AbstractTabularColumnFileReader extends DataFileReader { + /** + * Constructor. + * + * @param dataFile The data file. + * @param delimiter The delimiter. + */ public AbstractTabularColumnFileReader(Path dataFile, Delimiter delimiter) { super(dataFile, delimiter); } diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/ContinuousTabularData.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/ContinuousTabularData.java index fd6ce19f81..b1e729cbca 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/ContinuousTabularData.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/ContinuousTabularData.java @@ -31,16 +31,32 @@ public class ContinuousTabularData implements ContinuousData { private final DataColumn[] dataColumns; private final double[][] data; + /** + * Constructor. + * + * @param dataColumns The data columns. + * @param data The data. + */ public ContinuousTabularData(DataColumn[] dataColumns, double[][] data) { this.dataColumns = dataColumns; this.data = data; } + /** + * Get the data columns. + * + * @return the data columns. + */ @Override public DataColumn[] getDataColumns() { return this.dataColumns; } + /** + * Get the data. + * + * @return the data. + */ @Override public double[][] getData() { return this.data; diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/ContinuousTabularDatasetFileReader.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/ContinuousTabularDatasetFileReader.java index a3f9038e96..6cb85a1f09 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/ContinuousTabularDatasetFileReader.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/ContinuousTabularDatasetFileReader.java @@ -38,6 +38,12 @@ public class ContinuousTabularDatasetFileReader extends DatasetFileReader implem private boolean hasHeader; private char quoteChar; + /** + * Constructor. + * + * @param dataFile The data file. + * @param delimiter The delimiter. + */ public ContinuousTabularDatasetFileReader(Path dataFile, Delimiter delimiter) { super(dataFile, delimiter); this.hasHeader = this.hasHeader = true; diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/DiscreteTabularDataColumn.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/DiscreteTabularDataColumn.java index d0b33f5bc1..eb42d270dc 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/DiscreteTabularDataColumn.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/DiscreteTabularDataColumn.java @@ -34,21 +34,40 @@ public class DiscreteTabularDataColumn implements DiscreteDataColumn { private final Map values; private List categories; + /** + * Constructor. + * + * @param dataColumn The data column. + */ public DiscreteTabularDataColumn(DataColumn dataColumn) { this.dataColumn = dataColumn; this.values = new TreeMap<>(); } + /** + * Returns a string representation of the object. + * + * @return a string representation of the object. + */ @Override public String toString() { return "DiscreteTabularDataColumn{" + "dataColumn=" + this.dataColumn + ", values=" + this.values + ", categories=" + this.categories + '}'; } + /** + * Gets the encode value of the given value. + * + * @param value The value. + * @return the encode value of the given value. + */ @Override public Integer getEncodeValue(String value) { return this.values.get(value); } + /** + * Does a recategorization of the data column. + */ @Override public void recategorize() { Set keyset = this.values.keySet(); @@ -60,20 +79,40 @@ public void recategorize() { } } + /** + * Gets the value of the given encode value. + * + * @param value The encode value. + */ @Override public void setValue(String value) { this.values.put(value, null); } + /** + * Gets the data column. + * + * @return the data column. + */ @Override public DataColumn getDataColumn() { return this.dataColumn; } + /** + * Gets the values as a map + * + * @return the values. + */ public Map getValues() { return this.values; } + /** + * Gets the categories. + * + * @return the categories. + */ @Override public List getCategories() { return (this.categories == null) diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/MixedTabularData.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/MixedTabularData.java index 61d749c26c..8971b663b7 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/MixedTabularData.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/MixedTabularData.java @@ -33,6 +33,14 @@ public class MixedTabularData implements MixedData { private final double[][] continuousData; private final int[][] discreteData; + /** + * Constructor. + * + * @param numOfRows the number of rows. + * @param dataColumns the data columns. + * @param continuousData the continuous data. + * @param discreteData the discrete data. + */ public MixedTabularData(int numOfRows, DiscreteDataColumn[] dataColumns, double[][] continuousData, int[][] discreteData) { this.numOfRows = numOfRows; this.dataColumns = dataColumns; @@ -40,21 +48,41 @@ public MixedTabularData(int numOfRows, DiscreteDataColumn[] dataColumns, double[ this.discreteData = discreteData; } + /** + * Get the number of rows. + * + * @return the number of rows. + */ @Override public int getNumOfRows() { return this.numOfRows; } + /** + * Get the data columns. + * + * @return the data columns. + */ @Override public DiscreteDataColumn[] getDataColumns() { return this.dataColumns; } + /** + * Get the continuous data. + * + * @return the continuous data. + */ @Override public double[][] getContinuousData() { return this.continuousData; } + /** + * Get the discrete data. + * + * @return the discrete data. + */ @Override public int[][] getDiscreteData() { return this.discreteData; diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/MixedTabularDataColumn.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/MixedTabularDataColumn.java index 36797fe03a..0b22eb7071 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/MixedTabularDataColumn.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/MixedTabularDataColumn.java @@ -36,16 +36,32 @@ public class MixedTabularDataColumn implements DiscreteDataColumn { private final Map values; private List categories; + /** + * Constructor. + * + * @param dataColumn The data column. + */ public MixedTabularDataColumn(DataColumn dataColumn) { this.dataColumn = dataColumn; this.values = dataColumn.isDiscrete() ? new TreeMap<>() : null; } + /** + * Returns a string representation of the object. + * + * @return a string representation of the object. + */ @Override public String toString() { return "MixedTabularDataColumn{" + "dataColumn=" + this.dataColumn + ", values=" + this.values + ", categories=" + this.categories + '}'; } + /** + * Gets the encode value of the given value. + * + * @param value The value. + * @return the encode value of the given value. + */ @Override public Integer getEncodeValue(String value) { return (this.values == null) @@ -53,6 +69,9 @@ public Integer getEncodeValue(String value) { : this.values.get(value); } + /** + * Does a recategorization of the data column. + */ @Override public void recategorize() { if (this.values != null) { @@ -66,6 +85,11 @@ public void recategorize() { } } + /** + * Sets the value. + * + * @param value The value. + */ @Override public void setValue(String value) { if (this.values != null) { @@ -73,15 +97,30 @@ public void setValue(String value) { } } + /** + * Gets the data column. + * + * @return the data column. + */ @Override public DataColumn getDataColumn() { return this.dataColumn; } + /** + * Gets the values as a map. + * + * @return the values. + */ public Map getValues() { return this.values; } + /** + * Gets the categories. + * + * @return the categories. + */ @Override public List getCategories() { return (this.categories == null) ? Collections.EMPTY_LIST : this.categories; diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/MixedTabularDatasetFileReader.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/MixedTabularDatasetFileReader.java index 21e52ae86c..c8f1bbf019 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/MixedTabularDatasetFileReader.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/MixedTabularDatasetFileReader.java @@ -37,6 +37,13 @@ public class MixedTabularDatasetFileReader extends DatasetFileReader implements private boolean hasHeader; private char quoteChar; + /** + * Constructor. + * + * @param dataFile The data file. + * @param delimiter The delimiter. + * @param numberOfDiscreteCategories The number of discrete categories. + */ public MixedTabularDatasetFileReader(Path dataFile, Delimiter delimiter, int numberOfDiscreteCategories) { super(dataFile, delimiter); this.numberOfDiscreteCategories = numberOfDiscreteCategories; @@ -44,11 +51,22 @@ public MixedTabularDatasetFileReader(Path dataFile, Delimiter delimiter, int num this.quoteChar = '"'; } + /** + * Reads in the data. + * + * @return The data. + * @throws IOException If an I/O error occurs. + */ @Override public Data readInData() throws IOException { return readInData(Collections.EMPTY_SET); } + /** + * @param namesOfColumnsToExclude the names of columns to exclude + * @return The data. + * @throws IOException If an I/O error occurs. + */ @Override public Data readInData(Set namesOfColumnsToExclude) throws IOException { TabularColumnReader columnReader = new TabularColumnFileReader(this.dataFile, this.delimiter); @@ -70,6 +88,13 @@ public Data readInData(Set namesOfColumnsToExclude) throws IOException { return toMixedData(dataReader.read(dataColumns, this.hasHeader)); } + /** + * Reads in the data. + * + * @param columnsToExclude the columns to exclude + * @return The data. + * @throws IOException If an I/O error occurs. + */ @Override public Data readInData(int[] columnsToExclude) throws IOException { TabularColumnReader columnReader = new TabularColumnFileReader(this.dataFile, this.delimiter); @@ -141,11 +166,21 @@ private Data toMixedData(Data data) { } } + /** + * Sets whether the data file has a header. + * + * @param hasHeader Whether the data file has a header. + */ @Override public void setHasHeader(boolean hasHeader) { this.hasHeader = hasHeader; } + /** + * Sets the quote character. + * + * @param quoteCharacter The quote character. + */ @Override public void setQuoteCharacter(char quoteCharacter) { this.quoteChar = quoteCharacter; diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/TabularColumnFileReader.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/TabularColumnFileReader.java index 7053a73d91..c1231e58db 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/TabularColumnFileReader.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/TabularColumnFileReader.java @@ -40,17 +40,36 @@ */ public final class TabularColumnFileReader extends AbstractTabularColumnFileReader implements TabularColumnReader { -// private static final Logger LOGGER = LoggerFactory.getLogger(TabularColumnFileReader.class); - + /** + * Constructor. + * + * @param dataFile The data file. + * @param delimiter The delimiter. + */ public TabularColumnFileReader(Path dataFile, Delimiter delimiter) { super(dataFile, delimiter); } + /** + * Reads in the data columns. + * + * @param isDiscrete Whether the data is discrete. + * @return The data columns. + * @throws IOException If an I/O error occurs. + */ @Override public DataColumn[] readInDataColumns(boolean isDiscrete) throws IOException { return readInDataColumns(Collections.EMPTY_SET, isDiscrete); } + /** + * Reads in the data columns. + * + * @param namesOfColumnsToExclude the names of columns to exclude + * @param isDiscrete Whether the data is discrete. + * @return The data columns. + * @throws IOException If an I/O error occurs. + */ @Override public DataColumn[] readInDataColumns(Set namesOfColumnsToExclude, boolean isDiscrete) throws IOException { if (namesOfColumnsToExclude == null || namesOfColumnsToExclude.isEmpty()) { @@ -78,6 +97,14 @@ public DataColumn[] readInDataColumns(Set namesOfColumnsToExclude, boole } } + /** + * Reads in the data columns. + * + * @param columnsToExclude the columns to exclude + * @param isDiscrete Whether the data is discrete. + * @return The data columns. + * @throws IOException If an I/O error occurs. + */ @Override public DataColumn[] readInDataColumns(int[] columnsToExclude, boolean isDiscrete) throws IOException { int numOfCols = countNumberOfColumns(); @@ -87,6 +114,14 @@ public DataColumn[] readInDataColumns(int[] columnsToExclude, boolean isDiscrete return getColumns(validColsToExclude, isDiscrete); } + /** + * Generates the data columns. + * + * @param columnsToExclude the columns to exclude + * @param isDiscrete Whether the data is discrete. + * @return The data columns. + * @throws IOException If an I/O error occurs. + */ @Override public DataColumn[] generateColumns(int[] columnsToExclude, boolean isDiscrete) throws IOException { List columns = new LinkedList<>(); diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/TabularColumnReader.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/TabularColumnReader.java index 363a2ab877..298bb237b8 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/TabularColumnReader.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/TabularColumnReader.java @@ -31,12 +31,42 @@ */ public interface TabularColumnReader extends DataReader { + /** + * Read in the data columns. + * + * @param isDiscrete whether the data is discrete. + * @return the data columns. + * @throws IOException if an I/O error occurs. + */ DataColumn[] readInDataColumns(boolean isDiscrete) throws IOException; + /** + * Read in the data columns. + * + * @param namesOfColumnsToExclude the names of columns to exclude. + * @param isDiscrete whether the data is discrete. + * @return the data columns. + * @throws IOException if an I/O error occurs. + */ DataColumn[] readInDataColumns(Set namesOfColumnsToExclude, boolean isDiscrete) throws IOException; + /** + * Read in the data columns. + * + * @param columnsToExclude the columns to exclude. + * @param isDiscrete whether the data is discrete. + * @return the data columns. + * @throws IOException if an I/O error occurs. + */ DataColumn[] readInDataColumns(int[] columnsToExclude, boolean isDiscrete) throws IOException; + /** + * Generate the data columns. + * + * @param isDiscrete whether the data is discrete. + * @return the data columns. + * @throws IOException if an I/O error occurs. + */ DataColumn[] generateColumns(int[] columnsToExclude, boolean isDiscrete) throws IOException; } diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/TabularDataColumn.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/TabularDataColumn.java index 8eacaa114d..7b7f78d9ff 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/TabularDataColumn.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/TabularDataColumn.java @@ -32,12 +32,27 @@ public class TabularDataColumn implements DataColumn { private final boolean generated; private boolean discrete; + /** + * Constructor. + * + * @param name the name of the column. + * @param columnNumber the column number. + * @param generated whether the column is generated. + */ public TabularDataColumn(String name, int columnNumber, boolean generated) { this.name = name; this.columnNumber = columnNumber; this.generated = generated; } + /** + * Constructor. + * + * @param name the name of the column. + * @param columnNumber the column number. + * @param generated whether the column is generated. + * @param discrete whether the column is discrete. + */ public TabularDataColumn(String name, int columnNumber, boolean generated, boolean discrete) { this.name = name; this.columnNumber = columnNumber; @@ -45,31 +60,61 @@ public TabularDataColumn(String name, int columnNumber, boolean generated, boole this.discrete = discrete; } + /** + * Returns a string representation of the object. + * + * @return a string representation of the object. + */ @Override public String toString() { return "TabularDataColumn{" + "name=" + this.name + ", columnNumber=" + this.columnNumber + ", generated=" + this.generated + ", discrete=" + this.discrete + '}'; } + /** + * Get the name of the column. + * + * @return the name of the column. + */ @Override public String getName() { return this.name; } + /** + * Get the column number. + * + * @return the column number. + */ @Override public int getColumnNumber() { return this.columnNumber; } + /** + * Is the column generated? + * + * @return true if the column is generated, false otherwise. + */ @Override public boolean isGenerated() { return this.generated; } + /** + * Is the column discrete? + * + * @return true if the column is discrete, false otherwise. + */ @Override public boolean isDiscrete() { return this.discrete; } + /** + * Set the discrete status of the column. + * + * @param discrete true if the column is discrete, false otherwise. + */ @Override public void setDiscrete(boolean discrete) { this.discrete = discrete; diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/TabularDataFileReader.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/TabularDataFileReader.java index 4963ebadd6..7b25a54a8d 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/TabularDataFileReader.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/TabularDataFileReader.java @@ -38,12 +38,24 @@ */ public final class TabularDataFileReader extends DatasetFileReader implements TabularDataReader { -// private static final Logger LOGGER = LoggerFactory.getLogger(TabularDataFileReader.class); - + /** + * Constructor. + * + * @param dataFile The data file. + * @param delimiter The delimiter. + */ public TabularDataFileReader(Path dataFile, Delimiter delimiter) { super(dataFile, delimiter); } + /** + * Reads in the data. + * + * @param dataColumns the data columns. + * @param numberOfCategories maximum number of categories to be considered discrete + * @param hasHeader whether the data file has a header + * @throws IOException if an I/O error occurs. + */ @Override public void determineDiscreteDataColumns(DataColumn[] dataColumns, int numberOfCategories, boolean hasHeader) throws IOException { int numOfColsInDataFile = 0; @@ -318,8 +330,7 @@ public Data read(DataColumn[] dataColumns, boolean hasHeader, Metadata metadata) Data data = read(dataColumns, hasHeader); if (metadata != null) { - if (data instanceof ContinuousData) { - ContinuousData continuousData = (ContinuousData) data; + if (data instanceof ContinuousData continuousData) { double[][] contData = continuousData.getData(); metadata.getInterventionalColumns().forEach(column -> { ColumnMetadata valCol = column.getValueColumn(); @@ -337,8 +348,7 @@ public Data read(DataColumn[] dataColumns, boolean hasHeader, Metadata metadata) } } }); - } else if (data instanceof DiscreteData) { - DiscreteData verticalDiscreteData = (DiscreteData) data; + } else if (data instanceof DiscreteData verticalDiscreteData) { int[][] discreteData = verticalDiscreteData.getData(); metadata.getInterventionalColumns().forEach(column -> { ColumnMetadata valCol = column.getValueColumn(); @@ -356,8 +366,7 @@ public Data read(DataColumn[] dataColumns, boolean hasHeader, Metadata metadata) } } }); - } else if (data instanceof MixedTabularData) { - MixedTabularData mixedTabularData = (MixedTabularData) data; + } else if (data instanceof MixedTabularData mixedTabularData) { double[][] continuousData = mixedTabularData.getContinuousData(); int[][] discreteData = mixedTabularData.getDiscreteData(); metadata.getInterventionalColumns().forEach(column -> { @@ -570,7 +579,6 @@ private void readInMixedData(DiscreteDataColumn[] dataColumns, boolean hasHeader // ensure we have enough data if (columnIndex < numOfColsInDataFile) { String errMsg = String.format("Insufficient data on line %d. Extracted %d value(s) but expected %d.", lineNum, columnIndex, numOfColsInDataFile); -// TabularDataFileReader.LOGGER.error(errMsg); throw new DataReaderException(errMsg); } @@ -707,7 +715,6 @@ private void readInMixedData(DiscreteDataColumn[] dataColumns, boolean hasHeader // ensure we have enough data if (columnIndex < numOfColsInDataFile) { String errMsg = String.format("Insufficient data on line %d. Extracted %d value(s) but expected %d.", lineNum, columnIndex, numOfColsInDataFile); -// TabularDataFileReader.LOGGER.error(errMsg); throw new DataReaderException(errMsg); } } @@ -1298,7 +1305,7 @@ private void readInDiscreteCategorizes(DiscreteDataColumn[] dataColumns, boolean if (dataColumn.getColumnNumber() == colNum) { if (dataColumn.isDiscrete()) { String value = dataBuilder.toString().trim(); - if (value.length() > 0 && !value.equals(this.missingDataMarker)) { + if (!value.isEmpty() && !value.equals(this.missingDataMarker)) { discreteDataColumn.setValue(value); } } @@ -1309,7 +1316,6 @@ private void readInDiscreteCategorizes(DiscreteDataColumn[] dataColumns, boolean // ensure we have enough data if (columnIndex < numOfColsInDataFile) { String errMsg = String.format("Insufficient data on line %d. Extracted %d value(s) but expected %d.", lineNum, columnIndex, numOfColsInDataFile); -// TabularDataFileReader.LOGGER.error(errMsg); throw new DataReaderException(errMsg); } } @@ -1371,7 +1377,7 @@ private void readInDiscreteCategorizes(DiscreteDataColumn[] dataColumns, boolean if (dataColumn.getColumnNumber() == colNum) { if (dataColumn.isDiscrete()) { String value = dataBuilder.toString().trim(); - if (value.length() > 0 && !value.equals(this.missingDataMarker)) { + if (!value.isEmpty() && !value.equals(this.missingDataMarker)) { discreteDataColumn.setValue(value); } } @@ -1403,7 +1409,7 @@ private void readInDiscreteCategorizes(DiscreteDataColumn[] dataColumns, boolean if (dataColumn.getColumnNumber() == colNum) { if (dataColumn.isDiscrete()) { String value = dataBuilder.toString().trim(); - if (value.length() > 0 && !value.equals(this.missingDataMarker)) { + if (!value.isEmpty() && !value.equals(this.missingDataMarker)) { discreteDataColumn.setValue(value); } } diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/TabularDataReader.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/TabularDataReader.java index cc3c5dee66..518c93f544 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/TabularDataReader.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/TabularDataReader.java @@ -37,15 +37,32 @@ public interface TabularDataReader extends DatasetReader { * number of categories of a column is equal to or less than the given number of categories, it will be considered * to have discrete data. Else, it is considered to have continuous data. * - * @param dataColumns + * @param dataColumns the data columns * @param numberOfCategories maximum number of categories to be considered discrete - * @param hasHeader - * @throws IOException + * @param hasHeader whether the data has a header + * @throws IOException if an I/O error occurs */ void determineDiscreteDataColumns(DataColumn[] dataColumns, int numberOfCategories, boolean hasHeader) throws IOException; + /** + * Read the data. + * + * @param dataColumns the data columns + * @param hasHeader whether the data has a header + * @return the data + * @throws IOException if an I/O error occurs + */ Data read(DataColumn[] dataColumns, boolean hasHeader) throws IOException; + /** + * Read the data. + * + * @param dataColumns the data columns + * @param hasHeader whether the data has a header + * @param metadata the metadata + * @return the data + * @throws IOException if an I/O error occurs + */ Data read(DataColumn[] dataColumns, boolean hasHeader, Metadata metadata) throws IOException; } diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/TabularDatasetReader.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/TabularDatasetReader.java index 8b02026994..c437738929 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/TabularDatasetReader.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/TabularDatasetReader.java @@ -31,12 +31,37 @@ */ public interface TabularDatasetReader extends DatasetReader { + /** + * Read in the data. + * + * @return The data. + * @throws IOException If an I/O error occurs. + */ Data readInData() throws IOException; + /** + * Read in the data. + * + * @param namesOfColumnsToExclude the names of columns to exclude. + * @return The data. + * @throws IOException If an I/O error occurs. + */ Data readInData(Set namesOfColumnsToExclude) throws IOException; + /** + * Read in the data. + * + * @param columnsToExclude the columns to exclude. + * @return The data. + * @throws IOException If an I/O error occurs. + */ Data readInData(int[] columnsToExclude) throws IOException; + /** + * Set whether the data has a header. + * + * @param hasHeader whether the data has a header. + */ void setHasHeader(boolean hasHeader); } diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/VerticalDiscreteTabularData.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/VerticalDiscreteTabularData.java index b0634088f4..4d23024cbb 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/VerticalDiscreteTabularData.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/VerticalDiscreteTabularData.java @@ -31,16 +31,32 @@ public class VerticalDiscreteTabularData implements DiscreteData { private final DiscreteDataColumn[] dataColumns; private final int[][] data; + /** + * Constructor. + * + * @param dataColumns the data columns. + * @param data the data. + */ public VerticalDiscreteTabularData(DiscreteDataColumn[] dataColumns, int[][] data) { this.dataColumns = dataColumns; this.data = data; } + /** + * Gets the data columns. + * + * @return the data columns. + */ @Override public DiscreteDataColumn[] getDataColumns() { return this.dataColumns; } + /** + * Gets the data. + * + * @return the data. + */ @Override public int[][] getData() { return this.data; diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/VerticalDiscreteTabularDatasetFileReader.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/VerticalDiscreteTabularDatasetFileReader.java index 4271f0151e..77b31d045e 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/VerticalDiscreteTabularDatasetFileReader.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/VerticalDiscreteTabularDatasetFileReader.java @@ -38,17 +38,36 @@ public class VerticalDiscreteTabularDatasetFileReader extends DatasetFileReader private boolean hasHeader; private char quoteChar; + /** + * Constructor. + * + * @param dataFile The data file. + * @param delimiter The delimiter. + */ public VerticalDiscreteTabularDatasetFileReader(Path dataFile, Delimiter delimiter) { super(dataFile, delimiter); this.hasHeader = this.hasHeader = true; this.quoteChar = '"'; } + /** + * Reads in the data. + * + * @return The data. + * @throws IOException If an I/O error occurs. + */ @Override public Data readInData() throws IOException { return readInData(Collections.EMPTY_SET); } + /** + * Reads in the data. + * + * @param namesOfColumnsToExclude the names of columns to exclude. + * @return The data. + * @throws IOException If an I/O error occurs. + */ @Override public Data readInData(Set namesOfColumnsToExclude) throws IOException { TabularColumnReader columnReader = new TabularColumnFileReader(this.dataFile, this.delimiter); @@ -68,6 +87,13 @@ public Data readInData(Set namesOfColumnsToExclude) throws IOException { return dataReader.read(dataColumns, this.hasHeader); } + /** + * Reads in the data. + * + * @param columnsToExclude the columns to exclude. + * @return The data. + * @throws IOException If an I/O error occurs. + */ @Override public Data readInData(int[] columnsToExclude) throws IOException { TabularColumnReader columnReader = new TabularColumnFileReader(this.dataFile, this.delimiter); @@ -87,11 +113,21 @@ public Data readInData(int[] columnsToExclude) throws IOException { return dataReader.read(dataColumns, this.hasHeader); } + /** + * Set whether the data has a header. + * + * @param hasHeader whether the data has a header. + */ @Override public void setHasHeader(boolean hasHeader) { this.hasHeader = hasHeader; } + /** + * Set the quote character. + * + * @param quoteCharacter the quote character + */ @Override public void setQuoteCharacter(char quoteCharacter) { this.quoteChar = quoteCharacter; diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/util/Columns.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/util/Columns.java index 162a95bdfa..1a42d810a8 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/util/Columns.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/util/Columns.java @@ -30,6 +30,12 @@ public final class Columns { private Columns() { } + /** + * Sort the columns in ascending order. + * + * @param columns the columns to sort. + * @return the sorted columns. + */ public static int[] sortNew(int[] columns) { int size = (columns == null) ? 0 : columns.length; if (size > 0) { @@ -46,9 +52,9 @@ public static int[] sortNew(int[] columns) { /** * Keep all the columns that are between 1 and numOfCols, inclusive. * - * @param numberOfColumns - * @param columns - * @return + * @param numberOfColumns the number of columns. + * @param columns the columns to keep. + * @return the valid columns. */ public static int[] extractValidColumnNumbers(int numberOfColumns, int[] columns) { return (columns == null || columns.length == 0) diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/validation/Validation.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/validation/Validation.java index 8674e7ae13..3c61e87b7c 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/validation/Validation.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/validation/Validation.java @@ -25,6 +25,9 @@ */ public interface Validation { + /** + * Sets the maximum number of messages. + */ void setMaximumNumberOfMessages(int maxNumOfMsg); } diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/validation/ValidationResult.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/validation/ValidationResult.java index 9f9a62c27e..beeb9fc50b 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/validation/ValidationResult.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/validation/ValidationResult.java @@ -36,42 +36,91 @@ public class ValidationResult { private String message; + /** + * Default constructor. + * + * @param code the validation code. + * @param messageType the message type. + */ public ValidationResult(ValidationCode code, MessageType messageType) { this.code = code; this.messageType = messageType; this.attributes = new EnumMap<>(ValidationAttribute.class); } + /** + * Constructor with message. + * + * @param code the validation code. + * @param messageType the message type. + * @param message the message. + */ public ValidationResult(ValidationCode code, MessageType messageType, String message) { this(code, messageType); this.message = message; } + /** + * Return the string representation of this object. + * + * @return the string representation of this object. + */ @Override public String toString() { return "ValidationResult{" + "code=" + this.code + ", messageType=" + this.messageType + ", attributes=" + this.attributes + ", message=" + this.message + '}'; } + /** + * Return the hash code of this object. + * + * @return the hash code of this object. + */ public ValidationCode getCode() { return this.code; } + /** + * Return the message type. + * + * @return the message type. + */ public MessageType getMessageType() { return this.messageType; } + /** + * Return the attributes. + * + * @return the attributes. + */ public Map getAttributes() { return this.attributes; } + /** + * Sets the attribute value. + * + * @param attribute the attribute. + * @param value the value. + */ public void setAttribute(ValidationAttribute attribute, Object value) { this.attributes.put(attribute, value); } + /** + * Return the message. + * + * @return the message. + */ public String getMessage() { return this.message; } + /** + * Sets the message. + * + * @param message the message. + */ public void setMessage(String message) { this.message = message; } diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/validation/covariance/CovarianceValidation.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/validation/covariance/CovarianceValidation.java index b462818697..c9980db01b 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/validation/covariance/CovarianceValidation.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/validation/covariance/CovarianceValidation.java @@ -31,6 +31,11 @@ */ public interface CovarianceValidation extends Validation, DataReader { + /** + * Validate the covariance. + * + * @return the validation results. + */ List validate(); } diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/validation/covariance/LowerCovarianceDataFileValidation.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/validation/covariance/LowerCovarianceDataFileValidation.java index f6c3fac7c6..108c7388b0 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/validation/covariance/LowerCovarianceDataFileValidation.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/validation/covariance/LowerCovarianceDataFileValidation.java @@ -37,10 +37,21 @@ */ public class LowerCovarianceDataFileValidation extends AbstractDataFileValidation implements CovarianceValidation { + /** + * Constructor. + * + * @param dataFile the data file. + * @param delimiter the delimiter. + */ public LowerCovarianceDataFileValidation(Path dataFile, Delimiter delimiter) { super(dataFile, delimiter); } + /** + * Validate the covariance. + * + * @return the validation results. + */ @Override public List validate() { List validationResults = new LinkedList<>(); diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/validation/tabular/TabularColumnFileValidation.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/validation/tabular/TabularColumnFileValidation.java index bf5505d3df..d902a9b76e 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/validation/tabular/TabularColumnFileValidation.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/validation/tabular/TabularColumnFileValidation.java @@ -43,16 +43,33 @@ public class TabularColumnFileValidation extends AbstractTabularColumnFileReader private int maxNumOfMsg; + /** + * Constructor. + * + * @param dataFile The data file. + * @param delimiter The delimiter. + */ public TabularColumnFileValidation(Path dataFile, Delimiter delimiter) { super(dataFile, delimiter); this.maxNumOfMsg = Integer.MAX_VALUE; } + /** + * Constructor. + * + * @return The maximum number of messages. + */ @Override public List validate() { return validate(Collections.EMPTY_SET); } + /** + * Validate the data file. + * + * @param excludedColumns the columns to exclude. + * @return the validation results. + */ @Override public List validate(int[] excludedColumns) { List results = new LinkedList<>(); @@ -75,6 +92,12 @@ public List validate(int[] excludedColumns) { return results; } + /** + * Validate the data file. + * + * @param excludedColumns the columns to exclude. + * @return the validation results. + */ @Override public List validate(Set excludedColumns) { List results = new LinkedList<>(); @@ -86,14 +109,14 @@ public List validate(Set excludedColumns) { Set modifiedExcludedCols = new HashSet<>(); if (Character.isDefined(this.quoteCharacter)) { excludedColumns.stream() - .map(e -> e.trim()) + .map(String::trim) .filter(e -> !e.isEmpty()) .forEach(e -> modifiedExcludedCols.add(stripCharacter(e, this.quoteCharacter))); } else { excludedColumns.stream() - .map(e -> e.trim()) + .map(String::trim) .filter(e -> !e.isEmpty()) - .forEach(e -> modifiedExcludedCols.add(e)); + .forEach(modifiedExcludedCols::add); } int[] excludedCols = toColumnNumbers(modifiedExcludedCols); @@ -267,6 +290,11 @@ private void validateColumns(int[] excludedColumns, List resul results.add(result); } + /** + * Set the maximum number of messages. + * + * @param maxNumOfMsg + */ @Override public void setMaximumNumberOfMessages(int maxNumOfMsg) { this.maxNumOfMsg = maxNumOfMsg; diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/validation/tabular/TabularColumnValidation.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/validation/tabular/TabularColumnValidation.java index ac2fd9564c..d7321e3ea1 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/validation/tabular/TabularColumnValidation.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/validation/tabular/TabularColumnValidation.java @@ -32,10 +32,27 @@ */ public interface TabularColumnValidation extends Validation, DataReader { + /** + * Validate the columns. + * + * @return the validation results. + */ List validate(); + /** + * Validate the columns. + * + * @param excludedColumns the columns to exclude. + * @return the validation results. + */ List validate(int[] excludedColumns); + /** + * Validate the columns. + * + * @param excludedColumns the columns to exclude. + * @return the validation results. + */ List validate(Set excludedColumns); } diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/validation/tabular/TabularDataFileValidation.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/validation/tabular/TabularDataFileValidation.java index bf1b223abb..1b7f5b02a7 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/validation/tabular/TabularDataFileValidation.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/validation/tabular/TabularDataFileValidation.java @@ -44,11 +44,24 @@ public class TabularDataFileValidation extends DatasetFileReader implements Tabu private int maxNumOfMsg; + /** + * Constructor. + * + * @param dataFile the data file. + * @param delimiter the delimiter. + */ public TabularDataFileValidation(Path dataFile, Delimiter delimiter) { super(dataFile, delimiter); this.maxNumOfMsg = Integer.MAX_VALUE; } + /** + * Constructor. + * + * @param dataColumns the data columns. + * @param hasHeader the data has header. + * @return the validation results. + */ @Override public List validate(DataColumn[] dataColumns, boolean hasHeader) { List results = new LinkedList<>(); diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/validation/tabular/TabularDataValidation.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/validation/tabular/TabularDataValidation.java index e8f01ed450..9cb7b6bf2e 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/validation/tabular/TabularDataValidation.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/validation/tabular/TabularDataValidation.java @@ -32,6 +32,13 @@ */ public interface TabularDataValidation extends Validation, DatasetReader { + /** + * Validate the data columns. + * + * @param dataColumns the data columns. + * @param hasHeader the flag indicating if the data has a header. + * @return the validation results. + */ List validate(DataColumn[] dataColumns, boolean hasHeader); } From 7e64086d05767351107faaa1ceaaaa1a3066ae10 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Thu, 1 Feb 2024 02:45:12 -0500 Subject: [PATCH 151/163] Cleanup. --- .../pitt/dbmi/data/reader/DataFileReader.java | 30 + .../dbmi/data/reader/DatasetFileReader.java | 3 + .../pitt/dbmi/data/reader/DatasetReader.java | 6 + .../edu/pitt/dbmi/data/reader/Delimiter.java | 27 + .../reader/metadata/MetadataFileReader.java | 3 + .../data/reader/metadata/MetadataWriter.java | 7 + .../reader/preview/AbstractDataPreviewer.java | 24 + .../reader/preview/BasicDataPreviewer.java | 9 + .../AbstractTabularColumnFileReader.java | 18 +- .../tabular/DiscreteTabularDataColumn.java | 5 + .../reader/tabular/TabularColumnReader.java | 3 +- .../dbmi/data/reader/util/TextFileUtils.java | 14 +- .../AbstractDataFileValidation.java | 14 + .../data/reader/validation/MessageType.java | 23 + .../data/reader/validation/Validation.java | 2 + .../validation/ValidationAttribute.java | 63 ++ .../reader/validation/ValidationCode.java | 11 + .../tabular/TabularColumnFileValidation.java | 2 +- .../statistic/BicDiffPerRecord.java | 19 + .../edu/cmu/tetrad/bayes/BayesProperties.java | 38 + .../edu/cmu/tetrad/bayes/BayesUpdater.java | 3 + .../edu/cmu/tetrad/bayes/BayesXmlParser.java | 6 + .../cmu/tetrad/bayes/BayesXmlRenderer.java | 6 + .../java/edu/cmu/tetrad/data/BoxDataSet.java | 15 + .../java/edu/cmu/tetrad/data/DataSet.java | 41 +- .../inference/BCCausalInference.java | 15 +- .../constraint/inference/BCInference.java | 10 +- .../algcomparison/TimeoutComparisonTest.java | 140 ---- .../bayes/JunctionTreeAlgorithmTest.java | 20 +- .../edu/cmu/tetrad/test/TestCyclicity.java | 96 --- .../test/TestGeneralResamplingTest.java | 109 +-- .../cmu/tetrad/test/TestGeneralizedSem.java | 717 +----------------- .../cmu/tetrad/test/TestIndTestWaldLr.java | 118 --- .../edu/cmu/tetrad/test/TestMimbuild.java | 202 ----- .../java/edu/cmu/tetrad/test/TestPurify.java | 317 -------- 35 files changed, 415 insertions(+), 1721 deletions(-) delete mode 100644 tetrad-lib/src/test/java/edu/cmu/tetrad/algcomparison/TimeoutComparisonTest.java delete mode 100755 tetrad-lib/src/test/java/edu/cmu/tetrad/test/TestCyclicity.java delete mode 100644 tetrad-lib/src/test/java/edu/cmu/tetrad/test/TestIndTestWaldLr.java delete mode 100644 tetrad-lib/src/test/java/edu/cmu/tetrad/test/TestMimbuild.java delete mode 100644 tetrad-lib/src/test/java/edu/cmu/tetrad/test/TestPurify.java diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/DataFileReader.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/DataFileReader.java index 1520378dac..1c8dc2a12e 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/DataFileReader.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/DataFileReader.java @@ -31,14 +31,44 @@ */ public abstract class DataFileReader implements DataReader { + /** + * The buffer size for reading data file. + */ protected static final int BUFFER_SIZE = 1024 * 1024; + /** + * The newline character. + */ protected static final byte LINE_FEED = '\n'; + + /** + * The carriage return character. + */ protected static final byte CARRIAGE_RETURN = '\r'; + + /** + * The space character. + */ protected static final byte SPACE_CHAR = Delimiter.SPACE.getByteValue(); + + /** + * The data file. + */ protected final Path dataFile; + + /** + * The delimiter. + */ protected final Delimiter delimiter; + + /** + * The quote character. + */ protected byte quoteCharacter; + + /** + * The comment marker. + */ protected String commentMarker; /** diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/DatasetFileReader.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/DatasetFileReader.java index 7dbf33e487..44d64b2372 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/DatasetFileReader.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/DatasetFileReader.java @@ -27,6 +27,9 @@ */ public abstract class DatasetFileReader extends DataFileReader implements DatasetReader { + /** + * The missing data marker. + */ protected String missingDataMarker; /** diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/DatasetReader.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/DatasetReader.java index 638a339155..a74daf92dc 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/DatasetReader.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/DatasetReader.java @@ -25,8 +25,14 @@ */ public interface DatasetReader extends DataReader { + /** + * The missing data marker for continuous data. + */ double CONTINUOUS_MISSING_VALUE = Double.NaN; + /** + * The missing data marker for discrete data. + */ int DISCRETE_MISSING_VALUE = -99; /** diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/Delimiter.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/Delimiter.java index bdde12d9d4..fae0c50f5b 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/Delimiter.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/Delimiter.java @@ -25,12 +25,39 @@ */ public enum Delimiter { + /** + * The tab delimiter. + */ TAB("tab", '\t'), + + /** + * The space delimiter. + */ SPACE("space", ' '), + + /** + * The whitespace delimiter. + */ WHITESPACE("whitespace", ' '), + + /** + * The comma delimiter. + */ COMMA("comma", ','), + + /** + * The colon delimiter. + */ COLON("colon", ':'), + + /** + * The semicolon delimiter. + */ SEMICOLON("semicolon", ';'), + + /** + * The pipe delimiter. + */ PIPE("pipe", '|'); private final String name; diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/metadata/MetadataFileReader.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/metadata/MetadataFileReader.java index 1d6f241000..6e275dd59f 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/metadata/MetadataFileReader.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/metadata/MetadataFileReader.java @@ -32,6 +32,9 @@ */ public class MetadataFileReader implements MetadataReader { + /** + * The metadata file. + */ protected final Path metadataFile; /** diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/metadata/MetadataWriter.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/metadata/MetadataWriter.java index e42976576f..431d3244dc 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/metadata/MetadataWriter.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/metadata/MetadataWriter.java @@ -39,6 +39,13 @@ public interface MetadataWriter { */ String writeAsString(Metadata metadata) throws JsonProcessingException; + /** + * Writes the metadata to the output file. + * + * @param metadata The metadata. + * @param outputFile The output file. + * @throws IOException if an error occurs while writing the metadata. + */ void write(Metadata metadata, Path outputFile) throws IOException; } diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/preview/AbstractDataPreviewer.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/preview/AbstractDataPreviewer.java index 34f342f98e..39ca3f13a6 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/preview/AbstractDataPreviewer.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/preview/AbstractDataPreviewer.java @@ -27,11 +27,24 @@ */ public abstract class AbstractDataPreviewer { + /** + * The line feed character. + */ protected static final byte LINE_FEED = '\n'; + + /** + * The carriage return character. + */ protected static final byte CARRIAGE_RETURN = '\r'; + /** + * The ellipsis character. + */ protected static final String ELLIPSIS = "..."; + /** + * The data file. + */ protected final Path dataFile; /** @@ -43,12 +56,23 @@ public AbstractDataPreviewer(Path dataFile) { this.dataFile = dataFile; } + /** + * Check the number of characters parameter. + * + * @param numOfCharacters The number of characters. + */ protected void checkCharacterNumberParameter(int numOfCharacters) { if (numOfCharacters < 0) { throw new IllegalArgumentException("Parameter numOfCharacters must be positive integer."); } } + /** + * Check the line number parameters. + * + * @param fromLine The starting line number. + * @param toLine The ending line number. + */ protected void checkLineNumberParameter(int fromLine, int toLine) { if (fromLine < 0) { throw new IllegalArgumentException("Parameter fromLine must be positive integer."); diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/preview/BasicDataPreviewer.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/preview/BasicDataPreviewer.java index bf399c616a..b86c196e0a 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/preview/BasicDataPreviewer.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/preview/BasicDataPreviewer.java @@ -75,6 +75,15 @@ public List getPreviews(int fromLine, int toLine, int numOfCharacters) throws IO return linePreviews; } + /** + * Get the previews of the data file. + * + * @param fromLine the starting line number + * @param toLine the ending line number + * @param numOfCharacters the number of characters to preview + * @param list the list to store the previews + * @throws IOException if an I/O error occurs + */ protected void getPreviews(int fromLine, int toLine, int numOfCharacters, List list) throws IOException { try (FileChannel fc = new RandomAccessFile(this.dataFile.toFile(), "r").getChannel()) { long fileSize = fc.size(); diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/AbstractTabularColumnFileReader.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/AbstractTabularColumnFileReader.java index 0ce0aa3c78..0a112e1392 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/AbstractTabularColumnFileReader.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/AbstractTabularColumnFileReader.java @@ -40,13 +40,20 @@ public abstract class AbstractTabularColumnFileReader extends DataFileReader { /** * Constructor. * - * @param dataFile The data file. - * @param delimiter The delimiter. + * @param dataFile The data file. + * @param delimiter The delimiter. */ public AbstractTabularColumnFileReader(Path dataFile, Delimiter delimiter) { super(dataFile, delimiter); } + /** + * Get the column numbers for the specified column names. + * + * @param columnNames the column names + * @return the column numbers + * @throws IOException if an I/O error occurs + */ protected int[] toColumnNumbers(Set columnNames) throws IOException { List colNums = new LinkedList<>(); @@ -163,6 +170,13 @@ protected int[] toColumnNumbers(Set columnNames) throws IOException { return colNums.stream().mapToInt(e -> e).toArray(); } + /** + * Strip the specified character from the word. + * + * @param word the word + * @param character the character to strip + * @return the word with the specified character stripped + */ protected String stripCharacter(String word, byte character) { StringBuilder dataBuilder = new StringBuilder(); for (byte currChar : word.getBytes()) { diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/DiscreteTabularDataColumn.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/DiscreteTabularDataColumn.java index eb42d270dc..d1cd36a2e7 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/DiscreteTabularDataColumn.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/DiscreteTabularDataColumn.java @@ -120,6 +120,11 @@ public List getCategories() { : this.categories; } + /** + * Sets the categories. + * + * @param categories the categories. + */ public void setCategories(List categories) { this.categories = categories; } diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/TabularColumnReader.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/TabularColumnReader.java index 298bb237b8..5d7a58b0d6 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/TabularColumnReader.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/tabular/TabularColumnReader.java @@ -63,7 +63,8 @@ public interface TabularColumnReader extends DataReader { /** * Generate the data columns. * - * @param isDiscrete whether the data is discrete. + * @param isDiscrete whether the data is discrete. + * @param columnsToExclude the columns to exclude. * @return the data columns. * @throws IOException if an I/O error occurs. */ diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/util/TextFileUtils.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/util/TextFileUtils.java index e133241ff3..6aaed4afcd 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/util/TextFileUtils.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/util/TextFileUtils.java @@ -32,9 +32,19 @@ */ public class TextFileUtils { + /** + * The line feed delimiter for text data files. + */ protected static final byte LINE_FEED = '\n'; + + /** + * The carriage return delimiter for text data files. + */ protected static final byte CARRIAGE_RETURN = '\r'; + /** + * The space character for text data files. + */ protected static final byte SPACE_CHAR = ' '; private TextFileUtils() { @@ -53,8 +63,8 @@ private TextFileUtils() { * @param comment a comment symbol to ignore lines in files * @param quoteCharacter used for grouping characters * @param delims the set of delimiters to test for - * @return - * @throws IOException + * @return the inferred delimiter + * @throws IOException if an I/O error occurs */ public static char inferDelimiter(File file, int n, int skip, String comment, char quoteCharacter, char[] delims) throws IOException { if (file == null) { diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/validation/AbstractDataFileValidation.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/validation/AbstractDataFileValidation.java index a8758381b9..4741b2c485 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/validation/AbstractDataFileValidation.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/validation/AbstractDataFileValidation.java @@ -30,13 +30,27 @@ */ public abstract class AbstractDataFileValidation extends DataFileReader implements Validation { + /** + * The maximum number of messages to validate. + */ protected int maxNumOfMsg; + /** + * Constructor. + * + * @param dataFile the data file + * @param delimiter the delimiter + */ public AbstractDataFileValidation(Path dataFile, Delimiter delimiter) { super(dataFile, delimiter); this.maxNumOfMsg = Integer.MAX_VALUE; } + /** + * Set the maximum number of messages to validate. + * + * @param maxNumOfMsg the maximum number of messages + */ @Override public void setMaximumNumberOfMessages(int maxNumOfMsg) { this.maxNumOfMsg = maxNumOfMsg; diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/validation/MessageType.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/validation/MessageType.java index 702bf2e6f5..dae7c45b38 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/validation/MessageType.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/validation/MessageType.java @@ -25,11 +25,34 @@ */ public enum MessageType { + /** + * Error in file input/output operation. + */ FILE_IO_ERROR, + + /** + * Missing value in file. + */ FILE_MISSING_VALUE, + + /** + * Invalid number in file. + */ FILE_INVALID_NUMBER, + + /** + * Excess or insufficient data in file. + */ FILE_EXCESS_DATA, + + /** + * Excess or insufficient data in file. + */ FILE_INSUFFICIENT_DATA, + + /** + * File summary. + */ FILE_SUMMARY } diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/validation/Validation.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/validation/Validation.java index 3c61e87b7c..6ec74fa02c 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/validation/Validation.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/validation/Validation.java @@ -27,6 +27,8 @@ public interface Validation { /** * Sets the maximum number of messages. + * + * @param maxNumOfMsg the maximum number of messages. */ void setMaximumNumberOfMessages(int maxNumOfMsg); diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/validation/ValidationAttribute.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/validation/ValidationAttribute.java index 1fdf8b7df8..537d3178ae 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/validation/ValidationAttribute.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/validation/ValidationAttribute.java @@ -25,21 +25,84 @@ */ public enum ValidationAttribute { + /** + * The number of continuous variables. + */ CONTINUOUS_VAR_COUNT, + + /** + * The number of discrete variables. + */ DISCRETE_VAR_COUNT, + + /** + * The line number. + */ LINE_NUMBER, + + /** + * The column number. + */ COLUMN_NUMBER, + + /** + * The row number. + */ ROW_NUMBER, + + /** + * The expected count. + */ EXPECTED_COUNT, + + /** + * The actual count. + */ ACTUAL_COUNT, + + /** + * The line count. + */ LINE_COUNT, + + /** + * The column count. + */ COLUMN_COUNT, + + /** + * The row count. + */ ROW_COUNT, + + /** + * The assumed missing count. + */ ASSUMED_MISSING_COUNT, + + /** + * The labeled missing count. + */ LABELED_MISSING_COUNT, + + /** + * The number of rows with missing values. + */ ROW_WITH_MISSING_VALUE_COUNT, + + /** + * The number of columns with missing values. + */ COLUMN_WITH_MISSING_VALUE_COUNT, + + /** + * The file name. + */ FILE_NAME, + + /** + * The value. + */ VALUE } diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/validation/ValidationCode.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/validation/ValidationCode.java index 602719da6e..ca96714377 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/validation/ValidationCode.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/validation/ValidationCode.java @@ -25,8 +25,19 @@ */ public enum ValidationCode { + /** + * Information message. + */ INFO, + + /** + * Warning message. + */ WARNING, + + /** + * Error message. + */ ERROR } diff --git a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/validation/tabular/TabularColumnFileValidation.java b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/validation/tabular/TabularColumnFileValidation.java index d902a9b76e..f973575eda 100644 --- a/data-reader/src/main/java/edu/pitt/dbmi/data/reader/validation/tabular/TabularColumnFileValidation.java +++ b/data-reader/src/main/java/edu/pitt/dbmi/data/reader/validation/tabular/TabularColumnFileValidation.java @@ -293,7 +293,7 @@ private void validateColumns(int[] excludedColumns, List resul /** * Set the maximum number of messages. * - * @param maxNumOfMsg + * @param maxNumOfMsg the maximum number of messages. */ @Override public void setMaximumNumberOfMessages(int maxNumOfMsg) { diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/BicDiffPerRecord.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/BicDiffPerRecord.java index 3a34af506c..ca0f412a09 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/BicDiffPerRecord.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/statistic/BicDiffPerRecord.java @@ -29,6 +29,14 @@ public String getDescription() { "divided by the sample size"; } + /** + * Returns the difference between the true and estimated BIC scores, divided by the sample size. + * + * @param trueGraph The true graph (DAG, CPDAG, PAG_of_the_true_DAG). + * @param estGraph The estimated graph (same type). + * @param dataModel The data model. + * @return The difference between the true and estimated BIC scores, divided by the sample size. + */ @Override public double getValue(Graph trueGraph, Graph estGraph, DataModel dataModel) { double _true = SemBicScorer.scoreDag(GraphTransforms.dagFromCpdag(trueGraph, null), dataModel, precomputeCovariances); @@ -38,11 +46,22 @@ public double getValue(Graph trueGraph, Graph estGraph, DataModel dataModel) { return (_true - est) / ((DataSet) dataModel).getNumRows(); } + /** + * Returns the normalized value of the statistic. + * + * @param value The value of the statistic. + * @return The normalized value of the statistic. + */ @Override public double getNormValue(double value) { return tanh(value / 1e6); } + /** + * Returns true if the covariances are precomputed. + * + * @param precomputeCovariances True if the covariances are precomputed. + */ public void setPrecomputeCovariances(boolean precomputeCovariances) { this.precomputeCovariances = precomputeCovariances; } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/bayes/BayesProperties.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/bayes/BayesProperties.java index 1502801d06..539b5d1033 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/bayes/BayesProperties.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/bayes/BayesProperties.java @@ -316,10 +316,16 @@ private double getDofNode(int node, int[] parents) { return r * c; } + /** + * Returns the number of categories for the given variable. + */ public int getSampleSize() { return this.sampleSize; } + /** + * Returns the variable with the given name (assumed the target). + */ public Node getVariable(String targetName) { for (Node node : this.variables) { if (node.getName().equals(targetName)) { @@ -338,19 +344,35 @@ private DiscreteVariable getVariable(int i) { } } + /** + * Returns the likelihood ratio test statistic for the given graph and its degrees of freedom. + */ private static class Ret { private final double lik; private final int dof; + /** + * Constructs a new Ret object. + * @param lik The likelihood. + * @param dof The degrees of freedom. + */ public Ret(double lik, int dof) { this.lik = lik; this.dof = dof; } + /** + * Returns the likelihood. + * @return The likelihood. + */ public double getLik() { return this.lik; } + /** + * Returns the degrees of freedom. + * @return The degrees of freedom. + */ public int getDof() { return this.dof; } @@ -360,9 +382,25 @@ public int getDof() { * Returns the number of categories for the given variable. */ public static class LikelihoodRet { + + /** + * The p-value. + */ public double p; + + /** + * The BIC. + */ public double bic; + + /** + * The chi-squared statistic. + */ public double chiSq; + + /** + * The degrees of freedom. + */ public double dof; } } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/bayes/BayesUpdater.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/bayes/BayesUpdater.java index 10cbac9479..3796d0a127 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/bayes/BayesUpdater.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/bayes/BayesUpdater.java @@ -36,6 +36,9 @@ * @see Manipulation */ public interface BayesUpdater extends TetradSerializable { + /** + * Serial version ID for serialization. + */ long serialVersionUID = 23L; /** diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/bayes/BayesXmlParser.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/bayes/BayesXmlParser.java index 39fd3c60c1..8ec2e7fc44 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/bayes/BayesXmlParser.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/bayes/BayesXmlParser.java @@ -106,6 +106,12 @@ private static BayesIm makeBayesIm(BayesPm bayesPm, Element element2) { return bayesIm; } + /** + * Returns the BayesIm object represented by the given element. + * + * @param element the element + * @return the BayesIm object + */ public BayesIm getBayesIm(Element element) { if (!"bayesNet".equals(element.getQualifiedName())) { throw new IllegalArgumentException("Expecting 'bayesNet' element."); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/bayes/BayesXmlRenderer.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/bayes/BayesXmlRenderer.java index 2644e376eb..8a2b7b09fa 100755 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/bayes/BayesXmlRenderer.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/bayes/BayesXmlRenderer.java @@ -36,6 +36,12 @@ */ public final class BayesXmlRenderer { + /** + * Private constructor to prevent instantiation. + * + * @param bayesIm the Bayes net + * @return the XML element + */ public static Element getElement(BayesIm bayesIm) { if (bayesIm == null) { throw new NullPointerException(); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/data/BoxDataSet.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/data/BoxDataSet.java index 450149b03c..dd2c7268ad 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/data/BoxDataSet.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/data/BoxDataSet.java @@ -124,6 +124,12 @@ public final class BoxDataSet implements DataSet { */ private char outputDelimiter = '\t'; + /** + * Constructs a new data set with the given number of rows and columns, with all values set to missing. + * + * @param dataBox The data box. + * @param variables The variables. + */ public BoxDataSet(DataBox dataBox, List variables) { this.dataBox = dataBox; this.variables = new ArrayList<>(variables); @@ -135,6 +141,8 @@ public BoxDataSet(DataBox dataBox, List variables) { /** * Makes of copy of the given data set. + * + * @param dataSet The data set to copy. */ public BoxDataSet(BoxDataSet dataSet) { this.name = dataSet.name; @@ -147,6 +155,8 @@ public BoxDataSet(BoxDataSet dataSet) { /** * Generates a simple exemplar of this class to test serialization. + * + * @return A simple exemplar of this class. */ public static BoxDataSet serializableInstance() { List vars = new ArrayList<>(); @@ -1333,6 +1343,11 @@ public NumberFormat getNumberFormat() { return this.nf; } + /** + * Sets the number format to be used when printing out the data set. The default is the one at + * + * @param nf The number format to be used when printing out the data set. The default is the one at + */ public void setNumberFormat(NumberFormat nf) { if (nf == null) { throw new NullPointerException(); diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/data/DataSet.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/data/DataSet.java index b147c07053..ac5d924dd1 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/data/DataSet.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/data/DataSet.java @@ -189,8 +189,8 @@ public interface DataSet extends DataModel { boolean isContinuous(); /** - * @return true if this is a discrete data set--that is, if it contains at least one column and all the columns - * are discrete. + * @return true if this is a discrete data set--that is, if it contains at least one column and all the columns are + * discrete. */ boolean isDiscrete(); @@ -273,16 +273,20 @@ public interface DataSet extends DataModel { * Creates and returns a dataset consisting of those variables in the list vars. Vars must be a subset of the * variables of this DataSet. The ordering of the elements of vars will be the same as in the list of variables in * this DataSet. + * + * @return a new data set consisting of the variables in the list vars. */ DataSet subsetColumns(List vars); /** - * @return a new data set in which the column at indices[i] is placed at index i, for i = 0 to indices.length - - * 1. (View instead?) + * @param columns The indices of the columns to include in the new data set. + * @return a new data set in which the column at indices[i] is placed at index i, for i = 0 to indices.length - 1. + * (View instead?) */ DataSet subsetColumns(int[] columns); /** + * @param rows The indices of the rows to include in the new data set. * @return a new data set in which the row at indices[i] is placed at index i, for i = 0 to indices.length - 1. * (View instead?) */ @@ -295,16 +299,22 @@ public interface DataSet extends DataModel { /** * The number format of the dataset. + * + * @return The number format of the dataset. */ NumberFormat getNumberFormat(); /** * The number formatter used to print out continuous values. + * + * @param nf The number formatter used to print out continuous values. */ void setNumberFormat(NumberFormat nf); /** - * The character used a delimiter when the dataset is output. + * The character used a delimiter when the dataset is output + * + * @param character The character used as a delimiter when the dataset is output */ void setOutputDelimiter(Character character); @@ -313,12 +323,33 @@ public interface DataSet extends DataModel { */ void permuteRows(); + /** + * Returns the map of column names to tooltips. + * + * @return The map of column names to tooltips. + */ Map getColumnToTooltip(); + /** + * Checks if the given object is equal to this dataset. + * + * @param o The object to check. + * @return True if the given object is equal to this dataset. + */ boolean equals(Object o); + /** + * Returns a copy of this dataset. + * + * @return A copy of this dataset. + */ DataSet copy(); + /** + * Returns a dataset with the same dimuensions as this dataset, but with no data. + * + * @return a dataset with the same dimensions as this dataset, but with no data. + */ DataSet like(); } diff --git a/tetrad-lib/src/main/java/edu/pitt/dbmi/algo/bayesian/constraint/inference/BCCausalInference.java b/tetrad-lib/src/main/java/edu/pitt/dbmi/algo/bayesian/constraint/inference/BCCausalInference.java index 1c23193d78..0c1991d221 100644 --- a/tetrad-lib/src/main/java/edu/pitt/dbmi/algo/bayesian/constraint/inference/BCCausalInference.java +++ b/tetrad-lib/src/main/java/edu/pitt/dbmi/algo/bayesian/constraint/inference/BCCausalInference.java @@ -30,6 +30,10 @@ * @author Kevin V. Bui (kvb2@pitt.edu) */ public class BCCausalInference { + + /** + * The value of the PESS constant. + */ private static final double PESS_VALUE = 1.0; private final int numberOfNodes; private final int numberOfCases; @@ -460,7 +464,16 @@ private double gammlnCore(double xx) { * An enum for the type of operation. */ public enum OP { - DEPENDENT, INDEPENDENT + + /** + * The operation is dependent. + */ + DEPENDENT, + + /** + * The operation is independent. + */ + INDEPENDENT } /** diff --git a/tetrad-lib/src/main/java/edu/pitt/dbmi/algo/bayesian/constraint/inference/BCInference.java b/tetrad-lib/src/main/java/edu/pitt/dbmi/algo/bayesian/constraint/inference/BCInference.java index 8d8063789b..8b4a596dd3 100644 --- a/tetrad-lib/src/main/java/edu/pitt/dbmi/algo/bayesian/constraint/inference/BCInference.java +++ b/tetrad-lib/src/main/java/edu/pitt/dbmi/algo/bayesian/constraint/inference/BCInference.java @@ -523,7 +523,15 @@ public void setPriorEqivalentSampleSize(double priorEquivalentSampleSize) { * Enum for the type of constraint. */ public enum OP { - independent, dependent + /** + * The operation is independent. + */ + independent, + + /** + * The operation is dependent. + */ + dependent } } diff --git a/tetrad-lib/src/test/java/edu/cmu/tetrad/algcomparison/TimeoutComparisonTest.java b/tetrad-lib/src/test/java/edu/cmu/tetrad/algcomparison/TimeoutComparisonTest.java deleted file mode 100644 index 984f490c40..0000000000 --- a/tetrad-lib/src/test/java/edu/cmu/tetrad/algcomparison/TimeoutComparisonTest.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (C) 2017 University of Pittsburgh. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301 USA - */ -package edu.cmu.tetrad.algcomparison; - -import edu.cmu.tetrad.algcomparison.algorithm.Algorithms; -import edu.cmu.tetrad.algcomparison.algorithm.oracle.pag.Gfci; -import edu.cmu.tetrad.algcomparison.graph.RandomForward; -import edu.cmu.tetrad.algcomparison.independence.FisherZ; -import edu.cmu.tetrad.algcomparison.score.SemBicScore; -import edu.cmu.tetrad.algcomparison.simulation.SemSimulation; -import edu.cmu.tetrad.algcomparison.simulation.Simulations; -import edu.cmu.tetrad.algcomparison.statistic.*; -import edu.cmu.tetrad.util.Parameters; -import edu.cmu.tetrad.util.Params; -import org.junit.ClassRule; -import org.junit.Ignore; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.concurrent.TimeUnit; -import java.util.stream.Stream; - -import static java.lang.System.out; - -/** - * Nov 14, 2017 5:24:51 PM - * - * @author Kevin V. Bui (kvb2@pitt.edu) - */ -public class TimeoutComparisonTest { - - @ClassRule - public static TemporaryFolder tmpDir = new TemporaryFolder(); - - public TimeoutComparisonTest() { - } - - private static TimeoutComparison getTetradComparisonEngine() { - TimeoutComparison comparison = new TimeoutComparison(); - comparison.setShowAlgorithmIndices(true); - comparison.setShowSimulationIndices(true); - comparison.setSortByUtility(true); - comparison.setShowUtilities(true); - comparison.setParallelized(true); - - return comparison; - } - - private static Simulations getSimulations() { - Simulations simulations = new Simulations(); - simulations.add(new SemSimulation(new RandomForward())); - - return simulations; - } - - private static Algorithms getAlgorithms() { - Algorithms algorithms = new Algorithms(); - algorithms.add(new Gfci(new FisherZ(), new SemBicScore())); - - return algorithms; - } - - private static Statistics getStatistics() { - Statistics statistics = new Statistics(); - statistics.add(new AdjacencyPrecision()); - statistics.add(new AdjacencyRecall()); - statistics.add(new ArrowheadPrecision()); - statistics.add(new ArrowheadRecall()); - statistics.add(new MathewsCorrAdj()); - statistics.add(new MathewsCorrArrow()); - statistics.add(new F1Adj()); - statistics.add(new F1Arrow()); - statistics.add(new StructuralHammingDistance()); - statistics.add(new ElapsedCpuTime()); - - return statistics; - } - - private static Parameters getParameters() { - Parameters parameters = new Parameters(); - parameters.set(Params.NUM_RUNS, 1); - parameters.set(Params.NUM_MEASURES, 100); - parameters.set(Params.AVG_DEGREE, 4, 6); - parameters.set(Params.SAMPLE_SIZE, 250000); - parameters.set(Params.ALPHA, 1e-4, 1e-3, 1e-2); - - return parameters; - } - - /** - * Test of setComparisonGraph method, of class TimeoutComparison. - * - * @throws IOException - */ - @Ignore - @Test - public void testTimeoutComparison() throws IOException { - Parameters parameters = TimeoutComparisonTest.getParameters(); - Statistics statistics = TimeoutComparisonTest.getStatistics(); - Algorithms algorithms = TimeoutComparisonTest.getAlgorithms(); - Simulations simulations = TimeoutComparisonTest.getSimulations(); - - String resultsPath = TimeoutComparisonTest.tmpDir.newFolder("comparison").toString(); - - TimeoutComparison comparisonEngine = TimeoutComparisonTest.getTetradComparisonEngine(); - comparisonEngine.compareFromSimulations(resultsPath, simulations, algorithms, statistics, parameters, 60, TimeUnit.SECONDS); - - out.println("================================================================================"); - out.println("Output File:"); - out.println("================================================================================"); - Path outputFile = Paths.get(resultsPath, "Comparison.txt"); - if (Files.exists(outputFile)) { - try (Stream stream = Files.lines(outputFile)) { - stream.forEach(out::println); - } - } - out.println("================================================================================"); - } - -} diff --git a/tetrad-lib/src/test/java/edu/cmu/tetrad/bayes/JunctionTreeAlgorithmTest.java b/tetrad-lib/src/test/java/edu/cmu/tetrad/bayes/JunctionTreeAlgorithmTest.java index e99b508fe7..d1af1fe326 100644 --- a/tetrad-lib/src/test/java/edu/cmu/tetrad/bayes/JunctionTreeAlgorithmTest.java +++ b/tetrad-lib/src/test/java/edu/cmu/tetrad/bayes/JunctionTreeAlgorithmTest.java @@ -38,6 +38,7 @@ import java.nio.file.Paths; import java.text.DecimalFormat; import java.util.Arrays; +import java.util.Objects; import java.util.stream.Collectors; /** @@ -79,11 +80,11 @@ private static void printExampleProof(JunctionTreeAlgorithm jta, int[] values) { System.out.printf("P(v1=0|v2=0)P(v2=0)P(v3=0|v2=0) = %f%n", v1GivenV2 * v2Parent * v3Givenv2); } - @Ignore +// @Ignore @Test public void testJointProbGivenParents() throws IOException { - String graphFile = this.getClass().getResource("/jta/graph2.txt").getFile(); - String dataFile = this.getClass().getResource("/jta/data2.txt").getFile(); + String graphFile = Objects.requireNonNull(this.getClass().getResource("/jta/graph2.txt")).getFile(); + String dataFile = Objects.requireNonNull(this.getClass().getResource("/jta/data2.txt")).getFile(); Graph graph = readInGraph(Paths.get(graphFile)); DataModel dataModel = readInDiscreteData(Paths.get(dataFile)); @@ -106,7 +107,7 @@ public void testJointProbGivenParents() throws IOException { double probXYGivenZW = jta.getConditionalProbabilities(nodes, values, parents, parentValues); // 0.24614443432733896 } - @Ignore +// @Ignore @Test public void testJointProbability() { String graphFile = this.getClass().getResource("/jta/graph.txt").getFile(); @@ -123,11 +124,11 @@ public void testJointProbability() { } } - @Ignore +// @Ignore @Test public void testJunctionTree() { - String graphFile = this.getClass().getResource("/jta/graph.txt").getFile(); - String dataFile = this.getClass().getResource("/jta/data.txt").getFile(); + String graphFile = Objects.requireNonNull(this.getClass().getResource("/jta/graph.txt")).getFile(); + String dataFile = Objects.requireNonNull(this.getClass().getResource("/jta/data.txt")).getFile(); try { JunctionTreeAlgorithm jta = getJunctionTreeAlgorithm(graphFile, dataFile); @@ -146,8 +147,6 @@ public void testJunctionTree() { Assert.assertEquals(expected, actual); // P(v1=0|v2=1) - iNode = 0; - value = 0; parents[0] = 1; parentValues[0] = 1; conProb = jta.getConditionalProbability(iNode, value, parents, parentValues); @@ -156,7 +155,6 @@ public void testJunctionTree() { Assert.assertEquals(expected, actual); // P(v1=1|v2=0) - iNode = 0; value = 1; parents[0] = 1; parentValues[0] = 0; @@ -166,8 +164,6 @@ public void testJunctionTree() { Assert.assertEquals(expected, actual); // P(v1=1|v2=1) - iNode = 0; - value = 1; parents[0] = 1; parentValues[0] = 1; conProb = jta.getConditionalProbability(iNode, value, parents, parentValues); diff --git a/tetrad-lib/src/test/java/edu/cmu/tetrad/test/TestCyclicity.java b/tetrad-lib/src/test/java/edu/cmu/tetrad/test/TestCyclicity.java deleted file mode 100755 index c202b54802..0000000000 --- a/tetrad-lib/src/test/java/edu/cmu/tetrad/test/TestCyclicity.java +++ /dev/null @@ -1,96 +0,0 @@ -///////////////////////////////////////////////////////////////////////////////// -// For information as to what this class does, see the Javadoc, below. // -// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, // -// 2007, 2008, 2009, 2010, 2014, 2015, 2022 by Peter Spirtes, Richard // -// Scheines, Joseph Ramsey, and Clark Glymour. // -// // -// This program is free software; you can redistribute it and/or modify // -// it under the terms of the GNU General Public License as published by // -// the Free Software Foundation; either version 2 of the License, or // -// (at your option) any later version. // -// // -// This program is distributed in the hope that it will be useful, // -// but WITHOUT ANY WARRANTY; without even the implied warranty of // -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // -// GNU General Public License for more details. // -// // -// You should have received a copy of the GNU General Public License // -// along with this program; if not, write to the Free Software // -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // -/////////////////////////////////////////////////////////////////////////////// - -package edu.cmu.tetrad.test; - -import jdepend.framework.JDepend; -import jdepend.framework.JavaPackage; -import org.junit.Ignore; -import org.junit.Test; - -import java.io.File; -import java.io.IOException; -import java.util.Collection; -import java.util.LinkedList; -import java.util.List; - -import static org.junit.Assert.fail; - -/** - * Checks for package cycles. - */ -@Ignore -public class TestCyclicity { - private JDepend jdepend; - - private void setUp() { - this.jdepend = new JDepend(); - - try { - this.jdepend.addDirectory(new File("target/classes/edu/cmu/tetrad").getAbsolutePath()); -// jdepend.addDirectory(new File("../../../tetrad/target/classes/edu/cmu/tetradapp").getAbsolutePath()); - } catch (IOException e) { - fail(e.getMessage()); - } - } - - /** - * Tests that a package dependency cycle does not exist for any of the analyzed packages. - */ - @Test - public void testAllPackagesCycle() { - setUp(); - - Collection packages = this.jdepend.analyze(); - - for (Object aPackage : packages) { - JavaPackage p = (JavaPackage) aPackage; - - if (p.containsCycle()) { - System.out.println("\n***Package: " + p.getName() + "."); - System.out.println(); - System.out.println( - "This package participates in a package cycle. In the following " + - "\nlist, for each i, some class in package i depends on some " + - "\nclass in package i + 1. Please find the cycle and remove it."); - - List l = new LinkedList(); - p.collectCycle(l); - System.out.println(); - - for (int j = 0; j < l.size(); j++) { - JavaPackage pack = (JavaPackage) l.get(j); - System.out.println((j + 1) + ".\t" + pack.getName()); - } - - System.out.println(); - } - } - - if (this.jdepend.containsCycles()) { - fail("Package cycle(s) found!"); - } - } -} - - - - diff --git a/tetrad-lib/src/test/java/edu/cmu/tetrad/test/TestGeneralResamplingTest.java b/tetrad-lib/src/test/java/edu/cmu/tetrad/test/TestGeneralResamplingTest.java index 151d3947cc..ca8dac8c0b 100644 --- a/tetrad-lib/src/test/java/edu/cmu/tetrad/test/TestGeneralResamplingTest.java +++ b/tetrad-lib/src/test/java/edu/cmu/tetrad/test/TestGeneralResamplingTest.java @@ -24,7 +24,6 @@ import edu.cmu.tetrad.algcomparison.algorithm.oracle.pag.Gfci; import edu.cmu.tetrad.algcomparison.independence.BdeuTest; import edu.cmu.tetrad.algcomparison.independence.ChiSquare; -import edu.cmu.tetrad.algcomparison.independence.FisherZ; import edu.cmu.tetrad.algcomparison.independence.IndependenceWrapper; import edu.cmu.tetrad.algcomparison.score.BdeuScore; import edu.cmu.tetrad.algcomparison.score.ScoreWrapper; @@ -38,12 +37,10 @@ import edu.cmu.tetrad.graph.GraphTransforms; import edu.cmu.tetrad.graph.Node; import edu.cmu.tetrad.graph.RandomGraph; -import edu.cmu.tetrad.sem.LargeScaleSimulation; import edu.cmu.tetrad.util.Parameters; import edu.cmu.tetrad.util.Params; import edu.cmu.tetrad.util.RandomUtil; import edu.pitt.dbmi.algo.resampling.GeneralResamplingTest; -import org.junit.Ignore; import org.junit.Test; import java.util.ArrayList; @@ -164,10 +161,7 @@ public void testFGESc() { final boolean faithfulnessAssumed = false; final int maxDegree = -1; - final int numVars = 20; - final int edgesPerNode = 2; final int numLatentConfounders = 0; - final int numCases = 50; final int numBootstrapSamples = 5; final boolean verbose = true; @@ -176,12 +170,6 @@ public void testFGESc() { System.out.println("Truth Graph:"); System.out.println(dag); - int[] causalOrdering = new int[numVars]; - - for (int i = 0; i < numVars; i++) { - causalOrdering[i] = i; - } - BayesPm pm = new BayesPm(dag); BayesIm im = new MlBayesIm(pm, MlBayesIm.RANDOM); DataSet data = im.simulateData(1000, false); @@ -202,8 +190,6 @@ public void testFGESc() { bootstrapTest.setVerbose(verbose); bootstrapTest.setParameters(parameters); Graph resultGraph = bootstrapTest.search(); -// System.out.println("Estimated Graph:"); -// System.out.println(resultGraph.toString()); // Adjacency Confusion Matrix int[][] adjAr = GeneralResamplingTest.getAdjConfusionMatrix(dag, resultGraph); @@ -216,7 +202,7 @@ public void testFGESc() { TestGeneralResamplingTest.printEdgeTypeConfusionMatrix(edgeAr); } - @Ignore + // @Ignore @Test public void testFGESd() { final double structurePrior = 1; @@ -224,8 +210,6 @@ public void testFGESd() { final boolean faithfulnessAssumed = false; final int maxDegree = -1; - final int numVars = 20; - final int edgesPerNode = 2; final int numLatentConfounders = 0; final int numCases = 50; final int numBootstrapSamples = 5; @@ -276,8 +260,6 @@ public void testGFCIc() { final boolean faithfulnessAssumed = false; final int maxDegree = -1; - final int numVars = 20; - final int edgesPerNode = 2; final int numLatentConfounders = 2; final int numCases = 50; final int numBootstrapSamples = 5; @@ -288,17 +270,8 @@ public void testGFCIc() { BayesPm pm = new BayesPm(dag, 2, 3); BayesIm im = new MlBayesIm(pm, MlBayesIm.RANDOM); -// DagToPag dagToPag = new DagToPag(dag); -// Graph truePag = dagToPag.convert(); - Graph truePag = GraphTransforms.dagToPag(dag); - int[] causalOrdering = new int[numVars]; - - for (int i = 0; i < numVars; i++) { - causalOrdering[i] = i; - } - DataSet data = im.simulateData(numCases, false); Parameters parameters = new Parameters(); @@ -332,7 +305,7 @@ public void testGFCIc() { TestGeneralResamplingTest.printEdgeTypeConfusionMatrix(edgeAr); } - @Ignore + // @Ignore @Test public void testGFCId() { final double structurePrior = 1; @@ -340,8 +313,6 @@ public void testGFCId() { final boolean faithfulnessAssumed = false; final int maxDegree = -1; - final int numVars = 20; - final int edgesPerNode = 2; final int numLatentConfounders = 4; final int numCases = 50; final int numBootstrapSamples = 5; @@ -349,10 +320,6 @@ public void testGFCId() { final long seed = 123; Graph dag = TestGeneralResamplingTest.makeDiscreteDAG(numLatentConfounders); - -// DagToPag dagToPag = new DagToPag(dag); -// Graph truePag = dagToPag.convert(); - Graph truePag = GraphTransforms.dagToPag(dag); BayesPm pm = new BayesPm(dag, 2, 3); @@ -394,69 +361,6 @@ public void testGFCId() { TestGeneralResamplingTest.printEdgeTypeConfusionMatrix(edgeAr); } - @Ignore - @Test - public void testFCIc() { - final int penaltyDiscount = 2; - final int depth = 3; - final int maxPathLength = -1; - - final int numVars = 20; - final int edgesPerNode = 2; - final int numLatentConfounders = 2; - final int numCases = 50; - final int numBootstrapSamples = 5; - final boolean verbose = true; - - Graph dag = TestGeneralResamplingTest.makeContinuousDAG(numLatentConfounders); - -// DagToPag dagToPag = new DagToPag(dag); -// Graph truePag = dagToPag.convert(); - - Graph truePag = GraphTransforms.dagToPag(dag); - - int[] causalOrdering = new int[numVars]; - - for (int i = 0; i < numVars; i++) { - causalOrdering[i] = i; - } - - LargeScaleSimulation simulator = new LargeScaleSimulation(dag, dag.getNodes(), causalOrdering); - - DataSet data = simulator.simulateDataFisher(numCases); - - Parameters parameters = new Parameters(); - parameters.set(Params.PENALTY_DISCOUNT, penaltyDiscount); - parameters.set(Params.DEPTH, depth); - parameters.set(Params.MAX_PATH_LENGTH, maxPathLength); - parameters.set("numCPDAGsToStore", 0); - parameters.set(Params.VERBOSE, verbose); - - IndependenceWrapper test = new FisherZ(); - Fci algorithm = new Fci(test); - - GeneralResamplingTest bootstrapTest = new GeneralResamplingTest(data, algorithm, - numBootstrapSamples, 100.0, - true, 0, true); - bootstrapTest.setVerbose(verbose); - bootstrapTest.setParameters(parameters); - //bootstrapTest.setParallelMode(false); - Graph resultGraph = bootstrapTest.search(); - //System.out.println("Estimated PAG_of_the_true_DAG Graph:"); - //System.out.println(resultGraph.toString()); - - // Adjacency Confusion Matrix - int[][] adjAr = GeneralResamplingTest.getAdjConfusionMatrix(truePag, resultGraph); - - TestGeneralResamplingTest.printAdjConfusionMatrix(adjAr); - - // Edge Type Confusion Matrix - int[][] edgeAr = GeneralResamplingTest.getEdgeTypeConfusionMatrix(truePag, resultGraph); - - TestGeneralResamplingTest.printEdgeTypeConfusionMatrix(edgeAr); - } - - @Ignore @Test public void testFCId() { final double structurePrior = 1; @@ -464,8 +368,6 @@ public void testFCId() { final int depth = -1; final int maxPathLength = -1; - final int numVars = 20; - final int edgesPerNode = 2; final int numLatentConfounders = 4; final int numCases = 50; final int numBootstrapSamples = 5; @@ -473,10 +375,6 @@ public void testFCId() { final long seed = 123; Graph dag = TestGeneralResamplingTest.makeDiscreteDAG(numLatentConfounders); - -// DagToPag dagToPag = new DagToPag(dag); -// Graph truePag = dagToPag.convert(); - Graph truePag = GraphTransforms.dagToPag(dag); BayesPm pm = new BayesPm(dag, 2, 3); @@ -503,8 +401,6 @@ public void testFCId() { bootstrapTest.setVerbose(verbose); bootstrapTest.setParameters(parameters); Graph resultGraph = bootstrapTest.search(); - //System.out.println("Estimated Bootstrapped PAG_of_the_true_DAG Graph:"); - //System.out.println(resultGraph.toString()); // Adjacency Confusion Matrix int[][] adjAr = GeneralResamplingTest.getAdjConfusionMatrix(truePag, resultGraph); @@ -516,5 +412,4 @@ public void testFCId() { TestGeneralResamplingTest.printEdgeTypeConfusionMatrix(edgeAr); } - } diff --git a/tetrad-lib/src/test/java/edu/cmu/tetrad/test/TestGeneralizedSem.java b/tetrad-lib/src/test/java/edu/cmu/tetrad/test/TestGeneralizedSem.java index 9e6390bd10..0992fba21a 100644 --- a/tetrad-lib/src/test/java/edu/cmu/tetrad/test/TestGeneralizedSem.java +++ b/tetrad-lib/src/test/java/edu/cmu/tetrad/test/TestGeneralizedSem.java @@ -29,7 +29,6 @@ import edu.cmu.tetrad.util.RandomUtil; import edu.cmu.tetrad.util.StatUtils; import edu.cmu.tetrad.util.Vector; -import org.junit.Ignore; import org.junit.Test; import java.text.ParseException; @@ -42,7 +41,7 @@ /** * @author josephramsey */ -@Ignore +//@Ignore public class TestGeneralizedSem { private final boolean printStuff = false; @@ -463,720 +462,6 @@ public void test6() { print(estIm); print(estimator.getReport()); - - double aSquaredStar = estimator.getaSquaredStar(); - - assertEquals(1.04, aSquaredStar, 0.01); - } - - @Test - public void test7() { - RandomUtil.getInstance().setSeed(29999483L); - - List nodes = new ArrayList<>(); - final int numVars = 10; - - for (int i = 0; i < numVars; i++) nodes.add(new ContinuousVariable("X" + (i + 1))); - - Graph graph = RandomGraph.randomGraphRandomForwardEdges(nodes, 0, numVars, 30, 15, 15, false, true); - - GeneralizedSemPm pm = new GeneralizedSemPm(graph); - GeneralizedSemIm im = new GeneralizedSemIm(pm); - - print(im); - - DataSet data = im.simulateDataRecursive(1000, false); - - GeneralizedSemEstimator estimator = new GeneralizedSemEstimator(); - GeneralizedSemIm estIm = estimator.estimate(pm, data); - - print(estIm); - print(estimator.getReport()); - - double aSquaredStar = estimator.getaSquaredStar(); - - assertEquals(0.67, aSquaredStar, 0.01); - } - - @Test - public void test8() { - RandomUtil.getInstance().setSeed(29999483L); - - Node x = new GraphNode("X"); - Node y = new GraphNode("Y"); - - List nodes = new ArrayList<>(); - nodes.add(x); - nodes.add(y); - - Graph graph = new EdgeListGraph(nodes); - - graph.addDirectedEdge(x, y); - - SemPm spm = new SemPm(graph); - SemIm sim = new SemIm(spm); - - sim.setEdgeCoef(x, y, 20); - sim.setErrVar(x, 1); - sim.setErrVar(y, 1); - - GeneralizedSemPm pm = new GeneralizedSemPm(spm); - GeneralizedSemIm im = new GeneralizedSemIm(pm, sim); - - print(im); - - try { - pm.setParameterEstimationInitializationExpression("b1", "U(10, 30)"); - pm.setParameterEstimationInitializationExpression("T1", "U(.1, 3)"); - pm.setParameterEstimationInitializationExpression("T2", "U(.1, 3)"); - } catch (ParseException e) { - e.printStackTrace(); - } - - DataSet data = im.simulateDataRecursive(1000, false); - - GeneralizedSemEstimator estimator = new GeneralizedSemEstimator(); - GeneralizedSemIm estIm = estimator.estimate(pm, data); - - print(estIm); -// System.out.println(estimator.getReport()); - - double aSquaredStar = estimator.getaSquaredStar(); - - assertEquals(0.69, aSquaredStar, 0.01); - } - - @Test - public void test9() { - RandomUtil.getInstance().setSeed(29999483L); - - try { - Node x1 = new GraphNode("X1"); - Node x2 = new GraphNode("X2"); - Node x3 = new GraphNode("X3"); - Node x4 = new GraphNode("X4"); - - Graph g = new EdgeListGraph(); - g.addNode(x1); - g.addNode(x2); - g.addNode(x3); - g.addNode(x4); - - g.addDirectedEdge(x1, x2); - g.addDirectedEdge(x2, x3); - g.addDirectedEdge(x3, x4); - g.addDirectedEdge(x1, x4); - - GeneralizedSemPm pm = new GeneralizedSemPm(g); - - pm.setNodeExpression(x1, "E_X1"); - pm.setNodeExpression(x2, "a1 * tan(X1) + E_X2"); - pm.setNodeExpression(x3, "a2 * tan(X2) + E_X3"); - pm.setNodeExpression(x4, "a3 * tan(X1) + a4 * tan(X3) ^ 2 + E_X4"); - - pm.setNodeExpression(pm.getErrorNode(x1), "Beta(5, 2)"); - pm.setNodeExpression(pm.getErrorNode(x2), "Beta(2, 5)"); - pm.setNodeExpression(pm.getErrorNode(x3), "Beta(1, 3)"); - pm.setNodeExpression(pm.getErrorNode(x4), "Beta(1, 7)"); - - pm.setParameterEstimationInitializationExpression("c1", "U(1, 3)"); - pm.setParameterEstimationInitializationExpression("c2", "U(1, 3)"); - pm.setParameterEstimationInitializationExpression("c3", "U(1, 3)"); - pm.setParameterEstimationInitializationExpression("c4", "U(1, 3)"); - pm.setParameterEstimationInitializationExpression("c5", "U(1, 3)"); - pm.setParameterEstimationInitializationExpression("c6", "U(1, 3)"); - pm.setParameterEstimationInitializationExpression("c7", "U(1, 3)"); - pm.setParameterEstimationInitializationExpression("c8", "U(1, 3)"); - - GeneralizedSemIm im = new GeneralizedSemIm(pm); - - print("True model: "); - print(im); - - DataSet data = im.simulateDataRecursive(1000, false); - - pm.setNodeExpression(pm.getErrorNode(x1), "Beta(c1, c2)"); - pm.setNodeExpression(pm.getErrorNode(x2), "Beta(c3, c4)"); - pm.setNodeExpression(pm.getErrorNode(x3), "Beta(c5, c6)"); - pm.setNodeExpression(pm.getErrorNode(x4), "Beta(c7, c8)"); - - GeneralizedSemEstimator estimator = new GeneralizedSemEstimator(); - GeneralizedSemIm estIm = estimator.estimate(pm, data); - - print("\n\n\nEstimated model: "); - print(estIm); - print(estimator.getReport()); - - - double aSquaredStar = estimator.getaSquaredStar(); - - assertEquals(0.62, aSquaredStar, 0.01); - } catch (ParseException e) { - e.printStackTrace(); - } - } - - @Test - public void test10() { - RandomUtil.getInstance().setSeed(29999483L); - - try { - Node x1 = new GraphNode("X1"); - Node x2 = new GraphNode("X2"); - Node x3 = new GraphNode("X3"); - Node x4 = new GraphNode("X4"); - - Graph g = new EdgeListGraph(); - g.addNode(x1); - g.addNode(x2); - g.addNode(x3); - g.addNode(x4); - - g.addDirectedEdge(x1, x2); - g.addDirectedEdge(x2, x3); - g.addDirectedEdge(x3, x4); - g.addDirectedEdge(x1, x4); - - GeneralizedSemPm pm = new GeneralizedSemPm(g); - - pm.setNodeExpression(x1, "E_X1"); - pm.setNodeExpression(x2, "a1 * tan(X1) + E_X2"); - pm.setNodeExpression(x3, "a2 * tan(X2) + E_X3"); - pm.setNodeExpression(x4, "a3 * tan(X1) * a4 * tan(X3) ^ 2 + E_X4"); - - pm.setNodeExpression(pm.getErrorNode(x1), "Gamma(5, 2)"); - pm.setNodeExpression(pm.getErrorNode(x2), "Gamma(5, 2)"); - pm.setNodeExpression(pm.getErrorNode(x3), "Gamma(5, 2)"); - pm.setNodeExpression(pm.getErrorNode(x4), "Gamma(5, 2)"); - - pm.setParameterEstimationInitializationExpression("c1", "U(1, 5)"); - pm.setParameterEstimationInitializationExpression("c2", "U(1, 5)"); - pm.setParameterEstimationInitializationExpression("c3", "U(1, 5)"); - pm.setParameterEstimationInitializationExpression("c4", "U(1, 5)"); - pm.setParameterEstimationInitializationExpression("c5", "U(1, 5)"); - pm.setParameterEstimationInitializationExpression("c6", "U(1, 5)"); - pm.setParameterEstimationInitializationExpression("c7", "U(1, 5)"); - pm.setParameterEstimationInitializationExpression("c8", "U(1, 5)"); - - GeneralizedSemIm im = new GeneralizedSemIm(pm); - - print("True model: "); - print(im); - - DataSet data = im.simulateDataRecursive(1000, false); - - pm.setNodeExpression(pm.getErrorNode(x1), "Gamma(c1, c2)"); - pm.setNodeExpression(pm.getErrorNode(x2), "Gamma(c3, c4)"); - pm.setNodeExpression(pm.getErrorNode(x3), "Gamma(c5, c6)"); - pm.setNodeExpression(pm.getErrorNode(x4), "Gamma(c7, c8)"); - - - GeneralizedSemEstimator estimator = new GeneralizedSemEstimator(); - GeneralizedSemIm estIm = estimator.estimate(pm, data); - - print("\n\n\nEstimated model: "); - print(estIm); - print(estimator.getReport()); - - double aSquaredStar = estimator.getaSquaredStar(); - - assertEquals(1.42, aSquaredStar, 0.01); - } catch (ParseException e) { - e.printStackTrace(); - } - } - - @Test - public void test11() { - RandomUtil.getInstance().setSeed(29999483L); - - try { - Node x1 = new GraphNode("X1"); - Node x2 = new GraphNode("X2"); - Node x3 = new GraphNode("X3"); - Node x4 = new GraphNode("X4"); - - Graph g = new EdgeListGraph(); - g.addNode(x1); - g.addNode(x2); - g.addNode(x3); - g.addNode(x4); - - g.addDirectedEdge(x1, x2); - g.addDirectedEdge(x2, x3); - g.addDirectedEdge(x3, x4); - g.addDirectedEdge(x1, x4); - - GeneralizedSemPm pm = new GeneralizedSemPm(g); - - pm.setNodeExpression(x1, "E_X1"); - pm.setNodeExpression(x2, "a1 * tan(X1) + E_X2"); - pm.setNodeExpression(x3, "a2 * tan(X2) + E_X3"); - pm.setNodeExpression(x4, "a3 * tan(X1) + a4 * tan(X3) ^ 2 + E_X4"); - - pm.setNodeExpression(pm.getErrorNode(x1), "N(0, c1)"); - pm.setNodeExpression(pm.getErrorNode(x2), "N(0, c2)"); - pm.setNodeExpression(pm.getErrorNode(x3), "N(0, c3)"); - pm.setNodeExpression(pm.getErrorNode(x4), "N(0, c4)"); - - pm.setParameterExpression("c1", "4"); - pm.setParameterExpression("c2", "4"); - pm.setParameterExpression("c3", "4"); - pm.setParameterExpression("c4", "4"); - - GeneralizedSemIm im = new GeneralizedSemIm(pm); - - print("True model: "); - print(im); - - DataSet data = im.simulateDataRecursive(1000, false); - - GeneralizedSemIm imInit = new GeneralizedSemIm(pm); - imInit.setParameterValue("c1", 8); - imInit.setParameterValue("c2", 8); - imInit.setParameterValue("c3", 8); - imInit.setParameterValue("c4", 8); - - GeneralizedSemEstimator estimator = new GeneralizedSemEstimator(); - GeneralizedSemIm estIm = estimator.estimate(pm, data); - - print("\n\n\nEstimated model: "); - print(estIm); - print(estimator.getReport()); - - double aSquaredStar = estimator.getaSquaredStar(); - - assertEquals(7.07, aSquaredStar, 0.01); - } catch (ParseException e) { - e.printStackTrace(); - } - } - - @Test - public void test12() { - RandomUtil.getInstance().setSeed(29999483L); - - try { - Node x1 = new GraphNode("X1"); - Node x2 = new GraphNode("X2"); - Node x3 = new GraphNode("X3"); - Node x4 = new GraphNode("X4"); - - Graph g = new EdgeListGraph(); - g.addNode(x1); - g.addNode(x2); - g.addNode(x3); - g.addNode(x4); - - g.addDirectedEdge(x1, x2); - g.addDirectedEdge(x2, x3); - g.addDirectedEdge(x3, x4); - g.addDirectedEdge(x1, x4); - - GeneralizedSemPm pm = new GeneralizedSemPm(g); - - pm.setNodeExpression(x1, "E_X1"); - pm.setNodeExpression(x2, "a1 * tan(X1) + E_X2"); - pm.setNodeExpression(x3, "a2 * tan(X2) + E_X3"); - pm.setNodeExpression(x4, "a3 * tan(X1) + a4 * tan(X3) ^ 2 + E_X4"); - - pm.setNodeExpression(pm.getErrorNode(x1), "Normal(c1, c2)"); - pm.setNodeExpression(pm.getErrorNode(x2), "Normal(c3, c4)"); - pm.setNodeExpression(pm.getErrorNode(x3), "Normal(c5, c6)"); - pm.setNodeExpression(pm.getErrorNode(x4), "Normal(c7, c8)"); - - pm.setParameterExpression("c1", "1"); - pm.setParameterExpression("c2", "5"); - pm.setParameterExpression("c3", "1"); - pm.setParameterExpression("c4", "5"); - pm.setParameterExpression("c5", "1"); - pm.setParameterExpression("c6", "5"); - pm.setParameterExpression("c7", "1"); - pm.setParameterExpression("c8", "5"); - - GeneralizedSemIm im = new GeneralizedSemIm(pm); - - print("True model: "); - print(im); - - DataSet data = im.simulateDataRecursive(1000, false); - - GeneralizedSemIm imInit = new GeneralizedSemIm(pm); - imInit.setParameterValue("c1", 3); - imInit.setParameterValue("c2", 4); - imInit.setParameterValue("c3", 3); - imInit.setParameterValue("c4", 4); - imInit.setParameterValue("c5", 3); - imInit.setParameterValue("c6", 4); - imInit.setParameterValue("c7", 3); - imInit.setParameterValue("c8", 4); - - GeneralizedSemEstimator estimator = new GeneralizedSemEstimator(); - GeneralizedSemIm estIm = estimator.estimate(pm, data); - - print("\n\n\nEstimated model: "); - print(estIm); - print(estimator.getReport()); - - double aSquaredStar = estimator.getaSquaredStar(); - - assertEquals(2.56, aSquaredStar, 0.01); - } catch (ParseException e) { - e.printStackTrace(); - } - } - - @Test - public void test13() { - RandomUtil.getInstance().setSeed(29999483L); - - try { - Node x1 = new GraphNode("X1"); - Node x2 = new GraphNode("X2"); - Node x3 = new GraphNode("X3"); - Node x4 = new GraphNode("X4"); - - Graph g = new EdgeListGraph(); - g.addNode(x1); - g.addNode(x2); - g.addNode(x3); - g.addNode(x4); - - g.addDirectedEdge(x1, x2); - g.addDirectedEdge(x2, x3); - g.addDirectedEdge(x3, x4); - g.addDirectedEdge(x1, x4); - - GeneralizedSemPm pm = new GeneralizedSemPm(g); - - pm.setNodeExpression(x1, "E_X1"); - pm.setNodeExpression(x2, "a1 * tan(X1) + E_X1"); - pm.setNodeExpression(x3, "a2 * tan(X2) + E_X1"); - pm.setNodeExpression(x4, "a3 * tan(X1) + a4 * tan(X3) + E_X1"); - - pm.setNodeExpression(pm.getErrorNode(x1), "StudentT(c2)"); - pm.setNodeExpression(pm.getErrorNode(x2), "StudentT(c4)"); - pm.setNodeExpression(pm.getErrorNode(x3), "StudentT(c6)"); - pm.setNodeExpression(pm.getErrorNode(x4), "StudentT(c8)"); - - pm.setParameterExpression("c2", "3"); - pm.setParameterExpression("c4", "3"); - pm.setParameterExpression("c6", "3"); - pm.setParameterExpression("c8", "3"); - - GeneralizedSemIm im = new GeneralizedSemIm(pm); - - print("True model: "); - print(im); - - DataSet data = im.simulateDataRecursive(500, false); - - GeneralizedSemIm imInit = new GeneralizedSemIm(pm); - imInit.setParameterValue("c2", 1); - imInit.setParameterValue("c4", 1); - imInit.setParameterValue("c6", 1); - imInit.setParameterValue("c8", 1); - - GeneralizedSemEstimator estimator = new GeneralizedSemEstimator(); - GeneralizedSemIm estIm = estimator.estimate(pm, data); - - print("\n\n\nEstimated model: "); - print(estIm); - print(estimator.getReport()); - - double aSquaredStar = estimator.getaSquaredStar(); - - assertEquals(3.19, aSquaredStar, 0.01); - } catch (ParseException e) { - e.printStackTrace(); - } - } - - @Test - public void test14() { - RandomUtil.getInstance().setSeed(29999483L); - - try { - Node x1 = new GraphNode("X1"); - Node x2 = new GraphNode("X2"); - Node x3 = new GraphNode("X3"); - Node x4 = new GraphNode("X4"); - - Graph g = new EdgeListGraph(); - g.addNode(x1); - g.addNode(x2); - g.addNode(x3); - g.addNode(x4); - - g.addDirectedEdge(x1, x2); - g.addDirectedEdge(x2, x3); - g.addDirectedEdge(x3, x4); - g.addDirectedEdge(x1, x4); - - GeneralizedSemPm pm = new GeneralizedSemPm(g); - - pm.setNodeExpression(x1, "E_X1"); - pm.setNodeExpression(x2, "a1 * tan(X1) + E_X2"); - pm.setNodeExpression(x3, "a2 * tan(X2) + E_X3"); - pm.setNodeExpression(x4, "a3 * tan(X1) + a4 * tan(X3) ^ 2 + E_X4"); - - pm.setNodeExpression(pm.getErrorNode(x1), "N(0, c1)"); - pm.setNodeExpression(pm.getErrorNode(x2), "N(0, c2)"); - pm.setNodeExpression(pm.getErrorNode(x3), "N(0, c3)"); - pm.setNodeExpression(pm.getErrorNode(x4), "N(0, c4)"); - - pm.setParameterExpression("a1", "1"); - pm.setParameterExpression("a2", "1"); - pm.setParameterExpression("a3", "1"); - pm.setParameterExpression("a4", "1"); - pm.setParameterExpression("c1", "4"); - pm.setParameterExpression("c2", "4"); - pm.setParameterExpression("c3", "4"); - pm.setParameterExpression("c4", "4"); - - GeneralizedSemIm im = new GeneralizedSemIm(pm); - - print("True model: "); - print(im); - - DataSet data = im.simulateDataRecursive(1000, false); - - GeneralizedSemIm imInit = new GeneralizedSemIm(pm); - imInit.setParameterValue("c1", 8); - imInit.setParameterValue("c2", 8); - imInit.setParameterValue("c3", 8); - imInit.setParameterValue("c4", 8); - - GeneralizedSemEstimator estimator = new GeneralizedSemEstimator(); - GeneralizedSemIm estIm = estimator.estimate(pm, data); - - print("\n\n\nEstimated model: "); - print(estIm); - print(estimator.getReport()); - - double aSquaredStar = estimator.getaSquaredStar(); - - assertEquals(71.25, aSquaredStar, 0.01); - } catch (ParseException e) { - e.printStackTrace(); - } - } - - @Test - public void test15() { - RandomUtil.getInstance().setSeed(29999483L); - - try { - Node x1 = new GraphNode("X1"); - Node x2 = new GraphNode("X2"); - Node x3 = new GraphNode("X3"); - Node x4 = new GraphNode("X4"); - - Graph g = new EdgeListGraph(); - g.addNode(x1); - g.addNode(x2); - g.addNode(x3); - g.addNode(x4); - - g.addDirectedEdge(x1, x2); - g.addDirectedEdge(x2, x3); - g.addDirectedEdge(x3, x4); - g.addDirectedEdge(x1, x4); - - GeneralizedSemPm pm = new GeneralizedSemPm(g); - - pm.setNodeExpression(x1, "E_X1"); - pm.setNodeExpression(x2, "a1 * X1 + E_X2"); - pm.setNodeExpression(x3, "a2 * X2 + E_X3"); - pm.setNodeExpression(x4, "a3 * X1 + a4 * X3 ^ 2 + E_X4"); - - pm.setNodeExpression(pm.getErrorNode(x1), "Gamma(c1, c2)"); - pm.setNodeExpression(pm.getErrorNode(x2), "ChiSquare(c3)"); - pm.setNodeExpression(pm.getErrorNode(x3), "ChiSquare(c4)"); - pm.setNodeExpression(pm.getErrorNode(x4), "ChiSquare(c5)"); - - pm.setParameterExpression("c1", "5"); - pm.setParameterExpression("c2", "2"); - pm.setParameterExpression("c3", "10"); - pm.setParameterExpression("c4", "10"); - pm.setParameterExpression("c5", "10"); - - pm.setParameterEstimationInitializationExpression("c1", "U(1, 5)"); - pm.setParameterEstimationInitializationExpression("c2", "U(1, 5)"); - pm.setParameterEstimationInitializationExpression("c3", "U(1, 5)"); - pm.setParameterEstimationInitializationExpression("c4", "U(1, 5)"); - pm.setParameterEstimationInitializationExpression("c5", "U(1, 5)"); - - GeneralizedSemIm im = new GeneralizedSemIm(pm); - - print("True model: "); - print(im); - - DataSet data = im.simulateDataRecursive(1000, false); - - GeneralizedSemEstimator estimator = new GeneralizedSemEstimator(); - GeneralizedSemIm estIm = estimator.estimate(pm, data); - - print("\n\n\nEstimated model: "); - print(estIm); - print(estimator.getReport()); - - double aSquaredStar = estimator.getaSquaredStar(); - - assertEquals(.79, aSquaredStar, 0.01); - } catch (ParseException e) { - e.printStackTrace(); - } - } - - @Test - public void test16() { - RandomUtil.getInstance().setSeed(29999483L); - - try { - Node x1 = new GraphNode("X1"); - Node x2 = new GraphNode("X2"); - Node x3 = new GraphNode("X3"); - Node x4 = new GraphNode("X4"); - - Graph g = new EdgeListGraph(); - g.addNode(x1); - g.addNode(x2); - g.addNode(x3); - g.addNode(x4); - - g.addDirectedEdge(x1, x2); - g.addDirectedEdge(x2, x3); - g.addDirectedEdge(x3, x4); - g.addDirectedEdge(x1, x4); - - GeneralizedSemPm pm = new GeneralizedSemPm(g); - - pm.setNodeExpression(x1, "E_X1"); - pm.setNodeExpression(x2, "a1 * X1 + E_X2"); - pm.setNodeExpression(x3, "a2 * X2 + E_X3"); - pm.setNodeExpression(x4, "a3 * X1 + a4 * X3 ^ 2 + E_X4"); - - pm.setNodeExpression(pm.getErrorNode(x1), "N(0, c1)"); - pm.setNodeExpression(pm.getErrorNode(x2), "N(0, c2)"); - pm.setNodeExpression(pm.getErrorNode(x3), "N(0, c3)"); - pm.setNodeExpression(pm.getErrorNode(x4), "N(0, c4)"); - - GeneralizedSemIm im = new GeneralizedSemIm(pm); - - im.setParameterValue("a1", 1); - im.setParameterValue("a2", 1); - im.setParameterValue("a3", 1); - im.setParameterValue("a4", 1); - im.setParameterValue("c1", 1); - im.setParameterValue("c2", 1); - im.setParameterValue("c3", 1); - im.setParameterValue("c4", 1); - - print("True model: "); - print(im); - - DataSet data = im.simulateDataRecursive(1000, false); - - GeneralizedSemIm imInit = new GeneralizedSemIm(pm); - - imInit.setParameterValue("a1", .5); - imInit.setParameterValue("a2", .5); - imInit.setParameterValue("a3", .5); - imInit.setParameterValue("a4", .7); - imInit.setParameterValue("c1", 2); - imInit.setParameterValue("c2", 2); - imInit.setParameterValue("c3", 2); - imInit.setParameterValue("c4", 2); - - GeneralizedSemEstimator estimator = new GeneralizedSemEstimator(); - GeneralizedSemIm estIm = estimator.estimate(pm, data); - - print("\n\n\nEstimated model: "); - print(estIm); - print(estimator.getReport()); - - double aSquaredStar = estimator.getaSquaredStar(); - - assertEquals(50.38, aSquaredStar, 0.01); - } catch (ParseException e) { - e.printStackTrace(); - } - } - - @Test - public void test17() { - RandomUtil.getInstance().setSeed(29999483L); - - try { - Node x1 = new GraphNode("X1"); - Node x2 = new GraphNode("X2"); - Node x3 = new GraphNode("X3"); - Node x4 = new GraphNode("X4"); - - Graph g = new EdgeListGraph(); - g.addNode(x1); - g.addNode(x2); - g.addNode(x3); - g.addNode(x4); - - g.addDirectedEdge(x1, x2); - g.addDirectedEdge(x2, x3); - g.addDirectedEdge(x3, x4); - g.addDirectedEdge(x1, x4); - - GeneralizedSemPm pm = new GeneralizedSemPm(g); - - pm.setNodeExpression(x1, "E_X1"); - pm.setNodeExpression(x2, "a1 * X1 + E_X2"); - pm.setNodeExpression(x3, "a2 * X2 + E_X3"); - pm.setNodeExpression(x4, "a3 * X1 * a3 * a4 * X3 + E_X4"); - - pm.setNodeExpression(pm.getErrorNode(x1), "N(0, c1)"); - pm.setNodeExpression(pm.getErrorNode(x2), "N(0, c2)"); - pm.setNodeExpression(pm.getErrorNode(x3), "N(0, c3)"); - pm.setNodeExpression(pm.getErrorNode(x4), "N(0, c4)"); - - GeneralizedSemIm im = new GeneralizedSemIm(pm); - - im.setParameterValue("a1", 1); - im.setParameterValue("a2", 1); - im.setParameterValue("a3", 1); - im.setParameterValue("a4", 1); - im.setParameterValue("c1", 1); - im.setParameterValue("c2", 1); - im.setParameterValue("c3", 1); - im.setParameterValue("c4", 1); - - print("True model: "); - print(im); - - DataSet data = im.simulateDataRecursive(1000, false); - - GeneralizedSemIm imInit = new GeneralizedSemIm(pm); - - imInit.setParameterValue("a1", RandomUtil.getInstance().nextUniform(-3, 3)); - imInit.setParameterValue("a2", RandomUtil.getInstance().nextUniform(-3, 3)); - imInit.setParameterValue("a3", RandomUtil.getInstance().nextUniform(-3, 3)); - imInit.setParameterValue("a4", RandomUtil.getInstance().nextUniform(-3, 3)); - imInit.setParameterValue("c1", RandomUtil.getInstance().nextUniform(1, 3)); - imInit.setParameterValue("c2", RandomUtil.getInstance().nextUniform(1, 3)); - imInit.setParameterValue("c3", RandomUtil.getInstance().nextUniform(1, 3)); - imInit.setParameterValue("c4", RandomUtil.getInstance().nextUniform(1, 3)); - - GeneralizedSemEstimator estimator = new GeneralizedSemEstimator(); - GeneralizedSemIm estIm = estimator.estimate(pm, data); - - print("\n\n\nEstimated model: "); - print(estIm); - print(estimator.getReport()); - - double aSquaredStar = estimator.getaSquaredStar(); - - assertEquals(14.26, aSquaredStar, 0.01); - } catch (ParseException e) { - e.printStackTrace(); - } } private GeneralizedSemPm makeTypicalPm() { diff --git a/tetrad-lib/src/test/java/edu/cmu/tetrad/test/TestIndTestWaldLr.java b/tetrad-lib/src/test/java/edu/cmu/tetrad/test/TestIndTestWaldLr.java deleted file mode 100644 index 1422e9ac42..0000000000 --- a/tetrad-lib/src/test/java/edu/cmu/tetrad/test/TestIndTestWaldLr.java +++ /dev/null @@ -1,118 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// For information as to what this class does, see the Javadoc, below. // -// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, // -// 2007, 2008, 2009, 2010, 2014, 2015, 2022 by Peter Spirtes, Richard // -// Scheines, Joseph Ramsey, and Clark Glymour. // -// // -// This program is free software; you can redistribute it and/or modify // -// it under the terms of the GNU General Public License as published by // -// the Free Software Foundation; either version 2 of the License, or // -// (at your option) any later version. // -// // -// This program is distributed in the hope that it will be useful, // -// but WITHOUT ANY WARRANTY; without even the implied warranty of // -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // -// GNU General Public License for more details. // -// // -// You should have received a copy of the GNU General Public License // -// along with this program; if not, write to the Free Software // -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // -/////////////////////////////////////////////////////////////////////////////// - -package edu.cmu.tetrad.test; - -import edu.cmu.tetrad.data.ContinuousVariable; -import edu.cmu.tetrad.data.DataSet; -import edu.cmu.tetrad.data.Discretizer; -import edu.cmu.tetrad.graph.Graph; -import edu.cmu.tetrad.graph.Node; -import edu.cmu.tetrad.graph.RandomGraph; -import edu.cmu.tetrad.search.IndependenceTest; -import edu.cmu.tetrad.search.test.MsepTest; -import edu.cmu.tetrad.sem.SemIm; -import edu.cmu.tetrad.sem.SemPm; -import edu.cmu.tetrad.util.RandomUtil; -import edu.pitt.csb.mgm.IndTestMultinomialLogisticRegressionWald; -import org.junit.Ignore; -import org.junit.Test; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import static org.junit.Assert.assertEquals; - - -/** - * Tests the IndTestTimeSeries class. - * - * @author josephramsey - */ -@Ignore -public class TestIndTestWaldLr { - - @Test - public void testIsIndependent() { - RandomUtil.getInstance().setSeed(1450705713157L); - - int numPassed = 0; - - for (int i = 0; i < 10; i++) { - List nodes = new ArrayList<>(); - - for (int i1 = 0; i1 < 10; i1++) { - nodes.add(new ContinuousVariable("X" + (i1 + 1))); - } - - Graph graph = RandomGraph.randomGraph(nodes, 0, 10, - 3, 3, 3, false); - SemPm pm = new SemPm(graph); - SemIm im = new SemIm(pm); - DataSet data = im.simulateData(1000, false); - - Discretizer discretizer = new Discretizer(data); - discretizer.setVariablesCopied(true); - discretizer.equalCounts(data.getVariable(0), 2); - discretizer.equalCounts(data.getVariable(3), 2); - data = discretizer.discretize(); - - Node x1 = data.getVariable("X1"); - Node x2 = data.getVariable("X2"); - Node x3 = data.getVariable("X3"); - Node x4 = data.getVariable("X4"); - Node x5 = data.getVariable("X5"); - - Set cond = new HashSet<>(); - cond.add(x3); - cond.add(x4); - cond.add(x5); - - Node x1Graph = graph.getNode(x1.getName()); - Node x2Graph = graph.getNode(x2.getName()); - - Set condGraph = new HashSet<>(); - - for (Node node : cond) { - condGraph.add(graph.getNode(node.getName())); - } - - // Using the Wald LR test since it's most up to date. - IndependenceTest test = new IndTestMultinomialLogisticRegressionWald(data, 0.05, false); - MsepTest msep = new MsepTest(graph); - - boolean correct = test.checkIndependence(x2, x1, cond) == msep.checkIndependence(x2Graph, x1Graph, condGraph); - - if (correct) { - numPassed++; - } - } - -// System.out.println(RandomUtil.getInstance().getSeed()); - - // Do not always get all 10. - assertEquals(10, numPassed); - } -} - - diff --git a/tetrad-lib/src/test/java/edu/cmu/tetrad/test/TestMimbuild.java b/tetrad-lib/src/test/java/edu/cmu/tetrad/test/TestMimbuild.java deleted file mode 100644 index 1b71ba7542..0000000000 --- a/tetrad-lib/src/test/java/edu/cmu/tetrad/test/TestMimbuild.java +++ /dev/null @@ -1,202 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// For information as to what this class does, see the Javadoc, below. // -// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, // -// 2007, 2008, 2009, 2010, 2014, 2015, 2022 by Peter Spirtes, Richard // -// Scheines, Joseph Ramsey, and Clark Glymour. // -// // -// This program is free software; you can redistribute it and/or modify // -// it under the terms of the GNU General Public License as published by // -// the Free Software Foundation; either version 2 of the License, or // -// (at your option) any later version. // -// // -// This program is distributed in the hope that it will be useful, // -// but WITHOUT ANY WARRANTY; without even the implied warranty of // -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // -// GNU General Public License for more details. // -// // -// You should have received a copy of the GNU General Public License // -// along with this program; if not, write to the Free Software // -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // -/////////////////////////////////////////////////////////////////////////////// - -package edu.cmu.tetrad.test; - -import edu.cmu.tetrad.data.Clusters; -import edu.cmu.tetrad.data.CovarianceMatrix; -import edu.cmu.tetrad.data.DataGraphUtils; -import edu.cmu.tetrad.data.DataSet; -import edu.cmu.tetrad.graph.Graph; -import edu.cmu.tetrad.graph.Node; -import edu.cmu.tetrad.graph.NodeType; -import edu.cmu.tetrad.search.Bpc; -import edu.cmu.tetrad.search.Fofc; -import edu.cmu.tetrad.search.Mimbuild; -import edu.cmu.tetrad.search.MimbuildTrek; -import edu.cmu.tetrad.search.utils.BpcTestType; -import edu.cmu.tetrad.search.utils.GraphSearchUtils; -import edu.cmu.tetrad.search.utils.MimUtils; -import edu.cmu.tetrad.sem.ReidentifyVariables; -import edu.cmu.tetrad.sem.SemIm; -import edu.cmu.tetrad.sem.SemPm; -import edu.cmu.tetrad.util.Parameters; -import edu.cmu.tetrad.util.RandomUtil; -import org.junit.Ignore; -import org.junit.Test; - -import java.io.IOException; -import java.rmi.MarshalledObject; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; - -import static org.junit.Assert.assertEquals; - - -/** - * @author josephramsey - */ -@Ignore -public class TestMimbuild { - - @Test - public void test1() { - RandomUtil.getInstance().setSeed(49283494L); - - for (int r = 0; r < 1; r++) { - Graph mim = DataGraphUtils.randomSingleFactorModel(5, 5, 6, 0, 0, 0); - - Graph mimStructure = structure(mim); - - Parameters params = new Parameters(); - params.set("coefLow", 0.0); - params.set("coefHigh", 1.0); - - SemPm pm = new SemPm(mim); - SemIm im = new SemIm(pm, params); - DataSet data = im.simulateData(300, false); - - final String algorithm = "FOFC"; - Graph searchGraph; - List> partition; - - if (algorithm.equals("FOFC")) { - Fofc fofc = new Fofc(data, BpcTestType.TETRAD_WISHART, - Fofc.Algorithm.GAP, 0.001); - searchGraph = fofc.search(); - partition = fofc.getClusters(); - } else if (algorithm.equals("BPC")) { - final BpcTestType testType = BpcTestType.TETRAD_WISHART; - final BpcTestType purifyType = BpcTestType.TETRAD_BASED; - - Bpc bpc = new Bpc( - data, 0.001, - testType - ); - searchGraph = bpc.search(); - - partition = MimUtils.convertToClusters2(searchGraph); - } else { - throw new IllegalStateException(); - } - - List latentVarList = reidentifyVariables(mim, data, partition); - - Graph mimbuildStructure; - - for (int mimbuildMethod : new int[]{2}) { - if (mimbuildMethod == 2) { - Mimbuild mimbuild = new Mimbuild(); - mimbuild.setPenaltyDiscount(1); - mimbuild.setMinClusterSize(3); - mimbuildStructure = mimbuild.search(partition, latentVarList, new CovarianceMatrix(data)); - int shd = GraphSearchUtils.structuralHammingDistance(mimStructure, mimbuildStructure); - assertEquals(7, shd); - } else if (mimbuildMethod == 3) { -// System.out.println("Mimbuild Trek\n"); - MimbuildTrek mimbuild = new MimbuildTrek(); - mimbuild.setAlpha(0.1); - mimbuild.setMinClusterSize(3); - mimbuildStructure = mimbuild.search(partition, latentVarList, new CovarianceMatrix(data)); - int shd = GraphSearchUtils.structuralHammingDistance(mimStructure, mimbuildStructure); - assertEquals(3, shd); - } else { - throw new IllegalStateException(); - } - } - - } - - } - - - private Graph changeLatentNames(Graph full, Clusters measurements, List latentVarList) { - Graph g2 = null; - - try { - g2 = (Graph) new MarshalledObject(full).get(); - } catch (IOException | ClassNotFoundException e) { - e.printStackTrace(); - } - - for (int i = 0; i < measurements.getNumClusters(); i++) { - List d = measurements.getCluster(i); - String latentName = latentVarList.get(i); - - for (Node node : full.getNodes()) { - if (!(node.getNodeType() == NodeType.LATENT)) { - continue; - } - - List _children = new ArrayList<>(full.getChildren(node)); - - _children.removeAll(ReidentifyVariables.getLatents(full)); - - List childNames = getNames(_children); - - if (new HashSet<>(childNames).equals(new HashSet<>(d))) { - assert g2 != null; - g2.getNode(node.getName()).setName(latentName); - } - } - } - - return g2; - } - - private List getNames(List nodes) { - List names = new ArrayList<>(); - for (Node node : nodes) { - names.add(node.getName()); - } - return names; - } - - - private List reidentifyVariables(Graph mim, DataSet data, List> partition) { - List latentVarList = null; - - if (2 == 1) { - latentVarList = ReidentifyVariables.reidentifyVariables1(partition, mim); - } else if (2 == 2) { - latentVarList = ReidentifyVariables.reidentifyVariables2(partition, mim, data); - } else { - throw new IllegalStateException(); - } - - return latentVarList; - } - - private Graph structure(Graph mim) { - List latents = new ArrayList<>(); - - for (Node node : mim.getNodes()) { - if (node.getNodeType() == NodeType.LATENT) { - latents.add(node); - } - } - - return mim.subgraph(latents); - } -} - - diff --git a/tetrad-lib/src/test/java/edu/cmu/tetrad/test/TestPurify.java b/tetrad-lib/src/test/java/edu/cmu/tetrad/test/TestPurify.java deleted file mode 100644 index 6850c5f16b..0000000000 --- a/tetrad-lib/src/test/java/edu/cmu/tetrad/test/TestPurify.java +++ /dev/null @@ -1,317 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// For information as to what this class does, see the Javadoc, below. // -// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, // -// 2007, 2008, 2009, 2010, 2014, 2015, 2022 by Peter Spirtes, Richard // -// Scheines, Joseph Ramsey, and Clark Glymour. // -// // -// This program is free software; you can redistribute it and/or modify // -// it under the terms of the GNU General Public License as published by // -// the Free Software Foundation; either version 2 of the License, or // -// (at your option) any later version. // -// // -// This program is distributed in the hope that it will be useful, // -// but WITHOUT ANY WARRANTY; without even the implied warranty of // -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // -// GNU General Public License for more details. // -// // -// You should have received a copy of the GNU General Public License // -// along with this program; if not, write to the Free Software // -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // -/////////////////////////////////////////////////////////////////////////////// - -package edu.cmu.tetrad.test; - -import edu.cmu.tetrad.data.CovarianceMatrix; -import edu.cmu.tetrad.data.DataGraphUtils; -import edu.cmu.tetrad.data.DataSet; -import edu.cmu.tetrad.graph.*; -import edu.cmu.tetrad.search.Mimbuild; -import edu.cmu.tetrad.search.utils.*; -import edu.cmu.tetrad.sem.SemIm; -import edu.cmu.tetrad.sem.SemPm; -import edu.cmu.tetrad.util.RandomUtil; -import org.junit.Ignore; -import org.junit.Test; - -import java.util.ArrayList; -import java.util.List; - -import static org.junit.Assert.assertEquals; - -/** - * @author josephramsey - */ -@Ignore -public class TestPurify { - - @Test - public void test1() { - RandomUtil.getInstance().setSeed(48290483L); - - SemGraph graph = new SemGraph(); - - Node l1 = new GraphNode("L1"); - l1.setNodeType(NodeType.LATENT); - - Node l2 = new GraphNode("L2"); - l2.setNodeType(NodeType.LATENT); - - Node l3 = new GraphNode("L3"); - l3.setNodeType(NodeType.LATENT); - - Node x1 = new GraphNode("X1"); - Node x2 = new GraphNode("X2"); - Node x3 = new GraphNode("X3"); - Node x4 = new GraphNode("X4"); - Node x4b = new GraphNode("X4b"); - - Node x5 = new GraphNode("X5"); - Node x6 = new GraphNode("X6"); - Node x7 = new GraphNode("X7"); - Node x8 = new GraphNode("X8"); - Node x8b = new GraphNode("X8b"); - - Node x9 = new GraphNode("X9"); - Node x10 = new GraphNode("X10"); - Node x11 = new GraphNode("X11"); - Node x12 = new GraphNode("X12"); - Node x12b = new GraphNode("X12b"); - - graph.addNode(l1); - graph.addNode(l2); - graph.addNode(l3); - - graph.addNode(x1); - graph.addNode(x2); - graph.addNode(x3); - graph.addNode(x4); - graph.addNode(x4b); - - graph.addNode(x5); - graph.addNode(x6); - graph.addNode(x7); - graph.addNode(x8); - graph.addNode(x8b); - - graph.addNode(x9); - graph.addNode(x10); - graph.addNode(x11); - graph.addNode(x12); - graph.addNode(x12b); - - graph.addDirectedEdge(l1, x1); - graph.addDirectedEdge(l1, x2); - graph.addDirectedEdge(l1, x3); - graph.addDirectedEdge(l1, x4); - graph.addDirectedEdge(l1, x4b); - graph.addDirectedEdge(l1, x5); - - graph.addDirectedEdge(l2, x5); - graph.addDirectedEdge(l2, x6); - graph.addDirectedEdge(l2, x7); - graph.addDirectedEdge(l2, x8); - graph.addDirectedEdge(l2, x8b); - - graph.addDirectedEdge(l3, x9); - graph.addDirectedEdge(l3, x10); - graph.addDirectedEdge(l3, x11); - graph.addDirectedEdge(l3, x12); - graph.addDirectedEdge(l3, x12b); - - graph.addDirectedEdge(x1, x4); - - SemPm pm = new SemPm(graph); - SemIm im = new SemIm(pm); - DataSet data = im.simulateData(1000, false); - - List> partition = new ArrayList<>(); - - List cluster1 = new ArrayList<>(); - cluster1.add(x1); - cluster1.add(x2); - cluster1.add(x3); - cluster1.add(x4); - cluster1.add(x4b); - cluster1.add(x5); - - List cluster2 = new ArrayList<>(); - cluster2.add(x5); - cluster2.add(x6); - cluster2.add(x7); - cluster2.add(x8); - cluster2.add(x8b); - - List cluster3 = new ArrayList<>(); - cluster3.add(x9); - cluster3.add(x10); - cluster3.add(x11); - cluster3.add(x12); - cluster3.add(x12b); - - partition.add(cluster1); - partition.add(cluster2); - partition.add(cluster3); - - TetradTest test = new TetradTestContinuous(data, BpcTestType.TETRAD_WISHART, 0.05); - IPurify purify = new PurifyTetradBased(test); - purify.setTrueGraph(graph); - - List> partition2 = purify.purify(partition); - - assertEquals(3, partition2.get(0).size()); - assertEquals(2, partition2.get(1).size()); - assertEquals(5, partition2.get(2).size()); - } - - @Test - public void test1b() { - RandomUtil.getInstance().setSeed(48290483L); - - SemGraph graph = new SemGraph(); - - Node l1 = new GraphNode("L1"); - l1.setNodeType(NodeType.LATENT); - - Node l2 = new GraphNode("L2"); - l2.setNodeType(NodeType.LATENT); - - Node x1 = new GraphNode("X1"); - Node x2 = new GraphNode("X2"); - Node x3 = new GraphNode("X3"); - Node x4 = new GraphNode("X4"); - Node x5 = new GraphNode("X5"); - Node x6 = new GraphNode("X6"); - - Node x7 = new GraphNode("X7"); - Node x8 = new GraphNode("X8"); - Node x9 = new GraphNode("X9"); - Node x10 = new GraphNode("X10"); - Node x11 = new GraphNode("X11"); - Node x12 = new GraphNode("X12"); - - graph.addNode(l1); - graph.addNode(l2); - - graph.addNode(x1); - graph.addNode(x2); - graph.addNode(x3); - graph.addNode(x4); - graph.addNode(x5); - graph.addNode(x6); - - graph.addNode(x7); - graph.addNode(x8); - graph.addNode(x9); - graph.addNode(x10); - graph.addNode(x11); - graph.addNode(x12); - - graph.addDirectedEdge(l1, x1); - graph.addDirectedEdge(l1, x2); - graph.addDirectedEdge(l1, x3); - graph.addDirectedEdge(l1, x4); - graph.addDirectedEdge(l1, x5); - graph.addDirectedEdge(l1, x5); - graph.addDirectedEdge(l1, x6); - - graph.addDirectedEdge(l2, x6); - graph.addDirectedEdge(l2, x7); - graph.addDirectedEdge(l2, x8); - graph.addDirectedEdge(l2, x9); - graph.addDirectedEdge(l2, x10); - graph.addDirectedEdge(l2, x11); - graph.addDirectedEdge(l2, x12); - - graph.addDirectedEdge(x3, x4); - graph.addDirectedEdge(x9, x10); - - SemPm pm = new SemPm(graph); - SemIm im = new SemIm(pm); - DataSet data = im.simulateData(3000, false); - - List> partition = new ArrayList<>(); - - List cluster1 = new ArrayList<>(); - cluster1.add(x1); - cluster1.add(x2); - cluster1.add(x3); - cluster1.add(x4); - cluster1.add(x5); - - List cluster2 = new ArrayList<>(); - cluster2.add(x7); - cluster2.add(x8); - cluster2.add(x9); - cluster2.add(x10); - cluster2.add(x11); - cluster2.add(x12); - - partition.add(cluster1); - partition.add(cluster2); - - TetradTest test = new TetradTestContinuous(data, BpcTestType.TETRAD_WISHART, 0.0001); - IPurify purify = new PurifyTetradBased(test); - purify.setTrueGraph(graph); - - List> clustering = purify.purify(partition); - - assertEquals(4, clustering.get(0).size()); - assertEquals(5, clustering.get(1).size()); - - } - - @Test - public void test2() { - RandomUtil.getInstance().setSeed(48290483L); - - Graph graph = new EdgeListGraph(DataGraphUtils.randomSingleFactorModel(3, 3, 5, 0, 0, 0)); - - SemPm pm = new SemPm(graph); - SemIm im = new SemIm(pm); - DataSet data = im.simulateData(1000, false); - - List latents = new ArrayList<>(); - - for (Node node : graph.getNodes()) { - if (node.getNodeType() == NodeType.LATENT) latents.add(node); - } - - Graph structuralGraph = graph.subgraph(latents); - - List> clustering = new ArrayList<>(); - - for (Node node : latents) { - List adj = new ArrayList<>(graph.getAdjacentNodes(node)); - adj.removeAll(latents); - - clustering.add(adj); - } - - TetradTestContinuous test = new TetradTestContinuous(data, BpcTestType.TETRAD_WISHART, 0.001); - - IPurify purify = new PurifyTetradBased(test); - - List> purifiedClustering = purify.purify(clustering); - List latentsNames = new ArrayList<>(); - - for (Node latent : latents) { - latentsNames.add(latent.getName()); - } - - Mimbuild mimbuild = new Mimbuild(); - mimbuild.setPenaltyDiscount(1); - Graph _graph = mimbuild.search(purifiedClustering, latentsNames, new CovarianceMatrix(data)); - - List _latents = new ArrayList<>(); - - for (Node node : _graph.getNodes()) { - if (node.getNodeType() == NodeType.LATENT) _latents.add(node); - } - - Graph _structuralGraph = _graph.subgraph(_latents); - - assertEquals(2, _structuralGraph.getNumEdges()); - } -} - - From 195d158dcc6da994c287b2df217641a46f174c81 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Thu, 1 Feb 2024 02:48:13 -0500 Subject: [PATCH 152/163] Cleanup. --- tetrad-lib/src/main/java/edu/cmu/tetrad/data/DataSet.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/data/DataSet.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/data/DataSet.java index ac5d924dd1..bc7d3dc3d1 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/data/DataSet.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/data/DataSet.java @@ -346,7 +346,7 @@ public interface DataSet extends DataModel { DataSet copy(); /** - * Returns a dataset with the same dimuensions as this dataset, but with no data. + * Returns a dataset with the same dimensions as this dataset, but with no data. * * @return a dataset with the same dimensions as this dataset, but with no data. */ From 0db84c8a4c5f731e72acd917c65d0c9d4e6456d3 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Thu, 1 Feb 2024 03:05:17 -0500 Subject: [PATCH 153/163] Cleanup. --- .../java/edu/cmu/tetrad/data/ByteDataBox.java | 16 +++- .../java/edu/cmu/tetrad/data/DataBox.java | 12 +++ .../java/edu/cmu/tetrad/data/DataFilter.java | 3 + .../tetrad/search/utils/BpcAlgorithmType.java | 28 ++++++ .../cmu/tetrad/search/utils/BpcTestType.java | 95 +++++++++++++++---- 5 files changed, 137 insertions(+), 17 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/data/ByteDataBox.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/data/ByteDataBox.java index 3e777c5990..58ae752447 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/data/ByteDataBox.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/data/ByteDataBox.java @@ -23,6 +23,7 @@ import edu.cmu.tetrad.graph.Node; +import java.io.Serial; import java.util.ArrayList; import java.util.List; @@ -30,6 +31,7 @@ * Stores a 2D array of byte data. Note that the missing value marker for this box is -99. */ public class ByteDataBox implements DataBox { + @Serial private static final long serialVersionUID = 23L; /** @@ -50,6 +52,9 @@ public class ByteDataBox implements DataBox { /** * Constructs an 2D byte array consisting entirely of missing values (-99). + * + * @param rows the number of rows. + * @param cols the number of columns. */ public ByteDataBox(int rows, int cols) { this.data = new byte[rows][cols]; @@ -66,6 +71,8 @@ public ByteDataBox(int rows, int cols) { /** * Constructs a new data box using the given 2D byte data array as data. + * + * @param data the data to use. */ public ByteDataBox(byte[][] data) { int length = data[0].length; @@ -84,6 +91,8 @@ public ByteDataBox(byte[][] data) { /** * Generates a simple exemplar of this class to test serialization. + * + * @return a simple exemplar of this class to test serialization. */ public static BoxDataSet serializableInstance() { List vars = new ArrayList<>(); @@ -106,7 +115,12 @@ public int numCols() { } /** - * Sets the value at the given row/column to the given Number value. The value used is number.byteValue(). + * Sets the value at the given row/column to the given Number value. The value used is number.byteValue(). If the + * value is null, the missing value marker (-99) is used. + * + * @param row the row index. + * @param col the column index. + * @param value the value to store. */ public void set(int row, int col, Number value) { if (value == null) { diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/data/DataBox.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/data/DataBox.java index ffb1ca67c7..28f117f7a8 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/data/DataBox.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/data/DataBox.java @@ -46,12 +46,17 @@ public interface DataBox extends TetradSerializable { * Sets the value at the given row and column to the given Number. This number may be interpreted differently * depending on how values are stored. A value of null is interpreted as a missing value. * + * @param row the row index. + * @param col the column index. + * @param value the value to store. * @throws IllegalArgumentException if the given value cannot be stored (because it's out of range or cannot be * converted or whatever). */ void set(int row, int col, Number value) throws IllegalArgumentException; /** + * @param row the row index. + * @param col the column index. * @return the value at the given row and column as a Number. If the value is missing, null is uniformly returned. */ Number get(int row, int col); @@ -62,10 +67,17 @@ public interface DataBox extends TetradSerializable { DataBox copy(); /** + * @param rows the row indices. + * @param cols the column indices. * @return this data box, restricted to the given rows and columns. */ DataBox viewSelection(int[] rows, int[] cols); + /** + * Returns a data box of the same dimensions as this one, without setting any values. + * + * @return a new data box. + */ DataBox like(); } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/data/DataFilter.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/data/DataFilter.java index 6d15b59482..c8a342b506 100755 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/data/DataFilter.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/data/DataFilter.java @@ -32,6 +32,9 @@ public interface DataFilter { /** * Interpolates the given data set, producing a data set with no missing values. + * + * @param dataSet the data set to interpolate. + * @return the interpolated data set. */ DataSet filter(DataSet dataSet); } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/BpcAlgorithmType.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/BpcAlgorithmType.java index c2f34dd8a3..b7a5110e19 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/BpcAlgorithmType.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/BpcAlgorithmType.java @@ -29,12 +29,40 @@ * @author josephramsey */ public enum BpcAlgorithmType implements TetradSerializable { + + /** + * This one will work and does a good job for medium-sized models. + */ BUILD_PURE_CLUSTERS, + + /** + * This will work and does a good job for small models, no more than 4 latents. + */ SIMPLIFIED_BPC_DEPTH_0, + + /** + * This is very slow. + */ SIMPLIFIED_BPC_DEPTH_1, + + /** + * Even slower. + */ SIMPLIFIED_BPC, + + /** + * This option doesn't do any purify. + */ TETRAD_PURIFY_WASHDOWN, + + /** + * FOFC algorithm + */ FIND_ONE_FACTOR_CLUSTERS, + + /** + * FTFC algorithm. + */ FIND_TWO_FACTOR_CLUSTERS; private static final long serialVersionUID = 23L; diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/BpcTestType.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/BpcTestType.java index a5cf29545a..6193e197f4 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/BpcTestType.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/utils/BpcTestType.java @@ -28,31 +28,85 @@ */ public enum BpcTestType implements TetradSerializable { - // This one will work and does a good job for medium sized models. + /** + * This one will work and does a good job for medium sized models. + */ GAUSSIAN_PVALUE, - // This will work and does a good job for small models, no more than 4 latents. + /** + * This will work and does a good job for small models, no more than 4 latents. + */ GAUSSIAN_SCORE_MARKS, - // This is very slow. + /** + * This is very slow. + */ GAUSSIAN_SCORE, - // Even slower. + /** + * Even slower. + */ GAUSSIAN_SCORE_ITERATE, - // This option doesn't do any purify. + /** + * This option doesn't do any purify. + */ NONE, - DISCRETE_LRT, DISCRETE_VARIATIONAL, - - - // TETRAD_DELTA is kept for purpospes of serialization. - GAUSSIAN_FACTOR, DISCRETE, TETRAD_BOLLEN, TETRAD_DELTA, TETRAD_WISHART, - TETRAD_BASED, POPULATION, - - // For FTFC - SAG, GAP; - + /** + * Discrete LRT. + */ + DISCRETE_LRT, + + /** + * Discrete Variational. + */ + DISCRETE_VARIATIONAL, + + /** + * Gaussian Factor. + */ + GAUSSIAN_FACTOR, + + /** + * Discrete. + */ + DISCRETE, + + /** + * Bollen Tetrad test. + */ + TETRAD_BOLLEN, + + /** + * Delta Tetrad test. + */ + TETRAD_DELTA, + + /** + * Wishart Tetrad test. + */ + TETRAD_WISHART, + + /** + * Tetrad-based test. + */ + TETRAD_BASED, + + /** + * Population test. + */ + POPULATION, + + /** + * SAG test, for FTFC. + */ + SAG, + + /** + * GAP test, for FTFC. + */ + GAP; private static final long serialVersionUID = 23L; @@ -60,7 +114,11 @@ public static BpcTestType serializableInstance() { return BpcTestType.GAUSSIAN_PVALUE; } - + /** + * Returns the test type descriptions for the Purify algorithm. + * + * @return the test type descriptions for the Purify algorithm. + */ public static BpcTestType[] getPurifyTestDescriptions() { return new BpcTestType[]{ @@ -73,6 +131,11 @@ public static BpcTestType[] getPurifyTestDescriptions() { }; } + /** + * Returns the test type descriptions for the BuildPureClusters algorithm. + * + * @return the test type descriptions for the BuildPureClusters algorithm. + */ public static BpcTestType[] getTestDescriptions() { return new BpcTestType[]{ BpcTestType.TETRAD_WISHART, From c0ad0f8835b265a7393c5832ad9636163d41d2bc Mon Sep 17 00:00:00 2001 From: jdramsey Date: Thu, 1 Feb 2024 03:07:43 -0500 Subject: [PATCH 154/163] Cleanup. --- .../edu/cmu/tetrad/algcomparison/algorithm/oracle/pag/Ccd.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/pag/Ccd.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/pag/Ccd.java index 9accc6e7e6..5fec0b6156 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/pag/Ccd.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/pag/Ccd.java @@ -15,6 +15,7 @@ import edu.cmu.tetrad.util.Params; import edu.pitt.dbmi.algo.resampling.GeneralResamplingTest; +import java.io.Serial; import java.util.ArrayList; import java.util.List; @@ -29,8 +30,8 @@ algoType = AlgType.forbid_latent_common_causes ) @Bootstrapping -//@Experimental public class Ccd implements Algorithm, TakesIndependenceWrapper, ReturnsBootstrapGraphs { + @Serial private static final long serialVersionUID = 23L; private IndependenceWrapper test; private List bootstrapGraphs = new ArrayList<>(); From 85100395199a05f11fc3f4b95e9ea618d1bc1b49 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Thu, 1 Feb 2024 03:18:34 -0500 Subject: [PATCH 155/163] Cleanup. --- .../model/EmBayesEstimatorWrapper.java | 8 +--- .../model/PValueImproverWrapper.java | 12 +----- .../datamanip/DiscretizationWrapper.java | 12 +----- tetrad-lib/pom.xml | 37 ------------------- 4 files changed, 6 insertions(+), 63 deletions(-) diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/EmBayesEstimatorWrapper.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/EmBayesEstimatorWrapper.java index be285fa554..695b583314 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/EmBayesEstimatorWrapper.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/EmBayesEstimatorWrapper.java @@ -33,6 +33,7 @@ import java.io.IOException; import java.io.ObjectInputStream; +import java.io.Serial; /** * Wraps a Bayes Pm for use in the Tetrad application. @@ -41,6 +42,7 @@ * @author Frank Wimberly adapted for EM Bayes estimator and structural EM Bayes estimator */ public class EmBayesEstimatorWrapper implements SessionModel, GraphSource { + @Serial private static final long serialVersionUID = 23L; /** @@ -48,12 +50,6 @@ public class EmBayesEstimatorWrapper implements SessionModel, GraphSource { */ private String name; - /** - * @serial - * @deprecated - */ - private BayesPm bayesPm; - /** * @serial Cannot be null. */ diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/PValueImproverWrapper.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/PValueImproverWrapper.java index 27faa11081..b6dad98b95 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/PValueImproverWrapper.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/PValueImproverWrapper.java @@ -35,6 +35,7 @@ import java.beans.PropertyChangeListener; import java.io.IOException; import java.io.ObjectInputStream; +import java.io.Serial; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; @@ -45,27 +46,18 @@ * @author Ricardo Silva */ public class PValueImproverWrapper extends AbstractAlgorithmRunner { + @Serial private static final long serialVersionUID = 23L; private final DataWrapper dataWrapper; private final Parameters params = new Parameters(); - /** - * @deprecated - */ - private final double alpha = 0.05; private AlgorithmType algorithmType = AlgorithmType.BEAM; private String name; private Graph externalGraph; private Graph graph; private transient List listeners; private Parameters params2; - private SemIm estSem; - private Graph trueDag; private SemIm originalSemIm; private SemIm newSemIm; - /** - * @deprecated - */ - private SemIm semIm; public PValueImproverWrapper(DataWrapper dataWrapper, Parameters params, KnowledgeBoxModel knowledgeBoxModel) { diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/datamanip/DiscretizationWrapper.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/datamanip/DiscretizationWrapper.java index 0f1e014413..6a1e5c8854 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/datamanip/DiscretizationWrapper.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/datamanip/DiscretizationWrapper.java @@ -30,6 +30,7 @@ import java.io.IOException; import java.io.ObjectInputStream; +import java.io.Serial; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -41,18 +42,9 @@ * @author Tyler */ public class DiscretizationWrapper extends DataWrapper { + @Serial private static final long serialVersionUID = 23L; - - /** - * The discretized data set. - * - * @serial Not null. - * @deprecated - */ - private final List discretizedDataSets = null; - - /** * Constructs the DiscretizationWrapper by discretizing the select * DataModel. diff --git a/tetrad-lib/pom.xml b/tetrad-lib/pom.xml index e6056c4bfd..1a0c086e3a 100644 --- a/tetrad-lib/pom.xml +++ b/tetrad-lib/pom.xml @@ -50,25 +50,6 @@ - - - - - - - - - - - - - - - - - - - @@ -121,34 +102,22 @@ 1.0.3 compile - - - - - - - javax.help javahelp 2.0.05 - com.google.code.gson gson 2.10.1 - - org.json json 20231013 compile - - javax.xml.bind jaxb-api @@ -156,14 +125,11 @@ - org.jsoup jsoup 1.15.4 - - io.github.cmu-phil data-reader @@ -177,10 +143,7 @@ - UTF-8 - - From f4837b094fc706a30a491fcf43f7642b5a0f3116 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Thu, 1 Feb 2024 03:31:53 -0500 Subject: [PATCH 156/163] Cleanup. --- .../cmu/tetradapp/editor/LoadDataDialog.java | 2 ++ .../java/edu/cmu/tetrad/data/IDataReader.java | 23 ------------------- .../java/edu/cmu/tetrad/sem/SemXmlParser.java | 6 ++--- 3 files changed, 5 insertions(+), 26 deletions(-) delete mode 100644 tetrad-lib/src/main/java/edu/cmu/tetrad/data/IDataReader.java diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/LoadDataDialog.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/LoadDataDialog.java index 1a9e1429e5..261b98092d 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/LoadDataDialog.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/LoadDataDialog.java @@ -36,6 +36,7 @@ import java.awt.event.MouseEvent; import java.io.File; import java.io.IOException; +import java.io.Serial; import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedList; @@ -53,6 +54,7 @@ */ public final class LoadDataDialog extends JPanel { + @Serial private static final long serialVersionUID = 2299304318793152418L; private final List loadedFiles; diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/data/IDataReader.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/data/IDataReader.java deleted file mode 100644 index b2040105b4..0000000000 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/data/IDataReader.java +++ /dev/null @@ -1,23 +0,0 @@ -package edu.cmu.tetrad.data; - -/** - * Identifies a class that can read data from a file. - * - * @author josephramsey - */ -public interface IDataReader { - - /** - * The delimiter between entries in a line, one of DelimiterType.WHITESPACE, DelimiterType.TAB, DelimiterType.COMMA, - * DelimiterType.COLON - */ - void setDelimiter(DelimiterType delimiterType); - - /** - * The String identifier of the case ID column. - * - * @deprecated - */ - void setIdLabel(String caseIdsLabel); - -} diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/sem/SemXmlParser.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/sem/SemXmlParser.java index fe6e7e6e7b..829e1ff50a 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/sem/SemXmlParser.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/sem/SemXmlParser.java @@ -108,7 +108,7 @@ private static SemIm makeEdges(Element edgesElement, Dag semGraph) { edge = edges.get(i); causeNode = semGraph.getNode(edge.getAttributeValue(SemXmlConstants.CAUSE_NODE)); effectNode = semGraph.getNode(edge.getAttributeValue(SemXmlConstants.EFFECT_NODE)); - semIm.setParamValue(causeNode, effectNode, new Double(edge.getAttributeValue(SemXmlConstants.COEF))); + semIm.setParamValue(causeNode, effectNode, Double.parseDouble(edge.getAttributeValue(SemXmlConstants.COEF))); //semIm.getSemPm().getParameter(causeNode, effectNode).setFixed(new Boolean(edge.getAttributeValue(SemXmlConstants.FIXED)).booleanValue()); Parameter covarianceParameter = semIm.getSemPm().getCovarianceParameter(causeNode, effectNode); @@ -153,7 +153,7 @@ private static void addMarginalErrorDistribution(Element marginalDistributionEle node = graph.getExogenous(graph.getNode(normal.getAttributeValue(SemXmlConstants.VARIABLE))); //can't set mean at this point... - semIm.setParamValue(node, node, new Double(normal.getAttributeValue(SemXmlConstants.VARIANCE))); + semIm.setParamValue(node, node, Double.parseDouble(normal.getAttributeValue(SemXmlConstants.VARIANCE))); } } @@ -170,7 +170,7 @@ private static void addJointErrorDistribution(Element jointDistributionElement, normal = normals.get(i); node1 = semIm.getSemPm().getGraph().getExogenous(semIm.getSemPm().getGraph().getNode(normal.getAttributeValue(SemXmlConstants.NODE_1))); node2 = semIm.getSemPm().getGraph().getExogenous(semIm.getSemPm().getGraph().getNode(normal.getAttributeValue(SemXmlConstants.NODE_2))); - semIm.setParamValue(node1, node2, new Double(normal.getAttributeValue(SemXmlConstants.COVARIANCE))); + semIm.setParamValue(node1, node2, Double.parseDouble(normal.getAttributeValue(SemXmlConstants.COVARIANCE))); } } From 4e78da1358305a87884dc7e7524d5819371e1460 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Thu, 1 Feb 2024 05:55:10 -0500 Subject: [PATCH 157/163] Fixed an issue in chi square. --- .../main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java index aa37527a04..2c0fdba7ed 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java @@ -185,11 +185,7 @@ public Result calcChiSquare(int[] testIndices) { double expected = (sumRows[i] * sumCols[j]) / total; if (testType == TestType.CHI_SQUARE) { - if (expected == 0) { - throw new IllegalArgumentException("Total is zero."); - } - - if (expected > 0.0) { + if (expected > 0) { double d = observed - expected; _xSquare += (d * d) / expected; } From 3692a658481f6b24f389491180945edd687128a2 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Thu, 1 Feb 2024 05:56:16 -0500 Subject: [PATCH 158/163] Fixed an issue in chi square. --- .../main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java index 2c0fdba7ed..c6a6c0f6c1 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java @@ -185,10 +185,8 @@ public Result calcChiSquare(int[] testIndices) { double expected = (sumRows[i] * sumCols[j]) / total; if (testType == TestType.CHI_SQUARE) { - if (expected > 0) { - double d = observed - expected; - _xSquare += (d * d) / expected; - } + double d = observed - expected; + _xSquare += (d * d) / expected; } else if (testType == TestType.G_SQUARE) { // The G-square test is a likelihood ratio test, so we need to take the log of the From bf668bbdd42123c0267900f876896980fa0c76d7 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Thu, 1 Feb 2024 12:55:06 -0500 Subject: [PATCH 159/163] Fixed an issue in chi square. --- .../main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java index c6a6c0f6c1..539e067f19 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/test/ChiSquareTest.java @@ -185,6 +185,8 @@ public Result calcChiSquare(int[] testIndices) { double expected = (sumRows[i] * sumCols[j]) / total; if (testType == TestType.CHI_SQUARE) { + + // Note here expected > 0, so we can divide by it. double d = observed - expected; _xSquare += (d * d) / expected; } else if (testType == TestType.G_SQUARE) { @@ -195,7 +197,7 @@ public Result calcChiSquare(int[] testIndices) { if (observed > 0) { _xSquare += 2.0 * observed * log(observed / expected); } else { - _xSquare += 0.0; + _xSquare += 0; } } else { throw new IllegalArgumentException("Unknown test type: " + testType); From 324907600af0f142a7ea816c91a1bdca72d8c349 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Fri, 2 Feb 2024 01:50:27 -0500 Subject: [PATCH 160/163] Adding a random seed parameter to BOSS and GRaSP and algorithms that use BOSS and GRaSP. --- .../algcomparison/algorithm/multi/ImagesBoss.java | 3 ++- .../algcomparison/algorithm/oracle/cpdag/Boss.java | 7 ++++++- .../algorithm/oracle/cpdag/BossLingam.java | 2 ++ .../algcomparison/algorithm/oracle/cpdag/Grasp.java | 2 ++ .../algorithm/oracle/cpdag/RestrictedBoss.java | 2 ++ .../algcomparison/algorithm/oracle/pag/Bfci.java | 4 ++++ .../algcomparison/algorithm/oracle/pag/GraspFci.java | 4 ++++ .../src/main/java/edu/cmu/tetrad/search/BFci.java | 9 +++++++++ .../src/main/java/edu/cmu/tetrad/search/Cstar.java | 1 + .../src/main/java/edu/cmu/tetrad/search/Fask.java | 7 +++++++ .../src/main/java/edu/cmu/tetrad/search/Grasp.java | 9 +++++++++ .../src/main/java/edu/cmu/tetrad/search/GraspFci.java | 6 ++++++ .../src/main/java/edu/cmu/tetrad/search/Mimbuild.java | 6 ++++++ .../java/edu/cmu/tetrad/search/PermutationSearch.java | 10 ++++++++++ 14 files changed, 70 insertions(+), 2 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/multi/ImagesBoss.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/multi/ImagesBoss.java index eca28c086e..9aaa6bdc8c 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/multi/ImagesBoss.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/multi/ImagesBoss.java @@ -85,6 +85,7 @@ public Graph search(List dataSets, Parameters parameters) { if (meta == 1) { PermutationSearch search = new PermutationSearch(new Boss(score)); + search.setSeed(parameters.getLong(Params.SEED)); // edu.cmu.tetrad.search.Fges search = new edu.cmu.tetrad.search.Fges(score); search.setKnowledge(this.knowledge); // search.setVerbose(parameters.getBoolean(Params.VERBOSE)); @@ -184,7 +185,7 @@ public List getParameters() { parameters.add(Params.RANDOM_SELECTION_SIZE); parameters.add(Params.TIME_LAG); parameters.add(Params.IMAGES_META_ALG); - + parameters.add(Params.SEED); parameters.add(Params.VERBOSE); return parameters; diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/Boss.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/Boss.java index e15d581b94..7d9a4a3868 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/Boss.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/Boss.java @@ -42,7 +42,7 @@ public class Boss implements Algorithm, UsesScoreWrapper, HasKnowledge, private ScoreWrapper score; private Knowledge knowledge = new Knowledge(); private List bootstrapGraphs = new ArrayList<>(); - + private long seed = 01; public Boss() { // Used in reflection; do not delete. @@ -54,6 +54,8 @@ public Boss(ScoreWrapper score) { @Override public Graph search(DataModel dataModel, Parameters parameters) { + this.seed = parameters.getLong(Params.SEED); + if (parameters.getInt(Params.NUMBER_RESAMPLING) < 1) { if (parameters.getInt(Params.TIME_LAG) > 0) { DataSet dataSet = (DataSet) dataModel; @@ -68,6 +70,7 @@ public Graph search(DataModel dataModel, Parameters parameters) { Score score = this.score.getScore(dataModel, parameters); edu.cmu.tetrad.search.Boss boss = new edu.cmu.tetrad.search.Boss(score); + boss.setUseBes(parameters.getBoolean(Params.USE_BES)); boss.setNumStarts(parameters.getInt(Params.NUM_STARTS)); boss.setNumThreads(parameters.getInt(Params.NUM_THREADS)); @@ -75,6 +78,7 @@ public Graph search(DataModel dataModel, Parameters parameters) { boss.setVerbose(parameters.getBoolean(Params.VERBOSE)); PermutationSearch permutationSearch = new PermutationSearch(boss); permutationSearch.setKnowledge(this.knowledge); + permutationSearch.setSeed(seed); Graph graph = permutationSearch.search(); LogUtilsSearch.stampWithScore(graph, score); LogUtilsSearch.stampWithBic(graph, dataModel); @@ -118,6 +122,7 @@ public List getParameters() { params.add(Params.TIME_LAG); params.add(Params.NUM_THREADS); params.add(Params.USE_DATA_ORDER); + params.add(Params.SEED); params.add(Params.VERBOSE); return params; diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/BossLingam.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/BossLingam.java index 4dc585c651..dac01c2201 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/BossLingam.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/BossLingam.java @@ -67,6 +67,7 @@ public Graph search(DataModel dataModel, Parameters parameters) { boss.setUseDataOrder(parameters.getBoolean(Params.USE_DATA_ORDER)); boss.setVerbose(parameters.getBoolean(Params.VERBOSE)); PermutationSearch permutationSearch = new PermutationSearch(boss); + permutationSearch.setSeed(parameters.getLong(Params.SEED)); permutationSearch.setKnowledge(this.knowledge); Graph cpdag = permutationSearch.search(); @@ -114,6 +115,7 @@ public List getParameters() { parameters.add(Params.TIME_LAG); parameters.add(Params.NUM_THREADS); parameters.add(Params.USE_DATA_ORDER); + parameters.add(Params.SEED); parameters.add(Params.VERBOSE); return parameters; } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/Grasp.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/Grasp.java index 13340438fd..796bf0758b 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/Grasp.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/Grasp.java @@ -76,6 +76,7 @@ public Graph search(DataModel dataModel, Parameters parameters) { test.setVerbose(parameters.getBoolean(Params.VERBOSE)); edu.cmu.tetrad.search.Grasp grasp = new edu.cmu.tetrad.search.Grasp(test, score); + grasp.setSeed(parameters.getLong(Params.SEED)); grasp.setDepth(parameters.getInt(Params.GRASP_DEPTH)); grasp.setUncoveredDepth(parameters.getInt(Params.GRASP_SINGULAR_DEPTH)); grasp.setNonSingularDepth(parameters.getInt(Params.GRASP_NONSINGULAR_DEPTH)); @@ -141,6 +142,7 @@ public List getParameters() { params.add(Params.USE_DATA_ORDER); params.add(Params.ALLOW_INTERNAL_RANDOMNESS); params.add(Params.TIME_LAG); + params.add(Params.SEED); params.add(Params.VERBOSE); // Parameters diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/RestrictedBoss.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/RestrictedBoss.java index 50f0ca4e39..95020839a2 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/RestrictedBoss.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/cpdag/RestrictedBoss.java @@ -97,6 +97,7 @@ public Graph search(DataModel dataModel, Parameters parameters) { boss.setUseBes(parameters.getBoolean(Params.USE_BES)); boss.setNumStarts(parameters.getInt(Params.NUM_STARTS)); PermutationSearch permutationSearch = new PermutationSearch(boss); + permutationSearch.setSeed(parameters.getLong(Params.SEED)); permutationSearch.setKnowledge(knowledge); permutationSearch.search(); @@ -169,6 +170,7 @@ public List getParameters() { params.add(Params.NUM_STARTS); params.add(Params.TARGETS); params.add(Params.TRIMMING_STYLE); + params.add(Params.SEED); return params; } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/pag/Bfci.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/pag/Bfci.java index c8c4f34f5c..9fb5c2d212 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/pag/Bfci.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/pag/Bfci.java @@ -22,6 +22,7 @@ import edu.cmu.tetrad.util.Params; import edu.pitt.dbmi.algo.resampling.GeneralResamplingTest; +import java.io.Serial; import java.util.ArrayList; import java.util.List; @@ -46,6 +47,7 @@ public class Bfci implements Algorithm, UsesScoreWrapper, TakesIndependenceWrapper, HasKnowledge, ReturnsBootstrapGraphs { + @Serial private static final long serialVersionUID = 23L; private IndependenceWrapper test; private ScoreWrapper score; @@ -85,6 +87,7 @@ public Graph search(DataModel dataModel, Parameters parameters) { BFci search = new BFci(this.test.getTest(dataModel, parameters), this.score.getScore(dataModel, parameters)); + search.setSeed(parameters.getLong(Params.SEED)); search.setBossUseBes(parameters.getBoolean(Params.USE_BES)); search.setMaxPathLength(parameters.getInt(Params.MAX_PATH_LENGTH)); search.setCompleteRuleSetUsed(parameters.getBoolean(Params.COMPLETE_RULE_SET_USED)); @@ -136,6 +139,7 @@ public List getParameters() { params.add(Params.DO_DISCRIMINATING_PATH_RULE); params.add(Params.DEPTH); params.add(Params.TIME_LAG); + params.add(Params.SEED); params.add(Params.VERBOSE); // Parameters diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/pag/GraspFci.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/pag/GraspFci.java index 1475820bbb..874b2ba97d 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/pag/GraspFci.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/algcomparison/algorithm/oracle/pag/GraspFci.java @@ -81,6 +81,7 @@ public Graph search(DataModel dataModel, Parameters parameters) { edu.cmu.tetrad.search.GraspFci search = new edu.cmu.tetrad.search.GraspFci(test, score); // GRaSP + search.setSeed(parameters.getLong(Params.SEED)); search.setDepth(parameters.getInt(Params.GRASP_DEPTH)); search.setSingularDepth(parameters.getInt(Params.GRASP_SINGULAR_DEPTH)); search.setNonSingularDepth(parameters.getInt(Params.GRASP_NONSINGULAR_DEPTH)); @@ -154,6 +155,9 @@ public List getParameters() { // General params.add(Params.TIME_LAG); + + params.add(Params.SEED); + params.add(Params.VERBOSE); return params; diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/BFci.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/BFci.java index 13c973f84c..adcd9d6cbd 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/BFci.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/BFci.java @@ -29,6 +29,7 @@ import edu.cmu.tetrad.search.utils.FciOrient; import edu.cmu.tetrad.search.utils.SepsetProducer; import edu.cmu.tetrad.search.utils.SepsetsGreedy; +import edu.cmu.tetrad.util.RandomUtil; import edu.cmu.tetrad.util.TetradLogger; import java.util.List; @@ -81,6 +82,7 @@ public final class BFci implements IGraphSearch { private int depth = -1; private boolean doDiscriminatingPathRule = true; private boolean bossUseBes = false; + private long seed = -1; /** @@ -107,6 +109,10 @@ public BFci(IndependenceTest test, Score score) { * @return The discovered graph. */ public Graph search() { + if (seed != -1) { + RandomUtil.getInstance().setSeed(seed); + } + List nodes = getIndependenceTest().getVariables(); this.logger.log("info", "Starting FCI algorithm."); @@ -229,4 +235,7 @@ public void setBossUseBes(boolean useBes) { this.bossUseBes = useBes; } + public void setSeed(long seed) { + this.seed = seed; + } } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Cstar.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Cstar.java index d2971f4a1f..f2076b5e9b 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Cstar.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Cstar.java @@ -599,6 +599,7 @@ private Graph getPatternFges(DataSet sample) { private Graph getPatternBoss(DataSet sample) { Score score = this.score.getScore(sample, parameters); PermutationSearch boss = new PermutationSearch(new Boss(score)); + boss.setSeed(parameters.getLong(Params.SEED)); return boss.search(); } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fask.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fask.java index b8026db1d9..ee85566a22 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fask.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Fask.java @@ -174,6 +174,7 @@ public final class Fask implements IGraphSearch { private LeftRight leftRight = LeftRight.RSKEW; // The graph resulting from search. private Graph graph; + private long seed = -1; /** * Constructor. @@ -313,10 +314,12 @@ public Graph search() { if (this.adjacencyMethod == AdjacencyMethod.BOSS) { PermutationSearch fas = new PermutationSearch(new Boss(this.score)); + fas.setSeed(seed); fas.setKnowledge(this.knowledge); G = fas.search(); } else if (this.adjacencyMethod == AdjacencyMethod.GRASP) { Grasp fas = new Grasp(this.score); + fas.setSeed(seed); fas.setDepth(5); fas.setNonSingularDepth(1); fas.setUncoveredDepth(1); @@ -853,6 +856,10 @@ private void logTwoCycle(NumberFormat nf, List variables, double[][] d, No ); } + public void setSeed(long seed) { + this.seed = seed; + } + /** * Enumerates the options left-right rules to use for FASK. Options include the FASK left-right rule and three * left-right rules from the Hyvarinen and Smith pairwise orientation paper: Robust Skew, Skew, and Tanh. In that diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Grasp.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Grasp.java index f22e4c0215..6f38486952 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Grasp.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Grasp.java @@ -85,6 +85,7 @@ public class Grasp { private int numStarts = 1; // Whether to allow internal randomness in the algorithm. private boolean allowInternalRandomness = false; + private long seed = -1; /** * Constructor for a score. @@ -128,6 +129,10 @@ public Grasp(@NotNull IndependenceTest test, Score score) { * @return The discovered permutation at the end of the procedure. */ public List bestOrder(@NotNull List order) { + if (seed != -1) { + RandomUtil.getInstance().setSeed(seed); + } + long start = MillisecondTimes.timeMillis(); order = new ArrayList<>(order); @@ -521,4 +526,8 @@ private void graspDfs(@NotNull TeyssierScorer scorer, double sOld, int[] depth, } } } + + public void setSeed(long seed) { + this.seed = seed; + } } \ No newline at end of file diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/GraspFci.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/GraspFci.java index ca9ddd6f21..ac08a4e0b3 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/GraspFci.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/GraspFci.java @@ -94,6 +94,7 @@ public final class GraspFci implements IGraphSearch { private int uncoveredDepth = 1; // The depth for non-singular variables. private int nonSingularDepth = 1; + private long seed = -1; /** * Constructs a new GraspFci object. @@ -128,6 +129,7 @@ public Graph search() { // The PAG being constructed. // Run GRaSP to get a CPDAG (like GFCI with FGES)... Grasp alg = new Grasp(independenceTest, score); + alg.setSeed(seed); alg.setOrdered(ordered); alg.setUseScore(useScore); alg.setUseRaskuttiUhler(useRaskuttiUhler); @@ -291,4 +293,8 @@ public void setNonSingularDepth(int nonSingularDepth) { public void setOrdered(boolean ordered) { this.ordered = ordered; } + + public void setSeed(long seed) { + this.seed = seed; + } } diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Mimbuild.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Mimbuild.java index a93065d59a..fc44b3314a 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Mimbuild.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Mimbuild.java @@ -86,6 +86,7 @@ public class Mimbuild { private double penaltyDiscount = 1; // jf Clusters smaller than this size will be tossed out. private int minClusterSize = 3; + private long seed = -1; /** * Constructs a new Mimbuild search. @@ -151,6 +152,7 @@ public Graph search(List> clustering, List latentNames, ICova SemBicScore score = new SemBicScore(latentscov); score.setPenaltyDiscount(this.penaltyDiscount); Grasp search = new Grasp(score); + search.setSeed(seed); search.setKnowledge(this.knowledge); search.bestOrder(latentscov.getVariables()); graph = search.getGraph(true); @@ -511,6 +513,10 @@ private double sumOfDifferences(int[][] indicatorIndices, Matrix cov, double[][] return sum; } + public void setSeed(long seed) { + this.seed = seed; + } + private class Function1 implements org.apache.commons.math3.analysis.MultivariateFunction { private final int[][] indicatorIndices; private final Matrix measurescov; diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/PermutationSearch.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/PermutationSearch.java index ec54d8db43..90ec4f9cfc 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/PermutationSearch.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/PermutationSearch.java @@ -7,6 +7,7 @@ import edu.cmu.tetrad.search.score.Score; import edu.cmu.tetrad.search.utils.GrowShrinkTree; import edu.cmu.tetrad.search.utils.MeekRules; +import edu.cmu.tetrad.util.RandomUtil; import java.util.*; @@ -34,6 +35,7 @@ public class PermutationSearch { private final List order; private final Map gsts; private Knowledge knowledge = new Knowledge(); + private long seed = -1; /** * Constructs a new PermutationSearch using the given SuborderSearch. @@ -107,6 +109,10 @@ public static Graph getGraph(List nodes, Map> parents, Kno * @return The CPDAG. */ public Graph search() { + if (this.seed != -1) { + RandomUtil.getInstance().setSeed(this.seed); + } + List prefix; if (!this.knowledge.isEmpty() && this.knowledge.getVariablesNotInTiers().isEmpty()) { List order = new ArrayList<>(this.order); @@ -183,4 +189,8 @@ public void setKnowledge(Knowledge knowledge) { this.gsts.get(node).setKnowledge(required, forbidden); } } + + public void setSeed(long seed) { + this.seed = seed; + } } \ No newline at end of file From c288b6193bc6cfa857c5866f6c2802044fcab868 Mon Sep 17 00:00:00 2001 From: jdramsey Date: Fri, 2 Feb 2024 01:51:16 -0500 Subject: [PATCH 161/163] Cleanup. --- .../java/edu/cmu/tetrad/search/Mimbuild.java | 32 +++++++++---------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Mimbuild.java b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Mimbuild.java index fc44b3314a..2e3ee1c672 100644 --- a/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Mimbuild.java +++ b/tetrad-lib/src/main/java/edu/cmu/tetrad/search/Mimbuild.java @@ -42,23 +42,21 @@ import java.util.List; /** - * Provides an implementation of Mimbuild, an algorithm that takes a clustering - * of variables, each of which is explained by a single latent, then forms the implied covariance matrix over the latent - * variables, then runs a CPDAG search to in the structure over the latent themselves. - * - * Specifically, the search will first infer the covariance matrix over the - * latents and then will use the GRaSP algorithm (see) to infer the structure graph over the latents, using the SEM Bic - * score with the given penalty discount (default 2). - * - * One may wish to obtain the implied correlation matrix over the latents and - * run one's own choice of CPDAG algorithm on it with one's own test or score; a method is available to return this - * covariance matrix. - * - * A suitable clustering for Mimbuild may be obtained using the BPC or FOFC - * algorithm (see). - * - * This class is configured to respect the knowledge of forbidden and required - * edges, including knowledge of temporal tiers. + * Provides an implementation of Mimbuild, an algorithm that takes a clustering of variables, each of which is explained + * by a single latent, then forms the implied covariance matrix over the latent variables, then runs a CPDAG search to + * in the structure over the latent themselves. + *

                + * Specifically, the search will first infer the covariance matrix over the latents and then will use the GRaSP + * algorithm (see) to infer the structure graph over the latents, using the SEM Bic score with the given penalty + * discount (default 2). + *

                + * One may wish to obtain the implied correlation matrix over the latents and run one's own choice of CPDAG algorithm on + * it with one's own test or score; a method is available to return this covariance matrix. + *

                + * A suitable clustering for Mimbuild may be obtained using the BPC or FOFC algorithm (see). + *

                + * This class is configured to respect the knowledge of forbidden and required edges, including knowledge of temporal + * tiers. * * @author josephramsey * @see Bpc From aa58a8afc9d6bdbf7a42a8400afa773f74c6b61b Mon Sep 17 00:00:00 2001 From: Kevin Bui Date: Fri, 2 Feb 2024 02:04:35 -0500 Subject: [PATCH 162/163] Fixed GUI layout. --- .../tetradapp/editor/MarkovCheckEditor.java | 221 ++++++++++-------- 1 file changed, 119 insertions(+), 102 deletions(-) diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java index b7718d5cd0..c12f76cdb7 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/MarkovCheckEditor.java @@ -18,7 +18,6 @@ // along with this program; if not, write to the Free Software // // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // /////////////////////////////////////////////////////////////////////////////// - package edu.cmu.tetradapp.editor; import edu.cmu.tetrad.algcomparison.independence.IndependenceWrapper; @@ -38,38 +37,39 @@ import edu.cmu.tetradapp.ui.model.IndependenceTestModel; import edu.cmu.tetradapp.ui.model.IndependenceTestModels; import edu.cmu.tetradapp.util.*; -import org.jetbrains.annotations.NotNull; - -import javax.swing.*; -import javax.swing.border.EmptyBorder; -import javax.swing.table.AbstractTableModel; -import javax.swing.table.DefaultTableCellRenderer; -import javax.swing.table.JTableHeader; -import java.awt.Point; +import static edu.cmu.tetradapp.util.ParameterComponents.toArray; import java.awt.*; +import java.awt.Point; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.lang.reflect.InvocationTargetException; import java.text.DecimalFormat; import java.text.NumberFormat; -import java.util.List; import java.util.*; +import java.util.List; import java.util.function.Function; import java.util.stream.Collectors; - -import static edu.cmu.tetradapp.util.ParameterComponents.toArray; - +import javax.swing.*; +import javax.swing.border.EmptyBorder; +import javax.swing.table.AbstractTableModel; +import javax.swing.table.DefaultTableCellRenderer; +import javax.swing.table.JTableHeader; +import org.jetbrains.annotations.NotNull; /** - * A model for the Markov check. The Markov check for a given graph and dataset checks whether the graph is Markov with - * respect to the dataset. The Markov check can be used to check whether a graph is Markov with respect to a dataset, or - * whether a graph is Markov with respect to a dataset and a set of variables. The Markov check can also be used to - * check whether a graph is Markov with respect to a dataset and a set of variables, given a set of knowledge. For facts - * of the form X _||_ Y | Z, X and Y should be in the last tier of the knowledge, and Z should be in previous tiers. + * A model for the Markov check. The Markov check for a given graph and dataset + * checks whether the graph is Markov with respect to the dataset. The Markov + * check can be used to check whether a graph is Markov with respect to a + * dataset, or whether a graph is Markov with respect to a dataset and a set of + * variables. The Markov check can also be used to check whether a graph is + * Markov with respect to a dataset and a set of variables, given a set of + * knowledge. For facts of the form X _||_ Y | Z, X and Y should be in the last + * tier of the knowledge, and Z should be in previous tiers. * * @author josephramsey */ public class MarkovCheckEditor extends JPanel { + private final MarkovCheckIndTestModel model; private final NumberFormat nf = NumberFormatUtil.getInstance().getNumberFormat(); private final JLabel markovTestLabel = new JLabel("(Unspecified Test)"); @@ -126,16 +126,17 @@ public MarkovCheckEditor(MarkovCheckIndTestModel model) { model.getMarkovCheck().setSetType(ConditioningSetType.GLOBAL_MARKOV); break; default: - throw new IllegalArgumentException("Unknown conditioning set type: " + - conditioningSetTypeJComboBox.getSelectedItem()); + throw new IllegalArgumentException("Unknown conditioning set type: " + + conditioningSetTypeJComboBox.getSelectedItem()); } class MyWatchedProcess extends WatchedProcess { + public void watch() { if (model.getMarkovCheck().getSetType() == ConditioningSetType.GLOBAL_MARKOV && model.getVars().size() > 12) { int ret = JOptionPane.showOptionDialog(MarkovCheckEditor.this, - "The all subsets option is exponential and can become extremely slow beyond 12" + - "\nvariables. You may possibly be required to force quit Tetrad. Continue?", "Warning", + "The all subsets option is exponential and can become extremely slow beyond 12" + + "\nvariables. You may possibly be required to force quit Tetrad. Continue?", "Warning", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, null, null, null ); @@ -169,6 +170,7 @@ public void watch() { indTestJComboBox.addActionListener(e -> { class MyWatchedProcess extends WatchedProcess { + public void watch() { setTest(); model.getMarkovCheck().generateResults(); @@ -219,42 +221,33 @@ public void watch() { for (Node w : sourceGraph.getNodes()) { if (model.getMarkovCheck().getVariable(w.getName()) == null) { missingVars.add(w); - if (missingVars.size() >= 5) break; + if (missingVars.size() >= 5) { + break; + } } } if (!missingVars.isEmpty()) { - throw new IllegalArgumentException("At least these variables in the DAG are missing from the data:" + - "\n " + missingVars); + throw new IllegalArgumentException("At least these variables in the DAG are missing from the data:" + + "\n " + missingVars); } model.setVars(graph.getNodeNames()); - Box box = Box.createVerticalBox(); - Box box1 = Box.createHorizontalBox(); - box1.add(Box.createHorizontalStrut(20)); - box1.add(new JLabel("Test:")); - box1.add(indTestJComboBox); - box1.add(Box.createHorizontalGlue()); JButton params = new JButton("Params"); - box1.add(params); JButton recalculate = new JButton("Recalculate"); - box1.add(recalculate); this.percent = new DoubleTextField(0.5, 4, new DecimalFormat("0.0###")); + JLabel percentSampleLabel; if (model.getMarkovCheck().getIndependenceTest().getData() != null) { - box1.add(new JLabel("% Sample:")); - box1.add(percent); - } else if (!(model.getMarkovCheck().getIndependenceTest() instanceof RowsSettable)) { - box1.add(new JLabel("(Test cannot be subsampled)")); - box1.add(percent); + percentSampleLabel = new JLabel("% Sample:"); + } else if (!(model.getMarkovCheck().getIndependenceTest() instanceof RowsSettable)) { + percentSampleLabel = new JLabel("(Test cannot be subsampled)"); } else { - box1.add(new JLabel("(Not tabular data)")); + percentSampleLabel = new JLabel("(Not tabular data)"); } - box1.add(Box.createHorizontalGlue()); - recalculate.addActionListener(e -> refreshResult(model, percent)); percent.setFilter((value, oldValue) -> { @@ -282,14 +275,7 @@ public void watch() { new MyWatchedProcess2(); }); - box.add(box1); - - Box box2 = Box.createHorizontalBox(); - box2.add(Box.createHorizontalStrut(20)); - box2.add(new JLabel("Conditioning Sets:")); - box2.add(conditioningSetTypeJComboBox); - box2.add(Box.createHorizontalGlue()); - box.add(box2); + JLabel conditioningSetsLabel = new JLabel("Conditioning Sets:"); JTextArea testDescTextArea = new JTextArea(getHelpMessage()); testDescTextArea.setEditable(true); @@ -301,10 +287,10 @@ public void watch() { JTabbedPane pane = new JTabbedPane(); pane.addTab("Check Markov", indep); pane.addTab("Check Dependent Distribution", dep); - pane.addTab("Help", scroll); - box.add(pane); + pane.addTab("Help", new PaddingPanel(scroll)); class MyWatchedProcess extends WatchedProcess { + public void watch() { setTest(); model.getMarkovCheck().generateResults(); @@ -323,7 +309,57 @@ public void watch() { } new MyWatchedProcess(); - add(box); + // add(box); + initComponents(params, recalculate, pane, conditioningSetsLabel, percentSampleLabel); + } + + private void initComponents(JButton params, JButton recalculate, JTabbedPane pane, JLabel conditioningSetsLabel, JLabel percentSampleLabel) { + GroupLayout layout = new GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(pane) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(conditioningSetsLabel) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addComponent(conditioningSetTypeJComboBox, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)) + .addGroup(layout.createSequentialGroup() + .addComponent(testLabel) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addComponent(indTestJComboBox, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addComponent(params) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addComponent(recalculate) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addComponent(percentSampleLabel) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addComponent(percent, GroupLayout.PREFERRED_SIZE, 46, GroupLayout.PREFERRED_SIZE))) + .addGap(0, 0, Short.MAX_VALUE))) + .addContainerGap()) + ); + layout.setVerticalGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE) + .addComponent(testLabel) + .addComponent(indTestJComboBox, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) + .addComponent(params) + .addComponent(recalculate) + .addComponent(percentSampleLabel) + .addComponent(percent, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE) + .addComponent(conditioningSetTypeJComboBox, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) + .addComponent(conditioningSetsLabel)) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addComponent(pane, GroupLayout.DEFAULT_SIZE, 442, Short.MAX_VALUE) + .addContainerGap()) + ); } @NotNull @@ -344,7 +380,7 @@ If the first bar in this histogram is especially high (for the p-value case), th Feel free to select all of the data in the tables, copy it, and paste it into a text file or into Excel. This will let you analyze the data yourself. A note about Markov Blankets: The "Markov Blanket" conditioning set choice implements the Markov blanket calculation in a way that is correct for DAGs, CPDAGs, MAGs, and PAGs. For all of these graph types, the list of m-connecting facts in the Faithfulness tab should be empty, since the Markov blanket should screen off the target from any other variables in the dataset. It's possible that for some other graph types, this list may not be empty (i.e., the Markov blanket calculation may not be correct). - + Knowledge may be supplied to the Markov Checker. This will be interpreted as follows. For X _||_ Y | Z checked, X and Y will be drawn from the last tier of the knowledge, and the variables in Z will be drawn from all variables in tiers. Additional forbidden or required edges are not allowed. """; } @@ -369,7 +405,6 @@ private static HistogramPanel getHistogramPanel(List results } //========================PUBLIC METHODS==========================// - private void refreshResult(MarkovCheckIndTestModel model, DoubleTextField percent) { setTest(); @@ -402,25 +437,22 @@ private void setTest() { testLabel.setText(model.getMarkovCheck().getIndependenceTest().toString()); invalidate(); repaint(); - } catch (InstantiationException | IllegalAccessException | InvocationTargetException | - NoSuchMethodException e1) { + } catch (InstantiationException | IllegalAccessException | InvocationTargetException + | NoSuchMethodException e1) { TetradLogger.getInstance().forceLogMessage("Error: " + e1.getMessage()); throw new RuntimeException(e1); } } - } private JPanel buildGuiIndep() { - Box a1 = Box.createVerticalBox(); - Box a2 = Box.createHorizontalBox(); + JPanel tablelPanel = new JPanel(new BorderLayout()); + String setType = (String) conditioningSetTypeJComboBox.getSelectedItem(); conditioningLabelIndep.setText("Tests graphical predictions of Indep(X, Y | " + setType + ")"); - a2.add(conditioningLabelIndep); - a2.add(Box.createHorizontalGlue()); - a1.add(a2); + tablelPanel.add(conditioningLabelIndep, BorderLayout.NORTH); markovTestLabel.setText(model.getMarkovCheck().getIndependenceTest().toString()); testLabel.setText(model.getMarkovCheck().getIndependenceTest().toString()); @@ -450,7 +482,9 @@ public int getRowCount() { } public Object getValueAt(int rowIndex, int columnIndex) { - if (rowIndex > model.getResults(true).size()) return null; + if (rowIndex > model.getResults(true).size()) { + return null; + } if (columnIndex == 0) { return rowIndex + 1; @@ -535,13 +569,10 @@ public void mouseClicked(MouseEvent e) { }); JScrollPane scroll = new JScrollPane(table); - a1.add(scroll); + tablelPanel.add(scroll, BorderLayout.CENTER); - Box a3 = Box.createHorizontalBox(); JLabel label = new JLabel("Table contents can be selected and copied in to, e.g., Excel."); - a3.add(label); - a3.add(Box.createHorizontalGlue()); - a1.add(a3); + tablelPanel.add(label, BorderLayout.SOUTH); setLabelTexts(); @@ -577,38 +608,28 @@ public void mouseClicked(MouseEvent e) { a9.add(andersonDarlingPLabelIndep); a4.add(a9); - Box a11 = Box.createHorizontalBox(); - a11.add(a1); - a11.add(a4); - - JPanel panel = new JPanel(); - panel.setLayout(new BorderLayout()); - panel.add(a11, BorderLayout.CENTER); + JPanel checkMarkovPanel = new JPanel(new BorderLayout()); + checkMarkovPanel.add(new PaddingPanel(tablelPanel), BorderLayout.CENTER); + checkMarkovPanel.add(new PaddingPanel(a4), BorderLayout.EAST); - panel.setBorder(new EmptyBorder(10, 10, 10, 10)); - return panel; + return checkMarkovPanel; } - /** * Performs the action of opening a session from a file. */ private JPanel buildGuiDep() { - Box a1 = Box.createVerticalBox(); - Box a2 = Box.createHorizontalBox(); + JPanel tablelPanel = new JPanel(new BorderLayout()); + String setType = (String) conditioningSetTypeJComboBox.getSelectedItem(); conditioningLabelDep.setText("Tests graphical predictions of Dep(X, Y | " + setType + ")"); - - a2.add(conditioningLabelDep); - a2.add(Box.createHorizontalGlue()); - a1.add(a2); + tablelPanel.add(conditioningLabelDep, BorderLayout.NORTH); markovTestLabel.setText(model.getMarkovCheck().getIndependenceTest().toString()); testLabel.setText(model.getMarkovCheck().getIndependenceTest().toString()); // a1.add(Box.createVerticalStrut(5)); - this.tableModelDep = new AbstractTableModel() { public String getColumnName(int column) { if (column == 0) { @@ -634,7 +655,9 @@ public int getRowCount() { } public Object getValueAt(int rowIndex, int columnIndex) { - if (rowIndex > model.getResults(true).size()) return null; + if (rowIndex > model.getResults(true).size()) { + return null; + } if (columnIndex == 0) { return rowIndex + 1; @@ -719,13 +742,13 @@ public void mouseClicked(MouseEvent e) { }); JScrollPane scroll = new JScrollPane(table); - a1.add(scroll); + tablelPanel.add(scroll, BorderLayout.CENTER); Box a3 = Box.createHorizontalBox(); JLabel label = new JLabel("Table contents can be selected and copied in to, e.g., Excel."); a3.add(label); a3.add(Box.createHorizontalGlue()); - a1.add(a3); + tablelPanel.add(label, BorderLayout.SOUTH); setLabelTexts(); @@ -762,15 +785,13 @@ public void mouseClicked(MouseEvent e) { a4.add(a9); Box a11 = Box.createHorizontalBox(); - a11.add(a1); a11.add(a4); - JPanel panel = new JPanel(); - panel.setLayout(new BorderLayout()); - panel.add(a11, BorderLayout.CENTER); + JPanel checkDependDistributionPanel = new JPanel(new BorderLayout()); + checkDependDistributionPanel.add(new PaddingPanel(tablelPanel), BorderLayout.CENTER); + checkDependDistributionPanel.add(new PaddingPanel(a4), BorderLayout.EAST); - panel.setBorder(new EmptyBorder(10, 10, 10, 10)); - return panel; + return checkDependDistributionPanel; } private void sortByColumn(int sortCol, boolean indep) { @@ -1024,7 +1045,7 @@ private Box createParameterComponent(String parameter, Parameters parameters, Pa } private DoubleTextField getDoubleField(String parameter, Parameters parameters, - double defaultValue, double lowerBound, double upperBound) { + double defaultValue, double lowerBound, double upperBound) { DoubleTextField field = new DoubleTextField(parameters.getDouble(parameter, defaultValue), 8, new DecimalFormat("0.####"), new DecimalFormat("0.0#E0"), 0.001); @@ -1054,7 +1075,7 @@ private DoubleTextField getDoubleField(String parameter, Parameters parameters, } private IntTextField getIntTextField(String parameter, Parameters parameters, - int defaultValue, double lowerBound, double upperBound) { + int defaultValue, double lowerBound, double upperBound) { IntTextField field = new IntTextField(parameters.getInt(parameter, defaultValue), 8); field.setFilter((value, oldValue) -> { @@ -1083,7 +1104,7 @@ private IntTextField getIntTextField(String parameter, Parameters parameters, } private LongTextField getLongTextField(String parameter, Parameters parameters, - long defaultValue, long lowerBound, long upperBound) { + long defaultValue, long lowerBound, long upperBound) { LongTextField field = new LongTextField(parameters.getLong(parameter, defaultValue), 8); field.setFilter((value, oldValue) -> { @@ -1176,6 +1197,7 @@ private StringTextField getStringField(String parameter, Parameters parameters, } static class Renderer extends DefaultTableCellRenderer { + private JTable table; private boolean selected; @@ -1203,8 +1225,3 @@ public Component getTableCellRendererComponent(JTable table, Object value, boole } } - - - - - From ae8eed6781de45a649e643fd1e1ebe439b644f7c Mon Sep 17 00:00:00 2001 From: jdramsey Date: Fri, 2 Feb 2024 03:28:42 -0500 Subject: [PATCH 163/163] Added a feature to copy the selected dataset from a data box with multiple data models into a separate box. --- .../editor/SplitCasesParamsEditor.java | 2 +- .../java/edu/cmu/tetradapp/model/LogData.java | 15 ++-- .../cmu/tetradapp/model/SelectedDataset.java | 70 +++++++++++++++++++ .../model/datamanip/SplitCasesWrapper.java | 4 +- .../src/main/resources/config/devConfig.xml | 11 +++ .../src/main/resources/config/prodConfig.xml | 11 +++ 6 files changed, 107 insertions(+), 6 deletions(-) create mode 100644 tetrad-gui/src/main/java/edu/cmu/tetradapp/model/SelectedDataset.java diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/SplitCasesParamsEditor.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/SplitCasesParamsEditor.java index c2dc5538c3..4500d53593 100755 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/SplitCasesParamsEditor.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/editor/SplitCasesParamsEditor.java @@ -133,7 +133,7 @@ public void setup() { splitEditorPanel = new JPanel(); splitEditorPanel.setLayout(new BorderLayout()); - this.setNumSplits(params.getInt("numSplits", 3)); + this.setNumSplits(params.getInt("numSplits", 2)); JRadioButton shuffleButton = new JRadioButton("Shuffled order"); JRadioButton noShuffleButton = new JRadioButton("Original order"); diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/LogData.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/LogData.java index f0832b3830..6b2346a430 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/LogData.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/LogData.java @@ -25,27 +25,34 @@ import edu.cmu.tetrad.util.Parameters; import edu.cmu.tetrad.util.TetradSerializableUtils; +import java.io.Serial; + /** - * Applies a logarithmic transform + * Applies a logarithmic transform. * * @author Jeremy Espino */ public class LogData extends DataWrapper { + @Serial private static final long serialVersionUID = 23L; //=============================CONSTRUCTORS==============================// + /** + * Applies a logarithmic transform to the data. + * + * @param wrapper The data to transform. + * @param params The parameters for the transformation. + */ public LogData(DataWrapper wrapper, Parameters params) { DataModelList inList = wrapper.getDataModelList(); DataModelList outList = new DataModelList(); for (DataModel model : inList) { - if (!(model instanceof DataSet)) { + if (!(model instanceof DataSet dataSet)) { throw new IllegalArgumentException("Not a data set: " + model.getName()); } - DataSet dataSet = (DataSet) model; - double a = params.getDouble("a"); boolean isUnlog = params.getBoolean("unlog"); int base = params.getInt("base"); diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/SelectedDataset.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/SelectedDataset.java new file mode 100644 index 0000000000..bf11b0dbca --- /dev/null +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/SelectedDataset.java @@ -0,0 +1,70 @@ +/////////////////////////////////////////////////////////////////////////////// +// For information as to what this class does, see the Javadoc, below. // +// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, // +// 2007, 2008, 2009, 2010, 2014, 2015, 2022 by Peter Spirtes, Richard // +// Scheines, Joseph Ramsey, and Clark Glymour. // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation; either version 2 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program; if not, write to the Free Software // +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // +/////////////////////////////////////////////////////////////////////////////// + +package edu.cmu.tetradapp.model; + +import edu.cmu.tetrad.data.*; +import edu.cmu.tetrad.util.Parameters; +import edu.cmu.tetrad.util.TetradSerializableUtils; + +import java.io.Serial; + +/** + * Extracts a single dataset from a data box containing multiple datasets. + * + * @author josephramsey + */ +public class SelectedDataset extends DataWrapper { + @Serial + private static final long serialVersionUID = 23L; + + //=============================CONSTRUCTORS==============================// + + /** + * Applies a logarithmic transform to the data. + * + * @param wrapper The data to transform. + * @param params The parameters for the transformation. + */ + public SelectedDataset(DataWrapper wrapper, Parameters params) { + DataModelList inList = wrapper.getDataModelList(); + DataModelList outList = new DataModelList(); + DataModel selected = inList.getSelectedModel(); + outList.add(selected); + setDataModel(outList); + setSourceGraph(wrapper.getSourceGraph()); + LogDataUtils.logDataModelList("Extracted Data Model", getDataModelList()); + + } + + /** + * Generates a simple exemplar of this class to test serialization. + * + * @see TetradSerializableUtils + */ + public static PcRunner serializableInstance() { + return PcRunner.serializableInstance(); + } + +} + + + diff --git a/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/datamanip/SplitCasesWrapper.java b/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/datamanip/SplitCasesWrapper.java index e0807e838d..efa88ea5f0 100644 --- a/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/datamanip/SplitCasesWrapper.java +++ b/tetrad-gui/src/main/java/edu/cmu/tetradapp/model/datamanip/SplitCasesWrapper.java @@ -28,6 +28,7 @@ import edu.cmu.tetradapp.model.DataWrapper; import edu.cmu.tetradapp.model.PcRunner; +import java.io.Serial; import java.util.ArrayList; import java.util.List; @@ -37,6 +38,7 @@ * @author Tyler Gibson */ public class SplitCasesWrapper extends DataWrapper { + @Serial private static final long serialVersionUID = 23L; /** @@ -82,7 +84,7 @@ private static DataModel createSplits(DataSet dataSet, Parameters params) { } SplitCasesSpec spec = (SplitCasesSpec) params.get("splitCasesSpec", null); - int numSplits = params.getInt("numSplits", 3); + int numSplits = params.getInt("numSplits", 2); int sampleSize = spec.getSampleSize(); int[] breakpoints = spec.getBreakpoints(); List splitNames = spec.getSplitNames(); diff --git a/tetrad-gui/src/main/resources/config/devConfig.xml b/tetrad-gui/src/main/resources/config/devConfig.xml index 226049fdb6..d77283ca49 100644 --- a/tetrad-gui/src/main/resources/config/devConfig.xml +++ b/tetrad-gui/src/main/resources/config/devConfig.xml @@ -436,6 +436,17 @@ edu.cmu.tetradapp.editor.DataEditor + + + + + + + edu.cmu.tetradapp.model.SelectedDataset + + edu.cmu.tetradapp.editor.DataEditor + diff --git a/tetrad-gui/src/main/resources/config/prodConfig.xml b/tetrad-gui/src/main/resources/config/prodConfig.xml index 48a4b2f1aa..8c4c51bb8c 100644 --- a/tetrad-gui/src/main/resources/config/prodConfig.xml +++ b/tetrad-gui/src/main/resources/config/prodConfig.xml @@ -409,6 +409,17 @@ edu.cmu.tetradapp.editor.DataEditor + + + + + + + edu.cmu.tetradapp.model.SelectedDataset + + edu.cmu.tetradapp.editor.DataEditor +