14#ifndef ORTOOLS_SAT_CIRCUIT_H_
15#define ORTOOLS_SAT_CIRCUIT_H_
21#include "absl/container/btree_set.h"
22#include "absl/container/flat_hash_map.h"
23#include "absl/types/span.h"
57 absl::Span<const int> heads,
58 absl::Span<const Literal> enforcement_literals,
59 absl::Span<const Literal> literals,
Options options,
74 void AddArc(
int tail,
int head, LiteralIndex literal_index);
79 void FillReasonForPath(
int start_node,
std::vector<
Literal>* reason) const;
83 bool ReportConflictOrPropagateEnforcement(
std::vector<
Literal>* reason);
89 EnforcementId enforcement_id_;
99 std::vector<LiteralIndex> self_arcs_;
107 std::vector<Literal> watch_index_to_literal_;
111 std::vector<int> next_;
112 std::vector<int> prev_;
113 std::vector<LiteralIndex> next_literal_;
117 std::vector<int> level_ends_;
118 std::vector<Arc> added_arcs_;
122 int rev_must_be_in_cycle_size_ = 0;
123 std::vector<int> must_be_in_cycle_;
126 std::vector<bool> processed_;
127 std::vector<bool> in_current_path_;
128 std::vector<Literal> temp_reason_;
135 absl::Span<const int> heads,
136 absl::Span<const Literal> literals,
Model* model);
145 const int num_nodes_;
150 std::vector<Literal> watch_index_to_literal_;
151 std::vector<std::vector<std::pair<int, int>>> watch_index_to_arcs_;
155 std::vector<std::vector<int>> graph_;
156 std::vector<std::vector<Literal>> graph_literals_;
162 std::vector<std::vector<int>> components_;
164 std::vector<std::vector<int>>>
168 std::vector<int> level_ends_;
169 std::vector<int> touched_nodes_;
186 absl::Span<const int> distinguished_nodes,
198 void FillFixedPathInReason(
int start,
int end, std::vector<Literal>* reason);
201 const std::vector<std::vector<Literal>> graph_;
202 const int num_nodes_;
203 std::vector<bool> node_is_distinguished_;
207 std::vector<std::pair<int, int>> watch_index_to_arc_;
208 std::vector<std::pair<int, int>> fixed_arcs_;
209 std::vector<int> level_ends_;
212 std::vector<int> next_;
213 std::vector<int> prev_;
214 std::vector<bool> visited_;
219template <
class IntContainer>
221 absl::flat_hash_map<int, int>* mapping_output =
nullptr) {
222 const int num_arcs = tails->size();
223 if (num_arcs == 0)
return 0;
226 absl::btree_set<int> nodes;
227 for (
int arc = 0; arc < num_arcs; ++arc) {
228 nodes.insert((*tails)[arc]);
229 nodes.insert((*heads)[arc]);
234 absl::flat_hash_map<int, int> mapping;
235 for (
const int node : nodes) {
236 mapping[node] = new_index++;
240 for (
int arc = 0; arc < num_arcs; ++arc) {
241 (*tails)[arc] = mapping[(*tails)[arc]];
242 (*heads)[arc] = mapping[(*heads)[arc]];
245 if (mapping_output !=
nullptr) {
246 *mapping_output = std::move(mapping);
260 absl::Span<const int> heads,
261 absl::Span<const Literal> enforcement_literals,
262 absl::Span<const Literal> literals,
Model* model,
263 bool multiple_subcircuit_through_zero =
false);
267 absl::Span<
const std::vector<Literal>> graph);
269 absl::Span<
const std::vector<Literal>> graph,
270 absl::Span<const int> distinguished_nodes);
CircuitCoveringPropagator(std::vector< std::vector< Literal > > graph, absl::Span< const int > distinguished_nodes, Model *model)
void RegisterWith(GenericLiteralWatcher *watcher)
void SetLevel(int level) final
bool IncrementalPropagate(const std::vector< int > &watch_indices) final
bool IncrementalPropagate(const std::vector< int > &watch_indices) final
void SetLevel(int level) final
CircuitPropagator(int num_nodes, absl::Span< const int > tails, absl::Span< const int > heads, absl::Span< const Literal > enforcement_literals, absl::Span< const Literal > literals, Options options, Model *model)
CircuitPropagator & operator=(const CircuitPropagator &)=delete
CircuitPropagator(const CircuitPropagator &)=delete
bool IncrementalPropagate(const std::vector< int > &watch_indices) final
NoCyclePropagator(int num_nodes, absl::Span< const int > tails, absl::Span< const int > heads, absl::Span< const Literal > literals, Model *model)
void SetLevel(int level) final
PropagatorInterface()=default
std::function< void(Model *)> CircuitCovering(absl::Span< const std::vector< Literal > > graph, absl::Span< const int > distinguished_nodes)
int ReindexArcs(IntContainer *tails, IntContainer *heads, absl::flat_hash_map< int, int > *mapping_output=nullptr)
void LoadSubcircuitConstraint(int num_nodes, absl::Span< const int > tails, absl::Span< const int > heads, absl::Span< const Literal > enforcement_literals, absl::Span< const Literal > literals, Model *model, bool multiple_subcircuit_through_zero)
std::function< void(Model *)> ExactlyOnePerRowAndPerColumn(absl::Span< const std::vector< Literal > > graph)
ClosedInterval::Iterator end(ClosedInterval interval)
bool multiple_subcircuit_through_zero