def test_add(self): xl = -2.5 xu = 2.8 yl = -3.2 yu = 2.7 zl, zu = interval.add(xl, xu, yl, yu) x = np.linspace(xl, xu, 100) y = np.linspace(yl, yu, 100) for _x in x: _z = _x + y self.assertTrue(np.all(zl <= _z)) self.assertTrue(np.all(zu >= _z))
def _prop_bnds_leaf_to_root_SumExpression(node, bnds_dict): """ Parameters ---------- node: pyomo.core.expr.expr_pyomo5.SumExpression bnds_dict: ComponentMap """ arg0 = node.arg(0) lb, ub = bnds_dict[arg0] for i in range(1, node.nargs()): arg = node.arg(i) lb2, ub2 = bnds_dict[arg] lb, ub = interval.add(lb, ub, lb2, ub2) bnds_dict[node] = (lb, ub)
def _prop_bnds_leaf_to_root_SumExpression(node, bnds_dict): """ Parameters ---------- node: pyomo.core.expr.numeric_expr.SumExpression bnds_dict: ComponentMap """ arg0 = node.arg(0) lb, ub = bnds_dict[arg0] for i in range(1, node.nargs()): arg = node.arg(i) lb2, ub2 = bnds_dict[arg] lb, ub = interval.add(lb, ub, lb2, ub2) bnds_dict[node] = (lb, ub)
def _prop_bnds_root_to_leaf_SumExpression(node, bnds_dict): """ This function is a bit complicated. A simpler implementation would loop through each argument in the sum and do the following: bounds_on_arg_i = bounds_on_entire_sum - bounds_on_sum_of_args_excluding_arg_i and the bounds_on_sum_of_args_excluding_arg_i could be computed for each argument. However, the computational expense would grow approximately quadratically with the length of the sum. Thus, we do the following. Consider the expression y = x1 + x2 + x3 + x4 and suppose we have bounds on y. We first accumulate bounds to obtain a list like the following [(x1)_bounds, (x1+x2)_bounds, (x1+x2+x3)_bounds, (x1+x2+x3+x4)_bounds] Then we can propagate bounds back to x1, x2, x3, and x4 with the following (x4)_bounds = (x1+x2+x3+x4)_bounds - (x1+x2+x3)_bounds (x3)_bounds = (x1+x2+x3)_bounds - (x1+x2)_bounds (x2)_bounds = (x1+x2)_bounds - (x1)_bounds Parameters ---------- node: pyomo.core.expr.expr_pyomo5.ProductExpression bnds_dict: ComponentMap """ # first accumulate bounds accumulated_bounds = list() accumulated_bounds.append(bnds_dict[node.arg(0)]) lb0, ub0 = bnds_dict[node] for i in range(1, node.nargs()): _lb0, _ub0 = accumulated_bounds[i-1] _lb1, _ub1 = bnds_dict[node.arg(i)] accumulated_bounds.append(interval.add(_lb0, _ub0, _lb1, _ub1)) if lb0 > accumulated_bounds[node.nargs() - 1][0]: accumulated_bounds[node.nargs() - 1] = (lb0, accumulated_bounds[node.nargs()-1][1]) if ub0 < accumulated_bounds[node.nargs() - 1][1]: accumulated_bounds[node.nargs() - 1] = (accumulated_bounds[node.nargs()-1][0], ub0) for i in reversed(range(1, node.nargs())): lb0, ub0 = accumulated_bounds[i] lb1, ub1 = accumulated_bounds[i-1] lb2, ub2 = bnds_dict[node.arg(i)] _lb1, _ub1 = interval.sub(lb0, ub0, lb2, ub2) _lb2, _ub2 = interval.sub(lb0, ub0, lb1, ub1) if _lb1 > lb1: lb1 = _lb1 if _ub1 < ub1: ub1 = _ub1 if _lb2 > lb2: lb2 = _lb2 if _ub2 < ub2: ub2 = _ub2 accumulated_bounds[i-1] = (lb1, ub1) bnds_dict[node.arg(i)] = (lb2, ub2) lb, ub = bnds_dict[node.arg(0)] _lb, _ub = accumulated_bounds[0] if _lb > lb: lb = _lb if _ub < ub: ub = _ub bnds_dict[node.arg(0)] = (lb, ub)
def _prop_bnds_root_to_leaf_SumExpression(node, bnds_dict): """ This function is a bit complicated. A simpler implementation would loop through each argument in the sum and do the following: bounds_on_arg_i = bounds_on_entire_sum - bounds_on_sum_of_args_excluding_arg_i and the bounds_on_sum_of_args_excluding_arg_i could be computed for each argument. However, the computational expense would grow approximately quadratically with the length of the sum. Thus, we do the following. Consider the expression y = x1 + x2 + x3 + x4 and suppose we have bounds on y. We first accumulate bounds to obtain a list like the following [(x1)_bounds, (x1+x2)_bounds, (x1+x2+x3)_bounds, (x1+x2+x3+x4)_bounds] Then we can propagate bounds back to x1, x2, x3, and x4 with the following (x4)_bounds = (x1+x2+x3+x4)_bounds - (x1+x2+x3)_bounds (x3)_bounds = (x1+x2+x3)_bounds - (x1+x2)_bounds (x2)_bounds = (x1+x2)_bounds - (x1)_bounds Parameters ---------- node: pyomo.core.expr.numeric_expr.ProductExpression bnds_dict: ComponentMap """ # first accumulate bounds accumulated_bounds = list() accumulated_bounds.append(bnds_dict[node.arg(0)]) lb0, ub0 = bnds_dict[node] for i in range(1, node.nargs()): _lb0, _ub0 = accumulated_bounds[i-1] _lb1, _ub1 = bnds_dict[node.arg(i)] accumulated_bounds.append(interval.add(_lb0, _ub0, _lb1, _ub1)) if lb0 > accumulated_bounds[node.nargs() - 1][0]: accumulated_bounds[node.nargs() - 1] = (lb0, accumulated_bounds[node.nargs()-1][1]) if ub0 < accumulated_bounds[node.nargs() - 1][1]: accumulated_bounds[node.nargs() - 1] = (accumulated_bounds[node.nargs()-1][0], ub0) for i in reversed(range(1, node.nargs())): lb0, ub0 = accumulated_bounds[i] lb1, ub1 = accumulated_bounds[i-1] lb2, ub2 = bnds_dict[node.arg(i)] _lb1, _ub1 = interval.sub(lb0, ub0, lb2, ub2) _lb2, _ub2 = interval.sub(lb0, ub0, lb1, ub1) if _lb1 > lb1: lb1 = _lb1 if _ub1 < ub1: ub1 = _ub1 if _lb2 > lb2: lb2 = _lb2 if _ub2 < ub2: ub2 = _ub2 accumulated_bounds[i-1] = (lb1, ub1) bnds_dict[node.arg(i)] = (lb2, ub2) lb, ub = bnds_dict[node.arg(0)] _lb, _ub = accumulated_bounds[0] if _lb > lb: lb = _lb if _ub < ub: ub = _ub bnds_dict[node.arg(0)] = (lb, ub)