Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DON'T MERGE: Example matching decision trees for sample patterns #1482

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
2 changes: 2 additions & 0 deletions CMakeLists.txt
Expand Up @@ -666,6 +666,8 @@ if (BUILD_BENCHMARKS)
add_subdirectory(benchmarks)
endif()

add_subdirectory(matchpygen)

# At the end we print a nice summary

message("--------------------------------------------------------------------------------")
Expand Down
21 changes: 21 additions & 0 deletions matchpygen/CMakeLists.txt
@@ -0,0 +1,21 @@
project(matchpygen)

include_directories(BEFORE ${symengine_SOURCE_DIR})
include_directories(BEFORE ${symengine_BINARY_DIR})
include_directories(BEFORE ${teuchos_SOURCE_DIR})
include_directories(BEFORE ${teuchos_BINARY_DIR})

add_executable(example example.cpp)
target_link_libraries(example symengine)

add_executable(example_yield example_yield.cpp)
target_link_libraries(example_yield symengine)

add_executable(example_coroutine example_coroutine.cpp)
target_link_libraries(example_coroutine symengine)

add_executable(example_coroutine2 example_coroutine2.cpp)
target_link_libraries(example_coroutine2 symengine)

add_executable(example_setjmp example_setjmp.cpp)
target_link_libraries(example_setjmp symengine)
132 changes: 132 additions & 0 deletions matchpygen/example.cpp
@@ -0,0 +1,132 @@
#include <iostream>
#include <tuple>
#include <map>
#include <string>
#include <deque>

#include <symengine/basic.h>
#include <symengine/pow.h>

using namespace std;
using namespace SymEngine;

typedef map<string, RCP<const Basic>> Substitution2;

int try_add_variable(Substitution2 &subst, string variable_name,
RCP<const Basic> &replacement)
{
if (subst.find(variable_name) == subst.end()) {
subst[variable_name] = replacement;
// this[variable_name] = replacement; //.copy() if
// isinstance(replacement, Multiset) else replacement
} else {
// Node &existing_value = *(this->find(variable_name));
/*
if (isinstance(existing_value, tuple)) {
if (isinstance(replacement, Multiset)) {
if (Multiset(existing_value) != replacement){
return -1;
}
} else if (replacement != existing_value) {
return -1;
}
else if (isinstance(existing_value, Multiset)) {
if (!isinstance(replacement, (tuple, list, Multiset))) {
return -1;
}
auto &compare_value = Multiset(replacement);
if (existing_value == compare_value){
if (! isinstance(replacement, Multiset)) {
this->insert(make_pair(variable_name, replacement));
} else {
return -1;
}
} else if (replacement != existing_value){
return -1;
}
}
}
*/
}
return 0;
}

typedef deque<RCP<const Basic>> Deque;

Deque get_deque(RCP<const Basic> expr)
{
Deque d;
for (RCP<const Basic> i : expr->get_args()) {
d.push_back(i);
}
return d;
}

tuple<int, Substitution2> match_root(RCP<const Basic> subject)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's ok to use std::variant here, if that's what is intended.

For older compilers, we can provide a compatible implementation, say using Boost variant, i.e., by having SymEngine::variant, that will be equal to std::variant for compilers that support it, and boost::variant for older compilers. For now just use std::variant.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, std::variant was meant to be used in the other PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The return type is a tuple, the integer stands for the rule number (e.g. RUBI rules are numbered), while Substitution2 is a map of wildcards to expressions to be substituted. Substitution2 is then used in a replacement pattern to return the result of the integration.

{
;
Deque subjects;
subjects.push_back(subject);
Substitution2 subst0;
// state 2200;
if (subjects.size() >= 1 && is_a<Pow>(*subjects[0])) {
RCP<const Basic> tmp1 = subjects.front();
subjects.pop_front();
Deque subjects2 = get_deque(tmp1);
// state 2201;
if (subjects2.size() >= 1 && subjects2[0]->__eq__(*symbol("x"))) {
RCP<const Basic> tmp3 = subjects2.front();
subjects2.pop_front();
// state 2202;
if (subjects2.size() >= 1) {
auto tmp4 = subjects2.front();
subjects2.pop_front();
Substitution2 subst1(subst0);
if (!try_add_variable(subst1, "i2", tmp4)) {
// state 2203;
if (subjects2.size() == 0) {
// state 2204;
if (subjects.size() == 0) {
Substitution2 tmp_subst;
tmp_subst["w"] = subst1["i2"];
// 0: x**w;
return make_tuple(0, tmp_subst);
}
}
}
subjects2.push_front(tmp4);
}
subjects2.push_front(tmp3);
}
subjects.push_front(tmp1);
}
if (subjects.size() >= 1 && subjects[0]->__eq__(*symbol("y"))) {
auto &tmp6 = subjects.front();
subjects.pop_front();
// state 2205;
if (subjects.size() == 0) {
// 1: y;
return make_tuple(1, subst0);
}
subjects.push_front(tmp6);
}
return make_tuple(-1, subst0);
};

int main(int argc, char *argv[])
{
// Allowed patterns: x^w, y. w is a wildcard.
RCP<const Basic> expr;
RCP<const Basic> x = symbol("x");
expr = pow(x, integer(3));
auto result = match_root(expr);
RCP<const Basic> y = symbol("y");
std::cout << "Result for " << expr->__str__() << " is " << get<0>(result)
<< std::endl;
result = match_root(y);
std::cout << "Result for " << y->__str__() << " is " << get<0>(result)
<< std::endl;
result = match_root(x);
std::cout << "Result for " << x->__str__() << " is " << get<0>(result)
<< std::endl;
}
124 changes: 124 additions & 0 deletions matchpygen/example_coroutine.cpp
@@ -0,0 +1,124 @@
#include <iostream>
#include <tuple>
#include <map>
#include <string>
#include <deque>

#include <symengine/basic.h>
#include <symengine/pow.h>

#include "coroutine.h"

using namespace std;
using namespace SymEngine;

typedef map<string, RCP<const Basic>> Substitution2;

int try_add_variable(Substitution2 &subst, string variable_name,
RCP<const Basic> &replacement)
{
if (subst.find(variable_name) == subst.end()) {
subst[variable_name] = replacement;
} else {
}
return 0;
}

typedef deque<RCP<const Basic>> Deque;

Deque get_deque(RCP<const Basic> expr)
{
Deque d;
for (RCP<const Basic> i : expr->get_args()) {
d.push_back(i);
}
return d;
}

coroutine::Channel<tuple<int, Substitution2>> channel;

void yield(tuple<int, Substitution2> val)
{
channel.push(val);
coroutine::yield();
}

void match_root(RCP<const Basic> subject)
{
Deque subjects;
subjects.push_back(subject);
Substitution2 subst0;
// state 2200;
if (subjects.size() >= 1 && is_a<Pow>(*subjects[0])) {
RCP<const Basic> tmp1 = subjects.front();
subjects.pop_front();
Deque subjects2 = get_deque(tmp1);
// state 2201;
if (subjects2.size() >= 1 && subjects2[0]->__eq__(*symbol("x"))) {
RCP<const Basic> tmp3 = subjects2.front();
subjects2.pop_front();
// state 2202;
if (subjects2.size() >= 1) {
auto tmp4 = subjects2.front();
subjects2.pop_front();
Substitution2 subst1(subst0);
if (!try_add_variable(subst1, "i2", tmp4)) {
// state 2203;
if (subjects2.size() == 0) {
// state 2204;
if (subjects.size() == 0) {
Substitution2 tmp_subst;
tmp_subst["w"] = subst1["i2"];
// 0: x**w;
yield(make_tuple(0, tmp_subst));
}
}
}
subjects2.push_front(tmp4);
}
subjects2.push_front(tmp3);
}
subjects.push_front(tmp1);
}
if (subjects.size() >= 1 && subjects[0]->__eq__(*symbol("y"))) {
auto &tmp6 = subjects.front();
subjects.pop_front();
// state 2205;
if (subjects.size() == 0) {
// 1: y;
yield(make_tuple(1, subst0));
}
subjects.push_front(tmp6);
}
yield(make_tuple(-1, subst0));
};

int main(int argc, char *argv[])
{
// Allowed patterns: x^w, y. w is a wildcard.
RCP<const Basic> expr;
RCP<const Basic> x = symbol("x");

expr = pow(x, integer(3));
coroutine::routine_t mr1 = coroutine::create(std::bind(match_root, expr));
coroutine::resume(mr1);
auto result = channel.pop();
coroutine::destroy(mr1);

RCP<const Basic> y = symbol("y");
std::cout << "Result for " << expr->__str__() << " is " << get<0>(result)
<< std::endl;
mr1 = coroutine::create(std::bind(match_root, y));
coroutine::resume(mr1);
result = channel.pop();
coroutine::destroy(mr1);

std::cout << "Result for " << y->__str__() << " is " << get<0>(result)
<< std::endl;
mr1 = coroutine::create(std::bind(match_root, x));
coroutine::resume(mr1);
result = channel.pop();
coroutine::destroy(mr1);
std::cout << "Result for " << x->__str__() << " is " << get<0>(result)
<< std::endl;
}