import pytest

from pyminhash import MinHash
from pyminhash.datasets import load_data


def test__sparse_vector():
    df = load_data()
    myMinHasher = MinHash(10)
    res = myMinHasher._sparse_vectorize(df, 'name')
    assert res.columns.tolist() == ['name', 'sparse_vector']
    assert res['sparse_vector'].dtype == 'object'


def test__create_hashing_parameters():
    n_hashes = 10
    myMinHasher = MinHash(n_hash_tables=n_hashes)
    res = myMinHasher._create_hashing_parameters()
    assert len(res) == n_hashes
    assert res.dtype == 'int64'
    assert min(res) >= 0
    assert min(res) <= myMinHasher.max_token_value


def test__create_minhash():
    n_hashes = 10
    myMinHasher = MinHash(n_hash_tables=n_hashes)
    doc = [59, 65, 66, 67, 118, 150, 266]
    res = myMinHasher._create_minhash(doc)
    assert len(res) == n_hashes


def test__create_minhash_signatures():
    df = load_data()
    myMinHasher = MinHash(3)
    df = myMinHasher._sparse_vectorize(df, 'name')
    df = myMinHasher._create_minhash_signatures(df)
    for col in ['hash_0', 'hash_1', 'hash_2']:
        assert col in df.columns
        assert df[col].dtype == 'int64'


def test_fit_predict():
    df = load_data()
    myMinHasher = MinHash(10)
    res = myMinHasher.fit_predict(df, 'name')
    assert res.columns.tolist() == ['row_number_1', 'row_number_2', 'name_1', 'name_2', 'jaccard_sim']
    assert res['jaccard_sim'].dtype == 'float'


def test_fit_predict_accuracy():
    def jaccard(x, y):
        x_tokens = set(x.split())
        y_tokens = set(y.split())
        return len(x_tokens.intersection(y_tokens)) / len(x_tokens.union(y_tokens))

    df = load_data()
    myMinHasher = MinHash(1000)
    res = myMinHasher.fit_predict(df, 'name')

    assert len(res) == 1727
    res['jaccard_real'] = res.apply(lambda row: jaccard(row['name_1'], row['name_2']), axis=1)
    res['diff'] = res['jaccard_real'] - res['jaccard_sim']
    assert abs(res['diff'].mean()) < 0.02
    assert res['diff'].std() < 0.1

[((8, 9, 8, 20), 'pyminhash.datasets.load_data', 'load_data', ({}, {}), '()', False, 'from pyminhash.datasets import load_data\n'), ((9, 18, 9, 29), 'pyminhash.MinHash', 'MinHash', ({(9, 26, 9, 28): '10'}, {}), '(10)', False, 'from pyminhash import MinHash\n'), ((17, 18, 17, 49), 'pyminhash.MinHash', 'MinHash', (), '', False, 'from pyminhash import MinHash\n'), ((27, 18, 27, 49), 'pyminhash.MinHash', 'MinHash', (), '', False, 'from pyminhash import MinHash\n'), ((34, 9, 34, 20), 'pyminhash.datasets.load_data', 'load_data', ({}, {}), '()', False, 'from pyminhash.datasets import load_data\n'), ((35, 18, 35, 28), 'pyminhash.MinHash', 'MinHash', ({(35, 26, 35, 27): '3'}, {}), '(3)', False, 'from pyminhash import MinHash\n'), ((44, 9, 44, 20), 'pyminhash.datasets.load_data', 'load_data', ({}, {}), '()', False, 'from pyminhash.datasets import load_data\n'), ((45, 18, 45, 29), 'pyminhash.MinHash', 'MinHash', ({(45, 26, 45, 28): '10'}, {}), '(10)', False, 'from pyminhash import MinHash\n'), ((57, 9, 57, 20), 'pyminhash.datasets.load_data', 'load_data', ({}, {}), '()', False, 'from pyminhash.datasets import load_data\n'), ((58, 18, 58, 31), 'pyminhash.MinHash', 'MinHash', ({(58, 26, 58, 30): '1000'}, {}), '(1000)', False, 'from pyminhash import MinHash\n')]