def test_invalid_polyhedra(self): with self.assertRaises(ValueError): # Tetrahedron with one face incorrectly oriented. Polyhedron( vertex_positions=[ (0, 0, 0), (0, 1, 1), (1, 0, 1), (1, 1, 0), ], triangles=[ [0, 1, 3], [0, 1, 2], [0, 3, 2], [1, 2, 3], ], ) with self.assertRaises(ValueError): # Tetrahedron with a duplicated face. Polyhedron( vertex_positions=[ (0, 0, 0), (0, 1, 1), (1, 0, 1), (1, 1, 0), ], triangles=[ [0, 1, 3], [0, 2, 1], [0, 3, 2], [1, 2, 3], [1, 2, 3], ], ) with self.assertRaises(ValueError): # Tetrahedron with a missing face. Polyhedron( vertex_positions=[ (0, 0, 0), (0, 1, 1), (1, 0, 1), (1, 1, 0), ], triangles=[ [0, 1, 3], [0, 2, 1], [0, 3, 2], ], )
def _build_triangle(self, cell, points): faces = tvtk.CellArray() polygon = tvtk.Polygon() polygon.point_ids.number_of_ids = 3 polygon.point_ids.set_id(0, 0) polygon.point_ids.set_id(1, 1) polygon.point_ids.set_id(2, 2) faces.insert_next_cell(polygon) cell_points = self._get_cell_points(cell, points) poly = Polyhedron(cell_points, faces) name = 'Triang-{}-{}-{}'.format(*cell) return poly, name
def _build_tetrahedron(self, cell, points): faces = tvtk.CellArray() for i0,i1,i2 in [(0,1,2), (0,3,1), (0,2,3), (1,3,2)]: polygon = tvtk.Polygon() polygon.point_ids.number_of_ids = 3 polygon.point_ids.set_id(0, i0) polygon.point_ids.set_id(1, i1) polygon.point_ids.set_id(2, i2) faces.insert_next_cell(polygon) cell_points = self._get_cell_points(cell, points) poly = Polyhedron(cell_points, faces) name = 'Tetra-{}-{}-{}-{}'.format(*cell) return poly, name
def _build_quadrilateral(self, cell, points): faces = tvtk.CellArray() polygon = tvtk.Polygon() polygon.point_ids.number_of_ids = 4 polygon.point_ids.set_id(0, 0) polygon.point_ids.set_id(1, 1) polygon.point_ids.set_id(2, 2) polygon.point_ids.set_id(3, 3) faces.insert_next_cell(polygon) cell_points = self._get_cell_points(cell, points) poly = Polyhedron(cell_points, faces) name = 'Quad-{}-{}-{}-{}'.format(*cell) return poly, name
def _build_voxel(self, cell, points): faces = tvtk.CellArray() for i0,i1,i2,i3 in [(0,1,3,2), (1,3,7,5), (5,7,6,4), (4,0,2,6), (6,2,3,7), (0,1,5,4)]: polygon = tvtk.Polygon() polygon.point_ids.number_of_ids = 4 polygon.point_ids.set_id(0, i0) polygon.point_ids.set_id(1, i1) polygon.point_ids.set_id(2, i2) polygon.point_ids.set_id(3, i3) faces.insert_next_cell(polygon) cell_points = self._get_cell_points(cell, points) poly = Polyhedron(cell_points, faces) name = 'Voxel-{}-{}-{}-{}-{}-{}-{}-{}'.format(*cell) return poly, name
def main(args): if args.sig is not None: T = curver.triangulation_from_sig(args.sig) else: T = curver.load(args.genus, max(args.punctures, 1)).triangulation P = Polyhedron.from_triangulation(T, args.upper, zeros=args.zeros) num_integral_points = P.integral_points_count(triangulation='cddlib') print(P) try: print('Polytope dimension: {}'.format(P.as_sage().dimension())) except AttributeError: print('Polytope dimension: Unknown') print('Drawing from [0, {})'.format(num_integral_points)) common = dict(T=T, P=P, closed=args.punctures == 0) iterable = (dict(index=randrange(0, num_integral_points)) for _ in range(args.num)) process(from_index, common, iterable, cores=args.cores, path=args.output)
def test_numpy_int64_compatibility(self): # This is a repetition of test_cube, but using NumPy int64 # values in place of Python ints, and ndarrays in place # of lists or tuples. numpy_cube = Polyhedron( triangles=numpy.array(cube.triangles, dtype=numpy.int64), vertex_positions=numpy.array( cube.vertex_positions, dtype=numpy.int64), ) # Check volume self.assertEqual(numpy_cube.volume(), 8) def classify(point): x, y, z = point if -1 < x < 1 and -1 < y < 1 and -1 < z < 1: return "inside" if -1 <= x <= 1 and -1 <= y <= 1 and -1 <= z <= 1: return "boundary" return "outside" # Quarter-integer boundaries from -1.25 to 1.25 inclusive. xs = ys = zs = numpy.linspace(-1.25, 1.25, 11) points = [(x, y, z) for x in xs for y in ys for z in zs] for point in points: class_ = classify(point) if class_ == "inside": self.assertEqual(numpy_cube.winding_number(point), 1) elif class_ == "outside": self.assertEqual(numpy_cube.winding_number(point), 0) elif class_ == "boundary": # Point is on the boundary. with self.assertRaises(ValueError): numpy_cube.winding_number(point) else: assert False, "should never get here"
from polyhedron import Polyhedron n = 6 #number of variables m_B = 8 #number of inequality constraints m_A = 2 #number of equality constraints #randomly generate matrices for a polyhedron B_values = numpy.random.randint(low=-10, high=10, size=n * m_B) B = numpy.array(B_values).reshape(m_B, n) A = None if (m_A > 0): A_values = numpy.random.randint(low=-10, high=10, size=n * m_A) A = numpy.array(A_values).reshape(m_A, n) #build polyhedron (right-hand side vectors d and b do not affect set of circuits) P = Polyhedron(B=B, d=None, A=A, b=None) print('enumerating set of circuits C(A,B) for randomly generated A and B: ') print('A = ' + str(A)) print('B = ' + str(B)) print('\ntesting naive method:') start = timeit.default_timer() circuits = P.naive_circuit_enumeration() stop = timeit.default_timer() print('number of circuits: ' + str(len(circuits))) print('runtime: ' + str(round(stop - start, 3)) + ' seconds') print('circuits:') for g in circuits: print g print('\ntesting standard form method:') start = timeit.default_timer()
#b = numpy.array([0]) A = None b = None B = numpy.array([[-1, 0, 0], [0, 0, -1], [0, -1, -1], [0, -1, 0], [2, 1, 1], [3, 3, -1]]) d = numpy.array([0, 0, 2, 4, 6, 8]) m_B, n = B.shape m_A = 0 #m_A = A.shape[0] c = numpy.array([-8, -1, -5]) P = Polyhedron(B=B, d=d, A=A, b=b) x_initial = numpy.array([0, 0, 0]) print('\nstrictly feasible circuits:') circuits = P.get_strictly_feasible_circuits(x=x_initial) for g in circuits: print g g, steepness = P.get_steepest_descent_circuit([0, 0, 0], c=c) print('\nobjective f: ') print(c) print('steepest-descent circuit:') print(g) print('steepness:')
def createPolyhedron(self, parent=None, name=None): """Create a polyhedron from the current set of faces. Returns the Polyhedron object. """ # Build lookup tables (so that only the verts that are really # required are stored in the Polyhedron) # # Key: Original vertex index - Value: New vertex index vert_lut = {} has_normals = True has_tverts = True iv = 0 for f in self.faces: for v,tv,n in f: if v not in vert_lut: vert_lut[v] = iv iv+=1 if tv==None: has_tverts = False if n==None: has_normals = False numpolys = len(self.faces) numverts = len(vert_lut) pg = PolyhedronGeom() pg.verts.resize(numverts) pg.setNumPolys(numpolys) # Set vertices for v in vert_lut: newidx = vert_lut[v] pg.verts[newidx] = self.verts[v] # Set polys (this has to be done *before* any FACEVARYING variable # is created, otherwise the size of the variable wouldn't be known) idx = 0 for i,f in enumerate(self.faces): loop = [] for v,tv,n in f: loop.append(vert_lut[v]) pg.setPoly(i,[loop]) # Create variable N for storing the normals if has_normals: pg.newVariable("N", FACEVARYING, NORMAL) N = pg.slot("N") idx = 0 for f in self.faces: for v,tv,n in f: N[idx] = self.normals[n] idx += 1 # Set texture vertices if has_tverts: pg.newVariable("st", FACEVARYING, FLOAT, 2) st = pg.slot("st") idx = 0 for f in self.faces: for v,tv,n in f: st[idx] = self.tverts[tv] idx += 1 obj = Polyhedron(name=name, parent=parent) obj.geom = pg # Set the materials self.initMaterial(obj) return obj
import numpy import timeit from polyhedron import Polyhedron n = 7 #number of variables m_B = 14 #number of inequality constraints #randomly generate matrix for a full-dimensional polyhedron B_values = numpy.random.randint(low=-10, high=10, size=n * m_B) B = numpy.array(B_values).reshape(m_B, n) #build polyhedron P = Polyhedron(B=B, d=None, A=None, b=None) #randomly generate a vector to determine sign-compatibility direction u = numpy.random.randint(low=-10, high=10, size=n) u = numpy.array(u).reshape(n) B_u = B.dot(u) print('\nB = ' + str(B)) print('sign: ' + str(B_u)) print('\ntesting naive method:') start = timeit.default_timer() circuits = P.naive_circuit_enumeration() stop = timeit.default_timer() #post-processing for finding sign-compatible circuits sign_compatible_circuits = [] for g in circuits:
def createPolyhedron(self, parent=None, name=None): """Create a polyhedron from the current set of faces. Returns the Polyhedron object. """ # Build lookup tables (so that only the verts that are really # required are stored in the Polyhedron) # # Key: Original vertex index - Value: New vertex index vert_lut = {} has_normals = True has_tverts = True iv = 0 for f in self.faces: for v, tv, n in f: if v not in vert_lut: vert_lut[v] = iv iv += 1 if tv == None: has_tverts = False if n == None: has_normals = False numpolys = len(self.faces) numverts = len(vert_lut) pg = PolyhedronGeom() pg.verts.resize(numverts) pg.setNumPolys(numpolys) # Set vertices for v in vert_lut: newidx = vert_lut[v] pg.verts[newidx] = self.verts[v] # Set polys (this has to be done *before* any FACEVARYING variable # is created, otherwise the size of the variable wouldn't be known) idx = 0 for i, f in enumerate(self.faces): loop = [] for v, tv, n in f: loop.append(vert_lut[v]) pg.setPoly(i, [loop]) # Create variable N for storing the normals if has_normals: pg.newVariable("N", FACEVARYING, NORMAL) N = pg.slot("N") idx = 0 for f in self.faces: for v, tv, n in f: N[idx] = self.normals[n] idx += 1 # Set texture vertices if has_tverts: pg.newVariable("st", FACEVARYING, FLOAT, 2) st = pg.slot("st") idx = 0 for f in self.faces: for v, tv, n in f: st[idx] = self.tverts[tv] idx += 1 obj = Polyhedron(name=name, parent=parent) obj.geom = pg # Set the materials self.initMaterial(obj) return obj
def main(mps_fn='', results_dir='results', max_time=300, sd_method='dual_simplex', reset=False, partition_polytope=False, n=0, k=0, spindle=False, spindle_dim=0, n_cone_facets=0, n_parallel_facets=0): if mps_fn: print('Reading {}...'.format(mps_fn)) c, B, d, A, b = read_mps_preprocess(mps_fn) print('Building polyhedron...') P = Polyhedron(B, d, A, b, c) elif partition_polytope: print('Constructing partition polytope with n={} and k={}'.format( n, k)) # randomly generate cluster size bounds and objective function v1 = np.random.randint(0, n, size=k) v2 = np.random.randint(0, n // k, size=k) ub = [max(v1[i], v2[i]) for i in range(k)] lb = [min(v1[i], v2[i]) for i in range(k)] c = np.random.randint(0, 1000, size=n * k) P = PartitionPolytope(n, k, ub, lb, c) elif spindle: print('Constructing spindle with dimension n={}, with {} cone facets,' 'and with {} pairs of parallel facets'.format( spindle_dim, n_cone_facets, n_parallel_facets)) P = Spindle(spindle_dim, n_cone_facets, n_parallel_facets) c = P.c else: raise RuntimeError('Provide arguments for constructing polyhedron.') print('Finding feasible solution...') x_feasible = P.find_feasible_solution(verbose=False) if partition_polytope or spindle: print('Building gurobi model for simplex...') P.build_gurobi_model(c=c) P.set_solution(x_feasible) print('\nSolving with simplex method...') lp_result = P.solve_lp(verbose=False, record_objs=True) print('\nSolution using simplex method:') print(lp_result) print('\nSolving with steepest descent...') sd_result = sdac(P, x_feasible, c=c, method=sd_method, max_time=max_time, reset=reset) print('\nSolution for {} using steepest-descent augmentation:'.format( os.path.basename(mps_fn))) print(sd_result) if results_dir: if not os.path.exists(results_dir): os.mkdir(results_dir) if mps_fn: prefix = os.path.basename(mps_fn).split('.')[0] elif partition_polytope: prefix = 'n-{}_k-{}'.format(n, k) elif spindle: prefix = 'n-{}_c-{}_p-{}'.format(spindle_dim, n_cone_facets, n_parallel_facets) lp_fn = os.path.join(results_dir, prefix + '_lp.p') sd_fn = os.path.join(results_dir, prefix + '_sd.p') lp_result.save(lp_fn) sd_result.save(sd_fn)
def importFile(self, filename, invertfaces=False): """Import an OFF file. If invertfaces is True the orientation of each face is reversed. """ self.invertfaces = invertfaces self.texcoord_flag = False self.color_flag = False self.normal_flag = False self.four_flag = False self.ndim_flag = False self.ndim = 3 self.is_trimesh = True self.fhandle = file(filename) # Read the header z = self.readLine() self.parseHeaderKeyWord(z) # nOFF? if self.ndim_flag: # Read the dimension of vertices z = self.readLine() self.ndim = int(z) if self.ndim > 3: raise ValueError( "A vertex space dimension of %d is not supported" % (self.ndim)) # Read the number of vertices and faces... z = self.readLine().split(" ") self.numverts = int(z[0]) self.numfaces = int(z[1]) # Start with a TriMeshGeom # (this will be later converted into a PolyhedronGeom if faces # with more than 3 vertices are encountered) self.geom = TriMeshGeom() self.geom.verts.resize(self.numverts) self.geom.faces.resize(self.numfaces) # Read the vertices... self.readVertices() # Read the faces... self.readFaces() self.fhandle.close() # Create the actual object... nodename = os.path.basename(filename) nodename = os.path.splitext(nodename)[0] nodename = nodename.replace(" ", "_") if self.is_trimesh: n = TriMesh(name=nodename) else: n = Polyhedron(name=nodename) n.geom = self.geom
import unittest else: import unittest2 as unittest from polyhedron import Polyhedron # Sample polyhedra ############################################################ # Regular tetrahedron. tetrahedron = Polyhedron( vertex_positions=[ (0, 0, 0), (0, 1, 1), (1, 0, 1), (1, 1, 0), ], triangles=[ [0, 1, 3], [0, 2, 1], [0, 3, 2], [1, 2, 3], ], ) def tetrahedron_classify(point): x, y, z = point if x + y + z < 2 and x + y > z and x + z > y and y + z > x: return "inside" if x + y + z <= 2 and x + y >= z and x + z >= y and y + z >= x: return "boundary" return "outside"
def main(args): if args.genus == 0 and args.punctures == 6: common = dict( T=curver.load(0, 6).triangulation, P=Polyhedron( eqns=[], ieqs=[ [0, 1, 0, 1, -2, 0, 0], # 1 + 3 - 4 - 4 [0, -1, 1, 0, 2, 0, 0], # -1 + 2 + 4 + 4 [0, 1, 1, 0, 0, 0, -1], # 1 + 2 - 6 [0, -1, 0, 0, 1, 0, 1], # 4 + 6 - 1 [args.upper, -4, -8, -5, -4, -5, -2], [-args.lower, 4, 8, 5, 4, 5, 2], ] + [[-1] + [0] * i + [1] + [0] * (6 - i - 1) for i in range(6)]), embedding=np.array([ [1, 0, 1, -1, 0, 0], [1, 0, 1, 0, 0, 0], [1, 1, 0, 0, 0, 0], [1, 1, 0, 0, 1, -1], [1, 0, 1, -2, 0, 0], [-1, 1, 0, 2, 0, 0], [-1, 1, 0, 2, 1, 1], [0, 1, 0, 1, 1, 0], [0, 0, 0, 1, 0, 0], [0, 1, 1, 0, 0, 0], [0, 0, 0, 0, 1, 1], [-1, 0, 0, 1, 0, 1], ], dtype=object), closed=False, ) elif args.genus == 2 and args.punctures == 0: common = dict( T=curver.load(2, 1).triangulation, P=Polyhedron(eqns=[], ieqs=[ [-1, 1, 1, 1, 0, 0, -1], [-1, -1, -1, -1, 1, 1, 1], [args.upper, -7, -8, -7, -5, -5, -6], [-args.lower, 7, 8, 7, 5, 5, 6], ] + [[-1] + [0] * i + [1] + [0] * (6 - i - 1) for i in range(6)]), embedding=np.array([ [2, 2, 2, 0, 0, 0], [0, 0, 0, 1, 1, 2], [0, 0, 0, 1, 1, 0], [0, 0, 0, 0, 1, 1], [0, 0, 0, 1, 0, 1], [1, 2, 1, 0, 0, 0], [1, 0, 1, 0, 0, 0], [0, 1, 1, 0, 0, 0], [1, 1, 0, 0, 0, 0], ]), closed=True, ) elif args.genus == 2 and args.punctures == 1: common = dict( T=curver.load(2, 1).triangulation, P=Polyhedron( eqns=[], ieqs=[ [0, 1, 1, 0, -1, 0, 0, 0, 0], # 1 + 2 - 4 [0, 0, -1, 1, 1, 0, 0, 0, 0], # 3 + 4 - 2 [0, 0, 0, 0, 0, 1, 1, 0, -1], # 5 + 6 - 8 [0, 0, 0, 0, 0, 0, -1, 1, 1], # 7 + 8 - 6 [0, 0, 0, -1, -1, 0, 0, 1, 1], # 7 + 8 - 3 - 4 [0, 0, 0, 1, 1, 0, -1, 0, 1], # 3 + 4 + 8 - 6 [0, 0, 0, 1, 1, 0, 1, 0, -1], # 3 + 4 + 6 - 8 [args.upper, -11, -9, -9, -2, -9, -6, -6, -2], [-args.lower, 11, 9, 9, 2, 9, 6, 6, 2], ] + [[-1] + [0] * i + [1] + [0] * (8 - i - 1) for i in range(8)]), embedding=np.array( [ [0, 0, 2, 2, 0, 0, 0, 0], # 3 + 3 + 4 + 4 [0, 1, 1, 0, 0, 0, 0, 0], # 2 + 3 [0, -1, 1, 2, 0, 0, 0, 0], # 3 + 4 + 4 - 2 [1, 0, 1, 0, 0, 0, 0, 0], # 1 + 3 [1, 1, 0, 0, 0, 0, 0, 0], # 1 + 2 [0, 0, 0, 0, 0, 1, 1, 0], # 6 + 7 [0, 0, 0, 0, 0, -1, 1, 2], # 7 + 8 + 8 - 6 [0, 0, 0, 0, 1, 0, 1, 0], # 5 + 7 [0, 0, 0, 0, 1, 1, 0, 0], # 5 + 6 ], dtype=object), closed=False, ) elif args.genus == 3 and args.punctures == 0: common = dict( T=curver.load(3, 1).triangulation, P=Polyhedron( eqns=[], ieqs=[ # a1, b1, c1, a2, b2, c2, a3, b3, c3, x, y, z [-1, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, +1, +1], [-2, 0, -2, 0, 0, 0, 0, 0, 0, 0, 0, +1, +1], [-2, 0, 0, -2, 0, 0, 0, 0, 0, 0, 0, +1, +1], [-2, +2, +2, +2, 0, 0, 0, 0, 0, 0, 0, -1, -1], [-1, 0, 0, 0, 0, -1, -1, 0, 0, 0, +1, 0, +1], [-2, 0, 0, 0, 0, -2, 0, 0, 0, 0, +1, 0, +1], [-2, 0, 0, 0, 0, 0, -2, 0, 0, 0, +1, 0, +1], [-2, 0, 0, 0, +2, +2, +2, 0, 0, 0, -1, 0, -1], [-1, 0, 0, 0, 0, 0, 0, 0, -1, -1, +1, +1, 0], [-2, 0, 0, 0, 0, 0, 0, 0, -2, 0, +1, +1, 0], [-2, 0, 0, 0, 0, 0, 0, 0, 0, -2, +1, +1, 0], [-2, 0, 0, 0, 0, 0, 0, +2, +2, +2, -1, -1, 0], [ args.upper, -4, -2, -2, -4, -2, -2, -4, -2, -2, -6, -6, -6 ], [ -args.lower, +4, +2, +2, +4, +2, +2, +4, +2, +2, +6, +6, +6 ], ] + [[-1] + [0] * i + [1] + [0] * (12 - i - 1) for i in range(12)]), embedding=np.array([ #a1, b1, c1, a2, b2, c2, a3, b3, c3, x, y, z [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +1, +1], # 0 [0, -1, -1, 0, 0, 0, 0, 0, 0, 0, +1, +1], # 1 [0, +1, +1, 0, 0, 0, 0, 0, 0, 0, 0, 0], # 2 [+1, 0, +1, 0, 0, 0, 0, 0, 0, 0, 0, 0], # 3 [+1, +1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], # 4 [0, 0, 0, 0, 0, 0, 0, 0, 0, +1, 0, +1], # 5 [0, 0, 0, 0, -1, -1, 0, 0, 0, +1, 0, +1], # 6 [0, 0, 0, 0, +1, +1, 0, 0, 0, 0, 0, 0], # 7 [0, 0, 0, +1, 0, +1, 0, 0, 0, 0, 0, 0], # 8 [0, 0, 0, +1, +1, 0, 0, 0, 0, 0, 0, 0], # 9 [0, 0, 0, 0, 0, 0, 0, 0, 0, +1, +1, 0], # 10 [0, 0, 0, 0, 0, 0, 0, -1, -1, +1, +1, 0], # 11 [0, 0, 0, 0, 0, 0, 0, +1, +1, 0, 0, 0], # 12 [0, 0, 0, 0, 0, 0, +1, 0, +1, 0, 0, 0], # 13 [0, 0, 0, 0, 0, 0, +1, +1, 0, 0, 0, 0], # 14 ]), closed=True, ) else: raise ValueError( f'Intrinsic coordinates not known for S_{args.genus},{args.punctures}' ) iterable = (dict() for _ in count()) process(func, common, iterable, cores=args.cores, path=args.output)
n_paths = len(paths) with open(filename, 'w') as f: f.write("%s\n" % n_paths) for path in paths: f.write("%s\n" % len(path)) for point in path: f.write("%s %s %s\n" % (point[0], point[1], point[2])) if __name__ == "__main__": # p1 = Polyhedron(filelist=["../data/test/unit_cube_open.fold", "../data/test/rect_box.fold"]) # p = Polyhedron(filelist=["../data/test_case6.fold"]) # print unfold_polyhedron(p1, p1.unfolding_tree) # print p.unfolding_tree.children_bridges # unfold_polyhedron(p, p.unfolding_tree) # print p.unfolding_tree.children[0].children # p.write_to_off("../out/poly.off") # write_cut_path(gather_cuts(p, p.unfolding_tree), "../out/cuts.txt") if len(sys.argv) != 2: print "Usage: pass as argument a .fold file containing a orthogonal polyhedron" else: p = Polyhedron(filelist=[sys.argv[1]]) unfold_polyhedron(p, p.unfolding_tree) polyhedron_file = "../out/poly.off" cut_file = "../out/cuts.txt" exe_file = "../viewer/build/viewer" p.write_to_off(polyhedron_file) write_cut_path(gather_cuts(p, p.unfolding_tree), cut_file) print "here" os.system("cat %s %s | %s" % (polyhedron_file, cut_file, exe_file))