21#include "absl/container/flat_hash_set.h"
22#include "absl/log/check.h"
23#include "absl/strings/str_format.h"
31int64_t ValueToIndex(int64_t
value) {
return value - 1; }
33int64_t IndexToValue(int64_t
index) {
return index + 1; }
42 const std::vector<IntervalVar*>& intervals,
43 const std::vector<IntVar*>& nexts,
44 const std::string&
name)
46 intervals_(intervals),
48 previous_(nexts.
size() + 1, -1) {
55 return intervals_[
index];
61 int64_t hmin, hmax, dmin, dmax;
68 return absl::StrFormat(
69 "%s(horizon = %d..%d, duration = %d..%d, not ranked = %d, ranked = %d, "
71 name(), hmin, hmax, dmin, dmax, not_ranked, ranked,
80 int64_t*
const dmax)
const {
83 for (
int i = 0; i < intervals_.size(); ++i) {
97 int64_t hor_min = std::numeric_limits<int64_t>::max();
98 int64_t hor_max = std::numeric_limits<int64_t>::min();
99 for (
int i = 0; i < intervals_.size(); ++i) {
103 hor_min = std::min(hor_min, t->
StartMin());
104 hor_max = std::max(hor_max, t->
EndMax());
112 int64_t*
const hmax)
const {
113 absl::flat_hash_set<int> decided;
114 for (
int i = 0; i < intervals_.size(); ++i) {
115 if (intervals_[i]->CannotBePerformed()) {
120 while (nexts_[first]->Bound()) {
121 first = nexts_[first]->Min();
122 if (first < nexts_.size()) {
123 decided.insert(ValueToIndex(first));
128 if (first != nexts_.size()) {
130 int last = nexts_.size();
131 while (previous_[last] != -1) {
132 last = previous_[last];
133 decided.insert(ValueToIndex(last));
136 int64_t hor_min = std::numeric_limits<int64_t>::max();
137 int64_t hor_max = std::numeric_limits<int64_t>::min();
138 for (
int i = 0; i < intervals_.size(); ++i) {
139 if (!decided.contains(i)) {
141 hor_min = std::min(hor_min, t->
StartMin());
142 hor_max = std::max(hor_max, t->
EndMax());
150 int*
const unperformed)
const {
152 for (
int i = 0; i < intervals_.size(); ++i) {
153 if (intervals_[i]->CannotBePerformed()) {
159 while (first < nexts_.size() && nexts_[first]->Bound()) {
160 first = nexts_[first]->Min();
163 if (first != nexts_.size()) {
165 int last = nexts_.size();
166 while (previous_[last] != -1) {
167 last = previous_[last];
173 *not_ranked = intervals_.size() - *ranked - *unperformed;
176int SequenceVar::ComputeForwardFrontier() {
178 while (first != nexts_.size() && nexts_[first]->Bound()) {
179 first = nexts_[first]->Min();
184int SequenceVar::ComputeBackwardFrontier() {
186 int last = nexts_.size();
187 while (previous_[last] != -1) {
188 last = previous_[last];
194 std::vector<int>*
const possible_firsts,
195 std::vector<int>*
const possible_lasts) {
196 possible_firsts->clear();
197 possible_lasts->clear();
198 absl::flat_hash_set<int> to_check;
199 for (
int i = 0; i < intervals_.size(); ++i) {
200 if (intervals_[i]->MayBePerformed()) {
205 while (nexts_[first]->Bound()) {
206 first = nexts_[first]->Min();
207 if (first == nexts_.size()) {
210 to_check.erase(ValueToIndex(first));
213 IntVar*
const forward_var = nexts_[first];
214 std::vector<int> candidates;
215 int64_t smallest_start_max = std::numeric_limits<int64_t>::max();
216 int ssm_support = -1;
217 for (int64_t i = forward_var->
Min(); i <= forward_var->Max(); ++i) {
219 if (i != 0 && i < IndexToValue(intervals_.size()) &&
220 intervals_[ValueToIndex(i)]->MayBePerformed() &&
222 const int candidate = ValueToIndex(i);
223 candidates.push_back(candidate);
224 if (intervals_[candidate]->MustBePerformed()) {
225 if (smallest_start_max > intervals_[candidate]->StartMax()) {
226 smallest_start_max = intervals_[candidate]->StartMax();
227 ssm_support = candidate;
232 for (
int i = 0; i < candidates.size(); ++i) {
233 const int candidate = candidates[i];
234 if (candidate == ssm_support ||
235 intervals_[candidate]->EndMin() <= smallest_start_max) {
236 possible_firsts->push_back(candidate);
241 int last = nexts_.size();
242 while (previous_[last] != -1) {
243 last = previous_[last];
244 to_check.erase(ValueToIndex(last));
248 int64_t biggest_end_min = std::numeric_limits<int64_t>::min();
249 int bem_support = -1;
250 for (
const int candidate : to_check) {
251 if (nexts_[IndexToValue(candidate)]->Contains(last)) {
252 candidates.push_back(candidate);
253 if (intervals_[candidate]->MustBePerformed()) {
254 if (biggest_end_min < intervals_[candidate]->EndMin()) {
255 biggest_end_min = intervals_[candidate]->EndMin();
256 bem_support = candidate;
262 for (
int i = 0; i < candidates.size(); ++i) {
263 const int candidate = candidates[i];
264 if (candidate == bem_support ||
265 intervals_[candidate]->StartMax() >= biggest_end_min) {
266 possible_lasts->push_back(candidate);
272 const std::vector<int>& rank_last,
273 const std::vector<int>& unperformed) {
277 for (
const int value : unperformed) {
278 intervals_[
value]->SetPerformed(
false);
282 for (
int i = 0; i < rank_first.size(); ++i) {
283 const int next = 1 + rank_first[i];
284 nexts_[forward]->SetValue(
next);
288 int backward = IndexToValue(intervals_.size());
289 for (
int i = 0; i < rank_last.size(); ++i) {
290 const int next = 1 + rank_last[i];
291 nexts_[
next]->SetValue(backward);
298 intervals_[
index]->SetPerformed(
true);
299 int forward_frontier = 0;
300 while (forward_frontier != nexts_.size() &&
301 nexts_[forward_frontier]->Bound()) {
302 forward_frontier = nexts_[forward_frontier]->Min();
303 if (forward_frontier == IndexToValue(
index)) {
307 DCHECK_LT(forward_frontier, nexts_.size());
308 nexts_[forward_frontier]->SetValue(IndexToValue(
index));
313 const int forward_frontier = ComputeForwardFrontier();
314 if (forward_frontier < nexts_.size()) {
315 nexts_[forward_frontier]->RemoveValue(IndexToValue(
index));
321 intervals_[
index]->SetPerformed(
true);
323 int backward_frontier = nexts_.size();
324 while (previous_[backward_frontier] != -1) {
325 backward_frontier = previous_[backward_frontier];
326 if (backward_frontier == IndexToValue(
index)) {
330 DCHECK_NE(backward_frontier, 0);
331 nexts_[IndexToValue(
index)]->SetValue(backward_frontier);
336 const int backward_frontier = ComputeBackwardFrontier();
337 nexts_[IndexToValue(
index)]->RemoveValue(backward_frontier);
340void SequenceVar::UpdatePrevious()
const {
341 for (
int i = 0; i < intervals_.size() + 2; ++i) {
344 for (
int i = 0; i < nexts_.size(); ++i) {
345 if (nexts_[i]->Bound()) {
346 previous_[nexts_[i]->Min()] = i;
352 std::vector<int>*
const rank_last,
353 std::vector<int>*
const unperformed)
const {
354 CHECK(rank_first !=
nullptr);
355 CHECK(rank_last !=
nullptr);
356 CHECK(unperformed !=
nullptr);
359 unperformed->clear();
360 for (
int i = 0; i < intervals_.size(); ++i) {
361 if (intervals_[i]->CannotBePerformed()) {
362 unperformed->push_back(i);
366 while (nexts_[first]->Bound()) {
367 first = nexts_[first]->Min();
368 if (first < nexts_.size()) {
369 rank_first->push_back(ValueToIndex(first));
374 if (first != nexts_.size()) {
376 int last = nexts_.size();
377 while (previous_[last] != -1) {
378 last = previous_[last];
379 rank_last->push_back(ValueToIndex(last));
392class ScheduleOrPostpone :
public Decision {
394 ScheduleOrPostpone(
IntervalVar*
const var, int64_t est, int64_t*
const marker)
395 : var_(
var), est_(est), marker_(marker) {}
396 ~ScheduleOrPostpone()
override {}
398 void Apply(Solver*
const s)
override {
399 var_->SetPerformed(
true);
400 if (est_.Value() < var_->StartMin()) {
401 est_.SetValue(s, var_->StartMin());
403 var_->SetStartRange(est_.Value(), est_.Value());
406 void Refute(Solver*
const s)
override {
407 s->SaveAndSetValue(marker_, est_.Value());
410 void Accept(DecisionVisitor*
const visitor)
const override {
411 CHECK(visitor !=
nullptr);
412 visitor->VisitScheduleOrPostpone(var_, est_.Value());
415 std::string DebugString()
const override {
416 return absl::StrFormat(
"ScheduleOrPostpone(%s at %d)", var_->DebugString(),
421 IntervalVar*
const var_;
422 NumericalRev<int64_t> est_;
423 int64_t*
const marker_;
426class SetTimesForward :
public DecisionBuilder {
428 explicit SetTimesForward(
const std::vector<IntervalVar*>& vars)
430 markers_(vars.
size(),
std::numeric_limits<int64_t>::
min()) {}
432 ~SetTimesForward()
override {}
434 Decision*
Next(Solver*
const s)
override {
435 int64_t best_est = std::numeric_limits<int64_t>::max();
436 int64_t best_lct = std::numeric_limits<int64_t>::max();
441 for (
int i = 0;
i <
vars_.size(); ++
i) {
442 IntervalVar*
const v =
vars_[
i];
443 if (v->MayBePerformed() && v->StartMax() != v->StartMin() &&
445 (v->StartMin() < best_est ||
446 (v->StartMin() == best_est && v->EndMax() < best_lct))) {
447 best_est = v->StartMin();
448 best_lct = v->EndMax();
455 UnperformPostponedTaskBefore(std::numeric_limits<int64_t>::max());
458 UnperformPostponedTaskBefore(best_est);
460 new ScheduleOrPostpone(vars_[support], best_est, &markers_[support]));
463 std::string DebugString()
const override {
return "SetTimesForward()"; }
465 void Accept(ModelVisitor*
const visitor)
const override {
473 bool IsPostponed(
int index) {
474 DCHECK(vars_[
index]->MayBePerformed());
478 void UnperformPostponedTaskBefore(int64_t date) {
479 for (
int i = 0;
i <
vars_.size(); ++
i) {
480 IntervalVar*
const v =
vars_[
i];
481 if (v->MayBePerformed() && v->StartMin() != v->StartMax() &&
490 (v->EndMin() <= date || v->StartMax() <= date)) {
491 v->SetPerformed(
false);
496 const std::vector<IntervalVar*>
vars_;
497 std::vector<int64_t> markers_;
503class ScheduleOrExpedite :
public Decision {
505 ScheduleOrExpedite(IntervalVar*
const var, int64_t est, int64_t*
const marker)
506 : var_(
var), est_(est), marker_(marker) {}
507 ~ScheduleOrExpedite()
override {}
509 void Apply(Solver*
const s)
override {
510 var_->SetPerformed(
true);
511 if (est_.Value() > var_->EndMax()) {
512 est_.SetValue(s, var_->EndMax());
514 var_->SetEndRange(est_.Value(), est_.Value());
517 void Refute(Solver*
const s)
override {
518 s->SaveAndSetValue(marker_, est_.Value() - 1);
521 void Accept(DecisionVisitor*
const visitor)
const override {
522 CHECK(visitor !=
nullptr);
523 visitor->VisitScheduleOrExpedite(var_, est_.Value());
526 std::string DebugString()
const override {
527 return absl::StrFormat(
"ScheduleOrExpedite(%s at %d)", var_->DebugString(),
532 IntervalVar*
const var_;
533 NumericalRev<int64_t> est_;
534 int64_t*
const marker_;
537class SetTimesBackward :
public DecisionBuilder {
539 explicit SetTimesBackward(
const std::vector<IntervalVar*>& vars)
541 markers_(vars.
size(),
std::numeric_limits<int64_t>::
max()) {}
543 ~SetTimesBackward()
override {}
545 Decision*
Next(Solver*
const s)
override {
546 int64_t best_end = std::numeric_limits<int64_t>::min();
547 int64_t best_start = std::numeric_limits<int64_t>::min();
550 for (
int i = 0;
i <
vars_.size(); ++
i) {
551 IntervalVar*
const v =
vars_[
i];
552 if (v->MayBePerformed() && v->EndMax() > v->EndMin()) {
553 if (v->EndMax() <= markers_[i] &&
554 (v->EndMax() > best_end ||
555 (v->EndMax() == best_end && v->StartMin() > best_start))) {
556 best_end = v->EndMax();
557 best_start = v->StartMin();
573 return s->RevAlloc(
new ScheduleOrExpedite(
574 vars_[support], vars_[support]->EndMax(), &markers_[support]));
577 std::string DebugString()
const override {
return "SetTimesBackward()"; }
579 void Accept(ModelVisitor*
const visitor)
const override {
587 const std::vector<IntervalVar*>
vars_;
588 std::vector<int64_t> markers_;
593class RankFirst :
public Decision {
595 RankFirst(SequenceVar*
const seq,
int index)
596 : sequence_(seq), index_(
index) {}
597 ~RankFirst()
override {}
599 void Apply(Solver*
const s)
override { sequence_->RankFirst(index_); }
601 void Refute(Solver*
const s)
override { sequence_->RankNotFirst(index_); }
603 void Accept(DecisionVisitor*
const visitor)
const override {
604 CHECK(visitor !=
nullptr);
605 visitor->VisitRankFirstInterval(sequence_, index_);
608 std::string DebugString()
const override {
609 return absl::StrFormat(
"RankFirst(%s, %d)", sequence_->DebugString(),
614 SequenceVar*
const sequence_;
618class RankLast :
public Decision {
620 RankLast(SequenceVar*
const seq,
int index) : sequence_(seq), index_(
index) {}
621 ~RankLast()
override {}
623 void Apply(Solver*
const s)
override { sequence_->RankLast(index_); }
625 void Refute(Solver*
const s)
override { sequence_->RankNotLast(index_); }
627 void Accept(DecisionVisitor*
const visitor)
const override {
628 CHECK(visitor !=
nullptr);
629 visitor->VisitRankLastInterval(sequence_, index_);
632 std::string DebugString()
const override {
633 return absl::StrFormat(
"RankLast(%s, %d)", sequence_->DebugString(),
638 SequenceVar*
const sequence_;
642class RankFirstIntervalVars :
public DecisionBuilder {
644 RankFirstIntervalVars(
const std::vector<SequenceVar*>& sequences,
646 : sequences_(sequences), strategy_(str) {}
648 ~RankFirstIntervalVars()
override {}
650 Decision*
Next(Solver*
const s)
override {
651 SequenceVar* best_sequence =
nullptr;
652 best_possible_firsts_.clear();
654 if (FindSequenceVar(s, &best_sequence)) {
656 DCHECK(best_sequence !=
nullptr);
657 if (best_possible_firsts_.size() == 1 &&
658 best_sequence->Interval(best_possible_firsts_.back())
659 ->MustBePerformed()) {
660 best_sequence->RankFirst(best_possible_firsts_.back());
663 int best_interval = -1;
664 if (!FindIntervalVar(s, best_sequence, &best_interval)) {
667 CHECK_NE(-1, best_interval);
668 return s->RevAlloc(
new RankFirst(best_sequence, best_interval));
675 void Accept(ModelVisitor*
const visitor)
const override {
684 bool FindIntervalVarOnStartMin(Solver*
const s,
685 SequenceVar*
const best_sequence,
686 int*
const best_interval_index) {
687 int best_interval = -1;
688 int64_t best_start_min = std::numeric_limits<int64_t>::max();
690 const int candidate = best_possible_firsts_[
index];
691 IntervalVar*
const interval = best_sequence->Interval(candidate);
692 if (
interval->StartMin() < best_start_min) {
693 best_interval = candidate;
694 best_start_min =
interval->StartMin();
697 if (best_interval == -1) {
700 *best_interval_index = best_interval;
705 bool FindIntervalVarRandomly(Solver*
const s,
706 SequenceVar*
const best_sequence,
707 int*
const best_interval_index) {
708 DCHECK(!best_possible_firsts_.empty());
709 const int index = s->Rand32(best_possible_firsts_.size());
710 *best_interval_index = best_possible_firsts_[
index];
714 bool FindIntervalVar(Solver*
const s, SequenceVar*
const best_sequence,
715 int*
const best_interval_index) {
720 return FindIntervalVarOnStartMin(s, best_sequence, best_interval_index);
722 return FindIntervalVarRandomly(s, best_sequence, best_interval_index);
724 LOG(FATAL) <<
"Unknown strategy " << strategy_;
730 bool FindSequenceVarOnSlack(Solver*
const s,
731 SequenceVar**
const best_sequence) {
732 int64_t best_slack = std::numeric_limits<int64_t>::max();
733 int64_t best_ahmin = std::numeric_limits<int64_t>::max();
734 *best_sequence =
nullptr;
735 best_possible_firsts_.clear();
736 for (
int i = 0;
i < sequences_.size(); ++
i) {
737 SequenceVar*
const candidate_sequence = sequences_[
i];
741 candidate_sequence->ComputeStatistics(&ranked, ¬_ranked, &unperformed);
742 if (not_ranked > 0) {
743 candidate_possible_firsts_.clear();
744 candidate_possible_lasts_.clear();
745 candidate_sequence->ComputePossibleFirstsAndLasts(
746 &candidate_possible_firsts_, &candidate_possible_lasts_);
748 if (candidate_possible_firsts_.empty()) {
752 if (candidate_possible_firsts_.size() == 1 &&
753 candidate_sequence->Interval(candidate_possible_firsts_.back())
754 ->MustBePerformed()) {
755 *best_sequence = candidate_sequence;
756 best_possible_firsts_ = candidate_possible_firsts_;
761 int64_t hmin, hmax, dmin, dmax;
762 candidate_sequence->HorizonRange(&hmin, &hmax);
763 candidate_sequence->DurationRange(&dmin, &dmax);
764 int64_t ahmin, ahmax;
765 candidate_sequence->ActiveHorizonRange(&ahmin, &ahmax);
766 const int64_t current_slack = (hmax - hmin - dmax);
767 if (current_slack < best_slack ||
768 (current_slack == best_slack && ahmin < best_ahmin)) {
769 best_slack = current_slack;
770 *best_sequence = candidate_sequence;
771 best_possible_firsts_ = candidate_possible_firsts_;
776 return *best_sequence !=
nullptr;
779 bool FindSequenceVarRandomly(Solver*
const s,
780 SequenceVar**
const best_sequence) {
781 std::vector<SequenceVar*> all_candidates;
782 std::vector<std::vector<int>> all_possible_firsts;
783 for (
int i = 0;
i < sequences_.size(); ++
i) {
784 SequenceVar*
const candidate_sequence = sequences_[
i];
788 candidate_sequence->ComputeStatistics(&ranked, ¬_ranked, &unperformed);
789 if (not_ranked > 0) {
790 candidate_possible_firsts_.clear();
791 candidate_possible_lasts_.clear();
792 candidate_sequence->ComputePossibleFirstsAndLasts(
793 &candidate_possible_firsts_, &candidate_possible_lasts_);
795 if (candidate_possible_firsts_.empty()) {
799 if (candidate_possible_firsts_.size() == 1 &&
800 candidate_sequence->Interval(candidate_possible_firsts_.back())
801 ->MustBePerformed()) {
802 *best_sequence = candidate_sequence;
803 best_possible_firsts_ = candidate_possible_firsts_;
807 all_candidates.push_back(candidate_sequence);
808 all_possible_firsts.push_back(candidate_possible_firsts_);
811 if (all_candidates.empty()) {
814 const int chosen = s->Rand32(all_candidates.size());
815 *best_sequence = all_candidates[chosen];
816 best_possible_firsts_ = all_possible_firsts[chosen];
820 bool FindSequenceVar(Solver*
const s, SequenceVar**
const best_sequence) {
825 return FindSequenceVarOnSlack(s, best_sequence);
827 return FindSequenceVarRandomly(s, best_sequence);
829 LOG(FATAL) <<
"Unknown strategy " << strategy_;
833 const std::vector<SequenceVar*> sequences_;
835 std::vector<int> best_possible_firsts_;
836 std::vector<int> candidate_possible_firsts_;
837 std::vector<int> candidate_possible_lasts_;
842 int64_t*
const marker) {
843 CHECK(
var !=
nullptr);
844 CHECK(marker !=
nullptr);
845 return RevAlloc(
new ScheduleOrPostpone(
var, est, marker));
849 int64_t*
const marker) {
850 CHECK(
var !=
nullptr);
851 CHECK(marker !=
nullptr);
852 return RevAlloc(
new ScheduleOrExpedite(
var, est, marker));
861 return RevAlloc(
new SetTimesForward(intervals));
863 return RevAlloc(
new SetTimesBackward(intervals));
865 LOG(FATAL) <<
"Unknown strategy " << str;
871 CHECK(sequence !=
nullptr);
876 CHECK(sequence !=
nullptr);
882 return RevAlloc(
new RankFirstIntervalVars(sequences, str));
const std::vector< IntVar * > vars_
virtual int64_t Min() const =0
virtual bool Contains(int64_t v) const =0
virtual int64_t DurationMax() const =0
virtual int64_t EndMax() const =0
virtual bool MayBePerformed() const =0
virtual int64_t DurationMin() const =0
These methods query, set, and watch the duration of the interval var.
virtual int64_t StartMin() const =0
virtual bool MustBePerformed() const =0
virtual void VisitSequenceVariable(const SequenceVar *variable)
static const char kSequencesArgument[]
static const char kVariableGroupExtension[]
static const char kIntervalsArgument[]
virtual std::string name() const
Object naming.
void set_name(absl::string_view name)
virtual void RankSequence(SequenceVar *var, const std::vector< int > &rank_first, const std::vector< int > &rank_last, const std::vector< int > &unperformed)=0
virtual void RankNotFirst(SequenceVar *var, int index)=0
virtual void RankNotLast(SequenceVar *var, int index)=0
virtual void RankFirst(SequenceVar *var, int index)=0
SequenceVar modifiers.
virtual void RankLast(SequenceVar *var, int index)=0
void RankNotFirst(int index)
void HorizonRange(int64_t *hmin, int64_t *hmax) const
virtual void Accept(ModelVisitor *visitor) const
Accepts the given visitor.
void RankNotLast(int index)
void RankSequence(const std::vector< int > &rank_first, const std::vector< int > &rank_last, const std::vector< int > &unperformed)
IntervalVar * Interval(int index) const
Returns the index_th interval of the sequence.
void ComputePossibleFirstsAndLasts(std::vector< int > *possible_firsts, std::vector< int > *possible_lasts)
IntVar * Next(int index) const
Returns the next of the index_th interval of the sequence.
SequenceVar(Solver *s, const std::vector< IntervalVar * > &intervals, const std::vector< IntVar * > &nexts, const std::string &name)
--— SequenceVar --—
void RankFirst(int index)
void ComputeStatistics(int *ranked, int *not_ranked, int *unperformed) const
Compute statistics on the sequence.
void FillSequence(std::vector< int > *rank_first, std::vector< int > *rank_last, std::vector< int > *unperformed) const
std::string DebugString() const override
void ActiveHorizonRange(int64_t *hmin, int64_t *hmax) const
void DurationRange(int64_t *dmin, int64_t *dmax) const
For the time being, Solver is neither MT_SAFE nor MT_HOT.
Decision * MakeRankLastInterval(SequenceVar *sequence, int index)
DecisionBuilder * MakePhase(const std::vector< IntVar * > &vars, IntVarStrategy var_str, IntValueStrategy val_str)
Decision * MakeScheduleOrExpedite(IntervalVar *var, int64_t est, int64_t *marker)
SequenceStrategy
Used for scheduling. Not yet implemented.
@ CHOOSE_RANDOM_RANK_FORWARD
@ CHOOSE_MIN_SLACK_RANK_FORWARD
Decision * MakeRankFirstInterval(SequenceVar *sequence, int index)
Decision * MakeScheduleOrPostpone(IntervalVar *var, int64_t est, int64_t *marker)
@ INTERVAL_SET_TIMES_FORWARD
@ INTERVAL_DEFAULT
The default is INTERVAL_SET_TIMES_FORWARD.
@ INTERVAL_SET_TIMES_BACKWARD
@ INTERVAL_SIMPLE
The simple is INTERVAL_SET_TIMES_FORWARD.
PropagationMonitor * GetPropagationMonitor() const
Returns the propagation monitor.
const std::string name
A name for logging purposes.
In SWIG mode, we don't want anything besides these top-level includes.
std::string JoinDebugStringPtr(const std::vector< T > &v, absl::string_view separator)
Join v[i]->DebugString().