package edu.cmu.tetrad.algcomparison.algorithm.external;

import edu.cmu.tetrad.algcomparison.algorithm.ExternalAlgorithm;
import edu.cmu.tetrad.data.DataModel;
import edu.cmu.tetrad.data.DataType;
import edu.cmu.tetrad.graph.Edge;
import edu.cmu.tetrad.graph.EdgeListGraph;
import edu.cmu.tetrad.graph.Graph;
import edu.cmu.tetrad.util.Parameters;

import java.util.Set;

/**
 * An API to allow results from external algorithms to be included in a report through the algrorithm
 * comparison tool. This one is for matrix generated by PC in pcalg. See below. This script can generate
 * the files in R.
 * <p>
 * library("MASS");
 * library("pcalg");
 * <p>
 * path&lt;-"/Users/user/tetrad/comparison-final";
 * simulation&lt;-1;
 * <p>
 * subdir&lt;-"pc.solve.confl.TRUE";
 * dir.create(paste(path, "/save/", simulation, "/", subdir, sep=""));
 * <p>
 * for (i in 1:10) {
 * data&lt;-read.table(paste(path, "/save/", simulation, "/data/data.", i, ".txt", sep=""), header=TRUE)
 * n&lt;-nrow(data)
 * C&lt;-cor(data)
 * v&lt;-names(data)
 * suffStat&lt;-list(C = C, n=n)
 * pc.fit&lt;-pc(suffStat=suffStat, indepTest=gaussCItest, alpha=0.001, labels=v,
 * solve.conf=TRUE)
 * A&lt;-as(pc.fit, "amat")
 * name&lt;-paste(path, "/save/", simulation, "/", subdir, "/graph.", i, ".txt", sep="")
 * print(name)
 * write.matrix(A, file=name, sep="\t")
 * }
 *
 * @author josephramsey
 */
public class ExternalAlgorithmIntersection extends ExternalAlgorithm {
    static final long serialVersionUID = 23L;
    private final ExternalAlgorithm[] algorithms;
    private final String shortDescription;
    private long elapsed = -99;

    public ExternalAlgorithmIntersection(String shortDescription, ExternalAlgorithm... algorithms) {
        this.algorithms = algorithms;
        this.shortDescription = shortDescription;
    }

    /**
     * Reads in the relevant graph from the file (see above) and returns it.
     */
    public Graph search(DataModel dataSet, Parameters parameters) {
        this.elapsed = 0;

        for (ExternalAlgorithm algorithm : this.algorithms) {
            algorithm.setPath(this.path);
            algorithm.setSimIndex(this.simIndex);
            algorithm.setSimulation(this.simulation);
            this.elapsed += algorithm.getElapsedTime(dataSet, parameters);
        }

        Graph graph0 = this.algorithms[0].search(dataSet, parameters);
        Set<Edge> edges = graph0.getEdges();

        for (int i = 1; i < this.algorithms.length; i++) {
            edges.retainAll(this.algorithms[i].search(dataSet, parameters).getEdges());
        }

        EdgeListGraph intersection = new EdgeListGraph(graph0.getNodes());

        for (Edge edge : edges) {
            intersection.addEdge(edge);
        }

        return intersection;
    }

    /**
     * Returns the CPDAG of the supplied DAG.
     */
    public Graph getComparisonGraph(Graph graph) {
        return this.algorithms[0].getComparisonGraph(graph);
    }

    public String getDescription() {
        return this.shortDescription;
    }

    public DataType getDataType() {
        return DataType.Continuous;
    }

    public long getElapsedTime(DataModel dataSet, Parameters parameters) {
        return this.elapsed;
    }

}
