def _quantile(self, p, loc=None, scale=None, low=None, high=None): loc, scale, low, high = self._loc_scale_low_high(loc, scale, low, high) std_low, std_high = self._standardized_low_and_high(low=low, high=high, loc=loc, scale=scale) # Use the sum of tangents formula. # First, the quantile of the cauchy distribution is tan(pi * (x - 0.5)). # and the cdf of the cauchy distribution is 0.5 + arctan(x) / np.pi # WLOG, we will assume loc = 0 , scale = 1 (these can be taken in to account # by rescaling and shifting low and high, and then scaling the output). # We would like to compute quantile(p * (cdf(high) - cdf(low)) + cdf(low)) # This is the same as: # tan(pi * (cdf(low) + (cdf(high) - cdf(low)) * p - 0.5)) # Let a = pi * (cdf(low) - 0.5), b = pi * (cdf(high) - cdf(low)) * u # By using the formula for the cdf we have: # a = arctan(low), b = arctan_difference(high, low) * u # Thus the quantile is now tan(a + b). # By appealing to the sum of tangents formula we have: # tan(a + b) = (tan(a) + tan(b)) / (1 - tan(a) * tan(b)) = # (low + tan(b)) / (1 - low * tan(b)) # Thus for a 'standard' truncated cauchy we have the quantile as: # quantile(p) = (low + tan(b)) / (1 - low * tan(b)) where # b = arctan_difference(high, low) * p. tanb = tf.math.tan(tfp_math.atan_difference(std_high, std_low) * p) x = (std_low + tanb) / (1 - std_low * tanb) return x * scale + loc
def _mean(self): loc, scale, low, high = self._loc_scale_low_high() std_low, std_high = self._standardized_low_and_high( low=low, high=high, loc=loc, scale=scale) # Formula from David Olive, "Applied Robust Statistics" -- # see http://parker.ad.siu.edu/Olive/ch4.pdf . t = (tf.math.log1p(tf.math.square(std_high)) - tf.math.log1p(tf.math.square(std_low))) t = t / (2 * tfp_math.atan_difference(std_high, std_low)) return loc + scale * t
def _variance(self): loc, scale, low, high = self._loc_scale_low_high() std_low, std_high = self._standardized_low_and_high( low=low, high=high, loc=loc, scale=scale) # Formula from David Olive, "Applied Robust Statistics" -- # see http://parker.ad.siu.edu/Olive/ch4.pdf . atan_diff = tfp_math.atan_difference(std_high, std_low) t = (std_high - std_low - atan_diff) / atan_diff std_mean = ((tf.math.log1p(tf.math.square(std_high)) - tf.math.log1p(tf.math.square(std_low))) / (2 * atan_diff)) return tf.math.square(scale) * (t - tf.math.square(std_mean))
def _cauchy_cdf_diff(x, y): return tfp_math.atan_difference(x, y) / np.pi