Beispiel #1
0
void origNISim::initialize() {
    mat W_t(maxVertexId, maxVertexId, fill::zeros);
    for (int i = 0; i < maxVertexId; i++) {
        int e = origGraphSrc[i + 1], s = origGraphSrc[i];
        for (int j = s; j < e; j++) {
            W_t(i, origGraphDst[j]) = 1.0;
        }
    }
    double sumRow;
    double Degr = 0;
    for (int i = 0; i < maxVertexId; i++) {
        sumRow = 0;
        for (int j = 0; j < maxVertexId; j++)
            sumRow += W_t(i, j);
        if (sumRow == 0.0) {
            printf("node %d has no ingoing edges\n", i);
        } else {
            for (int j = 0; j < maxVertexId; j++)
                W_t(i, j) = W_t(i, j) / sumRow;
        }
        Degr += sumRow;
    }
    //start svd
    Mat<double> U;
    Col<double> s;
    Mat<double> V_t;
    svd(U, s, V_t, W_t);
    mat V = V_t.t();

    U = U.submat(0, 0, maxVertexId - 1, Rank - 1);
    V = V.submat(0, 0, Rank - 1, maxVertexId - 1);
    s = s.submat(0, 0, Rank - 1, 0);
    Ku = kron(U, U);//kronecker roduct
    mat sigma = kron(s, s);//one column
    mat K_sigma = diagmat(sigma);
    Kv = kron(V, V);

    mat K_vu = Kv * Ku;

    mat I(maxVertexId, maxVertexId);
    I.eye();
    A = inv(inv(K_sigma) - decayFactor * K_vu);
    V_r = Kv * vectorise(I);

    A.save(Apath);
    V_r.save(V_rpath);
    Kv.save(Kvpath);
    Ku.save(Kupath);
}
Beispiel #2
0
PureState SingleSampleCCE::create_cluster_state(const cClusterIndex& clstIndex)
{/*{{{*/
    uvec idx = clstIndex.getIndex();
    cx_vec state_vec = _bath_state_list[ idx[0] ].getVector();
    for(int i=1; i<idx.n_elem; ++i)
        state_vec = kron( state_vec, _bath_state_list[ idx[i] ].getVector() );

    PureState res( state_vec );
    return res;
}/*}}}*/
Beispiel #3
0
 void Mapping2D::assembleRHS(basics::Vector& vec)
 {
   for( map<int,pair<Range2D,Element2D> >::iterator iter=m_mapping.begin(); iter != m_mapping.end(); ++iter) {
     Element2D& element = iter->second.second;
     Range2D& nodes = iter->second.first;
     basics::Vector rhs = element.width()/2.f*element.height()/2.f*kron(basics::Matrix::diag(element.getWeightX()),basics::Matrix::diag(element.getWeightY()))*element.getRHS();
     for( int i=0;i<element.getRHS().length();++i )
       vec[nodes[0][i]] += rhs[i];
   }
 }
Beispiel #4
0
  JNIEXPORT jint JNICALL Java_edu_berkeley_bid_CUMAT_kroni
  (JNIEnv *env, jobject obj, jobject jA, jobject jB, jobject jC,
   int nrA, int ncA, int nrB, int ncB)
  {
    int *A = (int *)getPointer(env, jA);
    int *B = (int *)getPointer(env, jB);
    int *C = (int *)getPointer(env, jC);

    return kron(A, B, C, nrA, ncA, nrB, ncB);
  }
  void SimpleIndefDpleInternal::init() {

    DpleInternal::init();

    casadi_assert_message(!pos_def_,
      "pos_def option set to True: Solver only handles the indefinite case.");
    casadi_assert_message(const_dim_,
      "const_dim option set to False: Solver only handles the True case.");

    n_ = A_[0].size1();


    MX As = MX::sym("A", n_, K_*n_);
    MX Vs = MX::sym("V", n_, K_*n_);

    std::vector< MX > Vss = horzsplit(Vs, n_);
    std::vector< MX > Ass = horzsplit(As, n_);

    for (int k=0;k<K_;++k) {
      Vss[k]=(Vss[k]+Vss[k].T())/2;
    }

    std::vector< MX > AA_list(K_);
    for (int k=0;k<K_;++k) {
      AA_list[k] = kron(Ass[k], Ass[k]);
    }

    MX AA = blkdiag(AA_list);

    MX A_total = DMatrix::eye(n_*n_*K_) -
        vertcat(AA(range(K_*n_*n_-n_*n_, K_*n_*n_), range(K_*n_*n_)),
                AA(range(K_*n_*n_-n_*n_), range(K_*n_*n_)));

    std::vector<MX> Vss_shift;
    Vss_shift.push_back(Vss.back());
    Vss_shift.insert(Vss_shift.end(), Vss.begin(), Vss.begin()+K_-1);

    MX Pf = solve(A_total, vec(horzcat(Vss_shift)), getOption("linear_solver"));
    MX P = reshape(Pf, n_, K_*n_);

    std::vector<MX> v_in;
    v_in.push_back(As);
    v_in.push_back(Vs);
    f_ = MXFunction(v_in, P);
    f_.setInputScheme(SCHEME_DPLEInput);
    f_.setOutputScheme(SCHEME_DPLEOutput);
    f_.init();
  }
Beispiel #6
0
int MCMCPkPg::sampleRho( PkPgModel& model, PkPgResult& Result ){

  mat ymat   = Result.logTheta - Result.XBetaPk;
  vec yvec   = reshape( ymat, ymat.n_elem, 1 );
  mat Xmat   = kron( eye<mat>( model.V, model.V ), Result.Z );
  vec rhovec = reshape( Result.Rho, Result.Rho.n_elem, 1 );
  if( 1 ){
    // adaptive lasso
    mat resrho;
    vec resdelta, resiota;
    Bayes_AL( yvec, Xmat, 
              0, 1, 1,
              rhovec, Result.delta, Result.iota,
              resrho, resdelta, resiota,
              false, true, true ); 
    Result.Rho   = reshape( resrho.row( 0 ), Result.Rho.n_rows, Result.Rho.n_cols );
    Result.delta = resdelta( 0 );
    Result.iota  = resiota( 0 );
    Result.ZRho  = Result.Z * Result.Rho;
  } else{
    // lasso
    mat resrho;
    vec sigma2Samples;  
    mat invTau2Samples; 
    vec lambdaSamples;  
  
    int initialize = 0;
    if( Result.Rhoinit == 1 ){ // one time only
      initialize = 1;
      Result.Rhoinit = 0;
    }

    Bayes_Lasso( yvec, Xmat, 0, 1, 1, 
                 initialize,
                 rhovec, Result.Rhos2, Result.Rhot2, Result.Rholb,
                 resrho, sigma2Samples, invTau2Samples, lambdaSamples  );
  
    Result.Rho   = reshape( resrho.row( 0 ), Result.Rho.n_rows, Result.Rho.n_cols );
    Result.Rhos2 = sigma2Samples( 0 );
    Result.Rhot2 = invTau2Samples.row( 0 ).t();
    Result.Rholb = lambdaSamples( 0 ); 
    Result.ZRho  =  Result.Z * Result.Rho;
  }
  return 0;
} // END sampleRho --------------------------------------------------------------------
  void SimpleIndefDleInternal::init() {

    DleInternal::init();

    casadi_assert_message(!pos_def_,
      "pos_def option set to True: Solver only handles the indefinite case.");

    n_ = A_.size1();

    MX As = MX::sym("A", A_);
    MX Vs = MX::sym("V", V_);

    MX Vss = (Vs+Vs.T())/2;

    MX A_total = DMatrix::eye(n_*n_) - kron(As, As);

    MX Pf = solve(A_total, vec(Vss), getOption("linear_solver"));

    MX P = reshape(Pf, n_, n_);

    f_ = MXFunction(dleIn("a", As, "v", Vs),
      dleOut("p", MX(P(output().sparsity()))));

    f_.init();

    casadi_assert(getNumOutputs()==f_.getNumOutputs());
    for (int i=0;i<getNumInputs();++i) {
      casadi_assert_message(input(i).sparsity()==f_.input(i).sparsity(),
        "Sparsity mismatch for input " << i << ":" <<
        input(i).dimString() << " <-> " << f_.input(i).dimString() << ".");
    }
    for (int i=0;i<getNumOutputs();++i) {
      casadi_assert_message(output(i).sparsity()==f_.output(i).sparsity(),
        "Sparsity mismatch for output " << i << ":" <<
        output(i).dimString() << " <-> " << f_.output(i).dimString() << ".");
    }
  }
Beispiel #8
0
msym_error_t generateOrbitalTransforms(int sopsl, msym_symmetry_operation_t sops[sopsl], int l, double transform[sopsl][2*l+1][2*l+1]){
    msym_error_t ret = MSYM_SUCCESS;
    int kdim = ipow(3,l), norbs = 2*l+1;
    double (*mkron)[kdim][kdim] = malloc(sizeof(double[2][kdim][kdim]));
    double (*poly)[kdim] = malloc(sizeof(double[norbs][kdim]));
    
    for(int m = -l; m <= l;m++){
        if(MSYM_SUCCESS != (ret = orbitalPolynomial(l,m,poly[m+l]))) goto err;
        
        //Normalization
        vlnorm(kdim, poly[m+l]);
    }
    
    
    for(int i = 0;i < sopsl;i++){
        double M[3][3];
        mkron[0][0][0] = 1.0;
        symmetryOperationMatrix(&sops[i], M);
        for(int j = 0, d = 1;j < l;j++, d *= 3){
            kron(3,M,d,mkron[j%2],3*d,mkron[(j+1)%2]);
        }
        mmlmul(norbs, kdim, poly, kdim, mkron[l%2], mkron[(l+1)%2]);
        mmtlmul(norbs, kdim, mkron[(l+1)%2], norbs, poly, transform[i]);
        
        /* Scaling
        for(int j = 0; j < norbs;j++){
            double scale = vldot(kdim, poly[j], poly[j]);
            vlscale(1.0/scale, norbs, transform[i][j], transform[i][j]);
        }*/
    }
    
    
err:
    free(mkron);
    free(poly);
    return ret;
}
  void SimpleIndefDleInternal::init() {

    DleInternal::init();

    casadi_assert_message(!pos_def_,
      "pos_def option set to True: Solver only handles the indefinite case.");


    n_ = A_.size1();

    MX As = MX::sym("A", A_);
    MX Vs = MX::sym("V", V_);
    MX Cs = MX::sym("C", C_);
    MX Hs = MX::sym("H", H_);

    MX Vss = (Vs+Vs.T())/2;
    if (with_C_) Vss = mul(mul(Cs, Vss), Cs.T());

    MX A_total = DMatrix::eye(n_*n_) - kron(As,As);

    // Should be treated by solve node
    MX Pf = solve(A_total, vec(Vss), getOption("linear_solver"));

    std::vector<MX> v_in;
    v_in.push_back(As);
    v_in.push_back(Vs);
    v_in.push_back(Cs);

    MX P = reshape(Pf,n_,n_);

    std::vector<MX> HPH;

    if (with_H_) {
      std::vector<MX> H = horzsplit(Hs,Hi_);

      for (int k=0;k<H.size();++k) {
        HPH.push_back(mul(H[k].T(),mul(P,H[k])));
      }
    }

    std::vector<MX> dle_in(DLE_NUM_IN);
    dle_in[DLE_A] = As;
    dle_in[DLE_V] = Vs;
    if (with_C_) dle_in[DLE_C] = Cs;
    if (with_H_) dle_in[DLE_H] = Hs;

    f_ = MXFunction(dle_in,dleOut("p",with_H_? diagcat(HPH) : P(output().sparsity())));

    f_.init();

    casadi_assert(nOut()==f_.nOut());
    for (int i=0;i<nIn();++i) {
      casadi_assert_message(input(i).sparsity()==f_.input(i).sparsity(),
        "Sparsity mismatch for input " << i << ":" <<
        input(i).dimString() << " <-> " << f_.input(i).dimString() << ".");
    }
    for (int i=0;i<nOut();++i) {
      casadi_assert_message(output(i).sparsity()==f_.output(i).sparsity(),
        "Sparsity mismatch for output " << i << ":" <<
        output(i).dimString() << " <-> " << f_.output(i).dimString() << ".");
    }
  }
Beispiel #10
0
int main(void) {
    
    // Check if kron works, cf. 
    Eigen::MatrixXd A(2,2);
    A << 1, 2, 3, 4;
    Eigen::MatrixXd B(2,2);
    B << 5, 6, 7, 8;
    Eigen::MatrixXd C;
    
    Eigen::VectorXd x = Eigen::VectorXd::Random(4);
    Eigen::VectorXd y;
    kron(A,B,C);
    y = C*x;
    std::cout << "kron(A,B)=" << std::endl << C << std::endl;
    std::cout << "Using kron: y=       " << std::endl << y << std::endl;
    
    kron_fast(A,B,x,y);
    std::cout << "Using kron_fast: y=  " << std::endl << y << std::endl;
    kron_super_fast(A,B,x,y);
    std::cout << "Using kron_super_fast: y=  " << std::endl << y << std::endl;
    
    // Compute runtime of different implementations of kron
    unsigned int repeats = 10;
    timer<> tm_kron, tm_kron_fast, tm_kron_super_fast;
    std::vector<int> times_kron, times_kron_fast, times_kron_super_fast;
    
    for(unsigned int p = 2; p <= 10; p++) {
        tm_kron.reset();
        tm_kron_fast.reset();
        tm_kron_super_fast.reset();
        for(unsigned int r = 0; r < repeats; ++r) {
            unsigned int M = pow(2,p);
            A = Eigen::MatrixXd::Random(M,M);
            B = Eigen::MatrixXd::Random(M,M);
            x = Eigen::VectorXd::Random(M*M);
            
            // May be too slow for large p, comment if so
            tm_kron.start();
//             kron(A,B,C);
//             y = C*x;
            tm_kron.stop();
            
            tm_kron_fast.start();
            kron_fast(A,B,x,y);
            tm_kron_fast.stop();
            
            tm_kron_super_fast.start();
            kron_super_fast(A,B,x,y);
            tm_kron_super_fast.stop();
        }
        
        std::cout << "Lazy Kron took:       " << tm_kron.avg().count() / 1000000. << " ms" << std::endl;
        std::cout << "Kron fast took:       " << tm_kron_fast.avg().count() / 1000000. << " ms" << std::endl;
        std::cout << "Kron super fast took: " << tm_kron_super_fast.avg().count() / 1000000. << " ms" << std::endl;
        times_kron.push_back( tm_kron.avg().count() );
        times_kron_fast.push_back( tm_kron_fast.avg().count() );
        times_kron_super_fast.push_back( tm_kron_super_fast.avg().count() );
    }
    
    for(auto it = times_kron.begin(); it != times_kron.end(); ++it) {
        std::cout << *it << " ";
    }
    std::cout << std::endl;
    for(auto it = times_kron_fast.begin(); it != times_kron_fast.end(); ++it) {
        std::cout << *it << " ";
    }
    std::cout << std::endl;
    for(auto it = times_kron_super_fast.begin(); it != times_kron_super_fast.end(); ++it) {
        std::cout << *it << " ";
    }
    std::cout << std::endl;
}
double ElacticMapAnalyzer::findAElement(int type, int k, int l) {
    double a1, a2, a3, a4, a5, a6, a7;
    switch(type) {
    case 1:
        a1 = taxonsCount[(k-1)*q+(l-1)]/(double)TMatrix.size();
        a2 = (lambda/pq)*(4 - kron(k,1) - kron(k,p) - kron(l,1) - kron(l,q));
        a3 = (1-kron(k,2))*(1-kron(k,1))+(1-kron(k,p-1))*(1-kron(k,p))-2*(1-kron(k,p))*(1-kron(k,1));
        a4 = (1-kron(l,2))*(1-kron(l,1))+(1-kron(l,q-1))*(1-kron(l,q))-2*(1-kron(l,q))*(1-kron(l,1));
        a5 = (mu/pq);
        a6 = a5 * (a3 + a4);
        a7 = a1 + a2 + a6;
        return a7;
        //return taxonsCount[(k-1)*q+(l-1)]/(double)TMatrix.size() +
          //      (lambda/pq)*(4 - kron(k,1) - kron(k,p) - kron(l,1) - kron(l,q)) +
            //    (mu/pq)*((1-kron(k,2))*(1-kron(k,1))+(1-kron(k,p-1))*(1-kron(k,p))-2*(1-kron(k,p))*(1-kron(k,l)) +
              //           (1-kron(l,2))*(1-kron(l,1))+(1-kron(l,q-1))*(1-kron(l,q))-2*(1-kron(l,q))*(1-kron(l,1)));
    case 2:
        return (lambda/pq)*(kron(l,1)-1) + (2*mu/pq)*(kron(l,2)-1)*(1-kron(l,1));
    case 3:
        return (lambda/pq)*(kron(l,q)-1) + (2*mu/pq)*(kron(l,q-1)-1)*(1-kron(l,q));
    case 4:
        return (mu/pq)*(1-kron(l,2))*(1-kron(l,1));
    case 5:
        return (mu/pq)*(1-kron(l,q-1))*(1-kron(l,q));
    case 6:
        return (mu/pq)*(1-kron(k,2))*(1-kron(k,1));
    case 7:
        return (lambda/pq)*(kron(k,1)-1) + (2*mu/pq)*(kron(k,2)-1)*(1-kron(k,1));
    case 8:
        return (lambda/pq)*(kron(k,p)-1) + (2*mu/pq)*(kron(k,p-1)-1)*(1-kron(k,p));
    case 9:
        return (mu/pq)*(1-kron(k,p-1))*(1-kron(k,p));
    }
    return 0.0;
}
Beispiel #12
0
TR discord3_reg(const T1& rho1, arma::uword nodal, arma::uvec dim) {
  const auto& rho = as_Mat(rho1);
  arma::uword party_no = dim.n_elem;
  arma::uword dim1 = arma::prod(dim);

#ifndef QICLIB_NO_DEBUG
  if (rho.n_elem == 0)
    throw Exception("qic::discord3_reg", Exception::type::ZERO_SIZE);

  if (rho.n_rows != rho.n_cols)
    throw Exception("qic::discord3_reg", Exception::type::MATRIX_NOT_SQUARE);

  if (any(dim == 0))
    throw Exception("qic::discord3_reg", Exception::type::INVALID_DIMS);

  if (dim1 != rho.n_rows)
    throw Exception("qic::discord3_reg", Exception::type::DIMS_MISMATCH_MATRIX);

  if (nodal <= 0 || nodal > party_no)
    throw Exception("qic::discord3_reg", "Invalid measured party index");

  if (dim(nodal - 1) != 3)
    throw Exception("qic::discord3_reg", "Measured party is not qutrit");
#endif

  arma::uvec party = arma::zeros<arma::uvec>(party_no);
  for (arma::uword i = 0; i < party_no; ++i) party.at(i) = i + 1;

  arma::uvec rest = party;
  rest.shed_row(nodal - 1);

  auto rho_A = TrX(rho, rest, dim);
  auto rho_B = TrX(rho, {nodal}, dim);

  auto S_A = entropy(rho_A);
  auto S_B = entropy(rho_B);
  auto S_A_B = entropy(rho);
  auto I1 = S_A + S_B - S_A_B;

  dim1 /= 3;
  arma::uword dim2(1);
  for (arma::uword i = 0; i < nodal - 1; ++i) dim2 *= dim.at(i);
  arma::uword dim3(1);
  for (arma::uword i = nodal; i < party_no; ++i) dim3 *= dim.at(i);

  arma::Mat<trait::pT<T1> > eye2 =
    arma::eye<arma::Mat<trait::pT<T1> > >(dim1, dim1);
  arma::Mat<trait::pT<T1> > eye3 =
    arma::eye<arma::Mat<trait::pT<T1> > >(dim2, dim2);
  arma::Mat<trait::pT<T1> > eye4 =
    arma::eye<arma::Mat<trait::pT<T1> > >(dim3, dim3);

  typename arma::Col<trait::pT<T1> >::template fixed<3> disc;

  for (arma::uword i = 0; i < 3; ++i) {
    arma::Mat<std::complex<trait::pT<T1> > > proj1 =
      SPM<trait::pT<T1> >::get_instance().proj3.at(0, i + 1);

    arma::Mat<std::complex<trait::pT<T1> > > proj2 =
      SPM<trait::pT<T1> >::get_instance().proj3.at(1, i + 1);

    arma::Mat<std::complex<trait::pT<T1> > > proj3 =
      SPM<trait::pT<T1> >::get_instance().proj3.at(2, i + 1);

    if (nodal == 1) {
      proj1 = kron(proj1, eye2);
      proj2 = kron(proj2, eye2);
      proj3 = kron(proj3, eye2);
    } else if (party_no == nodal) {
      proj1 = kron(eye2, proj1);
      proj2 = kron(eye2, proj2);
      proj3 = kron(eye2, proj3);
    } else {
      proj1 = kron(kron(eye3, proj1), eye4);
      proj2 = kron(kron(eye3, proj2), eye4);
      proj3 = kron(kron(eye3, proj3), eye4);
    }

    arma::Mat<std::complex<trait::pT<T1> > > rho_1 = (proj1 * rho * proj1);
    arma::Mat<std::complex<trait::pT<T1> > > rho_2 = (proj2 * rho * proj2);
    arma::Mat<std::complex<trait::pT<T1> > > rho_3 = (proj3 * rho * proj3);

    trait::pT<T1> p1 = std::real(arma::trace(rho_1));
    trait::pT<T1> p2 = std::real(arma::trace(rho_2));
    trait::pT<T1> p3 = std::real(arma::trace(rho_3));

    trait::pT<T1> S_max = 0.0;
    if (p1 > _precision::eps<trait::pT<T1> >::value) {
      rho_1 /= p1;
      S_max += p1 * entropy(rho_1);
    }
    if (p2 > _precision::eps<trait::pT<T1> >::value) {
      rho_2 /= p2;
      S_max += p2 * entropy(rho_2);
    }
    if (p3 > _precision::eps<trait::pT<T1> >::value) {
      rho_3 /= p3;
      S_max += p3 * entropy(rho_3);
    }
    disc.at(i) = I1 - (S_B - S_max);
  }

  return disc;
}
Beispiel #13
0
msym_error_t generateOrbitalSubspaces(msym_point_group_t *pg, int esl, msym_equivalence_set_t *es, msym_permutation_t **perm, int basisl, msym_orbital_t basis[basisl], msym_thresholds_t *thresholds, int *subspacel, msym_subspace_t **subspace, int **pspan){
    msym_error_t ret = MSYM_SUCCESS;
    int lmax = -1, nmax = -1, eslmax = -1;
    for(int i = 0;i < basisl;i++){
        lmax = basis[i].l > lmax ? basis[i].l : lmax;
        nmax = basis[i].n > nmax ? basis[i].n : nmax;
    }
    
    if(lmax < 0){ret = MSYM_INVALID_ORBITALS; return ret;} //if we goto err here, code will get ugly due to scope
    
    for(int i = 0;i < esl;i++) eslmax = es[i].length > eslmax ? es[i].length : eslmax;
    
    struct _ltransforms {int d; void *t;} *lts = calloc(lmax+1,sizeof(struct _ltransforms));
    double (*mkron)[(2*lmax+1)*pg->order] = malloc(sizeof(double[(2*lmax+1)*pg->order][(2*lmax+1)*pg->order]));
    double (*mperm)[pg->order] = malloc(sizeof(double[pg->order][pg->order]));
    
    double (*mproj)[pg->ct->l+1][(2*lmax+1)*pg->order][(2*lmax+1)*pg->order] = malloc(sizeof(double[lmax+1][pg->ct->l+1][(2*lmax+1)*pg->order][(2*lmax+1)*pg->order]));
    double (*lspan)[pg->ct->l] = malloc(sizeof(double[lmax+1][pg->ct->l]));
    int (*ispan) = calloc(pg->ct->l,sizeof(int));
    int *aspan = calloc(pg->ct->l,sizeof(int));
    int *nl = malloc(sizeof(int[lmax+1]));
    
    msym_orbital_t *(*omap)[nmax][lmax][2*lmax+1] = malloc(sizeof(msym_orbital_t *[eslmax][nmax+1][lmax+1][2*lmax+1]));
    
    *subspace = NULL;
    
    msym_subspace_t *iss = calloc(pg->ct->l, sizeof(msym_subspace_t));
    for(int k = 0;k < pg->ct->l;k++){
        iss[k].type = ATOMIC_ORBITAL;
        iss[k].irrep = k;
        iss[k].subspacel = esl;
        iss[k].subspace = calloc(esl, sizeof(msym_subspace_t));
    }
    
    for(int l = 0; l <= lmax;l++){
        lts[l].d = 2*l+1;
        lts[l].t = malloc(sizeof(double[pg->sopsl][lts[l].d][lts[l].d]));
        if(MSYM_SUCCESS != (ret = generateOrbitalTransforms(pg->sopsl, pg->sops, l, lts[l].t))) goto err;
    }
    
    for(int i = 0; i < esl;i++){
        int esilmax = -1, esinmax = -1;
        
        memset(nl,0,sizeof(int[lmax+1]));
        for(int j = 0;j < es[i].elements[0]->aol;j++){
            esilmax = esilmax < es[i].elements[0]->ao[j]->l ? es[i].elements[0]->ao[j]->l : esilmax;
            esinmax = esinmax < es[i].elements[0]->ao[j]->n ? es[i].elements[0]->ao[j]->n : esinmax;
            nl[es[i].elements[0]->ao[j]->l] += es[i].elements[0]->ao[j]->m == 0;
        }
        
        msym_orbital_t *(*esomap)[esinmax+1][esilmax+1][2*esilmax+1] = omap;
        
        memset(esomap,0,sizeof(msym_orbital_t *[es->length][esinmax+1][esilmax+1][2*esilmax+1]));
        for(int a = 0;a < es[i].length;a++){
            for(int ao = 0;ao < es[i].elements[a]->aol;ao++){
                msym_orbital_t *o = es[i].elements[a]->ao[ao];
                esomap[a][o->n][o->l][o->m+o->l] = o;
            }
        }
        
        memset(lspan,0,sizeof(double[lmax+1][pg->ct->l]));
        
        for(int l = 0;l <= esilmax;l++){
            int d = es[i].length*lts[l].d;
            double (*mlproj)[d][d] = mproj[l];
            memset(mlproj,0,sizeof(double[pg->ct->l][d][d]));
            memset(ispan,0,sizeof(int[pg->ct->l]));
            
            for(int s = 0;s < pg->sopsl;s++){
                double (*lt)[lts[l].d][lts[l].d] = lts[l].t;
                permutationMatrix(&perm[i][s], mperm);
                kron(perm[i][s].p_length,mperm,lts[l].d,lt[s],d,mkron);
                
                //printSymmetryOperation(&pg->sops[s]);
                //printTransform(d, d, mkron);
                
                for(int k = 0;k < pg->ct->l;k++){
                    lspan[l][k] += pg->ct->irrep[k].v[pg->sops[s].cla]*mltrace(d, mkron);
                    mlscale(pg->ct->irrep[k].v[pg->sops[s].cla], d, mkron, mlproj[pg->ct->l]); //mproj[pg->ct.l] is a workspace
                    mladd(d, mlproj[pg->ct->l], mlproj[k], mlproj[k]); //Could do this based on the span later, but it's not a huge amount of work
                }
            }
            memset(mlproj[pg->ct->l],0,sizeof(double[d][d]));
            int nirrepl = 0;
            for(int k = 0;k < pg->ct->l;k++){
                int lirrepl = nirrepl;
                msym_subspace_t *ss = &iss[k].subspace[i];
                ispan[k] = (((int)round(lspan[l][k]))/pg->order);
                mlscale(((double) pg->ct->irrep[k].d)/pg->order, d, mlproj[k], mlproj[k]);
                nirrepl = mgs(d, mlproj[k], mlproj[pg->ct->l], nirrepl, thresholds->orthogonalization/basisl);
                
                if(nirrepl - lirrepl != ispan[k]*pg->ct->irrep[k].d){
                    //printTransform(d, d, mlproj[k]);
                    ret = MSYM_ORBITAL_ERROR;
                    msymSetErrorDetails("Ortogonal subspace of dimension (%d) inconsistent with span (%d) in %s",nirrepl - lirrepl,ispan[k]*pg->ct->irrep[k].d,pg->ct->irrep[k].name);
                    goto err;
                    
                }
                
                ss->type = ATOMIC_ORBITAL;
                ss->irrep = k;
                
                if(ispan[k] > 0){
                    ss->subspace = realloc(ss->subspace, sizeof(msym_subspace_t[ss->subspacel+nl[l]]));
                    for(int n = l+1; n <= esinmax;n++){
                        if(esomap[0][n][l][0] == NULL) continue;
                        
                        aspan[k] += ispan[k]*pg->ct->irrep[k].d;
                        msym_subspace_t *nss = &ss->subspace[ss->subspacel];
                        memset(nss,0,sizeof(msym_subspace_t));

                        nss->type = ATOMIC_ORBITAL;
                        nss->irrep = ss->irrep;
                        nss->d = ispan[k]*pg->ct->irrep[k].d;
                        double (*space)[d] = malloc(sizeof(double[nss->d][d]));
                        for(int dim = 0; dim < ss->subspace[ss->subspacel].d;dim++){
                            vlnorm2(d, mlproj[pg->ct->l][lirrepl+dim], space[dim]);
                        }
                        nss->space = (double*) space;
                        nss->basisl = 0;
                        nss->basis.o = malloc(sizeof(msym_orbital_t *[d]));
                        for(int e = 0;e < es[i].length;e++){
                            for(int m = -l;m <= l;m++){
                                nss->basis.o[nss->basisl++] = esomap[e][n][l][m+l];
                            }
                        }
                        ss->subspacel++;
                        if(nss->basisl != d) {
                            ret = MSYM_ORBITAL_ERROR;
                            msymSetErrorDetails("Basis length (%d) inconsistent with projection operator dimensions (%d)",nss->basisl,d);
                            goto err;
                        }
                    }
                }
            }
        }
    }

    printf("Subspace span (vectors) = ");
    for(int k = 0;k < pg->ct->l;k++){
        printf(" + %d%s",aspan[k],pg->ct->irrep[k].name);
    }
    printf("\n");
    
    msym_subspace_t tss = {.subspacel = pg->ct->l, .subspace = iss, .d = 0, .basisl = 0, .space = NULL};
    filterSubspace(&tss);
    *subspace = tss.subspace;
    *subspacel = tss.subspacel;
    *pspan = aspan;
    
    free(omap);
    free(nl);
    free(ispan);
    free(lspan);
    free(mproj);
    free(mperm);
    free(mkron);
    for(int l = 0;l <= lmax;l++){
        free(lts[l].t);
    }
    free(lts);
    
    return ret;
    
err:
    free(aspan);
    free(omap);
    free(nl);
    free(ispan);
    free(lspan);
    free(mproj);
    free(mperm);
    free(mkron);
    for(int l = 0;l < lmax;l++){
        free(lts[l].t);
    }
    free(lts);
    for(int k = 0;k < pg->ct->l;k++){
        freeSubspace(&iss[k]);
    }
    free(iss);
    return ret;
}

msym_error_t getOrbitalSubspaces(int ssl, msym_subspace_t ss[ssl], int basisl, msym_orbital_t basis[basisl], double c[basisl][basisl]){
    msym_error_t ret = MSYM_SUCCESS;
    int index = 0;
    memset(c,0,sizeof(double[basisl][basisl]));
    for(int i = 0;i < ssl;i++){
        if(MSYM_SUCCESS != (ret = getOrbitalSubspaceCoefficients(&ss[i],basisl,basis,&index,c))) goto err;
    }
    
    if(index != basisl){
        msymSetErrorDetails("Subspace index (%d) does not match basis length (%d)",index,basisl);
        ret = MSYM_INVALID_SUBSPACE;
        goto err;
    }
    
    return ret;
err:
    return ret;
}