danielutils 1.1.28__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- danielutils/__init__.py +50 -0
- danielutils/abstractions/__init__.py +3 -0
- danielutils/abstractions/db/__init__.py +10 -0
- danielutils/abstractions/db/database.py +206 -0
- danielutils/abstractions/db/database_definitions.py +219 -0
- danielutils/abstractions/db/database_exceptions.py +34 -0
- danielutils/abstractions/db/database_factory.py +70 -0
- danielutils/abstractions/db/database_initializer.py +261 -0
- danielutils/abstractions/db/database_models.py +213 -0
- danielutils/abstractions/db/dependencies.py +6 -0
- danielutils/abstractions/db/implementations/__init__.py +4 -0
- danielutils/abstractions/db/implementations/in_memory_database.py +365 -0
- danielutils/abstractions/db/implementations/persistent_in_memory_database.py +174 -0
- danielutils/abstractions/db/implementations/redis_database.py +403 -0
- danielutils/abstractions/db/implementations/sqlite_database.py +491 -0
- danielutils/abstractions/multiprogramming/__init__.py +3 -0
- danielutils/abstractions/multiprogramming/multi_id.py +26 -0
- danielutils/abstractions/multiprogramming/worker.py +104 -0
- danielutils/abstractions/multiprogramming/worker_pool.py +98 -0
- danielutils/abstractions/repl.py +125 -0
- danielutils/aliases.py +174 -0
- danielutils/async_/__init__.py +7 -0
- danielutils/async_/async_cmd.py +28 -0
- danielutils/async_/async_command.py +879 -0
- danielutils/async_/async_layered_command.py +125 -0
- danielutils/async_/async_retry_executor.py +86 -0
- danielutils/async_/async_worker_pool.py +110 -0
- danielutils/async_/time_strategy.py +73 -0
- danielutils/async_/utils.py +57 -0
- danielutils/better_builtins/__init__.py +3 -0
- danielutils/better_builtins/counter.py +48 -0
- danielutils/better_builtins/frange.py +266 -0
- danielutils/better_builtins/typed_builtins/__init__.py +4 -0
- danielutils/better_builtins/typed_builtins/factory.py +126 -0
- danielutils/better_builtins/typed_builtins/tdict.py +36 -0
- danielutils/better_builtins/typed_builtins/tlist.py +223 -0
- danielutils/better_builtins/typed_builtins/tset.py +67 -0
- danielutils/better_builtins/typed_builtins/ttuple.py +15 -0
- danielutils/colors.py +203 -0
- danielutils/context_managers/__init__.py +5 -0
- danielutils/context_managers/attr_context.py +40 -0
- danielutils/context_managers/multi_context.py +34 -0
- danielutils/context_managers/optional_context.py +33 -0
- danielutils/context_managers/state_context.py +25 -0
- danielutils/context_managers/temporary_file.py +108 -0
- danielutils/convenience.py +12 -0
- danielutils/conversions/__init__.py +2 -0
- danielutils/conversions/main_conversions.py +131 -0
- danielutils/conversions/specialized_conversions/__init__.py +2 -0
- danielutils/conversions/specialized_conversions/to_hex.py +25 -0
- danielutils/conversions/specialized_conversions/to_int.py +19 -0
- danielutils/custom_types.py +18 -0
- danielutils/data_structures/__init__.py +8 -0
- danielutils/data_structures/algorithms.py +52 -0
- danielutils/data_structures/comparer.py +47 -0
- danielutils/data_structures/default_dict.py +23 -0
- danielutils/data_structures/functions.py +35 -0
- danielutils/data_structures/graph/__init__.py +4 -0
- danielutils/data_structures/graph/binary_node.py +71 -0
- danielutils/data_structures/graph/graph.py +208 -0
- danielutils/data_structures/graph/multinode.py +101 -0
- danielutils/data_structures/graph/node.py +60 -0
- danielutils/data_structures/heap/__init__.py +3 -0
- danielutils/data_structures/heap/heap.py +119 -0
- danielutils/data_structures/heap/max_heap.py +18 -0
- danielutils/data_structures/heap/min_heap.py +18 -0
- danielutils/data_structures/queue/__init__.py +3 -0
- danielutils/data_structures/queue/atomic_queue.py +15 -0
- danielutils/data_structures/queue/priority_queue.py +110 -0
- danielutils/data_structures/queue/queue.py +92 -0
- danielutils/data_structures/stack.py +102 -0
- danielutils/data_structures/trees/__init__.py +2 -0
- danielutils/data_structures/trees/binary_syntax_tree.py +84 -0
- danielutils/data_structures/trees/binary_tree.py +63 -0
- danielutils/date.py +43 -0
- danielutils/date_time.py +23 -0
- danielutils/decorators/__init__.py +18 -0
- danielutils/decorators/atomic.py +45 -0
- danielutils/decorators/attach.py +61 -0
- danielutils/decorators/chain_decorators.py +39 -0
- danielutils/decorators/decorate_conditionally.py +32 -0
- danielutils/decorators/delay_call.py +47 -0
- danielutils/decorators/deprecate.py +46 -0
- danielutils/decorators/final.py +39 -0
- danielutils/decorators/limit_recursion.py +63 -0
- danielutils/decorators/memo.py +68 -0
- danielutils/decorators/normalize_decorator.py +55 -0
- danielutils/decorators/overload.py +204 -0
- danielutils/decorators/partially_implemented.py +32 -0
- danielutils/decorators/processify.py +74 -0
- danielutils/decorators/property.py +42 -0
- danielutils/decorators/singleton.py +59 -0
- danielutils/decorators/threadify.py +40 -0
- danielutils/decorators/timeout.py +82 -0
- danielutils/decorators/total_ordering.py +82 -0
- danielutils/decorators/validate.py +227 -0
- danielutils/exceptions.py +90 -0
- danielutils/functions/__init__.py +13 -0
- danielutils/functions/areoneof.py +47 -0
- danielutils/functions/check_foreach.py +39 -0
- danielutils/functions/factorial.py +24 -0
- danielutils/functions/flatten.py +33 -0
- danielutils/functions/foreach.py +20 -0
- danielutils/functions/isoftype.py +475 -0
- danielutils/functions/isoneof.py +71 -0
- danielutils/functions/multiloop.py +51 -0
- danielutils/functions/parallel_for.py +47 -0
- danielutils/functions/partition.py +45 -0
- danielutils/functions/powerset.py +31 -0
- danielutils/functions/subseteq.py +25 -0
- danielutils/functions/types_subseteq.py +51 -0
- danielutils/generators/__init__.py +3 -0
- danielutils/generators/conditional_generator.py +59 -0
- danielutils/generators/generator_from_stream.py +31 -0
- danielutils/generators/join_generators.py +109 -0
- danielutils/internet.py +92 -0
- danielutils/io_.py +451 -0
- danielutils/java/__init__.py +18 -0
- danielutils/java/interfaces/__init__.py +1 -0
- danielutils/java/interfaces/comparable.py +31 -0
- danielutils/java/java_interface.py +59 -0
- danielutils/logging_/__init__.py +2 -0
- danielutils/logging_/_impl/__init__.py +4 -0
- danielutils/logging_/_impl/builtin_impls/__init__.py +2 -0
- danielutils/logging_/_impl/builtin_impls/file_logger.py +35 -0
- danielutils/logging_/_impl/builtin_impls/print_logger.py +21 -0
- danielutils/logging_/_impl/log_level.py +13 -0
- danielutils/logging_/_impl/logger.py +109 -0
- danielutils/logging_/_impl/logger_strategy_impl_base.py +37 -0
- danielutils/logging_/utils.py +199 -0
- danielutils/lombok/__init__.py +1 -0
- danielutils/lombok/builder.py +68 -0
- danielutils/math_/__init__.py +2 -0
- danielutils/math_/constants.py +103 -0
- danielutils/math_/functions.py +34 -0
- danielutils/math_/math_print.py +52 -0
- danielutils/math_/math_symbols.py +125 -0
- danielutils/metaclasses/__init__.py +5 -0
- danielutils/metaclasses/atomic_class_meta.py +36 -0
- danielutils/metaclasses/implicit_data_deleter_meta.py +87 -0
- danielutils/metaclasses/instance_cache_meta.py +66 -0
- danielutils/metaclasses/interface.py +328 -0
- danielutils/metaclasses/overload_meta.py +48 -0
- danielutils/mock_/__init__.py +1 -0
- danielutils/mock_/mock_module.py +27 -0
- danielutils/path.py +55 -0
- danielutils/print_.py +123 -0
- danielutils/progress_bar/__init__.py +3 -0
- danielutils/progress_bar/ascii_progress_bar.py +161 -0
- danielutils/progress_bar/progress_bar.py +75 -0
- danielutils/progress_bar/progress_bar_pool.py +72 -0
- danielutils/protocols/__init__.py +3 -0
- danielutils/protocols/dictable.py +38 -0
- danielutils/protocols/evaluable.py +26 -0
- danielutils/protocols/serializable.py +51 -0
- danielutils/py.typed +0 -0
- danielutils/random_.py +47 -0
- danielutils/reflection/__init__.py +6 -0
- danielutils/reflection/declarations.py +288 -0
- danielutils/reflection/file/__init__.py +1 -0
- danielutils/reflection/file/file_reflection.py +85 -0
- danielutils/reflection/function/__init__.py +1 -0
- danielutils/reflection/function/function_reflections.py +152 -0
- danielutils/reflection/info_classes/__init__.py +6 -0
- danielutils/reflection/info_classes/argument_info.py +278 -0
- danielutils/reflection/info_classes/class_info.py +204 -0
- danielutils/reflection/info_classes/decorator_info.py +54 -0
- danielutils/reflection/info_classes/file_info.py +1180 -0
- danielutils/reflection/info_classes/folder_info.py +592 -0
- danielutils/reflection/info_classes/function_info.py +551 -0
- danielutils/reflection/info_classes/import_info.py +207 -0
- danielutils/reflection/interpreter/__init__.py +9 -0
- danielutils/reflection/interpreter/callstack.py +57 -0
- danielutils/reflection/interpreter/get_traceback.py +27 -0
- danielutils/reflection/interpreter/interpreter.py +41 -0
- danielutils/reflection/interpreter/is_debugging.py +13 -0
- danielutils/reflection/interpreter/os_.py +33 -0
- danielutils/reflection/interpreter/packages.py +33 -0
- danielutils/reflection/interpreter/python_version.py +33 -0
- danielutils/reflection/interpreter/signals.py +18 -0
- danielutils/reflection/interpreter/tracer.py +175 -0
- danielutils/reflection/module/__init__.py +3 -0
- danielutils/reflection/module/lazy_module.py +104 -0
- danielutils/reflection/module/module_reflections.py +34 -0
- danielutils/reflection/module/package_reflection.py +161 -0
- danielutils/retry_executor/__init__.py +3 -0
- danielutils/retry_executor/backoff_strategies/__init__.py +6 -0
- danielutils/retry_executor/backoff_strategies/constant_backoff.py +25 -0
- danielutils/retry_executor/backoff_strategies/exponential_backoff.py +26 -0
- danielutils/retry_executor/backoff_strategies/functional_backoff.py +29 -0
- danielutils/retry_executor/backoff_strategies/linear_backoff.py +23 -0
- danielutils/retry_executor/backoff_strategies/multiplicative_backoff.py +23 -0
- danielutils/retry_executor/backoff_strategies/no_backoff.py +17 -0
- danielutils/retry_executor/backoff_strategy.py +28 -0
- danielutils/retry_executor/retry_executor.py +55 -0
- danielutils/snippets/__init__.py +1 -0
- danielutils/snippets/try_get.py +28 -0
- danielutils/system/__init__.py +3 -0
- danielutils/system/independent.py +197 -0
- danielutils/system/layered_command.py +130 -0
- danielutils/system/windows/__init__.py +2 -0
- danielutils/system/windows/utils/__init__.py +1 -0
- danielutils/system/windows/utils/filetime.py +19 -0
- danielutils/system/windows/win32_ctime.py +183 -0
- danielutils/system/windows/windows.py +78 -0
- danielutils/testing/__init__.py +1 -0
- danielutils/testing/unittest_/__init__.py +2 -0
- danielutils/testing/unittest_/always_teardown_testcase.py +75 -0
- danielutils/testing/unittest_/auto_cwd_testcase.py +114 -0
- danielutils/text.py +169 -0
- danielutils/time.py +64 -0
- danielutils/tools/__init__.py +1 -0
- danielutils/tools/unittest_test_runner/__init__.py +9 -0
- danielutils/tools/unittest_test_runner/cli.py +70 -0
- danielutils/tools/unittest_test_runner/core/__init__.py +17 -0
- danielutils/tools/unittest_test_runner/core/discovery.py +322 -0
- danielutils/tools/unittest_test_runner/core/execution.py +244 -0
- danielutils/tools/unittest_test_runner/core/parser.py +163 -0
- danielutils/tools/unittest_test_runner/core/runner.py +561 -0
- danielutils/tools/unittest_test_runner/models.py +82 -0
- danielutils/university/__init__.py +7 -0
- danielutils/university/computability_and_complexity/__init__.py +2 -0
- danielutils/university/computability_and_complexity/discreate_finite_automaton.py +89 -0
- danielutils/university/computability_and_complexity/languages/__init__.py +0 -0
- danielutils/university/computability_and_complexity/languages/language.py +17 -0
- danielutils/university/computability_and_complexity/languages/sat.py +71 -0
- danielutils/university/computability_and_complexity/turing_machine.py +47 -0
- danielutils/university/databases/__init__.py +1 -0
- danielutils/university/databases/all.py +756 -0
- danielutils/university/image_proccesing/__init__.py +1 -0
- danielutils/university/image_proccesing/encoding/__init__.py +3 -0
- danielutils/university/image_proccesing/encoding/encoding.py +35 -0
- danielutils/university/image_proccesing/encoding/lossless/__init__.py +4 -0
- danielutils/university/image_proccesing/encoding/lossless/huffman.py +0 -0
- danielutils/university/image_proccesing/encoding/lossless/lossless_encoding.py +10 -0
- danielutils/university/image_proccesing/encoding/lossless/lzw.py +0 -0
- danielutils/university/image_proccesing/encoding/lossless/run_length.py +22 -0
- danielutils/university/image_proccesing/encoding/lossy/__init__.py +1 -0
- danielutils/university/image_proccesing/encoding/lossy/lossy_encoding.py +10 -0
- danielutils/university/image_proccesing/tansformations/__init__.py +0 -0
- danielutils/university/image_proccesing/tansformations/gaussian.py +0 -0
- danielutils/university/image_proccesing/tansformations/gradient.py +0 -0
- danielutils/university/image_proccesing/tansformations/hough.py +0 -0
- danielutils/university/image_proccesing/tansformations/laplacian.py +0 -0
- danielutils/university/image_proccesing/tansformations/transformation.py +11 -0
- danielutils/university/linear_algebra/__init__.py +1 -0
- danielutils/university/linear_algebra/matrix.py +404 -0
- danielutils/university/machine_learning/__init__.py +0 -0
- danielutils/university/machine_learning/activation_functions/__init__.py +2 -0
- danielutils/university/machine_learning/activation_functions/activation_function.py +11 -0
- danielutils/university/machine_learning/activation_functions/relu.py +11 -0
- danielutils/university/machine_learning/neuron.py +15 -0
- danielutils/university/oop/__init__.py +1 -0
- danielutils/university/oop/observer.py +31 -0
- danielutils/university/oop/strategy.py +9 -0
- danielutils/university/probability/__init__.py +7 -0
- danielutils/university/probability/conditional_variable/__init__.py +3 -0
- danielutils/university/probability/conditional_variable/conditional_variable.py +138 -0
- danielutils/university/probability/conditional_variable/continuous/__init__.py +0 -0
- danielutils/university/probability/conditional_variable/discrete/__init__.py +8 -0
- danielutils/university/probability/conditional_variable/discrete/bernoulli.py +38 -0
- danielutils/university/probability/conditional_variable/discrete/bernoulli_sum.py +31 -0
- danielutils/university/probability/conditional_variable/discrete/binomial.py +40 -0
- danielutils/university/probability/conditional_variable/discrete/conditional_from_discrete_probability_func.py +36 -0
- danielutils/university/probability/conditional_variable/discrete/discrete.py +42 -0
- danielutils/university/probability/conditional_variable/discrete/geometric.py +43 -0
- danielutils/university/probability/conditional_variable/discrete/poisson.py +32 -0
- danielutils/university/probability/conditional_variable/discrete/uniform.py +33 -0
- danielutils/university/probability/distributions.py +35 -0
- danielutils/university/probability/expressions/__init__.py +2 -0
- danielutils/university/probability/expressions/accumulation_expression.py +291 -0
- danielutils/university/probability/expressions/probability_expression.py +110 -0
- danielutils/university/probability/funcs/__init__.py +4 -0
- danielutils/university/probability/funcs/covariance.py +12 -0
- danielutils/university/probability/funcs/expected_value.py +41 -0
- danielutils/university/probability/funcs/probability_function.py +14 -0
- danielutils/university/probability/funcs/variance.py +17 -0
- danielutils/university/probability/operator.py +79 -0
- danielutils/university/probability/protocols.py +32 -0
- danielutils/university/probability/supp.py +101 -0
- danielutils/university/probability/transformation.py +44 -0
- danielutils/versioned_imports.py +31 -0
- danielutils-1.1.28.dist-info/METADATA +390 -0
- danielutils-1.1.28.dist-info/RECORD +287 -0
- danielutils-1.1.28.dist-info/WHEEL +5 -0
- danielutils-1.1.28.dist-info/licenses/LICENSE +21 -0
- danielutils-1.1.28.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
from fractions import Fraction
|
|
3
|
+
from typing import Callable, Any
|
|
4
|
+
from ..expressions import ProbabilityExpression, AccumulationExpression
|
|
5
|
+
from ..operator import Operator
|
|
6
|
+
from ..supp import Supp
|
|
7
|
+
from ..protocols import Evaluable
|
|
8
|
+
|
|
9
|
+
def _create_operator(op: Operator, reverse: bool = False) -> Callable[['ConditionalVariable', Any], Evaluable]:
|
|
10
|
+
def operator(self, other) -> Evaluable:
|
|
11
|
+
lhs, rhs = self, other
|
|
12
|
+
if reverse:
|
|
13
|
+
lhs, rhs = rhs, lhs
|
|
14
|
+
|
|
15
|
+
if reverse and op == Operator.ADD and other == 0:
|
|
16
|
+
return self
|
|
17
|
+
|
|
18
|
+
if isinstance(other, ConditionalVariable) and op == Operator.ADD:
|
|
19
|
+
combined = _combine_iid_bernoulli_sums(lhs, other)
|
|
20
|
+
if combined is not None:
|
|
21
|
+
return combined
|
|
22
|
+
|
|
23
|
+
if isinstance(other, (int, float, Fraction)):
|
|
24
|
+
return ProbabilityExpression(lhs, op, rhs)
|
|
25
|
+
|
|
26
|
+
if isinstance(rhs, ProbabilityExpression):
|
|
27
|
+
l = ProbabilityExpression(lhs, op, rhs.lhs)
|
|
28
|
+
r = ProbabilityExpression(rhs.rhs, None, None)
|
|
29
|
+
o = other.op
|
|
30
|
+
return AccumulationExpression(l, o, r)
|
|
31
|
+
|
|
32
|
+
raise NotImplementedError("Not Implemented")
|
|
33
|
+
|
|
34
|
+
return operator
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def _combine_iid_bernoulli_sums(lhs: 'ConditionalVariable', rhs: 'ConditionalVariable'):
|
|
38
|
+
from .discrete.bernoulli import Bernoulli
|
|
39
|
+
from .discrete.binomial import Binomial
|
|
40
|
+
from .discrete.bernoulli_sum import BernoulliSum
|
|
41
|
+
|
|
42
|
+
def count_and_p(variable: ConditionalVariable):
|
|
43
|
+
if isinstance(variable, Bernoulli):
|
|
44
|
+
return 1, variable.p
|
|
45
|
+
if isinstance(variable, BernoulliSum):
|
|
46
|
+
return variable.n, variable.p
|
|
47
|
+
if isinstance(variable, Binomial):
|
|
48
|
+
return variable.n, variable.p
|
|
49
|
+
return None, None
|
|
50
|
+
|
|
51
|
+
left_n, left_p = count_and_p(lhs)
|
|
52
|
+
right_n, right_p = count_and_p(rhs)
|
|
53
|
+
if left_n is None or right_n is None or left_p != right_p:
|
|
54
|
+
return None
|
|
55
|
+
return BernoulliSum(left_p, left_n + right_n)
|
|
56
|
+
|
|
57
|
+
class ConditionalVariable(ABC):
|
|
58
|
+
OPERATOR_TYPE = Callable[['ConditionalVariable', Any], Evaluable]
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
__eq__: OPERATOR_TYPE = _create_operator(Operator.EQ) # type:ignore
|
|
62
|
+
__ne__: OPERATOR_TYPE = _create_operator(Operator.NE) # type:ignore
|
|
63
|
+
__gt__: OPERATOR_TYPE = _create_operator(Operator.GT)
|
|
64
|
+
__ge__: OPERATOR_TYPE = _create_operator(Operator.GE)
|
|
65
|
+
__lt__: OPERATOR_TYPE = _create_operator(Operator.LT)
|
|
66
|
+
__le__: OPERATOR_TYPE = _create_operator(Operator.LE)
|
|
67
|
+
|
|
68
|
+
__or__: OPERATOR_TYPE = _create_operator(Operator.GIVEN)
|
|
69
|
+
__ror__: OPERATOR_TYPE = _create_operator(Operator.GIVEN, reverse=True)
|
|
70
|
+
__and__: OPERATOR_TYPE = _create_operator(Operator.AND)
|
|
71
|
+
__rand__: OPERATOR_TYPE = _create_operator(Operator.AND, reverse=True)
|
|
72
|
+
|
|
73
|
+
__mul__: OPERATOR_TYPE = _create_operator(Operator.MUL)
|
|
74
|
+
__truediv__: OPERATOR_TYPE = _create_operator(Operator.DIV)
|
|
75
|
+
__mod__: OPERATOR_TYPE = _create_operator(Operator.MODULUS)
|
|
76
|
+
__pow__: OPERATOR_TYPE = _create_operator(Operator.POW)
|
|
77
|
+
__add__: OPERATOR_TYPE = _create_operator(Operator.ADD)
|
|
78
|
+
__radd__: OPERATOR_TYPE = _create_operator(Operator.ADD, reverse=True)
|
|
79
|
+
__sub__: OPERATOR_TYPE = _create_operator(Operator.SUB)
|
|
80
|
+
__rsub__: OPERATOR_TYPE = _create_operator(Operator.SUB, reverse=True)
|
|
81
|
+
|
|
82
|
+
def __repr__(self) -> str:
|
|
83
|
+
return f"{self.__class__.__name__}"
|
|
84
|
+
|
|
85
|
+
def is_identical(self, other) -> bool:
|
|
86
|
+
if not isinstance(other, ConditionalVariable):
|
|
87
|
+
return False
|
|
88
|
+
return self is other
|
|
89
|
+
|
|
90
|
+
def is_independent(self, other) -> bool:
|
|
91
|
+
if not isinstance(other, ConditionalVariable):
|
|
92
|
+
return False
|
|
93
|
+
if self is other:
|
|
94
|
+
return False
|
|
95
|
+
if not self.supp.is_finite and not other.supp.is_finite:
|
|
96
|
+
raise ValueError("Can't check if two variables are independent if their supp is not finite")
|
|
97
|
+
|
|
98
|
+
if self.supp != other.supp:
|
|
99
|
+
return False
|
|
100
|
+
from ..funcs import probability_function as P
|
|
101
|
+
for k in self.supp:
|
|
102
|
+
if not (P((self == k) & (other == k)) == P(self == k) * P(other == k)):
|
|
103
|
+
return False
|
|
104
|
+
return True
|
|
105
|
+
|
|
106
|
+
def is_dependent(self, other) -> bool:
|
|
107
|
+
return not self.is_independent(other)
|
|
108
|
+
|
|
109
|
+
def is_correlated(self, other) -> bool:
|
|
110
|
+
if not isinstance(other, ConditionalVariable):
|
|
111
|
+
return False
|
|
112
|
+
from ..funcs import covariance as cov
|
|
113
|
+
return cov(self, other) == 0
|
|
114
|
+
|
|
115
|
+
def is_uncorrelated(self, other) -> bool:
|
|
116
|
+
return not self.is_correlated(other)
|
|
117
|
+
|
|
118
|
+
@abstractmethod
|
|
119
|
+
def evaluate(self, other: Any, operator: Operator) -> Fraction:
|
|
120
|
+
...
|
|
121
|
+
|
|
122
|
+
@abstractmethod
|
|
123
|
+
def between(self, a, b, *args) -> Fraction:
|
|
124
|
+
...
|
|
125
|
+
|
|
126
|
+
@property
|
|
127
|
+
@abstractmethod
|
|
128
|
+
def supp(self) -> Supp:
|
|
129
|
+
...
|
|
130
|
+
|
|
131
|
+
@abstractmethod
|
|
132
|
+
def is_equal(self, other) -> bool:
|
|
133
|
+
...
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
__all__ = [
|
|
137
|
+
"ConditionalVariable"
|
|
138
|
+
]
|
|
File without changes
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
from fractions import Fraction
|
|
2
|
+
|
|
3
|
+
from .discrete import DiscreteConditionalVariable
|
|
4
|
+
from ...supp import FrangeSupp
|
|
5
|
+
from ...operator import Operator
|
|
6
|
+
from ...protocols import ExpectedValueCalculable, VariableCalculable
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class Bernoulli(DiscreteConditionalVariable, ExpectedValueCalculable, VariableCalculable):
|
|
10
|
+
def evaluate(self, n: int, op: Operator) -> Fraction:
|
|
11
|
+
if op == Operator.EQ:
|
|
12
|
+
return self.p if n == 1 else 1 - self.p
|
|
13
|
+
if op == Operator.GE:
|
|
14
|
+
if n <= 0:
|
|
15
|
+
return Fraction(1, 1)
|
|
16
|
+
if n == 1:
|
|
17
|
+
return self.p
|
|
18
|
+
return Fraction(0, 1)
|
|
19
|
+
if op == Operator.LE:
|
|
20
|
+
if n >= 1:
|
|
21
|
+
return Fraction(1, 1)
|
|
22
|
+
if n == 0:
|
|
23
|
+
return 1 - self.p
|
|
24
|
+
return Fraction(0, 1)
|
|
25
|
+
|
|
26
|
+
return 1 - self.evaluate(n, op.inverse)
|
|
27
|
+
|
|
28
|
+
def __init__(self, p) -> None:
|
|
29
|
+
super().__init__(p, FrangeSupp(range(0, 2)))
|
|
30
|
+
|
|
31
|
+
def expected_value(self) -> Fraction:
|
|
32
|
+
return self.p
|
|
33
|
+
|
|
34
|
+
def variance(self) -> Fraction:
|
|
35
|
+
return self.p * (1 - self.p)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
__all__ = ['Bernoulli']
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
from fractions import Fraction
|
|
2
|
+
from typing import Union
|
|
3
|
+
|
|
4
|
+
from .discrete import DiscreteConditionalVariable
|
|
5
|
+
from .binomial import Binomial
|
|
6
|
+
from ...operator import Operator
|
|
7
|
+
from ...supp import FrangeSupp
|
|
8
|
+
from .....better_builtins import frange
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class BernoulliSum(DiscreteConditionalVariable):
|
|
12
|
+
"""Sum of iid Bernoulli variables; evaluates via Binomial."""
|
|
13
|
+
|
|
14
|
+
def __init__(self, p: Union[float, Fraction], n: int) -> None:
|
|
15
|
+
super().__init__(p, FrangeSupp(frange(0, n + 1)))
|
|
16
|
+
self._n = n
|
|
17
|
+
|
|
18
|
+
@property
|
|
19
|
+
def n(self) -> int:
|
|
20
|
+
return self._n
|
|
21
|
+
|
|
22
|
+
def evaluate(self, k: int, op: Operator) -> Fraction:
|
|
23
|
+
return Binomial(self._n, self.p).evaluate(k, op)
|
|
24
|
+
|
|
25
|
+
def is_equal(self, other) -> bool:
|
|
26
|
+
if not isinstance(other, BernoulliSum):
|
|
27
|
+
return False
|
|
28
|
+
return self.p == other.p and self._n == other._n
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
__all__ = ["BernoulliSum"]
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
from fractions import Fraction
|
|
2
|
+
from typing import Union
|
|
3
|
+
from math import factorial
|
|
4
|
+
from .discrete import DiscreteConditionalVariable
|
|
5
|
+
from ...supp import FrangeSupp
|
|
6
|
+
from ...operator import Operator
|
|
7
|
+
from .....better_builtins import frange
|
|
8
|
+
from ...protocols import ExpectedValueCalculable, VariableCalculable
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def choose(n: int, k: int) -> Fraction:
|
|
12
|
+
return Fraction(factorial(n), (factorial(k) * factorial(n - k)))
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class Binomial(DiscreteConditionalVariable, ExpectedValueCalculable, VariableCalculable):
|
|
16
|
+
def __init__(self, n: int, p: Union[float, Fraction]):
|
|
17
|
+
super().__init__(p, FrangeSupp(frange(0, float("inf"))))
|
|
18
|
+
self._n = n
|
|
19
|
+
|
|
20
|
+
@property
|
|
21
|
+
def n(self) -> int:
|
|
22
|
+
return self._n
|
|
23
|
+
|
|
24
|
+
def evaluate(self, k: int, op: Operator) -> Fraction:
|
|
25
|
+
if not 0 <= k <= self.n:
|
|
26
|
+
return Fraction(0, 1)
|
|
27
|
+
|
|
28
|
+
if op == Operator.EQ:
|
|
29
|
+
return choose(self.n, k) * ((1 - self.p) ** (self.n - k)) * (self.p ** k)
|
|
30
|
+
assert False # TODO
|
|
31
|
+
return 1 - self.evaluate(k, op.inverse)
|
|
32
|
+
|
|
33
|
+
def expected_value(self) -> Fraction:
|
|
34
|
+
return self.n * self.p
|
|
35
|
+
|
|
36
|
+
def variance(self) -> Fraction:
|
|
37
|
+
return self.n * self.p * (1 - self.p)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
__all__ = ['Binomial']
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
from typing import Callable
|
|
2
|
+
from fractions import Fraction
|
|
3
|
+
from .discrete import DiscreteConditionalVariable
|
|
4
|
+
from ...supp import FrangeSupp
|
|
5
|
+
from ...operator import Operator
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class ConditionalFromDiscreteProbabilityFunc(DiscreteConditionalVariable):
|
|
9
|
+
def evaluate(self, n: int, op: Operator) -> Fraction:
|
|
10
|
+
if op == Operator.EQ:
|
|
11
|
+
return self.f(n)
|
|
12
|
+
if op == Operator.LT:
|
|
13
|
+
res = Fraction(0, 1)
|
|
14
|
+
for k in range(n):
|
|
15
|
+
res += self.evaluate(k, Operator.EQ)
|
|
16
|
+
return res
|
|
17
|
+
if op == Operator.LE:
|
|
18
|
+
return self.evaluate(n, Operator.LT) + self.evaluate(n, Operator.EQ)
|
|
19
|
+
|
|
20
|
+
return 1 - self.evaluate(n, op.inverse)
|
|
21
|
+
|
|
22
|
+
def __init__(self, p: Callable[[int], Fraction], supp: FrangeSupp) -> None:
|
|
23
|
+
super().__init__(None, supp) # type:ignore
|
|
24
|
+
self.f = p
|
|
25
|
+
|
|
26
|
+
@property
|
|
27
|
+
def p(self):
|
|
28
|
+
raise AttributeError(f"{self.__class__.__name__} has no attribute 'p'")
|
|
29
|
+
|
|
30
|
+
def __repr__(self):
|
|
31
|
+
return self.__class__.__name__
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
__all__ = [
|
|
35
|
+
'ConditionalFromDiscreteProbabilityFunc',
|
|
36
|
+
]
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
from fractions import Fraction
|
|
2
|
+
from typing import Union
|
|
3
|
+
|
|
4
|
+
from ..conditional_variable import ConditionalVariable
|
|
5
|
+
from ...supp import FrangeSupp
|
|
6
|
+
from ...operator import Operator
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class DiscreteConditionalVariable(ConditionalVariable):
|
|
10
|
+
|
|
11
|
+
def __init__(self, p: Union[float, Fraction], supp: FrangeSupp):
|
|
12
|
+
self._p: Fraction = p if isinstance(p, Fraction) else Fraction.from_float(p)
|
|
13
|
+
self._supp: FrangeSupp = supp
|
|
14
|
+
|
|
15
|
+
def __repr__(self) -> str:
|
|
16
|
+
return f"{self.__class__.__name__}({self.p})"
|
|
17
|
+
|
|
18
|
+
@property
|
|
19
|
+
def supp(self) -> FrangeSupp:
|
|
20
|
+
return self._supp
|
|
21
|
+
|
|
22
|
+
@property
|
|
23
|
+
def p(self) -> Fraction:
|
|
24
|
+
return self._p
|
|
25
|
+
|
|
26
|
+
def between(self, a, b, op1: Operator, op2: Operator) -> Fraction: # type:ignore
|
|
27
|
+
a, b = min(a, b), max(a, b)
|
|
28
|
+
if not (float(a).is_integer() and float(b).is_integer()):
|
|
29
|
+
# a = a - (a % self.supp.step)
|
|
30
|
+
# b = b - (b % self.supp.step)
|
|
31
|
+
raise NotImplementedError("Only integers are currently implemented")
|
|
32
|
+
return 1 - (self.evaluate(a, op1.inverse) + self.evaluate(b, op2.inverse))
|
|
33
|
+
|
|
34
|
+
def is_equal(self, other) -> bool:
|
|
35
|
+
if not isinstance(other, DiscreteConditionalVariable):
|
|
36
|
+
return False
|
|
37
|
+
return self.__class__ == other.__class__ and self.p == other.p
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
__all__ = [
|
|
41
|
+
"DiscreteConditionalVariable"
|
|
42
|
+
]
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
from fractions import Fraction
|
|
2
|
+
from typing import Union, Tuple
|
|
3
|
+
|
|
4
|
+
from .discrete import DiscreteConditionalVariable
|
|
5
|
+
from ...operator import Operator
|
|
6
|
+
from .....better_builtins import frange
|
|
7
|
+
from ...supp import FrangeSupp
|
|
8
|
+
from ...protocols import ExpectedValueCalculable, VariableCalculable
|
|
9
|
+
from .....reflection import get_python_version
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class Geometric(DiscreteConditionalVariable, ExpectedValueCalculable, VariableCalculable):
|
|
13
|
+
def __init__(self, p: Union[float, Fraction]):
|
|
14
|
+
super().__init__(Fraction(p), FrangeSupp(frange(1, float("inf"), 1)))
|
|
15
|
+
|
|
16
|
+
def _is_edge_case(self, n: int, op: Operator) -> Tuple[bool, Fraction]:
|
|
17
|
+
if n <= 0 and op in Operator.greater_than_inequalities():
|
|
18
|
+
return True, Fraction(1, 1)
|
|
19
|
+
if n <= 0 and op in Operator.less_than_inequalities():
|
|
20
|
+
return True, Fraction(0, 1)
|
|
21
|
+
return False, Fraction(0, 1)
|
|
22
|
+
|
|
23
|
+
def evaluate(self, n: int, op: Operator) -> Fraction:
|
|
24
|
+
if (tup := self._is_edge_case(n, op))[0]:
|
|
25
|
+
return tup[1]
|
|
26
|
+
del tup
|
|
27
|
+
|
|
28
|
+
if op == Operator.EQ:
|
|
29
|
+
return (Fraction(1 - self.p) ** (n - 1)) * self.p
|
|
30
|
+
if op == Operator.GT:
|
|
31
|
+
return Fraction(1 - self.p) ** n
|
|
32
|
+
if op == Operator.GE:
|
|
33
|
+
return self.evaluate(n - 1, Operator.GT)
|
|
34
|
+
return 1 - self.evaluate(n, op.inverse)
|
|
35
|
+
|
|
36
|
+
def expected_value(self) -> Fraction:
|
|
37
|
+
return Fraction(1, self.p)
|
|
38
|
+
|
|
39
|
+
def variance(self) -> Fraction:
|
|
40
|
+
return Fraction(1 - self.p, self.p ** 2)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
__all__ = ['Geometric']
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
from fractions import Fraction
|
|
2
|
+
from typing import Union
|
|
3
|
+
from math import e, factorial
|
|
4
|
+
|
|
5
|
+
from .discrete import DiscreteConditionalVariable
|
|
6
|
+
from ...supp import FrangeSupp
|
|
7
|
+
from ...operator import Operator
|
|
8
|
+
from .....better_builtins import frange
|
|
9
|
+
from ...protocols import ExpectedValueCalculable, VariableCalculable
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class Poisson(DiscreteConditionalVariable, ExpectedValueCalculable, VariableCalculable):
|
|
13
|
+
def __init__(self, p: Union[float, Fraction]):
|
|
14
|
+
super().__init__(p, FrangeSupp(frange(1, float("inf"))))
|
|
15
|
+
|
|
16
|
+
def evaluate(self, n: int, op: Operator) -> Fraction:
|
|
17
|
+
if n < 0:
|
|
18
|
+
return Fraction(0, 1)
|
|
19
|
+
if op == Operator.EQ:
|
|
20
|
+
return Fraction((e ** (-self.p)) * (self.p ** n), factorial(n)) # type:ignore
|
|
21
|
+
|
|
22
|
+
assert False # TODO
|
|
23
|
+
return 1 - self.evaluate(n, op.inverse) # type:ignore
|
|
24
|
+
|
|
25
|
+
def expected_value(self) -> Fraction:
|
|
26
|
+
return self.p
|
|
27
|
+
|
|
28
|
+
def variance(self) -> Fraction:
|
|
29
|
+
return self.p
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
__all__ = ['Poisson']
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
from fractions import Fraction
|
|
2
|
+
|
|
3
|
+
from ...supp import FrangeSupp
|
|
4
|
+
from ...operator import Operator
|
|
5
|
+
|
|
6
|
+
from .discrete import DiscreteConditionalVariable
|
|
7
|
+
from ...protocols import ExpectedValueCalculable, VariableCalculable
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Uniform(DiscreteConditionalVariable, ExpectedValueCalculable, VariableCalculable):
|
|
11
|
+
def evaluate(self, n: int, op: Operator) -> Fraction:
|
|
12
|
+
if n not in self.supp:
|
|
13
|
+
return Fraction(0, 1)
|
|
14
|
+
|
|
15
|
+
if op == Operator.EQ:
|
|
16
|
+
return self.p
|
|
17
|
+
|
|
18
|
+
assert False # TODO
|
|
19
|
+
return self.evaluate(n, op.inverse)
|
|
20
|
+
|
|
21
|
+
def __init__(self, size) -> None:
|
|
22
|
+
super().__init__(Fraction(1, size), FrangeSupp(range(1, size + 1)))
|
|
23
|
+
|
|
24
|
+
def expected_value(self) -> Fraction:
|
|
25
|
+
return Fraction(Fraction.from_float(self.supp.minimum + self.supp.maximum), 2)
|
|
26
|
+
|
|
27
|
+
def variance(self) -> Fraction:
|
|
28
|
+
return Fraction(
|
|
29
|
+
Fraction.from_float((self.supp.maximum - self.supp.minimum - 1) ** 2 - 1),
|
|
30
|
+
12
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
__all__ = ['Uniform']
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
from .conditional_variable import ConditionalVariable
|
|
3
|
+
from .conditional_variable.discrete import Bernoulli, Geometric, Uniform, Binomial, Poisson
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class DiscreteDistribution(Enum):
|
|
7
|
+
Ber = Bernoulli
|
|
8
|
+
Geo = Geometric
|
|
9
|
+
Unif = Uniform
|
|
10
|
+
Bin = Binomial
|
|
11
|
+
Pois = Poisson
|
|
12
|
+
|
|
13
|
+
def __call__(self, *args, **kwargs) -> ConditionalVariable:
|
|
14
|
+
return self.value(*args, **kwargs)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class ContinuousDistribution(Enum):
|
|
18
|
+
Unif = None
|
|
19
|
+
Exp = None
|
|
20
|
+
Normal = None
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class Distribution:
|
|
24
|
+
Discrete = DiscreteDistribution
|
|
25
|
+
Continuous = ContinuousDistribution
|
|
26
|
+
# def __getattr__(self, item):
|
|
27
|
+
# if item in map(lambda x: x.name, list(self.value)):
|
|
28
|
+
# print("foo")
|
|
29
|
+
# return super().__getattr__(item)
|
|
30
|
+
|
|
31
|
+
__all__ = [
|
|
32
|
+
'DiscreteDistribution',
|
|
33
|
+
'ContinuousDistribution',
|
|
34
|
+
'Distribution'
|
|
35
|
+
]
|