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