So I have
M = [0.06,0.22,0.32,0.15,0.19]
wanted = 0.21
-0.05 <= -0.273*ln((new_M-M)/(M)+1) +0.0024 <= 0.05
New_M values are created by optimizing M values as close as possible to the wanted value(0.21), with bounds:
M - 0.1<=new_M<= M + 0.1
In other words M cannot be changed by more than 0.1, from both sides, in order to get as close as possible to wanted value 0.21, but also there is that constraint on the top as well.
Any suggestions on how to solve this problem?I've tried some optimization libraries(pulp, mip, scipy) but it didn't work for me, because I don't how to describe constraints and bounds for this problem. How should I optimize for specific target value with constraints and how should I use that value for new constraint(if it's possible)?
First some observations.
new_M
and new
in your formulas. I'll assume they are the same.Wanted
is probably part of an objective: make M
as close as possible to Wanted
. It is not a constraint.M
is a vector, but it seems all the optimization problems are independent. So we can solve for a scalar M
(and repeat for all elements in the list).M
and new_M
. "Optimizing M" seems to indicate M
is a decision variable. But I think you mean: "Optimizing New_M" with M
being a constant.M=0
. Note that you divide by M
in: (new_M-M)/(M)
. You must explain what that means. (Maybe you meant 0.32 instead of 0,32
).(M)
in ln((new_M-M)/(M)+1)
?M>0
in the following.So let me try to use more "traditional" mathematical notation:
min |x-wanted|
subject to
M - 0.1 ≤ x ≤ M + 0.1
-0.05 ≤ -0.273*ln(1+(x-M)/M)+0.0024 ≤ 0.05
x > 0 (implicit from the ln(.) calculation)
Here x
is the decision variable and M
,wanted
are constants.
Using high-school math, we can rewrite the second constraint as:
0.84*M ≤ x ≤ 1.2116*M
assumption: M > 0
So let:
L := max(M-0.1, 0.84*M, 0.0001)
U := min(M+0.1, 1.2116*M)
Now we just need to solve:
min |x-wanted|
subject to L ≤ x ≤ U
This can be solved with the "algorithm":
if wanted > U then x := U
else if wanted < L then x := L
else x := wanted
Or in Python:
M = [0.06,0.22,0,32,0.15,0.19]
wanted = 0.21
for m in M:
if m<=0: raise Exception("M<=0 not allowed")
L = max(m-0.1, 0.84*m, 0.0001)
U = min(m+0.1, 1.2116*m)
if wanted>U: x=U
elif wanted<L: x=L
else: x=wanted
print(f"M:{m}, x:{x}")
In conclusion: