edu.cmu.tetradapp.editor.RandomGraphEditor Maven / Gradle / Ivy
The newest version!
///////////////////////////////////////////////////////////////////////////////
// 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.EdgeListGraph;
import edu.cmu.tetrad.graph.Graph;
import edu.cmu.tetrad.graph.Node;
import edu.cmu.tetrad.graph.NodeType;
import edu.cmu.tetrad.util.Parameters;
import edu.cmu.tetradapp.util.IntTextField;
import org.apache.commons.math3.util.FastMath;
import javax.swing.*;
import javax.swing.border.TitledBorder;
import java.awt.*;
/**
* Edits the parameters for generating random graphs.
*
* @author josephramsey
*/
class RandomGraphEditor extends JPanel {
private final Parameters parameters;
private final IntTextField numNodesField;
private final IntTextField numLatentsField;
private final IntTextField maxEdgesField;
private final IntTextField maxIndegreeField;
private final IntTextField maxOutdegreeField;
private final IntTextField maxDegreeField;
// private final JRadioButton chooseUniform;
private final JRadioButton chooseFixed;
private final JComboBox connectedBox;
private final IntTextField numTwoCyclesField;
private final IntTextField minCycleLengthField;
/**
* Constructs a dialog to edit the given workbench randomization parameters.
*
* @param cyclicAllowed a boolean
* @param parameters a {@link edu.cmu.tetrad.util.Parameters} object
*/
public RandomGraphEditor(boolean cyclicAllowed, Parameters parameters) {
this(new EdgeListGraph(), cyclicAllowed, parameters);
}
/**
* Constructs a dialog to edit the given workbench randomization parameters. // * @param preferredNumNodes an
* integer which, if greater than 1, will revise the number of nodes, // * number of edges,a nd number of latent
* nodes. Useful if the interface suggests a number of nodes // * that overrides the number of nodes set in the
* preferences.
*
* @param oldGraph a {@link edu.cmu.tetrad.graph.Graph} object
* @param cyclicAllowed a boolean
* @param parameters a {@link edu.cmu.tetrad.util.Parameters} object
*/
public RandomGraphEditor(Graph oldGraph, boolean cyclicAllowed, Parameters parameters) {
if (parameters == null) {
throw new NullPointerException();
}
this.parameters = parameters;
int oldNumMeasured = 0;
int oldNumLatents = 0;
for (Node node : oldGraph.getNodes()) {
if (node.getNodeType() == NodeType.LATENT) {
oldNumMeasured++;
}
if (node.getNodeType() == NodeType.LATENT) {
oldNumLatents++;
}
}
int oldNumNodes = oldNumMeasured + oldNumLatents;
if (oldNumNodes > 1 && oldNumMeasured == getNumMeasuredNodes() &&
oldNumLatents == getNumLatents()) {
setNumMeasuredNodes(oldNumMeasured);
setNumLatents(oldNumLatents);
setMaxEdges(
FastMath.min(getMaxEdges(), oldNumNodes * (oldNumNodes - 1) / 2));
}
this.numNodesField = new IntTextField(getNumMeasuredNodes(), 4);
this.numLatentsField = new IntTextField(getNumLatents(), 4);
this.maxEdgesField = new IntTextField(getMaxEdges(), 4);
this.maxIndegreeField = new IntTextField(getMaxIndegree(), 4);
this.maxOutdegreeField = new IntTextField(getMaxOutdegree(), 4);
this.maxDegreeField = new IntTextField(getMaxDegree(), 4);
// JRadioButton randomForward = new JRadioButton("Add random forward edges");
// this.chooseUniform = new JRadioButton("Draw uniformly from all such DAGs");
this.chooseFixed = new JRadioButton("Guarantee maximum number of edges");
this.connectedBox = new JComboBox<>(new String[]{"No", "Yes"});
JComboBox addCyclesBox = new JComboBox<>(new String[]{"No", "Yes"});
this.numTwoCyclesField = new IntTextField(getMinNumCycles(), 4);
this.minCycleLengthField = new IntTextField(getMinCycleLength(), 4);
// ButtonGroup group = new ButtonGroup();
// group.add(randomForward);
//// group.add(this.chooseUniform);
// group.add(this.chooseFixed);
// randomForward.setSelected(true);
//// this.chooseUniform.setSelected(isUniformlySelected());
// this.chooseFixed.setSelected(isChooseFixed());
// set up text and ties them to the parameters object being edited.
this.numNodesField.setFilter((value, oldValue) -> {
if (value == numNodesField.getValue()) {
return oldValue;
}
try {
RandomGraphEditor.this.setNumMeasuredNodes(value);
} catch (Exception e) {
// Ignore.
}
maxEdgesField.setValue(RandomGraphEditor.this.getMaxEdges());
return value;
});
numLatentsField.setFilter((value, oldValue) -> {
if (value == numLatentsField.getValue()) {
return oldValue;
}
try {
RandomGraphEditor.this.setNumLatents(value);
} catch (Exception e) {
// Ignore.
}
maxEdgesField.setValue(RandomGraphEditor.this.getMaxEdges());
return value;
});
maxEdgesField.setFilter((value, oldValue) -> {
if (value == maxEdgesField.getValue()) {
return oldValue;
}
try {
RandomGraphEditor.this.setMaxEdges(value);
} catch (Exception e) {
// Ignore.
}
return value;
});
maxIndegreeField.setFilter((value, oldValue) -> {
if (value == maxIndegreeField.getValue()) {
return oldValue;
}
try {
RandomGraphEditor.this.setMaxIndegree(value);
} catch (Exception e) {
// Ignore.
}
maxOutdegreeField.setValue(RandomGraphEditor.this.getMaxOutdegree());
return value;
});
maxOutdegreeField.setFilter((value, oldValue) -> {
if (value == maxOutdegreeField.getValue()) {
return oldValue;
}
try {
RandomGraphEditor.this.setMaxOutdegree(value);
} catch (Exception e) {
// Ignore.
}
maxIndegreeField.setValue(RandomGraphEditor.this.getMaxIndegree());
maxDegreeField.setValue(RandomGraphEditor.this.getMaxDegree());
return value;
});
maxDegreeField.setFilter((value, oldValue) -> {
if (value == maxDegreeField.getValue()) {
return oldValue;
}
try {
RandomGraphEditor.this.setMaxDegree(value);
} catch (Exception e) {
// Ignore.
}
maxIndegreeField.setValue(RandomGraphEditor.this.getMaxIndegree());
maxOutdegreeField.setValue(RandomGraphEditor.this.getMaxOutdegree());
return value;
});
if (this.isConnected()) {
connectedBox.setSelectedItem("Yes");
} else {
connectedBox.setSelectedItem("No");
}
// if (this.isUniformlySelected() || this.isChooseFixed()) {
maxIndegreeField.setEnabled(true);
maxOutdegreeField.setEnabled(true);
maxDegreeField.setEnabled(true);
connectedBox.setEnabled(true);
// } else {
// maxIndegreeField.setEnabled(false);
// maxOutdegreeField.setEnabled(false);
// maxDegreeField.setEnabled(false);
// connectedBox.setEnabled(false);
// }
minCycleLengthField.setEnabled(this.isAddCycles());
connectedBox.setMaximumSize(connectedBox.getPreferredSize());
connectedBox.addActionListener(e -> {
JComboBox box = (JComboBox) e.getSource();
if ("Yes".equals(box.getSelectedItem())) {
RandomGraphEditor.this.setConnected(true);
} else if ("No".equals(box.getSelectedItem())) {
RandomGraphEditor.this.setConnected(false);
} else {
throw new IllegalArgumentException();
}
maxIndegreeField.setValue(RandomGraphEditor.this.getMaxIndegree());
maxOutdegreeField.setValue(RandomGraphEditor.this.getMaxOutdegree());
maxDegreeField.setValue(RandomGraphEditor.this.getMaxDegree());
maxEdgesField.setValue(RandomGraphEditor.this.getMaxEdges());
});
// randomForward.addActionListener(e -> {
// JRadioButton button = (JRadioButton) e.getSource();
// button.setSelected(true);
RandomGraphEditor.this.setRandomForward(true);
// RandomGraphEditor.this.setUniformlySelected(false);
// RandomGraphEditor.this.setChooseFixed(false);
maxIndegreeField.setEnabled(true);
maxOutdegreeField.setEnabled(true);
maxDegreeField.setEnabled(true);
connectedBox.setEnabled(true);
// });
// chooseUniform.addActionListener(e -> {
// JRadioButton button = (JRadioButton) e.getSource();
// button.setSelected(true);
// RandomGraphEditor.this.setRandomForward(false);
// RandomGraphEditor.this.setUniformlySelected(true);
// RandomGraphEditor.this.setChooseFixed(false);
//
// maxIndegreeField.setEnabled(true);
// maxOutdegreeField.setEnabled(true);
// maxDegreeField.setEnabled(true);
// connectedBox.setEnabled(true);
// });
// chooseFixed.addActionListener(e -> {
// JRadioButton button = (JRadioButton) e.getSource();
// button.setSelected(true);
// RandomGraphEditor.this.setRandomForward(false);
// RandomGraphEditor.this.setUniformlySelected(false);
// RandomGraphEditor.this.setChooseFixed(true);
//
// maxIndegreeField.setEnabled(false);
// maxOutdegreeField.setEnabled(false);
// maxDegreeField.setEnabled(false);
// connectedBox.setEnabled(false);
// });
if (this.isAddCycles()) {
addCyclesBox.setSelectedItem("Yes");
} else {
addCyclesBox.setSelectedItem("No");
}
addCyclesBox.setMaximumSize(addCyclesBox.getPreferredSize());
addCyclesBox.addActionListener(e -> {
JComboBox box = (JComboBox) e.getSource();
if ("Yes".equals(box.getSelectedItem())) {
RandomGraphEditor.this.setAddCycles(true);
// numTwoCyclesField.setEnabled(true);
minCycleLengthField.setEnabled(true);
} else if ("No".equals(box.getSelectedItem())) {
RandomGraphEditor.this.setAddCycles(false);
// numTwoCyclesField.setEnabled(false);
minCycleLengthField.setEnabled(false);
} else {
throw new IllegalArgumentException();
}
});
numTwoCyclesField.setFilter((value, oldValue) -> {
if (value == numTwoCyclesField.getValue()) {
return oldValue;
}
try {
RandomGraphEditor.this.setMinNumCycles(value);
} catch (Exception e) {
// Ignore.
}
return value;
});
minCycleLengthField.setFilter((value, oldValue) -> {
if (value == RandomGraphEditor.this.minCycleLengthField.getValue()) {
return oldValue;
}
try {
setMinCycleLength(value);
} catch (Exception e) {
// Ignore.
}
return value;
});
// construct the workbench.
setLayout(new BorderLayout());
Box b1 = Box.createVerticalBox();
Box b2 = Box.createHorizontalBox();
b2.add(new JLabel("Parameters for Random DAG:"));
b2.add(Box.createHorizontalGlue());
b1.add(b2);
b1.add(Box.createVerticalStrut(5));
Box b10 = Box.createHorizontalBox();
b10.add(new JLabel("Number of measured nodes:"));
b10.add(Box.createRigidArea(new Dimension(10, 0)));
b10.add(Box.createHorizontalGlue());
b10.add(this.numNodesField);
b1.add(b10);
Box b11 = Box.createHorizontalBox();
b11.add(new JLabel("Number of additional latent confounders:"));
b11.add(Box.createHorizontalStrut(25));
b11.add(Box.createHorizontalGlue());
b11.add(this.numLatentsField);
b1.add(b11);
b1.add(Box.createVerticalStrut(5));
Box b12 = Box.createHorizontalBox();
b12.add(new JLabel("Number of edges:"));
b12.add(Box.createHorizontalGlue());
b12.add(this.maxEdgesField);
b1.add(b12);
b1.add(Box.createVerticalStrut(5));
Box b14 = Box.createHorizontalBox();
b14.add(new JLabel("Maximum indegree:"));
b14.add(Box.createHorizontalGlue());
b14.add(this.maxIndegreeField);
b1.add(b14);
Box b15 = Box.createHorizontalBox();
b15.add(new JLabel("Maximum outdegree:"));
b15.add(Box.createHorizontalGlue());
b15.add(this.maxOutdegreeField);
b1.add(b15);
Box b13 = Box.createHorizontalBox();
b13.add(new JLabel("Maximum degree:"));
b13.add(Box.createHorizontalGlue());
b13.add(this.maxDegreeField);
b1.add(b13);
b1.add(Box.createVerticalStrut(5));
Box b16 = Box.createHorizontalBox();
b16.add(new JLabel("Connected:"));
b16.add(Box.createHorizontalGlue());
b16.add(this.connectedBox);
b1.add(b16);
b1.add(Box.createVerticalStrut(5));
// Box b17a = Box.createHorizontalBox();
// b17a.add(randomForward);
// b17a.add(Box.createHorizontalGlue());
// b1.add(b17a);
// Box b17 = Box.createHorizontalBox();
// b17.add(this.chooseUniform);
// b17.add(Box.createHorizontalGlue());
// b1.add(b17);
// Box b18 = Box.createHorizontalBox();
// b18.add(this.chooseFixed);
// b18.add(Box.createHorizontalGlue());
// b1.add(b18);
Box d = Box.createVerticalBox();
b1.setBorder(new TitledBorder(""));
d.add(b1);
if (cyclicAllowed) {
Box c1 = Box.createVerticalBox();
Box c2 = Box.createHorizontalBox();
c2.add(new JLabel("Create a cyclic graph?"));
c2.add(Box.createHorizontalGlue());
c2.add(addCyclesBox);
c1.add(c2);
c1.add(Box.createVerticalStrut(5));
Box c3 = Box.createHorizontalBox();
c3.add(new JLabel("Number of two cycles to add:"));
c3.add(Box.createHorizontalGlue());
c3.add(this.numTwoCyclesField);
c1.add(c3);
c1.add(Box.createVerticalStrut(5));
c1.setBorder(new TitledBorder(""));
d.add(Box.createVerticalStrut(5));
d.add(c1);
}
add(d, BorderLayout.CENTER);
}
/**
* {@inheritDoc}
*/
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
if (isChooseFixed() && enabled) {
this.numNodesField.setEnabled(enabled);
this.numLatentsField.setEnabled(enabled);
this.maxEdgesField.setEnabled(enabled);
this.maxIndegreeField.setEnabled(false);
this.maxOutdegreeField.setEnabled(false);
this.maxDegreeField.setEnabled(false);
this.connectedBox.setEnabled(false);
// this.chooseUniform.setEnabled(enabled);
this.chooseFixed.setEnabled(enabled);
} else {
this.numNodesField.setEnabled(enabled);
this.numLatentsField.setEnabled(enabled);
this.maxEdgesField.setEnabled(enabled);
this.maxIndegreeField.setEnabled(enabled);
this.maxOutdegreeField.setEnabled(enabled);
this.maxDegreeField.setEnabled(enabled);
this.connectedBox.setEnabled(enabled);
// this.chooseUniform.setEnabled(enabled);
this.chooseFixed.setEnabled(enabled);
}
}
/**
* isRandomForward.
*
* @return a boolean
*/
public boolean isRandomForward() {
return this.parameters.getBoolean("graphRandomForward", true);
}
private void setRandomForward(boolean randomFoward) {
this.parameters.set("graphRandomFoward", randomFoward);
}
// /**
// * isUniformlySelected.
// *
// * @return a boolean
// */
// public boolean isUniformlySelected() {
// return this.parameters.getBoolean("graphUniformlySelected", true);
// }
// private void setUniformlySelected(boolean uniformlySelected) {
// this.parameters.set("graphUniformlySelected", uniformlySelected);
// }
/**
* isChooseFixed.
*
* @return a boolean
*/
public boolean isChooseFixed() {
return this.parameters.getBoolean("graphChooseFixed", true);
}
private void setChooseFixed(boolean chooseFixed) {
this.parameters.set("graphChooseFixed", chooseFixed);
}
/**
* getNumNodes.
*
* @return a int
*/
public int getNumNodes() {
return getNumMeasuredNodes() + getNumLatents();
}
private int getNumMeasuredNodes() {
return this.parameters.getInt("newGraphNumMeasuredNodes", 10);
}
private void setNumMeasuredNodes(int numMeasuredNodes) {
if (numMeasuredNodes + getNumLatents() < 2) {
throw new IllegalArgumentException("Number of nodes Must be greater than or equal to 2.");
}
this.parameters.set("newGraphNumMeasuredNodes", numMeasuredNodes);
if (isConnected()) {
setMaxEdges(FastMath.max(getMaxEdges(), numMeasuredNodes + getNumLatents()));
}
}
/**
* getNumLatents.
*
* @return a int
*/
public int getNumLatents() {
return this.parameters.getInt("newGraphNumLatents", 0);
}
private void setNumLatents(int numLatentNodes) {
if (numLatentNodes < 0) {
throw new IllegalArgumentException(
"Number of additional latent confounders must be" + " >= 0: " +
numLatentNodes);
}
this.parameters.set("newGraphNumLatents", numLatentNodes);
}
/**
* getMaxEdges.
*
* @return a int
*/
public int getMaxEdges() {
return this.parameters.getInt("newGraphNumEdges", 10);
}
private void setMaxEdges(int numEdges) {
if (/*!isConnected() &&*/ numEdges < 0) {
throw new IllegalArgumentException(
"Number of edges Must be greater than or equal to 0: " + numEdges);
}
int maxNumEdges = getNumNodes() * (getNumNodes() - 1) / 2;
if (numEdges > maxNumEdges) {
numEdges = maxNumEdges;
}
this.parameters.set("newGraphNumEdges", numEdges);
}
/**
* getMaxDegree.
*
* @return a int
*/
public int getMaxDegree() {
return this.parameters.getInt("randomGraphMaxDegree", 100);
}
private void setMaxDegree(int maxDegree) {
if (!isConnected() && maxDegree < 1) {
this.parameters.set("randomGraphMaxDegree", 1);
return;
}
if (isConnected() && maxDegree < 3) {
this.parameters.set("randomGraphMaxDegree", 3);
return;
}
this.parameters.set("randomGraphMaxDegree", maxDegree);
}
/**
* getMaxIndegree.
*
* @return a int
*/
public int getMaxIndegree() {
return this.parameters.getInt("randomGraphMaxIndegree", 100);
}
private void setMaxIndegree(int maxIndegree) {
if (!isConnected() && maxIndegree < 1) {
this.parameters.set("randomGraphMaxIndegree", 1);
return;
}
if (isConnected() && maxIndegree < 2) {
this.parameters.set("randomGraphMaxIndegree", 2);
return;
}
this.parameters.set("randomGraphMaxIndegree", maxIndegree);
}
/**
* getMaxOutdegree.
*
* @return a int
*/
public int getMaxOutdegree() {
return this.parameters.getInt("randomGraphMaxOutdegree", 100);
}
private void setMaxOutdegree(int maxOutDegree) {
if (!isConnected() && maxOutDegree < 1) {
this.parameters.set("randomGraphMaxOutdegree", 1);
return;
}
if (isConnected() && maxOutDegree < 2) {
this.parameters.set("randomGraphMaxOutdegree", 2);
return;
}
this.parameters.set("randomGraphMaxOutdegree", maxOutDegree);
}
/**
* isConnected.
*
* @return a boolean
*/
public boolean isConnected() {
return this.parameters.getBoolean("randomGraphConnected", false);
}
private void setConnected(boolean connected) {
this.parameters.set("randomGraphConnected", connected);
if (connected) {
if (getMaxIndegree() < 2) {
setMaxIndegree(2);
}
if (getMaxOutdegree() < 2) {
setMaxOutdegree(2);
}
if (getMaxDegree() < 3) {
setMaxDegree(3);
}
if (getMaxEdges() < getNumNodes()) {
setMaxEdges(getNumNodes());
}
}
}
/**
* isAddCycles.
*
* @return a boolean
*/
public boolean isAddCycles() {
return this.parameters.getBoolean("randomGraphAddCycles", false);
}
private void setAddCycles(boolean addCycles) {
this.parameters.set("randomGraphAddCycles", addCycles);
}
/**
* getMinNumCycles.
*
* @return a int
*/
public int getMinNumCycles() {
int minNumCycles = this.parameters.getInt("randomGraphMinNumCycles", 0);
System.out.println("get min num cycles = " + minNumCycles);
return minNumCycles;
}
private void setMinNumCycles(int minNumCycles) {
System.out.println("set min num cycles = " + minNumCycles);
if (minNumCycles < 0) {
this.parameters.set("randomGraphMinNumCycles", 0);
return;
}
this.parameters.set("randomGraphMinNumCycles", minNumCycles);
}
/**
* getMinCycleLength.
*
* @return a int
*/
public int getMinCycleLength() {
return this.parameters.getInt("randomGraphMinCycleLength", 2);
}
private void setMinCycleLength(int minCycleLength) {
if (minCycleLength < 2) {
this.parameters.set("randomGraphMinCycleLength", 2);
return;
}
this.parameters.set("randomGraphMinCycleLength", minCycleLength);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy