Term* Term::multiply(Term* t) { if(t->get_term_type() == CONSTANT_TERM) { ConstantTerm* ct = static_cast<ConstantTerm*>(t); return multiply(ct->get_constant()); } if(get_term_type() == CONSTANT_TERM) { ConstantTerm* ct = static_cast<ConstantTerm*>(this); return t->multiply(ct->get_constant()); } // non-linear multiplication: use an uninterpreted function vector<Term*> args; if(t < this) { args.push_back(t); args.push_back(this); } else { args.push_back(this); args.push_back(t); } Term* ft = FunctionTerm::make("multiply", args, false); return ft; }
void Term::get_vars(set<Term*>& vars) { term_type tt = get_term_type(); if (tt == CONSTANT_TERM) return; if (tt == VARIABLE_TERM) { VariableTerm* vt = (VariableTerm*) this; vars.insert(vt); return; } if (tt == FUNCTION_TERM) { FunctionTerm* ft = (FunctionTerm*) this; for (unsigned int i = 0; i < ft->get_args().size(); i++) { ft->get_args()[i]->get_vars(vars); } } else { assert(tt == ARITHMETIC_TERM); ArithmeticTerm* at = (ArithmeticTerm*) this; map<Term*, long int>::const_iterator it = at->get_elems().begin(); for (; it != at->get_elems().end(); it++) { it->first->get_vars(vars); } } }
Term* Term::substitute(Term* (*sub_func)(Term* t, void* data), void* my_data) { Term* new_t = (*sub_func)(this, my_data); if(new_t != this) { return new_t; } Term* res = NULL; switch (get_term_type()) { case CONSTANT_TERM: case VARIABLE_TERM: { res= this; break; } case FUNCTION_TERM: { FunctionTerm* ft = (FunctionTerm*) this; const vector<Term*>& args = ft->get_args(); vector<Term*> new_args; bool changed = false; for (unsigned int i = 0; i < args.size(); i++) { Term* new_arg = args[i]->substitute(sub_func, my_data); if (new_arg != args[i]) changed = true; new_args.push_back(new_arg); } if (!changed) { res = this; break; } res= FunctionTerm::make(ft->get_id(), new_args, ft->is_invertible()); break; } case ARITHMETIC_TERM: { ArithmeticTerm* at = (ArithmeticTerm*) this; bool changed = false; map<Term*, long int> new_elems; map<Term*, long int>::const_iterator it = at->get_elems().begin(); for (; it != at->get_elems().end(); it++) { Term* new_t = it->first->substitute(sub_func, my_data); if (new_t != it->first) changed = true; new_elems[new_t]+= it->second; } if (!changed) { res = at; break; } res = ArithmeticTerm::make(new_elems, at->get_constant()); break; } default: assert(false); } return res; }
Term* Term::rename_variables(map<int, int>& replacements) { switch (get_term_type()) { case CONSTANT_TERM: return this; case VARIABLE_TERM: { VariableTerm* vt = (VariableTerm*) this; int var_id = vt->get_var_id(); if (replacements.count(var_id)==0) return this; Term* res= VariableTerm::make(replacements[var_id]); return res; } case FUNCTION_TERM: { FunctionTerm* ft = (FunctionTerm*) this; const vector<Term*>& args = ft->get_args(); vector<Term*> new_args; bool changed = false; for (unsigned int i = 0; i < args.size(); i++) { Term* new_arg = args[i]->rename_variables(replacements); if (new_arg != args[i]) changed = true; new_args.push_back(new_arg); } if (!changed) return this; Term* res= FunctionTerm::make(ft->get_id(), new_args, ft->is_invertible()); return res; } case ARITHMETIC_TERM: { ArithmeticTerm* at = (ArithmeticTerm*) this; bool changed = false; map<Term*, long int> new_elems; map<Term*, long int>::const_iterator it = at->get_elems().begin(); for (; it != at->get_elems().end(); it++) { Term* new_t = it->first->rename_variables(replacements); if (new_t != it->first) changed = true; new_elems[new_t] += it->second; } if (!changed) return at; Term* res= ArithmeticTerm::make(new_elems, at->get_constant()); return res; } default: assert(false); } }
Term* Term::rename_variable(int old_var_id, int new_var_id) { switch (get_term_type()) { case CONSTANT_TERM: return this; case VARIABLE_TERM: { VariableTerm* vt = (VariableTerm*) this; if (old_var_id != vt->get_var_id()) return this; Term* res = VariableTerm::make(new_var_id); return res; } case FUNCTION_TERM: { FunctionTerm* ft = (FunctionTerm*) this; const vector<Term*>& args = ft->get_args(); map<Term*, Term*> old_to_new; bool changed = false; for (unsigned int i = 0; i < args.size(); i++) { Term* old_arg = args[i]; Term* new_arg = args[i]->rename_variable(old_var_id, new_var_id); if (new_arg != args[i]) changed = true; old_to_new[old_arg] = new_arg; } if (!changed) return this; Term* res = ft->substitute(old_to_new); return res; } case ARITHMETIC_TERM: { ArithmeticTerm* at = (ArithmeticTerm*) this; bool changed = false; map<Term*, long int> new_elems; map<Term*, long int>::const_iterator it = at->get_elems().begin(); for (; it != at->get_elems().end(); it++) { Term* new_t = it->first->rename_variable(old_var_id, new_var_id); if (new_t != it->first) changed = true; new_elems[new_t] += it->second; } if (!changed) return at; Term* res = ArithmeticTerm::make(new_elems, at->get_constant()); return res; } default: assert(false); } }
/** * Create a list of terms in the specified condition. * * If there are no terms in the condition, 'term_list' will be NULL. * * @param py_dict A Python dict containing terms. Must not be NULL. * @param term_list Pointer to a GSList which will be set to the newly * created list of terms. Must not be NULL. * * @return SRD_OK upon success, a negative error code otherwise. */ static int create_term_list(PyObject *py_dict, GSList **term_list) { Py_ssize_t pos = 0; PyObject *py_key, *py_value; struct srd_term *term; uint64_t num_samples_to_skip; char *term_str; if (!py_dict || !term_list) return SRD_ERR_ARG; /* "Create" an empty GSList of terms. */ *term_list = NULL; /* Iterate over all items in the current dict. */ while (PyDict_Next(py_dict, &pos, &py_key, &py_value)) { /* Check whether the current key is a string or a number. */ if (PyLong_Check(py_key)) { /* The key is a number. */ /* TODO: Check if the number is a valid channel. */ /* Get the value string. */ if ((py_pydictitem_as_str(py_dict, py_key, &term_str)) != SRD_OK) { srd_err("Failed to get the value."); return SRD_ERR; } term = g_malloc0(sizeof(struct srd_term)); term->type = get_term_type(term_str); term->channel = PyLong_AsLong(py_key); g_free(term_str); } else if (PyUnicode_Check(py_key)) { /* The key is a string. */ /* TODO: Check if it's "skip". */ if ((py_pydictitem_as_long(py_dict, py_key, &num_samples_to_skip)) != SRD_OK) { srd_err("Failed to get number of samples to skip."); return SRD_ERR; } term = g_malloc0(sizeof(struct srd_term)); term->type = SRD_TERM_SKIP; term->num_samples_to_skip = num_samples_to_skip; term->num_samples_already_skipped = 0; } else { srd_err("Term key is neither a string nor a number."); return SRD_ERR; } /* Add the term to the list of terms. */ *term_list = g_slist_append(*term_list, term); } return SRD_OK; }
void Term::get_attributes(set<CNode*> & attributes) { CNode* attrib_c = NULL; if(attribute == TERM_ATTRIB_GEQZ) { attrib_c = ILPLeaf::make(this, ConstantTerm::make(0), ILP_GEQ); } else if(attribute == TERM_ATTRIB_GTZ) { attrib_c = ILPLeaf::make(this, ConstantTerm::make(0), ILP_GT); } if(attrib_c != NULL) attributes.insert(attrib_c); switch(get_term_type()) { case FUNCTION_TERM: { FunctionTerm* ft = (FunctionTerm*) this; const vector<Term*> & args = ft->get_args(); for(unsigned int i=0; i<args.size(); i++) { Term* t = args[i]; t->get_attributes(attributes); } break; } case ARITHMETIC_TERM: { ArithmeticTerm* at = (ArithmeticTerm*) this; const map<Term*, long int> & elems = at->get_elems(); map<Term*, long int>::const_iterator it= elems.begin(); for(; it!= elems.end(); it++) { Term* t = it->first; t->get_attributes(attributes); } break; } default: break; } }
void Term::get_nested_terms(set<Term*>& terms, bool include_function_subterms, bool include_constants) { if(! include_constants && get_term_type() == CONSTANT_TERM) return; if(terms.count(this) > 0) return; terms.insert(this); switch(this->get_term_type()) { case CONSTANT_TERM: case VARIABLE_TERM: return; case FUNCTION_TERM: { if(!include_function_subterms) return; FunctionTerm* ft = (FunctionTerm*) this; const vector<Term*>& args = ft->get_args(); for(unsigned int i=0; i< args.size(); i++) { args[i]->get_nested_terms(terms, include_function_subterms, include_constants); } return; } case ARITHMETIC_TERM: { ArithmeticTerm* at = (ArithmeticTerm*) this; const map<Term*, long int>& elems = at->get_elems(); map<Term*, long int>::const_iterator it = elems.begin(); for(; it!= elems.end(); it++) { it->first->get_nested_terms(terms, include_function_subterms, include_constants); } return; } default: assert(false); } }