GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/sets/normal_form.h Lines: 65 67 97.0 %
Date: 2021-05-22 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
namespace cvc5 {
22
namespace theory {
23
namespace sets {
24
25
class NormalForm {
26
 public:
27
  /**
28
   * Constructs a set of the form:
29
   *   (union (singleton c1) ... (union (singleton c_{n-1}) (singleton c_n))))
30
   * from the set { c1 ... cn }, also handles empty set case, which is why
31
   * setType is passed to this method.
32
   */
33
  template <bool ref_count>
34
648
  static Node elementsToSet(const std::set<NodeTemplate<ref_count> >& elements,
35
                            TypeNode setType)
36
  {
37
    typedef typename std::set<NodeTemplate<ref_count> >::const_iterator
38
        ElementsIterator;
39
648
    NodeManager* nm = NodeManager::currentNM();
40
648
    if (elements.size() == 0)
41
    {
42
43
      return nm->mkConst(EmptySet(setType));
43
    }
44
    else
45
    {
46
1210
      TypeNode elementType = setType.getSetElementType();
47
605
      ElementsIterator it = elements.begin();
48
1210
      Node cur = nm->mkSingleton(elementType, *it);
49
3893
      while (++it != elements.end())
50
      {
51
3288
        Node singleton = nm->mkSingleton(elementType, *it);
52
1644
        cur = nm->mkNode(kind::UNION, singleton, cur);
53
      }
54
605
      return cur;
55
    }
56
  }
57
58
  /**
59
   * Returns true if n is considered a to be a (canonical) constant set value.
60
   * A canonical set value is one whose AST is:
61
   *   (union (singleton c1) ... (union (singleton c_{n-1}) (singleton c_n))))
62
   * where c1 ... cn are constants and the node identifier of these constants
63
   * are such that:
64
   *   c1 > ... > cn.
65
   * Also handles the corner cases of empty set and singleton set.
66
   */
67
4208
  static bool checkNormalConstant(TNode n) {
68
8416
    Debug("sets-checknormal") << "[sets-checknormal] checkNormal " << n << " :"
69
4208
                              << std::endl;
70
4208
    if (n.getKind() == kind::EMPTYSET) {
71
      return true;
72
4208
    } else if (n.getKind() == kind::SINGLETON) {
73
      return n[0].isConst();
74
4208
    } else if (n.getKind() == kind::UNION) {
75
      // assuming (union {SmallestNodeID} ... (union {BiggerNodeId} ...
76
77
4400
      Node orig = n;
78
4400
      TNode prvs;
79
      // check intermediate nodes
80
16610
      while (n.getKind() == kind::UNION)
81
      {
82
8907
        if (n[0].getKind() != kind::SINGLETON || !n[0][0].isConst())
83
        {
84
          // not a constant
85
5000
          Trace("sets-isconst") << "sets::isConst: " << orig << " not due to "
86
2500
                                << n[0] << std::endl;
87
2500
          return false;
88
        }
89
12814
        Debug("sets-checknormal")
90
12814
            << "[sets-checknormal]              element = " << n[0][0] << " "
91
6407
            << n[0][0].getId() << std::endl;
92
6407
        if (!prvs.isNull() && n[0][0] >= prvs)
93
        {
94
412
          Trace("sets-isconst")
95
412
              << "sets::isConst: " << orig << " not due to compare " << n[0][0]
96
206
              << std::endl;
97
206
          return false;
98
        }
99
6201
        prvs = n[0][0];
100
6201
        n = n[1];
101
      }
102
103
      // check SmallestNodeID is smallest
104
1502
      if (n.getKind() != kind::SINGLETON || !n[0].isConst())
105
      {
106
186
        Trace("sets-isconst") << "sets::isConst: " << orig
107
93
                              << " not due to final " << n << std::endl;
108
93
        return false;
109
      }
110
2818
      Debug("sets-checknormal")
111
2818
          << "[sets-checknormal]              lst element = " << n[0] << " "
112
1409
          << n[0].getId() << std::endl;
113
      // compare last ID
114
1409
      if (n[0] < prvs)
115
      {
116
1217
        return true;
117
      }
118
384
      Trace("sets-isconst")
119
384
          << "sets::isConst: " << orig << " not due to compare final " << n[0]
120
192
          << std::endl;
121
    }
122
192
    return false;
123
  }
124
125
  /**
126
   * Converts a set term to a std::set of its elements. This expects a set of
127
   * the form:
128
   *   (union (singleton c1) ... (union (singleton c_{n-1}) (singleton c_n))))
129
   * Also handles the corner cases of empty set and singleton set.
130
   */
131
1354
  static std::set<Node> getElementsFromNormalConstant(TNode n) {
132
1354
    Assert(n.isConst());
133
1354
    std::set<Node> ret;
134
1354
    if (n.getKind() == kind::EMPTYSET) {
135
92
      return ret;
136
    }
137
5224
    while (n.getKind() == kind::UNION) {
138
1981
      Assert(n[0].getKind() == kind::SINGLETON);
139
1981
      ret.insert(ret.begin(), n[0][0]);
140
1981
      n = n[1];
141
    }
142
1262
    Assert(n.getKind() == kind::SINGLETON);
143
1262
    ret.insert(n[0]);
144
1262
    return ret;
145
  }
146
147
3907
  static Node mkBop( Kind k, std::vector< Node >& els, TypeNode tn, unsigned index = 0 ){
148
3907
    if( index>=els.size() ){
149
389
      return NodeManager::currentNM()->mkConst(EmptySet(tn));
150
3518
    }else if( index==els.size()-1 ){
151
2717
      return els[index];
152
    }else{
153
801
      return NodeManager::currentNM()->mkNode( k, els[index], mkBop( k, els, tn, index+1 ) );
154
    }
155
  }
156
157
};
158
}
159
}
160
}  // namespace cvc5
161
162
#endif