[+] A3 P3 Q1-2
This commit is contained in:
@@ -19,7 +19,7 @@ This file is Copyright (c) 2022 Mario Badr, David Liu, and Isaac Waller.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
import csv
|
||||
from typing import Any
|
||||
from typing import Any, Literal
|
||||
|
||||
# Make sure you've installed the necessary Python libraries (see assignment handout
|
||||
# "Installing new libraries" section)
|
||||
@@ -143,7 +143,7 @@ class Graph:
|
||||
else:
|
||||
raise ValueError
|
||||
|
||||
def get_all_vertices(self, kind: str = '') -> set:
|
||||
def get_all_vertices(self, kind: Literal['', 'user', 'book'] = '') -> set:
|
||||
"""Return a set of all vertex items in this graph.
|
||||
|
||||
If kind != '', only return the items of the given vertex kind.
|
||||
|
||||
@@ -20,7 +20,7 @@ This file is Copyright (c) 2022 Mario Badr, David Liu, and Isaac Waller.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
import csv
|
||||
from typing import Any, Union
|
||||
from typing import Any, Union, Literal
|
||||
|
||||
from a3_part1 import Graph
|
||||
|
||||
@@ -175,7 +175,7 @@ class WeightedGraph(Graph):
|
||||
# Part 2, Q2
|
||||
############################################################################
|
||||
def get_similarity_score(self, item1: Any, item2: Any,
|
||||
score_type: str = 'unweighted') -> float:
|
||||
score_type: Literal['unweighted', 'strict'] = 'unweighted') -> float:
|
||||
"""Return the similarity score between the two given items in this graph.
|
||||
|
||||
score_type is one of 'unweighted' or 'strict', corresponding to the
|
||||
@@ -194,7 +194,7 @@ class WeightedGraph(Graph):
|
||||
return self._vertices[item1].similarity_score_strict(self._vertices[item2])
|
||||
|
||||
def recommend_books(self, book: str, limit: int,
|
||||
score_type: str = 'unweighted') -> list[str]:
|
||||
score_type: Literal['unweighted', 'strict'] = 'unweighted') -> list[str]:
|
||||
"""Return a list of up to <limit> recommended books based on similarity to the given book.
|
||||
|
||||
score_type is one of 'unweighted' or 'strict', corresponding to the
|
||||
|
||||
@@ -18,8 +18,9 @@ please consult our Course Syllabus.
|
||||
This file is Copyright (c) 2022 Mario Badr, David Liu, and Isaac Waller.
|
||||
"""
|
||||
import random
|
||||
from typing import Literal
|
||||
|
||||
from a3_part2_recommendations import WeightedGraph, load_weighted_review_graph
|
||||
from a3_part2_recommendations import WeightedGraph
|
||||
|
||||
|
||||
################################################################################
|
||||
@@ -27,7 +28,7 @@ from a3_part2_recommendations import WeightedGraph, load_weighted_review_graph
|
||||
################################################################################
|
||||
def create_book_graph(review_graph: WeightedGraph,
|
||||
threshold: float = 0.05,
|
||||
score_type: str = 'unweighted') -> WeightedGraph:
|
||||
score_type: Literal['unweighted', 'strict'] = 'unweighted') -> WeightedGraph:
|
||||
"""Return a book graph based on the given review_graph.
|
||||
|
||||
The score_type parameter plays the same role as in WeightedGraph.get_similarity_score.
|
||||
@@ -46,6 +47,28 @@ def create_book_graph(review_graph: WeightedGraph,
|
||||
Preconditions:
|
||||
- score_type in {'unweighted', 'strict'}
|
||||
"""
|
||||
# Add all books as vertices
|
||||
book_graph = WeightedGraph()
|
||||
book_names: set[str] = review_graph.get_all_vertices('book')
|
||||
for b in book_names:
|
||||
book_graph.add_vertex(b, 'book')
|
||||
|
||||
# Add all edges
|
||||
for b1 in book_names:
|
||||
for b2 in book_names:
|
||||
if b1 == b2:
|
||||
continue
|
||||
|
||||
# Calculate similarity score
|
||||
score = review_graph.get_similarity_score(b1, b2, score_type)
|
||||
if score <= threshold:
|
||||
continue
|
||||
|
||||
# Add edge
|
||||
book_graph.add_edge(b1, b2, score)
|
||||
|
||||
# Done
|
||||
return book_graph
|
||||
|
||||
|
||||
################################################################################
|
||||
@@ -60,7 +83,21 @@ def cross_cluster_weight(book_graph: WeightedGraph, cluster1: set, cluster2: set
|
||||
- cluster1 != set() and cluster2 != set()
|
||||
- cluster1.isdisjoint(cluster2)
|
||||
- Every item in cluster1 and cluster2 is a vertex in book_graph
|
||||
|
||||
>>> bg = WeightedGraph()
|
||||
>>> for b in range(4): \
|
||||
bg.add_vertex(f'B{b}', 'book')
|
||||
>>> bg.add_edge('B0', 'B1', .5)
|
||||
>>> bg.add_edge('B0', 'B2', .4)
|
||||
>>> bg.add_edge('B1', 'B2', .3)
|
||||
>>> bg.get_weight('B0', 'B1')
|
||||
0.5
|
||||
>>> cross_cluster_weight(bg, {'B0', 'B1'}, {'B2', 'B3'}) == (.4 + .3) / 4
|
||||
True
|
||||
"""
|
||||
numerator = sum(book_graph.get_weight(v1, v2) for v1 in cluster1 for v2 in cluster2)
|
||||
denominator = len(cluster1) * len(cluster2)
|
||||
return numerator / denominator
|
||||
|
||||
|
||||
################################################################################
|
||||
@@ -151,3 +188,16 @@ if __name__ == '__main__':
|
||||
'allowed-io': ['find_clusters_greedy', 'find_clusters_random'],
|
||||
'max-nested-blocks': 4
|
||||
})
|
||||
|
||||
# Q1 Test
|
||||
# review_graph = load_weighted_review_graph('data/reviews_full.csv', 'data/book_names.csv')
|
||||
# book_graph = create_book_graph(review_graph, 0.03)
|
||||
# from a3_visualization import visualize_graph
|
||||
# visualize_graph(book_graph)
|
||||
|
||||
# Q3 Test
|
||||
# review_graph = load_weighted_review_graph('data/reviews_full.csv', 'data/book_names.csv')
|
||||
# book_graph = create_book_graph(review_graph, threshold=0.01, score_type='strict')
|
||||
# clusters = find_clusters_random(book_graph, 15)
|
||||
# from a3_visualization import visualize_graph_clusters
|
||||
# visualize_graph_clusters(book_graph, clusters)
|
||||
|
||||
Reference in New Issue
Block a user