I am fairly new to Python and it took me hours to figure out what I can do with no success. I am trying an example in plotting from https://jupyter.brynmawr.edu/services/public/dblank/jupyter.cs/FLAIRS-2015/TSPv3.ipynb#Python-and-iPython-Notebook:-Preliminaries. In the section on "Plotting Tours", as labeled as cell 15,16,17,18 and maybe more. The function for plot_tour and plot_lines are using map() and I read that in Python 3 it's a generator instead of a list. This made it confusing so is there any way around this to output the plot? which possibly not using map(). Thank you so much in advance.
First plot code:
def plot_tour(tour):
"Plot the cities as circles and the tour as lines between them."
plot_lines(list(tour) + [tour[0]])
def plot_lines(points, style='bo-'):
"Plot lines to connect a series of points."
plt.plot(map(X, points), map(Y, points), style)
plt.axis('scaled'); plt.axis('off')
plot_tour(alltours_tsp(Cities(8)))
This is the error im getting:
---------------------------------------------------------------------------
RuntimeError Traceback (most recent call last)
Input In [18], in <cell line: 1>()
----> 1 plot_tour(alltours_tsp(Cities(8)))
Input In [17], in plot_tour(tour)
1 def plot_tour(tour):
2 "Plot the cities as circles and the tour as lines between them."
----> 3 plot_lines(list(tour) + [tour[0]])
Input In [17], in plot_lines(points, style)
5 def plot_lines(points, style='bo-'):
6 "Plot lines to connect a series of points."
----> 7 plt.plot(map(X, points), map(Y, points), style)
8 plt.axis('scaled'); plt.axis('off')
File ~\anaconda3\lib\site-packages\matplotlib\pyplot.py:2757, in plot(scalex, scaley, data, *args, **kwargs)
2755 @_copy_docstring_and_deprecators(Axes.plot)
2756 def plot(*args, scalex=True, scaley=True, data=None, **kwargs):
-> 2757 return gca().plot(
2758 *args, scalex=scalex, scaley=scaley,
2759 **({"data": data} if data is not None else {}), **kwargs)
File ~\anaconda3\lib\site-packages\matplotlib\axes\_axes.py:1632, in Axes.plot(self, scalex, scaley, data, *args, **kwargs)
1390 """
1391 Plot y versus x as lines and/or markers.
1392
(...)
1629 (``'green'``) or hex strings (``'#008000'``).
1630 """
1631 kwargs = cbook.normalize_kwargs(kwargs, mlines.Line2D)
-> 1632 lines = [*self._get_lines(*args, data=data, **kwargs)]
1633 for line in lines:
1634 self.add_line(line)
File ~\anaconda3\lib\site-packages\matplotlib\axes\_base.py:312, in _process_plot_var_args.__call__(self, data, *args, **kwargs)
310 this += args[0],
311 args = args[1:]
--> 312 yield from self._plot_args(this, kwargs)
File ~\anaconda3\lib\site-packages\matplotlib\axes\_base.py:493, in _process_plot_var_args._plot_args(self, tup, kwargs, return_kwargs)
490 x, y = index_of(xy[-1])
492 if self.axes.xaxis is not None:
--> 493 self.axes.xaxis.update_units(x)
494 if self.axes.yaxis is not None:
495 self.axes.yaxis.update_units(y)
File ~\anaconda3\lib\site-packages\matplotlib\axis.py:1443, in Axis.update_units(self, data)
1437 def update_units(self, data):
1438 """
1439 Introspect *data* for units converter and update the
1440 axis.converter instance if necessary. Return *True*
1441 if *data* is registered for unit conversion.
1442 """
-> 1443 converter = munits.registry.get_converter(data)
1444 if converter is None:
1445 return False
File ~\anaconda3\lib\site-packages\matplotlib\units.py:206, in Registry.get_converter(self, x)
202 else:
203 # ... and avoid infinite recursion for pathological iterables for
204 # which indexing returns instances of the same iterable class.
205 if type(first) is not type(x):
--> 206 return self.get_converter(first)
207 return None
File ~\anaconda3\lib\site-packages\matplotlib\units.py:199, in Registry.get_converter(self, x)
197 pass
198 try: # If cache lookup fails, look up based on first element...
--> 199 first = cbook.safe_first_element(x)
200 except (TypeError, StopIteration):
201 pass
File ~\anaconda3\lib\site-packages\matplotlib\cbook\__init__.py:1678, in safe_first_element(obj)
1676 except TypeError:
1677 pass
-> 1678 raise RuntimeError("matplotlib does not support generators "
1679 "as input")
1680 return next(iter(obj))
RuntimeError: matplotlib does not support generators as input
Next plot code:
def plot_tsp(algorithm, cities):
"Apply a TSP algorithm to cities, plot the resulting tour, and print information."
# Find the solution and time how long it takes
t0 = time.clock()
tour = algorithm(cities)
t1 = time.clock()
assert valid_tour(tour, cities)
plot_tour(tour); plt.show()
print("{} city tour with length {:.1f} in {:.3f} secs for {}"
.format(len(tour), tour_length(tour), t1 - t0, algorithm.__name__))
def valid_tour(tour, cities):
"Is tour a valid tour for these cities?"
return set(tour) == set(cities) and len(tour) == len(cities)
plot_tsp(alltours_tsp, Cities(8))
This is the error im getting:
---------------------------------------------------------------------------
RuntimeError Traceback (most recent call last)
Input In [23], in <cell line: 1>()
----> 1 plot_tsp(alltours_tsp, Cities(8))
Input In [22], in plot_tsp(algorithm, cities)
6 t1 = time.perf_counter()
7 assert valid_tour(tour, cities)
----> 8 plot_tour(tour); plt.show()
9 print("{} city tour with length {:.1f} in {:.3f} secs for {}"
10 .format(len(tour), tour_length(tour), t1 - t0, algorithm.__name__))
Input In [17], in plot_tour(tour)
1 def plot_tour(tour):
2 "Plot the cities as circles and the tour as lines between them."
----> 3 plot_lines(list(tour) + [tour[0]])
Input In [17], in plot_lines(points, style)
5 def plot_lines(points, style='bo-'):
6 "Plot lines to connect a series of points."
----> 7 plt.plot(map(X, points), map(Y, points), style)
8 plt.axis('scaled'); plt.axis('off')
File ~\anaconda3\lib\site-packages\matplotlib\pyplot.py:2757, in plot(scalex, scaley, data, *args, **kwargs)
2755 @_copy_docstring_and_deprecators(Axes.plot)
2756 def plot(*args, scalex=True, scaley=True, data=None, **kwargs):
-> 2757 return gca().plot(
2758 *args, scalex=scalex, scaley=scaley,
2759 **({"data": data} if data is not None else {}), **kwargs)
File ~\anaconda3\lib\site-packages\matplotlib\axes\_axes.py:1632, in Axes.plot(self, scalex, scaley, data, *args, **kwargs)
1390 """
1391 Plot y versus x as lines and/or markers.
1392
(...)
1629 (``'green'``) or hex strings (``'#008000'``).
1630 """
1631 kwargs = cbook.normalize_kwargs(kwargs, mlines.Line2D)
-> 1632 lines = [*self._get_lines(*args, data=data, **kwargs)]
1633 for line in lines:
1634 self.add_line(line)
File ~\anaconda3\lib\site-packages\matplotlib\axes\_base.py:312, in _process_plot_var_args.__call__(self, data, *args, **kwargs)
310 this += args[0],
311 args = args[1:]
--> 312 yield from self._plot_args(this, kwargs)
File ~\anaconda3\lib\site-packages\matplotlib\axes\_base.py:493, in _process_plot_var_args._plot_args(self, tup, kwargs, return_kwargs)
490 x, y = index_of(xy[-1])
492 if self.axes.xaxis is not None:
--> 493 self.axes.xaxis.update_units(x)
494 if self.axes.yaxis is not None:
495 self.axes.yaxis.update_units(y)
File ~\anaconda3\lib\site-packages\matplotlib\axis.py:1443, in Axis.update_units(self, data)
1437 def update_units(self, data):
1438 """
1439 Introspect *data* for units converter and update the
1440 axis.converter instance if necessary. Return *True*
1441 if *data* is registered for unit conversion.
1442 """
-> 1443 converter = munits.registry.get_converter(data)
1444 if converter is None:
1445 return False
File ~\anaconda3\lib\site-packages\matplotlib\units.py:206, in Registry.get_converter(self, x)
202 else:
203 # ... and avoid infinite recursion for pathological iterables for
204 # which indexing returns instances of the same iterable class.
205 if type(first) is not type(x):
--> 206 return self.get_converter(first)
207 return None
File ~\anaconda3\lib\site-packages\matplotlib\units.py:199, in Registry.get_converter(self, x)
197 pass
198 try: # If cache lookup fails, look up based on first element...
--> 199 first = cbook.safe_first_element(x)
200 except (TypeError, StopIteration):
201 pass
File ~\anaconda3\lib\site-packages\matplotlib\cbook\__init__.py:1678, in safe_first_element(obj)
1676 except TypeError:
1677 pass
-> 1678 raise RuntimeError("matplotlib does not support generators "
1679 "as input")
1680 return next(iter(obj))
RuntimeError: matplotlib does not support generators as input
I suspect this notebook was made for an earlier version of python and packages. That's why you're having so many problems. I recommend tracking down some specifications of what python and package versions were used in the course. However, I did get a lot of the notebook to run with these changes:
def plot_lines(points, style='bo-'):
"Plot lines to connect a series of points."
plt.plot(list(map(X, points)), list(map(Y, points)), style)
plt.axis('scaled'); plt.axis('off')
Later on, time.time()
should be replaced with perf_counter()
.
def plot_tsp(algorithm, cities):
"Apply a TSP algorithm to cities, plot the resulting tour, and print information."
# Find the solution and time how long it takes
t0 = time.perf_counter()
tour = algorithm(cities)
t1 = time.perf_counter()
assert valid_tour(tour, cities)
plot_tour(tour); plt.show()
print("{} city tour with length {:.1f} in {:.3f} secs for {}"
.format(len(tour), tour_length(tour), t1 - t0, algorithm.__name__))
def benchmark(function, inputs):
"Run function on all the inputs; return pair of (average_time_taken, results)."
t0 = time.perf_counter()
results = map(function, inputs)
t1 = time.perf_counter()
average_time = (t1 - t0) / len(inputs)
return (average_time, results)
There are other changes that have to be made further down the notebook, however. I had problems with the benchmark
function and the USA big map
url request. You should really consider digging the package versions though.