-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbrownian.py
79 lines (74 loc) · 2.65 KB
/
brownian.py
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
import random
class BrownianVar(float):
def __new__(cls,v,vmin=None,vmax=None,step=None):
return super().__new__(cls,v)
def __init__(self,v,vmin,vmax,step) -> None:
step = abs(vmax-vmin)/2 if step > abs(vmax-vmin)/2 else step
# self.v = v
self.vmin = vmin
self.vmax = vmax
self.step = step
@property
def v(self):
return float(self)
def _setValue(self,v):
return BrownianVar(v,self.vmin,self.vmax,self.step)
def reset(self):
vNew = random.uniform(self.vmin,self.vmax)
return BrownianVar(vNew,self.vmin,self.vmax,self.step)
def move(self):
for i in range(1000):
vNew = random.gauss(self.v,self.step)
if vNew < self.vmax and vNew > self.vmin:
return BrownianVar(vNew,self.vmin,self.vmax,self.step)
print(f'No valid perturb, uniform reset instead! '+
f'{self.v} {self.vmin} {self.vmax} {self.step}')
return self.reset()
def __repr__(self):
return f'v={self.v} vmax={self.vmax} vmin={self.vmin} step={self.step}'
def __str__(self):
return str(self.v)
class BrownianVarMC(BrownianVar):
def __new__(cls,v,ref=None,width=None,type=None,step=None):
return super().__new__(cls,v)
def __init__(self,v,ref=None,width=None,type=None,step=None) -> None:
self._ref = ref
self._width = width
self._type = type
self._step = step
@property
def v(self):
return float(self)
@property
def vmin(self):
if self._type == 'abs':
return self._ref-self._width
elif self._type == 'abs_pos':
return max(self._ref-self._width,0)
elif self._type == 'rel':
return self._ref*(1-self._width/100)
elif self._type == 'rel_pos':
return max(self._ref*(1-self._width/100),0)
@property
def vmax(self):
if self._type == 'abs':
return self._ref+self._width
elif self._type == 'abs_pos':
return max(self._ref+self._width,0)
elif self._type == 'rel':
return self._ref*(1+self._width/100)
elif self._type == 'rel_pos':
return max(self._ref*(1+self._width/100),0)
@property
def step(self):
return abs(self.vmax-self.vmin)/2 if self._step > abs(self.vmax-self.vmin)/2 else self._step
def _setValue(self,v):
return BrownianVarMC(v,self._ref,self._width,self._type,self._step)
if __name__ == '__main__':
# a = BrownianVar(10,0,20,1)
# print(a)
# b = a._setValue(11)
# print(b)
a = BrownianVarMC(10,10,30,'rel',1)
a._ref = 15
b = a._setValue(15)