From fa2197d35860356c7919c64ccbc29d13b722c376 Mon Sep 17 00:00:00 2001 From: Nicholay Shestakov Date: Mon, 15 Dec 2025 15:15:44 +0300 Subject: [PATCH 1/4] Add walker scheme --- src/rewriting_hw_1/walker_scheme.py | 73 +++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 src/rewriting_hw_1/walker_scheme.py diff --git a/src/rewriting_hw_1/walker_scheme.py b/src/rewriting_hw_1/walker_scheme.py new file mode 100644 index 0000000..16d8218 --- /dev/null +++ b/src/rewriting_hw_1/walker_scheme.py @@ -0,0 +1,73 @@ +class WalkerScheme: + def __init__(self, events_and_probabilities: list[tuple[str, int]]): + if sum(probability[1] for probability in events_and_probabilities) != 1: + raise Exception("Сумма вероятностей не равна 1.") + self.table = self._get_table(events_and_probabilities) + + def _get_table(self, events_and_probabilities): + """Генерирует таблицу Уолкера.""" + equal_probability = ( + 1 / len(events_and_probabilities) + ) # Переменная с вероятностью события, если бы все события были равновероятными. + probabilities = { + event: equal_probability for event, _ in events_and_probabilities + } # Словарь, где изначально все вероятности эквивалентны и меняются после донорства кого-то кому-то. + how_many_added_for_event = { + event: 0 for event, _ in events_and_probabilities + } # Для заполнения нерозданных отрезков в конце + table = [] + global_barrier = 0 + + for i in range(len(events_and_probabilities)): + break_flag = False + for donor_event, donor_probability in events_and_probabilities: + if donor_probability < probabilities[donor_event]: + for ( + recipient_event, + recipient_probability, + ) in events_and_probabilities: + if recipient_probability > probabilities[recipient_event]: + table.append( + ( + donor_event, + recipient_event, + global_barrier + + equal_probability + - probabilities[donor_event] + + donor_probability, # Подсчёт барьера, где к глобальному барьеру прибавляется остаток вероятности донора по модулю эквивалентной вероятности + ) + ) + global_barrier += equal_probability + + how_many_added_for_event[recipient_event] += ( + equal_probability + - probabilities[donor_event] + + donor_probability + ) + how_many_added_for_event[donor_event] += ( + probabilities[donor_event] - donor_probability + ) + + probabilities[recipient_event] += ( + probabilities[donor_event] - donor_probability + ) + probabilities[donor_event] = donor_probability + + break_flag = True + break + if break_flag: + break + else: # Для оставшихся + for event, probability in how_many_added_for_event.items(): + print(how_many_added_for_event) + if probability < probabilities[event]: + global_barrier += equal_probability + table.append((event, event, global_barrier)) + break + + return table + + +scheme = WalkerScheme([("A", 0.1), ("B", 0.5), ("C", 0.4)]) + +print(scheme.table) From 1d5d49a3ebc786389a20d6e288dba1b7e2c32186 Mon Sep 17 00:00:00 2001 From: Nicholay Shestakov Date: Mon, 15 Dec 2025 15:16:01 +0300 Subject: [PATCH 2/4] Add test for walker scheme --- tests/walker_scheme_test.py | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 tests/walker_scheme_test.py diff --git a/tests/walker_scheme_test.py b/tests/walker_scheme_test.py new file mode 100644 index 0000000..de1cdbf --- /dev/null +++ b/tests/walker_scheme_test.py @@ -0,0 +1,8 @@ +from rewriting_hw_1.walker_scheme import WalkerScheme + + +def test_exception(): + try: + scheme = WalkerScheme([("A", 0.1), ("B", 1)]) + except Exception as e: + assert str(e) == "Сумма вероятностей не равна 1." From e7dba2c969f203fb72752bb204be17df802eaa57 Mon Sep 17 00:00:00 2001 From: Nicholay Shestakov Date: Mon, 15 Dec 2025 15:21:21 +0300 Subject: [PATCH 3/4] Add get_random in walker scheme class --- src/rewriting_hw_1/walker_scheme.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/rewriting_hw_1/walker_scheme.py b/src/rewriting_hw_1/walker_scheme.py index 16d8218..26ee8b4 100644 --- a/src/rewriting_hw_1/walker_scheme.py +++ b/src/rewriting_hw_1/walker_scheme.py @@ -1,3 +1,6 @@ +from math import floor + + class WalkerScheme: def __init__(self, events_and_probabilities: list[tuple[str, int]]): if sum(probability[1] for probability in events_and_probabilities) != 1: @@ -67,7 +70,7 @@ def _get_table(self, events_and_probabilities): return table - -scheme = WalkerScheme([("A", 0.1), ("B", 0.5), ("C", 0.4)]) - -print(scheme.table) + def get_random(self, probability): + if self.table[floor(probability * len(self.table))][2] > probability: + return self.table[floor(probability * len(self.table))][0] + return self.table[floor(probability * len(self.table))][1] From 86396bac179d3314f0e379e2a838d56f4e50ec32 Mon Sep 17 00:00:00 2001 From: Nicholay Shestakov Date: Mon, 15 Dec 2025 15:23:54 +0300 Subject: [PATCH 4/4] Update walker scheme test --- tests/walker_scheme_test.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/walker_scheme_test.py b/tests/walker_scheme_test.py index de1cdbf..41ab194 100644 --- a/tests/walker_scheme_test.py +++ b/tests/walker_scheme_test.py @@ -4,5 +4,6 @@ def test_exception(): try: scheme = WalkerScheme([("A", 0.1), ("B", 1)]) + print(scheme) except Exception as e: assert str(e) == "Сумма вероятностей не равна 1."