GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/sets/normal_form.h Lines: 65 67 97.0 %
Date: 2021-09-18 Branches: 170 342 49.7 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Andrew Reynolds, Kshitij Bansal, Mudathir Mohamed
4
 *
5
 * This file is part of the cvc5 project.
6
 *
7
 * Copyright (c) 2009-2021 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
 * Normal form for set constants.
14
 */
15
16
#include "cvc5_private.h"
17
18
#ifndef CVC5__THEORY__SETS__NORMAL_FORM_H
19
#define CVC5__THEORY__SETS__NORMAL_FORM_H
20
21
#include "expr/emptyset.h"
22
23
namespace cvc5 {
24
namespace theory {
25
namespace sets {
26
27
class NormalForm {
28
 public:
29
  /**
30
   * Constructs a set of the form:
31
   *   (union (singleton c1) ... (union (singleton c_{n-1}) (singleton c_n))))
32
   * from the set { c1 ... cn }, also handles empty set case, which is why
33
   * setType is passed to this method.
34
   */
35
  template <bool ref_count>
36
647
  static Node elementsToSet(const std::set<NodeTemplate<ref_count> >& elements,
37
                            TypeNode setType)
38
  {
39
    typedef typename std::set<NodeTemplate<ref_count> >::const_iterator
40
        ElementsIterator;
41
647
    NodeManager* nm = NodeManager::currentNM();
42
647
    if (elements.size() == 0)
43
    {
44
37
      return nm->mkConst(EmptySet(setType));
45
    }
46
    else
47
    {
48
1220
      TypeNode elementType = setType.getSetElementType();
49
610
      ElementsIterator it = elements.begin();
50
1220
      Node cur = nm->mkSingleton(elementType, *it);
51
3898
      while (++it != elements.end())
52
      {
53
3288
        Node singleton = nm->mkSingleton(elementType, *it);
54
1644
        cur = nm->mkNode(kind::UNION, singleton, cur);
55
      }
56
610
      return cur;
57
    }
58
  }
59
60
  /**
61
   * Returns true if n is considered a to be a (canonical) constant set value.
62
   * A canonical set value is one whose AST is:
63
   *   (union (singleton c1) ... (union (singleton c_{n-1}) (singleton c_n))))
64
   * where c1 ... cn are constants and the node identifier of these constants
65
   * are such that:
66
   *   c1 > ... > cn.
67
   * Also handles the corner cases of empty set and singleton set.
68
   */
69
4224
  static bool checkNormalConstant(TNode n) {
70
8448
    Debug("sets-checknormal") << "[sets-checknormal] checkNormal " << n << " :"
71
4224
                              << std::endl;
72
4224
    if (n.getKind() == kind::EMPTYSET) {
73
      return true;
74
4224
    } else if (n.getKind() == kind::SINGLETON) {
75
      return n[0].isConst();
76
4224
    } else if (n.getKind() == kind::UNION) {
77
      // assuming (union {SmallestNodeID} ... (union {BiggerNodeId} ...
78
79
4407
      Node orig = n;
80
4407
      TNode prvs;
81
      // check intermediate nodes
82
16632
      while (n.getKind() == kind::UNION)
83
      {
84
8933
        if (n[0].getKind() != kind::SINGLETON || !n[0][0].isConst())
85
        {
86
          // not a constant
87
5048
          Trace("sets-isconst") << "sets::isConst: " << orig << " not due to "
88
2524
                                << n[0] << std::endl;
89
2524
          return false;
90
        }
91
12818
        Debug("sets-checknormal")
92
12818
            << "[sets-checknormal]              element = " << n[0][0] << " "
93
6409
            << n[0][0].getId() << std::endl;
94
6409
        if (!prvs.isNull() && n[0][0] >= prvs)
95
        {
96
410
          Trace("sets-isconst")
97
410
              << "sets::isConst: " << orig << " not due to compare " << n[0][0]
98
205
              << std::endl;
99
205
          return false;
100
        }
101
6204
        prvs = n[0][0];
102
6204
        n = n[1];
103
      }
104
105
      // check SmallestNodeID is smallest
106
1495
      if (n.getKind() != kind::SINGLETON || !n[0].isConst())
107
      {
108
184
        Trace("sets-isconst") << "sets::isConst: " << orig
109
92
                              << " not due to final " << n << std::endl;
110
92
        return false;
111
      }
112
2806
      Debug("sets-checknormal")
113
2806
          << "[sets-checknormal]              lst element = " << n[0] << " "
114
1403
          << n[0].getId() << std::endl;
115
      // compare last ID
116
1403
      if (n[0] < prvs)
117
      {
118
1220
        return true;
119
      }
120
366
      Trace("sets-isconst")
121
366
          << "sets::isConst: " << orig << " not due to compare final " << n[0]
122
183
          << std::endl;
123
    }
124
183
    return false;
125
  }
126
127
  /**
128
   * Converts a set term to a std::set of its elements. This expects a set of
129
   * the form:
130
   *   (union (singleton c1) ... (union (singleton c_{n-1}) (singleton c_n))))
131
   * Also handles the corner cases of empty set and singleton set.
132
   */
133
1363
  static std::set<Node> getElementsFromNormalConstant(TNode n) {
134
1363
    Assert(n.isConst());
135
1363
    std::set<Node> ret;
136
1363
    if (n.getKind() == kind::EMPTYSET) {
137
98
      return ret;
138
    }
139
5261
    while (n.getKind() == kind::UNION) {
140
1998
      Assert(n[0].getKind() == kind::SINGLETON);
141
1998
      ret.insert(ret.begin(), n[0][0]);
142
1998
      n = n[1];
143
    }
144
1265
    Assert(n.getKind() == kind::SINGLETON);
145
1265
    ret.insert(n[0]);
146
1265
    return ret;
147
  }
148
149
2454
  static Node mkBop( Kind k, std::vector< Node >& els, TypeNode tn, unsigned index = 0 ){
150
2454
    if( index>=els.size() ){
151
318
      return NodeManager::currentNM()->mkConst(EmptySet(tn));
152
2136
    }else if( index==els.size()-1 ){
153
1442
      return els[index];
154
    }else{
155
694
      return NodeManager::currentNM()->mkNode( k, els[index], mkBop( k, els, tn, index+1 ) );
156
    }
157
  }
158
159
};
160
}
161
}
162
}  // namespace cvc5
163
164
#endif