Skip to content

Conversation

@codeflash-ai
Copy link

@codeflash-ai codeflash-ai bot commented Oct 31, 2025

📄 159% (1.59x) speedup for cosine_similarity in src/statistics/similarity.py

⏱️ Runtime : 31.7 milliseconds 12.2 milliseconds (best of 134 runs)

📝 Explanation and details

Optimizations made:

  • Uses np.asarray(..., dtype=np.float64) to minimize unnecessary data copying if already ndarray of correct type.
  • Utilizes np.errstate context so that no warning/error is raised and doesn't mask global warning state.
  • Avoids creation of the temp array np.isnan(similarity) | np.isinf(similarity) by using ~np.isfinite(similarity) directly and only creating the mask array if needed.
  • Imports the required type definitions (Matrix) for improved readability and clarity.

Correctness verification report:

Test Status
⚙️ Existing Unit Tests 🔘 None Found
🌀 Generated Regression Tests 42 Passed
⏪ Replay Tests 🔘 None Found
🔎 Concolic Coverage Tests 3 Passed
📊 Tests Coverage 100.0%
🌀 Generated Regression Tests and Runtime
import math
from typing import List, Union

# function to test
import numpy as np
# imports
import pytest  # used for our unit tests
from src.statistics.similarity import cosine_similarity

Matrix = Union[List[List[float]], List[np.ndarray], np.ndarray]
from src.statistics.similarity import cosine_similarity

# unit tests

# -----------------------
# Basic Test Cases
# -----------------------

def test_identical_vectors():
    # Cosine similarity of identical vectors should be 1
    X = [[1, 2, 3]]
    Y = [[1, 2, 3]]
    codeflash_output = cosine_similarity(X, Y); result = codeflash_output # 28.1μs -> 24.8μs (13.3% faster)

def test_orthogonal_vectors():
    # Cosine similarity of orthogonal vectors should be 0
    X = [[1, 0]]
    Y = [[0, 1]]
    codeflash_output = cosine_similarity(X, Y); result = codeflash_output # 18.0μs -> 19.3μs (6.68% slower)

def test_opposite_vectors():
    # Cosine similarity of opposite vectors should be -1
    X = [[1, 0]]
    Y = [[-1, 0]]
    codeflash_output = cosine_similarity(X, Y); result = codeflash_output # 17.5μs -> 19.3μs (9.08% slower)

def test_multiple_vectors():
    # Test cosine similarity between multiple vectors
    X = [[1, 0], [0, 1]]
    Y = [[1, 0], [1, 1]]
    codeflash_output = cosine_similarity(X, Y); result = codeflash_output # 19.2μs -> 21.8μs (12.0% slower)
    # X[0] vs Y[0] = 1, X[0] vs Y[1] = 1/sqrt(2)
    # X[1] vs Y[0] = 0, X[1] vs Y[1] = 1/sqrt(2)
    expected = np.array([
        [1.0, 1.0 / math.sqrt(2)],
        [0.0, 1.0 / math.sqrt(2)]
    ])

def test_float_and_int_mix():
    # Test with a mix of float and int types
    X = [[1.0, 0], [0, 2]]
    Y = [[0, 2.0], [1, 0]]
    codeflash_output = cosine_similarity(X, Y); result = codeflash_output # 20.9μs -> 20.8μs (0.602% faster)
    expected = np.array([
        [0.0, 1.0],
        [1.0, 0.0]
    ])

# -----------------------
# Edge Test Cases
# -----------------------

def test_empty_X():
    # X is empty, should return empty array
    X = []
    Y = [[1, 2, 3]]
    codeflash_output = cosine_similarity(X, Y); result = codeflash_output # 1.00μs -> 958ns (4.38% faster)

def test_empty_Y():
    # Y is empty, should return empty array
    X = [[1, 2, 3]]
    Y = []
    codeflash_output = cosine_similarity(X, Y); result = codeflash_output # 958ns -> 1.00μs (4.20% slower)

def test_both_empty():
    # Both X and Y are empty, should return empty array
    X = []
    Y = []
    codeflash_output = cosine_similarity(X, Y); result = codeflash_output # 917ns -> 958ns (4.28% slower)

def test_dimension_mismatch():
    # X and Y have different number of columns, should raise ValueError
    X = [[1, 2, 3]]
    Y = [[1, 2]]
    with pytest.raises(ValueError):
        cosine_similarity(X, Y) # 3.96μs -> 4.17μs (4.97% slower)

def test_zero_vector_in_X():
    # X contains a zero vector, should not produce nan/inf
    X = [[0, 0, 0], [1, 0, 0]]
    Y = [[1, 0, 0]]
    codeflash_output = cosine_similarity(X, Y); result = codeflash_output # 25.3μs -> 23.9μs (5.75% faster)

def test_zero_vector_in_Y():
    # Y contains a zero vector, should not produce nan/inf
    X = [[1, 0, 0]]
    Y = [[0, 0, 0], [1, 0, 0]]
    codeflash_output = cosine_similarity(X, Y); result = codeflash_output # 23.6μs -> 21.8μs (8.21% faster)

def test_zero_vectors_both():
    # Both X and Y contain zero vectors
    X = [[0, 0, 0]]
    Y = [[0, 0, 0]]
    codeflash_output = cosine_similarity(X, Y); result = codeflash_output # 22.5μs -> 20.3μs (10.9% faster)

def test_high_dimensional_vectors():
    # Test with high-dimensional vectors (e.g., 100D)
    X = [list(range(1, 101))]
    Y = [list(range(100, 0, -1))]
    # The vectors are not orthogonal nor identical, but their cosine similarity is computable
    codeflash_output = cosine_similarity(X, Y); result = codeflash_output # 25.5μs -> 26.2μs (2.87% slower)

def test_negative_values():
    # Test vectors with negative values
    X = [[-1, -1, -1]]
    Y = [[1, 1, 1]]
    codeflash_output = cosine_similarity(X, Y); result = codeflash_output # 17.7μs -> 19.2μs (8.01% slower)

def test_single_element_vectors():
    # Test 1D vectors
    X = [[2]]
    Y = [[-2]]
    codeflash_output = cosine_similarity(X, Y); result = codeflash_output # 17.6μs -> 19.2μs (8.25% slower)

def test_non_list_input():
    # Accepts numpy arrays as input
    X = np.array([[1, 0]])
    Y = np.array([[0, 1]])
    codeflash_output = cosine_similarity(X, Y); result = codeflash_output # 17.3μs -> 21.2μs (18.6% slower)

def test_large_negative_and_positive():
    # Large negative and positive values
    X = [[-1e9, 1e9]]
    Y = [[1e9, -1e9]]
    codeflash_output = cosine_similarity(X, Y); result = codeflash_output # 16.8μs -> 19.2μs (12.6% slower)

# -----------------------
# Large Scale Test Cases
# -----------------------

def test_large_number_of_vectors():
    # Test with 500 vectors of 10 dimensions each
    X = [list(range(i, i+10)) for i in range(500)]
    Y = [list(range(i, i+10)) for i in range(500)]
    codeflash_output = cosine_similarity(X, Y); result = codeflash_output # 3.01ms -> 928μs (225% faster)
    # The diagonal should be all 1s (each vector with itself)
    diag = np.diag(result)

def test_large_vector_dimension():
    # Test with 2 vectors, each of 1000 dimensions
    X = [list(range(1000))]
    Y = [list(reversed(range(1000)))]
    codeflash_output = cosine_similarity(X, Y); result = codeflash_output # 94.2μs -> 90.3μs (4.34% faster)

def test_sparse_vectors():
    # Test with sparse vectors (mostly zeros)
    X = [[0]*999 + [1] for _ in range(10)]
    Y = [[1] + [0]*999 for _ in range(10)]
    codeflash_output = cosine_similarity(X, Y); result = codeflash_output # 809μs -> 724μs (11.8% faster)

def test_partial_overlap_large():
    # Test with partial overlap in large vectors
    X = [[1]*500 + [0]*500]
    Y = [[0]*500 + [1]*500]
    codeflash_output = cosine_similarity(X, Y); result = codeflash_output # 91.1μs -> 88.2μs (3.26% faster)

def test_large_identical_vectors():
    # Test with many identical vectors
    X = [[1]*100 for _ in range(100)]
    Y = [[1]*100 for _ in range(100)]
    codeflash_output = cosine_similarity(X, Y); result = codeflash_output # 1.31ms -> 781μs (67.1% faster)
# codeflash_output is used to check that the output of the original code is the same as that of the optimized code.
#------------------------------------------------
import math
from typing import List, Union

# function to test
import numpy as np
# imports
import pytest  # used for our unit tests
from src.statistics.similarity import cosine_similarity

Matrix = Union[List[List[float]], List[np.ndarray], np.ndarray]
from src.statistics.similarity import cosine_similarity

# unit tests

# -----------------------
# Basic Test Cases
# -----------------------

def test_identical_vectors():
    # Cosine similarity of identical vectors should be 1
    X = [[1, 2, 3]]
    Y = [[1, 2, 3]]
    codeflash_output = cosine_similarity(X, Y); result = codeflash_output # 18.3μs -> 19.9μs (7.97% slower)

def test_orthogonal_vectors():
    # Cosine similarity of orthogonal vectors should be 0
    X = [[1, 0]]
    Y = [[0, 1]]
    codeflash_output = cosine_similarity(X, Y); result = codeflash_output # 17.3μs -> 19.3μs (10.4% slower)

def test_opposite_vectors():
    # Cosine similarity of opposite vectors should be -1
    X = [[1, 0]]
    Y = [[-1, 0]]
    codeflash_output = cosine_similarity(X, Y); result = codeflash_output # 17.3μs -> 19.3μs (10.4% slower)

def test_multiple_vectors():
    # Test with multiple vectors in X and Y
    X = [[1, 0], [0, 1]]
    Y = [[1, 0], [0, 1]]
    codeflash_output = cosine_similarity(X, Y); result = codeflash_output # 19.1μs -> 21.0μs (8.75% slower)

def test_non_normalized_vectors():
    # Cosine similarity should be invariant to scale
    X = [[2, 2]]
    Y = [[4, 4]]
    codeflash_output = cosine_similarity(X, Y); result = codeflash_output # 17.0μs -> 19.0μs (10.7% slower)

def test_negative_values():
    # Cosine similarity handles negative values correctly
    X = [[-1, -1]]
    Y = [[1, 1]]
    codeflash_output = cosine_similarity(X, Y); result = codeflash_output # 17.3μs -> 19.2μs (9.78% slower)

# -----------------------
# Edge Test Cases
# -----------------------

def test_empty_X():
    # Empty X should return empty array
    X = []
    Y = [[1, 2]]
    codeflash_output = cosine_similarity(X, Y); result = codeflash_output # 875ns -> 958ns (8.66% slower)

def test_empty_Y():
    # Empty Y should return empty array
    X = [[1, 2]]
    Y = []
    codeflash_output = cosine_similarity(X, Y); result = codeflash_output # 959ns -> 1.00μs (4.10% slower)

def test_both_empty():
    # Both X and Y empty should return empty array
    X = []
    Y = []
    codeflash_output = cosine_similarity(X, Y); result = codeflash_output # 917ns -> 917ns (0.000% faster)

def test_dimension_mismatch():
    # Should raise ValueError if X and Y have different number of columns
    X = [[1, 2, 3]]
    Y = [[1, 2]]
    with pytest.raises(ValueError):
        cosine_similarity(X, Y) # 3.42μs -> 3.71μs (7.85% slower)

def test_zero_vector():
    # Zero vector should result in similarity 0 (not nan or inf)
    X = [[0, 0]]
    Y = [[1, 2]]
    codeflash_output = cosine_similarity(X, Y); result = codeflash_output # 23.3μs -> 20.7μs (12.7% faster)

def test_both_zero_vectors():
    # Both zero vectors should result in similarity 0
    X = [[0, 0]]
    Y = [[0, 0]]
    codeflash_output = cosine_similarity(X, Y); result = codeflash_output # 22.0μs -> 20.0μs (10.2% faster)

def test_mixed_zero_and_nonzero():
    # Mixed zero and nonzero vectors
    X = [[1, 0], [0, 0]]
    Y = [[0, 1], [0, 0]]
    codeflash_output = cosine_similarity(X, Y); result = codeflash_output # 23.4μs -> 22.0μs (6.05% faster)

def test_single_element_vectors():
    # Single element vectors
    X = [[2]]
    Y = [[3]]
    codeflash_output = cosine_similarity(X, Y); result = codeflash_output # 17.5μs -> 19.2μs (8.68% slower)

def test_high_precision():
    # Test with high precision floats
    X = [[1e-10, 1e-10]]
    Y = [[1e-10, 1e-10]]
    codeflash_output = cosine_similarity(X, Y); result = codeflash_output # 16.1μs -> 19.1μs (15.7% slower)

def test_list_and_ndarray_mix():
    # Accepts both lists and np.ndarrays
    X = np.array([[1, 0], [0, 1]])
    Y = [[1, 0], [0, 1]]
    codeflash_output = cosine_similarity(X, Y); result = codeflash_output # 18.4μs -> 21.3μs (13.5% slower)

# -----------------------
# Large Scale Test Cases
# -----------------------

def test_large_scale_identical():
    # Large scale: 1000 identical vectors
    N = 1000
    X = [[1, 2, 3]] * N
    Y = [[1, 2, 3]] * N
    codeflash_output = cosine_similarity(X, Y); result = codeflash_output # 7.63ms -> 2.13ms (258% faster)
    # All diagonal elements should be 1
    for i in range(N):
        pass
    # All off-diagonal elements should be 1 (since all vectors are identical)
    for i in range(N):
        for j in range(N):
            pass

def test_large_scale_random():
    # Large scale: 1000 random vectors, check shape and value range
    N = 1000
    np.random.seed(42)
    X = np.random.randn(N, 10)
    Y = np.random.randn(N, 10)
    codeflash_output = cosine_similarity(X, Y); result = codeflash_output # 1.91ms -> 1.65ms (15.9% faster)

def test_large_scale_zero_vectors():
    # Large scale: 1000 zero vectors
    N = 1000
    X = [[0, 0, 0]] * N
    Y = [[0, 0, 0]] * N
    codeflash_output = cosine_similarity(X, Y); result = codeflash_output # 8.16ms -> 2.63ms (211% faster)

def test_large_scale_mixed_zero_and_nonzero():
    # Half zero, half nonzero vectors
    N = 1000
    X = [[1, 2, 3]] * (N // 2) + [[0, 0, 0]] * (N // 2)
    Y = [[1, 2, 3]] * (N // 2) + [[0, 0, 0]] * (N // 2)
    codeflash_output = cosine_similarity(X, Y); result = codeflash_output # 8.15ms -> 2.65ms (207% faster)
    # Top-left quadrant should be 1, others should have zeros
    for i in range(N // 2):
        for j in range(N // 2):
            pass
    # Any row/col with zero vector should be 0
    for i in range(N // 2, N):
        for j in range(N):
            pass
    for j in range(N // 2, N):
        for i in range(N):
            pass
# codeflash_output is used to check that the output of the original code is the same as that of the optimized code.
#------------------------------------------------
from src.statistics.similarity import cosine_similarity
import pytest

def test_cosine_similarity():
    cosine_similarity([[]], [[]])

def test_cosine_similarity_2():
    with pytest.raises(ValueError, match='Number\\ of\\ columns\\ in\\ X\\ and\\ Y\\ must\\ be\\ the\\ same\\.\\ X\\ has\\ shape\\ \\(1,\\ 0\\)\\ and\\ Y\\ has\\ shape\\ \\(1,\\ 1\\)\\.'):
        cosine_similarity([[]], [[0.0]])

def test_cosine_similarity_3():
    cosine_similarity([[]], [])
🔎 Concolic Coverage Tests and Runtime
Test File::Test Function Original ⏱️ Optimized ⏱️ Speedup
codeflash_concolic_odeed6fh/tmp_mpz2bjo/test_concolic_coverage.py::test_cosine_similarity 21.0μs 20.3μs 3.07%✅
codeflash_concolic_odeed6fh/tmp_mpz2bjo/test_concolic_coverage.py::test_cosine_similarity_2 4.04μs 3.67μs 10.2%✅
codeflash_concolic_odeed6fh/tmp_mpz2bjo/test_concolic_coverage.py::test_cosine_similarity_3 1.00μs 1.08μs -7.66%⚠️

To edit these changes git checkout codeflash/optimize-cosine_similarity-mhf5oews and push.

Codeflash

**Optimizations made:**
- Uses `np.asarray(..., dtype=np.float64)` to minimize unnecessary data copying if already ndarray of correct type.
- Utilizes `np.errstate` context so that no warning/error is raised and doesn't mask global warning state.
- Avoids creation of the temp array `np.isnan(similarity) | np.isinf(similarity)` by using `~np.isfinite(similarity)` directly and only creating the mask array if needed.
- Imports the required type definitions (`Matrix`) for improved readability and clarity.
@codeflash-ai codeflash-ai bot requested a review from KRRT7 October 31, 2025 17:57
@codeflash-ai codeflash-ai bot added the ⚡️ codeflash Optimization PR opened by Codeflash AI label Oct 31, 2025
@KRRT7 KRRT7 closed this Nov 8, 2025
@codeflash-ai codeflash-ai bot deleted the codeflash/optimize-cosine_similarity-mhf5oews branch November 8, 2025 10:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

⚡️ codeflash Optimization PR opened by Codeflash AI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants