# TASK-013

## Title

Music DNA Similarity Engine

---

## Objective

Implement the Music DNA Similarity Engine.

The engine compares two MusicDNAVector objects and produces a deterministic similarity result.

The result contains:

- overall similarity
- distance
- per-category similarity
- feature contribution explanation

This task introduces no recommendation system and no library search.

It compares exactly two vectors.

---

# Expected Commit Message

Add Music DNA Similarity Engine

---

# Requirements

Read before implementation

- docs/00_PROJECT_PRINCIPLES.md
- docs/01_SPEC.md
- docs/02_ARCHITECTURE.md
- docs/03_ANALYZER_API.md
- docs/04_MUSIC_DNA_SCHEMA.md
- docs/04a_FEATURE_REGISTRY.md
- docs/04b_NORMALIZATION_RULES.md
- docs/05_AI_DEVELOPER_GUIDE.md

---

# Scope

Create

src/similarity/

    __init__.py
    metrics.py
    engine.py
    explanation.py
    result.py
    exceptions.py

tests/

    test_similarity.py

---

# Metrics

Implement independent pure functions.

cosine_similarity()

Returns

0.0 .. 1.0

---

euclidean_distance()

Returns

>= 0

---

manhattan_distance()

Returns

>= 0

---

Metric functions must

accept

numpy.ndarray

dtype=float32

validate

- dimensions
- NaN
- Inf
- empty vectors
- schema compatibility

Metric functions must not know anything about MusicDNA.

---

# MusicDNALayout

Extend MusicDNALayout to support bidirectional mapping.

Required methods

get_index(feature_identifier)

get_feature(index)

contains(feature_identifier)

contains_index(index)

category(index)

indices(category)

dimension()

list_entries()

MusicDNALayout remains the single source of truth for vector layout.

Do not duplicate layout definitions anywhere else.

---

# SimilarityEngine

Implement

compare()

Input

MusicDNAVector A

MusicDNAVector B

metric

Output

SimilarityResult

Responsibilities

- validate vectors
- execute selected metric
- calculate overall similarity
- calculate distance
- calculate per-category similarity
- generate explanation

SimilarityEngine must only depend on

- MusicDNAVector
- MusicDNALayout
- similarity metrics

It must never require MusicDNA objects.

It must not know anything about

- database
- repositories
- filesystem
- CLI
- recommendation engine
- library search

---

# Per-Category Similarity

Calculate similarity independently for every MusicDNA block.

Categories

signal

spectral

dynamic

rhythm

harmony

Output

dictionary

Example

{
    "signal": 0.96,
    "spectral": 0.91,
    "dynamic": 0.88,
    "rhythm": 0.99,
    "harmony": 0.82
}

Category boundaries must come from MusicDNALayout.

---

# SimilarityExplanation

Implement explanation generation.

Input

MusicDNAVector

MusicDNAVector

MusicDNALayout

Output

Ordered list of feature identifiers.

Example

signal.rms

dynamic.range

spectral.centroid

rhythm.tempo

harmony.key

Explanation must

- compare vectors
- determine largest feature contributions
- convert vector indices back to feature identifiers using MusicDNALayout

The explanation layer must never require MusicDNA objects.

---

# SimilarityResult

Immutable frozen dataclass.

Fields

track_a

track_b

metric

similarity_score

distance

confidence

per_category_scores

top_contributors

vector_dimension

schema_version

---

# Confidence

Initial implementation

confidence = 1.0

Future tasks will improve this.

---

# CLI

Add

musimuse compare

Arguments

--track-a

--track-b

--metric

Supported metrics

cosine

euclidean

manhattan

Example

musimuse compare \
    --track-a observer \
    --track-b seaside \
    --metric cosine

Example output

Similarity Summary

Metric

Cosine

Similarity

0.9431

Distance

0.0569

Confidence

1.000

Per Category

Signal      0.95

Spectral    0.91

Dynamic     0.88

Rhythm      0.98

Harmony     0.82

Top Contributors

signal.rms

dynamic.range

spectral.centroid

rhythm.tempo

---

# Logging

similarity.started

similarity.metric

similarity.completed

similarity.validation_failed

---

# Validation

Reject

- NaN
- Inf
- dimension mismatch
- schema mismatch
- empty vectors
- unsupported metric

Raise dedicated exceptions.

---

# Determinism

Comparing identical vectors

must always return

Similarity = 1.0

Distance = 0.0

Per-category similarity = 1.0

Top contributors must be deterministic.

Running compare() multiple times with identical inputs must always produce identical results.

---

# Forbidden

Do NOT implement

- nearest-neighbour search
- ANN
- FAISS
- HNSW
- KD-tree
- Ball-tree
- recommendation engine
- playlist generation
- embeddings
- machine learning
- database search
- vector indexing

Those belong to future tasks.

---

# Tests

Cover

- cosine similarity
- euclidean distance
- manhattan distance
- identical vectors
- different vectors
- orthogonal vectors
- dimension mismatch
- NaN
- Inf
- schema mismatch
- per-category similarity
- reverse layout mapping
- SimilarityExplanation
- deterministic ordering
- CLI compare

---

# Documentation

Update

02_ARCHITECTURE.md

Document

- SimilarityEngine
- SimilarityResult
- SimilarityExplanation
- MusicDNALayout bidirectional mapping
- per-category similarity
- supported metrics

---

# Definition of Done

✓ Cosine similarity implemented

✓ Euclidean distance implemented

✓ Manhattan distance implemented

✓ MusicDNALayout supports reverse lookup

✓ SimilarityEngine implemented

✓ SimilarityResult implemented

✓ SimilarityExplanation implemented

✓ Per-category similarity implemented

✓ CLI compare implemented

✓ Validation implemented

✓ Deterministic output verified

✓ Tests pass

✓ Ruff passes

✓ Black passes

✓ isort passes

---

## Important

The Similarity Engine is a pure mathematical layer.

It operates exclusively on MusicDNAVector objects.

MusicDNALayout is the only component responsible for translating between feature identifiers and vector indices.

The Similarity Engine has no knowledge of MusicDNA, repositories, databases, collections, nearest-neighbour search, recommendation systems or machine learning.

Future tasks will build library-wide similarity search, recommendation engines, clustering and embeddings on top of this component without modifying its public API.