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 57717 : ExpressionTreeNode::ExpressionTreeNode(Operation* operation, const vector<ExpressionTreeNode>& children) : operation(operation), children(children) { 74 57717 : if (operation->getNumArguments() != children.size()) 75 0 : throw Exception("wrong number of arguments to function: "+operation->getName()); 76 57717 : } 77 : 78 8451 : ExpressionTreeNode::ExpressionTreeNode(Operation* operation, const ExpressionTreeNode& child1, const ExpressionTreeNode& child2) : operation(operation) { 79 8451 : children.push_back(child1); 80 8451 : children.push_back(child2); 81 8451 : if (operation->getNumArguments() != children.size()) 82 0 : throw Exception("wrong number of arguments to function: "+operation->getName()); 83 8451 : } 84 : 85 4115 : ExpressionTreeNode::ExpressionTreeNode(Operation* operation, const ExpressionTreeNode& child) : operation(operation) { 86 4115 : children.push_back(child); 87 4115 : if (operation->getNumArguments() != children.size()) 88 0 : throw Exception("wrong number of arguments to function: "+operation->getName()); 89 4115 : } 90 : 91 2021146 : ExpressionTreeNode::ExpressionTreeNode(Operation* operation) : operation(operation) { 92 2021146 : if (operation->getNumArguments() != children.size()) 93 0 : throw Exception("wrong number of arguments to function: "+operation->getName()); 94 2021146 : } 95 : 96 2754375 : ExpressionTreeNode::ExpressionTreeNode(const ExpressionTreeNode& node) : operation(node.operation == NULL ? NULL : node.operation->clone()), children(node.getChildren()) { 97 2754375 : } 98 : 99 31663 : ExpressionTreeNode::ExpressionTreeNode(ExpressionTreeNode&& node) : operation(node.operation), children(move(node.children)) { 100 31663 : node.operation = NULL; 101 : node.children.clear(); 102 31663 : } 103 : 104 2136904 : ExpressionTreeNode::ExpressionTreeNode() : operation(NULL) { 105 2136904 : } 106 : 107 7014371 : ExpressionTreeNode::~ExpressionTreeNode() { 108 7014371 : if (operation != NULL) 109 4887954 : delete operation; 110 7014371 : } 111 : 112 119242 : bool ExpressionTreeNode::operator!=(const ExpressionTreeNode& node) const { 113 119242 : if (node.getOperation() != getOperation()) 114 : return true; 115 61635 : if (getOperation().isSymmetric() && getChildren().size() == 2) { 116 9882 : if (getChildren()[0] == node.getChildren()[0] && getChildren()[1] == node.getChildren()[1]) 117 : return false; 118 3556 : if (getChildren()[0] == node.getChildren()[1] && getChildren()[1] == node.getChildren()[0]) 119 : return false; 120 3556 : return true; 121 : } 122 82810 : for (int i = 0; i < (int) getChildren().size(); i++) 123 33338 : if (getChildren()[i] != node.getChildren()[i]) 124 : return true; 125 : return false; 126 : } 127 : 128 85904 : bool ExpressionTreeNode::operator==(const ExpressionTreeNode& node) const { 129 85904 : return !(*this != node); 130 : } 131 : 132 64616 : ExpressionTreeNode& ExpressionTreeNode::operator=(const ExpressionTreeNode& node) { 133 64616 : if (operation != NULL) 134 11673 : delete operation; 135 64616 : operation = node.getOperation().clone(); 136 64616 : children = node.getChildren(); 137 64616 : return *this; 138 : } 139 : 140 2094686 : ExpressionTreeNode& ExpressionTreeNode::operator=(ExpressionTreeNode&& node) { 141 2094686 : if (operation != NULL) 142 10793 : delete operation; 143 2094686 : operation = node.operation; 144 2094686 : children = move(node.children); 145 2094686 : node.operation = NULL; 146 : node.children.clear(); 147 2094686 : return *this; 148 : } 149 : 150 4894397 : const Operation& ExpressionTreeNode::getOperation() const { 151 4894397 : return *operation; 152 : } 153 : 154 5838400 : const vector<ExpressionTreeNode>& ExpressionTreeNode::getChildren() const { 155 5838400 : return children; 156 : } 157 : 158 79774 : 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 79774 : int numTags = examples.size(); 164 153407 : for (const ExpressionTreeNode& child : getChildren()) 165 73633 : child.assignTags(examples); 166 79774 : if (numTags == examples.size()) { 167 : // All the children matched existing tags, so possibly this node does too. 168 : 169 226762 : for (int i = 0; i < examples.size(); i++) { 170 206936 : const ExpressionTreeNode& example = *examples[i]; 171 206936 : bool matches = (getChildren().size() == example.getChildren().size() && getOperation() == example.getOperation()); 172 232985 : for (int j = 0; matches && j < getChildren().size(); j++) 173 26049 : if (getChildren()[j].tag != example.getChildren()[j].tag) 174 : matches = false; 175 206936 : if (matches) { 176 30799 : tag = i; 177 30799 : return; 178 : } 179 : } 180 : } 181 : 182 : // This node does not match any previous node, so assign a new tag. 183 : 184 48975 : tag = examples.size(); 185 48975 : examples.push_back(this); 186 : } 187 : }