-
Notifications
You must be signed in to change notification settings - Fork 121
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
AbstractVariable
interface; allow variables to carry constraints
#358
Conversation
One thing is that now |
Ah, looking at #341, I think there's another catch. We likely want |
a030af7
to
7718bc6
Compare
I've rebased on top of #341 and add such an accessor. I think this just needs a few more tests and it's good to go. |
7718bc6
to
531957c
Compare
70a802f
to
74b4b4f
Compare
Codecov Report
@@ Coverage Diff @@
## master #358 +/- ##
==========================================
+ Coverage 88.03% 88.42% +0.39%
==========================================
Files 75 75
Lines 3460 3508 +48
==========================================
+ Hits 3046 3102 +56
+ Misses 414 406 -8
Continue to review full report at Codecov.
|
This is a continuation of #313; I made a PR from the JuliaOpt/Convex.jl repo instead of my fork to get docs previews (available here: https://www.juliaopt.org/Convex.jl/previews/PR358/).
Remaining things to do:
show
methods)_value
accessor discussed inAbstractVariable
interface; allow variables to carry constraints #358 (comment)This PR introduces an
AbstractVariable
type with a corresponding interface. User-defined types can implement the interface to have custom variable types which can be dispatched on in user-code. The interface consists ofevaluate
,set_value!
: get or set the numeric value of the variable.value
should returnnothing
when no numeric value is set. I decided to re-useevaluate
instead of introducing e.g.value
, since they would have the same meaning.vexity
,vexity!
: get or set thevexity
of the variable. Thevexity
should beAffineVexity()
unless the variable has beenfix!
'd, in which case it isConstVexity()
.sign
,vartype
, andconstraints
: get theSign
,VarType
(a new enum, for binary, integer, or continuous variables), numeric type, and a (possibly empty) vector of constraints which are to be applied to any problem in which the variable is used.constraints
: return those constraints carried by the variable (e.g. that it is positive semi-definite)Optionally, also users can also implement
sign!
,vartype!
, andadd_constraint!
to allow users to modify those values or add a constraint to a list of constraints which are applied to any problem in which the variable is used.Subtypes of
AbstractVariable
are expected to have fields (orgetproperty
overloads) forhead
,id_hash
andsize
, as those are expected of allAbstractExpr
's. Future work could be to clarify theAbstractExpr
interface. Moreover,AbstractVariable
's need to set their own hash asVariable
's do. This sounds confusing but I added an example to the docs. Moreover, subtypingAbstractVariable
is definitely not necessary for casual use (we got this far without it anyway!).The venerable
Variable
is the first user of this interface. The newconstraints
andvartype
methods lets us finish what we started in #299: getting rid ofsets
. The problem withsets
is that it tried to serve several orthogonal purposes simultaneously while at the same time, it wasn't always very clear what you could put in there that would have an effect.sets
was populated by:fixed
to indicate a variable was constant; this was changed in Allow callingfix!
twice in a row #299 by using thevexity
to indicate constantness.sets
was also used to add one particular constraint to a variable: semidefiniteness. This is replaced by the much more flexibleconstraints
(andadd_constraint!
) method. Now, aVariable
can carry around arbitrary constraints which automatically get applied to any problem the variable is in, just like:semidefinite
insets
did.sets
was finally used to indicate if a variable was binary, integer, or continuous. This was replaced byvartype
which uses an enum. I prefer the enum because it makes clear what the possible choices are, whereas when entering symbols, it wasn't immediately obvious (e.g.:bin
or:binary
?)What is the benefit? One nice thing you can do now is
Then later,
p = probabilityvector(3)
can be used like any other variable, but the constraints of having non-negative entries which add to 1 will be automatically applied to any problem it is used in. This allows very simple implementations of DSLs.The introduction of
AbstractVariable
allows more ambitious extensions as well. Since custom types can subtypeAbstractVariable
, variables can be used in dispatch, or even be used as callable types. Continuing with the probability example, let's say I often use my probability vectors for getting the expectation value of other variables, and I want to use function notation for this. I could defineAnd then I can use the new type freely in Convex problems. E.g.
(Back in August, I was experimenting with a similar DSL for quantum information theory in https://github.com/ericphanson/QuantumSDPs.jl; I hope to pick that up at some point.)
I re-implemented the old constructors that accept symbols for
set
, and translate them to the new variable type, which could be deprecated now or in a later PR. Many of the internals changes are simply changing e.g.x.sign
tosign(x)
, to use the interface instead.