-
Notifications
You must be signed in to change notification settings - Fork 23
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
DOE: NChooseK constraints #145
Comments
While working on the old mopti-based doe I did some experiments with NChooseK constraints. In mopti, the violation of NChooseK constraints is defined as the sum of the absolute values of the three smallest deviations from 0 if the number of of nonzero components is larger than k and 0 otherwise. I think this should be a continuous function, but not smooth. IPOPT had problems dealing with this constraint function (in fact, the current solution for NChooseK constraints in doe was chosen, because IPOPT was not able to find acceptable designs using this constraint function). I could have a look at this / you can assign the issue to me if you want to (except you want to take care of this @jduerholt , @DavidWalz) |
Would be happy if you could have a look at it, I have to finalize it next week for the BayesOpt part. I can at least say that the scipy SLSQP is able to handle it this version, as this optimizer is used in botorch for acqf optimization. I have already implemented these constraints here: bofire/bofire/utils/torch_tools.py Line 88 in 3c9fb82
I takes the domain and returns a list of torch callables which evaluate the constraints. You can in principle use these torch based callables directly as is in DoE and compute the Jacobian via torch autograd. Then you do not need to implement the gradients etc. by hand. Test cases can be found in this module: https://github.com/experimental-design/bofire/blob/main/tests/bofire/utils/test_torch_tools.py You can also have a look in botorch, how they convert the non-linear constraints to scipy including automatic generation of the Jacobian: https://github.com/pytorch/botorch/blob/f596e71cc3d6404f1af3dfda1a92983d7303ef07/botorch/generation/gen.py#L222 From my understanding the python ipopt interface is relatively similar to the scipy.optimize interface. |
I implemented the constraint / constraint jacobian inside the EXIT: Converged to a point of local infeasibility. Problem may be infeasible. At first I suspected my new lines of code to have mistakes in it, but the problem even remains for the toy problem from the sample notebook from this discussion, where SLSQP does the job. In case you want to reproduce this finding, this is code you can use for it
I assume that the reason for these problems could be the quickly vanishing gradients of the narrow Gaussians when moving away from its center. Once you are not close to the center anymore it becomes practically zero very fast and should therefore become uninformative. What do you think about this? Does it make sense to you? However, this does not explain why SLSQP does not have the same problems with this kind of constraint... So my conclusion would be right now that we should stick to the current solution in doe since IPOPT can produce acceptable results with it but can't with the narrow Gaussians. I wish you happy easter holidays! |
Totally overlooked this over easter. Sorry! One heretical question: why does one needs ipopt for DoE, should SLSQP not also do the job? |
Unfortunately it is necessary to use IPOPT, because for larger scale problems (e.g. 20 inputs, fully-quadratic model) the "normal" |
Thanks for the info, then it is like it is and we stick with your original implementation for the nchooseks and keep it just as option. Thanks for your effort, it was just an idea as it was working with slsqp ... Another option could be to have in |
We could add this as an option instead of of I used 6 inputs with bounds (0,1), a fully-quadratic model, n_experiment=10 and the following constraints
In the first two cases the NChooseK constraint is only semi-relevant since the optimal design without the nchoosek constraint fulfills the nchoosek constraints. The last case has a "real" nchoosek constraint. I have run each of these cases three times with these average objective values:
So to me this indicates that the current solution seems to be a pretty good surrogate for the actual nchoosek constraint (at least in this simple example), but is easier to handle (for both IPOPT and SLSQP). On the other hand, the current solution can only handle nchoosek constraints with min_count=0 (this case was the only one existing in |
Okay, then we remove it. It was worth a try ;) |
This is solved. |
Thank you for the thorough evaluation of these two methods. This is the kind of testing that I was hoping to get to. @Osburg and @jduerholt I appreciate you both exploring this.
In a formulation setting, I take it |
@Osburg, I also have a follow-up question. Could you give a brief description of what the "original implementation" or "current solution" is? From #145 (comment)
From #145 (comment)
|
Let me already comment from high level, @Osburg can then further add on it ;) It is important to know that we are talking in this issue just about the DoE submodule of Bofire, which can be used to generate for example D-optimal plans under constraints and different model functions. Despite D optimality also other optimality measures like K-optimality are possible (https://github.com/experimental-design/bofire/blob/main/bofire/strategies/enum.py#L4) In this contect we have tested the "original implementation" against the narrow gaussian method. Note that we use in the BO strategies based on botorch always the narrow gaussian approach. So what is the "orginal implementation"? @Osburg please correct if I am wrong ;) The original implementation which is also the current one is described here: https://basf.github.io/doe/nchoosek_constraint/ Just as additional note: the DoE part of BoFire was originally developed at BASF and later merged into BoFire where it is further developed. Unfortunately, we have not yet migrated the documentation ;) |
@jduerholt yes, this is how it still works :) Originally, I was asked to add support for NChooseK constraints in combination with a mixture constraint. Because of the symmetry of this constraint all variables are interchangeable. The assumption of the "current solution" is that we have such a symmetry. If this assumption is met we have a handwavy argument why the "current solution" works: because of the symmetry of the problem all variables should be 0 equally often in a D-optimal design. So we can take all possible combinations of |
Firstly, thanks for your work in implementing and verifying the NChooseK solution for DoE in BoFire. Sorry for reopening the issue. I have use cases where having min_count to be greater than 0 is needed. As noted above, I could generate samples and then filter out the ones that do not meet what I want but I would prefer to have the method be able to account for min_count > 0. Is there a limitation in being able to "easily" implement this or would it require re-evaluating how NChooseK works in its current form, e.g. having to re-visit the possibility for having the narrow Gaussian approach be a alternative method in these cases? Cheers |
@simonsung06 There is an implementation of what you need, see for example here bofire/tests/bofire/strategies/test_doe.py Line 204 in b04904d
The only problem is that this can take quite long, as the full categorical problem is build and solved via relaxation, - or if that fails to provide a feasible solution - via branch and bound. How does your use case look like? |
@simonsung06 just as an addition to what @dlinzner-bcs already wrote: In case of min_count = 1 it could be an idea to just add a linear constraint (in case of nonnegative decision variables) where
The result without the additional linear constraint is
By adding the linear constraint we can avoid the experiment (0,0,0). So in this very simple case it seems to work.
|
Thank you @dlinzner-bcs and @Osburg for the advice on this. It is nice to see that For my situation, it was for a mixture style DoE with 5 components that needed a Another query that I have: I generated the design using the |
Using the method I proposed for min_count=1 I do not run into your problem for a problem of the same structure as yours (so maybe it is worth for you to try it out on your problem, too). I created the following domain
This should roughly correspond to your problem. To ensure min_count=1 I added the additional linear equality constraint (where I assumed that we want at least a share of 10% for the active component, but it is open to you to choose a value you consider large enough). I assumed a fully-quadratic model and added two fixed experiments to imitate your problem as good as possible.
The resulting design looks like this
Using the space filling objective instead of d optimality IPOPT still converges and produces the following design
Does this approach go in the right direction or did I misunderstand you somewhere? Hope this is somewhat helpful... Cheers, P.S.: One question: You impose an NChooseKConstraint on 2 variables with max_count=2. If it is a valid option for you to use a linear inequality for ensuring that one component is nonzero, you could also just drop the NChooseKConstraint (since it will never be active), right? In fact, due to a bug it is not possible to use an NChooseKConstraint w/ max_count = #(variables in the constraint). I just opened a PR (#304) to fix this. If you do not want to wait for it to be merged it should be valid to just omit the NChooseKConstraint. |
Currently, there is no maximum number sadly. There are two things that you can try (aside from Aarons solution above):
, which will consider the problem as a relaxed one. One risk is that you might not end up with a valid design at the end. |
Thanks for the suggestions. They all proved to be useful for my problem and also to help me understand more in general. I liked how it looks without the NChooseKConstraint and just using the LinearInequalityConstraint instead. Still worked and generated designs quickly too. The iterative strategy also worked but I preferred the designed using the previously mentioned methods, but it is great to know this option exists :) |
@DavidWalz @Osburg
As iptopt is also supporting non-linear constraints, I thought about if it could be worth to implement a continuous relaxation for the NChooseK constraints. This would also make it possible to fully support NChooseK constraints in DoE. I am currently adding this continuous relaxation also to the BayesOpt methods in Bofire.
You can find a description here: pytorch/botorch#1749 (comment)
Just have a look at the linked tutorial notebook there. I tested it in BayesOpt and it works ;) What do you think?
The text was updated successfully, but these errors were encountered: