bool SpidirParams::order(SpeciesTree *stree) { if (stree->nnodes != nsnodes) { printError("wrong number of parameters: %d %d\n", stree->nnodes, nsnodes); return false; } ExtendArray<Node*> nodeorder(0, stree->nnodes); getTreePreOrder(stree, &nodeorder); // make interior node names ExtendArray<int> inodes(stree->nnodes); int inodename = 1; for (int i=0; i<stree->nnodes; i++) { Node *node = nodeorder[i]; if (node->isLeaf()) { inodes[node->name] = -1; } else { inodes[node->name] = inodename++; } } // loop through preordered nodes to construct permutation ExtendArray<int> invperm(0, stree->nnodes); for (int j=0; j<nsnodes; j++) { if (invperm.size() != j) { printError("unable to match '%s' to the species tree", names[j].c_str()); return false; } // try to parse node id as an int int id; bool isint = (sscanf(names[j].c_str(), "%d", &id) == 1); for (int i=0; i<stree->nnodes; i++) { if (stree->nodes[i]->isLeaf()) { // if leaf, check if names match if (names[j] == stree->nodes[i]->longname) { invperm.append(i); break; } } else { if (isint && id == inodes[i]) { invperm.append(i); break; } } } } // apply permutation ExtendArray<int> perm(stree->nnodes); invertPerm(invperm, perm, nsnodes); permute(names, perm, nsnodes); permute(sp_alpha, perm, nsnodes); permute(sp_beta, perm, nsnodes); return true; }
skyline_lu(const Matrix &A, const params &prm = params()) : n( backend::rows(A) ), perm(n), ptr(n + 1, 0), D(n, 0), y(n) { typedef typename backend::row_iterator<Matrix>::type row_iterator; // Find the permutation for the ordering. ordering::get(A, perm); // Get inverse permutation std::vector<int> invperm(n); for(int i = 0; i < n; ++i) invperm[perm[i]] = i; /* Let us find how large the rows of L and the columns of U should * be. Provisionally, we will store in ptr[i] the minimum required * height of column i over the diagonal, and length of row i below * the diagonal. The value(i,j) in the reordered matrix will be * the same as the value(perm[i],perm[j]) in the original matrix; * or, the value(i,j) in the original matrix will be the same as * value(invperm[i],invperm[j]) in the reordered matrix. */ // Traverse the matrix finding nonzero elements for(int i = 0; i < n; ++i) { for(row_iterator a = backend::row_begin(A, i); a; ++a) { int j = a.col(); real v = a.value(); int newi = invperm[i]; int newj = invperm[j]; if (v != 0) { if (newi > newj) { // row newi needs length at least newi - newj if (ptr[newi] < newi - newj) ptr[newi]= newi - newj; } else if (newi < newj) { // column newj needs height at least newj - newi if (ptr[newj] < newj - newi) ptr[newj]= newj - newi; } } } } // Transform ptr so that it doesn't contain the required lengths // and heights, but the indexes to the entries { int last = 0; for(int i = 1; i <= n; ++i) { int tmp = ptr[i]; ptr[i] = ptr[i-1] + last; last = tmp; } } // Allocate variables for skyline format entries L.resize(ptr.back(), 0); U.resize(ptr.back(), 0); // And finally traverse again the CSR matrix, copying its entries // into the correct places in the skyline format for(int i = 0; i < n; ++i) { for(row_iterator a = backend::row_begin(A, i); a; ++a) { int j = a.col(); real v = a.value(); int newi = invperm[i]; int newj = invperm[j]; if (v != 0) { if (newi < newj) { U[ ptr[newj + 1] + newi - newj ] = v; } else if (newi == newj) { D[newi] = v; } else /* newi > newj */ { L[ ptr[newi + 1] + newj - newi ] = v; } } } } factorize(); }