From 13ed587ceb14ba9ad4fefc43b14c939b62e387b1 Mon Sep 17 00:00:00 2001 From: mal0420 Date: Thu, 28 Apr 2022 21:09:37 -0500 Subject: [PATCH] Knotted should work now. I really was over-complicating it. I have commented the code and removed unused includes from the file. --- Project-2-input-example-1.txt | 20 ++++++ inc/graph.hpp | 12 ++-- src/knotted.cpp | 118 +++++++--------------------------- src/main.cpp | 4 +- 4 files changed, 53 insertions(+), 101 deletions(-) create mode 100644 Project-2-input-example-1.txt diff --git a/Project-2-input-example-1.txt b/Project-2-input-example-1.txt new file mode 100644 index 0000000..3a027c2 --- /dev/null +++ b/Project-2-input-example-1.txt @@ -0,0 +1,20 @@ +% A line starting with a % is a comment, and blank lines are skipped + +% First list the number of processes and resources using the keywords num_processes and num_resources. +%The value which corresponds to each keyword must be an integer. +%The keyword and its corresponding value must be separated by an equal sign (=) as demonstrated below: +num_processes=3 +num_resources=3 + +% Next, list the number of units of each resource in a single row, separated by commas (,) +2,1,1 + +% Then list the adjacency matrix. All processes will be listed first, followed by all of the resources. +% The order of resources in this list must be the same as the ordering of resources in the list above which specified the numer of units of each resource. +% Each row is listed on a separate line. Columns within a row are separated by a comma (,) +1,0,0,0,1,0 +0,1,0,1,0,1 +0,0,1,0,0,0 +1,0,1,1,0,0 +0,1,0,0,1,0 +0,0,1,0,0,1 \ No newline at end of file diff --git a/inc/graph.hpp b/inc/graph.hpp index 48b97f8..98be1a1 100644 --- a/inc/graph.hpp +++ b/inc/graph.hpp @@ -2,8 +2,9 @@ #ifndef PROJECT2_INC_GRAPH_HPP #define PROJECT2_INC_GRAPH_HPP -#include // string -#include // vector, vector +#include // set.find() +#include // string -- not used? +#include // vector, vector typedef std::vector> matrix; @@ -26,11 +27,14 @@ class graph { // is the graph... bool reducible (); // ? bool knotted (); // ? + // miscellaneous functions: // print the graph void print (); - + bool DFS( int node, std::set&visited, int parent ); + bool detectKnot(); + private: int num_processes = 0; int num_resources = 0; @@ -38,4 +42,4 @@ class graph { matrix m; // Tell me, Mr. Anderson, what good is a phone call if you are unable to speak? }; -#endif // PROJECT2_INC_GRAPH_HPP \ No newline at end of file +#endif // PROJECT2_INC_GRAPH_HPP diff --git a/src/knotted.cpp b/src/knotted.cpp index 8d3c41d..010549f 100644 --- a/src/knotted.cpp +++ b/src/knotted.cpp @@ -5,91 +5,35 @@ +--------------------------+--------------------------+ */ #include -#include -#include +#include // why set? because it supports find and it makes it easier. #include "graph.hpp" - -// goal is to create an group of objects that point to each other the same way the graph does and then detect loops -/* -enum class resourcetype { P, R }; - -struct PR { - int value; - resourcetype type; // {P,R} - resourcenum index; - vector in; - vector out; - bool visited; -}; - -void insertPR( struct PR** head,) { - struct PR* new_node = new PR; // neclare a new resource - new_node->value = new_data; - new_node->in.push_back(); - new_node->out.push_back(); - new_node->visited = false; +// depth-first-search is needed to detect the knot in the graph +bool graph::DFS ( int node, std::set&visited, int parent ) { + visited.insert(node); // once we come across this node, mark it as visited in the set + // note: node in this function is called using the iterator from the calling function. + for ( int ii = 0; ii < (num_processes+num_resources); ii++ ) { // for every process and resource... + if ( m[node][ii] ) { // m is the matrix part of graph class; if the valu + if ( ii == parent ) continue; // if index is parent, skip + if ( visited.find(ii) != visited.end() ) return true; // case index is visited, already visited + if ( DFS( ii, visited, node ) ) return true; // if search results is true + }//\if + }//\for + return false; } -void checkKnots () { - - // - // convert graph to a list where each item is a resource and has a list of connected resources - // ex: 0 (P1) : 0 (P1), 4 (R2) - // 1 (P2) : 1 (P2), 3 (R1), 5 (R3) - // - -}*/ - - -/* convert adjaceny matrix to adjaceny list */ -std::vector> convert(std::vector> x) { - std::vector> adjacencyList(x.size()); - for ( int ii = 0; ii < x.size(); ii++ ) - for ( int jj = 0; jj < x[ii].size(); jj++ ) - if (x[ii][jj] == 1) - adjacencyList[ii].push_back(jj); - return adjacencyList; +// this runs a DFS search on an undirected graph to detect a knot +bool graph::detectKnot() { + std::set visited; // define a set to keep track of visited nodes; a cycle will revisit visited nodes + for ( int ii = 0; ii < (num_processes+num_resources); ii++ ) { // for every process and resource... + if ( visited.find(ii) != visited.end() ) continue; // if this node is already found in visited, skip + if ( DFS(ii,visited,-1) ) return true; // start DFS with -1 for parent node, then it continues recursively + continue; // if neither above is true, continue searching until DFS is complete + }//\for + return false; // if no knot is found, return false } - - -/* linked list data structure */ -struct Vertex { - int data; // contents of node - struct Vertex* next; // point to next node - struct Vertex* prev; // point to prev node - bool visited; // flag used to signal visited -}; - -void pushLL(struct Vertex** list_head, int new_data) { - struct Vertex* new_node = new Vertex; // declare a new vertex - new_node->data = new_data; // populate the data for the new node - new_node->next = (*list_head); // link back to the old list from the new node - new_node->prev = (*list_head); // link back to the old list from the new node - new_node->visited = false; - (*list_head) = new_node; // point list head to the new node -} - -bool checkKnot(struct Vertex* v) { - - //vector> a; - //vector> AdjacencyList = convert(m); - - std::vector visited; // set to store the visited nodes - while ( v != NULL ) { // loop over the nodes in the linked list if the linked list is not empty - /* detect if node has been visited; if has, then there is a knot (and a loop) */ - if ( v->visited ) // find if this node is visited - return true; // immediate return - /* if node not visited, visit it and then continue */ - v->visited = true; // mark node as visited - v = v->next; // increment linked list position - } - return false; -} - - /* knotted: Perform the knot detection algorithm on the adjacency matrix to detect deadlocks @params: @@ -100,21 +44,5 @@ bool checkKnot(struct Vertex* v) { false if graph is not knotted (no deadlock) */ bool graph::knotted() { - /* Matrix sequel (copy) to preserve original */ - matrix revolutions = m; - struct Vertex* neo = NULL; // neo is the head of the linked list - - for ( int matrix_row = 0; matrix_row < num_processes + num_resources; matrix_row++ ) { - for ( int matrix_col = 0; matrix_col < num_processes + num_resources; matrix_col++ ) { - if ( matrix_row == matrix_col ) continue; // do not connect processes and resources to themselves - if ( m[matrix_row][matrix_col] == 1 ) { - pushLL(&neo,matrix_row); - } - else { - continue; - } - } - } - - return false; + return (detectKnot()) ? true : false; } \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index b3be782..0e346fb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -25,7 +25,7 @@ int main (int argc, char **argv) { g.print (); // Graph reduction printf ("Graph is %s\n", g.reducible () ? "not reducible! Deadlock!" : "reducible! No deadlock!"); - // TODO: Knot detection - // printf ("Graph is %s\n", g.knotted () ? "knotted! Deadlock!" : "not! No deadlock!"); + // Knot detection + printf ("Graph is %s\n", g.knotted () ? "knotted! Deadlock!" : "not! No deadlock!"); return 0; }