## Designing and Implementing a Graph Class

NetworkX is a Python library for graph processing. Recall that an undirected graph is a set of vertices (which may contain labels) and a set of edges (which may contain weights) that connect a subset of those vertices together.

For this exercise, you will build a design and implement a Graph class that:

1. Keeps track of the current number of edges in the graph.

2. Keeps a 10x10 adjacency matrix using a 2-D NumPy array initially containing all zeros. The entries in the ith row and jth column and the jth row and ith column are set to 1 if an edge exists between node i and node j.

3. Has a method add_edge() that takes two vertices (integers from 0-9) and sets the (i, j) and (j, i) entries of the adjacency matrix to 1, and updates the edge count

4. Has a method degree() that takes a vertex (an integer from 0-9) and returns its degree (the number of edges incident to that vertex)

## Using While Loop to Prompt Input

Your main() method should use a while loop to prompt a user to input an edge (a pair of integers from 0-9 separated by a space, ex: "3 8") until a user enters a "q" to quit the program. Each time a valid pair of vertices is entered by the user you should add the edge to the graph by updating the adjacency matrix and update its edge count. Once the user requests to exit the program, your code should output the degree of all vertices (including zeros for nodes that technically weren't inserted). Your code should also handle (raise and except) input errors in two ways using custom exception classes:

1. If the user provides an integer that is not between 0 and 9, raise a "VertexOutOfBoundsException" and handle it by printing "Vertex out of bounds." and a 'pass' statement and prompt the user again.

2. If the user provides a single integer, rather than a pair, raise a "SelfLoopException" and handle it by printing "Self-loops are not permitted." and a 'pass' statement and prompt the user again