Example #1
0
 def updateSublattice(self, sublattice):
     boltzmanFactor = np.exp(2 * self.interactionEnergies /
                             (self.k * self.t))
     evenDist = np.random.uniform(0, 1, size=self.spec)
     temp1 = np.greater(self.interactionEnergies, self.ground)
     temp2 = np.greater(boltzmanFactor, evenDist)
     criteria = np.logical_and(sublattice, np.logical_or(temp1, temp2))
     self.system = np.where(criteria, -self.system, self.system)
     self.updateEnergies()
Example #2
0
def greater(x1: Array, x2: Array, /) -> Array:
    """
    Array API compatible wrapper for :py:func:`np.greater <numpy.greater>`.

    See its docstring for more information.
    """
    if x1.dtype not in _numeric_dtypes or x2.dtype not in _numeric_dtypes:
        raise TypeError("Only numeric dtypes are allowed in greater")
    # Call result type here just to raise on disallowed type combinations
    _result_type(x1.dtype, x2.dtype)
    x1, x2 = Array._normalize_two_args(x1, x2)
    return Array._new(np.greater(x1._array, x2._array))
Example #3
0
 def __gt__(self, other):
     return cupy.greater(self, other)
Example #4
0
def _hc(k, cs, rho, omega):
    return (cs / sin(omega) * (rho**k) * sin(omega * (k + 1)) * greater(k, -1))
Example #5
0
def evaluate_chunks(
        results: [cp.ndarray, cp.ndarray,
                  cp.ndarray],  # closest triangle, distance, projection
        all_pts: cp.ndarray = None,
        vertices: cp.ndarray = None,
        edges: cp.ndarray = None,
        edge_norms: cp.ndarray = None,
        edge_normssq: cp.ndarray = None,
        normals: cp.ndarray = None,
        norms: cp.ndarray = None,
        normssq: cp.ndarray = None,
        zero_tensor: cp.ndarray = None,
        one_tensor: cp.ndarray = None,
        tris: cp.ndarray = None,
        vertex_normals: cp.ndarray = None,
        bounding_box: dict = None,
        chunk_size: int = None,
        num_verts: int = None) -> None:

    #
    # Expand vertex normals if non empty
    if vertex_normals is not None:
        vertex_normals = vertex_normals[tris]
        vertex_normals = cp.tile(cp.expand_dims(vertex_normals, axis=2),
                                 (1, 1, chunk_size, 1))

    # begin = time.time()
    #
    # Load and extend the batch
    num_chunks = all_pts.shape[0] // chunk_size
    for i in range(num_chunks):
        #
        # Get subset of the query points
        start_index = i * chunk_size
        end_index = (i + 1) * chunk_size
        pts = all_pts[start_index:end_index, :]

        #
        # Match the dimensions to those assumed above.
        #    REPEATED       REPEATED
        # [triangle_index, vert_index, querypoint_index, coordinates]
        pts = cp.tile(cp.expand_dims(pts, axis=(0, 1)), (num_verts, 3, 1, 1))

        #
        # Compute the differences between
        # vertices on each triangle and the
        # points of interest
        #
        # [triangle_index, vert_index, querypoint_index, coordinates]
        # ===================
        # [:,0,:,:] = p - p1
        # [:,1,:,:] = p - p2
        # [:,2,:,:] = p - p3
        diff_vectors = pts - vertices

        #
        # Compute alpha, beta, gamma
        barycentric = cp.empty(diff_vectors.shape)

        #
        # gamma = u x (p - p1)
        barycentric[:, 2, :, :] = cp.cross(edges[:, 0, :, :],
                                           diff_vectors[:, 0, :, :])
        # beta = (p - p1) x v
        barycentric[:, 1, :, :] = cp.cross(diff_vectors[:, 0, :, :],
                                           edges[:, 1, :, :])
        # alpha = w x (p - p2)
        barycentric[:, 0, :, :] = cp.cross(edges[:, 2, :, :],
                                           diff_vectors[:, 1, :, :])
        barycentric = cp.divide(
            cp.sum(cp.multiply(barycentric, normals), axis=3), normssq)

        #
        # Test conditions
        less_than_one = cp.less_equal(barycentric, one_tensor)
        more_than_zero = cp.greater_equal(barycentric, zero_tensor)

        #
        #     if 0 <= gamma and gamma <= 1
        #    and 0 <= beta and beta <= 1
        #    and 0 <= alpha and alpha <= 1:
        cond1 = cp.logical_and(less_than_one, more_than_zero)

        #
        #     if gamma <= 0:
        cond2 = cp.logical_not(more_than_zero[:, 2, :])
        cond2 = cp.tile(cp.expand_dims(cond2, axis=1), (1, 3, 1))

        #
        #     if beta <= 0:
        cond3 = cp.logical_not(more_than_zero[:, 1, :])
        cond3 = cp.tile(cp.expand_dims(cond3, axis=1), (1, 3, 1))

        #
        #     if alpha <= 0:
        cond4 = cp.logical_not(more_than_zero[:, 0, :])
        cond4 = cp.tile(cp.expand_dims(cond4, axis=1), (1, 3, 1))

        #
        # Get the projections for each case
        xi = cp.empty(barycentric.shape)
        barycentric_ext = cp.tile(cp.expand_dims(barycentric, axis=3),
                                  (1, 1, 1, 3))
        proj = cp.sum(cp.multiply(barycentric_ext, vertices), axis=1)
        #
        #     if 0 <= gamma and gamma <= 1
        #    and 0 <= beta and beta <= 1
        #    and 0 <= alpha and alpha <= 1:
        xi[cond1] = barycentric[cond1]

        #
        # if gamma <= 0:
        #  x = p - p1
        #  u = p2 - p1
        #  a = p1
        #  b = p2
        t2 = cp.divide(
            #
            # u.dot(x)
            cp.sum(cp.multiply(edges[:, 0, :, :], diff_vectors[:, 0, :, :]),
                   axis=2),
            edge_normssq[:, 0])
        xi2 = cp.zeros((t2.shape[0], 3, t2.shape[1]))
        xi2[:, 0, :] = -t2 + 1
        xi2[:, 1, :] = t2
        #
        t2 = cp.tile(cp.expand_dims(t2, axis=2), (1, 1, 3))
        lz = cp.less(t2, cp.zeros(t2.shape))
        go = cp.greater(t2, cp.ones(t2.shape))
        proj2 = vertices[:, 0, :, :] + cp.multiply(t2, edges[:, 0, :, :])
        proj2[lz] = vertices[:, 0, :, :][lz]
        proj2[go] = vertices[:, 1, :, :][go]
        #
        xi[cond2] = xi2[cond2]
        proj[cp.swapaxes(cond2, 1, 2)] = proj2[cp.swapaxes(cond2, 1, 2)]

        #
        # if beta <= 0:
        #  x = p - p1
        #  v = p3 - p1
        #  a = p1
        #  b = p3
        t3 = cp.divide(
            #
            # v.dot(x)
            cp.sum(cp.multiply(edges[:, 1, :, :], diff_vectors[:, 0, :, :]),
                   axis=2),
            edge_normssq[:, 1])
        xi3 = cp.zeros((t3.shape[0], 3, t3.shape[1]))
        xi3[:, 0, :] = -t3 + 1
        xi3[:, 2, :] = t3
        #
        t3 = cp.tile(cp.expand_dims(t3, axis=2), (1, 1, 3))
        lz = cp.less(t3, cp.zeros(t3.shape))
        go = cp.greater(t3, cp.ones(t3.shape))
        proj3 = vertices[:, 0, :, :] + cp.multiply(t3, edges[:, 1, :, :])
        proj3[lz] = vertices[:, 0, :, :][lz]
        proj3[go] = vertices[:, 2, :, :][go]
        #
        xi[cond3] = xi3[cond3]
        proj[cp.swapaxes(cond3, 1, 2)] = proj3[cp.swapaxes(cond3, 1, 2)]

        #
        #     if alpha <= 0:
        #  y = p - p2
        #  w = p3 - p2
        #  a = p2
        #  b = p3
        t4 = cp.divide(
            #
            # w.dot(y)
            cp.sum(cp.multiply(edges[:, 2, :, :], diff_vectors[:, 1, :, :]),
                   axis=2),
            edge_normssq[:, 2])
        xi4 = cp.zeros((t4.shape[0], 3, t4.shape[1]))
        xi4[:, 1, :] = -t4 + 1
        xi4[:, 2, :] = t4
        #
        t4 = cp.tile(cp.expand_dims(t4, axis=2), (1, 1, 3))
        lz = cp.less(t4, cp.zeros(t4.shape))
        go = cp.greater(t4, cp.ones(t4.shape))
        proj4 = vertices[:, 1, :, :] + cp.multiply(t4, edges[:, 2, :, :])
        proj4[lz] = vertices[:, 1, :, :][lz]
        proj4[go] = vertices[:, 2, :, :][go]
        #
        xi[cond4] = xi4[cond4]
        proj[cp.swapaxes(cond4, 1, 2)] = proj4[cp.swapaxes(cond4, 1, 2)]

        vec_to_point = pts[:, 0, :, :] - proj
        distances = cp.linalg.norm(vec_to_point, axis=2)

        # n = "\n"
        # print(f"{pts[:,0,:,:]=}")
        # print(f"{proj=}")
        # print(f"{pts[:,0,:,:] - proj=}")
        # print(f"{distances=}")

        min_distances = cp.min(distances, axis=0)

        closest_triangles = cp.argmin(distances, axis=0)

        projections = proj[closest_triangles, np.arange(chunk_size), :]

        #
        # Distinguish close triangles
        is_close = cp.isclose(distances, min_distances)

        #
        # Determine sign
        signed_normal = normals[:, 0, :, :]
        if vertex_normals is not None:
            signed_normal = cp.sum(vertex_normals.transpose() * xi.transpose(),
                                   axis=2).transpose()

        is_negative = cp.less_equal(
            cp.sum(cp.multiply(vec_to_point, signed_normal), axis=2), 0.)

        #
        # Combine
        is_close_and_negative = cp.logical_and(is_close, is_negative)

        #
        # Determine if inside
        is_inside = cp.all(cp.logical_or(is_close_and_negative,
                                         cp.logical_not(is_close)),
                           axis=0)

        #
        # Overwrite the signs of points
        # that are outside of the box
        if bounding_box is not None:
            #
            # Extract
            rotation_matrix = cp.asarray(bounding_box['rotation_matrix'])
            translation_vector = cp.asarray(bounding_box['translation_vector'])
            size = cp.asarray(bounding_box['size'])
            #
            # Transform
            transformed_pts = cp.dot(
                all_pts[start_index:end_index, :] - translation_vector,
                rotation_matrix)

            #
            # Determine if outside bbox
            inside_bbox = cp.all(cp.logical_and(
                cp.less_equal(0., transformed_pts),
                cp.less_equal(transformed_pts, size)),
                                 axis=1)

            #
            # Treat points outside bbox as
            # being outside of lumen
            print(f"{inside_bbox=}")
            is_inside = cp.logical_and(is_inside, inside_bbox)

        #
        # Apply sign to indicate whether the distance is
        # inside or outside the mesh.
        min_distances[is_inside] = -1 * min_distances[is_inside]

        #
        # Emplace results
        # [triangle_index, vert_index, querypoint_index, coordinates]
        results[0][start_index:end_index] = closest_triangles
        results[1][start_index:end_index] = min_distances
        results[2][start_index:end_index, :] = projections
def basis_pursuit(A, b, tol=1e-4, niter=100, biter=32):
    """
    solves min |x|_1 s.t. Ax=b using a Primal-Dual Interior Point Method

    Args:
      A: design matrix of size (d, n)
      b: measurement vector of length d
      tol: solver tolerance
      niter: maximum length of central path
      biter: maximum number of steps in backtracking line search

    Returns:
      vector of length n
    """
    A = cp.asarray(A)
    b = cp.asarray(b)
    d, n = A.shape
    alpha = 0.01
    beta = 0.5
    mu = 10
    e = cp.ones(n)
    gradf0 = cp.hstack([cp.zeros(n), e])
    x = (A.T).dot(inv(A.dot(A.T))).dot(b)
    absx = cp.abs(x)
    u = 0.95 * absx + 0.1 * cp.max(absx)

    fu1 = x - u
    fu2 = -x - u
    lamu1 = -1.0 / fu1
    lamu2 = -1.0 / fu2
    v = A.dot(lamu2 - lamu1)
    ATv = (A.T).dot(v)
    sdg = -(cp.inner(fu1, lamu1) + cp.inner(fu2, lamu2))
    tau = 2.0 * n * mu / sdg
    ootau = 1.0 / tau

    rcent = cp.hstack([-lamu1 * fu1, -lamu2 * fu2]) - ootau
    rdual = gradf0 + cp.hstack([lamu1 - lamu2 + ATv, -lamu1 - lamu2])
    rpri = A.dot(x) - b
    resnorm = cp.sqrt(norm(rdual)**2 + norm(rcent)**2 + norm(rpri)**2)
    rdp = cp.empty(2 * n)
    rcp = cp.empty(2 * n)

    for i in range(niter):

        oofu1 = 1.0 / fu1
        oofu2 = 1.0 / fu2
        w1 = -ootau * (oofu2 - oofu1) - ATv
        w2 = -1.0 - ootau * (oofu1 + oofu2)
        w3 = -rpri

        lamu1xoofu1 = lamu1 * oofu1
        lamu2xoofu2 = lamu2 * oofu2
        sig1 = -lamu1xoofu1 - lamu2xoofu2
        sig2 = lamu1xoofu1 - lamu2xoofu2
        sigx = sig1 - sig2**2 / sig1
        if cp.min(cp.abs(sigx)) == 0.0:
            break

        w1p = -(w3 - A.dot(w1 / sigx - w2 * sig2 / (sigx * sig1)))
        H11p = A.dot((A.T) * (e / sigx)[:, cp.newaxis])
        if cp.min(sigx) > 0.0:
            dv = solve(H11p, w1p)
        else:
            dv = solve(H11p, w1p)
        dx = (w1 - w2 * sig2 / sig1 - (A.T).dot(dv)) / sigx
        Adx = A.dot(dx)
        ATdv = (A.T).dot(dv)

        du = (w2 - sig2 * dx) / sig1
        dlamu1 = lamu1xoofu1 * (du - dx) - lamu1 - ootau * oofu1
        dlamu2 = lamu2xoofu2 * (dx + du) - lamu2 - ootau * oofu2

        s = 1.0
        indp = cp.less(dlamu1, 0.0)
        indn = cp.less(dlamu2, 0.0)
        if cp.any(indp):
            s = min(s, cp.min(-lamu1[indp] / dlamu1[indp]))
        if cp.any(indn):
            s = min(s, cp.min(-lamu2[indn] / dlamu2[indn]))
        indp = cp.greater(dx - du, 0.0)
        indn = cp.greater(-dx - du, 0.0)
        if cp.any(indp):
            s = min(s, cp.min(-fu1[indp] / (dx[indp] - du[indp])))
        if cp.any(indn):
            s = min(s, cp.min(-fu2[indn] / (-dx[indn] - du[indn])))
        s = 0.99 * s

        for j in range(biter):
            xp = x + s * dx
            up = u + s * du
            vp = v + s * dv
            ATvp = ATv + s * ATdv
            lamu1p = lamu1 + s * dlamu1
            lamu2p = lamu2 + s * dlamu2
            fu1p = xp - up
            fu2p = -xp - up
            rdp[:n] = lamu1p - lamu2p + ATvp
            rdp[n:] = -lamu1p - lamu2p
            rdp += gradf0
            rcp[:n] = -lamu1p * fu1p
            rcp[n:] = lamu2p * fu2p
            rcp -= ootau
            rpp = rpri + s * Adx
            s *= beta
            if (cp.sqrt(norm(rdp)**2 + norm(rcp)**2 + norm(rpp)**2) <=
                (1 - alpha * s) * resnorm):
                break
        else:
            break

        x = xp
        lamu1 = lamu1p
        lamu2 = lamu2p
        fu1 = fu1p
        fu2 = fu2p
        sdg = -(cp.inner(fu1, lamu1) + cp.inner(fu2, lamu2))
        if sdg < tol:
            return cp.asnumpy(x)

        u = up
        v = vp
        ATv = ATvp
        tau = 2.0 * n * mu / sdg
        rpri = rpp
        rcent[:n] = lamu1 * fu1
        rcent[n:] = lamu2 * fu2
        ootau = 1.0 / tau
        rcent -= ootau
        rdual[:n] = lamu1 - lamu2 + ATv
        rdual[n:] = -lamu1 + lamu2
        rdual += gradf0
        resnorm = cp.sqrt(norm(rdual)**2 + norm(rcent)**2 + norm(rpri)**2)

    return cp.asnumpy(x)