Closed dkhall closed 3 years ago
Oops! Do you have a working example? I test some small x0s but clearly didn't catch this.
use_pccp=False
doesn't fall back on the previous algorithm, but rather tries to do a sequential solve without any slack variables or feasibility solves, so it's likely to only work with a full x0 and no SignomialEqualities
The case I'm dealing with is probably too unwieldy to share, spread across multiple modules. I'll work to come up with a MWE.
Hi, I would also like to report similar issues.
use_pccp=False
is ignored.The nature of my problem requires that the optimization problem be solved without any slack (it is always feasible). However, the program seems to ignore use_pccp=False
. I have tried using high values of pccp_penalty
, but it does not seem to be making a difference as the value of my objective function is often pretty large. Additionally, it is worth noting that the program has no signomial equality constraints.
My signomial program is a little complex, but you can find a snippet at the end of this comment for your reference.
x0
ignored if supplied user-defined dictionary.I was able to find a small example for this (inspired by the documentation).
x = Variable('x')
y = Variable('y')
with SignomialsEnabled():
constraints = [x >= 1-y, y <= 0.2]
constraints+= [x>=0.000001]
d={x:0.8, y:0.2} # this is the optimal solution
m = Model(x, constraints)
print(m.localsolve(verbosity=0, solver='mosek_cli', x0=d).summary())
The program above ignores x0
and takes 4 iterations to arrive at the optimal value.
x0
. The docs https://gpkit.readthedocs.io/en/v0.9.9/signomialprogramming.html refer to it as xk
. However, using xk
in the program does not the result in the program using it as the initial position.localsolve()
accepts arbitrary arguments. For instance, m.localsolve(verbosity=0, solver='mosek_cli', banana=42)
does not throw any errors.use_pccp=False
from gpkit import Model, Variable, SignomialsEnabled
from gpkit.constraints.bounded import Bounded
# ... variables are th1 through th40.
# prev_res obtained from a previous solve
prev_res={th1: 0.1271235284874968, th2: 0.8728764994398744, th3: 0.7035231472386804, th4: 0.29647689185193177, th5: 0.4899583458305375, th6: 0.5100416448647169, th7: 0.6034266420601294, th8: 0.3965733346611888, th9: 0.6684074074242299, th10: 0.33159265703838525, th11: 0.22930254274891962, th12: 0.7706973689874355, th13: 1.0, th14: 0.8630073250876732, th15: 0.13699265057923807, th16: 1.0, th17: 1.0, th18: 1.0, th19: 1.0, th20: 0.9365216681429392, th21: 0.06347831039588891, th22: 0.7518573253206168, th23: 0.248142525077401, th24: 0.4436889611463308, th25: 0.5563109936540922, th26: 0.46457080482419366, th27: 0.5354292057400054, th28: 0.7516171452759821, th29: 0.24838284333694824, th30: 0.17493339106490582, th31: 0.8250666566267977, th32: 1.0, th33: 0.9183586668841595, th34: 0.08164138307826121, th35: 1.0, th36: 1.0, th37: 0.999999991511505, th38: 0.999999991511505, th39: 0.8758025613814215, th40: 0.12419740542485974, SGP.PCCPslack: 2.236259267395232}
objective_function= th1^-5412·th2^-37332·th3^-30064·th4^-12680·th5^-20955·th6^-21789·th7^-25856·th8^-16888·th9^-28464·th10^-14280·th11^-9924·th12^-32820·th13^-42744·th14^-36751·th15^-5993·th16^-42744·th17^-42744·th18^-42744·th19^-42744·th20^-5705·th21^-385·th22^-4585·th23^-1505·th24^-2691·th25^-3399·th26^-2744·th27^-3346·th28^-4697·th29^-1393·th30^-934·th31^-5156·th32^-6090·th33^-5739·th34^-351·th35^-6090·th36^-6090·th37^-6090·th38^-6090·th39^-42744·th40^-6090
# The last 2 constraints are signomial constraints
constraints = [th1 <= 1, th2 <= 1, th3 <= 1, th4 <= 1, th5 <= 1, th6 <= 1, th7 <= 1, th8 <= 1, th9 <= 1, th10 <= 1, th11 <= 1, th12 <= 1, th13 <= 1, th14 <= 1, th15 <= 1, th16 <= 1, th17 <= 1, th18 <= 1, th19 <= 1, th20 <= 1, th21 <= 1, th22 <= 1, th23 <= 1, th24 <= 1, th25 <= 1, th26 <= 1, th27 <= 1, th28 <= 1, th29 <= 1, th30 <= 1, th31 <= 1, th32 <= 1, th33 <= 1, th34 <= 1, th35 <= 1, th36 <= 1, th37 <= 1, th38 <= 1, th39 <= 1, th40 <= 1, th1 + th2 <= 1, th3 + th4 <= 1, th5 + th6 <= 1, th7 + th8 <= 1, th9 + th10 <= 1, th11 + th12 <= 1, th13 <= 1, th14 + th15 <= 1, th16 <= 1, th17 <= 1, th18 <= 1, th19 <= 1, th20 + th21 <= 1, th22 + th23 <= 1, th24 + th25 <= 1, th26 + th27 <= 1, th28 + th29 <= 1, th30 + th31 <= 1, th32 <= 1, th33 + th34 <= 1, th35 <= 1, th36 <= 1, th37 <= 1, th38 <= 1, th39 + th40 <= 1, th39·th19·th1·th18·th6·th3·th17·th7·th16·th13·th10·th11·th15·(th39·th19·th1·th18·th6·th3 + th40·th38·th20·th37·th25·th22) + 1 - th39·th19·th1·th18·th6·th3·(th39·th19·th1·th18·th6·th3·th17·th7·th16·th13·th10·th11·th15 + th40·th38·th20·th37·th25·th22·th36·th26·th35·th32·th29·th30·th34) - 0.1·(th39·th19·th1·th18·th6·th3·th17·th7·th16·th13·th10·th11·th15 + th40·th38·th20·th37·th25·th22·th36·th26·th35·th32·th29·th30·th34)·(th39·th19·th1·th18·th6·th3 + th40·th38·th20·th37·th25·th22) <= 1, th39·th19·th1·th18·th6·th3·(th39·th19·th1·th18·th6·th3·th17·th7·th16·th13·th10·th11·th15 + th40·th38·th20·th37·th25·th22·th36·th26·th35·th32·th29·th30·th34) + 1 - th39·th19·th1·th18·th6·th3·th17·th7·th16·th13·th10·th11·th15·(th39·th19·th1·th18·th6·th3 + th40·th38·th20·th37·th25·th22) - 0.1·(th39·th19·th1·th18·th6·th3·th17·th7·th16·th13·th10·th11·th15 + th40·th38·th20·th37·th25·th22·th36·th26·th35·th32·th29·th30·th34)·(th39·th19·th1·th18·th6·th3 + th40·th38·th20·th37·th25·th22) <= 1]
m = Model(objective_function, Bounded(constraints))
print(m.localsolve(verbosity=0, solver='mosek_cli', use_pccp=False, x0=prev_res).summary())
Thanks for your support!
This model does not seem to be bounded (and requires slackening by 0.00056% to solve, but that may just be numerical noise). I'll try reproducing the error another way!
With regards to pccp_solve, it's worth noting that enabling it generally makes the solve faster even if it's already feasible.
Figured out why it wasn't disabling PCCP - there's a different syntax for that which I forgot to document! Use m.sp(use_pccp=False).localsolve(...)
@dkhall also figured out the x0 issue: it wasn't properly "cleaning" the x0, so if you were including strings or variable objects as keys -- instead of VarKey objects as the previous solution would use -- it wouldn't convert them to VarKeys. I'll fix & test this.
@nikilrselvam re the points in 3: the x0 syntax and documentation definitely needs to be cleared up, I'll try to do that soon. As for the arbitrary keyword arguments, that's to make room for arbitrary arguments that a particular solver might use, as localsolve kwargs are passed along to the underlying solver! But because different solvers accept different arguments, none of them error on getting arguments they didn't want, leading to this silent acceptance.
To summarize the above:
use_pccp=False
is ignored.It needs to be specified when creating the program, not when solving. This is a bit confusing, because calling localsolve/solve on a Model will automatically create the relevant program, but you can also do so manually with, e.g.:
m.sp(use_pccp=False).localsolve(...)
x0
ignored if supplied user-defined dictionary.This is because it's no longer "cleaned" before being passed to the GP, and so any strings that are variables or strings will get ignored. Quick fix: use varkeys directly, e.g. d={x.key:0.8, y.key:0.2}
. I'll be changing the code to fix this, however, and use @nikilrselvam's example as a test.
@dkhall, @nikilrselvam hope this fixes your issues, and sorry for the wait!
@bqpd Thanks!
Disabling PCCP works as expected now that I'm using the correct syntax.
I expect the x0 cleaning fix will improve my particular situation, as I am using the strings of the variable names as the keys in my x0 dictionary (which lives in a separate, static module, so I haven't tested the varkey quick fix).
@bqpd Thank you for your prompt response!
I'm unsure which model you were referring to in your first comment (where you reported a slack of 0.00056%). In case you were referring to the snippet of the non-trivial program in my original comment, I use Bounded(constraints)
to introduce some trivial bounds. When I tried solving it with pccp
, my model reported a slack of around 2.23.
However, more importantly, I can confirm that disabling PCCP now seems to work as expected for me too! Thank you for clarifying this.
x0 fix is up, along with a fix to the error message that is presumably how y'all learned about use_pccp to clarify its proper syntax
@nikilrselvam also, welcome to GPkit! How'd you hear about this project?
@bqpd Thank you! I'm sorry I missed this message. I'm currently working at the UCLA StarAI Lab, and a graduate student who had used GPkit for a prior project introduced me to it! I'm finding it extremely useful in my current research :)
ah fabulous! glad to hear that.
@dkhall @nikilrselvam I realized that the syntax above couldn't handle changing the pccp_penalty and sweeping, so I changed it in https://github.com/convexengineering/gpkit/pull/1548 such that the pccp_penalty can be an argument to localsolve after all; the syntax you were using before (and that I erroneously suggested in the error message) should now work!
I have a fairly complex model, with a few SP constraints, that is sensitive to the initial guess, i.e., won't converge (or won't converge without slack) unless I give it a good x0. When I set x0= a pickle of a previous solution, it solves fine in 2 or 3 GPs. However, if I set x0= a dictionary with the same information as in the pickle, the solver appears to ignore x0 and has the same convergence history as if no x0 was given.
If I go back to 1f5f8bf, the behavior is as expected, with both the pickle-load and user-defined dictionary yielding the same convergence history. Beyond b6fd017, only the pickle-loaded x0 works, and .localsolve also appears to ignore use_pccp=False.