-
-
Notifications
You must be signed in to change notification settings - Fork 51.1k
Expand file tree
/
Copy pathchaos_machine.py
More file actions
137 lines (101 loc) · 3.29 KB
/
Copy pathchaos_machine.py
File metadata and controls
137 lines (101 loc) · 3.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
"""Example of a simple chaos machine (chaos-based PRNG).
A chaos machine uses chaotic dynamical systems to generate
pseudo-random numbers. This implementation combines a logistic map
with a Xorshift PRNG.
References:
- https://en.wikipedia.org/wiki/Chaos_theory
- https://en.wikipedia.org/wiki/Xorshift
"""
# Chaos Machine (K, t, m)
K = [0.33, 0.44, 0.55, 0.44, 0.33]
t = 3
m = 5
# Buffer Space (with Parameters Space)
buffer_space: list[float] = []
params_space: list[float] = []
# Machine Time
machine_time = 0
def push(seed: float) -> None:
"""Push a seed value into the chaos machine.
Updates the internal buffer and parameter spaces using a logistic-map
transition function.
Args:
seed: A numeric seed to push into the machine.
"""
global buffer_space, params_space, machine_time
# Choosing Dynamical Systems (All)
for key, value in enumerate(buffer_space):
# Evolution Parameter
e = float(seed / value)
# Control Theory: Orbit Change
value = (buffer_space[(key + 1) % m] + e) % 1
# Control Theory: Trajectory Change
r = (params_space[key] + e) % 1 + 3
# Modification (Transition Function) - Jumps
buffer_space[key] = round(float(r * value * (1 - value)), 10)
params_space[key] = r # Saving to Parameters Space
# Logistic Map
assert max(buffer_space) < 1
assert max(params_space) < 4
# Machine Time
machine_time += 1
def pull() -> int:
"""Pull a pseudo-random number from the chaos machine.
Uses a Xorshift PRNG seeded by the current chaotic state.
Returns:
A 32-bit unsigned integer.
>>> reset()
>>> isinstance(pull(), int)
True
>>> 0 <= pull() <= 0xFFFFFFFF
True
"""
global buffer_space, params_space, machine_time
# PRNG (Xorshift by George Marsaglia)
def xorshift(x: int, y: int) -> int:
x ^= y >> 13
y ^= x << 17
x ^= y >> 5
return x
# Choosing Dynamical Systems (Increment)
key = machine_time % m
# Evolution (Time Length)
for _ in range(t):
# Variables (Position + Parameters)
r = params_space[key]
value = buffer_space[key]
# Modification (Transition Function) - Flow
buffer_space[key] = round(float(r * value * (1 - value)), 10)
params_space[key] = (machine_time * 0.01 + r * 1.01) % 1 + 3
# Choosing Chaotic Data
x = int(buffer_space[(key + 2) % m] * (10**10))
y = int(buffer_space[(key - 2) % m] * (10**10))
# Machine Time
machine_time += 1
# PRNG (Xorshift by George Marsaglia)
x ^= y >> 13
y ^= x << 17
x ^= y >> 5
return x & 0xFFFFFFFF
def reset() -> None:
"""Reset the chaos machine to its initial state."""
global buffer_space, params_space, machine_time
buffer_space = K.copy()
params_space = [0] * m
machine_time = 0
if __name__ == "__main__":
# Initialization
reset()
# Pushing Data (Input)
import random
message = random.sample(range(0xFFFFFFFF), 100)
for chunk in message:
push(chunk)
# for controlling
inp = ""
# Pulling Data (Output)
while inp not in ("e", "E"):
print(f"{format(pull(), '#04x')}")
print(buffer_space)
print(params_space)
inp = input("(e)exit? ").strip()