std::vector<Sparsity> LrDpleInternal::getSparsity(const std::map<std::string, std::vector<Sparsity> >& st, const std::vector< std::vector<int> > &Hs_) { // Chop-up the arguments std::vector<Sparsity> As, Vs, Cs, Hs; if (st.count("a")) As = st.at("a"); if (st.count("v")) Vs = st.at("v"); if (st.count("c")) Cs = st.at("c"); if (st.count("h")) Hs = st.at("h"); bool with_H = !Hs.empty(); int K = As.size(); Sparsity A; if (K==1) { A = As[0]; } else { Sparsity AL = diagcat(vector_slice(As, range(As.size()-1))); Sparsity AL2 = horzcat(AL, Sparsity(AL.size1(), As[0].size2())); Sparsity AT = horzcat(Sparsity(As[0].size1(), AL.size2()), As.back()); A = vertcat(AT, AL2); } Sparsity V = diagcat(Vs.back(), diagcat(vector_slice(Vs, range(Vs.size()-1)))); Sparsity C; if (!Cs.empty()) { C = diagcat(Cs.back(), diagcat(vector_slice(Cs, range(Cs.size()-1)))); } Sparsity H; std::vector<int> Hs_agg; std::vector<int> Hi(1, 0); if (Hs_.size()>0 && with_H) { H = diagcat(Hs.back(), diagcat(vector_slice(Hs, range(Hs.size()-1)))); casadi_assert(K==Hs_.size()); for (int k=0;k<K;++k) { Hs_agg.insert(Hs_agg.end(), Hs_[k].begin(), Hs_[k].end()); int sum=0; for (int i=0;i<Hs_[k].size();++i) { sum+= Hs_[k][i]; } Hi.push_back(Hi.back()+sum); } } Sparsity res = LrDleInternal::getSparsity(make_map("a", A, "v", V, "c", C, "h", H), Hs_agg); if (with_H) { return diagsplit(res, Hi); } else { return diagsplit(res, As[0].size2()); } }
std::vector<Sparsity> horzsplit(const Sparsity& sp, const std::vector<int>& offset){ // Consistency check casadi_assert(offset.size()>=1); casadi_assert(offset.front()==0); casadi_assert_message(offset.back()==sp.size2(),"horzsplit(Sparsity,std::vector<int>): Last elements of offset (" << offset.back() << ") must equal the number of columns (" << sp.size2() << ")"); casadi_assert(isMonotone(offset)); // Number of outputs int n = offset.size()-1; // Get the sparsity of the input const vector<int>& colind_x = sp.colind(); const vector<int>& row_x = sp.row(); // Allocate result std::vector<Sparsity> ret; ret.reserve(n); // Sparsity pattern as CCS vectors vector<int> colind, row; int ncol, nrow = sp.size1(); // Get the sparsity patterns of the outputs for(int i=0; i<n; ++i){ int first_col = offset[i]; int last_col = offset[i+1]; ncol = last_col - first_col; // Construct the sparsity pattern colind.resize(ncol+1); copy(colind_x.begin()+first_col, colind_x.begin()+last_col+1, colind.begin()); for(vector<int>::iterator it=colind.begin()+1; it!=colind.end(); ++it) *it -= colind[0]; colind[0] = 0; row.resize(colind.back()); copy(row_x.begin()+colind_x[first_col],row_x.begin()+colind_x[last_col],row.begin()); // Append to the list ret.push_back(Sparsity(nrow,ncol,colind,row)); } // Return (RVO) return ret; }
MX GenericCall::projectArg(const MX& x, const Sparsity& sp, int i) { if (x.size()==sp.size()) { // Insert sparsity projection nodes if needed return project(x, sp); } else { // Different dimensions if (x.is_empty() || sp.is_empty()) { // NOTE: To permissive? // Replace nulls with zeros of the right dimension return MX::zeros(sp); } else if (x.is_scalar()) { // Scalar argument means set all return MX(sp, x); } else if (x.size1()==sp.size2() && x.size2()==sp.size1() && sp.is_vector()) { // Transposed vector return projectArg(x.T(), sp, i); } else { // Mismatching dimensions casadi_error("Cannot create function call node: Dimension mismatch for argument " << i << ". Argument has shape " << x.size() << " but function input has shape " << sp.size()); } } }