All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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