From 34ac9a7565cddd8d00e56e77ed5760aef92182c9 Mon Sep 17 00:00:00 2001 From: HangZhiYang <49983713+HangZhiYang@users.noreply.github.com> Date: Thu, 2 May 2019 19:43:26 +0800 Subject: [PATCH] =?UTF-8?q?=E5=86=99=E4=BA=86=E5=BE=88=E5=A4=9A=E6=B3=A8?= =?UTF-8?q?=E9=87=8A=EF=BC=8C=E5=88=A0=E4=BA=86=E4=B8=80=E5=A0=86=E6=B2=A1?= =?UTF-8?q?=E7=94=A8=E7=9A=84=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- graph.cpp | 22 +++++----------------- graph.h | 23 ++++++++++------------- main.cpp | 54 ++++++++++++++++++++++++++---------------------------- node.cpp | 39 ++++----------------------------------- node.h | 44 ++++++++++++++++++++++++-------------------- onepn.cpp | 21 +++++++++++++++++++++ onepn.h | 2 +- twopn.cpp | 17 +++++++++++++++++ zeropn.cpp | 20 ++++++++------------ zeropn.h | 5 ++--- 10 files changed, 118 insertions(+), 129 deletions(-) diff --git a/graph.cpp b/graph.cpp index d95a769..0455b1b 100644 --- a/graph.cpp +++ b/graph.cpp @@ -3,11 +3,7 @@ #include #include #include -bool asserted=0;//某一次运算是否已经给出error,避免重复输出 -Graph::Graph() -{ - cnt = 0; -} +bool asserted=0;//某一次eval是否已经给出error,避免重复输出 Node* Graph::operator[](const std::string str) { @@ -19,34 +15,26 @@ Node* Graph::operator[](const std::string str) void Graph::push(std::string str,Node* newnode) { - /*if(nodes[str]!=nullptr) - { - std::cout<<"Same name!"<second->reset(); asserted=0; nodes[nodename]->reset(); - } float Graph::eval(string nodename, const map &phMap) { ++cnt; - reset(nodename); - for(auto iter=phMap.begin(); iter != phMap.end(); iter++) + reset(nodename); + for(auto iter=phMap.begin(); iter != phMap.end(); iter++)//给placeholder赋值 nodes[iter->first]->setvalue(iter->second); outvalue[cnt] = nodes[nodename]->geteval(); - return nodes[nodename]->geteval(); + return outvalue[cnt]; } -void Graph::setvariable(string vname,float value) +void Graph::setvariable(string vname,float value) { ++cnt; nodes[vname]->setvalue(value); diff --git a/graph.h b/graph.h index 76adffd..47481ea 100644 --- a/graph.h +++ b/graph.h @@ -11,17 +11,14 @@ extern bool asserted; class Graph { - std::map nodes; - std::map nodesamename[50]; - std::map outvalue; - int size,cnt; - public: - Graph(); - - Node* operator[] (const string str);//鑾峰彇鑺傜偣 - void push(std::string str,Node* newnode); - void reset(string nodename); - float eval(string nodename, const map &phMap); - void setvariable(string vname,float value); - float lookupanswer(int t); + std::map nodes;//节点指针列表,由于有重名覆盖现象,所以不一定包括所有节点 + std::map outvalue;//计算结果历史纪录 + int cnt=0;//eval的次数 + public: + Node* operator[] (const string str);//已知节点名,获取节点指针 + void push(std::string str,Node* newnode);//加入新节点 + void reset(string nodename);//把某次eval的结果清除以便进行下一次计算 + float eval(string nodename, const map &phMap/*placeholder列表*/);//计算某节点数值,如果没有placeholder则phMap为空 + void setvariable(string vname,float value);//设置某个variable的值 + float lookupanswer(int t);//获取第t次eval的结果 }; diff --git a/main.cpp b/main.cpp index 05ce61c..777e640 100644 --- a/main.cpp +++ b/main.cpp @@ -3,7 +3,6 @@ #include #include #include -// #include #include #include "node.h" #include "graph.h" @@ -11,14 +10,14 @@ using namespace std; -map placeHolderMap; +map placeHolderMap;//placeholder的名字与数值一一对应,作为eval的参数 int main() { - Graph gra; - int n,m,q; - string name,type,tmp; - float value; - cin>>n; + Graph gra;//计算图 + int n,m,q;//样例中输入的三种操作的个数 + string name,type,tmp;//用到的临时字符串 + float value;//用到的临时float + cin>>n;//C V P三种节点 for(int i=0; i>name; @@ -26,46 +25,46 @@ int main() if(type=="C") { cin>>value; - gra.push(name,new Constant(value)); + gra.push(name,new Constant(value));//创建新的Constant } else if(type=="V") { cin>>value; - gra.push(name,new Variable(value)); + gra.push(name,new Variable(value));//创建新的Variable } else if(type=="P") { - gra.push(name,new Placeholder); + gra.push(name,new Placeholder);//创建新的PlaceHolder } - else assert(0); + else assert(0);//输入数据有误 } - cin>>m; + cin>>m;//运算节点 for(int i=0; i>name; cin>>tmp; assert(tmp=="="); - string p1,p2,p3,p4; + string p1,p2,p3,p4;//处理输入样例 cin>>p1; if(p1=="COND") { cin>>p2; cin>>p3; cin>>p4; - gra.push(name,new Cond(gra[p2],gra[p3],gra[p4])); + gra.push(name,new Cond(gra[p2],gra[p3],gra[p4]));//创建新的Cond continue; } else if(p1=="PRINT") { cin>>p2; - gra.push(name,new Print(p2,gra[p2])); + gra.push(name,new Print(p2,gra[p2]));//创建新的Print continue; } else if(p1=="SIN") { cin>>p2; - gra.push(name,new Opn(gra[p2])); + gra.push(name,new Sin(gra[p2]));//以下是创建各种单变量函数 continue; } else if(p1=="EXP") @@ -98,7 +97,7 @@ int main() cin>>p2; if(type=="+") { - gra.push(name,new sum(gra[p1],gra[p2])); + gra.push(name,new sum(gra[p1],gra[p2]));//以下是创建各种双变量函数 } else if(type=="-") { @@ -132,17 +131,16 @@ int main() { gra.push(name,new EQU(gra[p1],gra[p2])); } - else assert(0); + else assert(0);//输入数据有误 } } - cin>>q; -// int t=0; + cin>>q;//Eval SetConstant SetAnswer for(int i=0; i>type; if(type=="EVAL") { - placeHolderMap.clear(); + placeHolderMap.clear();//清空placeholder列表 ss>>name; string phcountstr; ss>>phcountstr; int phcount=0; - if(!phcountstr.empty()) + if(!phcountstr.empty())//判断是否有placeholder { phcount=stoi(phcountstr); } // cout<>name; ss>>value; - gra.setvariable(name,value); + gra.setvariable(name,value);//把name节点的值设为value } else if(type=="SETANSWER") { ss>>name; int t; ss>>t; - gra.setvariable(name,gra.lookupanswer(t)); + gra.setvariable(name,gra.lookupanswer(t));//把name节点的值设为gra.lookupanswer(t)(第t次计算的结果) } - else assert(0); + else assert(0);//输入数据有误 } } diff --git a/node.cpp b/node.cpp index de07988..43b077d 100644 --- a/node.cpp +++ b/node.cpp @@ -1,9 +1,6 @@ #include "node.h" -// float Node::geteval() -// { -// } -void Node::setvalue(float a) +void Node::setvalue(float a)//除了variable以外这个函数不起作用 { } @@ -14,7 +11,7 @@ void Node::reset() void OneParentNode::reset() { - p1->reset(); + p1->reset();//父节点也要清零 calculated=0; } void TwoParentsNode::reset() @@ -33,17 +30,12 @@ void ThreeParentsNode::reset() float ZeroParentNode::geteval() { - return 1; -} - -int ZeroParentNode::getParentsNum() -{ - return 0; + return NAN; } float OneParentNode::geteval() { - if(calculated)return tempeval; + if(calculated)return tempeval;//如果已计算就直接返回计算数值 else { calculated=1; @@ -52,22 +44,11 @@ float OneParentNode::geteval() } } -int OneParentNode::getParentsNum() -{ - return 1; -} - -// float OneParentNode::func(float x){} - OneParentNode::OneParentNode(Node* parent1) { p1=parent1; } -// float TwoParentsNode::func(float x,float y) -// { -// } - float TwoParentsNode::geteval() { if(calculated)return tempeval; @@ -79,19 +60,12 @@ float TwoParentsNode::geteval() } } -int TwoParentsNode::getParentsNum() -{ - return 2; -} - TwoParentsNode::TwoParentsNode(Node* parent1,Node* parent2) { p1=parent1; p2=parent2; } -// float ThreeParentsNode::func(float x,float y,float z){} - float ThreeParentsNode::geteval() { if(calculated)return tempeval; @@ -103,11 +77,6 @@ float ThreeParentsNode::geteval() } } -int ThreeParentsNode::getParentsNum() -{ - return 3; -} - ThreeParentsNode::ThreeParentsNode(Node* parent1,Node* parent2,Node* parent3) { p1=parent1; diff --git a/node.h b/node.h index 70cb10d..f5748e5 100644 --- a/node.h +++ b/node.h @@ -2,59 +2,63 @@ #include #include #include -class Node +class Node//节点按父节点的个数分为4类:0个(constant,variable,placeholder),1个(print和各种单变量函数),2个(四则运算与比较),3个(cond) { protected: - // friend class Graph; - float tempeval; - bool calculated = 0; + float tempeval;//临时计算数值(避免重复计算) + bool calculated = 0;//是否已计算 (避免重复计算) public: - virtual float geteval() = 0; - virtual void setvalue(float a); - // float tempeval; - // bool calculated = 0; - virtual void reset(); + virtual float geteval() = 0;//获取节点数值 + virtual void setvalue(float a);//对variable赋值 + virtual void reset();//设为"未计算"状态 }; -class ZeroParentNode:public Node +class ZeroParentNode:public Node//没有父节点的节点,constant,variable,placeholder { public: float geteval(); - int getParentsNum(); }; -class OneParentNode:public Node +class OneParentNode:public Node//1个父节点的节点,print和单变量函数 { public: - Node *p1;//parents + Node *p1;//父节点指针 OneParentNode(Node* parent); - virtual float func(float x) = 0; + virtual float func(float x) = 0;//这个节点对应的函数 virtual void reset(); float geteval(); - int getParentsNum(); }; -template + +template//单变量函数模板,更轻松地创建单变量函数节点 class Opn:public OneParentNode { using OneParentNode::OneParentNode; float func(float x){return f(x);} }; -class TwoParentsNode:public Node + +class TwoParentsNode:public Node//2个父节点的节点,四则运算与比较 { public: Node *p1,*p2;//parents - virtual float func(float x,float y) = 0; + virtual float func(float x,float y) = 0;//双变量函数 float geteval(); virtual void reset(); int getParentsNum(); TwoParentsNode(Node* parent1,Node* parent2); }; -class ThreeParentsNode:public Node +template//双变量函数模板,更轻松地创建双变量函数节点 +class Tpn:public TwoParentsNode +{ + using TwoParentsNode::TwoParentsNode; + float func(float x,float y){return f(x,y);} +}; + +class ThreeParentsNode:public Node//3个父节点的节点,只有cond { public: Node *p1,*p2,*p3;//parents - virtual float func(float x,float y,float z) = 0; + virtual float func(float x,float y,float z) = 0;//三变量函数 float geteval(); virtual void reset(); int getParentsNum(); diff --git a/onepn.cpp b/onepn.cpp index a2a57ef..8306315 100644 --- a/onepn.cpp +++ b/onepn.cpp @@ -38,3 +38,24 @@ float Sigmoid::func(float x) { return (tanh(x/2)+1)/2; } +/* +创建新的单变量函数的方法: +例:方法1: +class Sqr:public OneParentNode +{ + public: + using OneParentNode::OneParentNode; + float func(float x) + { + return x*x; + } +}; +gra.push(节点名,new Sqr(gra[父节点名]));(gra为Graph类的实例) + +方法2: +float Sqr(float x) +{ + return x*x; +} +gra.push(节点名,new Opn(gra[父节点名])); +*/ diff --git a/onepn.h b/onepn.h index ee3b229..31079ba 100644 --- a/onepn.h +++ b/onepn.h @@ -6,7 +6,7 @@ extern bool asserted; class Print:public OneParentNode { - std::string nm; + std::string nm;//父节点名 public: Print(std::string str, Node* parent); float func(float x); diff --git a/twopn.cpp b/twopn.cpp index 36f0bb9..86db4fe 100644 --- a/twopn.cpp +++ b/twopn.cpp @@ -51,3 +51,20 @@ float LEQ::func(float x,float y) if(isnan(x)||isnan(y))return NAN; return float(x<=y); } +/* +创建新的双变量函数的方法: +例:方法1: +class Pow:public TwoParentsNode +{ + public: + using TwoParentsNode::TwoParentsNode; + float func(float x,float y) + { + return std::pow(x,y); + } +}; +gra.push(节点名,new Pow(gra[父节点名1],gra[父节点名2]));(gra为Graph类的实例) + +方法2: +gra.push(节点名,new Tpn(gra[父节点名1],gra[父节点名2])); +*/ diff --git a/zeropn.cpp b/zeropn.cpp index d4414e7..8a1e43c 100644 --- a/zeropn.cpp +++ b/zeropn.cpp @@ -4,15 +4,15 @@ void Placeholder::setvalue(float a) { value=a; - calculated=1; + calculated=1;//未赋值为0,已赋值为1 } float Placeholder::geteval() { if(calculated) - return value; - else + return value;//若已赋值则返回对应数值 + else//否则输出error并返回nan { - if(!asserted) + if(!asserted) { std::cout<<"ERROR: Placeholder missing"<