Scippy

SCIP

Solving Constraint Integer Programs

expr_product.c
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program and library */
4 /* SCIP --- Solving Constraint Integer Programs */
5 /* */
6 /* Copyright (C) 2002-2022 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not visit scip.zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file expr_product.c
17  * @ingroup DEFPLUGINS_EXPR
18  * @brief product expression handler
19  * @author Stefan Vigerske
20  * @author Benjamin Mueller
21  * @author Felipe Serrano
22  * @author Ksenia Bestuzheva
23  */
24 
25 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
26 
27 #include <string.h>
28 
29 #include "scip/pub_expr.h"
30 #include "scip/expr_product.h"
31 #include "scip/expr_sum.h"
32 #include "scip/expr_pow.h"
33 #include "scip/expr_value.h"
34 #include "scip/expr_exp.h"
35 #include "scip/expr_abs.h"
36 #include "scip/expr_entropy.h"
37 #include "scip/cons_nonlinear.h"
38 #include "scip/pub_misc.h"
39 #include "scip/nlhdlr_bilinear.h"
40 
41 #define EXPRHDLR_NAME "prod"
42 #define EXPRHDLR_DESC "product expression"
43 #define EXPRHDLR_PRECEDENCE 50000
44 #define EXPRHDLR_HASHKEY SCIPcalcFibHash(54949.0)
45 
46 /** macro to activate/deactivate debugging information of simplify method */
47 /*lint -emacro(681,debugSimplify) */
48 /*lint -emacro(506,debugSimplify) */
49 /*lint -emacro(774,debugSimplify) */
50 #ifdef SIMPLIFY_DEBUG
51 #define debugSimplify printf
52 #else
53 #define debugSimplify while( FALSE ) printf
54 #endif
55 
56 
57 /*lint -e777*/
58 
59 /*
60  * Data structures
61  */
62 
63 /** expression data */
64 struct SCIP_ExprData
65 {
66  SCIP_Real coefficient; /**< coefficient */
67 };
68 
69 struct SCIP_ExprhdlrData
70 {
71  SCIP_CONSHDLR* conshdlr; /**< nonlinear constraint handler (to compute estimates for > 2-dim products) */
72 };
73 
74 /** node for linked list of expressions */
75 struct exprnode
76 {
77  SCIP_EXPR* expr; /**< expression in node */
78  struct exprnode* next; /**< next node */
79 };
80 
81 typedef struct exprnode EXPRNODE;
82 
83 /*
84  * Local methods
85  */
86 
87 /** evaluation callback for (vertex-polyhedral) functions used as input for facet computation of its envelopes */
88 static
90 {
91  /* funcdata is a pointer to the double holding the coefficient */
92  SCIP_Real ret = *(SCIP_Real*)funcdata;
93  int i;
94 
95  for( i = 0; i < nargs; ++i )
96  ret *= args[i];
97 
98  return ret;
99 }
100 
101 static
103  SCIP* scip, /**< SCIP data structure */
104  SCIP_Real simplifiedcoef, /**< simplified product should be simplifiedcoef * PI simplifiedfactors */
105  EXPRNODE** simplifiedfactors, /**< factors of simplified product */
106  SCIP_Bool changed, /**< indicates whether some of the simplified factors was changed */
107  SCIP_EXPR** simplifiedexpr, /**< buffer to store the simplified expression */
108  SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), /**< function to call to create ownerdata */
109  void* ownercreatedata /**< data to pass to ownercreate */
110  );
111 
112 /* methods for handling linked list of expressions */
113 
114 /** inserts newnode at beginning of list */
115 static
117  EXPRNODE* newnode, /**< node to insert */
118  EXPRNODE** list /**< list */
119  )
120 {
121  assert(list != NULL);
122  assert(newnode != NULL);
123 
124  newnode->next = *list;
125  *list = newnode;
126 }
127 
128 /** removes first element of list and returns it */
129 static
131  EXPRNODE** list /**< list */
132  )
133 {
134  EXPRNODE* first;
135 
136  assert(list != NULL);
137 
138  if( *list == NULL )
139  return NULL;
140 
141  first = *list;
142  *list = (*list)->next;
143  first->next = NULL;
144 
145  return first;
146 }
147 
148 /** returns length of list */
149 static
151  EXPRNODE* list /**< list */
152  )
153 {
154  int length;
155 
156  if( list == NULL )
157  return 0;
158 
159  length = 1;
160  while( (list=list->next) != NULL )
161  ++length;
162 
163  return length;
164 }
165 
166 /** creates expression node and captures expression */
167 static
169  SCIP* scip, /**< SCIP data structure */
170  SCIP_EXPR* expr, /**< expression stored at node */
171  EXPRNODE** newnode /**< pointer to store node */
172  )
173 {
174  SCIP_CALL( SCIPallocBlockMemory(scip, newnode) );
175 
176  (*newnode)->expr = expr;
177  (*newnode)->next = NULL;
178  SCIPcaptureExpr(expr);
179 
180  return SCIP_OKAY;
181 }
182 
183 /** creates expression list from expressions */
184 static
186  SCIP* scip, /**< SCIP data structure */
187  SCIP_EXPR** exprs, /**< expressions stored in list */
188  int nexprs, /**< number of expressions */
189  EXPRNODE** list /**< pointer to store list */
190  )
191 {
192  int i;
193 
194  assert(*list == NULL);
195  assert(nexprs > 0);
196 
197  debugSimplify("building expr list from %d expressions\n", nexprs);
198  for( i = nexprs - 1; i >= 0; --i )
199  {
200  EXPRNODE* newnode;
201 
202  SCIP_CALL( createExprNode(scip, exprs[i], &newnode) );
203  insertFirstList(newnode, list);
204  }
205  assert(nexprs > 1 || (*list)->next == NULL);
206 
207  return SCIP_OKAY;
208 }
209 
210 /** frees expression node and releases expressions */
211 static
213  SCIP* scip, /**< SCIP data structure */
214  EXPRNODE** node /**< node to be freed */
215  )
216 {
217  assert(node != NULL && *node != NULL);
218 
219  SCIP_CALL( SCIPreleaseExpr(scip, &(*node)->expr) );
220  SCIPfreeBlockMemory(scip, node);
221 
222  return SCIP_OKAY;
223 }
224 
225 /** frees an expression list */
226 static
228  SCIP* scip, /**< SCIP data structure */
229  EXPRNODE** exprlist /**< list */
230  )
231 {
232  EXPRNODE* current;
233 
234  if( *exprlist == NULL )
235  return SCIP_OKAY;
236 
237  current = *exprlist;
238  while( current != NULL )
239  {
240  EXPRNODE* tofree;
241 
242  tofree = current;
243  current = current->next;
244  SCIP_CALL( freeExprNode(scip, &tofree) );
245  }
246  assert(current == NULL);
247  *exprlist = NULL;
248 
249  return SCIP_OKAY;
250 }
251 
252 /* helper functions for simplifying expressions */
253 
254 /** creates a product expression with the elements of exprlist as its children */
255 static
257  SCIP* scip, /**< SCIP data structure */
258  EXPRNODE* exprlist, /**< list containing the children of expr */
259  SCIP_Real coef, /**< coef of expr */
260  SCIP_EXPR** expr, /**< pointer to store the product expression */
261  SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), /**< function to call to create ownerdata */
262  void* ownercreatedata /**< data to pass to ownercreate */
263  )
264 {
265  int i;
266  int nchildren;
267  SCIP_EXPR** children;
268 
269  /* asserts SP8 */
270  assert(coef == 1.0);
271  nchildren = listLength(exprlist);
272 
273  SCIP_CALL( SCIPallocBufferArray(scip, &children, nchildren) );
274 
275  for( i = 0; i < nchildren; ++i )
276  {
277  children[i] = exprlist->expr;
278  exprlist = exprlist->next;
279  }
280 
281  assert(exprlist == NULL);
282 
283  SCIP_CALL( SCIPcreateExprProduct(scip, expr, nchildren, children, coef, ownercreate, ownercreatedata) );
284 
285  SCIPfreeBufferArray(scip, &children);
286 
287  return SCIP_OKAY;
288 }
289 
290 /** simplifies a factor of a product expression: base, so that it is a valid children of a simplified product expr
291  *
292  * @note In contrast to other simplify methods, this does *not* return a simplified expression.
293  * Instead, the method is intended to be called only when simplifying a product expression.
294  * Since in general, base is not a simplified child of a product expression, this method returns
295  * a list of expressions L, such that (prod L) = baset *and* each expression in L
296  * is a valid child of a simplified product expression.
297  */
298 static
300  SCIP* scip, /**< SCIP data structure */
301  SCIP_EXPR* factor, /**< expression to be simplified */
302  SCIP_Real* simplifiedcoef, /**< coefficient of parent product expression */
303  EXPRNODE** simplifiedfactor, /**< pointer to store the resulting expression node/list of nodes */
304  SCIP_Bool* changed /**< pointer to store if some term actually got simplified */
305  )
306 {
307  assert(simplifiedfactor != NULL);
308  assert(*simplifiedfactor == NULL);
309  assert(factor != NULL);
310  assert(changed != NULL);
311 
312  /* enforces SP7 */
313  if( SCIPisExprValue(scip, factor) )
314  {
315  *changed = TRUE;
316  *simplifiedcoef *= SCIPgetValueExprValue(factor);
317  return SCIP_OKAY;
318  }
319 
320  /* enforces SP2 */
321  if( SCIPisExprProduct(scip, factor) )
322  {
323  *changed = TRUE;
324 
325  /* assert SP8 */
326  assert(SCIPgetCoefExprProduct(factor) == 1.0);
327  debugSimplify("[simplifyFactor] seeing a product: include its children\n");
328 
329  SCIP_CALL( createExprlistFromExprs(scip, SCIPexprGetChildren(factor), SCIPexprGetNChildren(factor), simplifiedfactor) );
330 
331  return SCIP_OKAY;
332  }
333 
334  /* enforces SP13: a sum with a unique child and no constant -> take the coefficient and use its child as factor */
335  if( SCIPisExprSum(scip, factor) && SCIPexprGetNChildren(factor) == 1 && SCIPgetConstantExprSum(factor) == 0.0 )
336  {
337  *changed = TRUE;
338 
339  /* assert SS8 and SS7 */
340  assert(SCIPgetCoefsExprSum(factor)[0] != 0.0 && SCIPgetCoefsExprSum(factor)[0] != 1.0);
341  debugSimplify("[simplifyFactor] seeing a sum of the form coef * child : take coef and child apart\n");
342 
343  SCIP_CALL( createExprlistFromExprs(scip, SCIPexprGetChildren(factor), 1, simplifiedfactor) );
344  *simplifiedcoef *= SCIPgetCoefsExprSum(factor)[0];
345 
346  return SCIP_OKAY;
347  }
348 
349  /* the given (simplified) expression `factor`, can be a child of a simplified product */
350  assert(!SCIPisExprProduct(scip, factor));
351  assert(!SCIPisExprValue(scip, factor));
352 
353  SCIP_CALL( createExprNode(scip, factor, simplifiedfactor) );
354 
355  return SCIP_OKAY;
356 }
357 
358 /** merges tomerge into finalchildren
359  *
360  * Both, tomerge and finalchildren contain expressions that could be the children of a simplified product
361  * (except for SP8 and SP10 which are enforced later).
362  * However, the concatenation of both lists will not in general yield a simplified product expression,
363  * because SP4, SP5 and SP14 could be violated. So the purpose of this method is to enforce SP4, SP5 and SP14.
364  * In the process of enforcing SP4, it could happen that SP2 is violated. Since enforcing SP2
365  * could generate further violations, we remove the affected children from finalchildren
366  * and include them in unsimplifiedchildren for further processing.
367  * @note if tomerge has more than one element, then they are the children of a simplified product expression
368  */
369 static
371  SCIP* scip, /**< SCIP data structure */
372  EXPRNODE* tomerge, /**< list to merge */
373  EXPRNODE** finalchildren, /**< pointer to store the result of merge between tomerge and *finalchildren */
374  EXPRNODE** unsimplifiedchildren,/**< the list of children that should go to the product expression;
375  * they are unsimplified when seen as children of a simplified product */
376  SCIP_Bool* changed, /**< pointer to store if some term actually got simplified */
377  SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), /**< function to call to create ownerdata */
378  void* ownercreatedata /**< data to pass to ownercreate */
379  )
380 {
381  EXPRNODE* tomergenode;
382  EXPRNODE* current;
383  EXPRNODE* previous;
384 
385  if( tomerge == NULL )
386  return SCIP_OKAY;
387 
388  if( *finalchildren == NULL )
389  {
390  *finalchildren = tomerge;
391  return SCIP_OKAY;
392  }
393 
394  tomergenode = tomerge;
395  current = *finalchildren;
396  previous = NULL;
397 
398  while( tomergenode != NULL && current != NULL )
399  {
400  int compareres;
401  EXPRNODE* aux;
402  SCIP_EXPR* base1;
403  SCIP_EXPR* base2;
404  SCIP_Real expo1;
405  SCIP_Real expo2;
406  SCIP_Bool issignpower1;
407  SCIP_Bool issignpower2;
408 
409  /* assert invariants */
410  assert(!SCIPisExprValue(scip, tomergenode->expr));
411  assert(!SCIPisExprValue(scip, current->expr));
412  assert(previous == NULL || previous->next == current);
413 
414  /* we are going to multiply the two exprs: current and tomergenode
415  * we first check if they are both exponentials
416  * if so, we multiply them
417  * otherwise, we interpret them as base^exponent
418  * the base of an expr is the expr itself
419  * if type(expr) != pow, otherwise it is the child of pow
420  */
421 
422  /* if both are exponentials, create a new exponential with the sum of their children */
423  if( SCIPisExprExp(scip, current->expr) && SCIPisExprExp(scip, tomergenode->expr) )
424  {
425  SCIP_EXPR* sum;
426  SCIP_EXPR* simplifiedsum;
427  SCIP_EXPR* expexpr;
428  SCIP_EXPR* simplifiedexp;
429 
430  /* inform that expressions changed */
431  *changed = TRUE;
432 
433  /* create sum */
434  SCIP_CALL( SCIPcreateExprSum(scip, &sum, 1, SCIPexprGetChildren(current->expr), NULL, 0.0, ownercreate, ownercreatedata) );
435  SCIP_CALL( SCIPappendExprSumExpr(scip, sum, SCIPexprGetChildren(tomergenode->expr)[0], 1.0) );
436 
437  /* simplify sum */
438  SCIP_CALL( SCIPcallExprSimplify(scip, sum, &simplifiedsum, ownercreate, ownercreatedata) );
439  SCIP_CALL( SCIPreleaseExpr(scip, &sum) );
440 
441  /* create exponential */
442  SCIP_CALL( SCIPcreateExprExp(scip, &expexpr, simplifiedsum, ownercreate, ownercreatedata) );
443  SCIP_CALL( SCIPreleaseExpr(scip, &simplifiedsum) );
444 
445  /* simplify exponential */
446  SCIP_CALL( SCIPcallExprSimplify(scip, expexpr, &simplifiedexp, ownercreate, ownercreatedata) );
447  SCIP_CALL( SCIPreleaseExpr(scip, &expexpr) );
448 
449  /* note that simplified exponential might be a product exp(x) * exp(-x + log(y*z)) -> y*z and so it is not a
450  * valid child of a simplified product; therefore we add it to the unsimplifiedchildren's list
451  */
452 
453  /* replace tomergenode's expression with simplifiedexp */
454  /* TODO: this code repeats below; add new function to avoid duplication */
455  SCIP_CALL( SCIPreleaseExpr(scip, &tomergenode->expr) );
456  tomergenode->expr = simplifiedexp;
457 
458  /* move tomergenode to unsimplifiedchildren */
459  aux = tomergenode;
460  tomergenode = tomergenode->next;
461  insertFirstList(aux, unsimplifiedchildren);
462 
463  /* remove current */
464  if( current == *finalchildren )
465  {
466  assert(previous == NULL);
467  aux = listPopFirst(finalchildren);
468  assert(aux == current);
469  current = *finalchildren;
470  }
471  else
472  {
473  assert(previous != NULL);
474  aux = current;
475  current = current->next;
476  previous->next = current;
477  }
478  SCIP_CALL( freeExprNode(scip, &aux) );
479 
480  continue;
481  }
482 
483  /* they were not exponentials, so collect bases and exponents */
484  if( SCIPisExprPower(scip, current->expr) )
485  {
486  base1 = SCIPexprGetChildren(current->expr)[0];
487  expo1 = SCIPgetExponentExprPow(current->expr);
488  issignpower1 = FALSE;
489  }
490  else if( SCIPisExprSignpower(scip, current->expr) )
491  {
492  base1 = SCIPexprGetChildren(current->expr)[0];
493  expo1 = SCIPgetExponentExprPow(current->expr);
494  issignpower1 = TRUE;
495  }
496  else
497  {
498  base1 = current->expr;
499  expo1 = 1.0;
500  issignpower1 = FALSE;
501  }
502  if( SCIPisExprPower(scip, tomergenode->expr) )
503  {
504  base2 = SCIPexprGetChildren(tomergenode->expr)[0];
505  expo2 = SCIPgetExponentExprPow(tomergenode->expr);
506  issignpower2 = FALSE;
507  }
508  else if( SCIPisExprSignpower(scip, tomergenode->expr) )
509  {
510  base2 = SCIPexprGetChildren(tomergenode->expr)[0];
511  expo2 = SCIPgetExponentExprPow(tomergenode->expr);
512  issignpower2 = TRUE;
513  }
514  else
515  {
516  base2 = tomergenode->expr;
517  expo2 = 1.0;
518  issignpower2 = FALSE;
519  }
520 
521  if( SCIPcompareExpr(scip, base1, base2) == 0 )
522  {
523  /* the bases are the same, so we should try to merge the multiplication of the powers */
524  SCIP_EXPR* power = NULL;
525 
526  if( !issignpower1 && !issignpower2 )
527  {
528  /* and both are normal power, then add to unsimplifiedchildren the resulting expr of simplify(base^(expo1 + expo2)) */
529 #if 0 /* TODO we should not loose the implicit base >= 0 constraint, if there is one, but then we should look at bounds on base; simplify currently doesn't */
530  /*
531  * unless expo1 or expo2 are fractional but expo1+expo2 is not fractional, then we better keep the original
532  * the reason for that is that x^fractional implies a constraint x >= 0
533  */
534  if( (EPSISINT(expo1, 0.0) && EPSISINT(expo2, 0.0)) || !EPSISINT(expo1+expo2, 0.0) ) /*lint !e835*/
535 #endif
536  {
537  SCIP_CALL( SCIPcreateExprPow(scip, &power, base1, expo1 + expo2, ownercreate, ownercreatedata) );
538  }
539  }
540  else if( issignpower1 ^ issignpower2 )
541  {
542  /* exactly one is signpower: sign(x) |x|^expo1 x^expo2 = sign(x)^(1+expo2) |x|^(expo1+expo2), with x = base */
543  if( EPSISINT(expo2, 0.0) ) /*lint !e835*/
544  {
545  if( (int)expo2 % 2 == 0 )
546  {
547  /* if expo2 is even, then sign(x)^(1+expo2) = sign(x), so we have signpower: sign(x) |x|^(expo1+expo2)
548  * TODO: we can remove this case distinction once the simplification of power expressions tranform
549  * |expr|^even -> expr^even, since the call to SCIPcallExprSimplify(scip, conshdlr, power,
550  * &simplifiedpower) below will take care of this.
551  */
552  SCIP_CALL( SCIPcreateExprSignpower(scip, &power, base1, expo1 + expo2, ownercreate, ownercreatedata) );
553  }
554  else
555  {
556  /* if expo2 is odd, then sign(x)^(1+expo2) = 1, so we have |x|^(expo1+expo2) */
557  SCIP_EXPR* absbase;
558 
559  SCIP_CALL( SCIPcreateExprAbs(scip, &absbase, base1, ownercreate, ownercreatedata) );
560  SCIP_CALL( SCIPcreateExprPow(scip, &power, absbase, expo1 + expo2, ownercreate, ownercreatedata) );
561  SCIP_CALL( SCIPreleaseExpr(scip, &absbase) );
562  }
563  }
564  else if( !EPSISINT(expo1+expo2, 0.0) ) /*lint !e835*/
565  {
566  /* if expo2 is fractional and expo1+expo2 is fractional, then we need x >= 0, so we can use x^(expo1+expo2) */
567  SCIP_CALL( SCIPcreateExprPow(scip, &power, base1, expo1 + expo2, ownercreate, ownercreatedata) );
568  }
569  /* else: expo2 is fractional but expo1+expo2 is integral, then we better do not do anything for now
570  * (leave power at NULL)
571  */
572  }
573  else
574  {
575  /* if both are signpower, then we have |base|^(expo1+expo2)
576  * if expo1+expo2 is even, then we can change this to base^(expo1+expo2)
577  */
578  if( EPSISINT(expo1+expo2, 0.0) && (int)(expo1+expo2)%2 == 0 ) /*lint !e835*/
579  {
580  SCIP_CALL( SCIPcreateExprPow(scip, &power, base1, expo1 + expo2, ownercreate, ownercreatedata) );
581  }
582  else
583  {
584  SCIP_EXPR* absbase;
585 
586  SCIP_CALL( SCIPcreateExprAbs(scip, &absbase, base1, ownercreate, ownercreatedata) );
587  SCIP_CALL( SCIPcreateExprPow(scip, &power, absbase, expo1 + expo2, ownercreate, ownercreatedata) );
588  SCIP_CALL( SCIPreleaseExpr(scip, &absbase) );
589  }
590  }
591 
592  if( power != NULL )
593  {
594  /* we have created a new power: simplify again and continue */
595  SCIP_EXPR* simplifiedpower;
596 
597  /* call simplifyPow or simplifySignpower */
598  SCIP_CALL( SCIPcallExprSimplify(scip, power, &simplifiedpower, ownercreate, ownercreatedata) );
599  SCIP_CALL( SCIPreleaseExpr(scip, &power) );
600 
601  /* replace tomergenode's expression with simplifiedpower */
602  SCIP_CALL( SCIPreleaseExpr(scip, &tomergenode->expr) );
603  tomergenode->expr = simplifiedpower;
604 
605  *changed = TRUE;
606 
607  /* move tomergenode to unsimplifiedchildren */
608  aux = tomergenode;
609  tomergenode = tomergenode->next;
610  insertFirstList(aux, unsimplifiedchildren);
611 
612  /* remove current */
613  if( current == *finalchildren )
614  {
615  assert(previous == NULL);
616  aux = listPopFirst(finalchildren);
617  assert(aux == current);
618  current = *finalchildren;
619  }
620  else
621  {
622  assert(previous != NULL);
623  aux = current;
624  current = current->next;
625  previous->next = current;
626  }
627  SCIP_CALL( freeExprNode(scip, &aux) );
628 
629  continue;
630  }
631  }
632 
633  /* bases are not the same, or we do not want to merge them
634  * then expressions cannot be the same
635  * therefore we need to insert tomergenode in finalchildren
636  * for this, we need to take care of the order
637  */
638  compareres = SCIPcompareExpr(scip, current->expr, tomergenode->expr);
639  if( compareres == -1 )
640  {
641  /* current < tomergenode => move current */
642  previous = current;
643  current = current->next;
644  }
645  else
646  {
647  *changed = TRUE;
648  assert(compareres == 1);
649 
650  /* insert: if current is the first node, then insert at beginning; otherwise, insert between previous and current */
651  if( current == *finalchildren )
652  {
653  assert(previous == NULL);
654  aux = tomergenode;
655  tomergenode = tomergenode->next;
656  insertFirstList(aux, finalchildren);
657  previous = *finalchildren;
658  }
659  else
660  {
661  assert(previous != NULL);
662  /* extract */
663  aux = tomergenode;
664  tomergenode = tomergenode->next;
665  /* insert */
666  previous->next = aux;
667  aux->next = current;
668  previous = aux;
669  }
670  }
671  }
672 
673  /* if all nodes of tomerge were merged, we are done */
674  if( tomergenode == NULL )
675  return SCIP_OKAY;
676 
677  assert(current == NULL);
678 
679  /* if all nodes of finalchildren were cancelled by nodes of tomerge (i.e., transfered to unsimplifiedchildren),
680  * then the rest of tomerge is finalchildren
681  */
682  if( *finalchildren == NULL )
683  {
684  assert(previous == NULL);
685  *finalchildren = tomergenode;
686  return SCIP_OKAY;
687  }
688 
689  /* there are still nodes of tomerge unmerged; these nodes are larger than finalchildren, so append at end */
690  assert(previous != NULL && previous->next == NULL);
691  previous->next = tomergenode;
692 
693  return SCIP_OKAY;
694 }
695 
696 /** simplifies the given (simplified) exprs so that they can be factors of a simplified product
697  *
698  * in particular, it will sort and multiply factors whose product leads to new expressions
699  */
700 static
702  SCIP* scip, /**< SCIP data structure */
703  SCIP_EXPR** exprs, /**< factors to be simplified */
704  int nexprs, /**< number of factors */
705  SCIP_Real* simplifiedcoef, /**< buffer to store coefficient of PI exprs; do not initialize */
706  EXPRNODE** finalchildren, /**< expr node list to store the simplified factors */
707  SCIP_Bool* changed, /**< buffer to store whether some factor changed */
708  SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), /**< function to call to create ownerdata */
709  void* ownercreatedata /**< data to pass to ownercreate */
710  )
711 {
712  EXPRNODE* unsimplifiedchildren;
713 
714  /* set up list of current children (when looking at each of them individually, they are simplified, but as
715  * children of a product expression they might be unsimplified)
716  */
717  unsimplifiedchildren = NULL;
718  SCIP_CALL( createExprlistFromExprs(scip, exprs, nexprs, &unsimplifiedchildren) );
719 
720  *changed = FALSE;
721 
722  /* while there are still children to process */
723  *finalchildren = NULL;
724  while( unsimplifiedchildren != NULL )
725  {
726  EXPRNODE* tomerge;
727  EXPRNODE* first;
728 
729  first = listPopFirst(&unsimplifiedchildren);
730  assert(first != NULL);
731 
732 #ifdef SIMPLIFY_DEBUG
733  debugSimplify("simplifying factor:\n");
734  SCIP_CALL( SCIPprintExpr(scip, first->expr, NULL) );
735  SCIPinfoMessage(scip, NULL, "\n");
736 #endif
737 
738  /* enforces SP2, SP7 and SP13 */
739  tomerge = NULL;
740  SCIP_CALL( simplifyFactor(scip, first->expr, simplifiedcoef, &tomerge, changed) );
741 
742  /* enforces SP4 and SP5 note: merge frees (or uses) the nodes of the tomerge list */
743  SCIP_CALL( mergeProductExprlist(scip, tomerge, finalchildren, &unsimplifiedchildren, changed, ownercreate, ownercreatedata) );
744 
745  /* free first */
746  SCIP_CALL( freeExprlist(scip, &first) );
747 
748  /* if the simplified coefficient is 0, we can return value 0 */
749  if( *simplifiedcoef == 0.0 )
750  {
751  *changed = TRUE;
752  SCIP_CALL( freeExprlist(scip, finalchildren) );
753  SCIP_CALL( freeExprlist(scip, &unsimplifiedchildren) );
754  assert(*finalchildren == NULL);
755  break;
756  }
757  }
758  return SCIP_OKAY;
759 }
760 
761 /* make sure product has at least two children
762  * - if it is empty; return value
763  * - if it has one child and coef = 1; return child
764  * - if it has one child and coef != 1; return (sum 0 coef expr)
765  */
766 static
768  SCIP* scip, /**< SCIP data structure */
769  SCIP_Real simplifiedcoef, /**< simplified product should be simplifiedcoef * PI simplifiedfactors */
770  EXPRNODE* finalchildren, /**< factors of simplified product */
771  SCIP_EXPR** simplifiedexpr, /**< buffer to store the simplified expression */
772  SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), /**< function to call to create ownerdata */
773  void* ownercreatedata /**< data to pass to ownercreate */
774  )
775 {
776  /* empty list --> return value */
777  if( finalchildren == NULL )
778  {
779  SCIP_CALL( SCIPcreateExprValue(scip, simplifiedexpr, simplifiedcoef, ownercreate, ownercreatedata) );
780  return SCIP_OKAY;
781  }
782 
783  /* one child and coef equal to 1 --> return child */
784  if( finalchildren->next == NULL && simplifiedcoef == 1.0 )
785  {
786  *simplifiedexpr = finalchildren->expr;
787  SCIPcaptureExpr(*simplifiedexpr);
788  return SCIP_OKAY;
789  }
790 
791  /* one child and coef different from 1 --> return (sum 0 coef child) */
792  if( finalchildren->next == NULL )
793  {
794  SCIP_EXPR* sum;
795 
796  SCIP_CALL( SCIPcreateExprSum(scip, &sum, 1, &(finalchildren->expr), &simplifiedcoef, 0.0, ownercreate, ownercreatedata) );
797 
798  /* simplifying here is necessary, the product could have sums as children e.g., (prod 2 (sum 1 <x>))
799  * -> (sum 0 2 (sum 1 <x>)) and that needs to be simplified to (sum 0 2 <x>)
800  */
801  SCIP_CALL( SCIPcallExprSimplify(scip, sum, simplifiedexpr, ownercreate, ownercreatedata) );
802  SCIP_CALL( SCIPreleaseExpr(scip, &sum) );
803  return SCIP_OKAY;
804  }
805 
806  return SCIP_OKAY;
807 }
808 
809 /** checks if it is entropy expression */
810 static
812  SCIP* scip, /**< SCIP data structure */
813  SCIP_Real simplifiedcoef, /**< simplified product should be simplifiedcoef * PI simplifiedfactors */
814  EXPRNODE* finalchildren, /**< factors of simplified product */
815  SCIP_EXPR** simplifiedexpr, /**< buffer to store the simplified expression */
816  SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), /**< function to call to create ownerdata */
817  void* ownercreatedata /**< data to pass to ownercreate */
818  )
819 {
820  SCIP_EXPR* entropicchild = NULL;
821 
822  if( !(finalchildren != NULL && finalchildren->next != NULL && finalchildren->next->next == NULL) )
823  return SCIP_OKAY;
824 
825  /* could be log(expr) * expr, e.g., log(sin(x)) * sin(x) (OR11) */
826  if( strcmp(SCIPexprhdlrGetName(SCIPexprGetHdlr(finalchildren->expr)), "log") == 0 )
827  {
828  assert(SCIPexprGetNChildren(finalchildren->expr) == 1);
829  if( 0 == SCIPcompareExpr(scip, SCIPexprGetChildren(finalchildren->expr)[0], finalchildren->next->expr) )
830  entropicchild = finalchildren->next->expr;
831  }
832  /* could be expr * log(expr), e.g., (1 + abs(x)) log(1 + abs(x)) (OR11) */
833  else if( strcmp(SCIPexprhdlrGetName(SCIPexprGetHdlr(finalchildren->next->expr)), "log") == 0 )
834  {
835  assert(SCIPexprGetNChildren(finalchildren->next->expr) == 1);
836  if( 0 == SCIPcompareExpr(scip, SCIPexprGetChildren(finalchildren->next->expr)[0], finalchildren->expr) )
837  entropicchild = finalchildren->expr;
838  }
839 
840  /* success --> replace finalchildren by entropy expression */
841  if( entropicchild != NULL )
842  {
843  SCIP_EXPR* entropy;
844 
845  simplifiedcoef *= -1.0;
846 
847  SCIP_CALL( SCIPcreateExprEntropy(scip, &entropy, entropicchild, ownercreate, ownercreatedata) );
848 
849  /* enforces SP8: if simplifiedcoef != 1.0, transform it into a sum with the (simplified) entropy as child */
850  if( simplifiedcoef != 1.0 )
851  {
852  SCIP_CALL( SCIPcreateExprSum(scip, simplifiedexpr, 1, &entropy, &simplifiedcoef, 0.0, ownercreate, ownercreatedata) );
853  SCIP_CALL( SCIPreleaseExpr(scip, &entropy) );
854  }
855  else
856  *simplifiedexpr = entropy;
857  }
858 
859  return SCIP_OKAY;
860 }
861 
862 /* expands product of two sums or one sum and another expression
863  * -) two sums: (prod (sum c1 s1 ... sn) (sum c2 t1 ... tm)
864  * Builds a sum representing the expansion, where all of its children are simplified, and then simplify the sum
865  * - constant != 0 --> c1 ti or c2 * sj is simplified (ti, sj are not sums, because they are children of a simplified sum)
866  * - sj * ti may be not be simplified, so put them in a product list and simplify them from there
867  * -) one sum: (prod factor (sum c s1 ... sn))
868  * - c != 0 --> c * factor is simplified (i.e. factor is not sum!)
869  * - factor * si may be not be simplified, so put them in a product list and simplify them from there
870  */
871 static
873  SCIP* scip, /**< SCIP data structure */
874  SCIP_Real simplifiedcoef, /**< simplified product should be simplifiedcoef * PI simplifiedfactors */
875  EXPRNODE* finalchildren, /**< factors of simplified product */
876  SCIP_EXPR** simplifiedexpr, /**< buffer to store the simplified expression */
877  SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), /**< function to call to create ownerdata */
878  void* ownercreatedata /**< data to pass to ownercreate */
879  )
880 {
881  /* we need only two children */
882  if( ! (finalchildren != NULL && finalchildren->next != NULL && finalchildren->next->next == NULL) )
883  return SCIP_OKAY;
884 
885  /* handle both sums case */
886  if( SCIPisExprSum(scip, finalchildren->expr) && SCIPisExprSum(scip, finalchildren->next->expr) )
887  {
888  SCIP_EXPR* expanded = NULL;
889  SCIP_Real c1 = SCIPgetConstantExprSum(finalchildren->expr);
890  SCIP_Real c2 = SCIPgetConstantExprSum(finalchildren->next->expr);
891  int nchildren1 = SCIPexprGetNChildren(finalchildren->expr);
892  int nchildren2 = SCIPexprGetNChildren(finalchildren->next->expr);
893  int j;
894  int k;
895 
896 #ifdef SIMPLIFY_DEBUG
897  debugSimplify("Multiplying sum1 * sum2\n");
898  debugSimplify("sum1: \n");
899  SCIP_CALL( SCIPprintExpr(scip, finalchildren->expr, NULL) );
900  SCIPinfoMessage(scip, NULL, "\n");
901  debugSimplify("sum2: \n");
902  SCIP_CALL( SCIPprintExpr(scip, finalchildren->next->expr, NULL) );
903  SCIPinfoMessage(scip, NULL, "\n");
904 #endif
905  SCIP_CALL( SCIPcreateExprSum(scip, &expanded, 0, NULL, NULL, c1 * c2 * simplifiedcoef, ownercreate, ownercreatedata) );
906 
907  /* multiply c1 * sum2 */
908  if( c1 != 0.0 )
909  {
910  int i;
911 
912  for( i = 0; i < nchildren2; ++i )
913  {
914  SCIP_EXPR* term;
915 
916  term = SCIPexprGetChildren(finalchildren->next->expr)[i];
917  SCIP_CALL( SCIPappendExprSumExpr(scip, expanded, term, SCIPgetCoefsExprSum(finalchildren->next->expr)[i] * c1 * simplifiedcoef) );
918  /* we are just re-using a child here, so do not release term! */
919 #ifdef SIMPLIFY_DEBUG
920  debugSimplify("Multiplying %f * summand2_i\n", c1);
921  debugSimplify("summand2_i: \n");
922  SCIP_CALL( SCIPprintExpr(scip, term, NULL) );
923  SCIPinfoMessage(scip, NULL, "\n");
924 #endif
925  }
926  }
927  /* multiply c2 * sum1 */
928  if( c2 != 0.0 )
929  {
930  int i;
931 
932  for( i = 0; i < nchildren1; ++i )
933  {
934  SCIP_EXPR* term;
935 
936  term = SCIPexprGetChildren(finalchildren->expr)[i];
937  SCIP_CALL( SCIPappendExprSumExpr(scip, expanded, term, SCIPgetCoefsExprSum(finalchildren->expr)[i] * c2 * simplifiedcoef) );
938  /* we are just re-using a child here, so do not release term! */
939 #ifdef SIMPLIFY_DEBUG
940  debugSimplify("Multiplying summand1_i * %f\n", c2);
941  debugSimplify("summand1_i: \n");
942  SCIP_CALL( SCIPprintExpr(scip, conshdlr, term, NULL) );
943  SCIPinfoMessage(scip, NULL, "\n");
944 #endif
945  }
946  }
947  /* multiply sum1 * sum2 without constants */
948  for( j = 0; j < nchildren1; ++j )
949  {
950  SCIP_EXPR* factors[2];
951  SCIP_Real coef1;
952 
953  coef1 = SCIPgetCoefsExprSum(finalchildren->expr)[j];
954  factors[0] = SCIPexprGetChildren(finalchildren->expr)[j];
955  for( k = 0; k < nchildren2; ++k )
956  {
957  EXPRNODE* finalfactors;
958  SCIP_Real factorscoef;
959  SCIP_Real coef2;
960  SCIP_EXPR* term = NULL;
961  SCIP_Bool dummy;
962 
963  coef2 = SCIPgetCoefsExprSum(finalchildren->next->expr)[k];
964  factors[1] = SCIPexprGetChildren(finalchildren->next->expr)[k];
965 
966 #ifdef SIMPLIFY_DEBUG
967  debugSimplify("multiplying %g expr1 * %g expr2\n", coef1, coef2);
968  debugSimplify("expr1:\n");
969  SCIP_CALL( SCIPprintExpr(scip, factors[0], NULL) );
970  SCIPinfoMessage(scip, NULL, "\n");
971  debugSimplify("expr2\n");
972  SCIP_CALL( SCIPprintExpr(scip, factors[1], NULL) );
973  SCIPinfoMessage(scip, NULL, "\n");
974 #endif
975 
976  factorscoef = coef1 * coef2;
977  SCIP_CALL( simplifyMultiplyChildren(scip, factors, 2, &factorscoef, &finalfactors, &dummy, ownercreate, ownercreatedata) );
978  assert(factorscoef != 0.0);
979 
980 #ifdef SIMPLIFY_DEBUG
981  {
982  EXPRNODE* node;
983  int i;
984 
985  debugSimplify("Building product from simplified factors\n");
986  node = finalfactors;
987  i = 0;
988  while( node != NULL )
989  {
990  debugSimplify("factor %d (nuses %d):\n", i, SCIPexprGetNUses(node->expr));
991  SCIP_CALL( SCIPprintExpr(scip, node->expr, NULL) );
992  SCIPinfoMessage(scip, NULL, "\n");
993  node = node->next;
994  i++;
995  }
996  }
997 #endif
998 
999  SCIP_CALL( buildSimplifiedProduct(scip, 1.0, &finalfactors, TRUE, &term, ownercreate, ownercreatedata) );
1000  assert(finalfactors == NULL);
1001  assert(term != NULL);
1002 
1003 #ifdef SIMPLIFY_DEBUG
1004  debugSimplify("%g expr1 * %g expr2 = %g * product\n", coef1, coef2, coef1 * coef2);
1005  debugSimplify("product: (nused %d)\n", SCIPexprGetNUses(term));
1006  SCIP_CALL( SCIPprintExpr(scip, term, NULL) );
1007  SCIPinfoMessage(scip, NULL, "\n");
1008 #endif
1009 
1010  SCIP_CALL( SCIPappendExprSumExpr(scip, expanded, term, factorscoef * simplifiedcoef) );
1011 
1012  SCIP_CALL( SCIPreleaseExpr(scip, &term) );
1013  }
1014  }
1015 
1016  /* simplify the sum */
1017  SCIP_CALL( SCIPcallExprSimplify(scip, expanded, simplifiedexpr, ownercreate, ownercreatedata) );
1018  SCIP_CALL( SCIPreleaseExpr(scip, &expanded) );
1019 
1020  return SCIP_OKAY;
1021  }
1022 
1023  /* handle one sum case */
1024  if( SCIPisExprSum(scip, finalchildren->expr) || SCIPisExprSum(scip, finalchildren->next->expr) )
1025  {
1026  SCIP_EXPR* expanded = NULL;
1027  SCIP_EXPR* factors[2];
1028  SCIP_EXPR* sum = NULL;
1029  SCIP_Real constant;
1030  int nchildren;
1031  int j;
1032 
1033  if( SCIPisExprSum(scip, finalchildren->expr) )
1034  {
1035  assert(!SCIPisExprSum(scip, finalchildren->next->expr));
1036  sum = finalchildren->expr;
1037  factors[0] = finalchildren->next->expr;
1038  }
1039  else
1040  {
1041  assert(!SCIPisExprSum(scip, finalchildren->expr));
1042  sum = finalchildren->next->expr;
1043  factors[0] = finalchildren->expr;
1044  }
1045  constant = simplifiedcoef * SCIPgetConstantExprSum(sum);
1046  nchildren = SCIPexprGetNChildren(sum);
1047 
1048  SCIP_CALL( SCIPcreateExprSum(scip, &expanded, 1, &factors[0], &constant, 0.0, ownercreate, ownercreatedata) );
1049  /* we are just re-using a child here, so do not release factor! */
1050 
1051  for( j = 0; j < nchildren; ++j )
1052  {
1053  SCIP_Real coef;
1054  SCIP_Real termcoef;
1055  SCIP_Bool dummy;
1056  EXPRNODE* finalfactors;
1057  SCIP_EXPR* term = NULL;
1058 
1059  coef = SCIPgetCoefsExprSum(sum)[j];
1060  factors[1] = SCIPexprGetChildren(sum)[j];
1061 
1062  termcoef = coef;
1063  SCIP_CALL( simplifyMultiplyChildren(scip, factors, 2, &termcoef, &finalfactors, &dummy, ownercreate, ownercreatedata) );
1064  assert(termcoef != 0.0);
1065 
1066  SCIP_CALL( buildSimplifiedProduct(scip, 1.0, &finalfactors, TRUE, &term, ownercreate, ownercreatedata) );
1067  assert(finalfactors == NULL);
1068  assert(term != NULL);
1069 
1070  SCIP_CALL( SCIPappendExprSumExpr(scip, expanded, term, termcoef * simplifiedcoef) );
1071  SCIP_CALL( SCIPreleaseExpr(scip, &term) );
1072  }
1073 
1074  /* simplify the sum */
1075  SCIP_CALL( SCIPcallExprSimplify(scip, expanded, simplifiedexpr, ownercreate, ownercreatedata) );
1076  SCIP_CALL( SCIPreleaseExpr(scip, &expanded) );
1077  }
1078 
1079  return SCIP_OKAY;
1080 }
1081 
1082 /** builds a simplified product from simplifiedfactors
1083  *
1084  * @note this function also releases simplifiedfactors
1085  */
1086 static
1088  SCIP* scip, /**< SCIP data structure */
1089  SCIP_Real simplifiedcoef, /**< simplified product should be simplifiedcoef * PI simplifiedfactors */
1090  EXPRNODE** simplifiedfactors, /**< factors of simplified product */
1091  SCIP_Bool changed, /**< indicates whether some of the simplified factors was changed */
1092  SCIP_EXPR** simplifiedexpr, /**< buffer to store the simplified expression */
1093  SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), /**< function to call to create ownerdata */
1094  void* ownercreatedata /**< data to pass to ownercreate */
1095  )
1096 {
1097  EXPRNODE* finalchildren = *simplifiedfactors;
1098 
1099  /* build product expression from finalchildren and post-simplify */
1100  debugSimplify("[simplifyProduct] finalchildren has length %d\n", listLength(finalchildren));
1101 
1102  *simplifiedexpr = NULL;
1103 
1104  SCIP_CALL( enforceSP11(scip, simplifiedcoef, *simplifiedfactors, simplifiedexpr, ownercreate, ownercreatedata) );
1105  if( *simplifiedexpr != NULL )
1106  goto CLEANUP;
1107 
1108  SCIP_CALL( enforceSP12(scip, simplifiedcoef, *simplifiedfactors, simplifiedexpr, ownercreate, ownercreatedata) );
1109  if( *simplifiedexpr != NULL )
1110  goto CLEANUP;
1111 
1112  SCIP_CALL( enforceSP10(scip, simplifiedcoef, *simplifiedfactors, simplifiedexpr, ownercreate, ownercreatedata) );
1113  if( *simplifiedexpr != NULL )
1114  goto CLEANUP;
1115 
1116  /* enforces SP8: if simplifiedcoef != 1.0, transform it into a sum with the (simplified) product as child */
1117  if( simplifiedcoef != 1.0 )
1118  {
1119  SCIP_EXPR* aux;
1120  SCIP_EXPR* sum;
1121 
1122  /* create sum */
1123  SCIP_CALL( createExprProductFromExprlist(scip, finalchildren, 1.0, &aux, ownercreate, ownercreatedata) );
1124  SCIP_CALL( SCIPcreateExprSum(scip, &sum, 1, &aux, &simplifiedcoef, 0.0, ownercreate, ownercreatedata) );
1125  SCIP_CALL( SCIPreleaseExpr(scip, &aux) );
1126 
1127  /* simplify sum */
1128  SCIP_CALL( SCIPcallExprSimplify(scip, sum, simplifiedexpr, ownercreate, ownercreatedata) );
1129  SCIP_CALL( SCIPreleaseExpr(scip, &sum) );
1130 
1131  goto CLEANUP;
1132  }
1133 
1134  /* build product expression from list */
1135  if( changed )
1136  {
1137  SCIP_CALL( createExprProductFromExprlist(scip, finalchildren, simplifiedcoef, simplifiedexpr, ownercreate, ownercreatedata) );
1138  goto CLEANUP;
1139  }
1140 
1141 CLEANUP:
1142 
1143  SCIP_CALL( freeExprlist(scip, simplifiedfactors) );
1144  return SCIP_OKAY;
1145 }
1146 
1147 /** computes an estimator for a product as a vertex polyhedral function
1148  *
1149  * Since the product is multilinear, its convex and concave envelopes are piecewise linear.
1150  */
1151 static
1153  SCIP* scip, /**< SCIP data structure */
1154  SCIP_CONSHDLR* conshdlr, /**< nonlinear constraint handler */
1155  int nfactors, /**< number of factors */
1156  SCIP_INTERVAL* bounds, /**< bound for each factor */
1157  SCIP_Real constantfactor, /**< another constant factor */
1158  SCIP_Real* refpoint, /**< reference point where to estimate, or NULL if called from initestimates */
1159  SCIP_Bool overestimate, /**< should estimator overestimate expr (TRUE) or underestimate (FALSE) */
1160  SCIP_Real targetvalue, /**< no need to compute facet if value in xstar would be worse than target value */
1161  SCIP_Real* coefs, /**< array to store cut coefficients */
1162  SCIP_Real* constant, /**< pointer to store cut constant */
1163  SCIP_Bool* success /**< pointer to store whether estimation was successful */
1164  )
1165 {
1166  SCIP_Real* box;
1167  SCIP_Real* xstar;
1168  int nfixed;
1169  int i;
1170 
1171  assert(conshdlr != NULL);
1172  assert(nfactors > 0);
1173  assert(bounds != NULL);
1174  assert(constantfactor != 0.0);
1175  assert(coefs != NULL);
1176  assert(constant != NULL);
1177  assert(success != NULL);
1178 
1179  *success = FALSE;
1180 
1181  /* assemble box, check for unbounded variables, assemble xstar */
1182  SCIP_CALL( SCIPallocBufferArray(scip, &box, 2*nfactors) );
1183  SCIP_CALL( SCIPallocBufferArray(scip, &xstar, nfactors) );
1184  for( i = 0, nfixed = 0; i < nfactors; ++i )
1185  {
1186  assert(!SCIPintervalIsEmpty(SCIP_INTERVAL_INFINITY, bounds[i]));
1187 
1188  if( SCIPisInfinity(scip, -bounds[i].inf) || SCIPisInfinity(scip, bounds[i].sup) )
1189  {
1190  SCIPdebugMsg(scip, "a factor is unbounded, no cut is possible\n");
1191  goto CLEANUP;
1192  }
1193 
1194  box[2*i] = bounds[i].inf;
1195  box[2*i+1] = bounds[i].sup;
1196 
1197  xstar[i] = refpoint != NULL ? refpoint[i] : 0.5 * (box[2*i] + box[2*i+1]);
1198 
1199  if( SCIPisRelEQ(scip, box[2*i], box[2*i+1]) )
1200  ++nfixed;
1201  }
1202 
1203  if( nfixed < nfactors && nfactors - nfixed <= SCIP_MAXVERTEXPOLYDIM )
1204  {
1206  overestimate, prodfunction, &constantfactor, xstar, box, nfactors, targetvalue, success, coefs, constant) );
1207  }
1208 
1209 CLEANUP:
1210  SCIPfreeBufferArray(scip, &xstar);
1211  SCIPfreeBufferArray(scip, &box);
1212 
1213  return SCIP_OKAY;
1214 }
1215 
1216 /*
1217  * Callback methods of expression handler
1218  */
1219 
1220 /** simplifies a product expression
1221  *
1222  * Summary: we first build a list of expressions (called finalchildren) which will be the children of the simplified product
1223  * and then we process this list in order to enforce SP8 and SP10.
1224  *
1225  * Description: In order to build finalchildren, we first build a list of unsimplified children (called unsimplifiedchildren)
1226  * with the children of the product. Each node of the list is manipulated (see simplifyFactor) in order to satisfy
1227  * SP2 and SP7 as follows:
1228  * - SP7: if the node's expression is a value, multiply the value to the products's coef
1229  * - SP2: if the node's expression is a product, then build a list with the child's children
1230  *
1231  * Then, we merge the built list (or the simplified node) into finalchildren. While merging, nodes from finalchildren
1232  * can go back to unsimplifiedchildren for further processing (see mergeProductExprlist() for more details).
1233  * After building finalchildren, we create the simplified product out of it, taking care that SP8 and SP10 are satisfied
1234  */
1235 static
1236 SCIP_DECL_EXPRSIMPLIFY(simplifyProduct)
1237 { /*lint --e{715}*/
1238  EXPRNODE* finalchildren;
1239  SCIP_Real simplifiedcoef;
1240  SCIP_Bool changed;
1241 
1242  assert(expr != NULL);
1243  assert(simplifiedexpr != NULL);
1244 
1245  simplifiedcoef = SCIPgetCoefExprProduct(expr);
1246 
1247 #ifdef SIMPLIFY_DEBUG
1248  debugSimplify("Simplifying expr:\n");
1249  SCIP_CALL( SCIPprintExpr(scip, expr, NULL) );
1250  SCIPinfoMessage(scip, NULL, "\n");
1251  debugSimplify("First multiplying children\n");
1252 #endif
1253 
1254  /* simplify and multiply factors */
1255  SCIP_CALL( simplifyMultiplyChildren(scip, SCIPexprGetChildren(expr), SCIPexprGetNChildren(expr), &simplifiedcoef,
1256  &finalchildren, &changed, ownercreate, ownercreatedata) );
1257 
1258 #ifdef SIMPLIFY_DEBUG
1259  {
1260  EXPRNODE* node;
1261  int i;
1262 
1263  debugSimplify("Building product from simplified factors\n");
1264  node = finalchildren;
1265  i = 0;
1266  while( node != NULL )
1267  {
1268  debugSimplify("factor %d:\n", i);
1269  SCIP_CALL( SCIPprintExpr(scip, node->expr, NULL) );
1270  SCIPinfoMessage(scip, NULL, "\n");
1271  node = node->next;
1272  i++;
1273  }
1274  }
1275 #endif
1276 
1277  /* get simplified product from simplified factors in finalchildren */
1278  SCIP_CALL( buildSimplifiedProduct(scip, simplifiedcoef, &finalchildren, changed, simplifiedexpr, ownercreate,
1279  ownercreatedata) );
1280  assert(finalchildren == NULL);
1281 
1282  if( *simplifiedexpr == NULL )
1283  {
1284  *simplifiedexpr = expr;
1285 
1286  /* we have to capture it, since it must simulate a "normal" simplified call in which a new expression is created */
1287  SCIPcaptureExpr(*simplifiedexpr);
1288  }
1289  assert(*simplifiedexpr != NULL);
1290 
1291  return SCIP_OKAY;
1292 }
1293 
1294 /** compare two product expressions
1295  *
1296  * The order of two product expressions, u and v, is a lexicographical order on the factors.
1297  *
1298  * Starting from the *last*, we find the first child where they differ, say, the i-th.
1299  * Then u < v <=> u_i < v_i.
1300  * If there is no such children and they have different number of children, then u < v <=> nchildren(u) < nchildren(v).
1301  * If all children are the same and they have the same number of children, then u < v <=> coeff(u) < coeff(v).
1302  * Otherwise, they are the same.
1303  *
1304  * Note: we are assuming expression are simplified, so within u, we have u_1 < u_2, etc.
1305  *
1306  * Example: y * z < x * y * z
1307  */
1308 static
1309 SCIP_DECL_EXPRCOMPARE(compareProduct)
1310 { /*lint --e{715}*/
1311  int compareresult;
1312  int i;
1313  int j;
1314  int nchildren1;
1315  int nchildren2;
1316  SCIP_EXPR** children1;
1317  SCIP_EXPR** children2;
1318 
1319  nchildren1 = SCIPexprGetNChildren(expr1);
1320  nchildren2 = SCIPexprGetNChildren(expr2);
1321  children1 = SCIPexprGetChildren(expr1);
1322  children2 = SCIPexprGetChildren(expr2);
1323 
1324  for( i = nchildren1 - 1, j = nchildren2 - 1; i >= 0 && j >= 0; --i, --j )
1325  {
1326  compareresult = SCIPcompareExpr(scip, children1[i], children2[j]);
1327  if( compareresult != 0 )
1328  return compareresult;
1329  /* expressions are equal, continue */
1330  }
1331 
1332  /* all children of one expression are children of the other expression, use number of children as a tie-breaker */
1333  if( i < j )
1334  {
1335  assert(i == -1);
1336  /* expr1 has less elements, hence expr1 < expr2 */
1337  return -1;
1338  }
1339  if( i > j )
1340  {
1341  assert(j == -1);
1342  /* expr1 has more elements, hence expr1 > expr2 */
1343  return 1;
1344  }
1345 
1346  /* everything is equal, use coefficient as tie-breaker */
1347  assert(i == -1 && j == -1);
1348  if( SCIPgetCoefExprProduct(expr1) < SCIPgetCoefExprProduct(expr2) )
1349  return -1;
1350  if( SCIPgetCoefExprProduct(expr1) > SCIPgetCoefExprProduct(expr2) )
1351  return 1;
1352 
1353  /* they are equal */
1354  return 0;
1355 }
1356 
1357 /** expression handler copy callback */
1358 static
1359 SCIP_DECL_EXPRCOPYHDLR(copyhdlrProduct)
1360 { /*lint --e{715}*/
1362 
1363  return SCIP_OKAY;
1364 }
1365 
1366 /** expression handler free callback */
1367 static
1368 SCIP_DECL_EXPRFREEHDLR(freehdlrProduct)
1369 { /*lint --e{715}*/
1370  assert(scip != NULL);
1371  assert(exprhdlr != NULL);
1372  assert(exprhdlrdata != NULL);
1373  assert(*exprhdlrdata != NULL);
1374 
1375  SCIPfreeBlockMemory(scip, exprhdlrdata);
1376  assert(*exprhdlrdata == NULL);
1377 
1378  return SCIP_OKAY;
1379 }
1380 
1381 /** expression data copy callback */
1382 static
1383 SCIP_DECL_EXPRCOPYDATA(copydataProduct)
1384 { /*lint --e{715}*/
1385  SCIP_EXPRDATA* sourceexprdata;
1386 
1387  assert(targetexprdata != NULL);
1388  assert(sourceexpr != NULL);
1389 
1390  sourceexprdata = SCIPexprGetData(sourceexpr);
1391  assert(sourceexprdata != NULL);
1392 
1393  SCIP_CALL( SCIPduplicateBlockMemory(targetscip, targetexprdata, sourceexprdata) );
1394 
1395  return SCIP_OKAY;
1396 }
1397 
1398 /** expression data free callback */
1399 static
1400 SCIP_DECL_EXPRFREEDATA(freedataProduct)
1401 { /*lint --e{715}*/
1402  SCIP_EXPRDATA* exprdata;
1403 
1404  assert(expr != NULL);
1405 
1406  exprdata = SCIPexprGetData(expr);
1407  assert(exprdata != NULL);
1408 
1409  SCIPfreeBlockMemory(scip, &exprdata);
1410 
1411  SCIPexprSetData(expr, NULL);
1412 
1413  return SCIP_OKAY;
1414 }
1415 
1416 /** expression print callback */
1417 static
1418 SCIP_DECL_EXPRPRINT(printProduct)
1419 { /*lint --e{715}*/
1420  SCIP_EXPRDATA* exprdata;
1421 
1422  assert(expr != NULL);
1423 
1424  exprdata = SCIPexprGetData(expr);
1425  assert(exprdata != NULL);
1426 
1427  switch( stage )
1428  {
1430  {
1431  /* print opening parenthesis, if necessary */
1432  if( EXPRHDLR_PRECEDENCE <= parentprecedence )
1433  {
1434  SCIPinfoMessage(scip, file, "(");
1435  }
1436 
1437  /* print coefficient, if not one */
1438  if( exprdata->coefficient != 1.0 )
1439  {
1440  if( exprdata->coefficient < 0.0 && EXPRHDLR_PRECEDENCE > parentprecedence )
1441  {
1442  SCIPinfoMessage(scip, file, "(%g)", exprdata->coefficient);
1443  }
1444  else
1445  {
1446  SCIPinfoMessage(scip, file, "%g", exprdata->coefficient);
1447  }
1448  }
1449  break;
1450  }
1451 
1453  {
1454  /* print multiplication sign, if not first factor */
1455  if( exprdata->coefficient != 1.0 || currentchild > 0 )
1456  {
1457  SCIPinfoMessage(scip, file, "*");
1458  }
1459  break;
1460  }
1461 
1463  {
1464  break;
1465  }
1466 
1468  {
1469  /* print closing parenthesis, if necessary */
1470  if( EXPRHDLR_PRECEDENCE <= parentprecedence )
1471  {
1472  SCIPinfoMessage(scip, file, ")");
1473  }
1474  break;
1475  }
1476 
1477  default:
1478  /* all stages should have been covered above */
1479  SCIPABORT();
1480  }
1481 
1482  return SCIP_OKAY;
1483 }
1484 
1485 /** product hash callback */
1486 static
1488 { /*lint --e{715}*/
1489  SCIP_EXPRDATA* exprdata;
1490  int c;
1491 
1492  assert(scip != NULL);
1493  assert(expr != NULL);
1494  assert(hashkey != NULL);
1495  assert(childrenhashes != NULL);
1496 
1497  exprdata = SCIPexprGetData(expr);
1498  assert(exprdata != NULL);
1499 
1500  *hashkey = EXPRHDLR_HASHKEY;
1501  *hashkey ^= SCIPcalcFibHash(exprdata->coefficient);
1502 
1503  for( c = 0; c < SCIPexprGetNChildren(expr); ++c )
1504  *hashkey ^= childrenhashes[c];
1505 
1506  return SCIP_OKAY;
1507 }
1508 
1509 /** expression point evaluation callback */
1510 static
1512 { /*lint --e{715}*/
1513  SCIP_EXPRDATA* exprdata;
1514  SCIP_Real childval;
1515  int c;
1516 
1517  assert(expr != NULL);
1518 
1519  exprdata = SCIPexprGetData(expr);
1520  assert(exprdata != NULL);
1521 
1522  *val = exprdata->coefficient;
1523  for( c = 0; c < SCIPexprGetNChildren(expr) && (*val != 0.0); ++c )
1524  {
1525  childval = SCIPexprGetEvalValue(SCIPexprGetChildren(expr)[c]);
1526  assert(childval != SCIP_INVALID);
1527 
1528  *val *= childval;
1529  }
1530 
1531  return SCIP_OKAY;
1532 }
1533 
1534 /** derivative evaluation callback computing <gradient, children.dot>
1535  *
1536  * If expr is \f$\prod_i x_i\f$, then computes \f$\sum_j \prod_{i\neq j} x_i x^{\text{dot}}_j\f$.
1537  */
1538 static
1539 SCIP_DECL_EXPRFWDIFF(fwdiffProduct)
1540 { /*lint --e{715}*/
1541  int c;
1542 
1543  assert(expr != NULL);
1544  assert(dot != NULL);
1545 
1546  assert(SCIPexprGetData(expr) != NULL);
1547 
1548  /* TODO add special handling for nchildren == 2 */
1549 
1550  /**! [SnippetExprFwdiffProduct] */
1551  *dot = 0.0;
1552  for( c = 0; c < SCIPexprGetNChildren(expr); ++c )
1553  {
1554  SCIP_EXPR* child;
1555 
1556  child = SCIPexprGetChildren(expr)[c];
1557 
1558  assert(SCIPexprGetEvalValue(child) != SCIP_INVALID);
1559  assert(SCIPexprGetDot(child) != SCIP_INVALID);
1560 
1561  if( SCIPexprGetDot(child) == 0.0 )
1562  continue;
1563 
1564  if( SCIPexprGetEvalValue(child) != 0.0 )
1565  *dot += SCIPexprGetEvalValue(expr) / SCIPexprGetEvalValue(child) * SCIPexprGetDot(child);
1566  else
1567  {
1568  SCIP_Real partial;
1569  int i;
1570 
1571  partial = SCIPexprGetData(expr)->coefficient;
1572  for( i = 0; i < SCIPexprGetNChildren(expr) && (partial != 0.0); ++i )
1573  {
1574  if( i == c )
1575  continue;
1576 
1577  partial *= SCIPexprGetEvalValue(SCIPexprGetChildren(expr)[i]);
1578  }
1579  *dot += partial * SCIPexprGetDot(child);
1580  }
1581  }
1582  /**! [SnippetExprFwdiffProduct] */
1583 
1584  return SCIP_OKAY;
1585 }
1586 
1587 /** expression backward forward derivative evaluation callback
1588  *
1589  * Computes \f$\frac{\partial}{\partial \text{childidx}} ( \langle \text{gradient}, \text{children.dot}\rangle )\f$.
1590  *
1591  * If expr is \f$\prod_i x_i\f$, and childidx is \f$k\f$ then computes
1592  * \f$\partial_k \sum_j \prod_{i \neq j} x_i x^{\text{dot}}_j
1593  * = \sum_{j \neq k} \prod_{i \neq j, k} x_i x^{\text{dot}}_j\f$
1594  */
1595 static
1596 SCIP_DECL_EXPRBWFWDIFF(bwfwdiffProduct)
1597 { /*lint --e{715}*/
1598  SCIP_EXPR* partialchild;
1599  int c;
1600 
1601  assert(expr != NULL);
1602  assert(bardot != NULL);
1603  assert(SCIPexprGetData(expr) != NULL);
1604  assert(childidx >= 0 && childidx < SCIPexprGetNChildren(expr));
1605 
1606  partialchild = SCIPexprGetChildren(expr)[childidx];
1607  assert(partialchild != NULL);
1608  assert(!SCIPisExprValue(scip, partialchild));
1609  assert(SCIPexprGetEvalValue(partialchild) != SCIP_INVALID);
1610 
1611  /* TODO add special handling for nchildren == 2 */
1612 
1613  /**! [SnippetExprBwfwdiffProduct] */
1614  *bardot = 0.0;
1615  for( c = 0; c < SCIPexprGetNChildren(expr); ++c )
1616  {
1617  SCIP_EXPR* child;
1618 
1619  if( c == childidx )
1620  continue;
1621 
1622  child = SCIPexprGetChildren(expr)[c];
1623 
1624  assert(SCIPexprGetEvalValue(child) != SCIP_INVALID);
1625  assert(SCIPexprGetDot(child) != SCIP_INVALID);
1626 
1627  if( SCIPexprGetDot(child) == 0.0 )
1628  continue;
1629 
1630  if( SCIPexprGetEvalValue(child) != 0.0 && SCIPexprGetEvalValue(partialchild) != 0.0 )
1631  *bardot += SCIPexprGetEvalValue(expr) / (SCIPexprGetEvalValue(child) * SCIPexprGetEvalValue(partialchild)) * SCIPexprGetDot(child);
1632  else
1633  {
1634  SCIP_Real partial;
1635  int i;
1636 
1637  partial = SCIPexprGetData(expr)->coefficient;
1638  for( i = 0; i < SCIPexprGetNChildren(expr) && (partial != 0.0); ++i )
1639  {
1640  if( i == c || i == childidx )
1641  continue;
1642 
1643  partial *= SCIPexprGetEvalValue(SCIPexprGetChildren(expr)[i]);
1644  }
1645  *bardot += partial * SCIPexprGetDot(child);
1646  }
1647  }
1648  /**! [SnippetExprBwfwdiffProduct] */
1649 
1650  return SCIP_OKAY;
1651 }
1652 
1653 /** expression derivative evaluation callback */
1654 static
1655 SCIP_DECL_EXPRBWDIFF(bwdiffProduct)
1656 { /*lint --e{715}*/
1657  SCIP_EXPR* child;
1658 
1659  assert(expr != NULL);
1660  assert(SCIPexprGetData(expr) != NULL);
1661  assert(childidx >= 0 && childidx < SCIPexprGetNChildren(expr));
1662 
1663  child = SCIPexprGetChildren(expr)[childidx];
1664  assert(child != NULL);
1665  assert(!SCIPisExprValue(scip, child));
1666  assert(SCIPexprGetEvalValue(child) != SCIP_INVALID);
1667 
1668  /* TODO add special handling for nchildren == 2 */
1669 
1670  /**! [SnippetExprBwdiffProduct] */
1671  if( !SCIPisZero(scip, SCIPexprGetEvalValue(child)) )
1672  {
1673  *val = SCIPexprGetEvalValue(expr) / SCIPexprGetEvalValue(child);
1674  }
1675  else
1676  {
1677  int i;
1678 
1679  *val = SCIPexprGetData(expr)->coefficient;
1680  for( i = 0; i < SCIPexprGetNChildren(expr) && (*val != 0.0); ++i )
1681  {
1682  if( i == childidx )
1683  continue;
1684 
1685  *val *= SCIPexprGetEvalValue(SCIPexprGetChildren(expr)[i]);
1686  }
1687  }
1688  /**! [SnippetExprBwdiffProduct] */
1689 
1690  return SCIP_OKAY;
1691 }
1692 
1693 /** expression interval evaluation callback */
1694 static
1695 SCIP_DECL_EXPRINTEVAL(intevalProduct)
1696 { /*lint --e{715}*/
1697  SCIP_EXPRDATA* exprdata;
1698  int c;
1699 
1700  assert(expr != NULL);
1701 
1702  exprdata = SCIPexprGetData(expr);
1703  assert(exprdata != NULL);
1704 
1705  /**! [SnippetExprIntevalProduct] */
1706  SCIPintervalSet(interval, exprdata->coefficient);
1707 
1708  SCIPdebugMsg(scip, "inteval %p with %d children: %.20g", (void*)expr, SCIPexprGetNChildren(expr), exprdata->coefficient);
1709 
1710  for( c = 0; c < SCIPexprGetNChildren(expr); ++c )
1711  {
1712  SCIP_INTERVAL childinterval;
1713 
1714  childinterval = SCIPexprGetActivity(SCIPexprGetChildren(expr)[c]);
1715  if( SCIPintervalIsEmpty(SCIP_INTERVAL_INFINITY, childinterval) )
1716  {
1717  SCIPintervalSetEmpty(interval);
1718  break;
1719  }
1720 
1721  /* multiply childinterval with the so far computed interval */
1722  SCIPintervalMul(SCIP_INTERVAL_INFINITY, interval, *interval, childinterval);
1723 
1724  SCIPdebugMsgPrint(scip, " *[%.20g,%.20g]", childinterval.inf, childinterval.sup);
1725  }
1726  SCIPdebugMsgPrint(scip, " = [%.20g,%.20g]\n", interval->inf, interval->sup);
1727  /**! [SnippetExprIntevalProduct] */
1728 
1729  return SCIP_OKAY;
1730 }
1731 
1732 /** estimates a multilinear function of the form \f$ f(x) := a \prod_{i = 1}^n x_i \f$
1733  *
1734  * \f$ x_i \f$ are the auxiliary variables of the children.
1735  * If !overestimate, then we look for an affine underestimator of \f$ f(x) \f$ which has a value above targetvalue at \f$ x^* \f$,
1736  * i.e., \f$ g(x) := \alpha^T x + \beta \le f(x)\f$ for all \f$ x \f$ in the domain, such that \f$ \alpha x^* + \beta > \text{targetvalue}\f$.
1737  *
1738  * Since \f$ f(x) \f$ is componentwise linear, its convex envelope is piecewise linear and its value can be computed by
1739  * finding the largest affine underestimator.
1740  * This is done either explicitly (if n=2) or by solving an LP, see SCIPcomputeFacetVertexPolyhedralNonlinear().
1741  */
1742 static
1743 SCIP_DECL_EXPRESTIMATE(estimateProduct)
1744 { /*lint --e{715}*/
1745  SCIP_EXPRDATA* exprdata;
1746  int nchildren;
1747 
1748  assert(scip != NULL);
1749  assert(expr != NULL);
1750  assert(strcmp(SCIPexprhdlrGetName(SCIPexprGetHdlr(expr)), EXPRHDLR_NAME) == 0);
1751  assert(refpoint != NULL);
1752  assert(coefs != NULL);
1753  assert(constant != NULL);
1754  assert(islocal != NULL);
1755  assert(branchcand != NULL);
1756  assert(*branchcand == TRUE);
1757  assert(success != NULL);
1758 
1759  exprdata = SCIPexprGetData(expr);
1760  assert(exprdata != NULL);
1761 
1762  *success = FALSE;
1763  *islocal = TRUE;
1764 
1765  nchildren = SCIPexprGetNChildren(expr);
1766 
1767  /* debug output: prints expression we are trying to estimate, bounds of variables and point */
1768 #ifdef SCIP_DEBUG
1769  {
1770  int c;
1771 
1772  SCIPdebugMsg(scip, "%sestimating product with %d variables\n", overestimate ? "over": "under", SCIPexprGetNChildren(expr));
1773  for( c = 0; c < SCIPexprGetNChildren(expr); ++c )
1774  {
1775  SCIPdebugMsg(scip, "child %d = %g in [%g, %g]\n", c, refpoint[c], localbounds[c].inf, localbounds[c].sup);
1776 
1777  if( SCIPisInfinity(scip, localbounds[c].sup) || SCIPisInfinity(scip, -localbounds[c].inf) )
1778  {
1779  SCIPdebugMsg(scip, "unbounded factor related to\n");
1781  }
1782  }
1783  }
1784 #endif
1785 
1786  /* bilinear term */
1787  if( nchildren == 2 )
1788  {
1789  SCIP_Real refpointx;
1790  SCIP_Real refpointy;
1791  SCIP_INTERVAL bndx;
1792  SCIP_INTERVAL bndy;
1793 
1794  /* collect first variable */
1795  refpointx = refpoint[0];
1796  bndx = localbounds[0];
1798 
1799  /* collect second variable */
1800  refpointy = refpoint[1];
1801  bndy = localbounds[1];
1803 
1804  /* adjust the reference points */
1805  refpointx = MIN(MAX(refpointx, bndx.inf), bndx.sup);
1806  refpointy = MIN(MAX(refpointy, bndy.inf), bndy.sup);
1807 
1808  coefs[0] = 0.0;
1809  coefs[1] = 0.0;
1810  *constant = 0.0;
1811  *success = TRUE;
1812 
1813  SCIPaddBilinMcCormick(scip, exprdata->coefficient, bndx.inf, bndx.sup, refpointx,
1814  bndy.inf, bndy.sup, refpointy, overestimate, &coefs[0], &coefs[1], constant,
1815  success);
1816  }
1817  else
1818  {
1819  SCIP_EXPRHDLRDATA* exprhdlrdata;
1820 
1821  exprhdlrdata = SCIPexprhdlrGetData(SCIPexprGetHdlr(expr));
1822  assert(exprhdlrdata != NULL);
1823 
1824  if( exprhdlrdata->conshdlr != NULL )
1825  {
1826  SCIP_CALL( estimateVertexPolyhedralProduct(scip, exprhdlrdata->conshdlr, nchildren, localbounds, exprdata->coefficient, refpoint, overestimate,
1827  targetvalue, coefs, constant, success) );
1828  }
1829  else
1830  {
1831  SCIPdebugMsg(scip, "no cons_nonlinear included in SCIP, cannot estimate vertex-polyhedral product function\n");
1832  }
1833  }
1834 
1835  return SCIP_OKAY;
1836 }
1837 
1838 /** initial estimators callback */
1839 static
1840 SCIP_DECL_EXPRINITESTIMATES(initestimatesProduct)
1841 {
1842  SCIP_EXPRDATA* exprdata;
1843  SCIP_Bool success = TRUE;
1844  int nchildren;
1845 
1846  assert(scip != NULL);
1847  assert(expr != NULL);
1848  assert(strcmp(SCIPexprhdlrGetName(SCIPexprGetHdlr(expr)), EXPRHDLR_NAME) == 0);
1849  assert(nreturned != NULL);
1850 
1851  nchildren = SCIPexprGetNChildren(expr);
1852 
1853  exprdata = SCIPexprGetData(expr);
1854  assert(exprdata != NULL);
1855 
1856  if( nchildren == 2 )
1857  {
1858  SCIP_INTERVAL bndx = bounds[0];
1859  SCIP_INTERVAL bndy = bounds[1];
1860 
1861  constant[0] = 0.0;
1862  coefs[0][0] = 0.0;
1863  coefs[0][1] = 0.0;
1864 
1865  /* build estimator */
1866  SCIPaddBilinMcCormick(scip, exprdata->coefficient, bndx.inf, bndx.sup, (bndx.inf + bndx.sup) / 2.0,
1867  bndy.inf, bndy.sup, (bndy.inf + bndy.sup ) / 2.0, overestimate, &coefs[0][0], &coefs[0][1],
1868  constant, &success);
1869  }
1870  else
1871  {
1872  SCIP_EXPRHDLRDATA* exprhdlrdata;
1873 
1874  exprhdlrdata = SCIPexprhdlrGetData(SCIPexprGetHdlr(expr));
1875  assert(exprhdlrdata != NULL);
1876 
1877  if( exprhdlrdata->conshdlr != NULL )
1878  {
1879  SCIP_CALL( estimateVertexPolyhedralProduct(scip, exprhdlrdata->conshdlr, nchildren, bounds, exprdata->coefficient, NULL, overestimate,
1880  overestimate ? SCIPinfinity(scip) : -SCIPinfinity(scip), coefs[0], constant, &success) );
1881  }
1882  else
1883  {
1884  SCIPdebugMsg(scip, "no cons_nonlinear included in SCIP, cannot estimate vertex-polyhedral product function\n");
1885  }
1886  }
1887 
1888  if( success )
1889  *nreturned = 1;
1890 
1891  return SCIP_OKAY;
1892 }
1893 
1894 /** expression reverse propagation callback */
1895 static
1896 SCIP_DECL_EXPRREVERSEPROP(reversepropProduct)
1897 { /*lint --e{715}*/
1898  SCIP_EXPRDATA* exprdata;
1899  SCIP_INTERVAL childbounds;
1900  SCIP_INTERVAL otherfactor;
1901  SCIP_INTERVAL zero;
1902  int i;
1903  int j;
1904 
1905  assert(scip != NULL);
1906  assert(expr != NULL);
1907  assert(SCIPexprGetNChildren(expr) > 0);
1908  assert(infeasible != NULL);
1909  assert(childrenbounds != NULL);
1910 
1911  *infeasible = FALSE;
1912 
1913  /* too expensive (runtime here is quadratic in number of children)
1914  * TODO implement something faster for larger numbers of factors, e.g., split product into smaller products
1915  */
1916  if( SCIPexprGetNChildren(expr) > 10 )
1917  return SCIP_OKAY;
1918 
1919  /* not possible to learn bounds on children if expression bounds are unbounded in both directions */
1921  return SCIP_OKAY;
1922 
1923  exprdata = SCIPexprGetData(expr);
1924  assert(exprdata != NULL);
1925 
1926  /**! [SnippetExprReversepropProduct] */
1927  SCIPintervalSet(&zero, 0.0);
1928 
1929  /* f = const * prod_k c_k => c_i solves c_i * (const * prod_{j:j!=i} c_j) = f */
1930  for( i = 0; i < SCIPexprGetNChildren(expr) && !(*infeasible); ++i )
1931  {
1932  SCIPintervalSet(&otherfactor, exprdata->coefficient);
1933 
1934  /* compute prod_{j:j!=i} c_j */
1935  for( j = 0; j < SCIPexprGetNChildren(expr); ++j )
1936  {
1937  if( i == j )
1938  continue;
1939 
1940  /* TODO we should compute these only one time instead of repeating this for almost every i */
1941  childbounds = childrenbounds[j];
1942  if( SCIPintervalIsEmpty(SCIP_INTERVAL_INFINITY, childbounds) )
1943  {
1944  *infeasible = TRUE;
1945  return SCIP_OKAY;
1946  }
1947 
1948  SCIPintervalMul(SCIP_INTERVAL_INFINITY, &otherfactor, otherfactor, childbounds);
1949  }
1950 
1951  childbounds = childrenbounds[i];
1952  if( SCIPintervalIsEmpty(SCIP_INTERVAL_INFINITY, childbounds) )
1953  {
1954  *infeasible = TRUE;
1955  return SCIP_OKAY;
1956  }
1957 
1958  /* solve x*otherfactor = f for x in c_i */
1959  SCIPintervalSolveUnivariateQuadExpression(SCIP_INTERVAL_INFINITY, &childbounds, zero, otherfactor, bounds, childbounds);
1960 
1961  SCIPdebugMsg(scip, "child %d: solved [%g,%g]*x = [%g,%g] with x in [%g,%g] -> x = [%g,%g]\n", i, otherfactor.inf, otherfactor.sup,
1962  bounds.inf, bounds.sup,
1963  childrenbounds[i].inf, childrenbounds[i].sup,
1964  childbounds.inf, childbounds.sup);
1965 
1966  /* store computed bounds of the expression */
1967  SCIPintervalIntersect(&childrenbounds[i], childrenbounds[i], childbounds);
1968  if( SCIPintervalIsEmpty(SCIP_INTERVAL_INFINITY, childrenbounds[i]) )
1969  {
1970  *infeasible = TRUE;
1971  return SCIP_OKAY;
1972  }
1973  }
1974  /**! [SnippetExprReversepropProduct] */
1975 
1976  return SCIP_OKAY;
1977 }
1978 
1979 /** expression curvature detection callback */
1980 static
1981 SCIP_DECL_EXPRCURVATURE(curvatureProduct)
1982 { /*lint --e{715}*/
1983  assert(scip != NULL);
1984  assert(expr != NULL);
1985  assert(success != NULL);
1986  assert(SCIPexprGetNChildren(expr) > 0);
1987 
1988  if( SCIPexprGetNChildren(expr) == 1 )
1989  {
1990  *childcurv = SCIPexprcurvMultiply(SCIPgetCoefExprProduct(expr), exprcurvature);
1991  *success = TRUE;
1992  }
1993  else
1994  {
1995  *success = FALSE;
1996  }
1997 
1998  return SCIP_OKAY;
1999 }
2000 
2001 /** expression monotonicity detection callback */
2002 static
2003 SCIP_DECL_EXPRMONOTONICITY(monotonicityProduct)
2004 { /*lint --e{715}*/
2005  SCIP_Real coef;
2006  int i;
2007  int nneg;
2008 
2009  assert(scip != NULL);
2010  assert(expr != NULL);
2011  assert(result != NULL);
2012  assert(SCIPexprGetNChildren(expr) >= 1);
2013  assert(childidx >= 0);
2014  assert(childidx < SCIPexprGetNChildren(expr));
2015 
2016  coef = SCIPgetCoefExprProduct(expr);
2017 
2018  /* count the number of negative children (except for childidx); if some children changes sign
2019  * -> monotonicity unknown
2020  */
2021  nneg = 0;
2022  for( i = 0; i < SCIPexprGetNChildren(expr); ++i )
2023  {
2024  SCIP_INTERVAL interval;
2025 
2026  if( i == childidx )
2027  continue;
2028 
2029  assert(SCIPexprGetChildren(expr)[i] != NULL);
2031  interval = SCIPexprGetActivity(SCIPexprGetChildren(expr)[i]);
2032 
2033  if( SCIPintervalGetSup(interval) <= 0.0 )
2034  nneg++;
2035  else if( SCIPintervalGetInf(interval) < 0.0 )
2036  {
2037  *result = SCIP_MONOTONE_UNKNOWN;
2038  return SCIP_OKAY;
2039  }
2040  }
2041 
2042  /* note that the monotonicity depends on the sign of the coefficient */
2043  if( nneg % 2 == 0 )
2044  *result = (coef >= 0.0) ? SCIP_MONOTONE_INC : SCIP_MONOTONE_DEC;
2045  else
2046  *result = (coef >= 0.0) ? SCIP_MONOTONE_DEC : SCIP_MONOTONE_INC;
2047 
2048  return SCIP_OKAY;
2049 }
2050 
2051 /** expression integrality detection callback */
2052 static
2053 SCIP_DECL_EXPRINTEGRALITY(integralityProduct)
2054 { /*lint --e{715}*/
2055  SCIP_EXPRDATA* exprdata;
2056  int i;
2057 
2058  assert(scip != NULL);
2059  assert(expr != NULL);
2060  assert(isintegral != NULL);
2061 
2062  exprdata = SCIPexprGetData(expr);
2063  assert(exprdata != NULL);
2064 
2065  *isintegral = EPSISINT(exprdata->coefficient, 0.0); /*lint !e835*/
2066 
2067  for( i = 0; i < SCIPexprGetNChildren(expr) && *isintegral; ++i )
2068  {
2069  SCIP_EXPR* child = SCIPexprGetChildren(expr)[i];
2070  assert(child != NULL);
2071 
2072  *isintegral = SCIPexprIsIntegral(child);
2073  }
2074 
2075  return SCIP_OKAY;
2076 }
2077 
2078 /** creates the handler for product expressions and includes it into SCIP */
2080  SCIP* scip /**< SCIP data structure */
2081  )
2082 {
2083  SCIP_EXPRHDLRDATA* exprhdlrdata;
2084  SCIP_EXPRHDLR* exprhdlr;
2085 
2086  /* allocate expression handler data */
2087  SCIP_CALL( SCIPallocClearBlockMemory(scip, &exprhdlrdata) );
2088  exprhdlrdata->conshdlr = SCIPfindConshdlr(scip, "nonlinear");
2089 
2091  exprhdlrdata) );
2092  assert(exprhdlr != NULL);
2093 
2094  SCIPexprhdlrSetCopyFreeHdlr(exprhdlr, copyhdlrProduct, freehdlrProduct);
2095  SCIPexprhdlrSetCopyFreeData(exprhdlr, copydataProduct, freedataProduct);
2096  SCIPexprhdlrSetSimplify(exprhdlr, simplifyProduct);
2097  SCIPexprhdlrSetCompare(exprhdlr, compareProduct);
2098  SCIPexprhdlrSetPrint(exprhdlr, printProduct);
2099  SCIPexprhdlrSetIntEval(exprhdlr, intevalProduct);
2100  SCIPexprhdlrSetEstimate(exprhdlr, initestimatesProduct, estimateProduct);
2101  SCIPexprhdlrSetReverseProp(exprhdlr, reversepropProduct);
2102  SCIPexprhdlrSetHash(exprhdlr, hashProduct);
2103  SCIPexprhdlrSetDiff(exprhdlr, bwdiffProduct, fwdiffProduct, bwfwdiffProduct);
2104  SCIPexprhdlrSetCurvature(exprhdlr, curvatureProduct);
2105  SCIPexprhdlrSetMonotonicity(exprhdlr, monotonicityProduct);
2106  SCIPexprhdlrSetIntegrality(exprhdlr, integralityProduct);
2107 
2108  return SCIP_OKAY;
2109 }
2110 
2111 /** creates a product expression */
2113  SCIP* scip, /**< SCIP data structure */
2114  SCIP_EXPR** expr, /**< pointer where to store expression */
2115  int nchildren, /**< number of children */
2116  SCIP_EXPR** children, /**< children */
2117  SCIP_Real coefficient, /**< constant coefficient of product */
2118  SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), /**< function to call to create ownerdata */
2119  void* ownercreatedata /**< data to pass to ownercreate */
2120  )
2121 {
2122  SCIP_EXPRDATA* exprdata;
2123 
2124  /**! [SnippetCreateExprProduct] */
2125  SCIP_CALL( SCIPallocBlockMemory(scip, &exprdata) );
2126  exprdata->coefficient = coefficient;
2127 
2128  SCIP_CALL( SCIPcreateExpr(scip, expr, SCIPgetExprhdlrProduct(scip), exprdata, nchildren, children, ownercreate, ownercreatedata) );
2129  /**! [SnippetCreateExprProduct] */
2130 
2131  return SCIP_OKAY;
2132 }
2133 
2134 /* from pub_expr.h */
2135 
2136 /** gets the constant coefficient of a product expression */
2138  SCIP_EXPR* expr /**< product expression */
2139  )
2140 {
2141  SCIP_EXPRDATA* exprdata;
2142 
2143  assert(expr != NULL);
2144 
2145  exprdata = SCIPexprGetData(expr);
2146  assert(exprdata != NULL);
2147 
2148  return exprdata->coefficient;
2149 }
struct exprnode * next
Definition: expr_product.c:78
static SCIP_DECL_EXPRBWDIFF(bwdiffProduct)
static SCIP_DECL_VERTEXPOLYFUN(prodfunction)
Definition: expr_product.c:89
SCIP_RETCODE SCIPcreateExprPow(SCIP *scip, SCIP_EXPR **expr, SCIP_EXPR *child, SCIP_Real exponent, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
Definition: expr_pow.c:3166
static SCIP_DECL_EXPRHASH(hashProduct)
SCIP_RETCODE SCIPprintExpr(SCIP *scip, SCIP_EXPR *expr, FILE *file)
Definition: scip_expr.c:1476
SCIP_Bool SCIPintervalIsEntire(SCIP_Real infinity, SCIP_INTERVAL operand)
SCIP_Bool SCIPisRelEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_RETCODE SCIPevalExprActivity(SCIP *scip, SCIP_EXPR *expr)
Definition: scip_expr.c:1706
static SCIP_RETCODE createExprNode(SCIP *scip, SCIP_EXPR *expr, EXPRNODE **newnode)
Definition: expr_product.c:168
static SCIP_DECL_EXPRINTEVAL(intevalProduct)
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition: scip_cons.c:877
int SCIPexprGetNChildren(SCIP_EXPR *expr)
Definition: expr.c:3798
SCIP_RETCODE SCIPcreateExprSignpower(SCIP *scip, SCIP_EXPR **expr, SCIP_EXPR *child, SCIP_Real exponent, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
Definition: expr_pow.c:3190
void SCIPexprhdlrSetDiff(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRBWDIFF((*bwdiff)), SCIP_DECL_EXPRFWDIFF((*fwdiff)), SCIP_DECL_EXPRBWFWDIFF((*bwfwdiff)))
Definition: expr.c:464
const char * SCIPexprhdlrGetName(SCIP_EXPRHDLR *exprhdlr)
Definition: expr.c:525
#define EXPRHDLR_HASHKEY
Definition: expr_product.c:44
static SCIP_DECL_EXPRFREEHDLR(freehdlrProduct)
#define EXPRHDLR_DESC
Definition: expr_product.c:42
SCIP_Real SCIPgetConstantExprSum(SCIP_EXPR *expr)
Definition: expr_sum.c:1172
static SCIP_RETCODE freeExprlist(SCIP *scip, EXPRNODE **exprlist)
Definition: expr_product.c:227
static SCIP_DECL_EXPRSIMPLIFY(simplifyProduct)
static SCIP_DECL_EXPRPRINT(printProduct)
#define debugSimplify
Definition: expr_product.c:53
SCIP_EXPRHDLRDATA * SCIPexprhdlrGetData(SCIP_EXPRHDLR *exprhdlr)
Definition: expr.c:555
#define FALSE
Definition: def.h:87
#define EPSISINT(x, eps)
Definition: def.h:214
static SCIP_RETCODE enforceSP12(SCIP *scip, SCIP_Real simplifiedcoef, EXPRNODE *finalchildren, SCIP_EXPR **simplifiedexpr, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
Definition: expr_product.c:872
handler for -x*log(x) expressions
struct SCIP_ExprData SCIP_EXPRDATA
Definition: type_expr.h:44
static SCIP_DECL_EXPRESTIMATE(estimateProduct)
SCIP_Real SCIPinfinity(SCIP *scip)
void SCIPintervalSolveUnivariateQuadExpression(SCIP_Real infinity, SCIP_INTERVAL *resultant, SCIP_INTERVAL sqrcoeff, SCIP_INTERVAL lincoeff, SCIP_INTERVAL rhs, SCIP_INTERVAL xbnds)
SCIP_Real SCIPgetExponentExprPow(SCIP_EXPR *expr)
Definition: expr_pow.c:3343
#define TRUE
Definition: def.h:86
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:54
static SCIP_DECL_EXPRCOPYHDLR(copyhdlrProduct)
static SCIP_RETCODE estimateVertexPolyhedralProduct(SCIP *scip, SCIP_CONSHDLR *conshdlr, int nfactors, SCIP_INTERVAL *bounds, SCIP_Real constantfactor, SCIP_Real *refpoint, SCIP_Bool overestimate, SCIP_Real targetvalue, SCIP_Real *coefs, SCIP_Real *constant, SCIP_Bool *success)
void SCIPexprhdlrSetHash(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRHASH((*hash)))
Definition: expr.c:442
SCIP_INTERVAL SCIPexprGetActivity(SCIP_EXPR *expr)
Definition: expr.c:3954
void SCIPintervalSet(SCIP_INTERVAL *resultant, SCIP_Real value)
void SCIPexprhdlrSetIntegrality(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRINTEGRALITY((*integrality)))
Definition: expr.c:431
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip_mem.h:99
SCIP_RETCODE SCIPcreateExprExp(SCIP *scip, SCIP_EXPR **expr, SCIP_EXPR *child, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
Definition: expr_exp.c:500
SCIP_EXPRHDLR * SCIPgetExprhdlrProduct(SCIP *scip)
Definition: scip_expr.c:904
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip_mem.h:127
void SCIPcaptureExpr(SCIP_EXPR *expr)
Definition: scip_expr.c:1399
SCIP_RETCODE SCIPappendExprSumExpr(SCIP *scip, SCIP_EXPR *expr, SCIP_EXPR *child, SCIP_Real childcoef)
Definition: expr_sum.c:1107
#define SCIP_EXPRITER_ENTEREXPR
Definition: type_expr.h:667
#define SCIP_EXPRITER_VISITEDCHILD
Definition: type_expr.h:669
#define SCIPdebugMsgPrint
Definition: scip_message.h:70
#define SCIPdebugMsg
Definition: scip_message.h:69
static SCIP_RETCODE createExprlistFromExprs(SCIP *scip, SCIP_EXPR **exprs, int nexprs, EXPRNODE **list)
Definition: expr_product.c:185
SCIP_RETCODE SCIPcreateExprSum(SCIP *scip, SCIP_EXPR **expr, int nchildren, SCIP_EXPR **children, SCIP_Real *coefficients, SCIP_Real constant, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
Definition: expr_sum.c:1070
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
Definition: scip_message.c:199
SCIP_Bool SCIPisExprProduct(SCIP *scip, SCIP_EXPR *expr)
Definition: scip_expr.c:1454
#define EXPRHDLR_PRECEDENCE
Definition: expr_product.c:43
bilinear nonlinear handler
public functions to work with algebraic expressions
int SCIPcompareExpr(SCIP *scip, SCIP_EXPR *expr1, SCIP_EXPR *expr2)
Definition: scip_expr.c:1723
static SCIP_RETCODE mergeProductExprlist(SCIP *scip, EXPRNODE *tomerge, EXPRNODE **finalchildren, EXPRNODE **unsimplifiedchildren, SCIP_Bool *changed, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
Definition: expr_product.c:370
SCIP_EXPRDATA * SCIPexprGetData(SCIP_EXPR *expr)
Definition: expr.c:3831
SCIP_EXPR ** SCIPexprGetChildren(SCIP_EXPR *expr)
Definition: expr.c:3808
SCIP_Real inf
Definition: intervalarith.h:46
SCIP_Real * SCIPgetCoefsExprSum(SCIP_EXPR *expr)
Definition: expr_sum.c:1157
static EXPRNODE * listPopFirst(EXPRNODE **list)
Definition: expr_product.c:130
static SCIP_RETCODE enforceSP10(SCIP *scip, SCIP_Real simplifiedcoef, EXPRNODE *finalchildren, SCIP_EXPR **simplifiedexpr, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
Definition: expr_product.c:767
SCIP_Real SCIPexprGetEvalValue(SCIP_EXPR *expr)
Definition: expr.c:3872
SCIP_RETCODE SCIPcreateExpr(SCIP *scip, SCIP_EXPR **expr, SCIP_EXPRHDLR *exprhdlr, SCIP_EXPRDATA *exprdata, int nchildren, SCIP_EXPR **children, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
Definition: scip_expr.c:964
SCIP_RETCODE SCIPcomputeFacetVertexPolyhedralNonlinear(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_Bool overestimate, SCIP_DECL_VERTEXPOLYFUN((*function)), void *fundata, SCIP_Real *xstar, SCIP_Real *box, int nallvars, SCIP_Real targetvalue, SCIP_Bool *success, SCIP_Real *facetcoefs, SCIP_Real *facetconstant)
static SCIP_DECL_EXPRMONOTONICITY(monotonicityProduct)
SCIP_Bool SCIPintervalIsEmpty(SCIP_Real infinity, SCIP_INTERVAL operand)
void SCIPintervalSetEmpty(SCIP_INTERVAL *resultant)
SCIP_Bool SCIPisExprValue(SCIP *scip, SCIP_EXPR *expr)
Definition: scip_expr.c:1432
SCIP_Real SCIPintervalGetInf(SCIP_INTERVAL interval)
#define NULL
Definition: lpi_spx1.cpp:155
SCIP_RETCODE SCIPcreateExprProduct(SCIP *scip, SCIP_EXPR **expr, int nchildren, SCIP_EXPR **children, SCIP_Real coefficient, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
SCIP_Real SCIPintervalGetSup(SCIP_INTERVAL interval)
power and signed power expression handlers
void SCIPintervalIntersect(SCIP_INTERVAL *resultant, SCIP_INTERVAL operand1, SCIP_INTERVAL operand2)
static SCIP_DECL_EXPRCURVATURE(curvatureProduct)
SCIP_Real SCIPexprGetDot(SCIP_EXPR *expr)
Definition: expr.c:3912
SCIP_Bool SCIPisExprSum(SCIP *scip, SCIP_EXPR *expr)
Definition: scip_expr.c:1443
#define SCIP_CALL(x)
Definition: def.h:384
SCIP_Real sup
Definition: intervalarith.h:47
SCIP_RETCODE SCIPcreateExprValue(SCIP *scip, SCIP_EXPR **expr, SCIP_Real value, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
Definition: expr_value.c:261
static SCIP_DECL_EXPRFREEDATA(freedataProduct)
static SCIP_DECL_EXPREVAL(evalProduct)
void SCIPexprhdlrSetCopyFreeHdlr(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRCOPYHDLR((*copyhdlr)), SCIP_DECL_EXPRFREEHDLR((*freehdlr)))
Definition: expr.c:359
SCIP_RETCODE SCIPcreateExprEntropy(SCIP *scip, SCIP_EXPR **expr, SCIP_EXPR *child, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
Definition: expr_entropy.c:674
static SCIP_DECL_EXPRINITESTIMATES(initestimatesProduct)
#define SCIP_INTERVAL_INFINITY
Definition: def.h:199
SCIP_Real SCIPgetCoefExprProduct(SCIP_EXPR *expr)
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:115
public data structures and miscellaneous methods
static SCIP_DECL_EXPRREVERSEPROP(reversepropProduct)
#define SCIP_Bool
Definition: def.h:84
#define SCIP_DECL_EXPR_OWNERCREATE(x)
Definition: type_expr.h:131
SCIP_RETCODE SCIPcreateExprAbs(SCIP *scip, SCIP_EXPR **expr, SCIP_EXPR *child, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
Definition: expr_abs.c:519
void SCIPexprhdlrSetMonotonicity(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRMONOTONICITY((*monotonicity)))
Definition: expr.c:420
static SCIP_DECL_EXPRINTEGRALITY(integralityProduct)
SCIP_RETCODE SCIPreleaseExpr(SCIP *scip, SCIP_EXPR **expr)
Definition: scip_expr.c:1407
constraint handler for nonlinear constraints specified by algebraic expressions
#define MAX(x, y)
Definition: tclique_def.h:83
void SCIPexprhdlrSetReverseProp(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRREVERSEPROP((*reverseprop)))
Definition: expr.c:501
SCIP_Bool SCIPexprIsIntegral(SCIP_EXPR *expr)
Definition: expr.c:4017
static SCIP_RETCODE freeExprNode(SCIP *scip, EXPRNODE **node)
Definition: expr_product.c:212
static int listLength(EXPRNODE *list)
Definition: expr_product.c:150
struct SCIP_ExprhdlrData SCIP_EXPRHDLRDATA
Definition: type_expr.h:183
void SCIPaddBilinMcCormick(SCIP *scip, SCIP_Real bilincoef, SCIP_Real lbx, SCIP_Real ubx, SCIP_Real refpointx, SCIP_Real lby, SCIP_Real uby, SCIP_Real refpointy, SCIP_Bool overestimate, SCIP_Real *lincoefx, SCIP_Real *lincoefy, SCIP_Real *linconstant, SCIP_Bool *success)
SCIP_EXPRHDLR * SCIPexprGetHdlr(SCIP_EXPR *expr)
Definition: expr.c:3821
SCIP_Bool SCIPisExprPower(SCIP *scip, SCIP_EXPR *expr)
Definition: scip_expr.c:1465
void SCIPexprhdlrSetPrint(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRPRINT((*print)))
Definition: expr.c:387
SCIP_EXPR * expr
Definition: expr_product.c:77
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
static SCIP_RETCODE createExprProductFromExprlist(SCIP *scip, EXPRNODE *exprlist, SCIP_Real coef, SCIP_EXPR **expr, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
Definition: expr_product.c:256
void SCIPexprhdlrSetCopyFreeData(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRCOPYDATA((*copydata)), SCIP_DECL_EXPRFREEDATA((*freedata)))
Definition: expr.c:372
absolute expression handler
constant value expression handler
product expression handler
void SCIPexprhdlrSetCompare(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRCOMPARE((*compare)))
Definition: expr.c:453
static SCIP_DECL_EXPRBWFWDIFF(bwfwdiffProduct)
void SCIPintervalMul(SCIP_Real infinity, SCIP_INTERVAL *resultant, SCIP_INTERVAL operand1, SCIP_INTERVAL operand2)
void SCIPexprhdlrSetCurvature(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRCURVATURE((*curvature)))
Definition: expr.c:409
void SCIPexprSetData(SCIP_EXPR *expr, SCIP_EXPRDATA *exprdata)
Definition: expr.c:3846
static SCIP_DECL_EXPRCOMPARE(compareProduct)
SCIP_RETCODE SCIPincludeExprhdlrProduct(SCIP *scip)
SCIP_Bool SCIPisExprSignpower(SCIP *scip, SCIP_EXPR *expr)
Definition: expr_pow.c:3215
#define SCIP_MAXVERTEXPOLYDIM
SCIP_Bool SCIPisExprExp(SCIP *scip, SCIP_EXPR *expr)
Definition: expr_exp.c:518
#define SCIP_Real
Definition: def.h:177
#define SCIP_INVALID
Definition: def.h:197
SCIP_Real SCIPgetValueExprValue(SCIP_EXPR *expr)
Definition: expr_value.c:285
static SCIP_DECL_EXPRCOPYDATA(copydataProduct)
static void insertFirstList(EXPRNODE *newnode, EXPRNODE **list)
Definition: expr_product.c:116
unsigned int SCIPcalcFibHash(SCIP_Real v)
Definition: misc.c:10242
#define SCIP_EXPRITER_LEAVEEXPR
Definition: type_expr.h:670
void SCIPexprhdlrSetEstimate(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRINITESTIMATES((*initestimates)), SCIP_DECL_EXPRESTIMATE((*estimate)))
Definition: expr.c:512
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
sum expression handler
static SCIP_RETCODE simplifyFactor(SCIP *scip, SCIP_EXPR *factor, SCIP_Real *simplifiedcoef, EXPRNODE **simplifiedfactor, SCIP_Bool *changed)
Definition: expr_product.c:299
SCIP_EXPRCURV SCIPexprcurvMultiply(SCIP_Real factor, SCIP_EXPRCURV curvature)
Definition: exprcurv.c:78
static SCIP_RETCODE simplifyMultiplyChildren(SCIP *scip, SCIP_EXPR **exprs, int nexprs, SCIP_Real *simplifiedcoef, EXPRNODE **finalchildren, SCIP_Bool *changed, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
Definition: expr_product.c:701
SCIP_RETCODE SCIPdismantleExpr(SCIP *scip, FILE *file, SCIP_EXPR *expr)
Definition: scip_expr.c:1596
#define SCIP_EXPRITER_VISITINGCHILD
Definition: type_expr.h:668
#define EXPRHDLR_NAME
Definition: expr_product.c:41
#define SCIPallocClearBlockMemory(scip, ptr)
Definition: scip_mem.h:82
SCIPallocBlockMemory(scip, subsol))
static SCIP_DECL_EXPRFWDIFF(fwdiffProduct)
static SCIP_RETCODE buildSimplifiedProduct(SCIP *scip, SCIP_Real simplifiedcoef, EXPRNODE **simplifiedfactors, SCIP_Bool changed, SCIP_EXPR **simplifiedexpr, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
static SCIP_RETCODE enforceSP11(SCIP *scip, SCIP_Real simplifiedcoef, EXPRNODE *finalchildren, SCIP_EXPR **simplifiedexpr, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
Definition: expr_product.c:811
SCIP_RETCODE SCIPincludeExprhdlr(SCIP *scip, SCIP_EXPRHDLR **exprhdlr, const char *name, const char *desc, unsigned int precedence, SCIP_DECL_EXPREVAL((*eval)), SCIP_EXPRHDLRDATA *data)
Definition: scip_expr.c:814
#define SCIPABORT()
Definition: def.h:356
int SCIPexprGetNUses(SCIP_EXPR *expr)
Definition: expr.c:3788
void SCIPexprhdlrSetSimplify(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRSIMPLIFY((*simplify)))
Definition: expr.c:490
void SCIPexprhdlrSetIntEval(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRINTEVAL((*inteval)))
Definition: expr.c:479
#define SCIPduplicateBlockMemory(scip, ptr, source)
Definition: scip_mem.h:94
exponential expression handler