কম্পিউটার টিউটোরিয়াল

বেলম্যান-ফোর্ড অ্যালগরিদম শর্টেস্ট পাথের জন্য (Bellman-Ford Algorithm for Shortest Paths)

বেলম্যান-ফোর্ড অ্যালগরিদম ব্যবহার করা হয় সোর্স ভার্টেক্স থেকে অন্য যেকোনো ভার্টেক্স পর্যন্ত ন্যূনতম দূরত্ব খুঁজে বের করতে। এই অ্যালগরিদমের মূল পার্থক্য ডিজ্কস্ট্রার অ্যালগরিদমের সাথে হচ্ছে, ডিজ্কস্ট্রায় আমরা নেগেটিভ ওজন হ্যান্ডেল করতে পারি না, কিন্তু এখানে সেটি সহজে হ্যান্ডেল করা যায়।

বেলম্যান-ফোর্ড অ্যালগরিদম শর্টেস্ট পাথের জন্য (Bellman-Ford Algorithm for Shortest Paths)

বেলম্যান-ফোর্ড অ্যালগরিদম বটম-আপ পদ্ধতিতে দূরত্ব খুঁজে বের করে। প্রথমে সে সেই দূরত্বগুলো খুঁজে বের করে যেগুলোর পথে শুধু একটি এজ থাকে। তারপর পথের দৈর্ঘ্য বাড়িয়ে সব সম্ভাব্য সমাধান খুঁজে বের করে।

ইনপুট এবং আউটপুট

ইনপুট: গ্রাফের কস্ট ম্যাট্রিক্স:
0  6  ∞  7  ∞
∞  0  5  8 -4
∞ -2  0  ∞  ∞
∞  ∞ -3  0  9
2  ∞  7  ∞  0
আউটপুট: সোর্স ভার্টেক্স: 2
Vert:   0   1   2   3   4
Dist:  -4  -2   0   3  -6
Pred:   4   2  -1   0   1
গ্রাফে কোনো নেগেটিভ এজ সাইকেল নেই

এলগরিদম

bellmanFord(dist, pred, source)

ইনপুট: দূরত্ব লিস্ট, প্রিডিসেসর লিস্ট, এবং সোর্স ভার্টেক্স।
আউটপুট: নেগেটিভ সাইকেল পাওয়া গেলে true।

শুরু
  iCount := 1
  maxEdge := n * (n - 1) / 2  // n হলো ভার্টেক্সের সংখ্যা
  গ্রাফের সব ভার্টেক্স v এর জন্য, করুন
    dist[v] := ∞
    pred[v] := φ
  শেষ লুপ
  dist[source] := 0
  eCount := গ্রাফে উপস্থিত এজের সংখ্যা
  edgeList নামে একটি এজ লিস্ট তৈরি করুন
  যতক্ষণ iCount < n, করুন
    i := 0 থেকে eCount পর্যন্ত, করুন
      যদি dist[edgeList[i].v] > dist[edgeList[i].u] + (cost[u,v] for edge i) 
        dist[edgeList[i].v] > dist[edgeList[i].u] + (cost[u,v] for edge i)
        pred[edgeList[i].v] := edgeList[i].u
    শেষ লুপ
  iCount := iCount + 1
  গ্রাফের সব ভার্টেক্স i এর জন্য, করুন
    যদি dist[edgeList[i].v] > dist[edgeList[i].u] + (cost[u,v] for edge i), 
      তবে return true
  শেষ লুপ
  return false
শেষ

উদাহরণ (C++ কোড)

#include <iostream>
#include <iomanip>
#define V 5
#define INF 999
using namespace std;

// গ্রাফের কস্ট ম্যাট্রিক্স (ডায়রেক্টেড) ভার্টেক্স 5
int costMat[V][V] = {
  {0, 6, INF, 7, INF},
  {INF, 0, 5, 8, -4},
  {INF, -2, 0, INF, INF},
  {INF, INF, -3, 0, 9},
  {2, INF, 7, INF, 0}
};

typedef struct {
  int u, v, cost;
} edge;

int isDiagraph() {
  // চেক করুন গ্রাফ ডায়রেক্টেড কিনা
  int i, j;
  for(i = 0; i < V; i++) {
    for(j = 0; j < V; j++) {
      if(costMat[i][j] != costMat[j][i]) {
        return 1;  // গ্রাফ ডায়রেক্টেড
      }
    }
  }
  return 0; // গ্রাফ অননির্দেশিত
}

int makeEdgeList(edge *eList) {
  // গ্রাফের এজ থেকে এজলিস্ট তৈরি করুন
  int count = -1;
  if(isDiagraph()) {
    for(int i = 0; i < V; i++) {
      for(int j = 0; j < V; j++) {
        if(costMat[i][j] != 0 && costMat[i][j] != INF) {
          count++;  // ডায়রেক্টেড গ্রাফ হলে এজ পাওয়া যায়
          eList[count].u = i; eList[count].v = j;
          eList[count].cost = costMat[i][j];
        }
      }
    }
  } else {
    for(int i = 0; i < V; i++) {
      for(int j = 0; j < i; j++) {
        if(costMat[i][j] != INF) {
          count++;  // অননির্দেশিত গ্রাফ হলে এজ পাওয়া যায়
          eList[count].u = i; eList[count].v = j;
          eList[count].cost = costMat[i][j];
        }
      }
    }
  }
  return count+1;
}

int bellmanFord(int *dist, int *pred, int src) {
  int icount = 1, ecount, max = V*(V-1)/2;
  edge edgeList[max];
  for(int i = 0; i < V; i++) {
    dist[i] = INF;  // অনন্ত দিয়ে ইনিশিয়ালাইজ
    pred[i] = -1;   // কোনো প্রিডিসেসর পাওয়া যায়নি
  }
  dist[src] = 0;  // শুরুর ভার্টেক্সের দূরত্ব ০
  ecount = makeEdgeList(edgeList);  // edgeList গঠন
  while(icount < V) {
    // ইটারেশনের সংখ্যা (Vertex - 1)
    for(int i = 0; i < ecount; i++) {
      if(dist[edgeList[i].v] > dist[edgeList[i].u] + costMat[edgeList[i].u][edgeList[i].v]) {
        // এজ রিল্যাক্স করুন এবং প্রিডিসেসর সেট করুন
        dist[edgeList[i].v] = dist[edgeList[i].u] + costMat[edgeList[i].u][edgeList[i].v];
        pred[edgeList[i].v] = edgeList[i].u;
      }
    }
    icount++;
  }
  // নেগেটিভ সাইকেলের জন্য টেস্ট
  for(int i = 0; i < ecount; i++) {
    if(dist[edgeList[i].v] > dist[edgeList[i].u] + costMat[edgeList[i].u][edgeList[i].v]) {
      return 1;  // নির্দেশ করে গ্রাফে নেগেটিভ সাইকেল আছে
    }
  }
  return 0;  // কোনো নেগেটিভ সাইকেল নেই
}

void display(int *dist, int *pred) {
  cout << "Vert: ";
  for(int i = 0; i < V; i++)
    cout << setw(3) << i << " ";
  cout << endl;
  cout << "Dist: ";
  for(int i = 0; i < V; i++)
    cout << setw(3) << dist[i] << " ";
  cout << endl;
  cout << "Pred: ";
  for(int i = 0; i < V; i++)
    cout << setw(3) << pred[i] << " ";
  cout << endl;
}

int main() {
  int dist[V], pred[V], source, report;
  source = 2;
  report = bellmanFord(dist, pred, source);
  cout << "Source Vertex: " << source << endl;
  display(dist, pred);
  if(report)
    cout << "The graph has a negative edge cycle" << endl;
  else
    cout << "The graph has no negative edge cycle" << endl;
}

আউটপুট

Source Vertex: 2
Vert:   0   1   2   3   4
Dist:  -4  -2   0   3  -6
Pred:   4   2  -1   0   1
The graph has no negative edge cycle
  1. CSMA/CD-এর জন্য ব্যাক-অফ অ্যালগরিদম

  2. ডেটা স্ট্রাকচরে ইয়েনস k-শর্টেস্ট পাথ অ্যালগরিদম

  3. C++ তে বেলম্যান-ফোর্ড অ্যালগরিদম (Bellman Ford Algorithm)

  4. ডিস্ট্রিবিউটেড শেয়ারড মেমরি বাস্তবায়নের অ্যালগরিদম