Branch data Line data Source code
1 : : /****************************************************************************** 2 : : * Top contributors (to current version): 3 : : * Gereon Kremer, Daniel Larraz 4 : : * 5 : : * This file is part of the cvc5 project. 6 : : * 7 : : * Copyright (c) 2009-2025 by the authors listed in the file AUTHORS 8 : : * in the top-level source directory and their institutional affiliations. 9 : : * All rights reserved. See the file COPYING in the top-level source 10 : : * directory for licensing information. 11 : : * **************************************************************************** 12 : : * 13 : : * Utilities for flattening nodes. 14 : : */ 15 : : 16 : : #include "cvc5_private.h" 17 : : 18 : : #ifndef CVC5__EXPR__ALGORITHMS__FLATTEN_H 19 : : #define CVC5__EXPR__ALGORITHMS__FLATTEN_H 20 : : 21 : : #include <algorithm> 22 : : 23 : : #include "expr/node.h" 24 : : 25 : : namespace cvc5::internal::expr::algorithm { 26 : : 27 : : /** 28 : : * Flatten a node into a vector of its (direct or indirect) children. 29 : : * Optionally, a sequence of kinds that should be flattened can be passed. If no 30 : : * kinds are given, flattening is done based on the kind of t. 31 : : * Note that flatten(t, c) is equivalent to flatten(t, c, t.getKind()). 32 : : * @param t The node to be flattened 33 : : * @param children The resulting list of children 34 : : * @param kinds Optional sequence of kinds to consider for flattening 35 : : */ 36 : : template <typename... Kinds> 37 : 1061928 : void flatten(TNode t, std::vector<TNode>& children, Kinds... kinds) 38 : : { 39 : 5309650 : std::vector<TNode> queue = {t}; 40 [ + + ]: 4689710 : while (!queue.empty()) 41 : : { 42 : 7255554 : TNode cur = queue.back(); 43 : 3627782 : queue.pop_back(); 44 : 3627782 : bool recurse = false; 45 : : // figure out whether to recurse into cur 46 : : if constexpr (sizeof...(kinds) == 0) 47 : : { 48 : 126772 : recurse = t.getKind() == cur.getKind(); 49 : : } 50 : : else 51 : : { 52 [ + + ][ + + ]: 3501010 : recurse = ((kinds == cur.getKind()) || ...); [ + + ] 53 : : } 54 [ + + ]: 3627782 : if (recurse) 55 : : { 56 : 1198283 : queue.insert(queue.end(), cur.rbegin(), cur.rend()); 57 : : } 58 : : else 59 : : { 60 : 2429499 : children.emplace_back(cur); 61 : : } 62 : : } 63 : 1061928 : } 64 : : 65 : : /** 66 : : * Check whether a node can be flattened, that is whether calling flatten() 67 : : * returns something other than its direct children. If no kinds are passed 68 : : * explicitly, this simply checks whether any of the children has the same kind 69 : : * as t. If a sequence of kinds is passed, this checks whether any of the 70 : : * children has one of these kinds. 71 : : * Note that canFlatten(t) is equivalent to canFlatten(t, t.getKind()). 72 : : * @param t The node that should be checked 73 : : * @param kinds Optional sequence of kinds 74 : : * @return true iff t could be flattened 75 : : */ 76 : : template <typename... Kinds> 77 : 5090612 : bool canFlatten(TNode t, Kinds... kinds) 78 : : { 79 : : if constexpr (sizeof...(kinds) == 0) 80 : : { 81 : 99968 : return std::any_of(t.begin(), t.end(), [k = t.getKind()](TNode child) { 82 : 298429 : return child.getKind() == k; 83 : 99944 : }); 84 : : } 85 : : else 86 : : { 87 [ + + ][ - - ]: 4990668 : if (!((t.getKind() == kinds) || ...)) [ - + ] 88 : : { 89 : 6 : return false; 90 : : } 91 : 17096786 : return std::any_of(t.begin(), t.end(), [=](TNode child) { 92 [ + + ][ + + ]: 12106124 : return ((child.getKind() == kinds) || ...); 93 : 4990662 : }); 94 : : } 95 : : } 96 : : 97 : : /** 98 : : * If t can be flattened, return a new node of the same kind as t with the 99 : : * flattened children. Otherwise, return t. 100 : : * If a sequence of kinds is given, the flattening (and the respective check) 101 : : * are done with respect to these kinds: see the documentation of flatten() 102 : : * and canFlatten() for more details. 103 : : * @param t The node to be flattened 104 : : * @param kinds Optional sequence of kinds 105 : : * @return A flattened version of t 106 : : */ 107 : : template <typename... Kinds> 108 : 99950 : Node flatten(NodeManager* nm, TNode t, Kinds... kinds) 109 : : { 110 [ + + ]: 99950 : if (!canFlatten(t, kinds...)) 111 : : { 112 : 92456 : return t; 113 : : } 114 : 14988 : std::vector<TNode> children; 115 : 7494 : flatten(t, children, kinds...); 116 : 7494 : return nm->mkNode(t.getKind(), children); 117 : : } 118 : : 119 : : } // namespace cvc5::internal::expr 120 : : 121 : : #endif