def function_convolution(self, dist_1, dist_2, bins=50): a_1, b_1, a_2, b_2 = 0, 0, 0, 0 if dist_1 in self.bounds: a_1, b_1 = self.bounds[dist_1] else: a_1, b_1 = calculate_bounds_of_probability_distribution(dist_1) self.bounds[dist_1] = a_1, b_1 if dist_2 in self.bounds: a_2, b_2 = self.bounds[dist_2] else: a_2, b_2 = calculate_bounds_of_probability_distribution(dist_2) self.bounds[dist_2] = a_2, b_2 if (type(dist_1.dist), type(dist_2.dist)) == (uniform_gen, uniform_gen): return self.function_convolution_uniform((a_1, b_1), (a_2, b_2)) convolution_bounds_a, convolution_bounds_b = min(a_1, a_2), max(b_1, b_2) delta = fabs(convolution_bounds_a - convolution_bounds_b) / bins convolution_interval = TimeInterval(convolution_bounds_a, convolution_bounds_b, bins) x = [dist_1.pdf(t) for t in convolution_interval] y = [dist_2.pdf(t) for t in reversed(convolution_interval)] c = convolve(x, y) dictionary_convolution = {} for t in xrange(len(c)): dictionary_convolution[delta * t] = c[t] bias = calculateCenterMass(dictionary_convolution)[0] + dist_2.mean() - dist_1.mean() dictionary_convolution_biased = {} for t in dictionary_convolution: dictionary_convolution_biased[t - bias] = dictionary_convolution[t] convolution_function = FunctionPiecewiseLinear(dictionary_convolution_biased, FunctionHorizontalLinear(0)) return convolution_function.normalised()
def function_convolution_uniform(self, bounds_1, bounds_2, probability=None): a1, b1 = bounds_1 a2, b2 = bounds_2 length_1 = fabs(a1 - b1) length_2 = fabs(a2 - b2) convolution_bounds_a, convolution_bounds_b = a1 - b2, b1 - a2 trapezium_0, trapezium_1 = convolution_bounds_a, convolution_bounds_a + min( length_2, length_1) trapezium_2, trapezium_3 = trapezium_1 + fabs( length_1 - length_2), convolution_bounds_b #assert trapezium_2 + min(length_2, length_1) == trapezium_3 if probability is None: probability = min(1 / length_1, 1 / length_2) result = FunctionPiecewiseLinear( { trapezium_0: 0, trapezium_1: probability, trapezium_2: probability, trapezium_3: 0 }, FUNCTION_ZERO) result.is_normalised = True return result
def compare(self, dist_1, dist_2): dist_1_interval = TimeInterval(*self.bounds_of(dist_1)) dist_2_interval = TimeInterval(*self.bounds_of(dist_2)) dictionary_input_output = {} for time_step in dist_1_interval + dist_2_interval: dictionary_input_output[time_step] = sqrt( dist_1.pdf(time_step) * dist_2.pdf(time_step)) geometric_mean = FunctionPiecewiseLinear( dictionary_input_output, function_undefined=FUNCTION_ZERO) same = integral(geometric_mean, NEGATIVE_INFINITY, POSITIVE_INFINITY) dist_1_mean, dist_1_skewness, dist_1_kurtosis = dist_1.stats( moments='msk') dist_1_standard_deviation = dist_1.std() dist_2_mean, dist_2_skewness, dist_2_kurtosis = dist_2.stats( moments='msk') dist_2_standard_deviation = dist_2.std() distance = fabs(dist_1_standard_deviation - dist_2_standard_deviation) + fabs(dist_1_skewness - dist_2_skewness) distance += fabs(dist_1_kurtosis - dist_2_kurtosis) delta = dist_1_mean - dist_2_mean non_same_portion = 1.0 - same portion_after, portion_before = 1.0, 0.0 if almost_equals(distance, 0): if delta < 0: portion_after, portion_before = 0.0, 1.0 else: dist_1_standardized_pdf = lambda x: dist_1.pdf( dist_1_standard_deviation * x + dist_1_mean) dist_2_standardized_pdf = lambda x: dist_2.pdf( dist_2_standard_deviation * x + dist_2_mean) geometric_mean = lambda t: sqrt( dist_1_standardized_pdf(t) * dist_2_standardized_pdf(t)) geometric_mean_scaled = lambda p: geometric_mean(p / distance) geometric_mean_scaled_length = max(self.duration_of(dist_1), self.duration_of(dist_2)) dictionary_input_output = {} for time_step in TimeInterval(-geometric_mean_scaled_length / 2.0, geometric_mean_scaled_length / 2.0): dictionary_input_output[time_step] = geometric_mean_scaled( time_step) geometric_mean_scaled = FunctionPiecewiseLinear( dictionary_input_output, function_undefined=FUNCTION_ZERO) portion_after = integral(geometric_mean_scaled, NEGATIVE_INFINITY, delta) portion_before = integral(geometric_mean_scaled, delta, POSITIVE_INFINITY) after = portion_after / (portion_after + portion_before) * non_same_portion return 1.0 - same - after, same, after
def __init__(self, dictionary_input_output): cdf_input_list, cdf_output_list = convert_dict_to_sorted_lists(dictionary_input_output) list.__init__(self, cdf_input_list) TimeInterval.__init__(self, self[0], self[-1], 2) self.cdf = FunctionPiecewiseLinear(dictionary_input_output, function_undefined=FUNCTION_ZERO) self.cdf.dictionary_bounds_function[(self.b, POSITIVE_INFINITY)] = FUNCTION_ONE pdf_output_list = [] dictionary_bounds_function = {} for bounds in sorted(self.cdf.dictionary_bounds_function): a, b = bounds if a in [NEGATIVE_INFINITY, POSITIVE_INFINITY] or b in [NEGATIVE_INFINITY, POSITIVE_INFINITY]: continue pdf_y_intercept = fabs(self.cdf.derivative((a + b) / 2.0)) pdf_output_list.append(pdf_y_intercept) dictionary_bounds_function[bounds] = FunctionHorizontalLinear(pdf_y_intercept) self.pdf = FunctionComposite(dictionary_bounds_function, function_undefined=FUNCTION_ZERO, domain=self, is_normalised=True) self.roulette_wheel = [] self._mean = 0 for bounds in sorted(self.pdf.dictionary_bounds_function): (a, b) = bounds if a in [NEGATIVE_INFINITY, POSITIVE_INFINITY] and b in [NEGATIVE_INFINITY, POSITIVE_INFINITY]: continue cdf = self.cdf.dictionary_bounds_function[bounds] pdf = self.pdf.dictionary_bounds_function[bounds] share = cdf(b) self.roulette_wheel.append((a, b, share)) self._mean += (a + b) / 2.0 * pdf(a) * (b - a)
def function_convolution_uniform(self, bounds_1, bounds_2, probability=None): a1, b1 = bounds_1 a2, b2 = bounds_2 length_1 = fabs(a1 - b1) length_2 = fabs(a2 - b2) convolution_bounds_a, convolution_bounds_b = a1 - b2, b1 - a2 trapezium_0, trapezium_1 = convolution_bounds_a, convolution_bounds_a + min(length_2, length_1) trapezium_2, trapezium_3 = trapezium_1 + fabs(length_1 - length_2), convolution_bounds_b #assert trapezium_2 + min(length_2, length_1) == trapezium_3 if probability is None: probability = min(1 / length_1, 1 / length_2) result = FunctionPiecewiseLinear( {trapezium_0: 0, trapezium_1: probability, trapezium_2: probability, trapezium_3: 0}, FUNCTION_ZERO) result.is_normalised = True return result
def __init__(self, dictionary_input_output): cdf_input_list, cdf_output_list = convert_dict_to_sorted_lists( dictionary_input_output) list.__init__(self, cdf_input_list) TimeInterval.__init__(self, self[0], self[-1], 2) self.cdf = FunctionPiecewiseLinear(dictionary_input_output, function_undefined=FUNCTION_ZERO) self.cdf.dictionary_bounds_function[(self.b, POSITIVE_INFINITY)] = FUNCTION_ONE pdf_output_list = [] dictionary_bounds_function = {} for bounds in sorted(self.cdf.dictionary_bounds_function): a, b = bounds if a in [NEGATIVE_INFINITY, POSITIVE_INFINITY ] or b in [NEGATIVE_INFINITY, POSITIVE_INFINITY]: continue pdf_y_intercept = fabs(self.cdf.derivative((a + b) / 2.0)) pdf_output_list.append(pdf_y_intercept) dictionary_bounds_function[bounds] = FunctionHorizontalLinear( pdf_y_intercept) self.pdf = FunctionComposite(dictionary_bounds_function, function_undefined=FUNCTION_ZERO, domain=self, is_normalised=True) self.roulette_wheel = [] self._mean = 0 for bounds in sorted(self.pdf.dictionary_bounds_function): (a, b) = bounds if a in [NEGATIVE_INFINITY, POSITIVE_INFINITY ] and b in [NEGATIVE_INFINITY, POSITIVE_INFINITY]: continue cdf = self.cdf.dictionary_bounds_function[bounds] pdf = self.pdf.dictionary_bounds_function[bounds] share = cdf(b) self.roulette_wheel.append((a, b, share)) self._mean += (a + b) / 2.0 * pdf(a) * (b - a)
def function_convolution(self, dist_1, dist_2, bins=50): a_1, b_1, a_2, b_2 = 0, 0, 0, 0 if dist_1 in self.bounds: a_1, b_1 = self.bounds[dist_1] else: a_1, b_1 = calculate_bounds_of_probability_distribution(dist_1) self.bounds[dist_1] = a_1, b_1 if dist_2 in self.bounds: a_2, b_2 = self.bounds[dist_2] else: a_2, b_2 = calculate_bounds_of_probability_distribution(dist_2) self.bounds[dist_2] = a_2, b_2 if (type(dist_1.dist), type(dist_2.dist)) == (uniform_gen, uniform_gen): return self.function_convolution_uniform((a_1, b_1), (a_2, b_2)) convolution_bounds_a, convolution_bounds_b = min(a_1, a_2), max(b_1, b_2) delta = fabs(convolution_bounds_a - convolution_bounds_b) / bins convolution_interval = TimeInterval(convolution_bounds_a, convolution_bounds_b, bins) x = [dist_1.pdf(t) for t in convolution_interval] y = [dist_2.pdf(t) for t in reversed(convolution_interval)] c = convolve(x, y) dictionary_convolution = {} for t in xrange(len(c)): dictionary_convolution[delta * t] = c[t] bias = calculateCenterMass( dictionary_convolution)[0] + dist_2.mean() - dist_1.mean() dictionary_convolution_biased = {} for t in dictionary_convolution: dictionary_convolution_biased[t - bias] = dictionary_convolution[t] convolution_function = FunctionPiecewiseLinear( dictionary_convolution_biased, FunctionHorizontalLinear(0)) return convolution_function.normalised()
def __init__(self, dictionary_beginning, dictionary_ending, bins=50): input_list_beginning, output_list_beginning = convert_dict_to_sorted_lists(dictionary_beginning) for i in xrange(1, len(input_list_beginning)): if not dictionary_beginning[input_list_beginning[i]] > dictionary_beginning[input_list_beginning[i - 1]]: raise TypeError("values of 'dictionary_beginning' should be increasing in time") input_list_ending, output_list_ending = convert_dict_to_sorted_lists(dictionary_ending) for i in xrange(1, len(input_list_ending)): if not dictionary_ending[input_list_ending[i]] < dictionary_ending[input_list_ending[i - 1]]: raise TypeError("values of 'dictionary_ending' should be decreasing in time") dictionary_ending = {} for i, time_step in enumerate(input_list_ending): dictionary_ending[time_step] = output_list_ending[len(input_list_ending) - i - 1] input_list_ending, output_list_ending = convert_dict_to_sorted_lists(dictionary_ending) distribution_beginning = ProbabilityDistributionPiecewiseLinear(dictionary_beginning) distribution_ending = ProbabilityDistributionPiecewiseLinear(dictionary_ending) TemporalEvent.__init__(self, distribution_beginning, distribution_ending, bins=bins) self._list = sorted(set(input_list_beginning + input_list_ending)) self.membership_function = FunctionPiecewiseLinear(self.to_dict(), FUNCTION_ZERO)
class ProbabilityDistributionPiecewiseLinear(list, TimeInterval, rv_frozen): dist = 'ProbabilityDistributionPiecewiseLinear' _mean = None asd = None def __init__(self, dictionary_input_output): cdf_input_list, cdf_output_list = convert_dict_to_sorted_lists(dictionary_input_output) list.__init__(self, cdf_input_list) TimeInterval.__init__(self, self[0], self[-1], 2) self.cdf = FunctionPiecewiseLinear(dictionary_input_output, function_undefined=FUNCTION_ZERO) self.cdf.dictionary_bounds_function[(self.b, POSITIVE_INFINITY)] = FUNCTION_ONE pdf_output_list = [] dictionary_bounds_function = {} for bounds in sorted(self.cdf.dictionary_bounds_function): a, b = bounds if a in [NEGATIVE_INFINITY, POSITIVE_INFINITY] or b in [NEGATIVE_INFINITY, POSITIVE_INFINITY]: continue pdf_y_intercept = fabs(self.cdf.derivative((a + b) / 2.0)) pdf_output_list.append(pdf_y_intercept) dictionary_bounds_function[bounds] = FunctionHorizontalLinear(pdf_y_intercept) self.pdf = FunctionComposite(dictionary_bounds_function, function_undefined=FUNCTION_ZERO, domain=self, is_normalised=True) self.roulette_wheel = [] self._mean = 0 for bounds in sorted(self.pdf.dictionary_bounds_function): (a, b) = bounds if a in [NEGATIVE_INFINITY, POSITIVE_INFINITY] and b in [NEGATIVE_INFINITY, POSITIVE_INFINITY]: continue cdf = self.cdf.dictionary_bounds_function[bounds] pdf = self.pdf.dictionary_bounds_function[bounds] share = cdf(b) self.roulette_wheel.append((a, b, share)) self._mean += (a + b) / 2.0 * pdf(a) * (b - a) def std(self): # Not properly implemented return 0 def stats(self, moments='mv'): # Not properly implemented # m, s, k return self.mean(), 0, 0 def mean(self): return self._mean def interval(self, alpha): if alpha == 1: return self.a, self.b raise NotImplementedError("'interval' is not implemented for 'alpha' other than 1") def rvs(self, size=None): if size is None: size = 1 else: assert isinstance(size, int) result = [] start, end = 0, 0 for i in xrange(size): rand = random() for a, b, share in self.roulette_wheel: if rand < share: start, end = a, b break result.append(random_time(start, end)) if size == 1: return result[0] return result # def plot(self): # import matplotlib.pyplot as plt # x_axis, y_axis = [], [] # for time_step in self: # x_axis.append(UnixTime(time_step - EPSILON).to_datetime()) # x_axis.append(UnixTime(time_step + EPSILON).to_datetime()) # y_axis.append(self.pdf(time_step - EPSILON)) # y_axis.append(self.pdf(time_step + EPSILON)) # plt.plot(x_axis, y_axis) # return plt def plot(self): import matplotlib.pyplot as plt x_axis, y_axis = [], [] for time_step in self: x_axis.append(time_step - EPSILON) x_axis.append(time_step + EPSILON) y_axis.append(self.pdf(time_step - EPSILON)) y_axis.append(self.pdf(time_step + EPSILON)) plt.plot(x_axis, y_axis) return plt def __hash__(self): return object.__hash__(self) def __repr__(self): return TimeInterval.__repr__(self) def __str__(self): return repr(self)
class ProbabilityDistributionPiecewiseLinear(list, TimeInterval, rv_frozen): dist = 'ProbabilityDistributionPiecewiseLinear' _mean = None asd = None def __init__(self, dictionary_input_output): cdf_input_list, cdf_output_list = convert_dict_to_sorted_lists( dictionary_input_output) list.__init__(self, cdf_input_list) TimeInterval.__init__(self, self[0], self[-1], 2) self.cdf = FunctionPiecewiseLinear(dictionary_input_output, function_undefined=FUNCTION_ZERO) self.cdf.dictionary_bounds_function[(self.b, POSITIVE_INFINITY)] = FUNCTION_ONE pdf_output_list = [] dictionary_bounds_function = {} for bounds in sorted(self.cdf.dictionary_bounds_function): a, b = bounds if a in [NEGATIVE_INFINITY, POSITIVE_INFINITY ] or b in [NEGATIVE_INFINITY, POSITIVE_INFINITY]: continue pdf_y_intercept = fabs(self.cdf.derivative((a + b) / 2.0)) pdf_output_list.append(pdf_y_intercept) dictionary_bounds_function[bounds] = FunctionHorizontalLinear( pdf_y_intercept) self.pdf = FunctionComposite(dictionary_bounds_function, function_undefined=FUNCTION_ZERO, domain=self, is_normalised=True) self.roulette_wheel = [] self._mean = 0 for bounds in sorted(self.pdf.dictionary_bounds_function): (a, b) = bounds if a in [NEGATIVE_INFINITY, POSITIVE_INFINITY ] and b in [NEGATIVE_INFINITY, POSITIVE_INFINITY]: continue cdf = self.cdf.dictionary_bounds_function[bounds] pdf = self.pdf.dictionary_bounds_function[bounds] share = cdf(b) self.roulette_wheel.append((a, b, share)) self._mean += (a + b) / 2.0 * pdf(a) * (b - a) def std(self): # Not properly implemented return 0 def stats(self, moments='mv'): # Not properly implemented # m, s, k return self.mean(), 0, 0 def mean(self): return self._mean def interval(self, alpha): if alpha == 1: return self.a, self.b raise NotImplementedError( "'interval' is not implemented for 'alpha' other than 1") def rvs(self, size=None): if size is None: size = 1 else: assert isinstance(size, int) result = [] start, end = 0, 0 for i in xrange(size): rand = random() for a, b, share in self.roulette_wheel: if rand < share: start, end = a, b break result.append(random_time(start, end)) if size == 1: return result[0] return result # def plot(self): # import matplotlib.pyplot as plt # x_axis, y_axis = [], [] # for time_step in self: # x_axis.append(UnixTime(time_step - EPSILON).to_datetime()) # x_axis.append(UnixTime(time_step + EPSILON).to_datetime()) # y_axis.append(self.pdf(time_step - EPSILON)) # y_axis.append(self.pdf(time_step + EPSILON)) # plt.plot(x_axis, y_axis) # return plt def plot(self): import matplotlib.pyplot as plt x_axis, y_axis = [], [] for time_step in self: x_axis.append(time_step - EPSILON) x_axis.append(time_step + EPSILON) y_axis.append(self.pdf(time_step - EPSILON)) y_axis.append(self.pdf(time_step + EPSILON)) plt.plot(x_axis, y_axis) return plt def __hash__(self): return object.__hash__(self) def __repr__(self): return TimeInterval.__repr__(self) def __str__(self): return repr(self)