Skip to content

Commit 5cc7e64

Browse files
authored
Merge pull request #94 from bzy-nya/master
fixes #92 and restructure Vector.py
2 parents d27caf0 + c7a9d89 commit 5cc7e64

File tree

2 files changed

+84
-67
lines changed

2 files changed

+84
-67
lines changed

cyaron/tests/polygon_test.py

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import unittest
2-
from cyaron import Polygon,Vector
2+
from cyaron import Polygon, Vector
3+
4+
35
class TestPolygon(unittest.TestCase):
46
def test_convex_hull(self):
5-
hull = Polygon.convex_hull(300, fx=lambda x:int(x*100000), fy=lambda x:int(x*100000))
7+
hull = Polygon.convex_hull(300, fx=lambda x: int(x * 100000), fy=lambda x: int(x * 100000))
68
points = hull.points
79
points = sorted(points)
810
# unique
@@ -35,24 +37,26 @@ def test_convex_hull(self):
3537
st.append(points[i])
3638
st.pop()
3739
self.assertEqual(len(st), len(hull.points))
40+
3841
def test_perimeter_area(self):
39-
poly = Polygon([[0,0],[0,1],[1,1],[1,0]])
40-
self.assertEqual(poly.perimeter(),4)
41-
self.assertEqual(poly.area(),1)
42+
poly = Polygon([[0, 0], [0, 1], [1, 1], [1, 0]])
43+
self.assertEqual(poly.perimeter(), 4)
44+
self.assertEqual(poly.area(), 1)
45+
4246
def test_simple_polygon(self):
4347
poly = Polygon.simple_polygon(Vector.random(300, [1000, 1000], 2))
4448
points = poly.points
45-
for i in range(0,len(points)):
46-
for j in range(i+2,len(points)):
47-
if j==len(points)-1 and i==0:
49+
for i in range(0, len(points)):
50+
for j in range(i + 2, len(points)):
51+
if j == len(points) - 1 and i == 0:
4852
continue
49-
a=points[i]
50-
b=points[(i+1)%len(points)]
51-
c=points[j]
52-
d=points[(j+1)%len(points)]
53-
prod=lambda x,y: x[0]*y[1]-x[1]*y[0]
54-
t1=prod([c[0]-a[0],c[1]-a[1]],[d[0]-a[0],d[1]-a[1]])\
55-
*prod([c[0]-b[0],c[1]-b[1]],[d[0]-b[0],d[1]-b[1]])
56-
t2=prod([a[0]-c[0],a[1]-c[1]],[b[0]-c[0],b[1]-c[1]])\
57-
*prod([a[0]-d[0],a[1]-d[1]],[b[0]-d[0],b[1]-d[1]])
58-
self.assertFalse(t1<=1e-9 and t2<=1e-9)
53+
a = points[i]
54+
b = points[(i + 1) % len(points)]
55+
c = points[j]
56+
d = points[(j + 1) % len(points)]
57+
prod = lambda x, y: x[0] * y[1] - x[1] * y[0]
58+
t1 = prod([c[0] - a[0], c[1] - a[1]], [d[0] - a[0], d[1] - a[1]]) \
59+
* prod([c[0] - b[0], c[1] - b[1]], [d[0] - b[0], d[1] - b[1]])
60+
t2 = prod([a[0] - c[0], a[1] - c[1]], [b[0] - c[0], b[1] - c[1]]) \
61+
* prod([a[0] - d[0], a[1] - d[1]], [b[0] - d[0], b[1] - d[1]])
62+
self.assertFalse(t1 <= 1e-9 and t2 <= 1e-9)

cyaron/vector.py

Lines changed: 62 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,78 +1,91 @@
1-
#coding=utf8
1+
# coding=utf8
22

3-
from .consts import ALPHABET_SMALL
43
from .utils import *
54
import random
5+
from enum import Enum
6+
7+
8+
class VectorRandomMode(Enum):
9+
unique = 0
10+
repeatable = 1
11+
float = 2
612

713

814
class Vector:
15+
916
@staticmethod
10-
def random(num=5, position_range=[10], mode=0, **kwargs):
11-
# mode 0=unique 1=repeatable 2=float
12-
if(num > 1000000):
17+
def random(num: int = 5, position_range: list = None, mode: VectorRandomMode = 0, **kwargs):
18+
"""
19+
brief : generating n random vectors in limited space
20+
param :
21+
# num : the number of vectors
22+
# position_range : a list of limits for each dimension
23+
# single number x represents range (0, x)
24+
# list [x, y] or tuple (x, y) represents range (x, y)
25+
# mode : the mode vectors generate, see Enum Class VectorRandomMode
26+
"""
27+
if position_range is None:
28+
position_range = [10]
29+
30+
if num > 1000000:
1331
raise Exception("num no more than 1e6")
14-
if(not list_like(position_range)):
15-
raise Exception("the 2nd param must be a list")
32+
if not list_like(position_range):
33+
raise Exception("the 2nd param must be a list or tuple")
1634

1735
dimension = len(position_range)
36+
1837
offset = []
38+
length = []
39+
1940
vector_space = 1
2041
for i in range(0, dimension):
21-
if(list_like(position_range[i])):
22-
if(position_range[i][1] < position_range[i][0]):
23-
raise Exception("max should larger than min")
24-
offset.insert(i, position_range[i][0])
25-
position_range[i] = position_range[i][1] - offset[i]
42+
if list_like(position_range[i]):
43+
if position_range[i][1] < position_range[i][0]:
44+
raise Exception("upper-bound should larger than lower-bound")
45+
offset.append(position_range[i][0])
46+
length.append(position_range[i][1] - position_range[i][0])
2647
else:
27-
offset.insert(i, 0)
28-
if(position_range[i] <= 0):
29-
raise Exception("the difference must more than 0")
30-
vector_space *= (position_range[i] + 1)
31-
if(mode == 0 and num > vector_space):
32-
raise Exception("1st param is too large that CYaRon can not generate unique vectors")
48+
offset.append(0)
49+
length.append(position_range[i])
50+
vector_space *= (length[i] + 1)
51+
52+
if mode == VectorRandomMode.unique and num > vector_space:
53+
raise Exception("1st param is so large that CYaRon can not generate unique vectors")
54+
3355
result = []
34-
35-
if(mode == 2 or mode == 1):
36-
for i in range(0, num):
37-
tmp = []
38-
for j in range(0, dimension):
39-
one_num = random.randint(0,position_range[j]) if mode == 1 else random.uniform(0,position_range[j])
40-
tmp.insert(j, one_num + offset[j])
41-
result.insert(i, tmp)
42-
43-
elif((mode == 0 and vector_space > 5 * num)):
44-
num_set = set([])
45-
rand = 0;
56+
if mode == VectorRandomMode.repeatable:
57+
result = [[random.randint(x, y) for x, y in zip(offset, length)] for _ in range(num)]
58+
elif mode == VectorRandomMode.float:
59+
result = [[random.uniform(x, y) for x, y in zip(offset, length)] for _ in range(num)]
60+
elif mode == VectorRandomMode.unique and vector_space > 5 * num:
61+
# O(NlogN)
62+
num_set = set()
4663
for i in range(0, num):
4764
while True:
48-
rand = random.randint(0, vector_space - 1);
49-
if(not rand in num_set):
65+
rand = random.randint(0, vector_space - 1)
66+
if rand not in num_set:
5067
break
51-
# Todo: So how to analyse then complexity? I think it is logn
5268
num_set.add(rand)
53-
tmp = Vector.get_vector(dimension, position_range, rand)
69+
tmp = Vector.get_vector(dimension, length, rand)
5470
for j in range(0, dimension):
5571
tmp[j] += offset[j]
56-
result.insert(i, tmp)
57-
58-
72+
result.append(tmp)
5973
else:
6074
# generate 0~vector_space and shuffle
61-
rand_arr = [i for i in range(0, vector_space)]
75+
rand_arr = list(range(0, vector_space))
6276
random.shuffle(rand_arr)
63-
for i in range(0, num):
64-
tmp = Vector.get_vector(dimension, position_range, rand_arr[i])
65-
for j in range(0, dimension):
66-
tmp[j] += offset[j]
67-
result.insert(i, tmp)
77+
result = [Vector.get_vector(dimension, length, x) for x in rand_arr[:num]]
78+
79+
for x in result:
80+
for i in range(dimension):
81+
x[i] += offset[i]
82+
6883
return result
6984

70-
@staticmethod
71-
def get_vector(dimension, position_range, hashnum):
85+
@staticmethod
86+
def get_vector(dimension: int, position_range: list, hashcode: int):
7287
tmp = []
7388
for i in range(0, dimension):
74-
tmp.insert(i, hashnum % (position_range[i] + 1))
75-
hashnum //= (position_range[i] + 1)
89+
tmp.append(hashcode % (position_range[i] + 1))
90+
hashcode //= (position_range[i] + 1)
7691
return tmp
77-
78-

0 commit comments

Comments
 (0)