Google OR-Tools: ortools/constraint_solver/demon_profiler.cc Source File

1

2

3

4

5

6

7

8

9

10

11

12

13

14#include <algorithm>

15#include <cmath>

16#include <cstddef>

17#include <cstdint>

18#include <string>

19#include <utility>

20#include <vector>

21

22#include "absl/container/flat_hash_map.h"

23#include "absl/status/status.h"

24#include "absl/strings/str_format.h"

25#include "absl/strings/string_view.h"

26#include "absl/time/clock.h"

27#include "absl/time/time.h"

38

40namespace {

41struct Container {

42 Container(const Constraint* ct_, int64_t value_) : ct(ct_), value(value_) {}

43 bool operator<(const Container& c) const { return value > c.value; }

44

45 const Constraint* ct;

46 int64_t value;

47};

48}

49

50

51

52

54 public:

57 active_constraint_(nullptr),

58 active_demon_(nullptr),

59 start_time_ns_(absl::GetCurrentTimeNanos()) {}

60

63 constraint_map_.end());

64 }

65

66

67

69 return (absl::GetCurrentTimeNanos() - start_time_ns_) / 1000;

70 }

71

73 Constraint* const constraint) override {

75 return;

76 }

77

78 CHECK(active_constraint_ == nullptr);

79 CHECK(active_demon_ == nullptr);

80 CHECK(constraint != nullptr);

84 active_constraint_ = constraint;

85 constraint_map_[constraint] = ct_run;

86 }

87

89 CHECK(active_constraint_ != nullptr);

90 CHECK(active_demon_ == nullptr);

91 CHECK(constraint != nullptr);

92 CHECK_EQ(constraint, active_constraint_);

93 ConstraintRuns* const ct_run = constraint_map_[constraint];

94 if (ct_run != nullptr) {

97 }

98 active_constraint_ = nullptr;

99 }

100

104 return;

105 }

106

107 CHECK(active_constraint_ == nullptr);

108 CHECK(active_demon_ == nullptr);

109 CHECK(constraint != nullptr);

110 CHECK(delayed != nullptr);

111 ConstraintRuns* const ct_run = constraint_map_[constraint];

113 active_constraint_ = constraint;

114 }

115

118 CHECK(active_constraint_ != nullptr);

119 CHECK(active_demon_ == nullptr);

120 CHECK(constraint != nullptr);

121 CHECK(delayed != nullptr);

122 CHECK_EQ(constraint, active_constraint_);

123 ConstraintRuns* const ct_run = constraint_map_[constraint];

124 if (ct_run != nullptr) {

127 }

128 active_constraint_ = nullptr;

129 }

130

133 return;

134 }

135

136 if (demon_map_.find(demon) == demon_map_.end()) {

137 CHECK(active_constraint_ != nullptr);

138 CHECK(active_demon_ == nullptr);

139 CHECK(demon != nullptr);

140 ConstraintRuns* const ct_run = constraint_map_[active_constraint_];

144 demon_map_[demon] = demon_run;

145 demons_per_constraint_[active_constraint_].push_back(demon_run);

146 }

147 }

148

150 CHECK(demon != nullptr);

152 return;

153 }

154 CHECK(active_demon_ == nullptr);

155 active_demon_ = demon;

156 DemonRuns* const demon_run = demon_map_[active_demon_];

157 if (demon_run != nullptr) {

159 }

160 }

161

163 CHECK(demon != nullptr);

165 return;

166 }

167 CHECK_EQ(active_demon_, demon);

168 DemonRuns* const demon_run = demon_map_[active_demon_];

169 if (demon_run != nullptr) {

171 }

172 active_demon_ = nullptr;

173 }

174

177 void PushContext(const std::string& context) override {}

179

181 if (active_demon_ != nullptr) {

182 DemonRuns* const demon_run = demon_map_[active_demon_];

183 if (demon_run != nullptr) {

186 }

187 active_demon_ = nullptr;

188

189 active_constraint_ = nullptr;

190 } else if (active_constraint_ != nullptr) {

191 ConstraintRuns* const ct_run = constraint_map_[active_constraint_];

192 if (ct_run != nullptr) {

195 }

196 active_constraint_ = nullptr;

197 }

198 }

199

200

203 constraint_map_.end());

204 constraint_map_.clear();

205 demon_map_.clear();

206 demons_per_constraint_.clear();

207 }

208

209

210 void SetMin(IntExpr* const expr, int64_t new_min) override {}

211 void SetMax(IntExpr* const expr, int64_t new_max) override {}

213 int64_t new_max) override {}

214

215 void SetMin(IntVar* const var, int64_t new_min) override {}

216 void SetMax(IntVar* const var, int64_t new_max) override {}

217 void SetRange(IntVar* const var, int64_t new_min, int64_t new_max) override {}

222 const std::vector<int64_t>& values) override {}

224 const std::vector<int64_t>& values) override {}

225

229 int64_t new_max) override {}

233 int64_t new_max) override {}

237 int64_t new_max) override {}

244 const std::vector<int>& rank_last,

245 const std::vector<int>& unperformed) override {}

246

247

248 void AddFakeRun(Demon* const demon, int64_t start_time, int64_t end_time,

249 bool is_fail) {

250 CHECK(demon != nullptr);

251 DemonRuns* const demon_run = demon_map_[demon];

252 CHECK(demon_run != nullptr);

255 if (is_fail) {

257 }

258 }

259

260

262 const char* const kConstraintFormat =

263 " - Constraint: %s\n failures=%d, initial propagation "

264 "runtime=%d us, demons=%d, demon invocations=%d, total demon "

265 "runtime=%d us\n";

266 const char* const kDemonFormat =

267 " --- Demon: %s\n invocations=%d, failures=%d, total "

268 "runtime=%d us, [average=%.2lf, median=%.2lf, stddev=%.2lf]\n";

270 const std::string model =

271 absl::StrFormat("Model %s:\n", solver->model_name());

274 std::vector<Container> to_sort;

275 for (absl::flat_hash_map<const Constraint*,

277 constraint_map_.begin();

278 it != constraint_map_.end(); ++it) {

279 const Constraint* const ct = it->first;

280 int64_t fails = 0;

281 int64_t demon_invocations = 0;

282 int64_t initial_propagation_runtime = 0;

283 int64_t total_demon_runtime = 0;

284 int demon_count = 0;

286 &demon_invocations, &total_demon_runtime,

287 &demon_count);

288 to_sort.push_back(

289 Container(ct, total_demon_runtime + initial_propagation_runtime));

290 }

291 std::sort(to_sort.begin(), to_sort.end());

292

293 for (int i = 0; i < to_sort.size(); ++i) {

294 const Constraint* const ct = to_sort[i].ct;

295 int64_t fails = 0;

296 int64_t demon_invocations = 0;

297 int64_t initial_propagation_runtime = 0;

298 int64_t total_demon_runtime = 0;

299 int demon_count = 0;

301 &demon_invocations, &total_demon_runtime,

302 &demon_count);

303 const std::string constraint_message =

304 absl::StrFormat(kConstraintFormat, ct->DebugString(), fails,

305 initial_propagation_runtime, demon_count,

306 demon_invocations, total_demon_runtime);

308 .IgnoreError();

309 const std::vector<DemonRuns*>& demons = demons_per_constraint_[ct];

310 const int demon_size = demons.size();

311 for (int demon_index = 0; demon_index < demon_size; ++demon_index) {

312 DemonRuns* const demon_runs = demons[demon_index];

313 int64_t invocations = 0;

314 int64_t fails = 0;

315 int64_t runtime = 0;

316 double mean_runtime = 0;

317 double median_runtime = 0;

318 double standard_deviation = 0.0;

320 &mean_runtime, &median_runtime,

321 &standard_deviation);

322 const std::string runs = absl::StrFormat(

323 kDemonFormat, demon_runs->demon_id(), invocations, fails, runtime,

324 mean_runtime, median_runtime, standard_deviation);

326 }

327 }

328 }

330 }

331

332

334 int64_t* const fails,

335 int64_t* const initial_propagation_runtime,

336 int64_t* const demon_invocations,

337 int64_t* const total_demon_runtime, int* demons) {

338 CHECK(constraint != nullptr);

339 ConstraintRuns* const ct_run = constraint_map_[constraint];

340 CHECK(ct_run != nullptr);

341 *demon_invocations = 0;

343 *initial_propagation_runtime = 0;

347 }

348 *total_demon_runtime = 0;

349

350

352 CHECK_EQ(*demons, demons_per_constraint_[constraint].size());

353 for (int demon_index = 0; demon_index < *demons; ++demon_index) {

354 const DemonRuns& demon_runs = ct_run->demons(demon_index);

355 *fails += demon_runs.failures();

358 *demon_invocations += runs;

359 for (int run_index = 0; run_index < runs; ++run_index) {

360 const int64_t demon_time =

362 *total_demon_runtime += demon_time;

363 }

364 }

365 }

366

368 int64_t* const demon_invocations, int64_t* const fails,

369 int64_t* const total_demon_runtime,

370 double* const mean_demon_runtime,

371 double* const median_demon_runtime,

372 double* const stddev_demon_runtime) {

373 CHECK(demon_runs != nullptr);

375

377 *demon_invocations = runs;

378 *fails = demon_runs->failures();

379 *total_demon_runtime = 0;

380 *mean_demon_runtime = 0.0;

381 *median_demon_runtime = 0.0;

382 *stddev_demon_runtime = 0.0;

383 std::vector<double> runtimes;

384 for (int run_index = 0; run_index < runs; ++run_index) {

385 const int64_t demon_time =

387 *total_demon_runtime += demon_time;

388 runtimes.push_back(demon_time);

389 }

390

391 if (!runtimes.empty()) {

392 *mean_demon_runtime = (1.0L * *total_demon_runtime) / runtimes.size();

393

394

395 std::sort(runtimes.begin(), runtimes.end());

396 const int pivot = runtimes.size() / 2;

397

398 if (runtimes.size() == 1) {

399 *median_demon_runtime = runtimes[0];

400 } else {

401 *median_demon_runtime =

402 runtimes.size() % 2 == 1

403 ? runtimes[pivot]

404 : (runtimes[pivot - 1] + runtimes[pivot]) / 2.0;

405 }

406

407

408 double total_deviation = 0.0f;

409

410 for (int i = 0; i < runtimes.size(); ++i) {

411 total_deviation += pow(runtimes[i] - *mean_demon_runtime, 2);

412 }

413

414 *stddev_demon_runtime = sqrt(total_deviation / runtimes.size());

415 }

416 }

417

418

419

420

422

423 std::string DebugString() const override { return "DemonProfiler"; }

424

425 private:

427 Demon* active_demon_;

428 const int64_t start_time_ns_;

429 absl::flat_hash_map<const Constraint*, ConstraintRuns*> constraint_map_;

430 absl::flat_hash_map<const Demon*, DemonRuns*> demon_map_;

431 absl::flat_hash_map<const Constraint*, std::vector<DemonRuns*> >

432 demons_per_constraint_;

433};

434

436 if (demon_profiler_ != nullptr) {

437 demon_profiler_->PrintOverview(this, filename);

438 }

439}

440

441

442

444

448 } else {

449 return nullptr;

450 }

451}

452

454

456 CHECK(demon != nullptr);

458 propagation_monitor_->RegisterDemon(demon);

459 }

460 return demon;

461}

462

463

464

469

471 int64_t start_time, int64_t end_time,

472 bool is_fail) {

473 monitor->AddFakeRun(demon, start_time, end_time, is_fail);

474}

475

478 int64_t* const fails,

479 int64_t* const initial_propagation_runtime,

480 int64_t* const demon_invocations,

481 int64_t* const total_demon_runtime,

482 int* const demon_count) {

483 monitor->ExportInformation(constraint, fails, initial_propagation_runtime,

484 demon_invocations, total_demon_runtime,

485 demon_count);

486}

487

492

497

498}

::int64_t initial_propagation_end_time(int index) const

::operations_research::DemonRuns *PROTOBUF_NONNULL add_demons()

void set_failures(::int64_t value)

::int64_t failures() const

const ::operations_research::DemonRuns & demons(int index) const

void add_initial_propagation_end_time(::int64_t value)

void set_constraint_id(Arg_ &&arg, Args_... args)

int initial_propagation_start_time_size() const

void add_initial_propagation_start_time(::int64_t value)

::int64_t initial_propagation_start_time(int index) const

std::string DebugString() const override

void RemoveValues(IntVar *const var, const std::vector< int64_t > &values) override

Definition demon_profiler.cc:223

void PrintOverview(Solver *const solver, absl::string_view filename)

Definition demon_profiler.cc:261

void SetEndRange(IntervalVar *const var, int64_t new_min, int64_t new_max) override

Definition demon_profiler.cc:232

void SetMax(IntVar *const var, int64_t new_max) override

Definition demon_profiler.cc:216

void Install() override

Definition demon_profiler.cc:421

void AddFakeRun(Demon *const demon, int64_t start_time, int64_t end_time, bool is_fail)

Definition demon_profiler.cc:248

void EndProcessingIntegerVariable(IntVar *const var) override

Definition demon_profiler.cc:176

void RankNotLast(SequenceVar *const var, int index) override

Definition demon_profiler.cc:242

void PopContext() override

Definition demon_profiler.cc:178

DemonProfiler(Solver *const solver)

Definition demon_profiler.cc:55

void SetStartRange(IntervalVar *const var, int64_t new_min, int64_t new_max) override

Definition demon_profiler.cc:228

void RankSequence(SequenceVar *const var, const std::vector< int > &rank_first, const std::vector< int > &rank_last, const std::vector< int > &unperformed) override

Definition demon_profiler.cc:243

void SetEndMax(IntervalVar *const var, int64_t new_max) override

Definition demon_profiler.cc:231

void SetPerformed(IntervalVar *const var, bool value) override

Definition demon_profiler.cc:238

void ExportInformation(const DemonRuns *const demon_runs, int64_t *const demon_invocations, int64_t *const fails, int64_t *const total_demon_runtime, double *const mean_demon_runtime, double *const median_demon_runtime, double *const stddev_demon_runtime)

Definition demon_profiler.cc:367

~DemonProfiler() override

Definition demon_profiler.cc:61

void SetDurationMin(IntervalVar *const var, int64_t new_min) override

Definition demon_profiler.cc:234

void EndConstraintInitialPropagation(Constraint *const constraint) override

Definition demon_profiler.cc:88

int64_t CurrentTime() const

Definition demon_profiler.cc:68

void ExportInformation(const Constraint *const constraint, int64_t *const fails, int64_t *const initial_propagation_runtime, int64_t *const demon_invocations, int64_t *const total_demon_runtime, int *demons)

Definition demon_profiler.cc:333

void SetValue(IntVar *const var, int64_t value) override

Definition demon_profiler.cc:219

void SetMin(IntVar *const var, int64_t new_min) override

IntVar modifiers.

Definition demon_profiler.cc:215

void RankNotFirst(SequenceVar *const var, int index) override

Definition demon_profiler.cc:240

void SetEndMin(IntervalVar *const var, int64_t new_min) override

Definition demon_profiler.cc:230

void SetDurationRange(IntervalVar *const var, int64_t new_min, int64_t new_max) override

Definition demon_profiler.cc:236

void BeginNestedConstraintInitialPropagation(Constraint *const constraint, Constraint *const delayed) override

Definition demon_profiler.cc:101

void SetMax(IntExpr *const expr, int64_t new_max) override

Definition demon_profiler.cc:211

void SetStartMax(IntervalVar *const var, int64_t new_max) override

Definition demon_profiler.cc:227

void BeginFail() override

Just when the failure occurs.

Definition demon_profiler.cc:180

void BeginConstraintInitialPropagation(Constraint *const constraint) override

Propagation events.

Definition demon_profiler.cc:72

void RankLast(SequenceVar *const var, int index) override

Definition demon_profiler.cc:241

void EndDemonRun(Demon *const demon) override

Definition demon_profiler.cc:162

void SetRange(IntVar *const var, int64_t new_min, int64_t new_max) override

Definition demon_profiler.cc:217

void BeginDemonRun(Demon *const demon) override

Definition demon_profiler.cc:149

void StartProcessingIntegerVariable(IntVar *const var) override

Definition demon_profiler.cc:175

void SetDurationMax(IntervalVar *const var, int64_t new_max) override

Definition demon_profiler.cc:235

void SetMin(IntExpr *const expr, int64_t new_min) override

IntExpr modifiers.

Definition demon_profiler.cc:210

std::string DebugString() const override

Definition demon_profiler.cc:423

void RankFirst(SequenceVar *const var, int index) override

SequenceVar modifiers.

Definition demon_profiler.cc:239

void RegisterDemon(Demon *const demon) override

Definition demon_profiler.cc:131

void SetStartMin(IntervalVar *const var, int64_t new_min) override

IntervalVar modifiers.

Definition demon_profiler.cc:226

void SetRange(IntExpr *const expr, int64_t new_min, int64_t new_max) override

Definition demon_profiler.cc:212

void RestartSearch() override

Restart the search.

Definition demon_profiler.cc:201

void SetValues(IntVar *const var, const std::vector< int64_t > &values) override

Definition demon_profiler.cc:221

void RemoveInterval(IntVar *const var, int64_t imin, int64_t imax) override

Definition demon_profiler.cc:220

void RemoveValue(IntVar *const var, int64_t value) override

Definition demon_profiler.cc:218

void PushContext(const std::string &context) override

Definition demon_profiler.cc:177

void EndNestedConstraintInitialPropagation(Constraint *const constraint, Constraint *const delayed) override

Definition demon_profiler.cc:116

void add_start_time(::int64_t value)

int start_time_size() const

void set_failures(::int64_t value)

void set_demon_id(Arg_ &&arg, Args_... args)

::int64_t end_time(int index) const

int end_time_size() const

::int64_t failures() const

::int64_t start_time(int index) const

void add_end_time(::int64_t value)

const ::std::string & demon_id() const

virtual Solver::DemonPriority priority() const

std::string DebugString() const override

PropagationMonitor(Solver *solver)

Demon * RegisterDemon(Demon *demon)

Adds a new demon and wraps it inside a DemonProfiler if necessary.

Definition demon_profiler.cc:455

void ExportProfilingOverview(const std::string &filename)

Definition demon_profiler.cc:435

@ VAR_PRIORITY

VAR_PRIORITY is between DELAYED_PRIORITY and NORMAL_PRIORITY.

@ IN_SEARCH

Executing the search code.

bool IsProfilingEnabled() const

Returns whether we are profiling the solver.

bool InstrumentsDemons() const

Returns whether we are instrumenting demons.

absl::Status WriteString(File *file, absl::string_view contents, Options options)

absl::Status Open(absl::string_view file_name, absl::string_view mode, File **f, Options options)

void STLDeleteContainerPairSecondPointers(ForwardIterator begin, ForwardIterator end)

void DeleteDemonProfiler(DemonProfiler *monitor)

Definition demon_profiler.cc:453

void DemonProfilerEndInitialPropagation(DemonProfiler *const monitor, Constraint *const constraint)

Definition demon_profiler.cc:493

DemonProfiler * BuildDemonProfiler(Solver *solver)

Definition demon_profiler.cc:445

void DemonProfilerExportInformation(DemonProfiler *const monitor, const Constraint *const constraint, int64_t *const fails, int64_t *const initial_propagation_runtime, int64_t *const demon_invocations, int64_t *const total_demon_runtime, int *const demon_count)

Definition demon_profiler.cc:476

void RegisterDemon(Solver *const solver, Demon *const demon, DemonProfiler *const monitor)

Definition demon_profiler.cc:465

void DemonProfilerBeginInitialPropagation(DemonProfiler *const monitor, Constraint *const constraint)

Definition demon_profiler.cc:488

void DemonProfilerAddFakeRun(DemonProfiler *const monitor, Demon *const demon, int64_t start_time, int64_t end_time, bool is_fail)

Definition demon_profiler.cc:470

void InstallDemonProfiler(DemonProfiler *monitor)

Definition demon_profiler.cc:443