Τεχνολογίες Υλοποίησης Αλγορίθµων Χρήστος Ζαρολιάγκης Καθηγητής Τµήµα Μηχ/κων Η/Υ & Πληροφορικής Πανεπιστήµιο Πατρών email: zaro@ceid.upatras.gr Ενότητα 7 1 / 48
Αδειες Χρήσης Το παρόν εκπαιδευτικό υλικό υπόκειται σε άδειες χρήσης Creative Commons. Για εκπαιδευτικό υλικό, όπως εικόνες, που υπόκειται σε άλλου τύπου άδειας χρήσης, η άδεια χρήσης αναφέρεται ϱητώς. 2 / 48
Χρηµατοδότηση Το παρόν εκπαιδευτικό υλικό έχει αναπτυχθεί στα πλαίσια του εκπαιδευτικού έργου του διδάσκοντα. Το έργο «Ανοικτά Ακαδηµαϊκά Μαθήµατα στο Πανεπιστήµιο Πατρών» έχει χρηµατοδοτήσει µόνο τη αναδιαµόρφωση του εκπαιδευτικού υλικού. Το έργο υλοποιείται στο πλαίσιο του Επιχειρησιακού Προγράµµατος «Εκπαίδευση και ια Βίου Μάθηση» και συγχρηµατοδοτείται από την Ευρωπαϊκή Ενωση (Ευρωπαϊκό Κοινωνικό Ταµείο) και από εθνικούς πόρους. 3 / 48
Περιεχόµενα Αλγόριθµοι Συντοµότερων ιαδροµών και Υλοποιήσεις Γενικά κόστη ακµών Αλγόριθµος Bellman-Ford Ελεγκτής Ορθότητας Αλγορίθµων Συντοµότερων ιαδροµών Αρχέτυπα για Αλγορίθµους Γραφηµάτων 4 / 48
Γενικευµένος Αλγόριθµος ΕΣ ΑΚ for all { v V d(v) = ; π(v) = nil; d(s) = 0; while e = (u, v) E : d(v) > d(u) + c(e) { d(v) = d(u) + c(e); π(v) = e; Γράφηµα προκατόχων (οριζόµενο από τους δείκτες π): P = {e : e = π(v) E, v V 5 / 48
Γενικευµένος Αλγόριθµος ΕΣ ΑΚ Ιδιότητες 1 d(s) = 0 ανν π(s) = nil, και d(v) < ανν π(v) nil, για v s 2 Αν π(v) = e = (u, v), τότε d(v) d(u) + c(e) 3 Αν π(v) nil, τότε η v είτε ϐρίσκεται σε έναν κύκλο του P, είτε είναι προσπελάσιµη από έναν κύκλο στο P, είτε είναι προσπελάσιµη από την s στο P. Αν π(s) nil, τότε η s ϐρίσκεται σε έναν κύκλο του P. 4 Οι κύκλοι στο P έχουν αρνητικό κόστος 5 Αν η v ϐρίσκεται σε έναν κύκλο του P ή είναι προσπελάσιµη από έναν κύκλο στο P, τότε δ(v) = 6 Αν v V f και d(v) = δ(v), τότε µια s-v διαδροµή στο P η οποία έχει κόστος δ(v) 7 Αν d(v) = δ(v) v V f, τότε το επαγώµενο από τις κορυφές του V f υπογράφηµα του P είναι ένα Σ 6 / 48
Γενικευµένος Αλγόριθµος ΕΣ ΑΚ Προβλήµατα ΠΧΠ εκθετική (ακόµη και σε απουσία αρνητικών κύκλων) Ο αλγόριθµος δεν τερµατίζει όταν αρνητικοί κύκλοι 7 / 48
Γενικευµένος Αλγόριθµος ΕΣ ΑΚ Αντιµετώπιση 1ου προβλήµατος ιατήρηση ενός συνόλου κορυφών U: κορυφές που προσωρινά δεν παραβιάζουν την τριγωνική ανισότητα U {u : d(u) < και (u, v) E µε d(u) + c(u, v) < d(v) for all { v V d(v) = ; π(v) = nil; d(s) = 0; U = {s; while U { επιλογή u U; U = U {u; for all e = (u, v) E { if d(v) > d(u) + c(e) then { U = U {v; d(v) = d(u) + c(e); π(v) = e; 8 / 48
Γενικευµένος Αλγόριθµος ΕΣ ΑΚ Αντιµετώπιση 1ου προβλήµατος Ποια κορυφή u U πρέπει να επιλέξουµε ; Υπαρξη Βέλτιστης Επιλογής (ι) Για κάθε v V f µε d(v) > δ(v), κορυφή u U µε d(u) = δ(u) και η οποία ϐρίσκεται σε µια s-v Σ (ιι) Οταν µια κορυφή u µε d(u) = δ(u) διαγράφεται από το U, τότε δεν προστίθεται ποτέ ξανά στο U 9 / 48
Γενικευµένος Αλγόριθµος ΕΣ ΑΚ Αντιµετώπιση 1ου προβλήµατος Σχέση µεταξύ (d, π) και (dist, pred) pred[v] = π(v), dist[v] = { d(v) αν d(v) < αυθαίρετη αν d(v) = + Αναπαράσταση του + d(v) = + ανν v s και π(v) = nil Σύγκριση d < d(v), d IR (pred[v] == nil && v!= s) d < dist[v] 10 / 48
Αλγόριθµος Bellman-Ford Αντιµετώπιση 2ου προβλήµατος Πώς επιλέγουµε κορυφές από το U ; Οργάνωση του αλγορίθµου σε ϕάσεις U i = U στην αρχή της ϕάσης i, i 0, U 0 = {s Στην ϕάση i, όλες οι κορυφές του U i διαγράφονται από το U και οι νέες κορυφές που προστίθενται στο U εισάγονται στο U i+1 Υλοποίηση του U µε χρήση ουράς Q Φάση i: όλες οι κορυφές του U i ϐρίσκονται στην αρχή της Q και όλες οι κορυφές του U i+1 ϐρίσκονται στο τέλος της Q, χωρισµένες από έναν διαχωριστή µε τιµή nil Οταν ο διαχωριστής nil ϐρίσκεται στην αρχή της Q, τότε αυξάνεται ϐηµατικά η phase_count node_array<bool> in_q : in_q[v] = true, ανν v Q (αποφυγή επανεισαγωγών στην Q) 11 / 48
Αλγόριθµος Bellman-Ford Ο αλγόριθµος τερµατίζει όταν Q =, ή όταν i = n Στην πρώτη περίπτωση (Q = ): d(v) = δ(v), v V Στη δεύτερη περίπτωση (i = n): d(v) = δ(v), v V + V f Οι κορυφές του V αντιµετωπίζονται σε µια µεταγενέστερη ϕάση 12 / 48
Αλγόριθµος Bellman-Ford Πρόβληµα ΕΣ ΑΚ bool BELLMAN_FORD_T(const graph& G, node s, const edge_array<nt>& c, node_array<nt>& dist, node_array<edge>& pred) Επιστρέφει false αν δ(v) = για κάποια κορυφή v αλλιώς, επιστρέφει true Χρόνος: O(nm) 13 / 48
Αλγόριθµος Bellman-Ford Πρόβληµα ΕΣ ΑΚ // BF: helper template <class NT> bool BELLMAN_FORD_T(const graph& G, node s, const edge_array<nt>& c, node_array<nt>& dist, node_array<edge>& pred ) { int n = G.number_of_nodes(); int phase_count = 0; b_queue<node> Q(n+1); node_array<bool> in_q(g,false); node u,v; edge e; forall_nodes(v,g) pred[v] = nil; dist[s] = 0; Q.append(s); in_q[s] = true; Q.append((node) nil); // end marker 14 / 48
Αλγόριθµος Bellman-Ford Πρόβληµα ΕΣ ΑΚ while( phase_count < n ) { u = Q.pop(); if ( u == nil) { phase_count++; if ( Q.empty() ) return true; Q.append((node) nil); continue; else in_q[u] = false; NT du = dist[u]; forall_adj_edges(e,u) { v = G.opposite(u,e); // makes it also work for ugraphs NT d = du + c[e]; if ( (pred[v] == nil && v!= s) d < dist[v] ) { dist[v] = d; pred[v] = e; if (!in_q[v] ) { Q.append(v); in_q[v] = true; // BF: postprocessing return false; 15 / 48
Αλγόριθµος Bellman-Ford Πρόβληµα ΕΣ ΑΚ Μεταγενέστερη Φάση: Q µετά από n φάσεις Πρόβληµα: µπορεί να υπάρχουν κορυφές στο V που δεν είναι ακόµη προσπελάσιµες από έναν κύκλο στο γράφηµα P Πώς µπορούµε να ϐρούµε αυτές τις κορυφές χωρίς να χρειαστεί να εκτελέσουµε τον αλγόριθµο για έναν µεγαλύτερο αριθµό ϕάσεων ; 16 / 48
Αλγόριθµος Bellman-Ford Πρόβληµα ΕΣ ΑΚ Βασικές Ιδιότητες µετά από n φάσεις δ k (v) = min{c(p) : p µια s-v διαδροµή µε το πολύ k ακµές 1 d(v) δ n (v) και αν v U, τότε d(v) < δ n 1 (v) 2 s V f ανν π(s) = nil 3 Κάθε κορυφή u U ϐρίσκεται είτε σε έναν κύκλο του P, είτε είναι προσπελάσιµη από έναν κύκλο στο P 4 Κάθε κορυφή v V είναι προσπελάσιµη στο G από κάποια u U 5 Αν π(s) nil, τότε κάθε κορυφή προσπελάσιµη από την s ϐρίσκεται είτε σε έναν κύκλο του P, είτε είναι προσπελάσιµη από έναν κύκλο στο P 17 / 48
Αλγόριθµος Bellman-Ford Πρόβληµα ΕΣ ΑΚ Μεταγενέστερη Φάση Εστω V f (π(s) = nil), και R V f το σύνολο των κορυφών που είναι προσπελάσιµες από την s στο P Ολες οι κορυφές w R που είναι προσπελάσιµες από µια κορυφή u U ανήκουν στο V και εποµένως πρέπει να ενηµερωθούν οι π(w) Ενηµέρωση π(w), w R Εκτέλεση ΑΠΒ από κάθε u U όταν µια κορυφή w R προσπελαύνεται µέσω της ακµής (z, w), τότε ϑέτουµε π(w) = (z, w) όλες οι κορυφές του R V είναι προσπελάσιµες από τις κορυφές του U και από την (3) προσπελάσιµες από έναν κύκλο στο P 18 / 48
Αλγόριθµος Bellman-Ford Πρόβληµα ΕΣ ΑΚ Μεταγενέστερη Φάση: Πώς προσδιορίζονται οι κορυφές του R ; ΑΠΒ από την s στο P, αφού πρώτα «κρύψουµε» τις ακµές που δεν ανήκουν στο P και µετά τις επαναφέρουµε στο αρχικό γράφηµα // BF: postprocessing if (pred[s]!= nil) return false; node_array<bool> in_r(g,false); forall_edges(e,g) if (e!= pred[g.target(e)]) ((graph*) &G)->hide_edge(e); DFS(G,s,in_R); // sets in_r[v] = true for v in R ((graph*) &G)->restore_all_edges(); node_array<bool> reached_from_node_in_u(g,false); forall_nodes(v,g) if (in_q[v] &&!reached_from_node_in_u[v]) Update_pred(G,v,in_R,reached_from_node_in_U,pred); 19 / 48
Αλγόριθµος Bellman-Ford Πρόβληµα ΕΣ ΑΚ Μεταγενέστερη Φάση: Πώς προσδιορίζονται οι κορυφές του R ; (συνέχεια) // BF: helper inline void Update_pred(const graph& G, node v, const node_array<bool>& in_r, node_array<bool>& reached_from_node_in_u, node_array<edge>& pred) { reached_from_node_in_u[v] = true; edge e; forall_adj_edges(e,v) { node w = G.target(e); if (!reached_from_node_in_u[w] ) { if ( in_r[w] ) pred[w] = e; Update_pred(G,w,in_R,reached_from_node_in_U,pred); 20 / 48
Γενικός Αλγόριθµος ΕΣ ΑΚ template <class NT> bool SHORTEST_PATH_T(const graph& G, node s, const edge_array<nt>& c, node_array<nt>& dist, node_array<edge>& pred ) { if ( Is_Acyclic(G) ) { ACYCLIC_SHORTEST_PATH_T(G,s,c,dist,pred); return true; bool non_negative = true; edge e; forall_edges(e,g) if (c[e] < 0) non_negative = false; if (non_negative) { DIJKSTRA_T(G,s,c,dist,pred); return true; return BELLMAN_FORD_T(G,s,c,dist,pred); 21 / 48
Ελεγκτής Ορθότητας Αλγορίθµων ΕΣ ΑΚ Ανάπτυξη προγράµµατος CHECK_SP_T(G,s,c,dist,pred) το οποίο ϑα ελέγχει αν το Ϲεύγος (dist, pred) είναι µια σωστή λύση του προβλήµατος ΕΣ ΑΚ (G, s, c) Εσφαλµένη λύση: σταµατάει αµέσως η εκτέλεση του προγράµµατος µε διαγνωστικό µήνυµα λάθους ("assertion failed") Σωστή λύση: επιστρέφει ένα node_array<int> label µε label[v] < 0, αν v V label[v] = 0, αν v V f label[v] > 0, αν v V + 22 / 48
Ελεγκτής Ορθότητας Αλγορίθµων ΕΣ ΑΚ Ορισµοί { αν pred[s] U f nil = {v; s-v διαδροµή στο P αν pred[s] = nil U + = {v; v s και pred[v] = nil U = {v; v ϐρίσκεται σε έναν κύκλο του P ή είναι προσπελάσιµη από έναν κύκλο στο P 23 / 48
Ελεγκτής Ορθότητας Αλγορίθµων ΕΣ ΑΚ Ελεγχοι Ορθότητας Το Ϲεύγος (dist, pred) είναι µια σωστή λύση αν ικανοποιούνται οι παρακάτω συνθήκες/έλεγχοι: 1 v U + αν διαδροµή s-v στο G 2 Ολοι οι κύκλοι στο P έχουν αρνητικό κόστος 3 ακµή (v, w) E µε v U και w U f 4 e = (v, w) E: αν v U f και w U f, τότε dist[v] + c[e] dist[w] 5 v U f : αν v = s, τότε dist[v] = 0, και αν v s τότε dist[v] = dist[u] + c[pred[v]] όπου u είναι η αρχική κορυφή της pred[v] 24 / 48
Υλοποίηση Ελεγκτή Συνθ. (1) & Κατηγοριοποίηση κορυφών Αρχικά όλες οι κορυφές έχουν label ίσο µε UNKNOWN Εκτέλεση ΑΠΒ για προσδιορισµό όλων των κορυφών που είναι προσπελάσιµες από την s, και έλεγχος για όλα τα v s: pred[v] = nil ανν s-v διαδροµή Σε όλες τις κορυφές που δεν είναι προσπελάσιµες από την s: ανάθεση τιµής label ίσο µε PLUS // condition (1) enum{ NEG_CYCLE = -2, ATT_TO_CYCLE = -1, FINITE = 0, PLUS = 1, CYCLE = 2, ON_CUR_PATH = 3, UNKNOWN = 4 ; node_array<int> label(g,unknown); node_array<bool> reachable(g,false); DFS(G,s,reachable); node v; forall_nodes(v,g) { if (v!= s) { assert( (pred[v] == nil) == (reachable[v] == false)); if (reachable[v] == false) label[v] = PLUS; 25 / 48
Υλοποίηση Ελεγκτή Συνθ. (1) & Κατηγοριοποίηση κορυφών s v w v Ακολουθούµε τη διαδροµή [v, source(pred[v]), source(pred[source(pred[v])]),...] µέχρι να συναντήσουµε µια κορυφή δύο ϕορές (U ) ή µέχρι να µην µπορούµε να προχωρήσουµε άλλο (U f ) U : κορυφές που ανήκουν σε έναν κύκλο στο P (label CYCLE) και κορυφές που είναι προσπελάσιµες από έναν κύκλο στο P (label ATT_TO_CYCLE) Η διαπέραση µιας διαδροµής δεν πρέπει να γίνει πολλές ϕορές η διαπέραση σταµατά όταν συναντήσουµε µια κορυφή µε label UNKNOWN Κατά τη διαπέραση όλες οι κορυφές της διαδροµής εισάγονται σε µία στοίβα S και παίρνουν label ON_CUR_PATH 26 / 48
Υλοποίηση Ελεγκτή Συνθ. (1) & Κατηγοριοποίηση κορυφών s v w v // classification of nodes if (pred[s] == nil) label[s] = FINITE; forall_nodes(v,g) { if ( label[v] == UNKNOWN ) { stack<node> S; node w = v; while ( label[w] == UNKNOWN ) { label[w] = ON_CUR_PATH; S.push(w); w = G.source(pred[w]); // label all nodes on current path 27 / 48
Υλοποίηση Ελεγκτή Συνθ. (1) & Κατηγοριοποίηση κορυφών s v Εξέταση κορυφής w µε label UNKNOWN w v Αν label[w]=finite, τότε όλες οι κορυφές της διαδροµής U f Αν label[w]=cycle ή label[w]=att_to_cycle, τότε όλες οι κορυφές (εκτός της w) είναι προσπελάσιµες από έναν κύκλο. Αν επίσης η w ανήκει στην τρέχουσα διαδροµή, τότε ανήκει στον κύκλο // label all nodes on current path int t = label[w]; if ( t == ON_CUR_PATH ) { node z; do { z = S.pop(); label[z] = CYCLE; while ( z!= w ); while (!S.empty() ) label[s.pop()] = ATT_TO_CYCLE; else // t is CYCLE, ATT_TO_CYCLE, or FINITE { if ( t == CYCLE ) t = ATT_TO_CYCLE; while (!S.empty() ) label[s.pop()] = t; 28 / 48
Υλοποίηση Ελεγκτή Συνθήκη (2) Για κάθε κορυφή v µε label[v]=cycle διαπερνούµε τον κύκλο στον οποίο ανήκει, υπολογίζουµε το κόστος του και ελέγχουµε αν είναι αρνητικό. Αν ναι, τότε δίνουµε σε όλες τις κορυφές του κύκλου νέο label ίσο µε NEG_CYCLE. Αυτό εξασφαλίζει ότι κάθε κύκλος διαπερνάται µόνο µία ϕορά // condition (2) forall_nodes(v,g) { if ( label[v] == CYCLE ) { node w = v; NT cycle_length = 0; do { cycle_length += c[pred[w]]; label[w] = NEG_CYCLE; w = G.source(pred[w]); while (w!= v); assert(cycle_length < 0); 29 / 48
Υλοποίηση Ελεγκτή Συνθήκες (3), (4) & (5) 3 ακµή (v, w) E µε v U και w U f 4 e = (v, w) E: αν v U f και w U f, τότε dist[v] + c[e] dist[w] 5 v U f : αν v = s, τότε dist[v] = 0, και αν v s τότε dist[v] = dist[u] + c[pred[v]] όπου u είναι η αρχική κορυφή της pred[v] //conditions (3), (4), and (5) if ( label[s] == FINITE ) assert(dist[s] == 0); edge e; forall_edges(e,g) { node v = G.source(e); node w = G.target(e); if ( label[w] == FINITE ) { assert( label[v] == FINITE label[v] == PLUS); if ( label[v] == FINITE ) { assert( dist[v] + c[e] >= dist[w] ); if ( e == pred[w] ) assert( dist[v] + c[e] == dist[w] ); 30 / 48
Υλοποίηση Ελεγκτή Το πλήρες πρόγραµµα template <class NT> node_array<int> CHECK_SP_T(const graph& G, node s, const edge_array<nt>& c, const node_array<nt>& dist, const node_array<edge>& pred) { // condition (1) // classification of nodes // condition (2) // conditions (3), (4), and (5) return label; 31 / 48
Αρχέτυπα για Αλγορίθµους Γραφηµάτων Αλγόριθµοι γραφηµάτων ακµές/κορυφές γραφηµάτων είναι συσχετισµένες µε τιµές ενός συγκεκριµένου (αριθµητικού) τύπου πρέπει να µπορούν να εφαρµοσθούν σε οποιονδήποτε αριθµητικό τύπο που ικανοποιεί κάποιες προϋποθέσεις (π.χ. είναι γραµµικά διατεταγµένος) Ο µηχανισµός αρχετύπων χρησιµοποιείται γιαυτό το σκοπό 32 / 48
Αρχέτυπα για Αλγορίθµους Γραφηµάτων Παράδειγµα: αλγόριθµος ΕΣ ΑΚ template <class NT> void DIJKSTRA_T(const graph& G, node s, const edge_array<nt>& c, node_array<nt>& dist, node_array<edge>& pred); Η παράµετρος αρχετύπου NT µπορεί να συγκεκριµενοποιηθεί µε οποιονδήποτε αριθµητικό τύπο που πληροί κάποιες συντακτικές και σηµασιολογικές προϋποθέσεις Π.χ. πρέπει να είναι γραµµικά διατεταγµένος και η λειτουργία της πρόσθεσης πρέπει να είναι µονότονη 33 / 48
Αρχέτυπα για Αλγορίθµους Γραφηµάτων Επιθυµητοί Στόχοι Οι πιο συχνά χρησιµοποιούµενες συγκεκριµενοποιήσεις πρέπει να είναι προµεταγλωττισµένες Οι προ-συγκεκριµενοποιηµένες εκδοχές πρέπει να µπορούν να χρησιµοποιούνται εναλλακτικά µε τις εκδοχές αρχετύπων 34 / 48
Αρχέτυπα για Αλγορίθµους Γραφηµάτων Μηχανισµός LEDA Για κάθε συνάρτηση Alg που υλοποιεί κάποιον αλγόριθµο τρία αρχεία Alg.h: ϐρίσκεται στον κατάλογο LEDAROOT/incl/LEDA και περιέχει τις δηλώσεις όλων των συναρτήσεων Η προ-συγκεκριµενοποιηµένη εκδοχή έχει όνοµα Alg, ενώ η εκδοχή αρχετύπου έχει όνοµα Alg_T Alg.t: ϐρίσκεται στον κατάλογο LEDAROOT/incl/LEDA/templates και περιέχει τον ορισµό της συνάρτησης αρχετύπου _Alg.c: ϐρίσκεται στον κατάλογο LEDAROOT/src και περιέχει τις υλοποιήσεις των συγκεκριµενοποιήσεων µε ϐάση τη συνάρτηση αρχετύπου Το αρχείο αυτό είναι προµεταγλωττισµένο στο αρχείο κώδικα αντικειµένου _Alg.o που περιέχεται σε κάποια από τις ϐιβλιοθήκες της LEDA 35 / 48
Αρχέτυπα για Αλγορίθµους Γραφηµάτων Μηχανισµός LEDA Χρήση των διαφορετικών εκδοχών Συνάρτηση αρχετύπου #include <LEDA/templates/Alg.t> Προ-συγκεκριµενοποιηµένη συνάρτηση #include <LEDA/Alg.h> 36 / 48
Αρχέτυπα για Αλγορίθµους Γραφηµάτων Παράδειγµα: αλγόριθµος Dijkstra // file dijkstra.h #ifndef DIJKSTRA_H #define DIJKSTRA_H #include <LEDA/graph.h> template <class NT> void DIJKSTRA_T(const graph& G, node s, const edge_array<nt>& c, node_array<nt>& dist, node_array<edge>& pred); // next come the pre-instantiated versions // void DIJKSTRA(const graph& G, node s, const edge_array<int>& c, node_array<int>& dist, node_array<edge>& pred); // and, similarly, for double,... #endif 37 / 48
Αρχέτυπα για Αλγορίθµους Γραφηµάτων Παράδειγµα: αλγόριθµος Dijkstra // file dijkstra.t #include <LEDA/dijkstra.h> template <class NT> void DIJKSTRA_T(const graph& G, node s, const edge_array<nt>& c, node_array<nt>& dist, node_array<edge>& pred) { /* implementation of DIJKSTRA_T */ 38 / 48
Αρχέτυπα για Αλγορίθµους Γραφηµάτων Παράδειγµα: αλγόριθµος Dijkstra // file _dijkstra.c #include <LEDA/templates/dijkstra.t> void DIJKSTRA(const graph& G, node s, const edge_array<int>& c, node_array<int>& dist, node_array<edge>& pred) { DIJKSTRA_T(G,s,c,dist,pred); // and, similarly, for double... 39 / 48
Αρχέτυπα για Αλγορίθµους Γραφηµάτων Παράδειγµα: αλγόριθµος Dijkstra Χρήση προ-συγκεκριµενοποιηµένης εκδοχής σε πρόγραµµα εφαρµογής #include <LEDA/dijkstra.h> // define G, s, c, dist, pred with number type int DIJKSTRA(G,s,c,dist,pred); 40 / 48
Αρχέτυπα για Αλγορίθµους Γραφηµάτων Παράδειγµα: αλγόριθµος Dijkstra Χρήση εκδοχής αρχετύπου σε πρόγραµµα εφαρµογής #include <LEDA/templates/dijkstra.t> // define G, s, c, dist, pred for any number type NT DIJKSTRA_T(G,s,c,dist,pred); // define G, s, c, dist, pred for number type int // and use template version DIJKSTRA_T(G,s,c,dist,pred); // use pre-instantiated version DIJKSTRA(G,s,c,dist,pred); 41 / 48
Αρχέτυπα για Αλγορίθµους Γραφηµάτων Μια συνιστώµενη διαφορετική µέθοδος Τα.t-αρχεία δεν πρέπει να συµπεριλαµβάνονται άµεσα στα προγράµµατα εφαρµογής, διότι µπορεί να περιέχουν ϐοηθητικές συναρτήσεις οι οποίες να δηµιουργούν πρόβληµα µε τον χώρο ονοµάτων του προγ/τος εφαρµογής ηµιουργία ενδιάµεσων αρχείων Π.χ. συγκεκριµενοποίηση της DIJKSTRA_T µε τον τύπο δεδοµένων real της LEDA // real_dijkstra.h #include <LEDA/real.h> void DIJKSTRA(const graph& G, node s, const edge_array<real>& c, node_array<real>& dist, node_array<edge>& pred) 42 / 48
Αρχέτυπα για Αλγορίθµους Γραφηµάτων Μια συνιστώµενη διαφορετική µέθοδος // real_dijkstra.c #include "real_dijkstra.h" #include <LEDA/templates/dijkstra.t> void DIJKSTRA(const graph& G, node s, const edge_array<real>& c, node_array<real>& dist, node_array<edge>& pred) { DIJKSTRA_T(G,s,c,dist,pred); Το αρχείο real_dijkstra.h συµπεριλαµβάνεται στο πρόγραµµα εφαρµογής, ενώ το αρχείο real_dijkstra.c προµεταγλωττίζεται και προστίθεται στη ϐιβλιοθήκη κώδικα αντικειµένου από τον διασυνδετή 43 / 48
Τέλος Ενότητας 44 / 48
Σηµείωµα Ιστορικού Εκδόσεων Εργου Το παρόν έργο αποτελεί την έκδοση 1.0. 45 / 48
Σηµείωµα Ιστορικού Εκδόσεων Εργου Copyright Πανεπιστήµιο Πατρών, Χρήστος Ζαρολιάγκης, 2014. «Τεχνολογίες Υλοποίησης Αλγορίθµων». Εκδοση: 1.0. Πάτρα 2014. ιαθέσιµο από τη δικτυακή διεύθυνση: https://eclass.upatras.gr/courses/ceid1084 46 / 48
Σηµείωµα Ιστορικού Εκδόσεων Εργου Το παρόν υλικό διατίθεται µε τους όρους της άδειας χρήσης Creative Commons Αναφορά, Μη Εµπορική Χρήση, Οχι Παράγωγα Εργα 4.0 [1] ή µεταγενέστερη, ιεθνής Εκδοση. Εξαιρούνται τα αυτοτελή έργα τρίτων π.χ. ϕωτογραφίες, διαγράµµατα κ.λ.π., τα οποία εµπεριέχονται σε αυτό. [1] http://creativecommons.org/licenses/by-nc-nd/4.0 Ως Μη Εµπορική ορίζεται η χρήση: που δεν περιλαµβάνει άµεσο ή έµµεσο οικονοµικό όφελος από την χρήση του έργου, για το διανοµέα του έργου και αδειοδόχο που δεν περιλαµβάνει οικονοµική συναλλαγή ως προϋπόθεση για τη χρήση ή πρόσβαση στο έργο που δεν προσπορίζει στο διανοµέα του έργου και αδειοδόχο έµµεσο οικονοµικό όφελος (π.χ. διαφηµίσεις) από την προβολή του έργου σε διαδικτυακό τόπο Ο δικαιούχος µπορεί να παρέχει στον αδειοδόχο ξεχωριστή άδεια να χρησιµοποιεί το έργο για εµπορική χρήση, εφόσον αυτό του Ϲητηθεί. 47 / 48
ιατήρηση Σηµειωµάτων Οποιαδήποτε αναπαραγωγή ή διασκευή του υλικού ϑα πρέπει να συµπεριλαµβάνει : το Σηµείωµα Αναφοράς το Σηµείωµα Αδειοδότησης τη δήλωση ιατήρησης Σηµειωµάτων το Σηµείωµα Χρήσης Εργων Τρίτων (εφόσον υπάρχει) µαζί µε τους συνοδευόµενους υπερσυνδέσµους 48 / 48