Ejemplo n.º 1
0
    def compute_data(self):
        """Compute the convex hull and associated data"""

        self.edges = set()
        self.point_edges = [[] for i in range(len(self.points))]
        self.edge_normals = {}

        ps = self.points

        self.planar = len(ps) <= 2
        if len(ps) == 1:
            self.edges.add((0, 0))  #phantom edge
            self.point_edges[0].append((0, 0))  #only one edge
            self.edge_normals = {(0, 0): [np.zeros(3), np.zeros(3)]}
        elif len(ps) == 2:
            self.edges.add((0, 1))  #unique edge
            self.point_edges[0].append((0, 1))  #only one edge
            self.point_edges[1].append((0, 1))  #only one edge

            #compute the normal of the arc
            n1 = np.cross(ps[0], ps[1])
            if nla.norm(n1) > 1e-7:
                n1 /= nla.norm(n1)

            self.edge_normals = {(0, 1): [n1, -n1]}

            #compute second normal of the arc
            n2 = ps[0] + ps[1]
            if nla.norm(n2) > 1e-7:
                n2 /= nla.norm(n2)

            self.edge_arc = {(0, 1): (n1, n2, 2 * np.pi)}
        else:
            data = ['']
            try:
                data = pyhull.qconvex('i FN Fn n -A%1.5f' % self.cos_merge, ps)
            except:
                data = ['']
            if not data[0]:
                #try the planar convex hull projecting in XY
                self.planar = True
                try:
                    data = pyhull.qconvex(
                        'i FN Fn n Qb0:0B0:0 -A%1.5f' % self.cos_merge, ps)
                except:
                    data = ['']
                if not data[0]:
                    #try the planar convex hull projecting in XZ
                    try:
                        data = pyhull.qconvex(
                            'i FN Fn n Qb1:0B1:0 -A%1.5f' % self.cos_merge, ps)
                    except:
                        data = ['']
                    if not data[0]:
                        #it should never get to this point!!!
                        #try the planar convex hull projecting in YZ
                        data = pyhull.qconvex(
                            'i FN Fn n Qb2:0B2:0 -A%1.5f' % self.cos_merge, ps)
            self.parse_data(data)
Ejemplo n.º 2
0
 def test_qconvex(self):
     data = [[-0.5, -0.5], [-0.5, 0.5], [0.5, -0.5], [0.5, 0.5]]
     self.assertEqual(['4', '0 2', '1 0', '2 3', '3 1'], qconvex("i", data))
     self.assertEqual(['4', '0 2', '1 0', '2 3', '3 1'],
                      qconvex("i Qt", data))
     self.assertEqual(qconvex("n", data), [
         '3', '4', '-0     -1   -0.5', '-1      0   -0.5',
         '1     -0   -0.5', '0      1   -0.5'
     ])
     self.assertIsNotNone(qconvex('QR0 FA Pp', data))
Ejemplo n.º 3
0
 def test_qconvex(self):
     data = [[-0.5, -0.5], [-0.5, 0.5], [0.5, -0.5], [0.5, 0.5]]
     self.assertEqual(['4', '0 2', '1 0', '2 3', '3 1'],
                      qconvex("i", data))
     self.assertEqual(['4', '0 2', '1 0', '2 3', '3 1'],
                      qconvex("i Qt", data))
     self.assertEqual(qconvex("n", data), ['3', '4',
                                           '-0     -1   -0.5',
                                           '-1      0   -0.5',
                                           '1     -0   -0.5',
                                           '0      1   -0.5'])
     self.assertIsNotNone(qconvex('QR0 FA Pp', data))
Ejemplo n.º 4
0
def zonotope_add(V, Sign, normals):
    # N: normals of the hyperplanes
    num_normals = normals.shape[0]
    dim = normals.shape[1]

    for i in range(num_normals):

        normal = normals[i]
        V_ = np.empty((0, dim))
        Sign_ = np.empty((0, i + Sign.shape[1]))

        for k in range(V.shape[0]):
            v = V[k]
            v_pm = np.vstack((v + normal, v - normal))
            v_sign = np.hstack((np.array([Sign[k], Sign[k]]), [[1], [-1]]))
            ind_v = [True, True]
            Sign_ = np.vstack((Sign_, v_sign[ind_v]))
            V_ = np.vstack((V_, v_pm[ind_v]))

        # take the convex hull of V_
        orth = sp.linalg.orth((V_ - V_[1, :]).T)
        if orth.shape[1] != V.shape[1]:
            Vr = np.dot((V_ - V_[1, :]), orth)
        else:
            Vr = V_ - V_[1, :]
        vertices = [list(Vr[i]) for i in range(Vr.shape[0])]
        ret = pyhull.qconvex('Fx', vertices)

        ind_vertices = [int(ret[j]) for j in range(1, len(ret))]
        V = V_[ind_vertices]
        Sign = Sign_[ind_vertices]

    return V, Sign
Ejemplo n.º 5
0
    def compute_hiperspaces(self):
        if not len(self.points) > 0:
            logger.error('No points to compute hull!')
            raise Exception('No points to compute hull!')

        # The heuristic caracteristic when searching to connect
        # different clusters does that it might fail
        # so we redirect the stdout to avoid such error
        # being visible to user
        stderr_fd = sys.stderr.fileno()
        with open('/tmp/qhull-output.log', 'w') as f, stderr_redirected(f):
            points = list(self.points)
            logger.info('Searching for hull in dimension %s based on %s points',
                    len(points[0]),len(points))
            output = qconvex('n',points)
            if len(output) == 1:
                logger.debug('Could not get Hull. Joggle input?')
        try:
            dim, facets_nbr, facets = self.__parse_hs_output(output)
        except IncorrectOutput:
            logger.error('Could not get hull')
            raise CannotGetHull()
        logger.info('Found hull in dimension %s of %s facets',
                dim,facets_nbr)
        self.dim = dim
        self.facets = facets
        return self.dim
Ejemplo n.º 6
0
def get_lines_voronoi(data):
    from pyhull import qconvex

    output = qconvex("o", data)

    nb_points = int(output[1].split(" ")[0])
    list_lines = []
    list_points = []
    for i in range(2, 2 + nb_points):
        list_points.append([float(c) for c in output[i].strip().split()])
    facets = []
    for i in range(2 + nb_points, len(output)):
        if output[i] != "":
            tmp = output[i].strip().split(" ")
            facets.append([int(tmp[j]) for j in range(1, len(tmp))])

    for i in range(len(facets)):
        for line in itertools.combinations(facets[i], 2):
            for j in range(len(facets)):
                if i != j and line[0] in facets[j] and line[1] in facets[j]:
                    # check if the two facets i and j are not coplanar
                    vector1 = np.array(list_points[facets[j][0]]) - np.array(list_points[facets[j][1]])
                    vector2 = np.array(list_points[facets[j][0]]) - np.array(list_points[facets[j][2]])
                    n1 = np.cross(vector1, vector2)
                    vector1 = np.array(list_points[facets[i][0]]) - np.array(list_points[facets[i][1]])
                    vector2 = np.array(list_points[facets[i][0]]) - np.array(list_points[facets[i][2]])
                    n2 = np.cross(vector1, vector2)

                    dot = math.fabs(np.dot(n1, n2) / (np.linalg.norm(n1) * np.linalg.norm(n2)))
                    if 1.05 > dot > 0.95:
                        continue
                    list_lines.append({"start": list_points[line[0]], "end": list_points[line[1]]})
                    break
    return list_lines
Ejemplo n.º 7
0
def convex_hull_volume_pyhull(pts):
    # call pyhull library
    output = pyhull.qconvex("Qt FA", pts)
    
    # parse output
    volume = -999.0
    facetArea = -999.0
    cnt1 = 0
    cnt2 = 0
    for line in output:
        if "facet area" in line:
            array = line.split(":")
            facetArea = float(array[1])
            
            cnt1 += 1
        
        if "volume" in line:
            array = line.split(":")
            volume = float(array[1])
            
            cnt2 += 1
    
    assert cnt1 == 1, "ERROR: 'facet area' found %d times in pyhull output" % cnt1
    assert cnt2 == 1, "ERROR: 'volume' found %d times in pyhull output" % cnt2
    
    return volume, facetArea
Ejemplo n.º 8
0
 def compute_hiperspaces(self):
     # La característica heurística al buscar conexiones entre
     # diferentes clusters hace que pueda fallar
     # por lo que redirigimos la salida para ser silenciosos
     # en esos casos
     if not len(self.points) > 0:
         logger.error('No points to compute hull!')
         raise Exception('No points to compute hull!')
     stderr_fd = sys.stderr.fileno()
     with open('/tmp/qhull-output.log', 'w') as f, stderr_redirected(f):
         points = list(self.points)
         logger.info('Searching for hull in dimension %s based on %s points',
                 len(points[0]),len(points))
         output = qconvex('n',points)
         if len(output) == 1:
             logger.debug('Could not get Hull. Joggle input?')
     try:
         dim, facets_nbr, facets = self.__parse_hs_output(output)
     except IncorrectOutput:
         logger.warning('Could not get hull')
         raise CannotGetHull()
     logger.info('Found hull in dimension %s of %s facets',
             dim,len(facets))
     self.dim = dim
     self.facets = facets
     if self.verbose:
         print "Computed MCH with ",facets_nbr," halfspaces"
         print 'This are them:\n'
         for facet in self.facets:print facet
     return self.dim
Ejemplo n.º 9
0
def zonotope_incidence_graph_opposite(A):
    V, S = zonotope_vertices(A)

    V_aff = project_affine_subspace(V.T).T
    if DEBUG:
        print('V_aff')
        print(V_aff)

    verts = [list(V_aff[i]) for i in range(V_aff.shape[0])]
    ret = pyhull.qconvex('Fv', verts)

    M = build_vertex_facet_matrix(ret, verts).T

    n = A.shape[0]
    d = V_aff.shape[1]
    I = build_incidence_graph(M, d)

    # Assign sign vectors for topes.
    for i in range(M.shape[1]):
        vf_key = tuple(np.where(M[:, i])[0].astype(int))
        f = I.rank(d - 1)[vf_key]
        f.pos = S[i]
    # Assign sign vectors for k faces.
    for k in range(d - 2, -1, -1):
        for u in I.rank(k).values():
            # print(u._sv_key, k)
            pos = np.zeros((n, ), int)
            for v in u.superfaces:
                # print('v', v.pos)
                pos += v.pos
            pos = (pos / len(u.superfaces)).astype(int)
            u.pos = pos
            # print('u', u.pos)

    return I
Ejemplo n.º 10
0
def convex_hull_volume_pyhull(pts):
    # call pyhull library
    output = pyhull.qconvex("Qt FA", pts)

    # parse output
    volume = -999.0
    facetArea = -999.0
    cnt1 = 0
    cnt2 = 0
    for line in output:
        if "facet area" in line:
            array = line.split(":")
            facetArea = float(array[1])

            cnt1 += 1

        if "volume" in line:
            array = line.split(":")
            volume = float(array[1])

            cnt2 += 1

    assert cnt1 == 1, "ERROR: 'facet area' found %d times in pyhull output" % cnt1
    assert cnt2 == 1, "ERROR: 'volume' found %d times in pyhull output" % cnt2

    return volume, facetArea
Ejemplo n.º 11
0
def zonotope_projected_vertex(normals):
    # N: normals of the hyperplanes
    num_normals = normals.shape[0]
    dim = normals.shape[1]
    V = np.vstack((normals[0], -normals[0]))
    Sign = np.array([[1], [-1]])

    for i in range(1, num_normals):

        normal = normals[i]

        V_ = np.vstack((V + normal, V - normal))
        Sign_ = np.ones((2 * Sign.shape[0], Sign.shape[1] + 1), dtype=int)
        Sign_[:, 0:Sign.shape[1]] = np.vstack((Sign, Sign))
        Sign_[Sign.shape[0]:, -1] = -1

        # take the convex hull of V_
        orth = sp.linalg.orth((V_ - np.mean(V_, axis=0)).T)
        if orth.shape[1] != V.shape[1]:
            Vr = np.dot((V_ - np.mean(V_, axis=0)), orth)
        else:
            Vr = V_ - V_[1, :]
        vertices = [list(Vr[i]) for i in range(Vr.shape[0])]

        info['n'].append(len(vertices))
        info['d'].append(len(vertices[0]))

        t_start = time()

        ret = pyhull.qconvex('Fv', vertices)

        info['time conv'].append(time() - t_start)

        #ind_vertices = [int(ret[j]) for j in range(1, len(ret))]
        ind_vertices = []
        for i in range(1, len(ret)):
            ind_vertices = ind_vertices + [int(x)
                                           for x in ret[i].split(' ')][1:]
        ind_vertices = np.unique(ind_vertices)

        info['# d-1 faces'].append(len(ret) - 1)
        info['# 0 faces'].append(len(ind_vertices))

        V = V_[ind_vertices]
        Sign = Sign_[ind_vertices]

    #
    # facets = np.zeros((int(ret[0]),len([int(x) for x in ret[1].split(' ')][1:])),dtype=int)
    # for i in range(1, len(ret)):
    #     facets[i-1] = [int(x) for x in ret[i].split(' ')][1:]
    # ret_facets = np.array(facets)
    #
    # for i in range(len(ind_vertices)):
    #     ret_facets[ret_facets == ind_vertices[i]] = i

    return V, Sign, info  #, ret_facets
Ejemplo n.º 12
0
def main():
    with open('res.txt', 'r') as rfile:
        lines = rfile.readlines()
    labels = np.array([x.split()[-1] for x in lines[1:]])
    data = np.array([[float(x) for x in y.split()[:-1]] for y in lines[1:]])
    data2 = data[:, :2]
    idx = [[int(x) for x in y.split()] for y in pyhull.qconvex('s i', data2)[1:]]
    coords = [[float(x) for x in y.split()]
              for y in pyhull.qconvex('s p', data2)[2:]]

    np_idx = np.array(idx)
    np_coords = np.array(coords)
    # print(idx)
    # print(coords)

    zero = np_coords[np_coords[:, 0] == 0][0][1]
    one = np_coords[np_coords[:, 0] == 1][0][1]
    zero_zero = np.copy(np_coords)
    zero_zero[:, 1] = np_coords[:, 1] - zero * (1 - np_coords[:, 0]) - one * np_coords[:, 0]
    bottom = np_coords[zero_zero[:, 1] <= 0]
    zero_zero = zero_zero[zero_zero[:, 1] <= 0]
    s_bottom = np.array(sorted(bottom, key=lambda x:x[0]))
    f = interpolate.interp1d(s_bottom[:, 0], s_bottom[:, 1])

    # test plot
    # x = np.linspace(0, 1, 100)
    # pylab.plot(x, f(x))
    # pylab.show()

    from_cvxhll = np.copy(data2)
    from_cvxhll[:, 1] = data2[:, 1] - f(data2[:, 0])

    print(sum(from_cvxhll[:, 1] < 0.001))
    low_e = data[from_cvxhll[:, 1] < 0.001]
    pylab.plot(low_e[:, 0], low_e[:, 1], 'o')
    pylab.plot(data[:, 0], data[:, 1], '*')
    # pylab.show()
    dir_list = labels[from_cvxhll[:, 1] < 0.001]
    for dirc in dir_list:
        print(dirc)
Ejemplo n.º 13
0
def construct_convex_hull_from_coords(coords: np.ndarray) -> Polyhedron:
    """Construct a polyhedron as a convex hull from a coordinate matrix.

    :param coords: An array of coordinates.

    :returns: A polyhedron whose facets are the non-simplicial facets of the
              convex hull of the vertices defined by `coords`.
    """
    dim = coords.shape[1]
    assert dim <= 3, 'We cannot visualise anything with more than three\
            dimensions.'

    vertices = []
    for i in range(coords.shape[0]):
        if dim == 2:
            vertices.append(Point(np.array([coords[i, 0], coords[i, 1], 0])))
        else:
            vertices.append(Point(coords[i, :]))
    if dim == 3:
        hull = qconvex("i", coords)
        n_facets = int(hull[0])
        facets = []
        for facet_vertices_str in hull[1:]:
            facet_vertices_idx = [
                int(x) for x in facet_vertices_str.split(' ')
            ]
            facet_vertices = [vertices[i] for i in facet_vertices_idx]
            facet = Facet([Contour.from_vertices(facet_vertices)])
            facets.append(facet)
        polyhedron = Polyhedron(facets)
    elif dim == 2:
        hull = qconvex("Fx", coords)
        n_hull_vertices = int(hull[0])
        hull_vertices = []
        for vertex_str in hull[1:]:
            vertex_idx = int(vertex_str)
            hull_vertices.append(vertices[vertex_idx])
        contour = Contour.from_vertices(hull_vertices)
        polyhedron = Polyhedron([Facet([contour])])
    return polyhedron
Ejemplo n.º 14
0
def zonotope_minkowski_sum(a, V, S):
    """Compute the Minkowski sum V ⊕ [a,-a].
    
    Arguments:
        a {1xd vector} -- End-point of line segment [a,-a]
        V {nxd matrix} -- Zonotope vertices
        S {nxn matrix} -- Zonotope sign vectors
    
    Returns:
        [matrix, matrix] -- Updated zonotope vertices and sign vectors.
    """
    a = np.reshape(a, (1, -1))

    V_sum = np.vstack((V + a, V - a))
    if DEBUG:
        print('V_sum')
        print(V_sum)

    S_sum = np.ones((2 * S.shape[0], S.shape[1] + 1), dtype=int)
    S_sum[:, 0:S.shape[1]] = np.vstack((S, S))
    S_sum[S.shape[0]:, -1] = -1
    if DEBUG:
        print('S_sum')
        print(S_sum)

    V_aff = project_affine_subspace(V_sum.T).T
    if DEBUG:
        print('V_aff')
        print(V_aff)

    vertices = [list(V_aff[i]) for i in range(V_aff.shape[0])]
    ret = pyhull.qconvex('Fv', vertices)

    idx = []
    for i in range(1, len(ret)):
        idx = idx + [int(x) for x in ret[i].split(' ')][1:]
    idx = np.unique(idx)
    if DEBUG:
        print('idx')
        print(idx)

    V = V_sum[idx]
    S = S_sum[idx]

    return V, S
Ejemplo n.º 15
0
def get_lines_voronoi(data):
    from pyhull import qconvex
    output = qconvex("o", data)

    nb_points = int(output[1].split(" ")[0])
    list_lines = []
    list_points = []
    for i in range(2, 2 + nb_points):
        list_points.append([float(c) for c in output[i].strip().split()])
    facets = []
    for i in range(2 + nb_points, len(output)):
        if output[i] != '':
            tmp = output[i].strip().split(" ")
            facets.append([int(tmp[j]) for j in range(1, len(tmp))])

    for i in range(len(facets)):
        for line in itertools.combinations(facets[i], 2):
            for j in range(len(facets)):
                if i != j and line[0] in facets[j] and line[1] in facets[j]:
                    #check if the two facets i and j are not coplanar
                    vector1 = np.array(list_points[facets[j][0]])\
                        - np.array(list_points[facets[j][1]])
                    vector2 = np.array(list_points[facets[j][0]])\
                        - np.array(list_points[facets[j][2]])
                    n1 = np.cross(vector1, vector2)
                    vector1 = np.array(list_points[facets[i][0]])\
                        - np.array(list_points[facets[i][1]])
                    vector2 = np.array(list_points[facets[i][0]])\
                        - np.array(list_points[facets[i][2]])
                    n2 = np.cross(vector1, vector2)

                    dot = math.fabs(
                        np.dot(n1, n2) /
                        (np.linalg.norm(n1) * np.linalg.norm(n2)))
                    if 1.05 > dot > 0.95:
                        continue
                    list_lines.append({
                        'start': list_points[line[0]],
                        'end': list_points[line[1]]
                    })
                    break
    return list_lines
Ejemplo n.º 16
0
def construct_convex_hull(vertices: Sequence[Point]) -> Polyhedron:
    """Construct a polyhedron as a convex hull from a list of vertices.

    :param vertices: A list of all vertices to be analysed.

    :returns: A polyhedron whose facets are the non-simplicial facets of the
              convex hull of `vertices`.
    """
    coords = np.zeros((len(vertices), 3))
    for i, vertex in enumerate(vertices):
        coords[i, :] = vertex.coordinates
    hull = qconvex("i", coords)
    n_facets = int(hull[0])
    facets = []
    for facet_vertices_str in hull[1:]:
        facet_vertices_idx = [int(x) for x in facet_vertices_str.split(' ')]
        facet_vertices = [vertices[i] for i in facet_vertices_idx]
        facet = Facet([Contour.from_vertices(facet_vertices)])
        facets.append(facet)
    polyhedron = Polyhedron(facets)
    return polyhedron
Ejemplo n.º 17
0
 def __init__(self, points, joggle=False):
     """
     Args:
         points:
             All the points as a sequence of sequences. e.g., [[-0.5, -0.5],
             [-0.5, 0.5], [0.5, -0.5], [0.5, 0.5]]
         joggle:
             Use qhull option to joggle inputs until simplical result is 
             obtained instead of merging facets.
     """
     self.points = points
     dim = map(len, self.points)
     if max(dim) != min(dim):
         raise ValueError("Input points must all have the same dimension!")
     self.dim = dim[0]
     if joggle:
         options = "i QJ"
     else:
         options = "i Qt"
     output = qconvex(options, points)
     output.pop(0)
     self.vertices = [map(int, row.strip().split()) for row in output]
Ejemplo n.º 18
0
    def __init__(self, points, joggle=False):
        """
        Initializes a ConvexHull from points.

        Args:
            points ([[float]]): All the points as a sequence of sequences.
                e.g., [[-0.5, -0.5], [-0.5, 0.5], [0.5, -0.5], [0.5, 0.5]]
            joggle (bool): Use qhull option to joggle inputs until simplical
                result is obtained instead of merging facets.
        """
        self.points = points
        dim = [len(i) for i in self.points]
        if max(dim) != min(dim):
            raise ValueError("Input points must all have the same dimension!")
        self.dim = dim[0]
        if joggle:
            options = "i QJ"
        else:
            options = "i Qt"
        output = qconvex(options, points)
        output.pop(0)
        self.vertices = [[int(i) for i in row.strip().split()]
                         for row in output]
Ejemplo n.º 19
0
    def __init__(self, points, joggle=False):
        """
        Initializes a ConvexHull from points.

        Args:
            points ([[float]]): All the points as a sequence of sequences.
                e.g., [[-0.5, -0.5], [-0.5, 0.5], [0.5, -0.5], [0.5, 0.5]]
            joggle (bool): Use qhull option to joggle inputs until simplical
                result is obtained instead of merging facets.
        """
        self.points = points
        dim = [len(i) for i in self.points]
        if max(dim) != min(dim):
            raise ValueError("Input points must all have the same dimension!")
        self.dim = dim[0]
        if joggle:
            options = "i QJ"
        else:
            options = "i Qt"
        output = qconvex(options, points)
        output.pop(0)
        self.vertices = [[int(i) for i in row.strip().split()]
                         for row in output]
Ejemplo n.º 20
0
def vertex2lattice(V):

    # orth = sp.linalg.orth((V - np.mean(V, 0)).T)
    # dim_V = orth.shape[1]
    #print(V)
    V_aff = proj_affine(V.T).T
    #print(V_aff)
    dim_V = V_aff.shape[1]
    n_vert = V.shape[0]
    if n_vert == 2 or n_vert == 1 or dim_V == 1:
        M = np.ones((n_vert, 1), int)
        L = FaceLattice(M, dim_V)
        return L

    # project V into affine space
    # if dim_V != V.shape[1]:
    #     V = np.dot((V - np.mean(V,0)), orth)
    # vertices = [list(V[i]) for i in range(n_vert)]

    vertices = [list(V_aff[i]) for i in range(n_vert)]
    ret = pyhull.qconvex('Fv', vertices)

    # get the convex hull of V
    # select faces with desired modes
    # Build facet-vertex incidence matrix.

    n_facets = int(ret[0])
    M = np.zeros((n_vert, n_facets), int)
    for i in range(1, len(ret)):
        vert_set = [int(x) for x in ret[i].split(' ')][1:]
        for v in vert_set:
            M[v, i - 1] = 1

    # Build face lattice.
    L = FaceLattice(M, dim_V)
    return L
Ejemplo n.º 21
0
 def count_surface(sites):
     """ 多面体を構成する面の数を return する """
     out = pyhull.qconvex('s i', sites)
     # voro = pyhull.qvoronoi('s o', sites)
     return len(out) - 1
Ejemplo n.º 22
0
def computeConvexHullVolume(points):
  outputStr = qconvex("FA", points)
  volumeSize = outputStr[-2].split()[3]
  print "ConvexHullSize:",volumeSize
  return volumeSize
Ejemplo n.º 23
0
def zonotope_vertex(normals):
    # solve info
    info = dict()
    info['iter'] = []
    info['n'] = []
    info['d'] = []
    info['time conv'] = []
    info['# 0 faces'] = []
    info['# d-1 faces'] = []

    # normals_proj = proj_affine(normals.T).T
    # normals_u, idu = unique_row(normals_proj)
    # normals = normals_u

    # N: normals of the hyperplanes
    num_normals = normals.shape[0]
    dim = normals.shape[1]
    V = np.vstack((normals[0], -normals[0]))
    Sign = np.array([[1], [-1]])

    for i in range(1, num_normals):
        info['iter'].append(i)

        normal = normals[i]

        V_ = np.vstack((V + normal, V - normal))

        Sign_ = np.ones((2 * Sign.shape[0], Sign.shape[1] + 1), dtype=int)
        Sign_[:, 0:Sign.shape[1]] = np.vstack((Sign, Sign))
        Sign_[Sign.shape[0]:, -1] = -1

        # take the convex hull of V_
        # orth = sp.linalg.orth((V_ - np.mean(V_,axis=0)).T)
        Vr = proj_affine(V_.T).T
        #print(Vr)

        # if orth.shape[1] != V.shape[1]:
        #     Vr = np.dot((V_ - np.mean(V_,axis=0)), orth)
        # else:
        #     Vr = V_ - np.mean(V_,axis=0)

        if Vr.shape[1] <= 1:
            V = V_[[np.argmax(Vr), np.argmin(Vr)]]
            Sign = Sign_[[np.argmax(Vr), np.argmin(Vr)]]
            continue

        vertices = [list(Vr[i]) for i in range(Vr.shape[0])]

        ret = pyhull.qconvex('Fv', vertices)
        if len(ret) - 1 == 0:
            return [], []

        #ind_vertices = [int(ret[j]) for j in range(1, len(ret))]
        ind_vertices = []
        for i in range(1, len(ret)):
            ind_vertices = ind_vertices + [int(x)
                                           for x in ret[i].split(' ')][1:]
        ind_vertices = np.unique(ind_vertices)
        #print(ret)
        V = V_[ind_vertices]
        Sign = Sign_[ind_vertices]

    #
    # facets = np.zeros((int(ret[0]),len([int(x) for x in ret[1].split(' ')][1:])),dtype=int)
    # for i in range(1, len(ret)):
    #     facets[i-1] = [int(x) for x in ret[i].split(' ')][1:]
    # ret_facets = np.array(facets)
    #
    # for i in range(len(ind_vertices)):
    #     ret_facets[ret_facets == ind_vertices[i]] = i
    #Sign = Sign[:,idu]
    return V, Sign  #, ret_facets
Ejemplo n.º 24
0
def prob_qhull(samples, data, rho_D_M, d_distr_samples,
        lam_domain, d_Tree=None): 
    r"""
    Calculates :math:`P_{\Lambda}(\mathcal{V}_{\lambda_{emulate}})`, the
    probability assoicated with a set of voronoi cells defined by
    ``num_l_emulate`` iid samples :math:`(\lambda_{emulate})`.

    This method is only intended when ``lam_domain`` is a generalized rectangle.

    :param samples: The samples in parameter space for which the model was run.
    :type samples: :class:`~numpy.ndarray` of shape (num_samples, ndim)
    :param data: The data from running the model given the samples.
    :type data: :class:`~numpy.ndarray` of size (num_samples, mdim)
    :param rho_D_M: The simple function approximation of rho_D
    :type rho_D_M: :class:`~numpy.ndarray` of shape  (M,mdim) 
    :param d_distr_samples: The samples in the data space that define a
        parition of D to for the simple function approximation
    :type d_distr_samples: :class:`~numpy.ndarray` of shape  (M,mdim) 
    :param d_Tree: :class:`~scipy.spatial.KDTree` for d_distr_samples
    :param lam_domain: The domain for each parameter for the model.
    :type lam_domain: :class:`~numpy.ndarray` of shape (ndim, 2)
    :returns: (P, io_ptr, lam_vol)

    """
    import pyhull
    if len(d_distr_samples.shape) == 1:
        d_distr_samples = np.expand_dims(d_distr_samples, axis=1)

    if d_Tree == None:
        d_Tree = spatial.KDTree(d_distr_samples)
        
    # Determine which inputs go to which M bins using the QoI
    #io_ptr = dsearchn(d_distr_samples, data);
    io_ptr = d_Tree.query(data)

    # Calcuate the bounding region for the parameters
    lam_bound = np.copy(samples)
    lam_width = lam_domain[:, 1] - lam_domain[:, 0]
    nbins = d_distr_samples.shape[1]
    # Add fake samples outside of lam_domain to close Voronoi tesselations.
    pts_per_edge = nbins
    sides = np.zeros((2, pts_per_edge))
    for i in range(lam_domain.shape[0]):
        sides[i, :] = np.linspace(lam_domain[i, 0], lam_domain[i, 1],
                pts_per_edge)
    # add midpoints
    for i in range(lam_domain.shape[0]):
        new_pt = sides
        new_pt[i, :] = np.repeat(lam_domain[i, 0] - lam_width[i]/pts_per_edge,
                pts_per_edge, 0).transpose() 
        lam_bound = np.vstack((lam_bound, new_pt))
        new_pt = sides
        new_pt[i, :] = np.repeat(lam_domain[i, 1] - lam_width[i]/pts_per_edge,
                pts_per_edge, 0).transpose() 
        lam_bound = np.vstack((lam_bound, new_pt))
        
    # add corners
    corners = np.zeros((2**lam_domain.shape[0], lam_domain.shape[0]))
    for i in range(lam_domain.shape[0]):
        corners[i, :] = lam_domain[i, np.repeat(np.hstack((np.ones((1,
            2**(i-1))), 2*np.ones((1, 2**(i - 1))))), 
            2**(lam_domain.shape[0]-i), 0).transpose()] 
        corners[i, :] += lam_width[i]*np.repeat(np.hstack((np.ones((1,
            2**(i-1))), -np.ones((1, 2**(i - 1))))),
            2**(lam_domain.shape[0]-i)/pts_per_edge, 0).transpose()

    lam_bound = np.vstack((lam_bound, corners))
    
    # Calculate the Voronoi diagram for samples. Calculate the volumes of 
    # the convex hulls of the corresponding Voronoi regions.
    lam_vol = np.zeros((samples.shape[-1],))
    for i in range((samples.shape[0])):
        vornoi = spatial.Voronoi(lam_bound)
        lam_vol[i] = float(pyhull.qconvex('Qt FA', vornoi.vertices).split()[-1])
    
    # Calculate probabilities.
    P = np.zeros((samples.shape[0],))
    for i in range(rho_D_M.shape[0]):
        Itemp = np.equal(io_ptr, i)
        P[Itemp] = rho_D_M[i]*lam_vol[Itemp]/np.sum(lam_vol[Itemp])
    P = P/np.sum[P]

    return (P, lam_vol, io_ptr)
Ejemplo n.º 25
0
def enumerate_contact_separating_3d(A, b):
    # Create solve info.
    info = dict()

    # Create halfspace inequalities, Ax - b <= 0.
    # A, b = build_normal_velocity_constraints(system.collider.manifolds)
    # b = np.zeros(b.shape)
    if DEBUG:
        print('A')
        print(A)
        print('b')
        print(b)

    n_pts = A.shape[0]
    info['n'] = n_pts

    # Get interior point using linear programming.
    t_lp = time()
    int_pt = int_pt_cone(A)
    info['time lp'] = time() - t_lp
    if DEBUG:
        print('int_pt2')
        print(int_pt, '\n', A @ int_pt)

    # Filter contact points which are always in contact.
    mask = np.zeros(n_pts, dtype=bool)
    c = np.where(np.abs(A @ int_pt) < 1e-6)[0]  # always contacting.
    mask[c] = 1
    A_c = A[mask, :]
    b_c = b[mask, :]
    A = A[~mask, :]
    b = b[~mask, :]
    if DEBUG:
        print(c)
        print(mask)

    # Project into null space of contacting points.
    # [A'; A_c]x ≤ 0, A_c⋅x = 0 ⇒ x ∈ NULL(A_c)
    # let NULL(A_c) = [x0, ... , xc]
    # A'⋅NULL(A_c)x' ≤ 0
    if np.sum(mask) > 0:
        N = null(A_c, np.finfo(np.float32).eps)
        A = A @ N
        int_pt = np.linalg.lstsq(N, int_pt, None)[0]
        if DEBUG:
            print('Null A_c')
            print(N)
            print('new int pt')
            print(int_pt)
            print(A @ int_pt)

    # Compute dual points.
    b_off = b - np.dot(A, int_pt)
    dual = A / b_off
    if DEBUG:
        print('b off')
        print(b_off)
        print('dual')
        print(dual)

    # Handle degenerate cases when d = 0 or 1.
    if np.sum(mask) == n_pts:
        cs_modes = [np.array(['c'] * n_pts)]
        lattice = FaceLattice()
        lattice.L = [[Face(range(n_pts), 0)]]
        lattice.L[0][0].m = cs_modes[0]
        return cs_modes, lattice, info
    if dual.shape[1] == 1:
        lattice = FaceLattice(M=np.ones((1, 1), int), d=1)
        dual_map = [list(np.where(~mask)[0])]
        cs_modes = lattice.csmodes(mask, dual_map)
        lattice.L = lattice.L[1:3]
        return cs_modes[1:3], lattice, info

    # Project dual points into affine space.
    dual = proj_affine(dual.T).T
    if DEBUG:
        print('proj dual')
        print(dual)
    info['d'] = dual.shape[1]

    # Filter duplicate points.
    idx = np.lexsort(np.rot90(dual))
    dual_map = []
    dual_unique = []
    i = 0
    while i < len(idx):
        if i == 0:
            dual_unique.append(dual[idx[i], :])
            dual_map.append([idx[i]])
        else:
            curr = dual[idx[i], :]
            last = dual_unique[-1]
            if np.linalg.norm(last - curr) < 1e-6:
                dual_map[-1].append(idx[i])
            else:
                dual_unique.append(dual[idx[i], :])
                dual_map.append([idx[i]])
        i += 1
    if DEBUG:
        print('dual map')
        print(dual_map)
        print('dual unique')
        print(dual_unique)

    # Handle various cases.
    dual = [list(dual_unique[i]) for i in range(len(dual_unique))]
    if len(dual_unique) == 1:
        d = 0
        M = np.array([[]])
    elif len(dual_unique[0]) == 1:
        d = 1
        M = np.zeros((len(dual), 2), int)
        i_min = np.argmin(np.array(dual).flatten())
        i_max = np.argmax(np.array(dual).flatten())
        M[i_min, 0] = 1
        M[i_max, 1] = 1
    else:
        d = len(dual[0])

        # Compute dual convex hull.
        t_start = time()
        ret = pyhull.qconvex('Fv', dual)
        info['time conv'] = time() - t_start

        if DEBUG:
            print(np.array(ret))

        # Build facet-vertex incidence matrix.
        n_facets = int(ret[0])
        M = np.zeros((len(dual), n_facets), int)
        for i in range(1, len(ret)):
            vert_set = [int(x) for x in ret[i].split(' ')][1:]
            for v in vert_set:
                M[v, i - 1] = 1

    if DEBUG:
        print('dual')
        print(np.array(dual))

    if DEBUG:
        print('M')
        print(M)

    # Build face lattice.
    t_start = time()
    lattice = FaceLattice(M, d)
    info['time lattice'] = time() - t_start

    # Build mode strings.
    cs_modes = lattice.csmodes(mask, dual_map)

    if DEBUG:
        print(cs_modes)

    info['# 0 faces'] = lattice.num_k_faces(0)
    info['# d-1 faces'] = lattice.num_k_faces(info['d'] - 1)
    info['# faces'] = lattice.num_faces()

    # Return mode strings.
    return cs_modes, lattice, info