def _call(self, x): if self.dom.leq(self.value, 0): # value == 0 return self.cod.get_top() else: if is_top(self.dom, x): # changed from 0. This must be top because of monotonicity. return self.cod.get_top() else: if is_top(self.dom, self.value): return 0 else: assert self.value > 0 return int(np.ceil(float(x) / self.value))
def _call(self, x): if self.dom.leq(self.value, 0): # value == 0 return self.cod.get_top() else: if is_top(self.dom, x): # changed from 0. This must be top because of monotonicity. return self.cod.get_top() else: if is_top(self.dom, self.value): return 0 else: assert self.value > 0 return int(np.ceil(float(x)/self.value))
def _call(self, x): if is_top(self.dom, self.c): if is_top(self.dom, x): return self.dom.get_top() else: raise MapNotDefinedHere() else: if self.dom.leq(self.c, x): if is_top(self.dom, x): return self.dom.get_top() assert isinstance(self.c, float) assert isinstance(x, float), x return x - self.c else: raise MapNotDefinedHere()
def sum_units(Fs, values, R): for Fi in Fs: check_isinstance(Fi, RcompUnits) res = 0.0 for Fi, x in zip(Fs, values): if is_top(Fi, x): return R.get_top() # reasonably sure this is correct... try: factor = 1.0 / float(R.units / Fi.units) except Exception as e: # pragma: no cover (DimensionalityError) raise_wrapped(Exception, e, 'some error', Fs=Fs, R=R) try: res += factor * x except FloatingPointError as e: if 'overflow' in str(e): res = np.inf break else: raise if np.isinf(res): return R.get_top() return res
def sample_sum_upperbound(F, R, f, nu): """ F = X R = PosetProduct((X, X)) Returns a set of points in R on the line {(a,b) | a + b = f }. If f = Top, F = Top. It uses the variable InvPlus2.ALGO to decide the type of sampling. """ if is_top(F, f): # +infinity top1 = R[0].get_top() top2 = R[1].get_top() return set([(top1, top2)]) if F.leq(f, 0.0): # f == 0 return set([(0.0, 0.0)]) from mcdp_dp.dp_inv_plus import InvPlus2 if InvPlus2.ALGO == InvPlus2.ALGO_VAN_DER_CORPUT: options = van_der_corput_sequence(nu) elif InvPlus2.ALGO == InvPlus2.ALGO_UNIFORM: options = np.linspace(0.0, 1.0, nu) else: assert False, InvPlus2.ALGO s = set() for o in options: s.add((f * o, f * (1.0 - o))) return s
def __init__(self, F, R, unit, value): check_isinstance(F, RcompUnits) check_isinstance(R, RcompUnits) check_isinstance(unit, RcompUnits) try: check_mult_units_consistency(F, unit, R) except AssertionError as e: msg = 'Invalid units.' raise_wrapped(ValueError, e, msg, F=F, R=R, unit=unit) amap = MultValueMap(F=F, R=R, unit=unit, value=value) # if value = Top: # f |-> f * Top # if is_top(unit, value): amap_dual = MultValueDPHelper2Map(R, F) elif unit.equal(0.0, value): amap_dual = ConstantPosetMap(R, F, F.get_top()) else: value2 = 1.0 / value unit2 = inverse_of_unit(unit) amap_dual = MultValueMap(F=R, R=F, unit=unit2, value=value2) WrapAMap.__init__(self, amap, amap_dual)
def _call(self, x): dom, cod = self.dom, self.cod if is_top(dom, self.c): return 0 if dom.leq(x, self.c): return 0 else: if is_top(dom, x): return cod.get_top() else: check_isinstance(x, int) res = x - self.c assert res >= 0 return res
def Nat_mult_antichain_Max(m): """ Returns the set of elements of Nat so that their product is at most m: Max { (a, b) | a * b <= m } """ # top -> [(top, top)] P = Nat() P.belongs(m) top = P.get_top() if is_top(P, m): s = set([(top, top)]) return s assert isinstance(m, int) if m < 1: return set([(0, 0)]) s = set() for o1 in range(1, m + 1): assert o1 >= 1 # We want the minimum x such that o1 * x >= f # x >= f / o1 # x* = ceil(f / o1) x = int(np.floor(m * 1.0 / o1)) assert x * o1 <= m # feasible assert (x + 1) * o1 > m, (x + 1, o1, m) # and minimum s.add((o1, x)) return s
def sum_units(Fs, values, R): ''' Might raise IncompatibleUnits ''' for Fi in Fs: check_isinstance(Fi, RcompUnits) res = 0.0 for Fi, x in zip(Fs, values): if is_top(Fi, x): return R.get_top() # reasonably sure this is correct... try: factor = 1.0 / float(R.units / Fi.units) except pint_DimensionalityError as e: # pragma: no cover (DimensionalityError) raise_wrapped(IncompatibleUnits, e, 'Pint cannot convert', Fs=Fs, R=R) try: res += factor * x except FloatingPointError as e: if 'overflow' in str(e): res = np.inf break else: raise if np.isinf(res): return R.get_top() return res
def Nat_mult_antichain_Max(m): """ Returns the set of elements of Nat so that their product is at most m: Max { (a, b) | a * b <= m } """ # top -> [(top, top)] P = Nat() P.belongs(m) top = P.get_top() if is_top(P, m): s = set([(top, top)]) return s assert isinstance(m, int) if m < 1: return set([(0, 0)]) s = set() for o1 in range(1, m + 1): assert o1 >= 1 # We want the minimum x such that o1 * x >= f # x >= f / o1 # x* = ceil(f / o1) x = int(np.floor(m * 1.0 / o1)) assert x * o1 <= m # feasible assert (x+1) * o1 > m, (x+1, o1, m) # and minimum s.add((o1, x)) return s
def invmultU_solve_options(F, R, f, n, algo): """ Returns a set of points in R that are on the line r1*r2=f. """ from .dp_inv_mult import InvMult2 assert algo in [InvMult2.ALGO_UNIFORM, InvMult2.ALGO_VAN_DER_CORPUT] if is_top(F, f): mcdp_dev_warning('FIXME Need much more thought about this') top1 = R[0].get_top() top2 = R[1].get_top() s = set([(top1, top2)]) return s check_isinstance(f, float) if f == 0.0: return set([(0.0, 0.0)]) if algo == InvMult2.ALGO_UNIFORM: mcdp_dev_warning('TODO: add ALGO as parameter. ') ps = samplec(n, f) elif algo == InvMult2.ALGO_VAN_DER_CORPUT: x1, x2 = generate_exp_van_der_corput_sequence(n=n, C=f) ps = zip(x1, x2) else: # pragma: no cover assert False return ps
def Nat_mult_antichain_Min(m): """ Returns the Minimal set of elements of Nat so that their product is at least m: Min { (a, b) | a * b >= m } """ # (top, 1) or (1, top) P = Nat() P.belongs(m) top = P.get_top() if is_top(P, m): s = set([(top, 1), (1, top)]) # XXX: return s assert isinstance(m, int) if m == 0: # any (r1,r2) is such that r1*r2 >= 0 return set([(0, 0)]) s = set() for o1 in range(1, m + 1): assert o1 >= 1 # We want the minimum x such that o1 * x >= f # x >= f / o1 # x* = ceil(f / o1) x = int(np.ceil(m * 1.0 / o1)) assert x * o1 >= m assert (x-1) * o1 < m assert x >= 1 s.add((o1, x)) return s
def Nat_mult_antichain_Min(m): """ Returns the Minimal set of elements of Nat so that their product is at least m: Min { (a, b) | a * b >= m } """ # (top, 1) or (1, top) P = Nat() P.belongs(m) top = P.get_top() if is_top(P, m): s = set([(top, 1), (1, top)]) # XXX: return s assert isinstance(m, int) if m == 0: # any (r1,r2) is such that r1*r2 >= 0 return set([(0, 0)]) s = set() for o1 in range(1, m + 1): assert o1 >= 1 # We want the minimum x such that o1 * x >= f # x >= f / o1 # x* = ceil(f / o1) x = int(np.ceil(m * 1.0 / o1)) assert x * o1 >= m assert (x - 1) * o1 < m assert x >= 1 s.add((o1, x)) return s
def diagram_label(self): from mcdp_posets.rcomp_units import format_pint_unit_short if is_top(self.unit, self.value): label = '× %s' % self.unit.format(self.value) else: assert isinstance(self.value, float) label = '× %.5f %s' % (self.value, format_pint_unit_short(self.unit.units)) return label
def eval_PlusN(x, context, wants_constant): """ Raises NotConstant if wants_constant is True. """ assert isinstance(x, CDP.PlusN) assert len(x.ops) > 1 # ops as a list ops_list = get_odd_ops(unwrap_list(x.ops)) # First, we flatten all operators ops = flatten_plusN(ops_list) # Then we divide in positive constants, negative constants, and resources. pos_constants, neg_constants, resources = \ eval_PlusN_sort_ops(ops, context, wants_constant) # first, sum the positive constants and the resources res = eval_PlusN_(pos_constants, resources, context) if len(neg_constants) == 0: # If there are no negative constants, we are done return res # elif len(neg_constants) > 1: # msg = 'Not implemented addition of more than one negative constant.' # raise_desc(DPInternalError, msg, neg_constants=neg_constants) else: # we have only one negative constant from mcdp_lang.misc_math import plus_constantsN constant = plus_constantsN(neg_constants) check_isinstance(constant.unit, RbicompUnits) constant.unit.check_leq(constant.value, 0.0) # now it's a positive value valuepos = RbicompUnits_reflect(constant.unit, constant.value) F = context.get_rtype(res) c_space = RcompUnits(pint_unit=constant.unit.units, string=constant.unit.string) # mainly to make sure we handle Top if is_top(constant.unit, valuepos): valuepos2 = c_space.get_top() else: valuepos2 = valuepos dp = MinusValueDP(F=F, c_value=valuepos2, c_space=c_space) r2 = create_operation(context, dp, resources=[res], name_prefix='_minus', op_prefix='_x', res_prefix='_y') return r2
def eval_PlusN(x, context, wants_constant): """ Raises NotConstant if wants_constant is True. """ assert isinstance(x, CDP.PlusN) assert len(x.ops) > 1 # ops as a list ops_list = get_odd_ops(unwrap_list(x.ops)) # First, we flatten all operators ops = flatten_plusN(ops_list) # Then we divide in positive constants, negative constants, and resources. pos_constants, neg_constants, resources = \ eval_PlusN_sort_ops(ops, context, wants_constant) # first, sum the positive constants and the resources res = eval_PlusN_(pos_constants, resources, context) if len(neg_constants) == 0: # If there are no negative constants, we are done return res # elif len(neg_constants) > 1: # msg = 'Not implemented addition of more than one negative constant.' # raise_desc(DPInternalError, msg, neg_constants=neg_constants) else: # we have only one negative constant from mcdp_lang.misc_math import plus_constantsN constant = plus_constantsN(neg_constants) check_isinstance(constant.unit, RbicompUnits) constant.unit.check_leq(constant.value, 0.0) # now it's a positive value valuepos = RbicompUnits_reflect(constant.unit, constant.value) F = context.get_rtype(res) c_space = RcompUnits(pint_unit=constant.unit.units, string=constant.unit.string) # mainly to make sure we handle Top if is_top(constant.unit, valuepos): valuepos2 = c_space.get_top() else: valuepos2 = valuepos dp = MinusValueDP(F=F, c_value=valuepos2, c_space=c_space) r2 = create_operation(context, dp, resources=[res]) return r2
def solve(self, f): if is_top(self.F, f): top = f elements = set([(top, 1), (1, top)]) # XXX: to check return self.R.Us(elements) if f > InvMult2Nat.memory_limit: msg = ('InvMult2Nat:solve(%s): This would produce' ' an antichain of length %s.') % (f,f) raise NotSolvableNeedsApprox(msg) options = Nat_mult_antichain_Min(f) return self.R.Us(options)
def solve(self, f): if is_top(self.F, f): top = f elements = set([(top, 1), (1, top)]) # XXX: to check return self.R.Us(elements) if f > MCDPConstants.InvMult2Nat_memory_limit: msg = ('InvMult2Nat:solve(%s): This would produce' ' an antichain of length %s.') % (f, f) raise NotSolvableNeedsApprox(msg) options = Nat_mult_antichain_Min(f) return self.R.Us(options)
def _call(self, x): assert isinstance(x, tuple) and len(x) == self.n top = self.top res = 0 N = self.dom[0] for xi in x: if is_top(N, xi): return top res += xi if np.isinf(res): return top return res
def sample_sum_lowerbound(F, R, f, n): """ Returns a set of points in R below the line {(a,b) | a + b = f } such that the line is contained in the upperclosure of the points. It uses the variable InvPlus2.ALGO to decide the type of sampling. """ check_isinstance(R, PosetProduct) assert len(R) == 2 if is_top(F, f): # +infinity top1 = R[0].get_top() top2 = R[1].get_top() return set([(top1, 0.0), (0.0, top2)]) if F.leq(f, 0.0): # f == 0 return set([(0.0, 0.0)]) from mcdp_dp.dp_inv_plus import InvPlus2 if InvPlus2.ALGO == InvPlus2.ALGO_VAN_DER_CORPUT: options = van_der_corput_sequence(n + 1) elif InvPlus2.ALGO == InvPlus2.ALGO_UNIFORM: options = np.linspace(0.0, 1.0, n + 1) else: assert False, InvPlus2.ALGO s = [] for o in options: s.append((f * o, f * (1.0 - o))) options = set() for i in range(n): x = s[i][0] y = s[i + 1][1] a = R.meet(s[i], s[i+1]) assert (x,y) == a, ((x,y), a) options.add((x, y)) return options
def sample_sum_lowerbound(F, R, f, n): """ Returns a set of points in R below the line {(a,b) | a + b = f } such that the line is contained in the upperclosure of the points. It uses the variable InvPlus2.ALGO to decide the type of sampling. """ check_isinstance(R, PosetProduct) assert len(R) == 2 if is_top(F, f): # +infinity top1 = R[0].get_top() top2 = R[1].get_top() return set([(top1, 0.0), (0.0, top2)]) if F.leq(f, 0.0): # f == 0 return set([(0.0, 0.0)]) from mcdp_dp.dp_inv_plus import InvPlus2 if InvPlus2.ALGO == InvPlus2.ALGO_VAN_DER_CORPUT: options = van_der_corput_sequence(n + 1) elif InvPlus2.ALGO == InvPlus2.ALGO_UNIFORM: options = np.linspace(0.0, 1.0, n + 1) else: assert False, InvPlus2.ALGO s = [] for o in options: s.append((f * o, f * (1.0 - o))) options = set() for i in range(n): x = s[i][0] y = s[i + 1][1] a = R.meet(s[i], s[i + 1]) assert (x, y) == a, ((x, y), a) options.add((x, y)) return options
def solve(self, f): # FIXME: what about the top? top = self.F.get_top() if is_top(self.F, f): s = set([(top, 0), (0, top)]) return self.R.Us(s) assert isinstance(f, int) s = set() if f >= MCDPConstants.InvPlus2Nat_max_antichain_size: msg = 'This would create an antichain of %s items.' % f raise NotSolvableNeedsApprox(msg) for o in range(f + 1): s.add((o, f - o)) return self.R.Us(s)
def solve(self, f): # FIXME: what about the top? top = self.F.get_top() if is_top(self.F, f): s = set([(top, 0), (0, top)]) return self.R.Us(s) assert isinstance(f, int) s = set() if f >= 100000: msg = 'This would create an antichain of %s items.' % f raise NotSolvableNeedsApprox(msg) for o in range(f + 1): s.add((o, f - o)) return self.R.Us(s)
def __init__(self, value): N = Nat() N.belongs(value) amap = MultValueNatMap(value) # if value = Top: # f |-> f * Top # if is_top(N, value): amap_dual = MultValueNatDPHelper2Map() elif N.equal(0, value): # r |-> Top amap_dual = ConstantPosetMap(N, N, N.get_top()) else: # f * c <= r # f <= r / c # r |-> floor(r/c) amap_dual = MultValueNatDPhelper(value) WrapAMap.__init__(self, amap, amap_dual)
def solve_r(self, r): # @UnusedVariable # Max { (f1, f2): f1 + f2 <= r } if self.n > 2: msg = 'SumNNatDP(%s).solve_r not implemented yet' % self.n raise_desc(DPNotImplementedError, msg) mcdp_dev_warning('move away') if is_top(self.R, r): top = self.F[0].get_top() s = set([(top, top)]) return self.F.Ls(s) assert isinstance(r, int) if r >= 100000: msg = 'This would create an antichain of %s items.' % r raise NotSolvableNeedsApprox(msg) s = set() for o in range(r + 1): s.add((o, r - o)) return self.F.Ls(s)
def Rcomp_from_Nat(value): if is_top(Nat(), value): val = Rcomp().get_top() else: val = float(value) return val
def invmultL_solve_options(F, R, f, n, algo): """ Returns a set of points that are *below* r1*r2 = f """ from .dp_inv_mult import InvMult2 assert algo in [InvMult2.ALGO_UNIFORM, InvMult2.ALGO_VAN_DER_CORPUT] if f == 0.0: return set([(0.0, 0.0)]) if is_top(F, f): mcdp_dev_warning('FIXME Need much more thought about this') top1 = R[0].get_top() top2 = R[1].get_top() s = set([(top1, top2)]) return s if algo == InvMult2.ALGO_UNIFORM: if n == 1: points = [(0.0, 0.0)] elif n == 2: points = [(0.0, 0.0)] else: pu = sorted(samplec(n - 1, f), key=lambda _: _[0]) assert len(pu) == n - 1, (len(pu), n - 1) nu = len(pu) points = set() points.add((0.0, pu[0][1])) points.add((pu[-1][0], 0.0)) for i in range(nu - 1): p = (pu[i][0], pu[i + 1][1]) points.add(p) elif algo == InvMult2.ALGO_VAN_DER_CORPUT: if n == 1: points = set([(0.0, 0.0)]) else: x1, x2 = generate_exp_van_der_corput_sequence(n=n - 1, C=f) pu = zip(x1, x2) assert len(pu) == n - 1, pu if do_extra_checks(): check_minimal(pu, R) nu = len(pu) points = [] points.append((0.0, pu[0][1])) for i in range(nu - 1): p = (pu[i][0], pu[i + 1][1]) points.append(p) points.append((pu[-1][0], 0.0)) points = set(points) else: # pragma: no cover assert False assert len(points) == n, (n, len(points), points) return points
def sample_sum_lowersets(F, R, f, n): """ Returns a set of points in R *above* the line {(a,b) | a + b = f } such that the line is contained in the downclosure of the points. It uses the variable InvPlus2.ALGO to decide the type of sampling. """ check_isinstance(R, PosetProduct) assert len(R) == 2 if is_top(F, f): # this is not correct, however it does not form a monotone sequence # +infinity top1 = R[0].get_top() top2 = R[1].get_top() return set([(top1, top2)]) if F.leq(f, 0.0): # f == 0 return set([(0.0, 0.0)]) from mcdp_dp.dp_inv_plus import InvPlus2 if InvPlus2.ALGO == InvPlus2.ALGO_VAN_DER_CORPUT: options = van_der_corput_sequence(n + 1) elif InvPlus2.ALGO == InvPlus2.ALGO_UNIFORM: options = np.linspace(0.0, 1.0, n + 1) else: assert False, InvPlus2.ALGO s = [] for o in options: try: s.append((f * o, f * (1.0 - o))) except FloatingPointError as e: if 'underflow' in str(e): # assert f <= finfo.tiny, (f, finfo.tiny) mcdp_dev_warning('not sure about this') s.append((finfo.eps, finfo.eps)) else: raise_wrapped(FloatingPointError, e, 'error', f=f, o=o) # the sequence s[] is ordered for i in range(len(s) - 1): xs = [_[0] for _ in s] ys = [_[1] for _ in s] if not xs[i] < xs[i + 1]: msg = 'Invalid sequence (s[%s].x = %s !< s[%s].x = %s.' % ( i, xs[i], i + 1, xs[i + 1]) xs2 = map(R[0].format, xs) ys2 = map(R[1].format, ys) raise_desc(AssertionError, msg, s=s, xs=xs, ys=ys, xs2=xs2, ys2=ys2) options = set() for i in range(n): x = s[i + 1][0] y = s[i][1] # join a = R.join(s[i], s[i + 1]) if (x, y) != a: msg = 'Numerical error' raise_desc(AssertionError, msg, x=x, y=y, a=a, s_i=s[i], s_i_plus=s[i + 1]) options.add((x, y)) return options
def sample_sum_lowersets(F, R, f, n): """ Returns a set of points in R *above* the line {(a,b) | a + b = f } such that the line is contained in the downclosure of the points. It uses the variable InvPlus2.ALGO to decide the type of sampling. """ check_isinstance(R, PosetProduct) assert len(R) == 2 if is_top(F, f): # this is not correct, however it does not form a monotone sequence # +infinity top1 = R[0].get_top() top2 = R[1].get_top() return set([(top1, top2)]) if F.leq(f, 0.0): # f == 0 return set([(0.0, 0.0)]) from mcdp_dp.dp_inv_plus import InvPlus2 if InvPlus2.ALGO == InvPlus2.ALGO_VAN_DER_CORPUT: options = van_der_corput_sequence(n + 1) elif InvPlus2.ALGO == InvPlus2.ALGO_UNIFORM: options = np.linspace(0.0, 1.0, n + 1) else: assert False, InvPlus2.ALGO s = [] for o in options: try: s.append((f * o, f * (1.0 - o))) except FloatingPointError as e: if 'underflow' in str(e): # assert f <= finfo.tiny, (f, finfo.tiny) mcdp_dev_warning('not sure about this') s.append((finfo.eps, finfo.eps)) else: raise_wrapped(FloatingPointError, e, 'error', f=f, o=o) # the sequence s[] is ordered for i in range(len(s)-1): xs = [_[0] for _ in s] ys = [_[1] for _ in s] if not xs[i] < xs[i+1]: msg = 'Invalid sequence (s[%s].x = %s !< s[%s].x = %s.' % (i, xs[i], i+1, xs[i+1]) xs2 = map(R[0].format, xs) ys2 = map(R[1].format, ys) raise_desc(AssertionError, msg, s=s, xs=xs, ys=ys, xs2=xs2, ys2=ys2) options = set() for i in range(n): x = s[i + 1][0] y = s[i][1] # join a = R.join(s[i], s[i+1]) if (x,y) != a: msg = 'Numerical error' raise_desc(AssertionError, msg, x=x, y=y, a=a, s_i=s[i], s_i_plus=s[i+1]) options.add((x, y)) return options
def _call(self, x): if is_top(self.dom, x): return self.cod.get_top() else: return 0
def _call(self, r): if is_top(self.dom, r): return self.cod.get_top() else: fmax = int(np.floor( float(r) / self.c )) return fmax
def _call(self, r): if is_top(self.dom, r): return self.cod.get_top() else: fmax = int(np.floor(float(r) / self.c)) return fmax