Solingen

lab1.py

Apr 9th, 2026
39
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.87 KB | None | 0 0
  1. import math
  2.  
  3. # ============================================================
  4. # Матрица предпочтений (строки = товары, столбцы = пользователи)
  5. # ============================================================
  6. products = ['P1', 'P2', 'P3', 'P4', 'P5', 'P6']
  7. users    = ['U1', 'U2', 'U3', 'U4', 'U5']
  8.  
  9. # ratings[i][j] — оценка пользователя users[j] для товара products[i]
  10. ratings = [
  11.     #   U1   U2   U3   U4   U5
  12.     [   5,   4,   5,   3,   5 ],  # P1
  13.     [   5,   5,   5,   3,   5 ],  # P2
  14.     [   5,   4,   4,   2,   5 ],  # P3
  15.     [   5,   3,   5,   0,   3 ],  # P4
  16.     [   5,   0,   5,   0,   0 ],  # P5
  17.     [   4,   5,   5,   3,   1 ],  # P6
  18. ]
  19.  
  20. # ============================================================
  21. # Режим демонстрации
  22. # ============================================================
  23. DEMO = False  # Установите False для краткого вывода
  24.  
  25. # ============================================================
  26. # Вспомогательные функции (без сторонних библиотек)
  27. # ============================================================
  28.  
  29. def dot_product(a, b):
  30.     """Скалярное произведение двух векторов."""
  31.     return sum(x * y for x, y in zip(a, b))
  32.  
  33. def norm(v):
  34.     """Евклидова норма вектора."""
  35.     return math.sqrt(sum(x ** 2 for x in v))
  36.  
  37. def cosine_similarity(a, b):
  38.     """
  39.    Косинусное подобие двух векторов:
  40.        cos(A, B) = (A · B) / (|A| * |B|)
  41.    Возвращает 0, если один из векторов нулевой.
  42.    """
  43.     n_a = norm(a)
  44.     n_b = norm(b)
  45.     if n_a == 0 or n_b == 0:
  46.         return 0.0
  47.     return dot_product(a, b) / (n_a * n_b)
  48.  
  49. def build_similarity_matrix(vectors, labels, entity_name, demo=False):
  50.     """
  51.    Строит симметричную матрицу косинусного подобия.
  52.    vectors — список векторов (списков чисел)
  53.    labels  — названия объектов
  54.    """
  55.     n = len(vectors)
  56.     sim = [[0.0] * n for _ in range(n)]
  57.  
  58.     if demo:
  59.         print(f"\n{'='*60}")
  60.         print(f"  Вычисление косинусного подобия: {entity_name}")
  61.         print(f"{'='*60}")
  62.  
  63.     for i in range(n):
  64.         for j in range(i + 1, n):
  65.             a, b = vectors[i], vectors[j]
  66.             dp   = dot_product(a, b)
  67.             na   = norm(a)
  68.             nb   = norm(b)
  69.             cos  = dp / (na * nb) if (na != 0 and nb != 0) else 0.0
  70.             sim[i][j] = cos
  71.             sim[j][i] = cos
  72.  
  73.             if demo:
  74.                 print(f"\n  {labels[i]} vs {labels[j]}")
  75.                 print(f"    Вектор {labels[i]}: {a}")
  76.                 print(f"    Вектор {labels[j]}: {b}")
  77.                 print(f"    Скалярное произведение ({labels[i]}·{labels[j]}): "
  78.                       f"{' + '.join(f'{x}×{y}' for x, y in zip(a, b))} = {dp}")
  79.                 print(f"    |{labels[i]}| = sqrt({' + '.join(str(x**2) for x in a)}) = {na:.6f}")
  80.                 print(f"    |{labels[j]}| = sqrt({' + '.join(str(x**2) for x in b)}) = {nb:.6f}")
  81.                 print(f"    cos({labels[i]}, {labels[j]}) = {dp} / ({na:.4f} × {nb:.4f}) = {cos:.6f}")
  82.  
  83.     return sim
  84.  
  85. def print_matrix(sim, labels, title):
  86.     """Вывод матрицы подобия."""
  87.     n = len(labels)
  88.     col_w = 10
  89.     label_w = 4
  90.  
  91.     print(f"\n  {title}")
  92.     # Заголовок
  93.     header = " " * label_w + "".join(f"{lbl:>{col_w}}" for lbl in labels)
  94.     print("  " + header)
  95.     print("  " + "-" * len(header))
  96.  
  97.     for i, lbl in enumerate(labels):
  98.         row = f"{lbl:<{label_w}}"
  99.         for j in range(n):
  100.             if i == j:
  101.                 row += f"{'1.000000':>{col_w}}"
  102.             else:
  103.                 row += f"{sim[i][j]:>{col_w}.6f}"
  104.         print("  " + row)
  105.  
  106. def find_closest_pair(sim, labels):
  107.     """
  108.    Возвращает пару с наибольшим косинусным подобием
  109.    (исключая диагональ i == j).
  110.    """
  111.     n = len(labels)
  112.     best_val = -1.0
  113.     best_pair = (None, None)
  114.     for i in range(n):
  115.         for j in range(i + 1, n):
  116.             if sim[i][j] > best_val:
  117.                 best_val = sim[i][j]
  118.                 best_pair = (labels[i], labels[j])
  119.     return best_pair, best_val
  120.  
  121. # ============================================================
  122. # 1. Векторы пользователей (столбцы матрицы оценок)
  123. # ============================================================
  124. user_vectors = []
  125. for j, u in enumerate(users):
  126.     vec = [ratings[i][j] for i in range(len(products))]
  127.     user_vectors.append(vec)
  128.  
  129. # ============================================================
  130. # 2. Векторы товаров (строки матрицы оценок)
  131. # ============================================================
  132. item_vectors = [list(row) for row in ratings]
  133.  
  134. # ============================================================
  135. # 3. Вычисление матриц подобия
  136. # ============================================================
  137. if DEMO:
  138.     print("\n" + "=" * 60)
  139.     print("  МАТРИЦА ПРЕДПОЧТЕНИЙ")
  140.     print("=" * 60)
  141.     col_w = 5
  142.     lbl_w = 4
  143.     header = " " * lbl_w + "".join(f"{u:>{col_w}}" for u in users)
  144.     print("  " + header)
  145.     print("  " + "-" * len(header))
  146.     for i, p in enumerate(products):
  147.         row = f"{p:<{lbl_w}}" + "".join(f"{ratings[i][j]:>{col_w}}" for j in range(len(users)))
  148.         print("  " + row)
  149.     print()
  150.  
  151. user_sim = build_similarity_matrix(user_vectors, users, "ПОЛЬЗОВАТЕЛИ", demo=DEMO)
  152. item_sim = build_similarity_matrix(item_vectors, products, "ТОВАРЫ", demo=DEMO)
  153.  
  154. # ============================================================
  155. # 4. Вывод итоговых матриц
  156. # ============================================================
  157. print("\n\n" + "=" * 60)
  158. print("  ИТОГОВЫЕ РЕЗУЛЬТАТЫ")
  159. print("=" * 60)
  160.  
  161. print_matrix(user_sim, users, "Матрица косинусного подобия ПОЛЬЗОВАТЕЛЕЙ")
  162. print_matrix(item_sim, products, "Матрица косинусного подобия ТОВАРОВ")
  163.  
  164. # ============================================================
  165. # 5. Поиск двух самых близких пар
  166. # ============================================================
  167. (u1, u2), u_score = find_closest_pair(user_sim, users)
  168. (p1, p2), p_score = find_closest_pair(item_sim, products)
  169.  
  170. print(f"\n  Два самых близких пользователя: {u1} и {u2}  "
  171.       f"(cos = {u_score:.6f})")
  172. print(f"  Два самых близких товара:        {p1} и {p2}  "
  173.       f"(cos = {p_score:.6f})")
  174. print()
Advertisement
Add Comment
Please, Sign In to add comment