import numpy as np import pandas as pd class KnowledgeBasedRecommender: def __init__(self, products_df): self.products = products_df.copy() def constraint_based(self, constraints, n_recommendations=10): filtered = self.products.copy() if "budget_max" in constraints: filtered = filtered[filtered["price"] <= constraints["budget_max"]] if "budget_min" in constraints: filtered = filtered[filtered["price"] >= constraints["budget_min"]] if "category" in constraints and constraints["category"]: filtered = filtered[filtered["category"].isin(constraints["category"])] brand_match = None if "brand" in constraints and constraints["brand"]: brand_match = filtered[filtered["brand"].isin(constraints["brand"])] if brand_match is not None and not brand_match.empty: filtered = brand_match if "min_rating" in constraints: filtered = filtered[filtered["avg_rating"] >= constraints["min_rating"]] if "subcategory" in constraints and constraints["subcategory"]: sub_match = filtered[filtered["subcategory"].isin(constraints["subcategory"])] if not sub_match.empty: filtered = sub_match filtered = filtered.sort_values("avg_rating", ascending=False) results = [(int(row["product_id"]), float(row["avg_rating"])) for _, row in filtered.head(n_recommendations).iterrows()] return results def rule_based(self, context, n_recommendations=10): rules = { "laptop": {"category": "Electronics", "subcategory": "Laptops"}, "smartphone": {"category": "Electronics", "subcategory": "Smartphones"}, "book": {"category": "Books"}, "camera": {"category": "Electronics", "subcategory": "Cameras"}, "headphone": {"category": "Electronics", "subcategory": "Headphones"}, } accessoires_map = { "Laptops": ["Laptop Bag", "Mouse", "Keyboard", "Cooling Pad"], "Smartphones": ["Phone Case", "Screen Protector", "Charger", "Power Bank"], "Cameras": ["Camera Bag", "Tripod", "Memory Card", "Lens Kit"], "Headphones": ["Headphone Stand", "Cable", "Carrying Case", "Ear Pads"], } interacted_category = context.get("interacted_category", "") scores = [] for _, product in self.products.iterrows(): score = 0 if interacted_category and product["category"] == "Electronics": if product["subcategory"] in accessoires_map.get(interacted_category, []): score += 50 if context.get("preferred_categories") and product["category"] in context["preferred_categories"]: score += 20 if context.get("budget_min", 0) <= product["price"] <= context.get("budget_max", 999999): score += 15 if context.get("favorite_brands") and product["brand"] in context["favorite_brands"]: score += 10 scores.append((int(product["product_id"]), score)) scores.sort(key=lambda x: x[1], reverse=True) return scores[:n_recommendations] def utility_based(self, preferences, weights=None, n_recommendations=10): if weights is None: weights = {"price": 0.2, "category": 0.3, "brand": 0.2, "rating": 0.3} price_min = preferences.get("budget_min", 0) price_max = preferences.get("budget_max", 999999) pref_cats = preferences.get("preferred_categories", set()) fav_brands = preferences.get("favorite_brands", set()) max_price = self.products["price"].max() min_price = self.products["price"].min() max_rating = self.products["avg_rating"].max() scores = [] for _, product in self.products.iterrows(): u = 0.0 if price_max > price_min: price_score = 1.0 - abs(product["price"] - (price_min + price_max) / 2) / ((price_max - price_min) / 2) price_score = max(0, min(1, price_score)) else: price_score = 1.0 if price_min <= product["price"] <= price_max else 0.0 u += weights["price"] * price_score cat_score = 1.0 if product["category"] in pref_cats else 0.0 u += weights["category"] * cat_score brand_score = 1.0 if product["brand"] in fav_brands else 0.0 u += weights["brand"] * brand_score rating_score = product["avg_rating"] / max_rating if max_rating > 0 else 0 u += weights["rating"] * rating_score scores.append((int(product["product_id"]), round(u, 4))) scores.sort(key=lambda x: x[1], reverse=True) return scores[:n_recommendations] def recommend(self, method, constraints=None, context=None, preferences=None, n_recommendations=10): if method == "constraint": return self.constraint_based(constraints or {}, n_recommendations) elif method == "rule": return self.rule_based(context or {}, n_recommendations) elif method == "utility": return self.utility_based(preferences or {}, n_recommendations=n_recommendations) else: raise ValueError(f"Unknown method: {method}")