14#ifndef OR_TOOLS_SAT_CIRCUIT_H_
15#define OR_TOOLS_SAT_CIRCUIT_H_
21#include "absl/container/btree_set.h"
22#include "absl/container/flat_hash_map.h"
23#include "absl/types/span.h"
55 absl::Span<const int> heads,
56 absl::Span<const Literal> literals,
Options options,
70 void AddArc(
int tail,
int head, LiteralIndex literal_index);
75 void FillReasonForPath(
int start_node,
std::vector<
Literal>* reason) const;
88 std::vector<LiteralIndex> self_arcs_;
96 std::vector<Literal> watch_index_to_literal_;
100 std::vector<int> next_;
101 std::vector<int> prev_;
102 std::vector<LiteralIndex> next_literal_;
106 std::vector<int> level_ends_;
107 std::vector<Arc> added_arcs_;
111 int rev_must_be_in_cycle_size_ = 0;
112 std::vector<int> must_be_in_cycle_;
115 std::vector<bool> processed_;
116 std::vector<bool> in_current_path_;
123 absl::Span<const int> heads,
124 absl::Span<const Literal> literals,
Model* model);
133 const int num_nodes_;
138 std::vector<Literal> watch_index_to_literal_;
139 std::vector<std::vector<std::pair<int, int>>> watch_index_to_arcs_;
143 std::vector<std::vector<int>> graph_;
144 std::vector<std::vector<Literal>> graph_literals_;
150 std::vector<std::vector<int>> components_;
152 std::vector<std::vector<int>>>
156 std::vector<int> level_ends_;
157 std::vector<int> touched_nodes_;
174 absl::Span<const int> distinguished_nodes,
186 void FillFixedPathInReason(
int start,
int end, std::vector<Literal>* reason);
189 const std::vector<std::vector<Literal>> graph_;
190 const int num_nodes_;
191 std::vector<bool> node_is_distinguished_;
195 std::vector<std::pair<int, int>> watch_index_to_arc_;
196 std::vector<std::pair<int, int>> fixed_arcs_;
197 std::vector<int> level_ends_;
200 std::vector<int> next_;
201 std::vector<int> prev_;
202 std::vector<bool> visited_;
207template <
class IntContainer>
209 absl::flat_hash_map<int, int>* mapping_output =
nullptr) {
210 const int num_arcs = tails->size();
211 if (num_arcs == 0)
return 0;
214 absl::btree_set<int> nodes;
215 for (
int arc = 0; arc < num_arcs; ++arc) {
216 nodes.insert((*tails)[arc]);
217 nodes.insert((*heads)[arc]);
222 absl::flat_hash_map<int, int> mapping;
223 for (
const int node : nodes) {
224 mapping[node] = new_index++;
228 for (
int arc = 0; arc < num_arcs; ++arc) {
229 (*tails)[arc] = mapping[(*tails)[arc]];
230 (*heads)[arc] = mapping[(*heads)[arc]];
233 if (mapping_output !=
nullptr) {
234 *mapping_output = std::move(mapping);
248 absl::Span<const int> heads,
249 absl::Span<const Literal> literals,
Model* model,
250 bool multiple_subcircuit_through_zero =
false);
254 absl::Span<
const std::vector<Literal>> graph);
256 absl::Span<
const std::vector<Literal>> graph,
257 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
void RegisterWith(GenericLiteralWatcher *watcher)
bool IncrementalPropagate(const std::vector< int > &watch_indices) final
void SetLevel(int level) final
CircuitPropagator & operator=(const CircuitPropagator &)=delete
CircuitPropagator(int num_nodes, absl::Span< const int > tails, absl::Span< const int > heads, absl::Span< const Literal > literals, Options options, Model *model)
CircuitPropagator(const CircuitPropagator &)=delete
This type is neither copyable nor movable.
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
void LoadSubcircuitConstraint(int num_nodes, absl::Span< const int > tails, absl::Span< const int > heads, absl::Span< const Literal > literals, Model *model, bool multiple_subcircuit_through_zero)
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)
std::function< void(Model *)> ExactlyOnePerRowAndPerColumn(absl::Span< const std::vector< Literal > > graph)
In SWIG mode, we don't want anything besides these top-level includes.
bool multiple_subcircuit_through_zero