* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Download 41.Applied.Recursion
Survey
Document related concepts
Transcript
Applying Recursion Routing in Computer Networks Review We’ve seen that recursion provides an elegant, simple, and (sometimes) efficient way to solve certain problems. A recursive solution consists of: – a base case: an instance of the problem that is trivial to solve; and – an induction step: a means of solving non-trivial instances using “smaller” solutions to the problem. Problem A computer network is a collection of computers, that communicate via links. 2 0 1 5 6 Links may represent 3 4 – phone lines – coaxial cable – infared transmissions – microwave relays – satellite communication links – ... Network Operations If we could represent a network in software, some of the useful operations might be: • Initialization (presumably from a file). • Is there a computer with id i in the network? • Is there a link from computer i to computer j ? • Is there a path from computer i to computer j ? Design We can represent the computers in the network by assigning each one a unique integer value (i.e., its network id). One way to represent the links in a network is to use an adjacency matrix -- a boolean matrix in which entry [i][j] is true if and only if there is a link from i to j. 2 0 3 1 5 4 6 [0] [1] [2] [3] [4] [5] [6] [0] F T F F F F T [1] T F T F F T F [2] F T F T F F F [3] F F T F T F F [4] F F F T F T T [5] F T F F T F F [6] T F F F T F F Class Members We might thus begin a Network class as follows: // Network.h // ... // Directives omitted class Network { public: Network(const string & fileName); int Size() const; bool HasComputer(int id) const; bool HasLink(int i, int j) const; vector<int> RouteFrom(int i, int j) const; private: vector<int> PathFrom(int i, int j, vector<int> visited) const; int mySize; // number of computers typedef vector<bool> Row; vector<Row> myLinks; // adjacency matrix }; Initialization For convenience, we will initialize our network using information from a file, whose format will be: – the first line of the file provides the number of computers in the network; and – each subsequent line is a pair i j indicating a bidirectional link between computers i and j. 2 0 3 1 5 6 4 7 0 1 2 3 4 4 0 1 1 2 3 4 5 6 6 5 Constructor We can define the class constructor as follows: // Network.cpp // ... #include “Network.h” Network::Network(const string & fileName) { ifstream in(fileName.data()); // open stream to file assert(in.is_open()); // verify int n; in >> n; assert(n > 0); mySize = n; // ... // // // // for convenience read number of comps check validity save Constructor // ... Network constructor (ct’d) myLinks = vector<Row>(n, Row(n, false)); int i, j; for (;;) { in >> i >> j; } } // n Rows // of n values // all ‘F’ // computers // loop: // read i, j if (in.eof()) break; // if done, quit assert(i >= 0 && i < mySize); assert(j >= 0 && j < mySize); // check i // check j myLinks[i][j] = myLinks[j][i] = true; // set links i,j // & j,i to ‘T’ in.close(); // close stream Declaration We can now declare a Network object: Network net(inputFile); If inputFile contains the values shown earlier, net will be constructed as follows: net mySize myLinks [0] 7 [0] [1] [2] [3] [4] [5] [6] F T F F F F T [1] T F T F F T F [2] F T F T F F F [3] F F T F T F F [4] F F F T F T T [5] F T F F T F F [6] T F F F T F F The Size() Operation The Size() operation is a simple extractor: // ... inline int Network::Size() const { return mySize; } The HasComputer() Operation The HasComputer() operation is also simple: // ... inline bool Network::HasComputer(int id) const { return id >= 0 && id < mySize; } The HasLink() Operation Thanks to our adjacency matrix, the HasLink() operation is also quite simple: // ... inline bool Network::HasLink(int i, int j) const { return myLinks[i][j]; } The RouteFrom() Operation The RouteFrom() operation is more complicated, since in some networks, it may be necessary to check many links in order to find a path. Example: How do we find the path from 5 to 4 in the following network? 2 0 3 1 5 6 4 RouteFrom() RouteFrom(i,j) can be implemented recursively. However, we must keep track of those nodes we have already visited on a route... If we pass this information via a parameter, we should define a recursive utility function PathFrom(i, j, visited) to do the actual work. Defining RouteFrom() PathFrom() makes RouteFrom() easy to define: // ... inline vector<int> Network::RouteFrom(int i, int j) const { vector<int> visited; return PathFrom(i, j, visited); } We could just make PathFrom() a public operation, but RouteFrom() provides a more convenient interface by not requiring the user to pass visited. Designing PathFrom() PathFrom(i, j, visited): Base case: HasLink(i,j) is true. Return a vector containing i and j. Induction Step: HasLink(i,j) is false. For each computer c: If HasLink(i,c) && c has not been visited: If there is a PathFrom(c,j) Add i to and return that path. Defining PathFrom() Here is one way PathFrom() can be defined: // ... vector<int> Network::PathFrom(int i, int j, vector<int> beenTo) const { vector<int> result; result.push_back(i); beenTo.push_back(i); if (myLinks[i][j]) // base case { result.push_back(j); beenTo.push_back(j); } // ... Defining PathFrom() (Ct’d) } // ... else // induction step { for (int v = 0; v < mySize; v++) { if (myLinks[i][v] && find(beenTo.begin(), beenTo.end(), v) == beenTo.end()) { vector<int> temp = PathFrom(v, j, beenTo); if (temp.size() > 1) { for (int k = 0; k < temp.size(); k++) result.push_back(temp[k]); break; } } } } return result; Class Members Our final declaration of Network is thus as follows: // Network.h // ... // Directives omitted class Network { public: Network(const string & fileName); int Size() const; bool HasComputer(int id) const; bool HasLink(int i, int j) const; vector<int> RouteFrom(int i, int j) const; private: vector<int> PathFrom(int i, int j, vector<int> visited) const; int mySize; // number of computers typedef vector<bool> Row; vector<Row> myLinks; // adjacency matrix }; Discussion PathFrom() is not very efficient, and the path it returns may not be the shortest path from i to j. The graph (a set of nodes and a set of edges connecting them) is often used to model networks. Efficient solutions have been devised for many graphtheory problems (e.g., the shortest path problem), providing ready-made solutions to the corresponding networking problems. Summary We have barely scratched the surface of C++! C++ is an incredibly rich programming language, that lets the programmer specifiy precisely what he or she wishes the computer to do. C++ provides many other libraries, containing more ready-made solutions to common problems. Continue on to the next course and learn about more features of the C++ programming language!