Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 : * -------------------------------------------------------------------------- * 3 : * Lepton * 4 : * -------------------------------------------------------------------------- * 5 : * This is part of the Lepton expression parser originating from * 6 : * Simbios, the NIH National Center for Physics-Based Simulation of * 7 : * Biological Structures at Stanford, funded under the NIH Roadmap for * 8 : * Medical Research, grant U54 GM072970. See https://simtk.org. * 9 : * * 10 : * Portions copyright (c) 2013-2016 Stanford University and the Authors. * 11 : * Authors: Peter Eastman * 12 : * Contributors: * 13 : * * 14 : * Permission is hereby granted, free of charge, to any person obtaining a * 15 : * copy of this software and associated documentation files (the "Software"), * 16 : * to deal in the Software without restriction, including without limitation * 17 : * the rights to use, copy, modify, merge, publish, distribute, sublicense, * 18 : * and/or sell copies of the Software, and to permit persons to whom the * 19 : * Software is furnished to do so, subject to the following conditions: * 20 : * * 21 : * The above copyright notice and this permission notice shall be included in * 22 : * all copies or substantial portions of the Software. * 23 : * * 24 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * 25 : * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * 26 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * 27 : * THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 28 : * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 29 : * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE * 30 : * USE OR OTHER DEALINGS IN THE SOFTWARE. * 31 : * -------------------------------------------------------------------------- * 32 : +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ 33 : /* -------------------------------------------------------------------------- * 34 : * lepton * 35 : * -------------------------------------------------------------------------- * 36 : * This is part of the lepton expression parser originating from * 37 : * Simbios, the NIH National Center for Physics-Based Simulation of * 38 : * Biological Structures at Stanford, funded under the NIH Roadmap for * 39 : * Medical Research, grant U54 GM072970. See https://simtk.org. * 40 : * * 41 : * Portions copyright (c) 2009-2021 Stanford University and the Authors. * 42 : * Authors: Peter Eastman * 43 : * Contributors: * 44 : * * 45 : * Permission is hereby granted, free of charge, to any person obtaining a * 46 : * copy of this software and associated documentation files (the "Software"), * 47 : * to deal in the Software without restriction, including without limitation * 48 : * the rights to use, copy, modify, merge, publish, distribute, sublicense, * 49 : * and/or sell copies of the Software, and to permit persons to whom the * 50 : * Software is furnished to do so, subject to the following conditions: * 51 : * * 52 : * The above copyright notice and this permission notice shall be included in * 53 : * all copies or substantial portions of the Software. * 54 : * * 55 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * 56 : * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * 57 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * 58 : * THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 59 : * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 60 : * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE * 61 : * USE OR OTHER DEALINGS IN THE SOFTWARE. * 62 : * -------------------------------------------------------------------------- */ 63 : 64 : #include "ExpressionTreeNode.h" 65 : #include "Exception.h" 66 : #include "Operation.h" 67 : #include <utility> 68 : 69 : namespace PLMD { 70 : using namespace lepton; 71 : using namespace std; 72 : 73 513214 : ExpressionTreeNode::ExpressionTreeNode(Operation* operation, const vector<ExpressionTreeNode>& children) : operation(operation), children(children) { 74 513214 : if (operation->getNumArguments() != children.size()) 75 0 : throw Exception("wrong number of arguments to function: "+operation->getName()); 76 513214 : } 77 : 78 55903 : ExpressionTreeNode::ExpressionTreeNode(Operation* operation, const ExpressionTreeNode& child1, const ExpressionTreeNode& child2) : operation(operation) { 79 55903 : children.push_back(child1); 80 55903 : children.push_back(child2); 81 55903 : if (operation->getNumArguments() != children.size()) 82 0 : throw Exception("wrong number of arguments to function: "+operation->getName()); 83 55903 : } 84 : 85 31817 : ExpressionTreeNode::ExpressionTreeNode(Operation* operation, const ExpressionTreeNode& child) : operation(operation) { 86 31817 : children.push_back(child); 87 31817 : if (operation->getNumArguments() != children.size()) 88 0 : throw Exception("wrong number of arguments to function: "+operation->getName()); 89 31817 : } 90 : 91 2091485 : ExpressionTreeNode::ExpressionTreeNode(Operation* operation) : operation(operation) { 92 2091485 : if (operation->getNumArguments() != children.size()) 93 0 : throw Exception("wrong number of arguments to function: "+operation->getName()); 94 2091485 : } 95 : 96 15370242 : ExpressionTreeNode::ExpressionTreeNode(const ExpressionTreeNode& node) : operation(node.operation == NULL ? NULL : node.operation->clone()), children(node.getChildren()) { 97 15370242 : } 98 : 99 300816 : ExpressionTreeNode::ExpressionTreeNode(ExpressionTreeNode&& node) : operation(node.operation), children(move(node.children)) { 100 300816 : node.operation = NULL; 101 : node.children.clear(); 102 300816 : } 103 : 104 3096582 : ExpressionTreeNode::ExpressionTreeNode() : operation(NULL) { 105 3096582 : } 106 : 107 21460059 : ExpressionTreeNode::~ExpressionTreeNode() { 108 21460059 : if (operation != NULL) 109 18436726 : delete operation; 110 21460059 : } 111 : 112 5535066 : bool ExpressionTreeNode::operator!=(const ExpressionTreeNode& node) const { 113 5535066 : if (node.getOperation() != getOperation()) 114 : return true; 115 1601794 : if (getOperation().isSymmetric() && getChildren().size() == 2) { 116 571080 : if (getChildren()[0] == node.getChildren()[0] && getChildren()[1] == node.getChildren()[1]) 117 : return false; 118 443232 : if (getChildren()[0] == node.getChildren()[1] && getChildren()[1] == node.getChildren()[0]) 119 : return false; 120 443232 : return true; 121 : } 122 1486747 : for (int i = 0; i < (int) getChildren().size(); i++) 123 761696 : if (getChildren()[i] != node.getChildren()[i]) 124 : return true; 125 : return false; 126 : } 127 : 128 4773370 : bool ExpressionTreeNode::operator==(const ExpressionTreeNode& node) const { 129 4773370 : return !(*this != node); 130 : } 131 : 132 511140 : ExpressionTreeNode& ExpressionTreeNode::operator=(const ExpressionTreeNode& node) { 133 511140 : if (operation != NULL) 134 63224 : delete operation; 135 511140 : operation = node.getOperation().clone(); 136 511140 : children = node.getChildren(); 137 511140 : return *this; 138 : } 139 : 140 2722283 : ExpressionTreeNode& ExpressionTreeNode::operator=(ExpressionTreeNode&& node) { 141 2722283 : if (operation != NULL) 142 73851 : delete operation; 143 2722283 : operation = node.operation; 144 2722283 : children = move(node.children); 145 2722283 : node.operation = NULL; 146 : node.children.clear(); 147 2722283 : return *this; 148 : } 149 : 150 36330514 : const Operation& ExpressionTreeNode::getOperation() const { 151 36330514 : return *operation; 152 : } 153 : 154 66651971 : const vector<ExpressionTreeNode>& ExpressionTreeNode::getChildren() const { 155 66651971 : return children; 156 : } 157 : 158 729246 : void ExpressionTreeNode::assignTags(vector<const ExpressionTreeNode*>& examples) const { 159 : // Assign tag values to all nodes in a tree, such that two nodes have the same 160 : // tag if and only if they (and all their children) are equal. This is used to 161 : // optimize other operations. 162 : 163 729246 : int numTags = examples.size(); 164 1397801 : for (const ExpressionTreeNode& child : getChildren()) 165 668555 : child.assignTags(examples); 166 729246 : if (numTags == examples.size()) { 167 : // All the children matched existing tags, so possibly this node does too. 168 : 169 17683297 : for (int i = 0; i < examples.size(); i++) { 170 17514922 : const ExpressionTreeNode& example = *examples[i]; 171 17514922 : bool matches = (getChildren().size() == example.getChildren().size() && getOperation() == example.getOperation()); 172 19179897 : for (int j = 0; matches && j < getChildren().size(); j++) 173 1664975 : if (getChildren()[j].tag != example.getChildren()[j].tag) 174 : matches = false; 175 17514922 : if (matches) { 176 302239 : tag = i; 177 302239 : return; 178 : } 179 : } 180 : } 181 : 182 : // This node does not match any previous node, so assign a new tag. 183 : 184 427007 : tag = examples.size(); 185 427007 : examples.push_back(this); 186 : } 187 : }