diff --git a/Submissions/002683914_Xiaoyang_Chen/Assignment4.ipynb b/Submissions/002683914_Xiaoyang_Chen/Assignment4.ipynb new file mode 100644 index 0000000..8d77211 --- /dev/null +++ b/Submissions/002683914_Xiaoyang_Chen/Assignment4.ipynb @@ -0,0 +1,631 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "83aa8a9e", + "metadata": {}, + "source": [ + "# INFO 6205 – Program Structure and Algorithms Worked Assignment 4 " + ] + }, + { + "cell_type": "markdown", + "id": "ed3c9c86", + "metadata": {}, + "source": [ + "Student Name:**Xiaoyang Chen** \n", + "Professor: **Nik Bear Brown**" + ] + }, + { + "cell_type": "markdown", + "id": "71703bd3", + "metadata": {}, + "source": [ + "## Question 1 \n", + "In a weighted directed graph G = (V, E, W), where V is the set of vertices, E is the set of directed edges, and W is the set of weights for the edges, define the Minimum Weight Path Cover problem. This problem seeks to find a set of disjoint paths such that every vertex belongs to exactly one path, and the total weight of these paths is as small as possible.\n", + "\n", + "Decision Problem Formulation:\n", + "Input: A weighted directed graph G=(V,E,W)\n", + "Output: If there exists a set of disjoint paths that cover all vertices and have the minimum total weight, output the total weight of these paths; otherwise, output \"No solution\".\n", + "\n", + "## Solutions: \n", + "\n", + "### A. (10 points) Is the Minimum Weight Path Cover problem in P? If so, prove it. \n", + "To determine if the Minimum Weight Path Cover problem is in P (Polynomial time), one needs to establish whether there exists an algorithm that can solve the problem in polynomial time. This would typically involve either demonstrating an existing polynomial-time algorithm or proving that the problem can be reduced to another problem that is already known to be in P.\n", + "\n", + "### B. (5 points) Suppose we require each path to have at most four vertices. We call this the 4-Path Cover problem. Is the 4-Path Cover problem in NP? If so, prove it.\n", + "For the 4-Path Cover problem to be in NP (Nondeterministic Polynomial time), it should be possible to verify the correctness of a given solution in polynomial time. One approach to prove this is to show that, given a set of paths, one can check in polynomial time if they are disjoint, cover all vertices, have at most four vertices each, and whether their total weight is minimal.\n", + " \n", + "### C. (10 points) Is the 4-Path Cover problem NP-complete? If so, prove it.\n", + "To prove that the 4-Path Cover problem is NP-complete, it must first be shown to be in NP (as per point B). Then, it must be proven that any problem in NP can be reduced to this problem in polynomial time. This typically involves selecting a known NP-complete problem and demonstrating a polynomial-time reduction to the 4-Path Cover problem.\n" + ] + }, + { + "cell_type": "markdown", + "id": "ebda60e8", + "metadata": {}, + "source": [ + "## Question 2 \n", + "The Directed k-Link Path Problem is defined as follows. We are given a directed graph G = (V, E) and k distinct nodes V1,V2,V3......Vk\n", + " in V. The problem is to decide whether there exists a path in G that links all k nodes in a sequence, i.e., a path that starts at any of these k nodes and visits each of the k nodes exactly once, in any order.\n", + " \n", + "### Decision Problem Formulation:\n", + "Input: A directed graph G=(V,E) and k distinct nodes V1,V2,V3......Vk in V. \n", + "Output: Yes, if there exists a path in G that links all k nodes in a sequence; otherwise, No. \n", + "\n", + "## Solutions:\n", + "\n", + "### NP Verification:\n", + "To prove that the Directed k-Link Path Problem is in NP, show that given a solution (i.e., a path that links all k nodes), it can be verified in polynomial time. This can be done by checking if the path is valid within G and touches each of the k nodes exactly once.\n", + "\n", + "### NP-completeness Proof:\n", + "First, establish that the problem is in NP (as shown above). \n", + "Then, to prove NP-completeness, reduce a known NP-complete problem to this one. A suitable candidate for reduction might be the Hamiltonian Path Problem, which is known to be NP-complete. \n", + "A possible reduction approach is to construct a graph for the Directed k-Link Path Problem from a given instance of the Hamiltonian Path Problem. The reduction should be done in such a way that a solution to the Hamiltonian Path Problem implies a solution to the Directed k-Link Path Problem, and vice versa. \n", + "\n", + "### Algorithm Implementation :\n", + "\n", + "A potential algorithm to solve this problem might involve searching for paths that touch all k nodes. \n", + "A depth-first search (DFS) algorithm could be modified to keep track of visited k nodes and terminate once all have been visited. \n", + "However, this approach could be exponential in time complexity, reflecting the NP-hard nature of the problem. \n", + "To optimize, pruning strategies and heuristics might be employed to avoid exploring obviously non-viable paths. \n", + "\n", + "### Pseudocode" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8efbbb57", + "metadata": {}, + "outputs": [], + "source": [ + "function isKLinkPathExists(G, k, nodes):\n", + " for each node in nodes:\n", + " if DFS(G, node, nodes, k, []):\n", + " return True\n", + " return False\n", + "\n", + "function DFS(G, current, nodes, k, visited):\n", + " if len(visited) == k:\n", + " return True\n", + " for each neighbor in G[current]:\n", + " if neighbor in nodes and neighbor not in visited:\n", + " if DFS(G, neighbor, nodes, k, visited + [neighbor]):\n", + " return True\n", + " return False" + ] + }, + { + "cell_type": "markdown", + "id": "282cf5f6", + "metadata": {}, + "source": [ + "### Python Code" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "46b4bb20", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "True\n" + ] + } + ], + "source": [ + "def is_k_link_path_exists(graph, k, nodes):\n", + " def dfs(current, visited):\n", + " if len(visited) == k:\n", + " return True\n", + " for neighbor in graph[current]:\n", + " if neighbor in nodes and neighbor not in visited:\n", + " if dfs(neighbor, visited + [neighbor]):\n", + " return True\n", + " return False\n", + "\n", + " for node in nodes:\n", + " if dfs(node, [node]):\n", + " return True\n", + " return False\n", + "\n", + "# Example Usage\n", + "graph = {\n", + " 'A': ['B', 'C'],\n", + " 'B': ['C', 'D'],\n", + " 'C': ['D'],\n", + " 'D': ['E'],\n", + " 'E': ['A']\n", + "}\n", + "\n", + "nodes = ['A', 'C', 'E']\n", + "k = 3\n", + "\n", + "print(is_k_link_path_exists(graph, k, nodes))\n" + ] + }, + { + "cell_type": "markdown", + "id": "8c296339", + "metadata": {}, + "source": [ + "This code works as follows:\n", + "\n", + "The is_k_link_path_exists function iterates over each of the k nodes and uses a depth-first search (starting from that node) to find a path that visits all k nodes. \n", + "\n", + "The dfs function searches for a path starting from the current node. If it reaches a point where the length of the visited list is k, it means all k nodes have been visited in a sequence, and it returns True. \n", + "\n", + "The graph is represented as a dictionary where each key is a node, and the corresponding value is a list of its neighbors. \n", + "\n", + "This algorithm can be inefficient for large graphs or large k, as it explores many potential paths before finding a suitable one or concluding that none exists. It's a brute-force approach and reflects the NP-hard nature of the problem. For large instances, more sophisticated methods or heuristics would be necessary to find solutions in a reasonable amount of time. " + ] + }, + { + "cell_type": "markdown", + "id": "0d8b06eb", + "metadata": {}, + "source": [ + "## Question 3 \n", + "You are organizing a game hack-a-thon and want to make sure there is at least one instructor who is skilled at each of the n skills required to build a game (e.g. programming, art, animation, modeling, artificial intelligence, analytics, etc.) You have received job applications from m potential instructors. For each of n skills, there is some subset of potential instructors qualified to teach it. The question is: For a given number k ≤ m, is is possible to hire at most k instructors that can teach all of the n skills. We’ll call this the Cheapest Teacher Set. Show that Cheapest Teacher Set is NP-complete\n", + "\n", + "### Problem Statement:\n", + "You are managing a software project that requires completing n different types of tasks, such as coding, testing, documentation, etc. Each task type has a specific number of units of work associated with it. You have a team of m developers, each skilled in various types of tasks. The question is: For a given number k ≤ m, can you assign tasks to at most k developers in such a way that all task types are covered and the total workload does not exceed the capacity of the selected developers? We'll call this the Efficient Workforce Allocation.\n", + "\n", + "### Input Format:\n", + "\n", + "An integer, n (1 ≤ n ≤ 20), representing the number of different task types. \n", + "An integer, m (1 ≤ m ≤ 20), representing the number of developers. \n", + "A list of n positive integers, where the i-th integer (1 ≤ i ≤ n) represents the units of work for the i-th task type. \n", + "A list of m developers, each described by: \n", + "A unique identifier, like a name or ID. \n", + "A list of task types the developer is skilled in. \n", + "The maximum workload capacity of the developer. \n", + "\n", + "### Output Format:\n", + "A binary decision: \"YES\" if it's possible to assign tasks to at most k developers in a way that ensures all task types are covered and the total workload does not exceed their capacities, or \"NO\" if it's not possible.\n", + "\n", + "## Solutions:\n", + "\n", + "### Modeling the Problem:\n", + "\n", + "Represent this problem as a bipartite graph where one set of nodes represents tasks, and the other set represents developers.\n", + "Edges between tasks and developers exist if a developer is skilled for that task. The weight of an edge can represent the workload of the task.\n", + "\n", + "### Task Allocation as Bipartite Graph Matching:\n", + "\n", + "We need to find a matching in this graph where all tasks are assigned to developers without overloading any developer.\n", + "This can be approached as a \"Maximum Bipartite Matching\" problem, but with the added constraint of workload capacities.\n", + "\n", + "### Handling Workload Capacities:\n", + "\n", + "Each developer node can be duplicated in proportion to their capacity. For instance, if a developer has twice the capacity of another, they would be represented as two nodes in the graph.\n", + "This modification allows us to use standard bipartite matching algorithms while respecting individual workload limits.\n", + "\n", + "### Algorithm Selection:\n", + "\n", + "A suitable algorithm for solving this problem is the \"Hungarian Algorithm\" or \"Ford-Fulkerson Algorithm\" for maximum flow, adapted to handle the modified graph with duplicated nodes for capacities.\n", + "\n", + "### Algorithm Implementation:\n", + "\n", + "Construct the bipartite graph based on the input data.\n", + "Duplicate developer nodes according to their capacities.\n", + "Apply the chosen algorithm to find an optimal matching.\n", + "If all tasks can be matched to developers without exceeding capacities, return \"YES\". Otherwise, return \"NO\".\n", + "\n", + "### Example Python Code Skeleton" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9748fed8", + "metadata": {}, + "outputs": [], + "source": [ + "def efficient_workforce_allocation(tasks, developers):\n", + " # Step 1: Construct the bipartite graph\n", + " graph = construct_graph(tasks, developers)\n", + "\n", + " # Step 2: Duplicate developer nodes based on capacities\n", + " modified_graph = duplicate_nodes_for_capacity(graph, developers)\n", + "\n", + " # Step 3: Apply a matching algorithm (e.g., Hungarian, Ford-Fulkerson)\n", + " matching = find_maximum_matching(modified_graph)\n", + "\n", + " # Step 4: Check if all tasks are assigned\n", + " return \"YES\" if all_tasks_assigned(matching, tasks) else \"NO\"\n", + "\n", + "# Functions: construct_graph, duplicate_nodes_for_capacity, find_maximum_matching, all_tasks_assigned\n", + "# These would be implemented according to the specifics of the chosen algorithm and data structure.\n" + ] + }, + { + "cell_type": "markdown", + "id": "dc4de270", + "metadata": {}, + "source": [ + "### Conclusion\n", + "\n", + "This detailed approach showcases how the problem can be transformed into a known computational problem (bipartite matching) and solved with established algorithms, taking into consideration the unique constraints of workload capacities. This model provides a clear path from problem statement to algorithmic solution, suitable for real-world project management scenarios.\n", + "\n", + "### Overall Complexity\n", + "1. Constructing the Graph\n", + "Time Complexity: O(n * m), where n is the number of tasks and m is the number of developers. This is because we need to check each task against each developer to determine if an edge (i.e., a potential assignment) can be made. \n", + "\n", + "Space Complexity: O(n + m + e), where e is the number of edges in the bipartite graph. The space needed depends on the number of tasks, developers, and potential assignments (edges) between them. \n", + "\n", + "2. Duplicating Nodes for Capacity \n", + "Time Complexity: O(m * C), where C is the maximum capacity among all developers. In the worst case, we duplicate each developer node C times. \n", + "\n", + "Space Complexity: O(m * C + e'). Here, e' is the number of edges in the modified graph. The space complexity increases due to the duplication of developer nodes. \n", + "\n", + "3. Finding the Maximum Matching \n", + "Algorithm Choice: The choice of algorithm for finding the maximum matching affects complexity. Let's consider the Ford-Fulkerson algorithm as an example.\n", + "Time Complexity (Ford-Fulkerson): O(E * F), where E is the number of edges in the modified graph, and F is the maximum flow, which in this context is the total number of units of work across all tasks. \n", + "\n", + "Space Complexity: O(n + m * C), as the algorithm operates on the modified graph. \n", + "\n", + "Overall Complexity \n", + "Total Time Complexity: The most time-consuming part is finding the maximum matching. So, the total time complexity is dominated by O(E * F). \n", + "Total Space Complexity: The most space-consuming part is the modified graph, leading to a total space complexity of O(m * C + e'). " + ] + }, + { + "cell_type": "markdown", + "id": "948bc0b8", + "metadata": {}, + "source": [ + "## Question 4\n", + "\n", + "You are coordinating a series of n workshops, each requiring specific equipment or materials. There are m different types of resources available, each with a unique set of characteristics. Each workshop needs a particular combination of resources to be successfully conducted. The challenge is to determine if it's possible, for a given number k ≤ m, to allocate the resources in such a way that all n workshops can be conducted with the available resources. This problem will be referred to as the \"Workshop Resource Allocation Problem.\"" + ] + }, + { + "cell_type": "markdown", + "id": "54664c25", + "metadata": {}, + "source": [ + "## Solutions:\n", + "Formulate this problem as a maximum flow problem by modeling it as a flow network:\n", + "\n", + "### A. Create a Flow Network Representing the Allocation Process:\n", + "\n", + "Construct a source node \"S\" and a sink node \"T.\"\n", + "Create a node for each of the n workshops.\n", + "Create a node for each of the m resources.\n", + "Connect edges from the source \"S\" to each resource node, with capacities representing the availability or quantity of each resource.\n", + "Connect edges from each resource node to the workshops they can support, indicating the possible allocation of resources to workshops.\n", + "Connect edges from each workshop node to the sink \"T,\" with capacities representing the resource requirements of each workshop.\n", + "\n", + "### B. Can All n Workshops be Conducted with k Resources?\n", + "\n", + "The feasibility of conducting all n workshops with at most k resources depends on the availability and compatibility of resources with the workshops' requirements.\n", + "Using a maximum flow algorithm (such as Ford-Fulkerson), determine if there exists a flow from \"S\" to \"T\" that satisfies the resource requirements of all workshops.\n", + "If the maximum flow value equals the sum of all workshop requirements, then it is possible to conduct all workshops. Otherwise, it is not feasible with the given resources.\n", + "\n", + "### Complexity Analysis:\n", + "\n", + "Time Complexity: The complexity largely depends on the maximum flow algorithm used. With Ford-Fulkerson implemented via Edmonds-Karp, it would be O(V * E^2), where V is the number of vertices (workshops + resources + 2) and E is the number of edges in the flow network. \n", + "\n", + "Space Complexity: The space complexity is O(V + E), needed to store the flow network.\n", + "\n", + "### Python Code Skeleton:" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "f8968fda", + "metadata": {}, + "outputs": [], + "source": [ + "def workshop_resource_allocation(workshops, resources, k):\n", + " # Step 1: Create the flow network\n", + " network = create_flow_network(workshops, resources)\n", + "\n", + " # Step 2: Apply a maximum flow algorithm\n", + " max_flow = ford_fulkerson(network)\n", + "\n", + " # Step 3: Check if the maximum flow equals the total workshop requirements\n", + " total_requirements = sum(workshop.requirement for workshop in workshops)\n", + " return \"YES\" if max_flow == total_requirements else \"NO\"\n", + "\n", + "# Functions: create_flow_network, ford_fulkerson\n", + "# These functions would be implemented based on the specifics of the problem and the chosen algorithm.\n" + ] + }, + { + "cell_type": "markdown", + "id": "0ef7c2be", + "metadata": {}, + "source": [ + "## Question 5\n", + "You are tasked with allocating facilities to cover a set of services in a city. There are n facilities, each having specific capabilities or services it can provide. You have received job applications from m potential facility operators. For each of the services, there is a subset of potential operators qualified to manage it. The question is: For a given number k ≤ m, is it possible to allocate at most k facilities that can cover all the services? We'll call this the Optimal Facility Allocation.\n", + "\n", + "## Solutions:\n", + "Each facility corresponds to a specific service, and potential operators are qualified to manage one or more services based on their capabilities. Our goal is to determine whether we can cover all the services efficiently, with at most k facility operators. \n", + "\n", + "The problem is in NP, as given a set of k facility operators, it can be verified in linear time whether each service is covered. \n", + "\n", + "To show the problem is NP-complete, we can reduce from the Set Cover problem. \n", + "\n", + "In an Set Cover example, given a set U of n elements and a collection of m subsets of U, we ask whether there are at most k of these sets whose union is equal to all of U. \n", + "\n", + "Construct an instance of the Optimal Facility Allocation as follows: For each element of U, create a specific service. For each of the m subsets, create a facility operator, and let this operator be qualified to manage the services that are elements of this subset. \n", + "\n", + "There are k facility operators that can cover all the services if and only if there are k subsets whose union is U. \n", + "\n", + "Clearly, the reduction takes polynomial time. Since the Set Cover is in NP-complete, the Optimal Facility Allocation is an NP-complete problem.\n" + ] + }, + { + "cell_type": "markdown", + "id": "d273cdd6", + "metadata": {}, + "source": [ + "## Question 6\n", + "The \"Subset Sum to K\" problem is the task of deciding whether a given set S of positive integers can have a subset S' whose elements sum up to a specific value K. For instance, given S = {3, 4, 5, 2} and K = 9, a valid solution to the problem is the subset S' = {4, 5}, as the sum of the numbers in S' equals 9.\n", + "\n", + "### Questions:\n", + "A. Is the \"Subset Sum to K\" problem in NP? Why or why not? \n", + "B. Is the \"Subset Sum to K\" problem NP-complete? If NP-complete, prove it. \n", + "\n", + "## Solutions:\n", + "\n", + "### A. Is the \"Subset Sum to K\" problem in NP? \n", + "\n", + "Yes, the \"Subset Sum to K\" problem is in NP (Nondeterministic Polynomial time). \n", + "Reason: Any solution to the \"Subset Sum to K\" problem (i.e., a subset S' of S) can be verified quickly (in polynomial time) to check if the sum of its elements equals K. This characteristic of quick verification is a defining trait of NP problems. \n", + "\n", + "### B. Is the \"Subset Sum to K\" problem NP-complete? \n", + "\n", + "Yes, the \"Subset Sum to K\" problem is NP-complete. \n", + "\n", + "Proof: The \"Subset Sum to K\" problem is a well-known NP-complete problem. The NP-completeness can be shown by reducing a known NP-complete problem, such as the \"Set Partition\" problem, to it.\n", + "Reduction from Set Partition to Subset Sum to K: Given an instance of the Set Partition problem with a set S, create an instance of the Subset Sum to K problem with the same set S and K being half of the sum of all elements in S. A solution to this Subset Sum to K problem would partition S into two subsets with equal sums, thus solving the Set Partition problem.\n", + "This reduction can be done in polynomial time, and a solution to the Subset Sum to K problem implies a solution to the Set Partition problem. Therefore, Subset Sum to K is at least as hard as Set Partition, an NP-complete problem, making Subset Sum to K also NP-complete.\n", + "\n", + "### Conclusion:\n", + "The \"Subset Sum to K\" problem is an interesting variant of the Set Partition problem, where instead of dividing a set into two subsets of equal sum, we are looking for a subset with a sum equal to a specific value. This problem is not only in NP but also NP-complete, reflecting its computational complexity and the challenges in finding efficient solutions for larger instances." + ] + }, + { + "cell_type": "markdown", + "id": "48513a7d", + "metadata": {}, + "source": [ + "## Question 7\n", + "You have recently received a special invite from Google for its latest mobile OS update, Google Lollipop. You have also been given a certain d number of invites, that you can send out to your network in google plus. Your friends who receive your invite can further send invites to any of their friends (i.e., your friend- of-friends) but their friends (your friend-of-friends) cannot send any further invites to anyone. You are faced with the following challenge: Given that your google plus network can be modelled into a graph (using some API), design an efficient algorithm that would select d people from your list of friends such that everybody in your network (friends and friend-of-friends) receive the updates. a. Show that the problem GOOGLE-L-INVITE is NP Complete. b. Would it be easier to simply conclude on the possibility (true/false) of finding such d friends rather than actually finding the list of those friends? (Hint: Visualize the problem graphically. Is it possible to reduce the problem into a known partitioning problem?)\n", + "\n", + "### Problem Statement:\n", + "You are in charge of a marketing campaign and need to select a group of influencers to maximize the reach of your product. Each influencer has a specific reach, quantified by the number of people they can influence directly and indirectly through their network. \n", + "You need to find the most effective group of influencers, within a budget constraint, to maximize the total reach. \n", + "\n", + "### Tasks:\n", + "a. Show that the problem of finding the most effective group of influencers is NP-complete. \n", + "b. Discuss the implications of determining the optimal group size versus identifying the actual influencers in the group. \n", + "\n", + "### Input:\n", + "\n", + "A graph representing the network of influencers and their connections. \n", + "Reach level assigned to each influencer. \n", + "An integer k representing the budget or size constraint for the initial group. \n", + "Output: \n", + "a. The most effective set of k influencers that maximizes the total reach. \n", + "b. The size of the optimal group for maximum reach. \n", + "\n", + "### Constraints:\n", + "\n", + "The number of influencers is at most 1000.\n", + "The number of connections between influencers is at most 5000.\n", + "The reach level for each influencer is a positive integer." + ] + }, + { + "cell_type": "markdown", + "id": "2195be5a", + "metadata": {}, + "source": [ + "## Solution:\n", + "\n", + "### A. NP-Completeness:\n", + "\n", + "In NP: Verifying a solution (a set of influencers) is in NP, as you can quickly calculate the total reach of the selected influencers and check if it meets the criteria. \n", + "NP-Complete: The problem is NP-complete as it can be reduced from the \"Set Cover\" problem, which is known to be NP-complete. Each influencer 'covers' certain people in their network, and the goal is to find the smallest group of influencers that cover the entire network (or maximize reach within a budget).\n", + "\n", + "### B. Optimal Group Size vs. Identifying Influencers:\n", + "\n", + "Determining the size of the optimal group is computationally simpler than identifying the actual influencers in the optimal set. The latter requires exploring various combinations of influencers, which is computationally expensive, especially for large networks.\n", + "\n", + "### Algorithm Design:\n", + "\n", + "Model the network as a graph.\n", + "Use a greedy algorithm to select influencers until the budget k is reached.\n", + "Prioritize influencers with higher reach.\n", + "\n", + "### Pseudocode:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "91a625ac", + "metadata": {}, + "outputs": [], + "source": [ + "function findMostEffectiveInfluencers(graph, k):\n", + " selected_influencers = []\n", + " while k > 0 and there are unselected influencers:\n", + " influencer = selectInfluencerWithHighestReach(graph)\n", + " selected_influencers.append(influencer)\n", + " k -= 1\n", + " updateGraph(graph, influencer)\n", + " return selected_influencers\n", + "\n", + "function selectInfluencerWithHighestReach(graph):\n", + " # Select the influencer with the highest reach\n", + " # ...\n", + "\n", + "function updateGraph(graph, influencer):\n", + " # Update the graph to reflect the selection of the influencer\n", + " # ...\n" + ] + }, + { + "cell_type": "markdown", + "id": "688d2f45", + "metadata": {}, + "source": [ + "### Python Code" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1f627b9c", + "metadata": {}, + "outputs": [], + "source": [ + "def find_most_effective_influencers(graph, k):\n", + " selected = []\n", + " while k > 0 and graph.has_unselected_influencers():\n", + " influencer = graph.select_highest_reach_influencer()\n", + " selected.append(influencer)\n", + " k -= 1\n", + " graph.update_after_selection(influencer)\n", + " return selected\n", + "\n", + "class InfluencerGraph:\n", + " def __init__(self, ...):\n", + " # Initialize the graph\n", + " ...\n", + "\n", + " def has_unselected_influencers(self):\n", + " # Check if there are any unselected influencers\n", + " ...\n", + "\n", + " def select_highest_reach_influencer(self):\n", + " # Logic to select the influencer with the highest reach\n", + " ...\n", + "\n", + " def update_after_selection(self, influencer):\n", + " # Logic to update the graph after an influencer is selected\n", + " ...\n", + "\n", + "# Example usage\n", + "graph = InfluencerGraph(...)\n", + "result = find_most_effective_influencers(graph, k)\n" + ] + }, + { + "cell_type": "markdown", + "id": "e9cea0bb", + "metadata": {}, + "source": [ + "Conclusion: \n", + "This problem is a variant of the influence maximization problem in network analysis, where the challenge is to select a subset of nodes (influencers) to achieve maximum spread or coverage. The solution involves a combination of graph theory and algorithmic optimization, particularly dealing with NP-complete problems. The presented approach, while not guaranteed to find the absolute optimal set due to the NP-completeness of the problem, aims to provide a practical and efficient solution within the given constraints." + ] + }, + { + "cell_type": "markdown", + "id": "60af67f0", + "metadata": {}, + "source": [ + "## Question 8\n", + "You're managing a large botanical garden with various plant species that require different types of fertilizers. You have Np palm trees, \n", + "No orchids, Nc cacti, and Nb bamboo plants. To care for them, you have four kinds of fertilizers: \n", + "Tm tons of mineral fertilizer, To tons of organic fertilizer, Tw tons of water-soluble fertilizer, and Th tons of humus fertilizer. Palm trees use only mineral and water-soluble fertilizers, orchids use only organic and humus fertilizers, cacti use only mineral and humus fertilizers, and bamboos will use organic, water-soluble, and humus fertilizers. Each plant species requires one ton of fertilizer to stay healthy for a season.\n", + "\n", + "Design an algorithm to determine whether you have enough fertilizer to care for all the plants for a season. Your algorithm should reduce this problem to a network flow problem and prove its correctness.\n", + "\n", + "### Algorithm:\n", + "\n", + "Construct a Graph G and Capacities c: \n", + "\n", + "Vertices: \n", + "Create vertices Vp,Vo,Vc, and Vb for the plants. \n", + "Create vertices Um,Uo,Uw, and Uh for the types of fertilizers. \n", + "Create a source s and sink t. \n", + "Edges: \n", + "Connect s to Um,Uo,Uw, and Uh with capacities Tm,To,Tw, and Th, respectively. \n", + "Connect Vp,Vo,Vc, and Vb to t with capacities Np,No,Nc, and Nb, respectively. \n", + "For each type of fertilizer, create an edge from that fertilizer's vertex to the vertex of each plant that uses it, with capacity 1. \n", + "Solve Max Flow on G and c. \n", + "\n", + "Return “Yes\" if and only if the size of the flow is Np+No+Nc+Nb. \n", + "\n", + "### Correctness:\n", + "\n", + "There is a way to care for the plants if and only if there is a flow of size N, where \n", + "\n", + "N=Np+No+Nc+Nb, in G.\n", + "Assign flow from s to each fertilizer vertex equal to the amount of that fertilizer being used.\n", + "Set flow from each fertilizer vertex to each plant vertex equal to the amount of that fertilizer being consumed by the plant in question.\n", + "The total flow into t must be N for all plants to be cared for.\n", + "\n", + "### Pseudocode:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c1216f01", + "metadata": {}, + "outputs": [], + "source": [ + "function careForPlants(graph, n_p, n_o, n_c, n_b, t_m, t_o, t_w, t_h):\n", + " create vertices and edges as described\n", + " max_flow = solveMaxFlow(graph)\n", + " return max_flow == (n_p + n_o + n_c + n_b)\n", + "\n", + "function solveMaxFlow(graph):\n", + " # Implement a max flow algorithm like Ford-Fulkerson\n", + " # ...\n" + ] + }, + { + "cell_type": "markdown", + "id": "dd064f8b", + "metadata": {}, + "source": [ + "### Conclusion: \n", + "This problem, similar to the Zoo Tycoon problem, involves mapping a real-world resource allocation issue into a network flow problem. The correctness of the solution hinges on the fundamental principles of network flow, particularly the max-flow min-cut theorem, ensuring that each plant receives the required amount of fertilizer. The provided solution is a straightforward application of the max flow algorithm to a creatively modeled problem scenario." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "780d6101", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.13" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/Submissions/002683914_Xiaoyang_Chen/Xiaoyang_Chen_002683914.md b/Submissions/002683914_Xiaoyang_Chen/Xiaoyang_Chen_002683914.md index 168c44c..8de9549 100644 --- a/Submissions/002683914_Xiaoyang_Chen/Xiaoyang_Chen_002683914.md +++ b/Submissions/002683914_Xiaoyang_Chen/Xiaoyang_Chen_002683914.md @@ -8,4 +8,7 @@ All questions relate to topics we covered from the first assignment to last Wedn 10/22/2023 Assiggnment 3 This assignment is mainly designed to focus on the knowledge points in worked assignment 3. Each question in the homework is given a detailed answer and idea analysis. Most of the answers include code or pseudo-code to better explain its principles. -The Reflections, References, and License involved in this assignment are included in the file Assignment3.ipynb \ No newline at end of file +The Reflections, References, and License involved in this assignment are included in the file Assignment3.ipynb + +11/18/2023 Assiggnment 4 +Today, we explored several challenging computational problems, focusing on translating real-world scenarios into network flow or NP-complete problems. Starting from a Zoo Tycoon-inspired animal feeding challenge, we designed a similar problem for a botanical garden's fertilizer allocation, applying network flow algorithms for solutions. We also delved into problems akin to Set Partition and Subset Sum, highlighting their categorization as NP-complete and the need for efficient verification of potential solutions. These exercises deepened our understanding of network flows and NP-completeness, demonstrating the translation of practical issues into algorithmically solvable forms. \ No newline at end of file