|
| 1 | +# Current limitations: |
| 2 | +# - use fixed values for some properties |
| 3 | +# - EAGERFREQ = 100 |
| 4 | +# - NEEDSCONS = TRUE |
| 5 | +# - SEPAPRIORITY = 0 |
| 6 | +# - SEPAFREQ = -1 |
| 7 | +# - DELAYSEPA = FALSE |
| 8 | +# - PROPFREQ = -1 |
| 9 | +# - DELAYPROP = -1 |
| 10 | +# - PROP_TIMING = SCIP_PROPTIMING_BEFORELP |
| 11 | +# - PRESOLTIMING = SCIP_PRESOLTIMING_MEDIUM |
| 12 | +# - MAXPREROUNDS = -1 |
| 13 | +# - don't support optional methods: CONSHLDRCOPY, CONSFREE, CONSINIT, CONSEXIT, |
| 14 | +# CONSINITPRE, CONSEXITPRE, CONSINITSOL, CONSEXITSOL, CONSDELETE, CONSTRANS, |
| 15 | +# CONSINITLP, CONSSEPALP, CONSSEPASOL, CONSENFORELAX, CONSPROP, CONSPRESOL, |
| 16 | +# CONSRESPROP, CONSACTIVE, CONSDEACTIVE, CONSENABLE, CONSDISABLE, CONSDELVARS, |
| 17 | +# CONSPRINT, CONSCOPY, CONSPARSE, CONSGETVARS, CONSGETNVARS, CONSGETDIVEBDCHGS |
| 18 | +# - don't support linear or nonlinear constraint upgrading |
| 19 | + |
| 20 | +# Abstract Types: |
| 21 | + |
| 22 | +# (also: CONSHDLRDATA) |
| 23 | +abstract type AbstractConstraintHandler end |
| 24 | + |
| 25 | +# (also: CONSDATA) |
| 26 | +abstract type AbstractConstraint{Handler} end |
| 27 | + |
| 28 | +# Example implementation |
| 29 | +mutable struct ExampleConstraintHandler <: AbstractConstraintHandler |
| 30 | +end |
| 31 | + |
| 32 | +### ^ above: what it will look like to Julia users |
| 33 | +### = here: sketches for the translation |
| 34 | + |
| 35 | +### v below: what it will look like to SCIP |
| 36 | + |
| 37 | +# Methods |
| 38 | + |
| 39 | +# CONSENFOLP |
| 40 | +# (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, |
| 41 | +# int nusefulconss, SCIP_Bool solinfeasible, SCIP_RESULT* result) |
| 42 | + |
| 43 | +function _consenfolp(scip::Ptr{SCIP_}, conshdlr::Ptr{SCIP_CONSHDLR}, |
| 44 | + conss::Ptr{Ptr{SCIP_CONS}}, nconss::Cint, |
| 45 | + nusefulconss::Cint, solinfeasible::SCIP_Bool, |
| 46 | + result::Ptr{SCIP_RESULT}) |
| 47 | + return SCIP_OKAY |
| 48 | +end |
| 49 | + |
| 50 | +# CONSENFOPS |
| 51 | +# (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, |
| 52 | +# int nusefulconss, SCIP_Bool solinfeasible, SCIP_Bool objinfeasible, |
| 53 | +# SCIP_RESULT* result) |
| 54 | +function _consenfops(scip::Ptr{SCIP_}, conshdlr::Ptr{SCIP_CONSHDLR}, |
| 55 | + conss::Ptr{Ptr{SCIP_CONS}}, nconss::Cint, |
| 56 | + nusefulconss::Cint, solinfeasible::SCIP_Bool, |
| 57 | + objinfeasible::SCIP_Bool, result::Ptr{SCIP_RESULT}) |
| 58 | + return SCIP_OKAY |
| 59 | +end |
| 60 | + |
| 61 | +# CONSCHECK |
| 62 | +# (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS** conss, int nconss, |
| 63 | +# SCIP_SOL* sol, SCIP_Bool checkintegrality, SCIP_Bool checklprows, |
| 64 | +# SCIP_Bool printreason, SCIP_Bool completely, SCIP_RESULT* result |
| 65 | +function _conscheck(scip::Ptr{SCIP_}, conshdlr::{SCIP_CONSHDLR}, |
| 66 | + conss::Ptr{Ptr{SCIP_CONS}}, nconss::Cint, |
| 67 | + sol::Ptr{SCIP_SOL}, checkintegrality::SCIP_Bool, |
| 68 | + checklprows::SCIP_Bool, printreason::SCIP_Bool, |
| 69 | + completely::SCIP_Bool, result::Ptr{SCIP_RESULT}) |
| 70 | + return SCIP_OKAY |
| 71 | +end |
| 72 | + |
| 73 | +# CONSLOCK |
| 74 | +# (SCIP* scip, SCIP_CONSHDLR* conshdlr, SCIP_CONS* cons, |
| 75 | +# SCIP_LOCKTYPE locktype, int nlockspos, int nlocksneg) |
| 76 | +function _conslock(scip::Ptr{SCIP_}, conshdlr::Ptr{SCIP_CONSHDLR}, |
| 77 | + cons::Ptr{SCIP_CONS}, locktype::Ptr{SCIP_LOCKTYPE}, |
| 78 | + nlockspos::Cint, nlocksneg::Cint) |
| 79 | + return SCIP_OKAY |
| 80 | +end |
| 81 | + |
| 82 | +# SCIPincludeConsXyz(SCIP* scip) |
| 83 | +# |
| 84 | +# - is called by users, not SCIP: no need to make it signature conformant. |
| 85 | +# - set properties (NAME, DESC, ENFOPRIORITY, CHECKPRIORITY). |
| 86 | +# - initialize conshdlrdata (== Julia object) |
| 87 | +# - could be called from the constructor to constraint handler? |
| 88 | +function include_conshdlr(mscip::ManagedSCIP, constraint_handler::CH) where CH <: AbstractConstraintHandler |
| 89 | + # get C function pointers from Julia functions |
| 90 | + # TODO: need specific methods? ask users to specify as function arguments? |
| 91 | + _enfolp = @cfunction(_consenfolp, SCIP_RETCODE, (Ptr{SCIP_}, Ptr{SCIP_CONSHDLR}, Ptr{Ptr{SCIP_CONS}}, Cint, Cint, SCIP_Bool, SCIP_Bool, Ptr{SCIP_RESULT})) |
| 92 | + _enfops = @cfunction(_consenfops, SCIP_RETCODE, (Ptr{SCIP_}, Ptr{SCIP_CONSHDLR}, Ptr{Ptr{SCIP_CONS}}, Cint, Cint, SCIP_Bool, SCIP_Bool, SCIP_Bool, Ptr{SCIP_RESULT})) |
| 93 | + _check = @cfunction(_conscheck, SCIP_RETCODE, (Ptr{SCIP_}, Ptr{SCIP_CONSHDLR}, Ptr{Ptr{SCIP_CONS}}, Cint, Ptr{SCIP_SOL}, SCIP_Bool, SCIP_Bool, SCIP_Bool, SCIP_Bool, Ptr{SCIP_RESULT})) |
| 94 | + _lock = @cfunction(_conslock, SCIP_RETCODE, (Ptr{SCIP_}, Ptr{SCIP_CONSHDLR}, Ptr{SCIP_CONS}, Ptr{SCIP_LOCKTYPE}, Cint, Cint)) |
| 95 | + |
| 96 | + # We don't need to store this, I guess. |
| 97 | + conshdlr__ = Ref{Ptr{SCIP_CONSHDLR}} |
| 98 | + conshdlr__[] = C_NULL |
| 99 | + |
| 100 | + # Fixed values for some properties: |
| 101 | + EAGERFREQ = 100 |
| 102 | + NEEDSCONS = TRUE |
| 103 | + |
| 104 | + # Get other values from methods: |
| 105 | + name = get(constraint_handler, Name()) |
| 106 | + desc = get(constraint_handler, Description()) |
| 107 | + enfoprio = get(constraint_handler, EnforcePriority()) |
| 108 | + checkprio = get(constraint_handler, CheckPriority()) |
| 109 | + |
| 110 | + # Register constraint handler with SCIP instance. |
| 111 | + @SC SCIPincludeConshdlrBasic(mscip, conshdlr__, name, desc, enfopriority, |
| 112 | + chckpriority, EAGERFREQ, NEEDSCONS, |
| 113 | + _enfolp, _enfops, _check, _lock, |
| 114 | + constraint_handler) |
| 115 | + |
| 116 | + # Sanity checks |
| 117 | + @assert conshdlr__[] != C_NULL |
| 118 | +end |
| 119 | + |
| 120 | +# SCIPcreateConsBasicXyz(SCIP* scip, SCIP_CONS** cons, char* name, ...) |
| 121 | +# |
| 122 | +# - is called by users, not SCIP: no need to make it signature conformant. |
| 123 | +# - add custom arguments as needed |
| 124 | +# - store in consdata (== Julia object) |
| 125 | +# - could be the same as the constructor to AbstractConstraint? |
0 commit comments