|
|
|||
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
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|