core 22.6 KB
Newer Older
Gauthier Quesnel's avatar
2019    
Gauthier Quesnel committed
1
/* Copyright (C) 2016-2019 INRA
Gauthier Quesnel's avatar
Gauthier Quesnel committed
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

Gauthier Quesnel's avatar
Gauthier Quesnel committed
23
24
#ifndef ORG_VLEPROJECT_BARYONYX_SOLVER_CORE
#define ORG_VLEPROJECT_BARYONYX_SOLVER_CORE
Gauthier Quesnel's avatar
Gauthier Quesnel committed
25

26
27
#include <array>
#include <forward_list>
28
#include <functional>
Gauthier Quesnel's avatar
Gauthier Quesnel committed
29
#include <limits>
30
#include <memory>
31
#include <numeric>
Gauthier Quesnel's avatar
Gauthier Quesnel committed
32
33
#include <stdexcept>
#include <string>
34
#include <string_view>
Gauthier Quesnel's avatar
Gauthier Quesnel committed
35
36
#include <vector>

37
38
#include <cstdint>

Gauthier Quesnel's avatar
Gauthier Quesnel committed
39
#include <baryonyx/export>
Gauthier Quesnel's avatar
Gauthier Quesnel committed
40

Gauthier Quesnel's avatar
Gauthier Quesnel committed
41
namespace baryonyx {
Gauthier Quesnel's avatar
Gauthier Quesnel committed
42

Gauthier Quesnel's avatar
Gauthier Quesnel committed
43
/** @c index is used as accessors for all array. */
44
using index = std::int32_t;
45
46
47

/** @c value is used as value for variable. */
using var_value = std::int_least8_t;
Gauthier Quesnel's avatar
Gauthier Quesnel committed
48

49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
struct string_buffer
{
    constexpr static std::size_t string_buffer_node_length = 1024 * 1024;

    using value_type = std::array<char, string_buffer_node_length>;
    using container_type = std::forward_list<value_type>;

    string_buffer() noexcept = default;
    ~string_buffer() noexcept = default;

    string_buffer(const string_buffer&) = delete;
    string_buffer(string_buffer&&) = delete;
    string_buffer& operator=(const string_buffer&) = delete;
    string_buffer& operator=(string_buffer&&) = delete;

    std::string_view append(std::string_view str)
    {
        if (m_container.empty() ||
            str.size() + m_position > string_buffer_node_length)
            do_alloc();

        std::size_t position = m_position;
        m_position += str.size();

        char* buffer = m_container.front().data() + position;

        std::copy_n(str.data(), str.size(), buffer);

        return std::string_view(buffer, str.size());
    }

80
81
82
83
84
85
86
87
88
    std::size_t size() const noexcept
    {
        return std::accumulate(
          m_container.cbegin(),
          m_container.cend(),
          0,
          [](int cumul, const auto& /*elem*/) { return cumul + 1; });
    }

89
90
91
92
93
94
95
96
97
98
99
100
101
private:
    void do_alloc()
    {
        m_container.emplace_front();
        m_position = 0;
    }

    container_type m_container;
    std::size_t m_position = { 0 };
};

using string_buffer_ptr = std::shared_ptr<string_buffer>;

102
struct precondition_failure : std::logic_error
103
{
104
    precondition_failure(const char* msg)
105
      : std::logic_error(msg)
106
    {}
Gauthier Quesnel's avatar
Gauthier Quesnel committed
107
108
};

109
struct postcondition_failure : std::logic_error
110
{
111
    postcondition_failure(const char* msg)
112
      : std::logic_error(msg)
113
    {}
Gauthier Quesnel's avatar
Gauthier Quesnel committed
114
115
};

116
struct numeric_cast_failure : std::logic_error
117
{
118
119
120
    numeric_cast_failure()
      : std::logic_error("numeric_cast_failure: loss of range")
    {}
Gauthier Quesnel's avatar
Gauthier Quesnel committed
121
122
};

123
struct file_access_error
124
{
125
126
127
128
129
130
131
132
133
    std::string file;
    int error;
};

struct file_access_failure : std::runtime_error
{
    file_access_failure(std::string file, int error)
      : std::runtime_error("file_access_failure")
      , m_error{ std::move(file), error }
134
    {}
Gauthier Quesnel's avatar
Gauthier Quesnel committed
135

136
137
    std::string file() const
    {
138
        return m_error.file;
139
    }
140

141
142
    int error() const
    {
143
        return m_error.error;
144
145
    }

Gauthier Quesnel's avatar
Gauthier Quesnel committed
146
private:
147
    file_access_error m_error;
Gauthier Quesnel's avatar
Gauthier Quesnel committed
148
149
};

150
enum class file_format_error_tag
151
{
152
153
    success,
    file_not_found,
154
155
156
    bad_end_of_file,
    bad_general,
    bad_binary,
157
    bad_objective_function_type,
158
    bad_objective,
Gauthier Quesnel's avatar
Gauthier Quesnel committed
159
    bad_objective_quadratic,
160
    bad_bound,
161
    bad_end,
162
163
    bad_constraint,
    too_many_variables,
164
    too_many_constraints,
165
166
    bad_name, // Mainly use when read result file and report unknown variable.
    empty_context
167
};
Gauthier Quesnel's avatar
Gauthier Quesnel committed
168

169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
struct file_format_error
{
    std::string element;
    int line;
    int column;
    file_format_error_tag tag;
};

struct file_format_failure : std::runtime_error
{
    file_format_failure(std::string element,
                        file_format_error_tag failure,
                        int line,
                        int column)
      : std::runtime_error("file_format_failure")
      , m_error{ std::move(element), line, column, failure }
185
    {}
Gauthier Quesnel's avatar
Gauthier Quesnel committed
186

187
188
189
    file_format_failure(file_format_error_tag failure, int line, int column)
      : std::runtime_error("file_format_failure")
      , m_error{ std::string(), line, column, failure }
190
    {}
Gauthier Quesnel's avatar
Gauthier Quesnel committed
191

192
193
194
    file_format_failure(file_format_error_tag failure)
      : std::runtime_error("file_format_failure")
      , m_error{ std::string(), -1, -1, failure }
195
    {}
196

197
198
    std::string element() const
    {
199
        return m_error.element;
200
    }
201

202
203
    int line() const
    {
204
        return m_error.line;
205
    }
206

207
208
    int column() const
    {
209
        return m_error.column;
210
    }
211

212
    file_format_error_tag failure() const
213
    {
214
        return m_error.tag;
215
    }
216

Gauthier Quesnel's avatar
Gauthier Quesnel committed
217
private:
218
    file_format_error m_error;
Gauthier Quesnel's avatar
Gauthier Quesnel committed
219
220
};

221
enum class problem_definition_error_tag
222
{
223
    empty_variables = 1,
224
225
226
227
228
229
230
231
232
233
234
    empty_objective_function,
    variable_not_used,
    bad_bound,
    multiple_constraint,
};

struct problem_definition_error
{
    std::string element;
    problem_definition_error_tag tag;
};
Gauthier Quesnel's avatar
Gauthier Quesnel committed
235

236
237
238
239
240
struct problem_definition_failure : std::runtime_error
{
    problem_definition_failure(std::string element,
                               problem_definition_error_tag failure)
      : std::runtime_error("problem_definition_failure")
241
      , m_error{ std::move(element), failure }
242
    {}
Gauthier Quesnel's avatar
Gauthier Quesnel committed
243

244
245
    std::string element() const
    {
246
        return m_error.element;
247
    }
248

249
    problem_definition_error_tag failure() const
250
    {
251
        return m_error.tag;
252
    }
253

Gauthier Quesnel's avatar
Gauthier Quesnel committed
254
private:
255
    problem_definition_error m_error;
Gauthier Quesnel's avatar
Gauthier Quesnel committed
256
257
};

258
enum class solver_error_tag
259
{
260
    no_solver_available = 1,
261
262
263
264
265
266
267
268
    unrealisable_constraint,
    not_enough_memory
};

struct solver_error
{
    solver_error_tag tag;
};
Gauthier Quesnel's avatar
Gauthier Quesnel committed
269

270
271
272
273
274
struct solver_failure : std::runtime_error
{
    solver_failure(solver_error_tag failure)
      : std::runtime_error("solver_failure")
      , m_error{ failure }
275
    {}
Gauthier Quesnel's avatar
Gauthier Quesnel committed
276

277
    solver_error_tag failure() const
278
    {
279
        return m_error.tag;
280
    }
Gauthier Quesnel's avatar
Gauthier Quesnel committed
281
282

private:
283
    solver_error m_error;
Gauthier Quesnel's avatar
Gauthier Quesnel committed
284
285
};

286
/**
287
288
289
290
291
 * @brief Stores the solver parameters options.
 *
 * @details @c baryonyx::solver_parameters manage behaviour of baryonyx
 *     solvers. If bad value are provided, for instance negative value for the
 *     @c delta or @c kappa-step variables, the default is used.
292
293
 *
 */
Gauthier Quesnel's avatar
Gauthier Quesnel committed
294
struct BX_EXPORT solver_parameters
295
{
296
    enum class pre_constraint_order
297
    {
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
        none = 0, ///< Use the raw_problem (or lp file) order for constraints
                  ///< and variables.
        memory,   ///< Default, use the raw_problem (or lp file) order for
                  ///< constraints but sort the variables to improve the memory
                  ///< cache efficiency.
        less_greater_equal, ///< sort constraints according to their type
                            ///< (first less and finally greater then equal)
                            ///< and sort variable to improve the memory cache
                            ///< efficiency.
        less_equal_greater, ///< sort constraints according to their type
                            ///< (first less and finally equal then greater)
                            ///< and sort variable to improve the memory cache
                            ///< efficiency.
        greater_less_equal, ///< sort constraints according to their type
                            ///< (first greater then less and finally equal)
                            ///< and sort variable to improve the memory cache
                            ///< efficiency.
        greater_equal_less, ///< sort constraints according to their type
                            ///< (first greater then equal and finally less)
                            ///< and sort variable to improve the memory cache
                            ///< efficiency.
        equal_less_greater, ///< sort constraints according to their type
                            ///< (first equal then less and finally greater)
                            ///< and sort variable to improve the memory cache
                            ///< efficiency.
        equal_greater_less, ///< sort constraints according to their type
                            ///< (first equal then greater and finally less)
                            ///< and sort variable to improve the memory cache
                            ///< efficiency.
        p1,                 ///< reserved
        p2,                 ///< reserved
        p3,                 ///< reserved
        p4,                 ///< reserved

332
    };
Gauthier Quesnel's avatar
Gauthier Quesnel committed
333

334
    enum class init_policy_type
335
    {
336
337
338
        bastert,
        pessimistic_solve,
        optimistic_solve,
339
340
    };

341
    enum class floating_point_type
Gauthier Quesnel's avatar
Gauthier Quesnel committed
342
    {
343
344
345
346
        float_type = 0,
        double_type,
        longdouble_type
    };
Gauthier Quesnel's avatar
params    
Gauthier Quesnel committed
347

348
    enum class constraint_order
Gauthier Quesnel's avatar
params    
Gauthier Quesnel committed
349
    {
350
351
352
353
354
        none = 0,
        reversing,
        random_sorting,
        infeasibility_decr,
        infeasibility_incr,
355
356
        lagrangian_decr,
        lagrangian_incr,
357
358
        pi_sign_change,
        cycle
359
    };
Gauthier Quesnel's avatar
params    
Gauthier Quesnel committed
360

361
    enum class cost_norm_type
Gauthier Quesnel's avatar
params    
Gauthier Quesnel committed
362
    {
363
364
365
366
367
368
        none = 0,
        random,
        l1,
        l2,
        loo
    };
Gauthier Quesnel's avatar
Gauthier Quesnel committed
369

370
371
372
373
374
375
376
377
378
379
380
381
    enum class mode_type : unsigned
    {
        none = 0,
        manual = 1,
        nlopt = 2,
        branch = 4
    };

    /**
     * Preprocessor options available for @c solve or @c optimize function.
     */
    enum class preprocessor_options
382
    {
383
384
        none = 0,
        all
385
    };
386

387
    enum class observer_type
Gauthier Quesnel's avatar
Gauthier Quesnel committed
388
    {
389
390
391
392
        none,
        pnm,
        file
    };
Gauthier Quesnel's avatar
Gauthier Quesnel committed
393

394
395
396
397
398
399
    enum class solver_type
    {
        bastert,
        random
    };

400
401
402
403
404
405
406
407
408
409
    /**
     * @brief Solution storage policy for the optimizer mode.
     */
    enum class storage_type
    {
        one,   ///< stores only the best solution found.
        bound, ///< stores the best and the bad solution found.
        five   ///< stores the best five solution found.
    };

410
411
412
413
414
415
416
417
418
    double time_limit{ -1 }; ///< value <= 0 means infinity time.
    double theta{ 0.5 };
    double delta{ -1 }; ///< value == -1 means automatic.
    double kappa_min{ 0 };
    double kappa_step{ 1.e-3 };
    double kappa_max{ 0.6 };
    double alpha{ 1 };
    double pushing_k_factor{ 0.9 };
    double pushing_objective_amplifier{ 5 };
419
    double init_policy_random{ 0.5 };
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438

    // Probability to insert a bastert solution during the crossover
    // operation.
    double init_crossover_bastert_insertion{ 0.01 };

    double init_crossover_solution_selection_mean{ 0.0 };
    double init_crossover_solution_selection_stddev{ 0.3 };

    // Probability to mutate the solution after the crossover operation.
    // @c init_mutation_variable defines the number of variables to
    // changes, @c init_mutation_value defines the value of the variables.
    // If @c init_mutation_variable_mean and init_mutation_variable_stddev
    // equal zeros, no mutation are done after the crossover.

    double init_mutation_variable_mean{ 0.0001 };
    double init_mutation_variable_stddev{ 0.001 };
    double init_mutation_value_mean{ 0.5 };
    double init_mutation_value_stddev{ 0.2 };

439
440
441
442
    double init_kappa_improve_start{ 0 };
    double init_kappa_improve_increase{ 0.02 };
    double init_kappa_improve_stop{ 0.2 };

443
    double w{ 0.05 };       ///< 5% of limit
444
445
    unsigned int seed{ 0 }; ///< value == 0 means automatic seed.
    int thread{ 0 };        ///< value <= 0 means automatic detection.
446
    long int limit{ 1000 }; ///< value <= 0 means infinity loop.
447
448
449
    int print_level{ 0 };
    int pushes_limit{ 100 };
    int pushing_iteration_limit{ 50 };
450
    int init_population_size{ 100 };
451
452
453
454
455
    pre_constraint_order pre_order{ pre_constraint_order::none };
    constraint_order order{ constraint_order::none };
    floating_point_type float_type{ floating_point_type::double_type };
    init_policy_type init_policy{ init_policy_type::bastert };
    cost_norm_type cost_norm{ cost_norm_type::loo };
456
457
    mode_type mode{ mode_type::none };
    preprocessor_options preprocessor{ preprocessor_options::all };
458
    observer_type observer{ observer_type::none };
459
    storage_type storage{ storage_type::one };
460
    solver_type solver{ solver_type::bastert };
461
    bool debug{ false };
Gauthier Quesnel's avatar
Gauthier Quesnel committed
462
463
};

464
/**
465
 * @brief Stores logging system and parameters.
Gauthier Quesnel's avatar
Gauthier Quesnel committed
466
 *
467
 * @details @c baryonyx::context manages the logging system and stores a set of
468
 *     parameters for solvers. Default, the logging system is active and use
469
470
471
472
473
 *     @c stdout C file structure as output stream. To disable logging system,
 *         use the CMake WITH_LOG=OFF or undefined the @c BARYONYX_ENABLE_LOG
 *         preprocessor value to hide all messages. To disable debug message
 *         only, use the CMake WITH_DEBUG=OFF or undefined the @c
 *         BARYONYX_ENABLE_DEBUG preprocessor value.
474
475
476
 *
 *     The implementation of this class is hidden into private include to
 *     ensure a stable ABI of the Baryonyx library.
477
 */
478
struct context;
479

480
481
482
483
484
485
486
487
488
489
/**
 * @brief Stores the @c context into smart pointer.
 *
 * @details This type is use in many place of the Baryonyx library and
 *     application to simplify source code. We use a no copyable smart pointer
 *     to ensure thread safe library. Each thread must use its own @c context.
 *     Use the @c copy_context function to simplify the copy. We provide a free
 *     function to delete context pointer to avoid context publication.
 */
using context_ptr = std::unique_ptr<context, void (*)(context*)>;
490

Gauthier Quesnel's avatar
Gauthier Quesnel committed
491
BX_EXPORT context_ptr
492
make_context(int verbose_level = 6);
493

494
495
496
497
498
499
500
501
/**
 * @brief Assign baryonyx internal parameters.
 *
 * @details This function is used to provide internal parameters to Baryonyx
 *     library and to ensures a stable API and ABI (for example extends the
 *     solver without change in @c solver_parameters). Normally, this function
 *     is not used.
 *
502
 * @param ctx Baryonyx's internal state.
503
504
505
 * @param name The name of the parameters.
 * @param value A string representation of the parameters.
 */
Gauthier Quesnel's avatar
Gauthier Quesnel committed
506
BX_EXPORT void
507
context_set_parameters(const context_ptr& ctx,
508
                       const std::string& name,
509
                       std::string value);
510

511
512
513
514
515
516
/**
 * @brief Affects parameters to the solver.
 *
 * @details For each variables of @c params, value is check and assign to the
 *     solver's internal variables.
 *
517
 * @param ctx Baryonyx's internal state.
518
519
 * @param params Parameters to be copied.
 */
Gauthier Quesnel's avatar
Gauthier Quesnel committed
520
BX_EXPORT void
521
522
523
524
525
526
context_set_solver_parameters(const context_ptr& ctx,
                              const solver_parameters& params);

/**
 * @brief Get solver's internal state.
 *
527
 * @param ctx Baryonyx's internal state.
528
529
530
 *
 * @return A copy of the internal state.
 */
Gauthier Quesnel's avatar
Gauthier Quesnel committed
531
BX_EXPORT
532
533
solver_parameters
context_get_solver_parameters(const context_ptr& ctx);
534

535
536
537
538
539
540
enum class variable_type
{
    real,
    binary,
    general
};
Gauthier Quesnel's avatar
Gauthier Quesnel committed
541

542
543
544
545
546
547
548
549
550
551
enum class problem_solver_type
{
    equalities_01,
    equalities_101,
    equalities_Z,
    inequalities_01,
    inequalities_101,
    inequalities_Z
};

552
553
554
555
556
enum class objective_function_type
{
    maximize,
    minimize
};
Gauthier Quesnel's avatar
Gauthier Quesnel committed
557

558
559
enum class operator_type
{
560
561
562
563
    equal,
    greater,
    less,
};
Gauthier Quesnel's avatar
Gauthier Quesnel committed
564

565
566
struct variable_value
{
567
    variable_value() = default;
568
569
570
571
572

    variable_value(int min_, int max_, variable_type type_)
      : min(min_)
      , max(max_)
      , type(type_)
573
    {}
574

575
    int min{ 0 };
576
    int max{ std::numeric_limits<int>::infinity() };
577
    variable_type type{ variable_type::real };
Gauthier Quesnel's avatar
Gauthier Quesnel committed
578
579
};

580
581
struct variables
{
582
    std::vector<std::string_view> names;
583
    std::vector<variable_value> values;
Gauthier Quesnel's avatar
Gauthier Quesnel committed
584
585
};

586
587
struct function_element
{
588
589
    function_element() = default;

Gauthier Quesnel's avatar
Gauthier Quesnel committed
590
    function_element(int factor_, index variable_index_) noexcept
591
592
      : factor(factor_)
      , variable_index(variable_index_)
593
    {}
Gauthier Quesnel's avatar
Gauthier Quesnel committed
594

595
596
    int factor = { 0 };
    index variable_index{ -1 };
Gauthier Quesnel's avatar
Gauthier Quesnel committed
597
598
};

599
600
601
602
603
struct objective_function_element
{
    objective_function_element(double factor_, index variable_index_) noexcept
      : factor(factor_)
      , variable_index(variable_index_)
604
    {}
605
606
607
608
609

    double factor = { 0 };
    index variable_index{ -1 };
};

Gauthier Quesnel's avatar
Gauthier Quesnel committed
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
struct objective_quadratic_element
{
    objective_quadratic_element() noexcept = default;

    constexpr objective_quadratic_element(double factor_,
                                          index variable_index_a_,
                                          index variable_index_b_) noexcept
      : factor(factor_)
      , variable_index_a(variable_index_a_)
      , variable_index_b(variable_index_b_)
    {}

    double factor = 0;
    index variable_index_a = -1;
    index variable_index_b = -1;
};

627
628
struct constraint
{
629
630
631
632
633
634
635
636
637
638
639
640
    constraint() = default;

    constraint(std::string_view label_,
               std::vector<function_element>&& elements_,
               int value_,
               int id_)
      : label(label_)
      , elements(elements_)
      , value(value_)
      , id(id_)
    {}

641
    std::string_view label;
642
    std::vector<function_element> elements;
643
    int value = { 0 };
644
    int id;
Gauthier Quesnel's avatar
Gauthier Quesnel committed
645
646
};

647
648
struct objective_function
{
649
    std::vector<objective_function_element> elements;
Gauthier Quesnel's avatar
Gauthier Quesnel committed
650
    std::vector<objective_quadratic_element> qelements;
651
    double value = { 0 };
652
653
654
655
};

struct affected_variables
{
656
    void push_back(std::string_view name, bool value)
657
658
659
660
661
    {
        names.emplace_back(name);
        values.emplace_back(value);
    }

662
    std::vector<std::string_view> names;
663
    std::vector<var_value> values;
Gauthier Quesnel's avatar
Gauthier Quesnel committed
664
};
Gauthier Quesnel's avatar
Gauthier Quesnel committed
665

666
667
struct raw_problem
{
668
669
670
671
672
    raw_problem() = default;
    raw_problem(file_format_error_tag status_)
      : status(status_)
    {}

673
674
    string_buffer_ptr strings;

675
676
677
678
679
680
    objective_function objective;

    std::vector<constraint> equal_constraints;
    std::vector<constraint> greater_constraints;
    std::vector<constraint> less_constraints;

681
682
683
684
685
    constexpr operator bool() const noexcept
    {
        return status == file_format_error_tag::success;
    }

686
687
688
    variables vars;

    objective_function_type type = { objective_function_type::maximize };
689
    file_format_error_tag status = { file_format_error_tag::success };
690
691
};

692
693
694
enum class result_status
{
    success,
695
696
    internal_error,
    uninitialized,
697
698
    time_limit_reached,
    kappa_max_reached,
699
700
    limit_reached,
    empty_context
701
702
};

703
704
705
706
struct solution
{
    solution() = default;

707
    solution(std::vector<var_value> variables_, double value_)
708
      : variables(std::move(variables_))
709
710
711
      , value(value_)
    {}

712
    std::vector<var_value> variables;
713
714
715
    double value;
};

716
717
struct result
{
718
719
    string_buffer_ptr strings;

720
    result() = default;
721

722
723
724
725
    result(result_status status_)
      : status(status_)
    {}

726
    std::string_view method;
727
    affected_variables affected_vars;
728

729
    std::vector<std::string_view> variable_name;
730
731
    std::vector<solution> solutions;

732
    double duration = 0.0;
733
    long int loop = 0;
734
735
736
    index variables = 0;
    index constraints = 0;
    index remaining_constraints = std::numeric_limits<index>::max();
737

738
739
740
    // The variable id with the heaviest load factor i.e. the variable which
    // changes too many times during the @c update_row in-the-middle process.
    int annoying_variable = 0;
741

742
    result_status status{ result_status::uninitialized };
743
744
745
746
747

    operator bool() const
    {
        return status == result_status::success;
    }
Gauthier Quesnel's avatar
Gauthier Quesnel committed
748
749
};

750
751
/// Function called after the preprocessor.
using solver_started_cb = std::function<void(const solver_parameters& params)>;
752

753
/// Function called for each solution improvement.
754
755
756
757
758
using solver_updated_cb = std::function<void(int remaining_constraints,
                                             double value,
                                             long int loop,
                                             double duration,
                                             long int reinit_number)>;
759

760
761
/// finish Function called at the end of the computation.
using solver_finished_cb = std::function<void(const result& r)>;
762

763
764
765
766
767
768
769
770
771
772
/**
 * @brief Register callback functions.
 * @details These functions are called during computation of the @c solver or
 *     @c optimize functions. They allow to retrieve data during computation.
 *
 * @param ctx Baryonyx's internal state.
 * @param start Function called after the preprocessor.
 * @param update Function called for each solution improvement.
 * @param finish Function called at the end of the computation.
 */
Gauthier Quesnel's avatar
Gauthier Quesnel committed
773
BX_EXPORT void
774
775
776
777
context_register(const context_ptr& ctx,
                 solver_started_cb start = solver_started_cb(),
                 solver_updated_cb update = solver_updated_cb(),
                 solver_finished_cb finish = solver_finished_cb());
778

Gauthier Quesnel's avatar
Gauthier Quesnel committed
779
/**
Gauthier Quesnel's avatar
Gauthier Quesnel committed
780
 * Read a @e lp file from the @e file.
Gauthier Quesnel's avatar
Gauthier Quesnel committed
781
 *
Gauthier Quesnel's avatar
Gauthier Quesnel committed
782
 * @exception baryonyx::file_format_error, baryonyx::file_access_error,
Gauthier Quesnel's avatar
Gauthier Quesnel committed
783
 *     std::system_error.
784
785
786
 *
 * @param ctx Baryonyx's internal state.
 * @param filename The file to read.
Gauthier Quesnel's avatar
Gauthier Quesnel committed
787
 */
Gauthier Quesnel's avatar
Gauthier Quesnel committed
788
BX_EXPORT
789
raw_problem
790
make_problem(const baryonyx::context_ptr& ctx, const std::string& filename);
Gauthier Quesnel's avatar
Gauthier Quesnel committed
791
792

/**
793
794
795
 * @brief Read a @c baryonyx::result from a file.
 * @details A @c baryonyx::result file store all meta data into comments and
 *     variable value.
Gauthier Quesnel's avatar
Gauthier Quesnel committed
796
 *
797
798
 * @param ctx Baryonyx's internal state.
 * @param filename The file to read.
Gauthier Quesnel's avatar
Gauthier Quesnel committed
799
 */
Gauthier Quesnel's avatar
Gauthier Quesnel committed
800
BX_EXPORT
801
result
802
make_result(const baryonyx::context_ptr& ctx, const std::string& filename);
803

804
805
806
807
/**
 * @details Try to solve or find a feasible solution for the @c
 *     baryonyx::problem.
 *
808
 * @param ctx Baryonyx's internal state.
809
810
811
812
813
 * @param pb Problem definition.
 *
 * @exception baryonyx::solver_error
 * @exception baryonyx::problem_definition
 */
Gauthier Quesnel's avatar
Gauthier Quesnel committed
814
BX_EXPORT
815
result
816
solve(const baryonyx::context_ptr& ctx, const raw_problem& pb);
817

818
819
820
821
/**
 * @details Try to optimize the @c baryonyx::problem with a set of
 *     parameters.
 *
822
 * @param ctx Baryonyx's internal state.
823
824
825
826
827
828
 * @param pb Problem definition.
 *
 * @return A representation of the result.
 *
 * @throw @c baryonyx::solver_error.
 */
Gauthier Quesnel's avatar
Gauthier Quesnel committed
829
BX_EXPORT
830
result
831
optimize(const baryonyx::context_ptr& ctx, const raw_problem& pb);
832

833
834
835
836
837
838
839
840
841
/**
 * @details Try to valid the @c baryonyx::result according to the
 *    @c baryonyx::raw_problem.
 *
 * @param pb Problem definition.
 * @param r A representation of the result of the problem @c pb.
 *
 * @return true if @c r is a solution of the problem @c pb, false otherwise.
 */
Gauthier Quesnel's avatar
Gauthier Quesnel committed
842
BX_EXPORT
843
844
845
bool
is_valid_solution(const raw_problem& pb, const result& r);

846
847
848
849
850
851
852
853
854
855
/**
 * @details Computes the value of the solution of the @c baryonyx::result
 *    according to the @c baryonyx::raw_problem.
 *
 * @param pb Problem definition.
 * @param r A representation of the result of the problem @c pb.
 *
 * @return the value of the solution if @c r is a solution of the problem
 *    @c pb.
 */
Gauthier Quesnel's avatar
Gauthier Quesnel committed
856
BX_EXPORT
857
858
double
compute_solution(const raw_problem& pb, const result& r);
Gauthier Quesnel's avatar
Gauthier Quesnel committed
859
860
861
}

#endif