Ejemplo n.º 1
0
def test_circumsphere():
    from numpy import allclose
    from numpy.random import normal, uniform

    from adaptive.learner.triangulation import circumsphere, fast_norm

    def generate_random_sphere_points(dim, radius=0):
        """https://math.stackexchange.com/a/1585996"""

        vec = [None] * (dim + 1)
        center = uniform(-100, 100, dim)
        radius = uniform(1.0, 100.0) if radius == 0 else radius
        for i in range(dim + 1):
            points = normal(0, size=dim)
            x = fast_norm(points)
            points = points / x * radius
            vec[i] = tuple(points + center)

        return radius, center, vec

    for dim in range(2, 10):
        radius, center, points = generate_random_sphere_points(dim)
        circ_center, circ_radius = circumsphere(points)
        err_msg = ""
        if not allclose(circ_center, center):
            err_msg += f"Calculated center ({circ_center}) differs from true center ({center})\n"
        if not allclose(radius, circ_radius):
            err_msg += (
                f"Calculated radius {circ_radius} differs from true radius {radius}\n"
            )
        if err_msg:
            raise AssertionError(err_msg)
Ejemplo n.º 2
0
def choose_point_in_simplex(simplex, transform=None):
    """Choose a new point in inside a simplex.

    Pick the center of the simplex if the shape is nice (that is, the
    circumcenter lies within the simplex). Otherwise take the middle of the
    longest edge.

    Parameters
    ----------
    simplex : numpy array
        The coordinates of a triangle with shape (N+1, N).
    transform : N*N matrix
        The multiplication to apply to the simplex before choosing
        the new point.

    Returns
    -------
    point : numpy array of length N
        The coordinates of the suggested new point.
    """

    if transform is not None:
        simplex = np.dot(simplex, transform)

    # choose center if and only if the shape of the simplex is nice,
    # otherwise: the center the longest edge
    center, _radius = circumsphere(simplex)
    if point_in_simplex(center, simplex):
        point = np.average(simplex, axis=0)
    else:
        distances = scipy.spatial.distance.pdist(simplex)
        distance_matrix = scipy.spatial.distance.squareform(distances)
        i, j = np.unravel_index(np.argmax(distance_matrix),
                                distance_matrix.shape)
        point = (simplex[i, :] + simplex[j, :]) / 2

    if transform is not None:
        point = np.linalg.solve(transform, point)  # undo the transform

    return point