Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:36:24

0001 //===- CNFFormula.h ---------------------------------------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 //  A representation of a boolean formula in 3-CNF.
0010 //
0011 //===----------------------------------------------------------------------===//
0012 
0013 #ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_CNFFORMULA_H
0014 #define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_CNFFORMULA_H
0015 
0016 #include <cstdint>
0017 #include <vector>
0018 
0019 #include "clang/Analysis/FlowSensitive/Formula.h"
0020 
0021 namespace clang {
0022 namespace dataflow {
0023 
0024 /// Boolean variables are represented as positive integers.
0025 using Variable = uint32_t;
0026 
0027 /// A null boolean variable is used as a placeholder in various data structures
0028 /// and algorithms.
0029 constexpr Variable NullVar = 0;
0030 
0031 /// Literals are represented as positive integers. Specifically, for a boolean
0032 /// variable `V` that is represented as the positive integer `I`, the positive
0033 /// literal `V` is represented as the integer `2*I` and the negative literal
0034 /// `!V` is represented as the integer `2*I+1`.
0035 using Literal = uint32_t;
0036 
0037 /// A null literal is used as a placeholder in various data structures and
0038 /// algorithms.
0039 constexpr Literal NullLit = 0;
0040 
0041 /// Clause identifiers are represented as positive integers.
0042 using ClauseID = uint32_t;
0043 
0044 /// A null clause identifier is used as a placeholder in various data structures
0045 /// and algorithms.
0046 constexpr ClauseID NullClause = 0;
0047 
0048 /// Returns the positive literal `V`.
0049 inline constexpr Literal posLit(Variable V) { return 2 * V; }
0050 
0051 /// Returns the negative literal `!V`.
0052 inline constexpr Literal negLit(Variable V) { return 2 * V + 1; }
0053 
0054 /// Returns whether `L` is a positive literal.
0055 inline constexpr bool isPosLit(Literal L) { return 0 == (L & 1); }
0056 
0057 /// Returns whether `L` is a negative literal.
0058 inline constexpr bool isNegLit(Literal L) { return 1 == (L & 1); }
0059 
0060 /// Returns the negated literal `!L`.
0061 inline constexpr Literal notLit(Literal L) { return L ^ 1; }
0062 
0063 /// Returns the variable of `L`.
0064 inline constexpr Variable var(Literal L) { return L >> 1; }
0065 
0066 /// A boolean formula in 3-CNF (conjunctive normal form with at most 3 literals
0067 /// per clause).
0068 class CNFFormula {
0069   /// `LargestVar` is equal to the largest positive integer that represents a
0070   /// variable in the formula.
0071   const Variable LargestVar;
0072 
0073   /// Literals of all clauses in the formula.
0074   ///
0075   /// The element at index 0 stands for the literal in the null clause. It is
0076   /// set to 0 and isn't used. Literals of clauses in the formula start from the
0077   /// element at index 1.
0078   ///
0079   /// For example, for the formula `(L1 v L2) ^ (L2 v L3 v L4)` the elements of
0080   /// `Clauses` will be `[0, L1, L2, L2, L3, L4]`.
0081   std::vector<Literal> Clauses;
0082 
0083   /// Start indices of clauses of the formula in `Clauses`.
0084   ///
0085   /// The element at index 0 stands for the start index of the null clause. It
0086   /// is set to 0 and isn't used. Start indices of clauses in the formula start
0087   /// from the element at index 1.
0088   ///
0089   /// For example, for the formula `(L1 v L2) ^ (L2 v L3 v L4)` the elements of
0090   /// `ClauseStarts` will be `[0, 1, 3]`. Note that the literals of the first
0091   /// clause always start at index 1. The start index for the literals of the
0092   /// second clause depends on the size of the first clause and so on.
0093   std::vector<size_t> ClauseStarts;
0094 
0095   /// Indicates that we already know the formula is unsatisfiable.
0096   /// During construction, we catch simple cases of conflicting unit-clauses.
0097   bool KnownContradictory;
0098 
0099 public:
0100   explicit CNFFormula(Variable LargestVar);
0101 
0102   /// Adds the `L1 v ... v Ln` clause to the formula.
0103   /// Requirements:
0104   ///
0105   ///  `Li` must not be `NullLit`.
0106   ///
0107   ///  All literals in the input that are not `NullLit` must be distinct.
0108   void addClause(ArrayRef<Literal> lits);
0109 
0110   /// Returns whether the formula is known to be contradictory.
0111   /// This is the case if any of the clauses is empty.
0112   bool knownContradictory() const { return KnownContradictory; }
0113 
0114   /// Returns the largest variable in the formula.
0115   Variable largestVar() const { return LargestVar; }
0116 
0117   /// Returns the number of clauses in the formula.
0118   /// Valid clause IDs are in the range [1, `numClauses()`].
0119   ClauseID numClauses() const { return ClauseStarts.size() - 1; }
0120 
0121   /// Returns the number of literals in clause `C`.
0122   size_t clauseSize(ClauseID C) const {
0123     return C == ClauseStarts.size() - 1 ? Clauses.size() - ClauseStarts[C]
0124                                         : ClauseStarts[C + 1] - ClauseStarts[C];
0125   }
0126 
0127   /// Returns the literals of clause `C`.
0128   /// If `knownContradictory()` is false, each clause has at least one literal.
0129   llvm::ArrayRef<Literal> clauseLiterals(ClauseID C) const {
0130     size_t S = clauseSize(C);
0131     if (S == 0)
0132       return llvm::ArrayRef<Literal>();
0133     return llvm::ArrayRef<Literal>(&Clauses[ClauseStarts[C]], S);
0134   }
0135 
0136   /// An iterator over all literals of all clauses in the formula.
0137   /// The iterator allows mutation of the literal through the `*` operator.
0138   /// This is to support solvers that mutate the formula during solving.
0139   class Iterator {
0140     friend class CNFFormula;
0141     CNFFormula *CNF;
0142     size_t Idx;
0143     Iterator(CNFFormula *CNF, size_t Idx) : CNF(CNF), Idx(Idx) {}
0144 
0145   public:
0146     Iterator(const Iterator &) = default;
0147     Iterator &operator=(const Iterator &) = default;
0148 
0149     Iterator &operator++() {
0150       ++Idx;
0151       assert(Idx < CNF->Clauses.size() && "Iterator out of bounds");
0152       return *this;
0153     }
0154 
0155     Iterator next() const {
0156       Iterator I = *this;
0157       ++I;
0158       return I;
0159     }
0160 
0161     Literal &operator*() const { return CNF->Clauses[Idx]; }
0162   };
0163   friend class Iterator;
0164 
0165   /// Returns an iterator to the first literal of clause `C`.
0166   Iterator startOfClause(ClauseID C) { return Iterator(this, ClauseStarts[C]); }
0167 };
0168 
0169 /// Converts the conjunction of `Vals` into a formula in conjunctive normal
0170 /// form where each clause has at least one and at most three literals.
0171 /// `Atomics` is populated with a mapping from `Variables` to the corresponding
0172 /// `Atom`s for atomic booleans in the input formulas.
0173 CNFFormula buildCNF(const llvm::ArrayRef<const Formula *> &Formulas,
0174                     llvm::DenseMap<Variable, Atom> &Atomics);
0175 
0176 } // namespace dataflow
0177 } // namespace clang
0178 
0179 #endif // LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_CNFFORMULA_H