""" Reality DNA Unique fingerprint for each place Enables global similarity search """ from typing import Dict, List, Optional, Tuple from dataclasses import dataclass import json @dataclass class RealityDNA: """DNA fingerprint of a place""" location_id: str location_name: str coordinates: Dict[str, float] # Core dimensions walkability: float tourism: float retail: float family: float noise: float history: float safety: float greenery: float connectivity: float affordability: float # Derived dna_vector: List[float] dna_hash: str def to_dict(self) -> Dict: return { "location_id": self.location_id, "location_name": self.location_name, "coordinates": self.coordinates, "dna": { "walkability": round(self.walkability, 1), "tourism": round(self.tourism, 1), "retail": round(self.retail, 1), "family": round(self.family, 1), "noise": round(self.noise, 1), "history": round(self.history, 1), "safety": round(self.safety, 1), "greenery": round(self.greenery, 1), "connectivity": round(self.connectivity, 1), "affordability": round(self.affordability, 1) }, "dna_vector": [round(v, 2) for v in self.dna_vector], "dna_hash": self.dna_hash } class RealityDNABuilder: """Builds Reality DNA from signals""" def build(self, location_id: str, location_name: str, signals: Dict[str, float]) -> RealityDNA: """Build DNA from signal values""" # Extract core dimensions walkability = signals.get("walkability", 50) tourism = signals.get("tourism", 50) retail = signals.get("retail_density", 50) family = signals.get("family_friendly", 50) noise = signals.get("noise_level", 50) history = signals.get("historical_value", 50) safety = signals.get("safety_index", 50) greenery = signals.get("greenery", 50) connectivity = signals.get("mobile_connectivity", 50) affordability = 100 - signals.get("rent_burden", 50) # Invert # Create vector vector = [ walkability, tourism, retail, family, noise, history, safety, greenery, connectivity, affordability ] # Create hash dna_hash = self._hash_vector(vector) return RealityDNA( location_id=location_id, location_name=location_name, coordinates=signals.get("coordinates", {"lat": 0, "lng": 0}), walkability=walkability, tourism=tourism, retail=retail, family=family, noise=noise, history=history, safety=safety, greenery=greenery, connectivity=connectivity, affordability=affordability, dna_vector=vector, dna_hash=dna_hash ) def _hash_vector(self, vector: List[float]) -> str: """Create hash from DNA vector""" # Quantize to 10 levels quantized = [int(v / 10) for v in vector] return "".join(str(min(q, 9)) for q in quantized) class GlobalSimilaritySearch: """Find similar places globally""" def __init__(self): self.dna_database: Dict[str, RealityDNA] = {} def add_place(self, dna: RealityDNA): """Add a place to the database""" self.dna_database[dna.location_id] = dna def find_similar( self, query_dna: RealityDNA, top_k: int = 5, exclude_self: bool = True ) -> List[Dict]: """ Find places similar to query Returns: List of similar places with similarity scores """ similarities = [] for location_id, candidate in self.dna_database.items(): if exclude_self and location_id == query_dna.location_id: continue # Calculate similarity similarity = self._calculate_similarity(query_dna.dna_vector, candidate.dna_vector) similarities.append({ "location_id": candidate.location_id, "location_name": candidate.location_name, "coordinates": candidate.coordinates, "similarity": round(similarity, 3), "dna": candidate.to_dict()["dna"] }) # Sort by similarity similarities.sort(key=lambda x: x["similarity"], reverse=True) return similarities[:top_k] def find_by_dna_pattern( self, pattern: Dict[str, float], top_k: int = 5 ) -> List[Dict]: """ Find places matching a DNA pattern Example: {"walkability": 90, "tourism": 80, "history": 95} → Finds places like Gamla Stan """ # Create query vector from pattern query_vector = [ pattern.get("walkability", 50), pattern.get("tourism", 50), pattern.get("retail", 50), pattern.get("family", 50), pattern.get("noise", 50), pattern.get("history", 50), pattern.get("safety", 50), pattern.get("greenery", 50), pattern.get("connectivity", 50), pattern.get("affordability", 50) ] similarities = [] for location_id, candidate in self.dna_database.items(): similarity = self._calculate_similarity(query_vector, candidate.dna_vector) similarities.append({ "location_id": candidate.location_id, "location_name": candidate.location_name, "coordinates": candidate.coordinates, "similarity": round(similarity, 3), "dna": candidate.to_dict()["dna"] }) similarities.sort(key=lambda x: x["similarity"], reverse=True) return similarities[:top_k] def find_contrasts( self, query_dna: RealityDNA, top_k: int = 3 ) -> List[Dict]: """Find places that are opposite to query""" similarities = [] for location_id, candidate in self.dna_database.items(): if location_id == query_dna.location_id: continue similarity = self._calculate_similarity(query_dna.dna_vector, candidate.dna_vector) similarities.append({ "location_id": candidate.location_id, "location_name": candidate.location_name, "coordinates": candidate.coordinates, "similarity": round(similarity, 3), "dna": candidate.to_dict()["dna"] }) # Sort ascending (least similar = most contrast) similarities.sort(key=lambda x: x["similarity"]) return similarities[:top_k] def _calculate_similarity(self, vector_a: List[float], vector_b: List[float]) -> float: """Calculate cosine similarity between two DNA vectors""" if len(vector_a) != len(vector_b): return 0.0 # Cosine similarity dot_product = sum(a * b for a, b in zip(vector_a, vector_b)) magnitude_a = sum(a * a for a in vector_a) ** 0.5 magnitude_b = sum(b * b for b in vector_b) ** 0.5 if magnitude_a == 0 or magnitude_b == 0: return 0.0 return dot_product / (magnitude_a * magnitude_b) def get_stats(self) -> Dict: """Get database statistics""" return { "total_places": len(self.dna_database), "coverage": self._calculate_coverage() } def _calculate_coverage(self) -> Dict: """Calculate geographic coverage""" if not self.dna_database: return {} lats = [d.coordinates["lat"] for d in self.dna_database.values()] lngs = [d.coordinates["lng"] for d in self.dna_database.values()] return { "lat_range": [min(lats), max(lats)], "lng_range": [min(lngs), max(lngs)], "center": { "lat": sum(lats) / len(lats), "lng": sum(lngs) / len(lngs) } } # Example usage def example_reality_dna(): """Example: Build DNA and search globally""" builder = RealityDNABuilder() search = GlobalSimilaritySearch() # Build DNA for Stockholm Gamla Stan gamla_stan_signals = { "walkability": 96, "tourism": 98, "retail_density": 88, "family_friendly": 51, "noise_level": 74, "historical_value": 100, "safety_index": 81, "greenery": 20, "mobile_connectivity": 85, "rent_burden": 80, "coordinates": {"lat": 59.325, "lng": 18.07} } gamla_stan = builder.build("SE-001", "Stockholm Gamla Stan", gamla_stan_signals) search.add_place(gamla_stan) print("=== Reality DNA: Gamla Stan ===") print(f"Hash: {gamla_stan.dna_hash}") print(f"Vector: {gamla_stan.dna_vector}") # Add more places places = [ ("DK-001", "Copenhagen Nyhavn", { "walkability": 90, "tourism": 95, "retail_density": 85, "family_friendly": 60, "noise_level": 70, "historical_value": 90, "safety_index": 85, "greenery": 30, "mobile_connectivity": 90, "rent_burden": 75, "coordinates": {"lat": 55.68, "lng": 12.59} }), ("DE-001", "Berlin Mitte", { "walkability": 85, "tourism": 80, "retail_density": 90, "family_friendly": 65, "noise_level": 75, "historical_value": 75, "safety_index": 75, "greenery": 40, "mobile_connectivity": 88, "rent_burden": 70, "coordinates": {"lat": 52.52, "lng": 13.405} }), ("JP-001", "Tokyo Shibuya", { "walkability": 95, "tourism": 90, "retail_density": 95, "family_friendly": 55, "noise_level": 85, "historical_value": 40, "safety_index": 90, "greenery": 25, "mobile_connectivity": 95, "rent_burden": 85, "coordinates": {"lat": 35.66, "lng": 139.7} }), ("US-001", "Manhattan SoHo", { "walkability": 92, "tourism": 85, "retail_density": 95, "family_friendly": 45, "noise_level": 80, "historical_value": 70, "safety_index": 70, "greenery": 20, "mobile_connectivity": 90, "rent_burden": 90, "coordinates": {"lat": 40.72, "lng": -74.0} }) ] for loc_id, name, signals in places: dna = builder.build(loc_id, name, signals) search.add_place(dna) # Find similar to Gamla Stan print("\n=== Places Similar to Gamla Stan ===") similar = search.find_similar(gamla_stan, top_k=3) for place in similar: print(f" {place['location_name']}: {place['similarity']:.3f}") # Find by pattern print("\n=== Places with High History + Tourism ===") pattern_places = search.find_by_dna_pattern({ "history": 90, "tourism": 90, "walkability": 80 }) for place in pattern_places: print(f" {place['location_name']}: {place['similarity']:.3f}") # Find contrasts print("\n=== Places Most Different from Gamla Stan ===") contrasts = search.find_contrasts(gamla_stan) for place in contrasts: print(f" {place['location_name']}: {place['similarity']:.3f}") return search if __name__ == '__main__': example_reality_dna()