Dear All,
in a ticket (#21254) I recently created with Dylan Rupel I need to explore a
(possibly) infinite n-regular tree in a breath-first search. The way it is
implemented right now is via iterators. I am writing to you to ask if there
is a preferred way to deal with user interaction and KeyboardInterrupt.

At the moment the init function of :class:`ClusterAlgebra` calls
:meth:`reset_exploring_iterator` that creates an instance of :meth:`seeds` and
stores it in an internal var ``_sd_iter``. The methods that need to explore
the tree just call ``next`` on this iterator till they get the data they are
looking for. This process is potentially never ending. For this reason the
user may specify a maximum depth at which to stop.

Since this iterator is computationally intense, it easy to imagine that
users will tend to start searching but change their mind in mid computation
and send an interrupt. This, unfortunately, leaves ``_sd_iter`` in a
corrupted state and all future calls to it will result in a StopIteration.

At the moment we have a warning in the docstring of each method accessing
_sd_iter to explain that after sending a KeyboardInterrupt the user needs to
call :meth:`reset_exploring_iterator`. Do you think we should instead catch
the interrupt, reset the iterator and then raise it again like this?


@@ -1999,12 +1999,17 @@ class ClusterAlgebra(Parent):
             sage: len(A.g_vectors_so_far())
             14
         """
-        while self._explored_depth <= depth:
-            try:
-                seed = next(self._sd_iter)
-                self._explored_depth = seed.depth()
-            except StopIteration:
-                break
+        try:
+            while self._explored_depth <= depth:
+                try:
+                    seed = next(self._sd_iter)
+                    self._explored_depth = seed.depth()
+                except StopIteration:
+                    break
+        except KeyboardInterrupt:
+            print("Got a KeyboardInterrupt, cleaning up before returning.")
+            self.reset_exploring_iterator()
+            raise KeyboardInterrupt

The advantage of this is that the user does not have to remember an extra
(unnatural?) step. The drawback is that he/she looses any customization that
may have been made by a previous call to :meth:`reset_exploring_iterator`.


On a related topic. In the situation just described, the next exploration
will have to begin from the root of the tree resulting in a lot of wasted
effort. Is there any way around this? Sending a node of the tree back to the
iterator does not seem useful because of the breath-first search.

Thanks
S.


-- 
You received this message because you are subscribed to the Google Groups 
"sage-devel" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sage-devel+unsubscr...@googlegroups.com.
To post to this group, send email to sage-devel@googlegroups.com.
Visit this group at https://groups.google.com/group/sage-devel.
For more options, visit https://groups.google.com/d/optout.

Reply via email to