1

Hie, I am trying to use the python module grinpy, and I am using jupyter notebook if that helps. I have written the following code:

import grinpy as gp
G = gp.petersen_graph()
a = gp.chromatic_number(G)
print(a)

Now a should be a number, so I just want it to print a number, but it seems to print a lot of other things as a result of the 3rd line, followed by the number in the 4th line.

How can I block it from printing the unwanted stuff?

Maybe it's also worth noting that I intend to use this module in a similar way in larger programs.

Thank you!

Here is the output:

Welcome to the CBC MILP Solver 
Version: 2.10.3 
Build Date: Dec 15 2019 

command line - /opt/homebrew/lib/python3.9/site-packages/pulp/solverdir/cbc/osx/64/cbc /var/folders/wb/tmprjpmd5vd6zkhfy1sbs57r0000gn/T/37918f7940534834b5bb691051ec13cd-pulp.mps timeMode elapsed branch printingOptions all solution /var/folders/wb/tmprjpmd5vd6zkhfy1sbs57r0000gn/T/37918f7940534834b5bb691051ec13cd-pulp.sol (default strategy 1)
At line 2 NAME          MODEL
At line 3 ROWS
At line 265 COLUMNS
At line 1096 RHS
At line 1357 BOUNDS
At line 1468 ENDATA
Problem MODEL has 260 rows, 110 columns and 600 elements
Coin0008I MODEL read with 0 errors
Option for timeMode changed from cpu to elapsed
Continuous objective value is 1 - 0.00 seconds
Cgl0003I 0 fixed, 0 tightened bounds, 139 strengthened rows, 0 substitutions
Cgl0003I 0 fixed, 0 tightened bounds, 91 strengthened rows, 0 substitutions
Cgl0003I 0 fixed, 0 tightened bounds, 20 strengthened rows, 0 substitutions
Cgl0004I processed model has 160 rows, 110 columns (110 integer (110 of which binary)) and 550 elements
Cutoff increment increased from 1e-05 to 0.9999
Cbc0045I 10 integer variables out of 110 objects (110 integer) have cost of 1 - high priority
Cbc0045I branch on satisfied N create fake objective Y random cost Y
Cbc0038I Initial state - 20 integers unsatisfied sum - 10
Cbc0038I Pass   1: suminf.   10.00000 (20) obj. 2 iterations 15
Cbc0038I Pass   2: suminf.   10.00000 (20) obj. 2 iterations 15
Cbc0038I Pass   3: suminf.    0.00000 (0) obj. 7 iterations 111
Cbc0038I Solution found of 7
Cbc0038I Rounding solution of 4 is better than previous of 7

Cbc0038I Before mini branch and bound, 81 integers at bound fixed and 0 continuous
Cbc0038I Full problem 160 rows 110 columns, reduced to 38 rows 20 columns
Cbc0038I Mini branch and bound did not improve solution (0.01 seconds)
Cbc0038I Round again with cutoff of 2.90009
Cbc0038I Pass   4: suminf.   10.00000 (20) obj. 2 iterations 0
Cbc0038I Pass   5: suminf.   10.00000 (20) obj. 2 iterations 16
Cbc0038I Pass   6: suminf.    2.29793 (21) obj. 2.90009 iterations 100
Cbc0038I Pass   7: suminf.    1.39874 (24) obj. 2.90009 iterations 51
Cbc0038I Pass   8: suminf.    8.50000 (17) obj. 2.5 iterations 76
Cbc0038I Pass   9: suminf.    8.50000 (17) obj. 2.5 iterations 40
Cbc0038I Pass  10: suminf.    1.69847 (17) obj. 2.90009 iterations 66
Cbc0038I Pass  11: suminf.    1.39874 (24) obj. 2.90009 iterations 56
Cbc0038I Pass  12: suminf.    1.39874 (24) obj. 2.90009 iterations 69
Cbc0038I Pass  13: suminf.    1.39874 (24) obj. 2.90009 iterations 37
Cbc0038I Pass  14: suminf.   10.00000 (20) obj. 2 iterations 52
Cbc0038I Pass  15: suminf.   10.00000 (20) obj. 2 iterations 12
Cbc0038I Pass  16: suminf.   10.00000 (20) obj. 2 iterations 57
Cbc0038I Pass  17: suminf.    1.39874 (24) obj. 2.90009 iterations 66
Cbc0038I Pass  18: suminf.    1.39874 (24) obj. 2.90009 iterations 50
Cbc0038I Pass  19: suminf.    8.50000 (17) obj. 2.5 iterations 72
Cbc0038I Pass  20: suminf.    8.50000 (17) obj. 2.5 iterations 17
Cbc0038I Pass  21: suminf.    1.69847 (17) obj. 2.90009 iterations 55
Cbc0038I Pass  22: suminf.    1.39874 (24) obj. 2.90009 iterations 46
Cbc0038I Pass  23: suminf.    1.89829 (18) obj. 2.90009 iterations 77
Cbc0038I Pass  24: suminf.    1.39874 (24) obj. 2.90009 iterations 38
Cbc0038I Pass  25: suminf.    1.39874 (24) obj. 2.90009 iterations 64
Cbc0038I Pass  26: suminf.    1.39874 (24) obj. 2.90009 iterations 31
Cbc0038I Pass  27: suminf.    8.50000 (17) obj. 2.5 iterations 77
Cbc0038I Pass  28: suminf.    8.50000 (17) obj. 2.5 iterations 7
Cbc0038I Pass  29: suminf.    1.69847 (17) obj. 2.90009 iterations 71
Cbc0038I Pass  30: suminf.    1.39874 (24) obj. 2.90009 iterations 59
Cbc0038I Pass  31: suminf.    1.49865 (25) obj. 2.90009 iterations 79
Cbc0038I Pass  32: suminf.    1.39874 (24) obj. 2.90009 iterations 35
Cbc0038I Pass  33: suminf.    2.09811 (19) obj. 2.90009 iterations 77
Cbc0038I Pass  34: suminf.    1.39874 (24) obj. 2.90009 iterations 31
Cbc0038I Pass  35: suminf.    8.50000 (17) obj. 2.5 iterations 95
Cbc0038I Pass  36: suminf.    8.50000 (17) obj. 2.5 iterations 19
Cbc0038I Pass  37: suminf.    1.69847 (17) obj. 2.90009 iterations 65
Cbc0038I Pass  38: suminf.    1.39874 (24) obj. 2.90009 iterations 46
Cbc0038I Pass  39: suminf.    1.49865 (24) obj. 2.90009 iterations 55
Cbc0038I Pass  40: suminf.    1.39874 (24) obj. 2.90009 iterations 31
Cbc0038I Pass  41: suminf.    8.29973 (19) obj. 2.90009 iterations 82
Cbc0038I Pass  42: suminf.    2.09811 (19) obj. 2.90009 iterations 27
Cbc0038I Pass  43: suminf.    1.39874 (24) obj. 2.90009 iterations 28
Cbc0038I Pass  44: suminf.    8.50000 (17) obj. 2.5 iterations 58
Cbc0038I Pass  45: suminf.    8.50000 (17) obj. 2.5 iterations 18
Cbc0038I Pass  46: suminf.    1.69847 (17) obj. 2.90009 iterations 64
Cbc0038I Pass  47: suminf.    1.39874 (24) obj. 2.90009 iterations 50
Cbc0038I Pass  48: suminf.   10.00000 (20) obj. 2 iterations 41
Cbc0038I Pass  49: suminf.   10.00000 (20) obj. 2 iterations 24
Cbc0038I Pass  50: suminf.   10.00000 (20) obj. 2 iterations 30
Cbc0038I Pass  51: suminf.    2.09811 (21) obj. 2.90009 iterations 73
Cbc0038I Pass  52: suminf.    1.39874 (24) obj. 2.90009 iterations 58
Cbc0038I Pass  53: suminf.    1.39874 (24) obj. 2.90009 iterations 74
Cbc0038I Pass  54: suminf.    1.39874 (24) obj. 2.90009 iterations 30
Cbc0038I Pass  55: suminf.   10.00000 (20) obj. 2 iterations 68
Cbc0038I Pass  56: suminf.   10.00000 (20) obj. 2 iterations 32
Cbc0038I Pass  57: suminf.   10.00000 (20) obj. 2 iterations 29
Cbc0038I Pass  58: suminf.    7.29973 (28) obj. 2.90009 iterations 80
Cbc0038I Pass  59: suminf.    1.89829 (18) obj. 2.90009 iterations 62
Cbc0038I Pass  60: suminf.    1.39874 (24) obj. 2.90009 iterations 28
Cbc0038I Pass  61: suminf.    1.39874 (24) obj. 2.90009 iterations 58
Cbc0038I Pass  62: suminf.    1.39874 (24) obj. 2.90009 iterations 23
Cbc0038I Pass  63: suminf.    8.50000 (17) obj. 2.5 iterations 68
Cbc0038I Pass  64: suminf.    8.50000 (17) obj. 2.5 iterations 17
Cbc0038I Pass  65: suminf.    1.69847 (17) obj. 2.90009 iterations 54
Cbc0038I Pass  66: suminf.    1.39874 (24) obj. 2.90009 iterations 34
Cbc0038I Pass  67: suminf.    1.39874 (24) obj. 2.90009 iterations 69
Cbc0038I Pass  68: suminf.    1.39874 (24) obj. 2.90009 iterations 21
Cbc0038I Pass  69: suminf.   10.00000 (20) obj. 2 iterations 75
Cbc0038I Pass  70: suminf.   10.00000 (20) obj. 2 iterations 26
Cbc0038I Pass  71: suminf.   10.00000 (20) obj. 2 iterations 9
Cbc0038I Pass  72: suminf.    2.89739 (24) obj. 2.90009 iterations 80
Cbc0038I Pass  73: suminf.    1.39874 (24) obj. 2.90009 iterations 52
Cbc0038I Pass  74: suminf.    3.49685 (25) obj. 2.90009 iterations 78
Cbc0038I Pass  75: suminf.    1.39874 (24) obj. 2.90009 iterations 25
Cbc0038I Pass  76: suminf.    8.50000 (17) obj. 2.5 iterations 54
Cbc0038I Pass  77: suminf.    8.50000 (17) obj. 2.5 iterations 16
Cbc0038I Pass  78: suminf.    1.69847 (17) obj. 2.90009 iterations 48
Cbc0038I Pass  79: suminf.    1.39874 (24) obj. 2.90009 iterations 51
Cbc0038I Pass  80: suminf.    2.49775 (21) obj. 2.90009 iterations 56
Cbc0038I Pass  81: suminf.    1.39874 (24) obj. 2.90009 iterations 46
Cbc0038I Pass  82: suminf.    1.39874 (24) obj. 2.90009 iterations 97
Cbc0038I Pass  83: suminf.    1.39874 (24) obj. 2.90009 iterations 35
Cbc0038I Pass  84: suminf.   10.00000 (20) obj. 2 iterations 24
Cbc0038I Pass  85: suminf.   10.00000 (20) obj. 2 iterations 12
Cbc0038I Pass  86: suminf.   10.00000 (20) obj. 2 iterations 26
Cbc0038I Pass  87: suminf.   10.90009 (24) obj. 2.90009 iterations 82
Cbc0038I Pass  88: suminf.   11.80018 (32) obj. 2.90009 iterations 62
Cbc0038I Pass  89: suminf.    2.49775 (24) obj. 2.90009 iterations 70
Cbc0038I Pass  90: suminf.    1.39874 (24) obj. 2.90009 iterations 52
Cbc0038I Pass  91: suminf.    1.39874 (24) obj. 2.90009 iterations 59
Cbc0038I Pass  92: suminf.    1.39874 (24) obj. 2.90009 iterations 23
Cbc0038I Pass  93: suminf.    1.39874 (24) obj. 2.90009 iterations 84
Cbc0038I Pass  94: suminf.    1.39874 (24) obj. 2.90009 iterations 33
Cbc0038I Pass  95: suminf.    9.50000 (19) obj. 2.5 iterations 62
Cbc0038I Pass  96: suminf.    8.00000 (25) obj. 2.5 iterations 13
Cbc0038I Pass  97: suminf.    1.89829 (25) obj. 2.90009 iterations 46
Cbc0038I Pass  98: suminf.    1.39874 (24) obj. 2.90009 iterations 34
Cbc0038I Pass  99: suminf.    1.39874 (24) obj. 2.90009 iterations 50
Cbc0038I Pass 100: suminf.    1.39874 (24) obj. 2.90009 iterations 36
Cbc0038I Pass 101: suminf.    8.50000 (17) obj. 2.5 iterations 63
Cbc0038I Pass 102: suminf.    8.50000 (17) obj. 2.5 iterations 23
Cbc0038I Pass 103: suminf.    1.39874 (24) obj. 2.90009 iterations 64
Cbc0038I No solution found this major pass
Cbc0038I Before mini branch and bound, 8 integers at bound fixed and 0 continuous
Cbc0038I Full problem 160 rows 110 columns, reduced to 150 rows 102 columns - 6 fixed gives 83, 62 - ok now
Cbc0038I Mini branch and bound did not improve solution (0.06 seconds)
Cbc0038I After 0.06 seconds - Feasibility pump exiting with objective of 4 - took 0.05 seconds
Cbc0012I Integer solution of 4 found by feasibility pump after 0 iterations and 0 nodes (0.06 seconds)
Cbc0012I Integer solution of 3 found by DiveCoefficient after 0 iterations and 0 nodes (0.06 seconds)
Cbc0038I Full problem 160 rows 110 columns, reduced to 30 rows 10 columns
Cbc0031I 9 added rows had average density of 17.555556
Cbc0013I At root node, 18 cuts changed objective from 2 to 2.0625 in 8 passes
Cbc0014I Cut generator 0 (Probing) - 0 row cuts average 0.0 elements, 0 column cuts (0 active)  in 0.002 seconds - new frequency is -100
Cbc0014I Cut generator 1 (Gomory) - 25 row cuts average 79.2 elements, 0 column cuts (0 active)  in 0.001 seconds - new frequency is 1
Cbc0014I Cut generator 2 (Knapsack) - 0 row cuts average 0.0 elements, 0 column cuts (0 active)  in 0.002 seconds - new frequency is -100
Cbc0014I Cut generator 3 (Clique) - 0 row cuts average 0.0 elements, 0 column cuts (0 active)  in 0.000 seconds - new frequency is -100
Cbc0014I Cut generator 4 (MixedIntegerRounding2) - 0 row cuts average 0.0 elements, 0 column cuts (0 active)  in 0.000 seconds - new frequency is -100
Cbc0014I Cut generator 5 (FlowCover) - 0 row cuts average 0.0 elements, 0 column cuts (0 active)  in 0.000 seconds - new frequency is -100
Cbc0014I Cut generator 6 (TwoMirCuts) - 28 row cuts average 58.3 elements, 0 column cuts (0 active)  in 0.005 seconds - new frequency is -100
Cbc0014I Cut generator 7 (ZeroHalf) - 60 row cuts average 15.7 elements, 0 column cuts (0 active)  in 0.028 seconds - new frequency is 1
Cbc0001I Search completed - best objective 3, took 545 iterations and 0 nodes (0.13 seconds)
Cbc0035I Maximum depth 0, 0 variables fixed on reduced cost
Cuts at root node changed objective from 2 to 2.0625
Probing was tried 8 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.002 seconds)
Gomory was tried 8 times and created 25 cuts of which 0 were active after adding rounds of cuts (0.001 seconds)
Knapsack was tried 8 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.002 seconds)
Clique was tried 8 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
MixedIntegerRounding2 was tried 8 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
FlowCover was tried 8 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
TwoMirCuts was tried 8 times and created 28 cuts of which 0 were active after adding rounds of cuts (0.005 seconds)
ZeroHalf was tried 8 times and created 60 cuts of which 0 were active after adding rounds of cuts (0.028 seconds)

Result - Optimal solution found

Objective value:                3.00000000
Enumerated nodes:               0
Total iterations:               545
Time (CPU seconds):             0.11
Time (Wallclock seconds):       0.13

Option for printingOptions changed from normal to all
Total time (CPU seconds):       0.12   (Wallclock seconds):       0.13

3

As you can see, there is a number 3 at the bottom, which is from the print command. So I'm asking how to get rid of the rest of this.

  • You might find some answers [here.](https://stackoverflow.com/questions/8391411/how-to-block-calls-to-print) – IncognitoIdentity Jun 20 '23 at 17:53
  • Depends on how it's printing it. Is it using the `logging` module, the `warnings` module, or just writing to standard output or standard error directly? – chepner Jun 20 '23 at 17:54
  • I would suggest that you look at the result of `help(gp.chromatic_number)`. There's probably an optional argument that allows you to prevent the method from printing – Ben Grossmann Jun 20 '23 at 17:54
  • Never mind: after checking the source code on github, it appears that there is no such optional argument – Ben Grossmann Jun 20 '23 at 17:57
  • @chepner Not sure but I tihnk it's standard output – Keven McFlurry Jun 20 '23 at 17:58
  • I scanned through the source code, I don't see anything that prints or logs. In general, libraries like this don't do any printing of their own. – Barmar Jun 20 '23 at 18:03
  • @Barmar Is this an issue with my jupyter setup then, do you think? – Keven McFlurry Jun 20 '23 at 18:04
  • What are the other things it's printing? Can you add the output to the question (post it as formatted text, not a screenshot). – Barmar Jun 20 '23 at 18:05
  • @Barmar Actually there are quite a few python modules that print unwanted stuff whenever they're used. For instance, there are several linear programming solvers that print "thank you for using ((name of the solver))" whenever their `solve` function is called. – Stef Jun 20 '23 at 18:07
  • Hie @Barmar I edited and added the extraneous output – Keven McFlurry Jun 20 '23 at 18:08
  • grinpy imports the pulp library, it looks like it's coming from there. – Barmar Jun 20 '23 at 18:16
  • See https://github.com/coin-or/pulp/issues/351 It looks like `grinpy` isn't passing the `msg=False` option when calling pulp. – Barmar Jun 20 '23 at 18:19
  • Related: [How to disable the calculations log of pulp?](https://stackoverflow.com/questions/38237449/how-to-disable-the-calculations-log-of-pulp) – Stef Jun 20 '23 at 18:20
  • @Barmar Ah, this makes sense. What should I do to my code to fix it? I only know very basic Python. Thank you! – Keven McFlurry Jun 20 '23 at 18:25
  • 2
    the problem isn't in your code. This is something the grinpy programmers need to fix there. – Barmar Jun 20 '23 at 18:27
  • Try the link in @IncognitoIdentity's comment, it shows how you can temporarily hide output. – Barmar Jun 20 '23 at 18:28
  • @Barmar I tried a few of the answers in this comment and none of them worked :( please can someone run the code and find a way that works? Thank you so much – Keven McFlurry Jun 20 '23 at 18:37
  • There's easier ways because OP wrote " I am using jupyter notebook". Separate out the first three lines from the last one. For your first three lines, add at the top of the cell `%%capture` and install wurlizter and incorporate using it as I suggest in my answer. Run the two cells. Based on [here](https://stackoverflow.com/a/23692951/8508004) and [here](https://stackoverflow.com/a/69689611/8508004). – Wayne Jun 20 '23 at 19:12

1 Answers1

1

First add a new cell and run %pip install wurlitzer in that cell. (Once it is installed where you are working, you can delete the cell if you'd like.)

Separate out the current provided code into two sections and add the use of wurlitzer to encompass everything but the print() so that the noisy parts are under control of the with context manager there:

Notebook cell:

from wurlitzer import pipes
with pipes() as (out, err):
   import grinpy as gp
   G = gp.petersen_graph()
   a = gp.chromatic_number(G)
print(a)

Wurlitzer is necessary here because the main offending noisy output is C-level stdout/stderr pipes that the commonly-used %%capture (see section below) will fail to suppress. See here for more on wurlitzer for this kind of use.

Sometimes in my tests, I saw a warning the first time I invoked wurlitzer in that manner. You can perhaps add the use of %%capture if that is a consistent issue and you don't want that warning showing at all. In addition though, you have to move the print(a) to another cell, or repeat it or the %%capture cell magic will block it. The addition of %%capture as the first line of the cell, in conjunction with wurlizter, insures even that warning is silenced. See more about the use of the %%capture cell magic in the next section. This is how you can combine to remove any warning from this process, too:

First cell:

%%capture
from wurlitzer import pipes
with pipes() as (out, err):
   import grinpy as gp
   G = gp.petersen_graph()
   a = gp.chromatic_number(G)

Second cell:

print(a)

If it had just been a problem with normal Python & shell-based, noisy output then the addition of %%capture cell magic to the first line of the first cell alone would have been enough, sort of like so:

First cell:

%%capture
import grinpy as gp
G = gp.petersen_graph()
a = gp.chromatic_number(G)

Second cell:

print(a)

Use of %%capture cell magic to suppress typical output is based on answer to 'How do you suppress output in Jupyter running IPython?'.

But it isn't sufficient here; wurlitzer use is necessary in the case of the reproducible code provided by OP.

Wayne
  • 6,607
  • 8
  • 36
  • 93
  • Thank you so much! Haven't tried this yet but I plan on running chromatic_number and similar commands (all of which have the same issue) a lot in a program. Is there a way I can avoid making loads of different cells? Sorry if I'm misunderstanding something in your answer – Keven McFlurry Jun 20 '23 at 19:52
  • I updated it to not use two cells if you just are looking to suppress the main noise you posted about. You'll see you just need to indent within the `with` statement the parts to suppress and then you can put the `print()` in the same cell by not indenting it in line with the with. – Wayne Jun 21 '23 at 03:51