-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathhalton.py
112 lines (100 loc) · 3.46 KB
/
halton.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
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
__author__ = "Juri Bieler"
__version__ = "0.0.1"
__email__ = "[email protected]"
__status__ = "Development"
# ==============================================================================
# description :n-dimensional Sampling plans
# date :2018-07-23
# version :0.01
# notes :
# python_version :3.6
# ==============================================================================
import numpy as np
class Halton:
def __init__(self):
pass
def prime(self, n):
"""
:param n
:return the n-th prime number (starting from n=0 => 2)
"""
n += 1
prime_list = [2]
num = 3
while len(prime_list) < n:
for p in prime_list:
if num % p == 0:
break
else:
prime_list.append(num)
num += 2
return prime_list[-1]
def halton(self, i, prim):
"""
:param i the index of the generated number
:param prim the base
"""
# add one to exclude 0 as result
i = int(i+1)
baseStr = self.base(i, prim)
baseStrInv = self.str_inverse(baseStr)
decimal = self.base_fract_str_to_float(baseStrInv, prim)
return decimal
def str_inverse(self, nums):
"""
:param number list
:return the inverse list of numbers
"""
str_inv = np.zeros((len(nums)))
for i in range(0, len(nums)):
str_inv[len(nums)-1 - i ] = nums[i]
return list(str_inv)
def base_fract_str_to_float(self, base_fracs, base):
"""
:param baseFracs a list that represents a number with base notation
:param the base of baseFracStr
:return a float of baseFracs evaluated with base, as fraction
"""
res = 0.
for i in range(0, len(base_fracs)):
res += int(base_fracs[i]) * int(base) ** (-1 * (i + 1))
return res
def base(self, decimal, base):
"""
:param decimal int number
:param base the base to use for convertion
:return the decimal number noted as base-number
"""
#list = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
other_base = []
while decimal != 0:
other_base.append(int(decimal % base))
decimal = decimal / base
out = []
for s in reversed(other_base):
if s != 0 or len(out) > 0:
out.append(s)
return out
def generate_sample_plan(self, point_count, dimension, bounds, base=None):
"""
generates sampling plan
:param point_count: number of sampling points
:param dimension: dimension of the sampling plan
:param bounds: vector of tooples representing the bounds for every input
:param base: vector of bases for every input
:return: matrix: list of point_count entries with each dimension entries representing the sampling plan
"""
if not base is None:
used_base = base
else:
used_base = []
for i in range(0, dimension):
used_base.append(self.prime(i))
points = []
for i in range(0, point_count):
scaled_point = []
for d in range(0, dimension):
halt = self.halton(i, used_base[d])
scaled_point.append(bounds[d][0] + (halt * (bounds[d][1]- bounds[d][0])))
points.append(scaled_point)
return points