void OutputNode::printPart(std::ostream &stream, int part) const{ if(part==0){ if(ndep()>1) stream << "["; } else if(part==ndep()){ if(ndep()>1) stream << "]"; stream << "{" << oind_ << "}"; } else { stream << ","; } }
std::string SXNode::printCompact(std::map<const SXNode*, int>& nodeind, std::vector<std::string>& intermed) const { // Get reference to node index int& ind = nodeind[this]; // If positive, already in intermediate expressions if (ind>0) { stringstream ss; ss << "@" << ind; return ss.str(); } // Get expressions for dependencies std::string arg[2]; for (int i=0; i<ndep(); ++i) { arg[i] = dep(i)->printCompact(nodeind, intermed); } // Get expression for this string s = print(arg[0], arg[1]); // Decide what to do with the expression if (ind==0) { // Inline expression return s; } else { // Add to list of intermediate expressions and return reference intermed.push_back(s); ind = intermed.size(); // For subsequent references stringstream ss; ss << "@" << ind; return ss.str(); } }
void EvaluationMX::printPart(std::ostream &stream, int part) const { if (part == 0) { stream << fcn_ << ".call(["; } else if (part == ndep()) { stream << "])"; } else { stream << ","; } }
void Vertcat::printPart(std::ostream &stream, int part) const { if (part==0) { stream << "vertcat("; } else if (part==ndep()) { stream << ")"; } else { stream << ", "; } }
std::string Call::print(const std::vector<std::string>& arg) const { stringstream ss; ss << fcn_.name() << "("; for (int i=0; i<ndep(); ++i) { if (i!=0) ss << ", "; ss << arg.at(i); } ss << ")"; return ss.str(); }
void Call::evalFwd(const vector<vector<MX> >& fseed, vector<vector<MX> >& fsens) { // Nondifferentiated inputs and outputs vector<MX> arg(ndep()); for (int i=0; i<arg.size(); ++i) arg[i] = dep(i); vector<MX> res(nout()); for (int i=0; i<res.size(); ++i) res[i] = getOutput(i); // Call the cached functions fcn_.forward(arg, res, fseed, fsens); }
void Diagcat::evaluateMX(const MXPtrV& input, MXPtrV& output, const MXPtrVV& fwdSeed, MXPtrVV& fwdSens, const MXPtrVV& adjSeed, MXPtrVV& adjSens, bool output_given) { int nfwd = fwdSens.size(); int nadj = adjSeed.size(); // Non-differentiated output if (!output_given) { *output[0] = diagcat(getVector(input)); } // Forward sensitivities for (int d = 0; d<nfwd; ++d) { *fwdSens[d][0] = diagcat(getVector(fwdSeed[d])); } // Quick return? if (nadj==0) return; // Get offsets for each row and column vector<int> offset1(ndep()+1, 0); vector<int> offset2(ndep()+1, 0); for (int i=0; i<ndep(); ++i) { int ncol = dep(i).sparsity().size2(); int nrow = dep(i).sparsity().size1(); offset2[i+1] = offset2[i] + ncol; offset1[i+1] = offset1[i] + nrow; } // Adjoint sensitivities for (int d=0; d<nadj; ++d) { MX& aseed = *adjSeed[d][0]; vector<MX> s = diagsplit(aseed, offset1, offset2); aseed = MX(); for (int i=0; i<ndep(); ++i) { adjSens[d][i]->addToSum(s[i]); } } }
void SXNode::canInline(std::map<const SXNode*, int>& nodeind) const { // Add or mark node in map std::map<const SXNode*, int>::iterator it=nodeind.find(this); if (it==nodeind.end()) { // First time encountered, mark inlined nodeind.insert(it, make_pair(this, 0)); // Handle dependencies with recursion for (int i=0; i<ndep(); ++i) { dep(i)->canInline(nodeind); } } else if (it->second==0 && getOp()!=OP_PARAMETER) { // Node encountered before, do not inline (except if symbolic primitive) it->second = -1; } }
void Call::evalAdj(const vector<vector<MX> >& aseed, vector<vector<MX> >& asens) { // Nondifferentiated inputs and outputs vector<MX> arg(ndep()); for (int i=0; i<arg.size(); ++i) arg[i] = dep(i); vector<MX> res(nout()); for (int i=0; i<res.size(); ++i) res[i] = getOutput(i); // Call the cached functions vector<vector<MX> > v; fcn_.reverse(arg, res, aseed, v); for (int i=0; i<v.size(); ++i) { for (int j=0; j<v[i].size(); ++j) { if (!v[i][j].is_empty()) { // TODO(@jaeandersson): Hack asens[i][j] += v[i][j]; } } } }
MX Concat::getGetNonzeros(const Sparsity& sp, const std::vector<int>& nz) const { // Get the first nonnegative nz int nz_test = -1; for (vector<int>::const_iterator i=nz.begin(); i!=nz.end(); ++i) { if (*i>=0) { nz_test = *i; break; } } // Quick return if none if (nz_test<0) return MX::zeros(sp); // Find out to which dependency it might depend int begin=0, end=0; int i; for (i=0; i<ndep(); ++i) { begin = end; end += dep(i).size(); if (nz_test < end) break; } // Check if any nz refer to a different nonzero for (vector<int>::const_iterator j=nz.begin(); j!=nz.end(); ++j) { if (*j>=0 && (*j < begin || *j >= end)) { // Fallback to the base class return MXNode::getGetNonzeros(sp, nz); } } // All nz refer to the same dependency, update the nonzero indices if (begin==0) { return dep(i)->getGetNonzeros(sp, nz); } else { vector<int> nz_new(nz); for (vector<int>::iterator j=nz_new.begin(); j!=nz_new.end(); ++j) { if (*j>=0) *j -= begin; } return dep(i)->getGetNonzeros(sp, nz_new); } }
/** \brief Get required length of arg field */ virtual size_t sz_arg() const { return ndep();}
/** \brief Does the node depend on other nodes*/ virtual bool hasDep() const {return ndep()>0; }