def __add__(self, other): """Addition of two asymptotic developments. Parameters ---------- other: `Asymptotic` or Number. Returns ------- sum : Asymptotic The sum of this asymptotic development and `other`. Examples -------- >>> print(Asymptotic(mu=42, nu=2, xi=69) + Asymptotic(mu=1, nu=51, xi=3)) exp(42 n + 2 log n + 69 + o(1)) >>> print(Asymptotic(mu=42, nu=2, xi=69) + Asymptotic(mu=42, nu=51, xi=3)) exp(42 n + 51 log n + 3 + o(1)) >>> print(Asymptotic(mu=42, nu=2, xi=4) + Asymptotic(mu=42, nu=2, xi=3)) exp(42 n + 2 log n + 4.31326 + o(1)) >>> print(Asymptotic(mu=42, nu=2, xi=4) + 1) exp(42 n + 2 log n + 4 + o(1)) >>> print(1 + Asymptotic(mu=42, nu=2, xi=4)) exp(42 n + 2 log n + 4 + o(1)) >>> print(Asymptotic(mu=42, nu=2, xi=69) + Asymptotic(mu=41.99999999, nu=51, xi=3)) exp(42 n + 51 log n + 3 + o(1)) """ if not isinstance(other, Asymptotic): other = Asymptotic(0, 0, self.ce.log(other), symbolic=self.symbolic) if isnan(self.mu) or isnan(other.mu): return Asymptotic(self.ce.nan, self.ce.nan, self.ce.nan, symbolic=self.symbolic) elif self.ce.look_equal(self.mu, other.mu): mu = max(self.mu, other.mu) if isnan(self.nu) or isnan(other.nu): return Asymptotic(mu, self.ce.nan, self.ce.nan, symbolic=self.symbolic) elif self.ce.look_equal(self.nu, other.nu): nu = max(self.nu, other.nu) xi = self.ce.simplify(self.ce.log(self.ce.exp(self.xi) + self.ce.exp(other.xi))) return Asymptotic(mu, nu, xi, symbolic=self.symbolic) elif self.nu > other.nu: return Asymptotic(mu, self.nu, self.xi, symbolic=self.symbolic) else: return Asymptotic(mu, other.nu, other.xi, symbolic=self.symbolic) elif self.mu > other.mu: return Asymptotic(self.mu, self.nu, self.xi, symbolic=self.symbolic) else: return Asymptotic(other.mu, other.nu, other.xi, symbolic=self.symbolic)
def nice(x, suffix): # x : coefficient, suffix : `sympy` expression if isnan(x): return ' + ?' if suffix == 1 else ' + ? %s' % suffix if x == 0: return '' a = sympy.symbols('a') result = str(a + x * suffix) assert result[0:2] == 'a ' return result[1:]
def __repr__(self): s = 'asymptotic = %s' % self.asymptotic lab_sorted = sorted(self._labels_std_one.keys()) lab_sorted.extend(sorted(self._labels_std_two.keys())) for label in lab_sorted: val = getattr(self, 'phi_' + label) if not isnan(val): if self.symbolic: s += ', phi_' + label + ' = %s' % val else: s += ', phi_' + label + ' = {:.6g}'.format(float(val)) return '<%s>' % s
def look_equal(self, other, *args, **kwargs): """Test if two asymptotic developments can reasonably be considered as equal. Parameters ---------- other : Asymptotic *args Cf. ``math.isclose``. **kwargs Cf. ``math.isclose``. Returns ------- bool True if this asymptotic development can reasonably be considered equal to `other`. Cf. :meth:`ComputationEngine.look_equal`. Examples -------- >>> Asymptotic(mu=1, nu=2, xi=3).look_equal( ... Asymptotic(mu=0.999999999999, nu=2.00000000001, xi=3)) True """ if not isinstance(other, Asymptotic): return False some_coefficients_are_nan = (isnan(self.mu) or isnan(self.nu) or isnan(self.xi) or isnan(other.mu) or isnan(other.nu) or isnan(other.xi)) if some_coefficients_are_nan: raise ValueError('Can assert look_equal only when all coefficients are known.') return (self.ce.look_equal(self.mu, other.mu, *args, **kwargs) and self.ce.look_equal(self.nu, other.nu, * args, ** kwargs) and self.ce.look_equal(self.xi, other.xi, *args, **kwargs))
def ballot(self): """str : This can be a valid ballot or ``'utility-dependent'``. """ if isnan(self.utility_threshold): raise AssertionError('Unable to compute utility threshold' ) # pragma: no cover - Should never happen elif self.ce.look_equal(self.utility_threshold, 1): return ballot_low_u(self.ranking, self.voting_rule) elif self.ce.look_equal(self.utility_threshold, 0, abs_tol=1E-9): return ballot_high_u(self.ranking, self.voting_rule) else: assert 0 <= self.utility_threshold <= 1 return UTILITY_DEPENDENT
def nice(x, suffix): if isnan(x): return ' + ? ' + suffix if suffix else ' + ?' if x == 1 and suffix: return ' + ' + suffix if x == -1 and suffix: return ' - ' + suffix if x == 0: return '' result = ' + ' if x > 0 else ' - ' result += "{:.6g}".format(float(abs(x))) result += ' ' + suffix if suffix else '' return result
def limit(self): """Number, nan or infinity : Limit when `n` tends to infinity. Examples -------- >>> import numpy as np >>> Asymptotic(mu=-1, nu=0, xi=0).limit 0 >>> Asymptotic(mu=1, nu=0, xi=0).limit inf >>> Asymptotic(mu=-1, nu=np.nan, xi=np.nan).limit 0 >>> Asymptotic(mu=0, nu=-1, xi=np.nan).limit 0 `nan` means that the limit is unknown: >>> Asymptotic(mu=0, nu=0, xi=np.nan).limit nan """ if isnan(self.mu): return self.ce.nan elif self.mu > 0: return self.ce.inf elif self.mu < 0: return 0 else: # self.mu == 0 if isnan(self.nu): return self.ce.nan elif self.nu > 0: return self.ce.inf elif self.nu < 0: return 0 else: # self.nu == 0: if isnan(self.xi): return self.ce.nan else: return self.ce.simplify(self.ce.exp(self.xi))
def pseudo_offset(phi, phi_left, phi_right): if isnan(phi): return phi_left * phi_right else: return phi