From a9df5b37da4f5cf9c7c502f600a9944cdaf3f527 Mon Sep 17 00:00:00 2001 From: tomsmeding Date: Sat, 28 Jan 2017 20:00:03 +0100 Subject: Initial --- .gitignore | 2 + Makefile | 22 +++++ main.cpp | 129 ++++++++++++++++++++++++ tree.cpp | 326 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ tree.h | 94 ++++++++++++++++++ 5 files changed, 573 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 main.cpp create mode 100644 tree.cpp create mode 100644 tree.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..df0f618 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.o +boog diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..e6d626b --- /dev/null +++ b/Makefile @@ -0,0 +1,22 @@ +CXX = g++ +CXXFLAGS = -Wall -Wextra -std=c++11 -g -fwrapv +LDFLAGS = +TARGET = boog + +.PHONY: all clean remake + +all: $(TARGET) + +clean: + rm -f *.o $(TARGET) + rm -rf *.dSYM + +remake: clean + make all + + +$(TARGET): $(patsubst %.cpp,%.o,$(wildcard *.cpp)) + $(CXX) $^ -o $@ $(LDFLAGS) + +%.o: %.cpp $(wildcard *.h) + $(CXX) $(CXXFLAGS) -c -o $@ $< diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..2b7e748 --- /dev/null +++ b/main.cpp @@ -0,0 +1,129 @@ +#include +#include +#include +#include +#include +#include +#include "tree.h" + +using namespace std; + + +struct Axiom{ + Tree from,to; +}; + +ostream& operator<<(ostream &os,const Axiom &ax){ + return os< "< &dst,const string &expr){ + size_t idx=expr.find('='); + bool twoway=true; + if(idx==string::npos){ + idx=expr.find('>'); + assert(idx!=string::npos); + twoway=false; + } + assert(expr.find('=',idx+1)==string::npos); + assert(expr.find('>',idx+1)==string::npos); + string from=expr.substr(0,idx),to=expr.substr(idx+1); + dst.push_back({Tree(from),Tree(to)}); + if(twoway)dst.push_back({Tree(to),Tree(from)}); +} + +vector importAxioms(const vector &list){ + vector axioms; + for(const string &str : list){ + parseAxiom(axioms,str); + } + return axioms; +} + +using Heuristic = int (*)(const Tree&); + +int heuristic(const Tree &tree){ + return tree.nleaves(); +} + +template +struct AscendingCompare{ + bool operator()(const Tree &a,const Tree &b) const { + return F(a)>F(b); + } +}; + +template +vector* deduceEq(const vector &axioms,const Tree &startTree,const Tree &target){ + priority_queue,AscendingCompare> pqu; + map parentMap; + pqu.push(startTree); + Tree current; + while(true){ + if(pqu.size()==0)return nullptr; + current=pqu.top(); + pqu.pop(); + cerr<<"current = "< *v=new vector(); + Tree *t=¤t; + while(true){ + // cerr<<"*t = "<<*t<push_back(*t); + auto it=parentMap.find(*t); + if(it==parentMap.end())break; + t=&it->second; + } + return v; +} + + +int main(){ + const vector axioms=importAxioms({ + // "([1]*[2])>([2]*[1])", + // "(([1]*[2])*[3])=([1]*([2]*[3]))", + + // "([1]*([1]*[2]))=[1]", + // "(([2]*[1])*[1])=[1]", + + // "[1]=([1]*[1])", + // "(([1]*[2])*[3])=(([2]*[3])*[1])", + + "[1]=[2]", + }); + const Tree t_from("(1*2)"),t_to("(2*1)"); + + for(const Axiom &ax : axioms)cout< *res=deduceEq(axioms,t_from,t_to); + if(res==nullptr){ + cout<<"No deduction"<size()-1;i>=0;i--){ + cout<at(i)< +#include +#include "tree.h" + +using namespace std; + + +int uniqid(){ + static int id=10; + return id++; +} + + +bool Variable::isOperator() const { + return id==0; +} + +bool Variable::isFixed() const { + return id<0; +} + +bool Variable::isTemp() const { + return id>0; +} + +bool Variable::operator==(Variable v) const { + return id==v.id; +} + +bool Variable::operator!=(Variable v) const { + return id!=v.id; +} + +Variable::operator int() const { + return id; +} + +namespace std { + size_t hash::operator()(Variable v) const { + return inthasher(v.id); + } +} + +ostream& operator<<(ostream &os,const Variable &v){ + assert(!v.isOperator()); + if(v.isFixed())return os<<-v.id; + else return os<<'['< ok, L="<<__LINE__< null, L="<<__LINE__<match(*pat.left,accum); + if(!as){ + //cerr<<" -> null, L="<<__LINE__<match(*pat.right,as); + if(!right_res){ + //cerr<<" -> null, L="<<__LINE__< null, L="<<__LINE__< ok, L="<<__LINE__<emplace(pat.v,*this); + //cerr<<" -> ok, L="<<__LINE__<find(pat.v); + if(it==accum->end()){ + accum->emplace(pat.v,*this); + //cerr<<" -> ok, L="<<__LINE__<second==*this){ + //cerr<<" -> ok, L="<<__LINE__< null, L="<<__LINE__<left=left->apply(as); + n->right=right->apply(as); + } else { + auto it=as.find(v); + if(it==as.end())n->v=v; + else *n=it->second; + } + return n; +} + +int Tree::Node::nleaves() const { + if(v.isOperator()){ + return left->nleaves()+right->nleaves(); + } else { + return 1; + } +} + +int Tree::Node::compare(const Node &other) const { + if(v.isTemp()&&other.v.isTemp())return 0; + if(vother.v)return 1; + if(!v.isOperator())return 0; + int c=left->compare(*other.left); + if(c!=0)return c; + return right->compare(*other.right); +} + +bool operator==(const Tree::Node &a,const Tree::Node &b){ + if(a.v.isTemp()&&b.v.isTemp())return true; + if(a.v!=b.v)return false; + if(!a.v.isOperator())return true; + return *a.left==*b.left&&*a.right==*b.right; +} + +bool operator!=(const Tree::Node &a,const Tree::Node &b){ + return !(a==b); +} + +ostream& operator<<(ostream &os,const Tree::Node &node){ + if(node.v.isOperator()){ + return os<<'('<<*node.left<<'*'<<*node.right<<')'; + } else { + return os<0); + idx=endp-data; + assert(data[idx]==']'); + idx++; + assert(!v.isOperator()); + return new Node(v); + } else { + char *endp; + const char *data=expr.data(); + assert(isdigit(data[idx])); + Variable v=-strtol(data+idx,&endp,10); + assert(endp-(data+idx)>0); + idx=endp-data; + assert(!v.isOperator()); + return new Node(v); + } +} + +Tree::Node* Tree::parseNode(const string &expr,size_t &idx){ + Node *l=parseTerm(expr,idx); + if(idx==expr.size())return l; + assert(expr[idx]=='*'); + idx++; + Node *r=parseTerm(expr,idx); + assert(idx==expr.size()||expr[idx]==')'); + return new Node(l,r); +} + +Tree::Tree():root(nullptr){} + +Tree::Tree(const string &expr){ + size_t idx=0; + root=parseNode(expr,idx); +} + +Tree::Tree(const Tree &other){ + if(root)delete root; + if(other.root){ + root=new Node(*other.root); + } else { + root=nullptr; + } +} + +Tree::~Tree(){ + if(root)delete root; +} + +Tree& Tree::operator=(const Tree &other){ + assert(other.root); + if(root)delete root; + root=new Node(*other.root); + return *this; +} + +bool Tree::matches(const Tree &pat) const { + assert(root&&pat.root); + Assign *as=root->match(*pat.root); + if(as){ + delete as; + return true; + } else { + return false; + } +} + +void Tree::replace(Node *subj,const Tree &pat,const Tree &repl,vector &accum){ + Assign *as=subj->match(*pat.root); + if(as){ + Node *res=repl.root->apply(*as); + Node backup=*subj; + *subj=*res; + accum.push_back(*this); + *subj=backup; + delete res; + delete as; + } + if(subj->left){ + replace(subj->left,pat,repl,accum); + replace(subj->right,pat,repl,accum); + } +} + +vector Tree::replace(const Tree &pat,const Tree &repl){ + assert(root&&pat.root); + vector res; + replace(root,pat,repl,res); + return res; +} + +int Tree::nleaves() const { + assert(root); + return root->nleaves(); +} + +int Tree::compare(const Tree &other) const { + assert(root&&other.root); + return root->compare(*other.root); +} + +bool TreeCompare::operator()(const Tree &a,const Tree &b) const { + return a.compare(b)<0; +} + +ostream& operator<<(ostream &os,const Tree &tree){ + return os<<*tree.root; +} diff --git a/tree.h b/tree.h new file mode 100644 index 0000000..7d8cf15 --- /dev/null +++ b/tree.h @@ -0,0 +1,94 @@ +#pragma once + +#include +#include +#include +#include + +using namespace std; + + +int uniqid(); + +struct Variable{ + int id; + + Variable(int id):id(id){} + + bool isOperator() const; + bool isFixed() const; + bool isTemp() const; + + bool operator==(Variable v) const; + bool operator!=(Variable v) const; + + operator int() const; +}; + +namespace std { + template <> + struct hash{ + hash inthasher; + size_t operator()(Variable v) const; + }; +} + +class Tree{ + struct Node; + + using Assign = unordered_map; + + struct Node{ + Variable v; + Node *left,*right; + + explicit Node(Variable v); + Node(Node *left,Node *right); + Node(const Node &other); + ~Node(); + + Node& operator=(const Node &other); + + Assign* match(const Node &pat,Assign *accum=nullptr) const; + + Node* apply(const Assign &as) const; + + int nleaves() const; + + int compare(const Node &other) const; + }; + + Node *root=nullptr; + + static Node* parseTerm(const string &expr,size_t &idx); + static Node* parseNode(const string &expr,size_t &idx); + + void replace(Node *subj,const Tree &pat,const Tree &repl,vector &accum); + +public: + Tree(); // Creates invalid tree + Tree(const string &expr); + Tree(const Tree &other); + ~Tree(); + + Tree& operator=(const Tree &other); + + bool matches(const Tree &pat) const; + vector replace(const Tree &pat,const Tree &repl); + + int nleaves() const; + + int compare(const Tree &other) const; + + friend ostream& operator<<(ostream &os,const Variable &v); + friend ostream& operator<<(ostream &os,const Node &node); + friend ostream& operator<<(ostream &os,const Tree &tree); + friend bool operator==(const Node &a,const Node &b); + friend bool operator!=(const Node &a,const Node &b); +}; + +struct TreeCompare{ + bool operator()(const Tree &a,const Tree &b) const; +}; + +ostream& operator<<(ostream &os,const Tree &tree); -- cgit v1.2.3