-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathreader.py
122 lines (103 loc) · 3.36 KB
/
reader.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
113
114
115
116
117
118
119
120
121
122
from enum import Enum
from gmpy2 import mpq, mpz
def reader(path):
read_matrix = False
read_dimensions = False
read_bounding_box = False
offset_at_the_end = False
number_type = NumberType.undefined
matrix = []
bounding_box_matrix = []
with open(path) as infile:
for line in infile.readlines():
if line.startswith('flipped representation'):
offset_at_the_end = True
if line.startswith('begin'):
read_matrix = True
read_dimensions = True
continue
elif line.startswith('end'):
read_matrix = False
elif line.startswith('bounding box'):
read_bounding_box = True
elif line.startswith('bounding box end'):
read_bounding_box = False
elif read_dimensions:
m, d, number_type= parse_matrix_meta(line)
read_dimensions = False
continue
elif read_matrix:
matrix.append(parse_hyperplane_line(line, d, number_type, offset_at_the_end))
elif read_bounding_box:
bounding_box_matrix.append(
parse_hyperplane_line(line, d, number_type, offset_at_the_end)
)
return matrix, m, d, bounding_box_matrix
def parse_matrix_meta(line):
m, d, numberTypeStr = line.split()
m = int(m)
d = int(d)
numberType = NumberType[numberTypeStr]
return m, d, numberType
def parse_hyperplane_line(line, dim, numberType, offset_at_the_end=False):
entries = line.split()
if offset_at_the_end:
entries = [entries[-1]] + entries[:-1]
if len(entries) != dim:
raise ValueError('Line has to have {} many entries: {}!'.format(dim, entries))
if numberType == NumberType.float:
matrix_row = upscale_matrix_row(entries)
elif numberType == NumberType.rational:
matrix_row = []
for entry in entries:
splitted = entry.split('/')
if len(splitted) not in [1, 2]:
raise ValueError
if len(splitted) == 1:
matrix_row.append(mpz(int(splitted[0])))
else:
matrix_row.append(mpq(int(splitted[0]), int(splitted[1])))
elif numberType == NumberType.integer:
matrix_row = [mpz(a) for a in line]
return matrix_row
def upscale_matrix_row(row, scaling=1e+7):
integer_row = all(float(c).is_integer() for c in row)
if integer_row:
return [mpz(float(c)) for c in row]
else:
return [mpz(float(c)*scaling) for c in row]
class NumberType(Enum):
undefined = 0
rational = 1
integer = 2
float = 3
def __str__(self):
return self.name
def gcd(a, b):
"""Return greatest common divisor using Euclid's Algorithm."""
while b:
a, b = b, a % b
return a
def lcm(a, b):
"""Return lowest common multiple."""
return a * b // gcd(a, b)
def lcmm(*args):
"""Return lcm of args."""
z = lcm(args[0], args[1])
if len(args) == 2:
return z
for arg in args[2:]:
z = lcm(z, arg)
return z
def test_parse():
A, m, d = reader('data/arrangement.ine')
assert m == 4
assert d == 3
A1 = [
[3, -1, -1],
[-1, 1, 0],
[-1, 0, 1],
[3, -2, 0]
]
A1 = [[mpq(a) for a in ai] for ai in A1]
assert A == A1