Build an objective function with Log and Exponential inside.
AnsweredDear all,
I am new to GUROBI Optimization and I am trying to code the function which is shown in the picture below:
Unfortunately when I am writing the objective function I get the following error :
'gurobipy.LinExpr' object has no attribute 'exp'
The objective function I have built looks like this:
objective_function = (1/n)*(gp.quicksum(np.log(1+np.exp(-gp.quicksum(score[b_list[j]]*new_df.iloc[i][columns_list[j]] for j in range(j_len))))for i in range(i_len))) + l_param*gp.quicksum(1 for j in range(j_len))
where " new_df.iloc[i][columns_list[j]] "is the Xi,j of the function and " score[b_list[j]] " are the bj covariates.
Furthermore the score variable is set as:
score = m.addVars(b_list, name="b_covariates")
I sense that i should use a piecewise-linear approximation of the function but due to the nested sums, logarithm and exponential I am a little confused.
I would appreciate it if someone could shed me some light in order to continue.
-
Hi Athanasios,
Gurobi does not have built in non-linear functions other than the bilinear product of two variables.
You can use the addGenConstrExp and addGenConstrLog functions to implement a piecewise-linear approximation of the \(\exp\) and \(\log\) functions. Note that you need to introduce auxiliary variables when using these functions, because they only accept a single variable as input and output, i.e., you would have to model the \(\exp\) part of you objective as\[\begin{align}
z &= - \sum_{j=1}^p b_j x_{i,j} \\
y &= \exp(z)
\end{align}\]The \(\log\) part would have to be modeled in an analogous way.
Moreover, you cannot access the \(\texttt{score}\) variables via
for j in range(j_len):
print(score[b_list[j]])but rather as
for b in b_list:
print(score[b])unless the object \(\texttt{b_list}\) has some properties which are not listed in your post.
Best regards,
Jaromił1 -
Dear Jaromil,
Thank you for your answer. I have considered your answer and i have concluded to the modelling shown in the picture1 below which gives me the results shown in picture2:
1)
2)
I want to believe that this is what you meant in your answer, correct me if i am mistaken. Furthermore when i am trying to change a lit the subjective function as shown in bold in order to add the bj!=0 constrain
m.setObjective((y2 + l_param*gp.quicksum(1 for i in range(j_len) if score[b_list[i]]!=0)) , GRB.MINIMIZE)
it produces the error:
GurobiError: Inequality constraints not supported
Is it a way to add the if-statement and make it work?
P.S:
I considered what did you mentioned for the b_list and the "score". Both the loops are essentially resulting in the same outcome as i checked and they are not producing me an error.
a) for j in range(j_len):
print(score[b_list[j]])
b) for b in b_list:
print(score[b])Again thank you for your answer and i would be pleased to continue our discussion.
0 -
Hi Athanasios,
Your model looks correct.
However, the final solution has large constraint violations, see the Warning in the last lines of the LOG file. This is most likely cause by the huge coefficient matrix range \(\texttt{[9e-02, 1e+09]}\). You should try to reformulate or rescale your model. Our Guidelines for Numerical Issues are a good starting point.
Regarding the error. You are trying to check whether the variables \(\texttt{score}\) are \(\neq 0\). This is not possible at the time of model construction, because the variable objects don't have any values. Modeling \(\texttt{if-then}\)-statements has been already discussed in multiple Community Forum posts. You might also want to have a look at the stackexchange post How to write if else statement in linear programming?
Best regards,
Jaromił0 -
Hi Jaromil,
Thank you for your answer. As i understand it, although if i model correctly the if-statement, i t would not be feasible to apply it in the current problem for the reason you described.
Furthermore, as far as the huge coefficient matrix range, i tried to round my dataset's values but the only thing i was able to succeed is to limit the range of the matrix values but it still remains chaotic as you can see:
I have read the documentation but to be honest i am a bit lost. Do you think that there is anything else to do in the current situation?
0 -
Hi Athanasios,
You could try experimenting with the NumericFocus and the Presolve parameter. The parameters FuncPieces and FuncPieceError can be used to adjust the quality of the piecewise-linear approximation. It may already be enough to provide a good quality solution. You should provide tight bounds for every variable occurring in a nonlinear term. For variables occurring in \(\log\) terms, the lower bound should be \(>0\). A reformulation may improve numerical behavior. You could also use the write() function to write an LP file and inspect the model by hand.
Best regards,
Jaromił0 -
Hi again Jaromil,
I tried to use the functions you mentioned as the image shows.
Unfortunately, the matrix range still remains huge as you can observe.
The only thing i have not understood from the FuncPieces documentation is the:
This parameter only applies to function constraints whose FuncPieces attribute has been set to .
which is mentioned but maybe it does not play an important role.
I am tending to believe that the current problem it is not solvable at all with the above approach. However, i would like to thank you for the help you provided me.
Best regards,
Thanasis
0
Please sign in to leave a comment.
Comments
6 comments