All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cvc5-cvc5-1.2.0.src.theory.sets.normal_form.h Maven / Gradle / Ivy

The newest version!
/******************************************************************************
 * Top contributors (to current version):
 *   Andrew Reynolds, Kshitij Bansal, Aina Niemetz
 *
 * This file is part of the cvc5 project.
 *
 * Copyright (c) 2009-2024 by the authors listed in the file AUTHORS
 * in the top-level source directory and their institutional affiliations.
 * All rights reserved.  See the file COPYING in the top-level source
 * directory for licensing information.
 * ****************************************************************************
 *
 * Normal form for set constants.
 */

#include "cvc5_private.h"

#ifndef CVC5__THEORY__SETS__NORMAL_FORM_H
#define CVC5__THEORY__SETS__NORMAL_FORM_H

#include "expr/emptyset.h"

namespace cvc5::internal {
namespace theory {
namespace sets {

class NormalForm {
 public:
  /**
   * Constructs a set of the form:
   *   (union (singleton c1) ... (union (singleton c_{n-1}) (singleton c_n))))
   * from the set { c1 ... cn }, also handles empty set case, which is why
   * setType is passed to this method.
   */
  template 
  static Node elementsToSet(const std::set >& elements,
                            TypeNode setType)
  {
    typedef typename std::set >::const_iterator
        ElementsIterator;
    NodeManager* nm = NodeManager::currentNM();
    if (elements.size() == 0)
    {
      return nm->mkConst(EmptySet(setType));
    }
    else
    {
      ElementsIterator it = elements.begin();
      Node cur = nm->mkNode(Kind::SET_SINGLETON, *it);
      while (++it != elements.end())
      {
        Node singleton = nm->mkNode(Kind::SET_SINGLETON, *it);
        cur = nm->mkNode(Kind::SET_UNION, singleton, cur);
      }
      return cur;
    }
  }

  /**
   * Returns true if n is considered to be a (canonical) constant set value.
   * A canonical set value is one whose AST is:
   *   (union (singleton c1) ... (union (singleton c_{n-1}) (singleton c_n))))
   * where c1 ... cn are constants and the node identifier of these constants
   * are such that:
   *   c1 > ... > cn.
   * Also handles the corner cases of empty set and singleton set.
   */
  static bool checkNormalConstant(TNode n) {
    Trace("sets-checknormal") << "[sets-checknormal] checkNormal " << n << " :"
                              << std::endl;
    if (n.getKind() == Kind::SET_EMPTY)
    {
      return true;
    }
    else if (n.getKind() == Kind::SET_SINGLETON)
    {
      return n[0].isConst();
    }
    else if (n.getKind() == Kind::SET_UNION)
    {
      // assuming (union {SmallestNodeID} ... (union {BiggerNodeId} ...

      Node orig = n;
      TNode prvs;
      // check intermediate nodes
      while (n.getKind() == Kind::SET_UNION)
      {
        if (n[0].getKind() != Kind::SET_SINGLETON || !n[0][0].isConst())
        {
          // not a constant
          Trace("sets-isconst") << "sets::isConst: " << orig << " not due to "
                                << n[0] << std::endl;
          return false;
        }
        Trace("sets-checknormal")
            << "[sets-checknormal]              element = " << n[0][0] << " "
            << n[0][0].getId() << std::endl;
        if (!prvs.isNull() && n[0][0] >= prvs)
        {
          Trace("sets-isconst")
              << "sets::isConst: " << orig << " not due to compare " << n[0][0]
              << std::endl;
          return false;
        }
        prvs = n[0][0];
        n = n[1];
      }

      // check SmallestNodeID is smallest
      if (n.getKind() != Kind::SET_SINGLETON || !n[0].isConst())
      {
        Trace("sets-isconst") << "sets::isConst: " << orig
                              << " not due to final " << n << std::endl;
        return false;
      }
      Trace("sets-checknormal")
          << "[sets-checknormal]              lst element = " << n[0] << " "
          << n[0].getId() << std::endl;
      // compare last ID
      if (n[0] < prvs)
      {
        return true;
      }
      Trace("sets-isconst")
          << "sets::isConst: " << orig << " not due to compare final " << n[0]
          << std::endl;
    }
    return false;
  }

  /**
   * Converts a set term to a std::set of its elements. This expects a set of
   * the form:
   *   (union (singleton c1) ... (union (singleton c_{n-1}) (singleton c_n))))
   * Also handles the corner cases of empty set and singleton set.
   */
  static std::set getElementsFromNormalConstant(TNode n) {
    Assert(n.isConst());
    std::set ret;
    if (n.getKind() == Kind::SET_EMPTY)
    {
      return ret;
    }
    while (n.getKind() == Kind::SET_UNION)
    {
      Assert(n[0].getKind() == Kind::SET_SINGLETON);
      ret.insert(ret.begin(), n[0][0]);
      n = n[1];
    }
    Assert(n.getKind() == Kind::SET_SINGLETON);
    ret.insert(n[0]);
    return ret;
  }
  
  static Node mkBop( Kind k, std::vector< Node >& els, TypeNode tn, unsigned index = 0 ){
    if( index>=els.size() ){
      return NodeManager::currentNM()->mkConst(EmptySet(tn));
    }else if( index==els.size()-1 ){
      return els[index];
    }else{
      return NodeManager::currentNM()->mkNode( k, els[index], mkBop( k, els, tn, index+1 ) );
    }
  }

};
}
}
}  // namespace cvc5::internal

#endif




© 2015 - 2024 Weber Informatics LLC | Privacy Policy