@@ -407,36 +407,71 @@ end
407
407
408
408
# # Submittables
409
409
410
+ """
411
+ RejectSolution(callback_data)
412
+
413
+ Reject feasible solution provided by [`CallbackVariablePrimal`](@ref).
414
+
415
+ This can be submitted only from the [`FeasibleSolutionCallback`](@ref). The
416
+ field `callback_data` is a solver-specific callback type that is passed as the
417
+ argument to the feasible solution callback.
418
+ """
419
+ struct RejectSolution{CBDT} <: AbstractSubmittable
420
+ callback_data:: CBDT
421
+ end
422
+
410
423
"""
411
424
LazyConstraint(callback_data)
412
425
413
- Lazy constraint `func`-in-`set` submitted as a tuple `( func, set) `. The optimal
426
+ Lazy constraint `func`-in-`set` submitted as ` func, set`. The optimal
414
427
solution returned by [`VariablePrimal`](@ref) will satisfy all lazy
415
428
constraints that have been submitted.
416
429
417
- This can be submitted only from the lazy callback (that is, the function set to
418
- [`LazyCallback`](@ref)). The field `callback_data` is a solver-specific
419
- callback type that is passed as the argument to the lazy callback.
430
+ This can be submitted only from the [`FeasibleSolutionCallback`](@ref). The
431
+ field `callback_data` is a solver-specific callback type that is passed as the
432
+ argument to the feasible solution callback.
420
433
"""
421
- struct LazyConstraint <: AbstractSubmittable
422
- callback_data:: Any
434
+ struct LazyConstraint{CBDT} <: AbstractSubmittable
435
+ callback_data:: CBDT
423
436
end
424
437
425
438
"""
426
439
HeuristicSolution(callback_data)
427
440
428
- Heuristically obtained integer-feasible solutions. The solution is given by a
429
- `Dict{VariableIndex, Float64}` mapping the variables to their solution value.
441
+ Heuristically obtained feasible solution. The solution is submitted as
442
+ `variables, values` where `values[i]` gives the value of `variables[i]`,
443
+ similarly to [`set`](@ref).
430
444
431
- This can be submitted only from the heuristic callback (that is, the function
432
- set to [`HeuristicCallback`](@ref)). The field `callback_data` is a
433
- solver-specific callback type that is passed as the argument to the heuristic
434
- callback.
445
+ This can be submitted only from the [`InfeasibleSolutionCallback`](@ref). The
446
+ field `callback_data` is a solver-specific callback type that is passed as the
447
+ argument to the infeasible solution callback.
435
448
436
449
Note that the solver may silently reject the provided solution.
437
450
"""
438
- struct HeuristicSolution <: AbstractSubmittable
439
- callback_data:: Any
451
+ struct HeuristicSolution{CBDT} <: AbstractSubmittable
452
+ callback_data:: CBDT
453
+ end
454
+
455
+ """
456
+ UserCut(callback_data)
457
+
458
+ Constraint `func`-to-`set` suggested to render the solution given by
459
+ [`CallbackVariablePrimal`](@ref) trivially infeasible. The solution is submitted
460
+ as `func, set`. For instance, for a solution satisfying all constraints except
461
+ [`SingleVariable`](@ref)-in-[`Integer`](@ref) constraints, a
462
+ [`ScalarAffineFunction`](@ref)-in-[`LessThan`](@ref) may be submitted cut it
463
+ off. Note that, as opposed to [`LazyConstraint`](@ref), the provided constraint
464
+ cannot modify the feasible set, the constraint should be redundant, e.g., it
465
+ may be a consequence of affine and integrality constraints.
466
+
467
+ This can be submitted only from the [`InfeasibleSolutionCallback`](@ref). The
468
+ field `callback_data` is a solver-specific callback type that is passed as the
469
+ argument to the infeasible solution callback.
470
+
471
+ Note that the solver may silently ignore the provided constraint.
472
+ """
473
+ struct UserCut{CBDT} <: AbstractSubmittable
474
+ callback_data:: CBDT
440
475
end
441
476
442
477
# # Optimizer attributes
@@ -525,43 +560,97 @@ attributes (i.e, the attributes `attr` such that `is_set_by_optimize(attr)`)
525
560
may not be accessible from the callback hence trying to get result attributes
526
561
might throw a [`OptimizeInProgress`](@ref) error.
527
562
563
+ Some solvers require a complete solution, others only partial solutions. It's up
564
+ to you to provide the appropriate one. If in doubt, give a complete solution.
565
+
528
566
The value of the attribute should be a function taking only one argument, that
529
567
is commonly called `callback_data`, that can be used for instance in
530
- [`LazyCallback `](@ref), [`HeuristicSolution `](@ref).
568
+ [`FeasibleSolutionCallback `](@ref), [`InfeasibleSolutionCallback `](@ref).
531
569
"""
532
570
abstract type AbstractCallback <: AbstractOptimizerAttribute end
533
571
534
572
"""
535
- LazyCallback () <: AbstractCallback
573
+ FeasibleSolutionCallback () <: AbstractCallback
536
574
537
- The *lazy* callback can be used to submit [`LazyConstraint`](@ref) which are
538
- added on-demand at integer nodes in the branch and bound tree . Note that there
539
- is no guarantee that the callback is called at *every* integer primal solution.
575
+ The callback can be used to reject a feasible primal solution by submitting
576
+ [`RejectSolution`](@ref) and/or [`LazyConstraint`](@ref) . Note that there
577
+ is no guarantee that the callback is called at *every* feasible primal solution.
540
578
541
- The solution at the integer node is accessed through
542
- [`VariablePrimalAtIntegerNode `](@ref). Trying to access other result
579
+ The feasible primal solution is accessed through
580
+ [`CallbackVariablePrimal `](@ref). Trying to access other result
543
581
attributes will throw [`OptimizeInProgress`](@ref) as discussed in
544
582
[`AbstractCallback`](@ref).
583
+
584
+ ## Examples
585
+
586
+ ```julia
587
+ x = MOI.add_variables(optimizer, 8)
588
+ MOI.submit(optimizer, MOI.FeasibleSolutionCallback(), callback_data -> begin
589
+ sol = MOI.get(optimizer, MOI.CallbackVariablePrimal(callback_data), x)
590
+ if MOI.supports(optimizer, MOI.RejectSolution(callback_data))
591
+ # determine if it should be rejected only if it's supported as it may
592
+ # be time consuming.
593
+ if # should reject
594
+ MOI.submit(optimizer, MOI.RejectSolution(callback_data))
595
+ end
596
+ end
597
+ if MOI.supports(optimizer, MOI.LazyConstraint(callback_data))
598
+ # determine the lazy constraint only if it's supported as it may be time
599
+ # consuming.
600
+ if # should add a lazy constraint
601
+ func = # computes function
602
+ set = # computes set
603
+ MOI.submit(optimizer, MOI.LazyConstraint(callback_data), func, set)
604
+ end
605
+ end
606
+ end
607
+ ```
545
608
"""
546
- struct LazyCallback <: AbstractCallback end
609
+ struct FeasibleSolutionCallback <: AbstractCallback end
547
610
548
611
"""
549
- HeuristicCallback () <: AbstractCallback
612
+ InfeasibleSolutionCallback () <: AbstractCallback
550
613
551
- The *heuristic* callback can be used to submit [`HeuristicSolution`](@ref) at
552
- fractional (i.e., non-integer) nodes in the branch and bound tree. Note that
553
- there is not guarantee that the callback is called *everytime* the solver has a
554
- fractional solution.
614
+ The callback can be used to submit [`HeuristicSolution`](@ref) and/or
615
+ [`UserCut`](@ref) given an infeasible primal solution.
616
+ For instance, it may be called at fractional (i.e., non-integer) nodes in the
617
+ branch and bound tree of a mixed-integer problem. Note that there is not
618
+ guarantee that the callback is called *everytime* the solver has an infeasible
619
+ solution.
555
620
556
- The solution at the fractional node is accessed through
557
- [`VariablePrimalAtFractionalNode `](@ref). Trying to access other result
621
+ The infeasible solution is accessed through
622
+ [`CallbackVariablePrimal `](@ref). Trying to access other result
558
623
attributes will throw [`OptimizeInProgress`](@ref) as discussed in
559
624
[`AbstractCallback`](@ref).
560
625
561
- Some solvers require a complete solution, others only partial solutions. It's up
562
- to you to provide the appropriate one. If in doubt, give a complete solution.
626
+ ## Examples
627
+
628
+ ```julia
629
+ x = MOI.add_variables(optimizer, 8)
630
+ MOI.submit(optimizer, MOI.InfeasibleSolutionCallback(), callback_data -> begin
631
+ sol = MOI.get(optimizer, MOI.CallbackVariablePrimal(callback_data), x)
632
+ if MOI.supports(optimizer, MOI.HeuristicSolution(callback_data))
633
+ # determine the heuristic solution only if it it's supported as it may
634
+ # be time consuming.
635
+ if # can find a heuristic solution
636
+ values = # computes heuristic solution
637
+ MOI.submit(optimizer, MOI.HeuristicSolution(callback_data), x,
638
+ values)
639
+ end
640
+ end
641
+ if MOI.supports(optimizer, MOI.UserCut(callback_data))
642
+ # determine the user cut only if it's supported as it may be time
643
+ # consuming.
644
+ if # can find a user cut
645
+ func = # computes function
646
+ set = # computes set
647
+ MOI.submit(optimizer, MOI.UserCut(callback_data), func, set)
648
+ end
649
+ end
650
+ end
651
+ ```
563
652
"""
564
- struct HeuristicCallback <: AbstractCallback end
653
+ struct InfeasibleSolutionCallback <: AbstractCallback end
565
654
566
655
# # Model attributes
567
656
@@ -784,25 +873,13 @@ end
784
873
VariablePrimal () = VariablePrimal (1 )
785
874
786
875
"""
787
- VariablePrimalAtIntegerNode(callback_data)
788
-
789
- A variable attribute for the assignment to some primal variable's value at the
790
- integer node from which the [`LazyCallback`](@ref) corresponding to
791
- `callback_data` was called.
792
- """
793
- struct VariablePrimalAtIntegerNode <: AbstractVariableAttribute
794
- callback_data:: Any
795
- end
796
-
797
- """
798
- VariablePrimalAtFractionalNode(callback_data)
876
+ CallbackVariablePrimal(callback_data)
799
877
800
- A variable attribute for the assignment to some primal variable's value at the
801
- fractional node from which the [`HeuristicCallback`](@ref) corresponding to
802
- `callback_data` was called.
878
+ A variable attribute for the assignment to some primal variable's value during
879
+ the callback identified by `callback_data`.
803
880
"""
804
- struct VariablePrimalAtFractionalNode <: AbstractVariableAttribute
805
- callback_data:: Any
881
+ struct CallbackVariablePrimal{CBDT} <: AbstractVariableAttribute
882
+ callback_data:: CBDT
806
883
end
807
884
808
885
"""
0 commit comments