private double getDerivative(Sextad sextad, Sigma sigma) { Node a = sigma.getA(); Node b = sigma.getB(); Node n1 = sextad.getI(); Node n2 = sextad.getJ(); Node n3 = sextad.getK(); Node n4 = sextad.getL(); Node n5 = sextad.getM(); Node n6 = sextad.getN(); if (a == n1) { if (b == n4) { return r(n2, n5) * r(n3, n6) - r(n2, n6) * r(n3, n5); } else if (b == n5) { return -r(n2, n4) * r(n3, n6) + r(n3, n4) * r(n2, n6); } else if (b == n6) { return r(n2, n4) * r(n3, n5) - r(n3, n4) * r(n2, n5); } } else if (a == n2) { if (b == n4) { return r(n3, n5) * r(n1, n6) - r(n1, n5) * r(n3, n6); } else if (b == n5) { return r(n1, n4) * r(n3, n6) - r(n3, n4) * r(n1, n6); } else if (b == n6) { return -r(n1, n4) * r(n3, n5) + r(n3, n4) * r(n1, n5); } } else if (a == n3) { if (b == n4) { return r(n1, n5) * r(n2, n6) - r(n2, n5) * r(n1, n6); } else if (b == n5) { return -r(n1, n4) * r(n2, n6) + r(n2, n4) * r(n1, n6); } else if (b == n6) { return r(n1, n4) * r(n2, n5) - r(n2, n4) * r(n1, n5); } } // symmetry n6 = sextad.getI(); n5 = sextad.getJ(); n4 = sextad.getK(); n3 = sextad.getL(); n2 = sextad.getM(); n1 = sextad.getN(); if (a == n1) { if (b == n4) { return r(n2, n5) * r(n3, n6) - r(n2, n6) * r(n3, n5); } else if (b == n5) { return -r(n2, n4) * r(n3, n6) + r(n3, n4) * r(n2, n6); } else if (b == n6) { return r(n2, n4) * r(n3, n5) - r(n3, n4) * r(n2, n5); } } else if (a == n2) { if (b == n4) { return r(n3, n5) * r(n1, n6) - r(n1, n5) * r(n3, n6); } else if (b == n5) { return r(n1, n4) * r(n3, n6) - r(n3, n4) * r(n1, n6); } else if (b == n6) { return -r(n1, n4) * r(n3, n5) + r(n3, n4) * r(n1, n5); } } else if (a == n3) { if (b == n4) { return r(n1, n5) * r(n2, n6) - r(n2, n5) * r(n1, n6); } else if (b == n5) { return -r(n1, n4) * r(n2, n6) + r(n2, n4) * r(n1, n6); } else if (b == n6) { return r(n1, n4) * r(n2, n5) - r(n2, n4) * r(n1, n5); } } return 0.0; }
/** * Takes a list of tetrads for the given data set and returns the chi square value for the test. * We assume that the tetrads are non-redundant; if not, a matrix exception will be thrown. * * <p>Calculates the T statistic (Bollen and Ting, p. 161). This is significant if tests as * significant using the Chi Square distribution with degrees of freedom equal to the number of * nonredundant tetrads tested. */ @Override // public double calcChiSquare1(Sextad... sextads) { // this.storedSextads = sextads; // // this.df = sextads.length; // // // Need a list of symbolic covariances--i.e. covariances that appear in tetrads. // Set<Sigma> boldSigmaSet = new LinkedHashSet<Sigma>(); // List<Sigma> boldSigma = new ArrayList<Sigma>(); // // for (Sextad sextad : sextads) { // boldSigmaSet.add(new Sigma(sextad.getI(), sextad.getL())); // boldSigmaSet.add(new Sigma(sextad.getI(), sextad.getM())); // boldSigmaSet.add(new Sigma(sextad.getI(), sextad.getN())); // // boldSigmaSet.add(new Sigma(sextad.getJ(), sextad.getL())); // boldSigmaSet.add(new Sigma(sextad.getJ(), sextad.getM())); // boldSigmaSet.add(new Sigma(sextad.getJ(), sextad.getN())); // // boldSigmaSet.add(new Sigma(sextad.getK(), sextad.getL())); // boldSigmaSet.add(new Sigma(sextad.getK(), sextad.getM())); // boldSigmaSet.add(new Sigma(sextad.getK(), sextad.getN())); // } // // for (Sigma sigma : boldSigmaSet) { // boldSigma.add(sigma); // } // // // Need a matrix of variances and covariances of sample covariances. // TetradMatrix sigma_ss = TetradMatrix.instance(boldSigma.size(), boldSigma.size()); // // for (int i = 0; i < boldSigma.size(); i++) { // for (int j = 0; j < boldSigma.size(); j++) { // Sigma sigmaef = boldSigma.get(i); // Sigma sigmagh = boldSigma.get(j); // // Node e = sigmaef.getA(); // Node f = sigmaef.getB(); // Node g = sigmagh.getA(); // Node h = sigmagh.getB(); // // if (cov != null && cov instanceof CorrelationMatrix) { // //// Assumes multinormality. Using formula 23. (Not implementing formula 22 because // that case //// does not come up.) // double rr = 0.5 * (r(e, f) * r(g, h)) // * (r(e, g) * r(e, g) + r(e, h) * r(e, h) + r(f, g) * r(f, g) + r(f, // h) * r(f, h)) // + r(e, g) * r(f, h) + r(e, h) * r(f, g) // - r(e, f) * (r(f, g) * r(f, h) + r(e, g) * r(e, h)) // - r(g, h) * (r(f, g) * r(e, g) + r(f, h) * r(e, h)); // // sigma_ss.set(i, j, rr); // } else if (cov != null && dataSet == null) { // // // Assumes multinormality--see p. 160. // double _ss = r(e, g) * r(f, h) + r(e, h) * r(f, g); // + or -? Different // advise. + in the code. // sigma_ss.set(i, j, _ss); // } else { // double _ss = sxyzw(e, f, g, h) - r(e, f) * r(g, h); // sigma_ss.set(i, j, _ss); // } // } // } // // // Need a matrix of of population estimates of partial derivatives of tetrads // // with respect to covariances in boldSigma. // TetradMatrix del = TetradMatrix.instance(boldSigma.size(), sextads.length); // // for (int i = 0; i < boldSigma.size(); i++) { // for (int j = 0; j < sextads.length; j++) { // Sigma sigma = boldSigma.get(i); // Sextad sextad = sextads[j]; // // Node m1 = sextad.getI(); // Node m2 = sextad.getJ(); // Node m3 = sextad.getK(); // Node m4 = sextad.getL(); // Node m5 = sextad.getM(); // Node m6 = sextad.getN(); // // double derivative = getDerivative(m1, m2, m3, m4, m5, m6, sigma.getA(), // sigma.getB()); // del.set(i, j, derivative); // } // } // // // Need a vector of population estimates of the sextads. // TetradMatrix t = TetradMatrix.instance(sextads.length, 1); // // for (int i = 0; i < sextads.length; i++) { // Sextad sextad = sextads[i]; // // List<Node> nodes = new ArrayList<Node>(); // // nodes.add(sextad.getI()); // nodes.add(sextad.getJ()); // nodes.add(sextad.getK()); // nodes.add(sextad.getL()); // nodes.add(sextad.getM()); // nodes.add(sextad.getN()); // // TetradMatrix m = TetradMatrix.instance(3, 3); // // for (int k1 = 0; k1 < 3; k1++) { // for (int k2 = 0; k2 < 3; k2++) { // m.set(k1, k2, r(nodes.get(k1), nodes.get(3+k2))); // } // } // // double value = TetradAlgebra.det(m); // t.set(i, 0, value); // this.storedValue = value; // } // // // Now multiply to get Sigma_tt // TetradMatrix w1 = TetradAlgebra.times(del.transpose(), sigma_ss); // TetradMatrix sigma_tt = TetradAlgebra.times(w1, del); // // // And now invert and multiply to get T. // TetradMatrix v0 = TetradAlgebra.inverse(sigma_tt); // TetradMatrix v1 = TetradAlgebra.times(t.transpose(), v0); // TetradMatrix v2 = TetradAlgebra.times(v1, t); // double chisq = N * v2.get(0, 0); // // this.chisq = chisq; // return chisq; // } public double calcChiSquare(Sextad... sextads) { this.storedSextads = sextads; this.df = 4; // sextads.length; List<Sigma> boldSigma = new ArrayList<Sigma>(); List<Node> _nodes = new ArrayList<Node>(sextads[0].getNodes()); for (int i = 0; i < _nodes.size(); i++) { for (int j = i + 1; j < _nodes.size(); j++) { boldSigma.add(new Sigma(_nodes.get(i), _nodes.get(j))); } } // Need a matrix of variances and covariances of sample covariances. TetradMatrix sigma_ss = new TetradMatrix(boldSigma.size(), boldSigma.size()); for (int i = 0; i < boldSigma.size(); i++) { for (int j = i; j < boldSigma.size(); j++) { Sigma sigmaef = boldSigma.get(i); Sigma sigmagh = boldSigma.get(j); Node e = sigmaef.getA(); Node f = sigmaef.getB(); Node g = sigmagh.getA(); Node h = sigmagh.getB(); if (cov != null && cov instanceof CorrelationMatrix) { // Assumes multinormality. Using formula 23. (Not implementing formula 22 // because that case // does not come up.) double rr = 0.5 * (r(e, f) * r(g, h)) * (r(e, g) * r(e, g) + r(e, h) * r(e, h) + r(f, g) * r(f, g) + r(f, h) * r(f, h)) + r(e, g) * r(f, h) + r(e, h) * r(f, g) - r(e, f) * (r(f, g) * r(f, h) + r(e, g) * r(e, h)) - r(g, h) * (r(f, g) * r(e, g) + r(f, h) * r(e, h)); sigma_ss.set(i, j, rr); sigma_ss.set(j, i, rr); } else if (cov != null && dataSet == null) { // Assumes multinormality--see p. 160. double _ss = r(e, g) * r(f, h) + r(e, h) * r(f, g); // + or -? Different advise. + in the code. // double _ss = r(e, g) * r(f, h) - r(e, h) * r(g, f); // shouldn't // this be a tetrad? sigma_ss.set(i, j, _ss); sigma_ss.set(j, i, _ss); } else { double _ss = sxyzw(e, f, g, h) - r(e, f) * r(g, h); sigma_ss.set(i, j, _ss); sigma_ss.set(j, i, _ss); } } } // Need a matrix of of population estimates of partial derivatives of tetrads // with respect to covariances in boldSigma. TetradMatrix del = new TetradMatrix(boldSigma.size(), sextads.length); for (int j = 0; j < sextads.length; j++) { Sextad sextad = sextads[j]; for (int i = 0; i < boldSigma.size(); i++) { Sigma sigma = boldSigma.get(i); double derivative = getDerivative(sextad, sigma); del.set(i, j, derivative); } } // Need a vector of population estimates of the sextads. TetradMatrix t = new TetradMatrix(sextads.length, 1); for (int i = 0; i < sextads.length; i++) { Sextad sextad = sextads[i]; List<Node> nodes = sextad.getNodes(); TetradMatrix m = new TetradMatrix(3, 3); for (int k1 = 0; k1 < 3; k1++) { for (int k2 = 0; k2 < 3; k2++) { m.set(k1, k2, r(nodes.get(k1), nodes.get(3 + k2))); } } double det = m.det(); t.set(i, 0, det); this.storedValue = det; // ? } // for (int i = 0; i < sextads.length; i++) { // Sextad sextad = sextads[i]; // // List<Node> nodes = new ArrayList<Node>(); // // nodes.add(sextad.getI()); // nodes.add(sextad.getJ()); // nodes.add(sextad.getK()); // nodes.add(sextad.getL()); // nodes.add(sextad.getM()); // nodes.add(sextad.getN()); // // TetradMatrix m = TetradMatrix.instance(3, 3); // // for (int k1 = 0; k1 < 3; k1++) { // for (int k2 = 0; k2 < 3; k2++) { // m.set(k1, k2, r(nodes.get(k1), nodes.get(3+k2))); // } // } // // double value = TetradAlgebra.det(m); // t.set(i, 0, value); // this.storedValue = value; // } TetradMatrix sigma_tt = del.transpose().times(sigma_ss).times(del); try { this.chisq = N * t.transpose().times(sigma_tt.inverse()).times(t).get(0, 0); return chisq; } catch (Exception e) { return Double.NaN; } }