hagaycohen2 / CPP_EX1_24

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

מטלה 1 , תכנות מערכות 2

פרטים אישיים

חגי כהן , hagaycohen2@gmail.com , #####6180

מבנה וחלוקה למחלקות

מבט על

מתחילת המטלה ולאורך העבודה עליה תמיד חזרתי להוראה המרכזית

ליצור מחלקה שמייצגת גרף ולממש אלגוריתמים על הגרפים

התכונות המתארות גרף והמטודות הישירות עליהן יושבות יחד במחלקה "גרף"

במקביל כתבתי מחלקת אלגוריתמים המחזיקה אלגוריתמים ופונקציות עזר המאבחנים את הגרפים מהבטים שונים

לצד מחלקות אלה הוספתי מקרי קצה לקובץ הטסטים כדי לוודא את נכונות האלגוריתמים

אציין שהשתמשתי בקובץ הדמו המצורף רק בכדי לבדוק שהקוד שלי עובד ונתתי את הדגש שלי בעיקר במימושי המחלקות

מבנה המחלקות מפורט בהמשך.

גרפים

Graph.hpp

בקובץ זה מוגדר המבנה הבסיסי של גרף במחלקה Graph וחתימות המטודות שלו, התכונות מוגדרות פרטיות והן :

מטריצת שכנויות, מספר הקודקודים , מספר הצלעות

   vector<vector<int>> matrix;
   size_t vertices;
   size_t edges;

כל המטודות מוגדרות ציבוריות ונגישות למשתמש והן:

 // constructor
    Graph();

    void loadGraph(vector<vector<int>> graph);
    void printGraph();
    vector<vector<int>> getMatrix();
    size_t getVertices();

על המטרה ואופן המימוש אפרט בחלק השני של הקובץ.

Graph.cpp

קובץ זה מכיל את מימושי המטודות והבנאי של גרפים

קובץ זה אינו נגיש למשתמש חשוף רק לקובץ Graph.hpp

בנוסף נעשה שימוש גם ב namespace std

אלגוריתמים

Algorithms.hpp

בקובץ זה מוגדרים קבועים וכן מוגדרות שתי מחלקות, מחלקת Algorithms , והמחלקה negativeCycleException

המחלקה Algorithms

המחלקהAlgorithms היא אוסף מטודות סטטיות אשר מנתחות גרפים מהבטים שונים ומחזירות מסקנות בהתאם

המחלקה מחולקת לאוסף מטודות סטטיות ציבוריות אשר כל אחת מיצגת "שאלה אחרת על גרף"

static int isConnected(Graph &graph);
    static string shortestPath(Graph &graph, size_t src, size_t dest);
    static string isContainsCycle(Graph &graph);
    static string isBipartite(Graph &graph);
    static string negativeCycle(Graph &graph);

ובנוסף אליהן אוסף מטודות סטטיות פרטיות המשמשות עבורן כפונקציות עזר

static vector<vector<int>> DFS(Graph &graph, size_t src);
    static vector<int> DFS_visit(Graph &graph, size_t src, vector<int> &visited);
    static void DFS_parents_visit(Graph &graph, size_t src, vector<int> &visited, vector<int> &parents);              
    static vector<int> DFS_backEdge(Graph &graph, size_t src, vector<int> &visited, vector<int> &parents);
    static vector<int> BellmanFord(Graph &graph, size_t src);

כאמור מימוש האלגוריתמים ואופן השימוש בכל מתודה יפורט בחלקת השני של קובץ זה.

המחלקה negativeCycleException

מחלקה זו מייצגת שגיאה מיוחדת אשר זורקת פונקציית העזר BellmanFord

השגיאה מכילה בתוכה את המעגל השלילי שזוהה.

Algorithms.cpp

קובץ זה מכיל תחילה את המימושים של פונקציות העזר מ Algorithms.hpp

לאחר מכל בעזרת פונקציות אלה והמתודות במחלקה Graph ממומשים כל האלגוריתמים הציבוריים של המחלקה

שונות

Test.cpp

קובץ בדיקות כפי שניתן עם המטלה שאיליו הוספתי עוד מקרי קצה

הקובץ מחולק לפי סוגי בדיקות בהתאם לאלגוריתמים השונים

המשכתי את הקובץ הקיים כדי "להרוויח" גם את הבדיקות הנתונות בנוסף לבדיקות שלי

Makefile

עשיתי מספר שינויים בקובץ המייק שמטרתם לפצל בין הרצת תוכנית על אוסף גרפים (במקרה הזה demo)

לבין הרצת בדיקות על האלגוריתמים

פיצול זה נעשה מתוך חשיבה שהמחלקות שלי נועדו לשמש משתמשים אשר ירצו לקבל מסקנות לגבי הגרפים שלהם

ולא נרצה שבכל שימוש במערכת האלגוריתמים יבדקו מחדש אלא נריץ בדיקה רק כשנבצע שינוי כלשהו במימוש

מימושים והנחות

הנחות כלליות

  • כל המשקלים של הצלעות הם ערכים שלמים
  • מעגל מכיל לפחות שלושה קודקודים
  • אין צלעות מקודקוד לעצמו

גרפים

Graph - בנאי

בנאי יחיד שמאתחל גרף עם 0 צלעות ו 0 קודקודים

loadGraph

מאתחלת מטריצת שכנויות חדשה לגרף ומעדכן בהתאם את מספר הצלעות והקודקודים בגרף

הפונקציה תחזיר שגיאה אם המטריצה לא סימטרית או שהוכנס ערך לא חוקי (למשל, צלע מקודקוד לעצמו)

printGraph

מציינת את כמות הצלעות והקודקודים בגרף ומדפיסה אותו בייצוג של מטריצת שכנויות

getMatrix , getVertices

כמצופה מחזירות את מספר הצלעות ומספר הקודקודים

אלגוריתמים

קבועים

const int INT_MAX = 2147483647;
const int WHITE = 0;
const int GRAY = 1;
const int BLACK = 2;

לצורך נוחות בצביעת קודקודים ואיתחול משקלי מסלולים

DFS

פונקציית עזר העוברת על הגרף בשיטת DFS ומחזירה יער DFS (כפי שלמדנו באלגוריתמים 1)

DFS_visit

פונקציית עזר הנקראת באופן רקורסיבי ב DFS

DFS_parents_visit

פונקציית עזר העוברת על הגרף באותה שיטה כמו DFS אך מחזירה את רשימת ההורים של כל קודקוד ביער DFS

DFS_backEdge

פונקציית עזר אשר עוברת על הגרף בשיטת DFS ומחזירה צלע מסוג back edge אם יש כזו

BellmanFord

פונקציית עזר שבדיוק כמו אלגוריתם בלמן פורד שלמדנו מחזירה מערך של הורים במסלול הקצר ביותר עבור כל קודקוד ל src מסויים.

ההבדל המרכזי הוא שהפונקצייה שלי זורקת שגיאה מיוחדת כאשר מזוהה מעגל שלילי כך שהמעגל השלילי נמצא בשגיאה עצמה

negativeCycleException

מחלקה המייצגת שגיאה הנזרקת כאשר מזוהה מעגל שלילי באלגוריתם BellmanFord

הבנאי של השגיאה מקבל את מערך ההורים ואת הקודקוד שאליו זוהה relax לאחר N מעברים על כל הצלעות

בהפעלת הבנאי הוא עוקב אחרי מצבעי ההורים ומזהה את המעגל ושומר אותו כתכונה של השגיאה

התכונה מוגדרת public וניתנת לגישה ע"י הפונקציה שתפסה אותה

isConnected

פונקצייה ציבורית אשר מקבלת גרף ומחזירה האם הוא קשיר

הפונקצייה קוראת ל DFS ומבצעת קריאה נוספת מהשורש של העץ האחרון ביער

לפי שיטה זו אם יהיה עץ יחיד היער שמתקבל מהקריאה השנייה נדע שהגרף קשיר

שיטה זו מוכחת בקורס אלגוריתמים אחד

shortestPath

פונקצייה ציבורית אשר מחזירה את המסלול הקצר ביותר (הקל ביותר אם הגרף ממושקל) בין שני קודקודים

אם מדובר באותו הקודקוד הפונקצייה תחזיר אותו

אם לא, הפונקצייה תקרא BellmanFord

אם פונקציית העזר תזרוק שגיאה אזי יש מעגל שלילי והפונקצייה תחזיר -1

גם אם אין מעגל שלילי אבל גם אין מסלול הפונקצייה תחזיר -1

במידה ויש מסלול הפונקציה תחלץ אותו ע"י מעבר על התוצאה המתקבלת מפונקציית העזר

isContainsCycle

הפונקצייה קוראת ל DFS_parents_visit ושולחת את המערך המתקבל ל - DFS_backEdge

backEdgeפונקציית העזר תחזיר וקטור ריק אם אין מעגל ואם יש היא תחזיר את ה שבעזרתה נשחזר את המעגל ונחזיר אותו

isBipartite

הפונקצייה בודקת אם הגרף הוא 2 צביע על ידי מעבר BFS אם הגרף אכן ניתן לצביעה בשני צבעים הפונקצייה תחזיר את הקבוצות ואם לא הפונקציה תחזיר 0

negativeCycle

הפונקצייה תקרא ל BellmanFord ואם תזרק שגיאה היא תחלץ מתוכה את המעגל השלילי, במידה ואין מעגל שלילי יוחזר 0

שונות

tests

בקובץ Test.cpp מאותחלים גרפים מסוגים שונים המייצגים מקרי קצה ומקים גנרים עבור האלגוריתמים השונים

התוצאה הנוודקת בהשוואה היא התוצאה הצפוייה מהאלגוריתמים כפי שמימשתי אותם

Makefile

קובץ מייק סטנדרטי כאשר ברירת המחדל שלו היא לקמפל את הפרוייקט ולהריץ את הדמו בנוסף קיימת הרצת טסטים ע"י הפקודה make run_test

קיימות אפשרויות גם להריץ tidy ןכן גם valgrind

בסוף הקובץ מוגדרת הפעולה clean וגם .PHONY כדי לקמפל תמיד את הקבצים שנרצה להתעלם מחתימת הזמן שלהם

demo - הערות

יש לציין שהוספתי namespace משלי ולכן נעשו שינויים בקובץ כדי שירוץ

לר שיניתי את הטעויות בתיעוד שהוזכרו בפורום כי את הבדיקות שלי עשיתי מול test ולא מול demo

About


Languages

Language:C++ 99.7%Language:Makefile 0.3%