coin-or / GrUMPy

A Python library for visualizing algorithms for solving mathematical optimization problems.
Eclipse Public License 1.0
63 stars 22 forks source link

Problems generating the tree image #15

Open jwalteros opened 4 years ago

jwalteros commented 4 years ago

I tried to run the BBVis.py example to get a grasp of the tree visualization feature, but I am getting the following error from line 27

gnuplot_image = io.StringIO(bt.GenerateTreeImage())

I am getting:

File "/home/totalunimodular/.local/lib/python3.8/site-packages/coinor/grumpy/BBTree.py", line 1467, in GenerateTreeImage return gp.communicate(input=data)[0] File "/usr/lib/python3.8/subprocess.py", line 1024, in communicate stdout, stderr = self._communicate(input, endtime, timeout) File "/usr/lib/python3.8/subprocess.py", line 1846, in _communicate input_view = memoryview(self._input) TypeError: memoryview: a bytes-like object is required, not 'str'

After a quick google search, it seems this may be a Python 2/Python 3 issue, but I am not sure how to address it. Any insights would be appreciated.

Thanks.

abdxyz commented 3 years ago

I got the same results as you. I also tried xdot. xdot 0.6 just can't be installed on python 3.8. If I use xdot 1.2, it will result the following error.

  File "/home/dxy/anaconda3/envs/test-cylp/lib/python3.7/site-packages/coinor/grumpy/BBTree.py", line 306, in display
    BinaryTree.display(self, pause = pause, wait_for_click = wait_for_click)
  File "/home/dxy/anaconda3/envs/test-cylp/lib/python3.7/site-packages/coinor/gimpy/graph.py", line 1761, in display
    window.set_dotcode(self.to_string())
  File "/home/dxy/anaconda3/envs/test-cylp/lib/python3.7/site-packages/xdot/ui/window.py", line 688, in set_dotcode
    if self.dotwidget.set_dotcode(dotcode, filename):
  File "/home/dxy/anaconda3/envs/test-cylp/lib/python3.7/site-packages/xdot/ui/window.py", line 145, in set_dotcode
    if self._set_dotcode(dotcode, filename, center=center):
  File "/home/dxy/anaconda3/envs/test-cylp/lib/python3.7/site-packages/xdot/ui/window.py", line 131, in _set_dotcode
    assert isinstance(dotcode, bytes)
AssertionErrorfile:

Process finished with exit code 1

If I set the mode to file, it will output a simple file like this

self.T.set_display_mode('file')
self.T.display()

graph

tkralphs commented 3 years ago

@jwalteros Sorry for not having responded to your initial report. There are definitely some issues in that part of the code, which uses gnuplot, since the upgrade to Python 3. It didn't look that easy to untangle and I never got back to it. What we should really be doing is using some more modern plotting program, such as matplotlib.

@abdxyz matplotlib can be used for displaying the trees produced in branch-and-bound, which are built using GiMPy. If you have a recent versions of GiMPy, you should be able to do

self.T.set_display_mode('matplotlib')
self.T.display()

to get an interactive graph that will update in the same window. It's not as nice as xdot, but works. I can't recall now what the current situation with xdot is. I believe I may have gotten it working, but you may have to get the source from Github.

jwalteros commented 3 years ago

Hi @tkralphs, no problem. I found an alternative that seems to work quite well and is easy to implement. I used the DiGraphimplementation of networkx to generate the tree, and then used the graphviz_layout tool to produce the image. I pretty much adapted the suggestion from this post. If that is Ok with you, I can perhaps fork the repo and add my implementation.

tkralphs commented 3 years ago

Sure, it would be good to have an additional implementation, but GrUMPy can already do essentially what you're suggesting, if I understand correctly, except the tree gets stored as a GiMPy graph object, instead of a networkx object.

I'm not sure it's clear, but there are actually two totally separate ways of visualizing trees, one in which we do the layout internally and use gnuplot in order to better control the exact position of the nodes and produce the pictures, and one using graphviz to just do the whole layout. I wanted to combine these, since using gnuplot was always pretty clunky and the graphs were pretty ugly. I never got around to figuring out how to force graphviz to put the nodes where I wanted them, though. I guess you are suggesting to tell networkx where to put the nodes based on what graphviz tells it. I suppose this could be an overall solution to unifying, although I'm hesitant to introduce a dependency on networkx.

Anyway, it would be interesting to see what you did and maybe after seeing it, we can figure out how to finally get rid of the dependence on gnuplot.