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

cvc5-cvc5-1.2.0.src.theory.ff.cocoa_encoder.h Maven / Gradle / Ivy

The newest version!
/******************************************************************************
 * Top contributors (to current version):
 *   Alex Ozdemir
 *
 * 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.
 * ****************************************************************************
 *
 * encoding Nodes as cocoa ring elements.
 */

#include "cvc5_private.h"

#ifdef CVC5_USE_COCOA

#ifndef CVC5__THEORY__FF__COCOA_H
#define CVC5__THEORY__FF__COCOA_H

// external includes
#include 
#include 

// std includes
#include 
#include 
#include 
#include 

// internal includes
#include "expr/node.h"
#include "theory/ff/cocoa_util.h"
#include "theory/ff/core.h"
#include "theory/ff/util.h"

namespace cvc5::internal {
namespace theory {
namespace ff {

/**
 *  Create cocoa symbol, sanitizing varName.
 *  If index is given, subscript the symbol by it.
 */
CoCoA::symbol cocoaSym(const std::string& varName,
                       std::optional index = {});

/**
 * Class for encoding a Node as a Poly.
 *
 * Requires two passes over the nodes. On the first pass it collects variables,
 * !=s, and bitsums. On the second, it encodes. The first stage is called
 * "Stage::Scan", the second is "Stage::Encode".
 *
 * Two stages are necessary because when creating a CoCoA polynomial ring, one
 * must declare all the variables up-front. So, before we create any polynomials
 * (to encode terms), we must know all the (CoCoA) variables. CoCoA variables
 * are used to encode cvc5 variables, bitsums, and witnesses of disequality (a
 * != b is encoded as (a - b)w = 1, where w is the witness).
 */
class CocoaEncoder : public FieldObj
{
 public:
  /** Create a new encoder, for this field. */
  CocoaEncoder(const FfSize& size);
  /** Add a fact (one must call this twice per fact, once per stage). */
  void addFact(const Node& fact);
  /** Start Stage::Encode. */
  void endScan();
  /**
   * Get the polys who's common zero we are finding (excluding bitsums).
   * Available in Stage::Encode.
   */
  const std::vector& polys() const { return d_polys; }
  /**
   * Get the bitsum polys.
   * These have form: x - b0 - 2*b1 - 4b2 ... - 2^n*b_n.
   * Available in Stage::Encode.
   */
  const std::vector& bitsumPolys() const { return d_bitsumPolys; }
  /**
   * Get the poly for this term
   * Available in Stage::Encode.
   */
  const Poly& getTermEncoding(const Node& t) const { return d_cache.at(t); }
  /**
   * Get the bitsum terms (for the bitsumPolys).
   * Available in Stage::Encode.
   */
  std::vector bitsums() const;
  /**
   * The poly ring we've encoded into.
   * Available in Stage::Encode.
   */
  const CoCoA::ring& polyRing() const { return d_polyRing.value(); }
  /**
   * A list of (indeterminant num, Node) pairs. Useful for extracting a model.
   * Available in Stage::Encode.
   */
  std::vector> nodeIndets() const;
  /**
   * Convert a (coefficient) Scalar to a FiniteFieldValue.
   */
  FiniteFieldValue cocoaFfToFfVal(const Scalar& elem);
  /**
   * Does some fact that imply this poly?
   */
  bool polyHasFact(const Poly& poly) const;
  /**
   * Get the fact that implies this poly.
   */
  const Node& polyFact(const Poly& poly) const;

 private:
  /**
   * Get a fresh symbol that starts with varName.
   * If index is given, subscript the symbol by it.
   */
  CoCoA::symbol freshSym(const std::string& varName,
                         std::optional index = {});
  /** a bitsum or a var */
  const Node& symNode(CoCoA::symbol s) const;
  /** have we assigned this symbol to some Node? */
  bool hasNode(CoCoA::symbol s) const;
  /** get the poly for this symbol */
  const Poly& symPoly(CoCoA::symbol s) const;
  /** encode this term as a poly (caching) */
  void encodeTerm(const Node& t);
  /** encode this fact as a poly that must be zero (caching) */
  void encodeFact(const Node& f);

  /** Which pass we're in. */
  enum class Stage
  {
    /** collecting: variable, !=, bitsum */
    Scan,
    /** encoding terms */
    Encode,
  };

  // configuration

  /** the stage that we're in; initially scanning */
  Stage d_stage{Stage::Scan};

  // populated during Stage::Scan

  /** all nodes scanned */
  std::unordered_set d_scanned{};
  /** all variables seen */
  std::unordered_set d_vars{};
  /** map: bitsum term to its symbol */
  std::unordered_map d_bitsumSyms{};
  /** map: variable term to its symbol */
  std::unordered_map d_varSyms{};
  /** map: term (a != b) to the symbol for the inverse of (a - b) */
  std::unordered_map d_diseqSyms{};
  /** all symbols */
  std::vector d_syms{};
  /** map: symbol name to polynomial */
  std::unordered_map d_symPolys{};
  /** map: symbol name to term */
  std::unordered_map d_symNodes{};

  // populated at the end of Stage::Scan

  /** the polynomial ring */
  std::optional d_polyRing{};

  // populated during Stage::Encode

  /** encoding cache */
  std::unordered_map d_cache{};
  /** polynomials that must be zero (except bitsums) */
  std::vector d_polys{};
  /** bitsum polynomials that must be zero */
  std::vector d_bitsumPolys{};
  /** polys to the facts that imply them */
  std::unordered_map d_polyFacts{};
};

}  // namespace ff
}  // namespace theory
}  // namespace cvc5::internal

#endif /* CVC5__THEORY__FF__COCOA_H */

#endif /* CVC5_USE_COCOA */




© 2015 - 2024 Weber Informatics LLC | Privacy Policy