PyDTMC 8.3.0__tar.gz → 8.4.0__tar.gz
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.
- PyDTMC-8.4.0/MANIFEST.in +8 -0
- {PyDTMC-8.3.0 → PyDTMC-8.4.0}/PKG-INFO +2 -1
- {PyDTMC-8.3.0 → PyDTMC-8.4.0}/PyDTMC.egg-info/PKG-INFO +2 -1
- PyDTMC-8.4.0/PyDTMC.egg-info/SOURCES.txt +42 -0
- {PyDTMC-8.3.0 → PyDTMC-8.4.0}/README.md +1 -0
- {PyDTMC-8.3.0 → PyDTMC-8.4.0}/pydtmc/__init__.py +3 -2
- {PyDTMC-8.3.0 → PyDTMC-8.4.0}/pydtmc/custom_types.py +4 -2
- {PyDTMC-8.3.0 → PyDTMC-8.4.0}/pydtmc/generators.py +48 -1
- {PyDTMC-8.3.0 → PyDTMC-8.4.0}/pydtmc/hidden_markov_model.py +2 -1
- {PyDTMC-8.3.0 → PyDTMC-8.4.0}/pydtmc/markov_chain.py +112 -10
- {PyDTMC-8.3.0 → PyDTMC-8.4.0}/pydtmc/plotting.py +209 -5
- {PyDTMC-8.3.0 → PyDTMC-8.4.0}/pydtmc/validation.py +4 -1
- {PyDTMC-8.3.0 → PyDTMC-8.4.0}/setup.py +1 -1
- {PyDTMC-8.3.0 → PyDTMC-8.4.0}/tests/test_generators_instance.py +13 -0
- {PyDTMC-8.3.0 → PyDTMC-8.4.0}/tests/test_generators_static.py +14 -2
- {PyDTMC-8.3.0 → PyDTMC-8.4.0}/tests/test_plotting.py +35 -4
- {PyDTMC-8.3.0 → PyDTMC-8.4.0}/tests/test_properties.py +6 -1
- {PyDTMC-8.3.0 → PyDTMC-8.4.0}/tests/test_validation.py +2 -2
- PyDTMC-8.3.0/MANIFEST.in +0 -15
- PyDTMC-8.3.0/PyDTMC.egg-info/SOURCES.txt +0 -84
- PyDTMC-8.3.0/data/empty +0 -0
- PyDTMC-8.3.0/docs/Makefile +0 -12
- PyDTMC-8.3.0/docs/build/empty +0 -0
- PyDTMC-8.3.0/docs/make.bat +0 -40
- PyDTMC-8.3.0/docs/source/_static/css/style.css +0 -64
- PyDTMC-8.3.0/docs/source/_templates/empty +0 -0
- PyDTMC-8.3.0/docs/source/assessment_functions.rst +0 -10
- PyDTMC-8.3.0/docs/source/conf.py +0 -369
- PyDTMC-8.3.0/docs/source/custom_exceptions.rst +0 -6
- PyDTMC-8.3.0/docs/source/genindex.rst +0 -2
- PyDTMC-8.3.0/docs/source/hidden_markov_model.rst +0 -15
- PyDTMC-8.3.0/docs/source/hidden_markov_model_methods_instance.rst +0 -19
- PyDTMC-8.3.0/docs/source/hidden_markov_model_methods_static.rst +0 -15
- PyDTMC-8.3.0/docs/source/hidden_markov_model_properties.rst +0 -17
- PyDTMC-8.3.0/docs/source/index.rst +0 -19
- PyDTMC-8.3.0/docs/source/markov_chain.rst +0 -15
- PyDTMC-8.3.0/docs/source/markov_chain_methods_instance.rst +0 -49
- PyDTMC-8.3.0/docs/source/markov_chain_methods_static.rst +0 -22
- PyDTMC-8.3.0/docs/source/markov_chain_properties.rst +0 -47
- PyDTMC-8.3.0/docs/source/plotting_functions.rst +0 -10
- PyDTMC-8.3.0/tests/__init__.py +0 -1
- PyDTMC-8.3.0/tests/benchmarks.py +0 -44
- PyDTMC-8.3.0/tests/conftest.py +0 -247
- PyDTMC-8.3.0/tests/files/file_empty.txt +0 -0
- PyDTMC-8.3.0/tests/files/file_filled.txt +0 -0
- PyDTMC-8.3.0/tests/files/file_noextension +0 -0
- PyDTMC-8.3.0/tests/fixtures/fixtures_aliases.json +0 -96
- PyDTMC-8.3.0/tests/fixtures/fixtures_assessments.json +0 -362
- PyDTMC-8.3.0/tests/fixtures/fixtures_benchmarks.json +0 -6
- PyDTMC-8.3.0/tests/fixtures/fixtures_classification.json +0 -92
- PyDTMC-8.3.0/tests/fixtures/fixtures_conversions.json +0 -42
- PyDTMC-8.3.0/tests/fixtures/fixtures_fitting.json +0 -160
- PyDTMC-8.3.0/tests/fixtures/fixtures_generators_instance.json +0 -428
- PyDTMC-8.3.0/tests/fixtures/fixtures_generators_static.json +0 -916
- PyDTMC-8.3.0/tests/fixtures/fixtures_hmm.json +0 -1765
- PyDTMC-8.3.0/tests/fixtures/fixtures_measures.json +0 -1702
- PyDTMC-8.3.0/tests/fixtures/fixtures_plotting.json +0 -36
- PyDTMC-8.3.0/tests/fixtures/fixtures_properties.json +0 -812
- PyDTMC-8.3.0/tests/fixtures/fixtures_simulations.json +0 -882
- PyDTMC-8.3.0/tests/fixtures/fixtures_utilities.json +0 -184
- PyDTMC-8.3.0/tests/fixtures/fixtures_validation.json +0 -3006
- PyDTMC-8.3.0/tests/utilities.py +0 -78
- {PyDTMC-8.3.0 → PyDTMC-8.4.0}/LICENSE.md +0 -0
- {PyDTMC-8.3.0 → PyDTMC-8.4.0}/PyDTMC.egg-info/dependency_links.txt +0 -0
- {PyDTMC-8.3.0 → PyDTMC-8.4.0}/PyDTMC.egg-info/requires.txt +0 -0
- {PyDTMC-8.3.0 → PyDTMC-8.4.0}/PyDTMC.egg-info/top_level.txt +0 -0
- {PyDTMC-8.3.0 → PyDTMC-8.4.0}/pydtmc/assessments.py +0 -0
- {PyDTMC-8.3.0 → PyDTMC-8.4.0}/pydtmc/base_classes.py +0 -0
- {PyDTMC-8.3.0 → PyDTMC-8.4.0}/pydtmc/computations.py +0 -0
- {PyDTMC-8.3.0 → PyDTMC-8.4.0}/pydtmc/decorators.py +0 -0
- {PyDTMC-8.3.0 → PyDTMC-8.4.0}/pydtmc/exceptions.py +0 -0
- {PyDTMC-8.3.0 → PyDTMC-8.4.0}/pydtmc/files_io.py +0 -0
- {PyDTMC-8.3.0 → PyDTMC-8.4.0}/pydtmc/fitting.py +0 -0
- {PyDTMC-8.3.0 → PyDTMC-8.4.0}/pydtmc/measures.py +0 -0
- {PyDTMC-8.3.0 → PyDTMC-8.4.0}/pydtmc/simulations.py +0 -0
- {PyDTMC-8.3.0 → PyDTMC-8.4.0}/pydtmc/utilities.py +0 -0
- {PyDTMC-8.3.0 → PyDTMC-8.4.0}/requirements.txt +0 -0
- {PyDTMC-8.3.0 → PyDTMC-8.4.0}/setup.cfg +0 -0
- {PyDTMC-8.3.0 → PyDTMC-8.4.0}/tests/test_aliases.py +0 -0
- {PyDTMC-8.3.0 → PyDTMC-8.4.0}/tests/test_assessments.py +0 -0
- {PyDTMC-8.3.0 → PyDTMC-8.4.0}/tests/test_classification.py +0 -0
- {PyDTMC-8.3.0 → PyDTMC-8.4.0}/tests/test_conversions.py +0 -0
- {PyDTMC-8.3.0 → PyDTMC-8.4.0}/tests/test_fitting.py +0 -0
- {PyDTMC-8.3.0 → PyDTMC-8.4.0}/tests/test_hmm.py +0 -0
- {PyDTMC-8.3.0 → PyDTMC-8.4.0}/tests/test_measures.py +0 -0
- {PyDTMC-8.3.0 → PyDTMC-8.4.0}/tests/test_simulations.py +0 -0
- {PyDTMC-8.3.0 → PyDTMC-8.4.0}/tests/test_utilities.py +0 -0
PyDTMC-8.4.0/MANIFEST.in
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# Inclusions
|
|
2
|
+
graft data docs tests
|
|
3
|
+
include README.md LICENSE.md requirements.txt setup.py
|
|
4
|
+
|
|
5
|
+
# Exclusions
|
|
6
|
+
global-exclude *.dll *.py[cdo] *.so .env .git* __pycache__ *~
|
|
7
|
+
prune .git .github .idea dist docs/build images
|
|
8
|
+
exclude .readthedocs.yaml CODE_OF_CONDUCT.md CONTRIBUTING.md
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: PyDTMC
|
|
3
|
-
Version: 8.
|
|
3
|
+
Version: 8.4.0
|
|
4
4
|
Summary: A full-featured and lightweight library for discrete-time Markov chains analysis.
|
|
5
5
|
Home-page: https://github.com/TommasoBelluzzo/PyDTMC
|
|
6
6
|
Author: Tommaso Belluzzo
|
|
@@ -149,6 +149,7 @@ DISCRETE-TIME MARKOV CHAIN
|
|
|
149
149
|
> APERIODIC: YES
|
|
150
150
|
> IRREDUCIBLE: NO
|
|
151
151
|
ABSORBING: YES
|
|
152
|
+
MONOTONE: NO
|
|
152
153
|
REGULAR: NO
|
|
153
154
|
REVERSIBLE: YES
|
|
154
155
|
SYMMETRIC: NO
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: PyDTMC
|
|
3
|
-
Version: 8.
|
|
3
|
+
Version: 8.4.0
|
|
4
4
|
Summary: A full-featured and lightweight library for discrete-time Markov chains analysis.
|
|
5
5
|
Home-page: https://github.com/TommasoBelluzzo/PyDTMC
|
|
6
6
|
Author: Tommaso Belluzzo
|
|
@@ -149,6 +149,7 @@ DISCRETE-TIME MARKOV CHAIN
|
|
|
149
149
|
> APERIODIC: YES
|
|
150
150
|
> IRREDUCIBLE: NO
|
|
151
151
|
ABSORBING: YES
|
|
152
|
+
MONOTONE: NO
|
|
152
153
|
REGULAR: NO
|
|
153
154
|
REVERSIBLE: YES
|
|
154
155
|
SYMMETRIC: NO
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
LICENSE.md
|
|
2
|
+
MANIFEST.in
|
|
3
|
+
README.md
|
|
4
|
+
requirements.txt
|
|
5
|
+
setup.cfg
|
|
6
|
+
setup.py
|
|
7
|
+
PyDTMC.egg-info/PKG-INFO
|
|
8
|
+
PyDTMC.egg-info/SOURCES.txt
|
|
9
|
+
PyDTMC.egg-info/dependency_links.txt
|
|
10
|
+
PyDTMC.egg-info/requires.txt
|
|
11
|
+
PyDTMC.egg-info/top_level.txt
|
|
12
|
+
pydtmc/__init__.py
|
|
13
|
+
pydtmc/assessments.py
|
|
14
|
+
pydtmc/base_classes.py
|
|
15
|
+
pydtmc/computations.py
|
|
16
|
+
pydtmc/custom_types.py
|
|
17
|
+
pydtmc/decorators.py
|
|
18
|
+
pydtmc/exceptions.py
|
|
19
|
+
pydtmc/files_io.py
|
|
20
|
+
pydtmc/fitting.py
|
|
21
|
+
pydtmc/generators.py
|
|
22
|
+
pydtmc/hidden_markov_model.py
|
|
23
|
+
pydtmc/markov_chain.py
|
|
24
|
+
pydtmc/measures.py
|
|
25
|
+
pydtmc/plotting.py
|
|
26
|
+
pydtmc/simulations.py
|
|
27
|
+
pydtmc/utilities.py
|
|
28
|
+
pydtmc/validation.py
|
|
29
|
+
tests/test_aliases.py
|
|
30
|
+
tests/test_assessments.py
|
|
31
|
+
tests/test_classification.py
|
|
32
|
+
tests/test_conversions.py
|
|
33
|
+
tests/test_fitting.py
|
|
34
|
+
tests/test_generators_instance.py
|
|
35
|
+
tests/test_generators_static.py
|
|
36
|
+
tests/test_hmm.py
|
|
37
|
+
tests/test_measures.py
|
|
38
|
+
tests/test_plotting.py
|
|
39
|
+
tests/test_properties.py
|
|
40
|
+
tests/test_simulations.py
|
|
41
|
+
tests/test_utilities.py
|
|
42
|
+
tests/test_validation.py
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
2
|
|
|
3
3
|
__title__ = 'PyDTMC'
|
|
4
|
-
__version__ = '8.
|
|
4
|
+
__version__ = '8.4.0'
|
|
5
5
|
__author__ = 'Tommaso Belluzzo'
|
|
6
6
|
|
|
7
7
|
__all__ = [
|
|
8
8
|
'ValidationError',
|
|
9
9
|
'HiddenMarkovModel', 'MarkovChain',
|
|
10
10
|
'assess_first_order', 'assess_homogeneity', 'assess_markov_property', 'assess_stationarity', 'assess_theoretical_compatibility',
|
|
11
|
-
'plot_comparison', 'plot_eigenvalues', 'plot_graph', 'plot_redistributions', 'plot_sequence', 'plot_trellis'
|
|
11
|
+
'plot_comparison', 'plot_eigenvalues', 'plot_flow', 'plot_graph', 'plot_redistributions', 'plot_sequence', 'plot_trellis'
|
|
12
12
|
]
|
|
13
13
|
|
|
14
14
|
from pydtmc.exceptions import (
|
|
@@ -34,6 +34,7 @@ from pydtmc.assessments import (
|
|
|
34
34
|
from pydtmc.plotting import (
|
|
35
35
|
plot_comparison,
|
|
36
36
|
plot_eigenvalues,
|
|
37
|
+
plot_flow,
|
|
37
38
|
plot_graph,
|
|
38
39
|
plot_redistributions,
|
|
39
40
|
plot_sequence,
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
2
|
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
3
5
|
__all__ = [
|
|
4
6
|
# Base Types
|
|
5
7
|
'tany',
|
|
@@ -157,11 +159,11 @@ tstack = _tp.List[_ins.FrameInfo]
|
|
|
157
159
|
ostack = _tp.Optional[tstack]
|
|
158
160
|
|
|
159
161
|
# noinspection PyTypeHints
|
|
160
|
-
thmm = _tp.
|
|
162
|
+
thmm = _tp.ForwardRef('HiddenMarkovModel')
|
|
161
163
|
ohmm = _tp.Optional[thmm]
|
|
162
164
|
|
|
163
165
|
# noinspection PyTypeHints
|
|
164
|
-
tmc = _tp.
|
|
166
|
+
tmc = _tp.ForwardRef('MarkovChain')
|
|
165
167
|
omc = _tp.Optional[tmc]
|
|
166
168
|
|
|
167
169
|
tmodel = _tp.Union[thmm, tmc]
|
|
@@ -15,6 +15,7 @@ __all__ = [
|
|
|
15
15
|
'mc_gamblers_ruin',
|
|
16
16
|
'mc_lazy',
|
|
17
17
|
'mc_lump',
|
|
18
|
+
'mc_population_genetics_model',
|
|
18
19
|
'mc_random',
|
|
19
20
|
'mc_sub',
|
|
20
21
|
'mc_urn_model'
|
|
@@ -883,6 +884,52 @@ def mc_lump(p: _tarray, states: _tlist_str, partitions: _tlists_int) -> _tmc_gen
|
|
|
883
884
|
return p_lump, state_names, None
|
|
884
885
|
|
|
885
886
|
|
|
887
|
+
def mc_population_genetics_model(model: str, n: int, s: float, u: float, v: float) -> _tmc_generation:
|
|
888
|
+
|
|
889
|
+
size = n + 1
|
|
890
|
+
|
|
891
|
+
p = _np.zeros((size, size), dtype=float)
|
|
892
|
+
p[0, 0] = 1.0
|
|
893
|
+
p[n, n] = 1.0
|
|
894
|
+
|
|
895
|
+
ui = 1.0 - u
|
|
896
|
+
vi = 1.0 - v
|
|
897
|
+
|
|
898
|
+
if model == 'moran':
|
|
899
|
+
|
|
900
|
+
r = 1.0 - s
|
|
901
|
+
|
|
902
|
+
for i in range(1, n):
|
|
903
|
+
nmi = n - i
|
|
904
|
+
ri = r * i
|
|
905
|
+
|
|
906
|
+
pm1 = (i / n) * (((ri * v) + (nmi * vi)) / (ri + nmi))
|
|
907
|
+
pp1 = (nmi / n) * (((ri * ui) + (nmi * v)) / (ri + nmi))
|
|
908
|
+
|
|
909
|
+
p[i, i - 1] = pm1
|
|
910
|
+
p[i, i] = 1.0 - pm1 - pp1
|
|
911
|
+
p[i, i + 1] = pp1
|
|
912
|
+
|
|
913
|
+
else:
|
|
914
|
+
|
|
915
|
+
q = _np.arange(0, size)
|
|
916
|
+
|
|
917
|
+
for i in range(1, n):
|
|
918
|
+
|
|
919
|
+
k = i / n
|
|
920
|
+
|
|
921
|
+
pm = (k * ui) + ((1.0 - k) * v)
|
|
922
|
+
ps = min((pm * (1.0 + s)) / ((pm * (1.0 + s)) - pm + 1.0), 1.0)
|
|
923
|
+
|
|
924
|
+
p[i, :] = _np.exp(_sps.binom.logpmf(q, n, ps))
|
|
925
|
+
|
|
926
|
+
p /= _np.sum(p, axis=1, keepdims=True)
|
|
927
|
+
|
|
928
|
+
state_names = [f'{i:d}' for i in range(1, size + 1)]
|
|
929
|
+
|
|
930
|
+
return p, state_names, None
|
|
931
|
+
|
|
932
|
+
|
|
886
933
|
# noinspection DuplicatedCode
|
|
887
934
|
def mc_random(rng: _trand, size: int, zeros: int, mask: _tarray) -> _tmc_generation:
|
|
888
935
|
|
|
@@ -968,7 +1015,7 @@ def mc_sub(p: _tarray, states: _tlist_str, adjacency_matrix: _tarray, sub_states
|
|
|
968
1015
|
return p, state_names, None
|
|
969
1016
|
|
|
970
1017
|
|
|
971
|
-
def mc_urn_model(
|
|
1018
|
+
def mc_urn_model(model: str, n: int) -> _tmc_generation:
|
|
972
1019
|
|
|
973
1020
|
dn = n * 2
|
|
974
1021
|
size = dn + 1
|
|
@@ -542,7 +542,8 @@ class HiddenMarkovModel(_Model):
|
|
|
542
542
|
def to_matrices(self) -> _tpair_array:
|
|
543
543
|
|
|
544
544
|
"""
|
|
545
|
-
|
|
545
|
+
The method returns a tuple of two items representing the underlying matrices of the hidden Markov model.
|
|
546
|
+
|
|
546
547
|
| The first item is the transition matrix and the second item is the emission matrix.
|
|
547
548
|
"""
|
|
548
549
|
|
|
@@ -117,6 +117,7 @@ from .generators import (
|
|
|
117
117
|
mc_gamblers_ruin as _gamblers_ruin,
|
|
118
118
|
mc_lazy as _lazy,
|
|
119
119
|
mc_lump as _lump,
|
|
120
|
+
mc_population_genetics_model as _population_genetics_model,
|
|
120
121
|
mc_random as _random,
|
|
121
122
|
mc_sub as _sub,
|
|
122
123
|
mc_urn_model as _urn_model
|
|
@@ -174,6 +175,7 @@ from .validation import (
|
|
|
174
175
|
validate_labels_current as _validate_labels_current,
|
|
175
176
|
validate_labels_input as _validate_labels_input,
|
|
176
177
|
validate_mask as _validate_mask,
|
|
178
|
+
validate_markov_chain as _validate_markov_chain,
|
|
177
179
|
validate_matrix as _validate_matrix,
|
|
178
180
|
validate_partitions as _validate_partitions,
|
|
179
181
|
validate_random_distribution as _validate_random_distribution,
|
|
@@ -257,6 +259,7 @@ class MarkovChain(_Model):
|
|
|
257
259
|
lines.append(f' > APERIODIC: {("YES" if self.is_aperiodic else "NO (" + str(self.period) + ")")}')
|
|
258
260
|
lines.append(f' > IRREDUCIBLE: {("YES" if self.is_irreducible else "NO")}')
|
|
259
261
|
lines.append(f' ABSORBING: {("YES" if self.is_absorbing else "NO")}')
|
|
262
|
+
lines.append(f' MONOTONE: {("YES" if self.is_stochastically_monotone else "NO")}')
|
|
260
263
|
lines.append(f' REGULAR: {("YES" if self.is_regular else "NO")}')
|
|
261
264
|
lines.append(f' REVERSIBLE: {("YES" if self.is_reversible else "NO")}')
|
|
262
265
|
lines.append(f' SYMMETRIC: {("YES" if self.is_symmetric else "NO")}')
|
|
@@ -690,6 +693,31 @@ class MarkovChain(_Model):
|
|
|
690
693
|
|
|
691
694
|
return result
|
|
692
695
|
|
|
696
|
+
@_cached_property
|
|
697
|
+
@_object_mark(aliases=['is_monotone'])
|
|
698
|
+
def is_stochastically_monotone(self) -> bool:
|
|
699
|
+
|
|
700
|
+
"""
|
|
701
|
+
A property indicating whether the Markov chain is stochastically monotone.
|
|
702
|
+
"""
|
|
703
|
+
|
|
704
|
+
result = True
|
|
705
|
+
|
|
706
|
+
for m in range(1, self.__size):
|
|
707
|
+
|
|
708
|
+
sm = _np.sum(self.__p[:, m:], axis=1)
|
|
709
|
+
|
|
710
|
+
for k, l in zip(range(self.__size - 1), range(1, self.__size)):
|
|
711
|
+
|
|
712
|
+
sk = sm[k]
|
|
713
|
+
sl = sm[l]
|
|
714
|
+
|
|
715
|
+
if sl < sk:
|
|
716
|
+
result = False
|
|
717
|
+
break
|
|
718
|
+
|
|
719
|
+
return result
|
|
720
|
+
|
|
693
721
|
@_cached_property
|
|
694
722
|
def is_symmetric(self) -> bool:
|
|
695
723
|
|
|
@@ -1547,6 +1575,36 @@ class MarkovChain(_Model):
|
|
|
1547
1575
|
|
|
1548
1576
|
return self.__cache['mrt']
|
|
1549
1577
|
|
|
1578
|
+
@_object_mark(instance_generator=True)
|
|
1579
|
+
def merge_with(self, other: _tmc, gamma: float) -> _tmc:
|
|
1580
|
+
|
|
1581
|
+
"""
|
|
1582
|
+
The method returns a Markov chain whose transition matrix is defined below.
|
|
1583
|
+
|
|
1584
|
+
| :math:`p_{new} = (1 - \gamma) p_{current} + \gamma p_{other}`
|
|
1585
|
+
|
|
1586
|
+
:param other: the other Markov chain to be merged.
|
|
1587
|
+
:param gamma: the merger blending factor.
|
|
1588
|
+
:raises ValidationError: if any input argument is not compliant.
|
|
1589
|
+
"""
|
|
1590
|
+
|
|
1591
|
+
try:
|
|
1592
|
+
|
|
1593
|
+
other = _validate_markov_chain(other, self.__size)
|
|
1594
|
+
gamma = _validate_float(gamma, lower_limit=(0.0, True), upper_limit=(1.0, True))
|
|
1595
|
+
|
|
1596
|
+
except Exception as ex: # pragma: no cover
|
|
1597
|
+
raise _create_validation_error(ex, _ins.trace()) from None
|
|
1598
|
+
|
|
1599
|
+
p_current = self.__p
|
|
1600
|
+
p_other = other.p
|
|
1601
|
+
|
|
1602
|
+
p = ((1.0 - gamma) * p_current) + (gamma * p_other)
|
|
1603
|
+
states = _create_labels(self.__size, 'M')
|
|
1604
|
+
mc = MarkovChain(p, states)
|
|
1605
|
+
|
|
1606
|
+
return mc
|
|
1607
|
+
|
|
1550
1608
|
@_object_mark(aliases=['mt'])
|
|
1551
1609
|
def mixing_time(self, initial_distribution: _onumeric = None, jump: int = 1, cutoff_type: str = 'natural') -> _oint:
|
|
1552
1610
|
|
|
@@ -2050,7 +2108,7 @@ class MarkovChain(_Model):
|
|
|
2050
2108
|
sigma = _validate_float(sigma, lower_limit=(0.0, True))
|
|
2051
2109
|
rho = _validate_float(rho, lower_limit=(-1.0, False), upper_limit=(1.0, False))
|
|
2052
2110
|
|
|
2053
|
-
if states is not None:
|
|
2111
|
+
if states is not None: # pragma: no cover
|
|
2054
2112
|
states = _validate_labels_input(states, size)
|
|
2055
2113
|
|
|
2056
2114
|
if approximation_type == 'tauchen':
|
|
@@ -2091,7 +2149,7 @@ class MarkovChain(_Model):
|
|
|
2091
2149
|
p = _validate_vector(p, 'creation', False)
|
|
2092
2150
|
q = _validate_vector(q, 'annihilation', False)
|
|
2093
2151
|
|
|
2094
|
-
if states is not None:
|
|
2152
|
+
if states is not None: # pragma: no cover
|
|
2095
2153
|
states = _validate_labels_input(states, {p.shape[0], q.shape[0]}.pop())
|
|
2096
2154
|
|
|
2097
2155
|
except Exception as ex: # pragma: no cover
|
|
@@ -2136,7 +2194,7 @@ class MarkovChain(_Model):
|
|
|
2136
2194
|
diagonal_bias_factor = None if diagonal_bias_factor is None else _validate_float(diagonal_bias_factor, lower_limit=(0.0, True))
|
|
2137
2195
|
shift_concentration = _validate_boolean(shift_concentration)
|
|
2138
2196
|
|
|
2139
|
-
if states is not None:
|
|
2197
|
+
if states is not None: # pragma: no cover
|
|
2140
2198
|
states = _validate_labels_input(states, size)
|
|
2141
2199
|
|
|
2142
2200
|
except Exception as ex: # pragma: no cover
|
|
@@ -2463,7 +2521,7 @@ class MarkovChain(_Model):
|
|
|
2463
2521
|
size = _validate_integer(size, lower_limit=(3, False))
|
|
2464
2522
|
w = _validate_float(w, lower_limit=(0.0, True), upper_limit=(1.0, True))
|
|
2465
2523
|
|
|
2466
|
-
if states is not None:
|
|
2524
|
+
if states is not None: # pragma: no cover
|
|
2467
2525
|
states = _validate_labels_input(states, size)
|
|
2468
2526
|
|
|
2469
2527
|
except Exception as ex: # pragma: no cover
|
|
@@ -2503,6 +2561,50 @@ class MarkovChain(_Model):
|
|
|
2503
2561
|
|
|
2504
2562
|
return mc
|
|
2505
2563
|
|
|
2564
|
+
@staticmethod
|
|
2565
|
+
@_object_mark(instance_generator=True)
|
|
2566
|
+
def population_genetics_model(model: str, n: int, s: float = 0.0, u: float = 1.0e-9, v: float = 1.0e-9, states: _olist_str = None) -> _tmc:
|
|
2567
|
+
|
|
2568
|
+
"""
|
|
2569
|
+
The method generates a Markov chain based on the specified population genetics model.
|
|
2570
|
+
|
|
2571
|
+
:param model:
|
|
2572
|
+
- **moran** for the Moran model;
|
|
2573
|
+
- **wright-fisher** for the Wright-Fisher model.
|
|
2574
|
+
:param n: the number of individuals.
|
|
2575
|
+
:param s: the selection intensity.
|
|
2576
|
+
:param u: the backward mutation rate.
|
|
2577
|
+
:param v: the forward mutation rate.
|
|
2578
|
+
:param states: the name of each state (*if omitted, an increasing sequence of integers starting at 1*).
|
|
2579
|
+
:raises ValidationError: if any input argument is not compliant.
|
|
2580
|
+
"""
|
|
2581
|
+
|
|
2582
|
+
try:
|
|
2583
|
+
|
|
2584
|
+
model = _validate_enumerator(model, ['moran', 'wright-fisher'])
|
|
2585
|
+
n = _validate_integer(n, lower_limit=(2, False), upper_limit=(500, False))
|
|
2586
|
+
s = _validate_float(s, lower_limit=(-1.0, False))
|
|
2587
|
+
u = _validate_float(u, lower_limit=(0.0, False), upper_limit=(1.0, False))
|
|
2588
|
+
v = _validate_float(v, lower_limit=(0.0, False), upper_limit=(1.0, False))
|
|
2589
|
+
|
|
2590
|
+
if states is not None: # pragma: no cover
|
|
2591
|
+
states = _validate_labels_input(states, n + 1)
|
|
2592
|
+
|
|
2593
|
+
except Exception as ex: # pragma: no cover
|
|
2594
|
+
raise _create_validation_error(ex, _ins.trace()) from None
|
|
2595
|
+
|
|
2596
|
+
if model == 'wright-fisher' and (4.0 * n * max(u, v)) > 1.0:
|
|
2597
|
+
raise _ValidationError('The highest mutation rate specified is too high for the Wright-Fisher model.')
|
|
2598
|
+
|
|
2599
|
+
p, states_out, _ = _population_genetics_model(model, n, s, u, v)
|
|
2600
|
+
|
|
2601
|
+
if states is None:
|
|
2602
|
+
states = states_out
|
|
2603
|
+
|
|
2604
|
+
mc = MarkovChain(p, states)
|
|
2605
|
+
|
|
2606
|
+
return mc
|
|
2607
|
+
|
|
2506
2608
|
# noinspection DuplicatedCode
|
|
2507
2609
|
@staticmethod
|
|
2508
2610
|
@_object_mark(instance_generator=True, random_output=True)
|
|
@@ -2528,7 +2630,7 @@ class MarkovChain(_Model):
|
|
|
2528
2630
|
rng = _create_rng(seed)
|
|
2529
2631
|
size = _validate_integer(size, lower_limit=(2, False))
|
|
2530
2632
|
|
|
2531
|
-
if states is not None:
|
|
2633
|
+
if states is not None: # pragma: no cover
|
|
2532
2634
|
states = _validate_labels_input(states, size)
|
|
2533
2635
|
|
|
2534
2636
|
zeros = _validate_integer(zeros, lower_limit=(0, False))
|
|
@@ -2597,31 +2699,31 @@ class MarkovChain(_Model):
|
|
|
2597
2699
|
|
|
2598
2700
|
@staticmethod
|
|
2599
2701
|
@_object_mark(instance_generator=True)
|
|
2600
|
-
def urn_model(
|
|
2702
|
+
def urn_model(model: str, n: int, states: _olist_str = None) -> _tmc:
|
|
2601
2703
|
|
|
2602
2704
|
"""
|
|
2603
2705
|
The method generates a Markov chain of size **2N + 1** based on the specified urn model.
|
|
2604
2706
|
|
|
2605
|
-
:param n: the number of elements in each urn.
|
|
2606
2707
|
:param model:
|
|
2607
2708
|
- **bernoulli-laplace** for the Bernoulli-Laplace urn model;
|
|
2608
2709
|
- **ehrenfest** for the Ehrenfest urn model.
|
|
2710
|
+
:param n: the number of elements in each urn.
|
|
2609
2711
|
:param states: the name of each state (*if omitted, an increasing sequence of integers starting at 1*).
|
|
2610
2712
|
:raises ValidationError: if any input argument is not compliant.
|
|
2611
2713
|
"""
|
|
2612
2714
|
|
|
2613
2715
|
try:
|
|
2614
2716
|
|
|
2615
|
-
n = _validate_integer(n, lower_limit=(1, False))
|
|
2616
2717
|
model = _validate_enumerator(model, ['bernoulli-laplace', 'ehrenfest'])
|
|
2718
|
+
n = _validate_integer(n, lower_limit=(1, False))
|
|
2617
2719
|
|
|
2618
|
-
if states is not None:
|
|
2720
|
+
if states is not None: # pragma: no cover
|
|
2619
2721
|
states = _validate_labels_input(states, (2 * n) + 1)
|
|
2620
2722
|
|
|
2621
2723
|
except Exception as ex: # pragma: no cover
|
|
2622
2724
|
raise _create_validation_error(ex, _ins.trace()) from None
|
|
2623
2725
|
|
|
2624
|
-
p, states_out, _ = _urn_model(
|
|
2726
|
+
p, states_out, _ = _urn_model(model, n)
|
|
2625
2727
|
|
|
2626
2728
|
if states is None:
|
|
2627
2729
|
states = states_out
|