Repository: Pyomo/pyomo

Issue:
Bug in CBCplugin
I've spotted a bug in my implementation of: https://github.com/Pyomo/pyomo/pull/874

In `pyomo/solvers/plugins/solvers/CBCplugin.py`
Line 479 should read 
```python
optim_value = float(tokens[6])
```
Instead of 
```python
optim_value = float(tokens[6][:-1])
```

Shall I raise a PR to fix?


Discussion:
Yes, please open a PR.  Also please include (if possible) a test case that demonstrated the bug / exercises the solution.  Thank you!

Resolving patch:
diff --git a/pyomo/solvers/plugins/solvers/CBCplugin.py b/pyomo/solvers/plugins/solvers/CBCplugin.py
--- a/pyomo/solvers/plugins/solvers/CBCplugin.py
+++ b/pyomo/solvers/plugins/solvers/CBCplugin.py
@@ -476,7 +476,7 @@ def process_logfile(self):
                 elif n_tokens > 15 and tokens[1:3] == ('Partial', 'search') \
                         and tokens[4:6] == ('best', 'objective') and tokens[7:9] == ('(best', 'possible') \
                         and tokens[12] == 'iterations' and tokens[15] == 'nodes':
-                    optim_value = float(tokens[6][:-1])
+                    optim_value = float(tokens[6])
                     lower_bound = float(tokens[9][:-2])
                     results.solver.statistics.black_box.number_of_iterations = int(tokens[11])
                     nodes = int(tokens[14])


Test patch:
diff --git a/pyomo/solvers/tests/checks/data/cbc/fix_parsing_bug.out b/pyomo/solvers/tests/checks/data/cbc/fix_parsing_bug.out
new file mode 100644
--- /dev/null
+++ b/pyomo/solvers/tests/checks/data/cbc/fix_parsing_bug.out
@@ -0,0 +1,86 @@
+Solver command line: ['/Users/username/PycharmProjects/pyomo_cbc_return_handling/solvers/cbc/Darwin/cbc', '-randomCbcSeed', '42', '-randomSeed', '42', '-printingOptions', 'all', '-import', '/var/folders/17/g4zpz4f11h59hqtf94dlhhd80000gp/T/tmpo2dkgjoy.pyomo.lp', '-stat=1', '-solve', '-solu', '/var/folders/17/g4zpz4f11h59hqtf94dlhhd80000gp/T/tmpo2dkgjoy.pyomo.soln']
+
+Welcome to the CBC MILP Solver 
+Version: 2.9.9 
+Build Date: Aug 25 2017 
+
+command line - /Users/username/PycharmProjects/pyomo_cbc_return_handling/solvers/cbc/Darwin/cbc -randomCbcSeed 42 -randomSeed 42 -printingOptions all -import /var/folders/17/g4zpz4f11h59hqtf94dlhhd80000gp/T/tmpo2dkgjoy.pyomo.lp -stat=1 -solve -solu /var/folders/17/g4zpz4f11h59hqtf94dlhhd80000gp/T/tmpo2dkgjoy.pyomo.soln (default strategy 1)resources/solvers/cbc/cbc-osx/cbc -sec 900 -timeMode elapsed -randomCbcSeed 42 -randomSeed 42 -randomizedRounding off -threads 1 -maxSolutions 1 -printingOptions all -import /var/folders/17/g4zpz4f11h59hqtf94dlhhd80000gp/T/tmp2kpl8a93.pyomo.lp -stat=1 -solve -solu /var/folders/17/g4zpz4f11h59hqtf94dlhhd80000gp/T/tmp2kpl8a93.pyomo.soln (default strategy 1)
+seconds was changed from 1e+100 to 900
+Option for timeMode changed from cpu to elapsed
+randomCbcSeed was changed from -1 to 42
+randomSeed was changed from 1234567 to 42
+threads was changed from 0 to 1
+maxSolutions was changed from 9999999 to 1
+Option for printingOptions changed from normal to all
+ CoinLpIO::readLp(): Maximization problem reformulated as minimization
+Presolve 205 (-1) rows, 104 (-1) columns and 552 (-1) elements
+Statistics for presolved model
+Original problem has 40 integers (40 of which binary)
+Presolved problem has 40 integers (40 of which binary)
+==== 72 zero objective 2 different
+32 variables have objective of -1
+72 variables have objective of 0
+==== absolute objective values 2 different
+72 variables have objective of 0
+32 variables have objective of 1
+==== for integers 40 zero objective 1 different
+40 variables have objective of 0
+==== for integers absolute objective values 1 different
+40 variables have objective of 0
+===== end objective counts
+
+
+Problem has 205 rows, 104 columns (32 with objective) and 552 elements
+Column breakdown:
+0 of type 0.0->inf, 0 of type 0.0->up, 0 of type lo->inf, 
+0 of type lo->up, 0 of type free, 0 of type fixed, 
+0 of type -inf->0.0, 0 of type -inf->up, 104 of type 0.0->1.0 
+Row breakdown:
+0 of type E 0.0, 13 of type E 1.0, 0 of type E -1.0, 
+0 of type E other, 0 of type G 0.0, 0 of type G 1.0, 
+0 of type G other, 128 of type L 0.0, 64 of type L 1.0, 
+0 of type L other, 0 of type Range 0.0->1.0, 0 of type Range other, 
+0 of type Free 
+Continuous objective value is -4 - 0.00 seconds
+Cgl0003I 0 fixed, 0 tightened bounds, 85 strengthened rows, 0 substitutions
+Cgl0003I 0 fixed, 0 tightened bounds, 88 strengthened rows, 0 substitutions
+Cgl0003I 0 fixed, 0 tightened bounds, 74 strengthened rows, 0 substitutions
+Cgl0003I 0 fixed, 0 tightened bounds, 72 strengthened rows, 0 substitutions
+Cgl0003I 0 fixed, 0 tightened bounds, 79 strengthened rows, 0 substitutions
+Cgl0003I 0 fixed, 0 tightened bounds, 73 strengthened rows, 0 substitutions
+Cgl0003I 0 fixed, 0 tightened bounds, 51 strengthened rows, 0 substitutions
+Cgl0003I 0 fixed, 0 tightened bounds, 40 strengthened rows, 0 substitutions
+Cgl0003I 0 fixed, 0 tightened bounds, 17 strengthened rows, 0 substitutions
+Cgl0004I processed model has 158 rows, 104 columns (104 integer (104 of which binary)) and 990 elements
+Cutoff increment increased from 1e-05 to 0.9999
+Cbc0038I Initial state - 0 integers unsatisfied sum - 0
+Cbc0038I Solution found of -3
+Cbc0038I After 0.08 seconds - Feasibility pump exiting with objective of -3 (stopping after 1 solutions) - took 0.00 seconds
+Cbc0012I Integer solution of -3 found by feasibility pump after 0 iterations and 0 nodes (0.08 seconds)
+Cbc0030I Thread 0 used 0 times,  waiting to start 0.00030899048, 0 cpu time, 0 locks, 0 locked, 0 waiting for locks
+Cbc0030I Main thread 0 waiting for threads,  1 locks, 1.001358e-05 locked, 0 waiting for locks
+Cbc0019I Exiting on maximum solutions
+Cbc0005I Partial search - best objective -3 (best possible -3), took 0 iterations and 0 nodes (0.08 seconds)
+Cbc0035I Maximum depth 0, 0 variables fixed on reduced cost
+Cuts at root node changed objective from -3 to -3
+Probing was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
+Gomory was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
+Knapsack was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
+Clique was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
+MixedIntegerRounding2 was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
+FlowCover was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
+TwoMirCuts was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
+
+Result - Stopped on solution limit
+
+Objective value:                -3.00000000
+Lower bound:                    -3.000
+Gap:                            0.00
+Enumerated nodes:               0
+Total iterations:               0
+Time (CPU seconds):             0.08
+Time (Wallclock seconds):       0.08
+
+Total time (CPU seconds):       0.08   (Wallclock seconds):       0.09
+
+
diff --git a/pyomo/solvers/tests/checks/data/cbc/fix_parsing_bug.out.soln b/pyomo/solvers/tests/checks/data/cbc/fix_parsing_bug.out.soln
new file mode 100644
--- /dev/null
+++ b/pyomo/solvers/tests/checks/data/cbc/fix_parsing_bug.out.soln
@@ -0,0 +1,106 @@
+Stopped on iterations - objective value -3.00000000
+      0 x161                               0                      -1
+      1 x163                               0                      -1
+      2 x166                               0                      -1
+      3 x168                               0                      -1
+      4 x170                               0                      -1
+      5 x172                               0                      -1
+      6 x174                               1                      -1
+      7 x176                               0                      -1
+      8 x178                               0                      -1
+      9 x180                               0                      -1
+     10 x182                               0                      -1
+     11 x184                               0                      -1
+     12 x185                               0                      -1
+     13 x187                               0                      -1
+     14 x189                               0                      -1
+     15 x191                               0                      -1
+     16 x193                               0                      -1
+     17 x195                               0                      -1
+     18 x198                               0                      -1
+     19 x200                               0                      -1
+     20 x202                               0                      -1
+     21 x204                               1                      -1
+     22 x205                               0                      -1
+     23 x207                               0                      -1
+     24 x209                               1                      -1
+     25 x211                               0                      -1
+     26 x214                               0                      -1
+     27 x216                               0                      -1
+     28 x218                               0                      -1
+     29 x220                               0                      -1
+     30 x222                               0                      -1
+     31 x223                               0                      -1
+     32 x1                                 0                       0
+     33 x11                                0                       0
+     34 x15                                0                       0
+     35 x19                                1                       0
+     36 x23                                0                       0
+     37 x27                                0                       0
+     38 x30                                0                       0
+     39 x32                                0                       0
+     40 x106                               0                       0
+     41 x129                               0                       0
+     42 x34                                0                       0
+     43 x42                                0                       0
+     44 x66                                0                       0
+     45 x74                                0                       0
+     46 x98                                1                       0
+     47 x108                               0                       0
+     48 x139                               0                       0
+     49 x44                                0                       0
+     50 x76                                0                       0
+     51 x112                               0                       0
+     52 x143                               1                       0
+     53 x48                                0                       0
+     54 x80                                0                       0
+     55 x116                               0                       0
+     56 x147                               0                       0
+     57 x52                                0                       0
+     58 x84                                0                       0
+     59 x127                               0                       0
+     60 x160                               0                       0
+     61 x63                                0                       0
+     62 x95                                1                       0
+     63 x124                               0                       0
+     64 x158                               0                       0
+     65 x60                                0                       0
+     66 x92                                0                       0
+     67 x120                               0                       0
+     68 x155                               0                       0
+     69 x56                                1                       0
+     70 x88                                0                       0
+     71 x151                               0                       0
+     72 x162                               0                       0
+     73 x164                               0                       0
+     74 x165                               0                       0
+     75 x167                               0                       0
+     76 x169                               0                       0
+     77 x171                               0                       0
+     78 x173                               0                       0
+     79 x175                               0                       0
+     80 x177                               0                       0
+     81 x179                               0                       0
+     82 x181                               0                       0
+     83 x183                               0                       0
+     84 x186                               0                       0
+     85 x188                               0                       0
+     86 x190                               0                       0
+     87 x192                               0                       0
+     88 x194                               0                       0
+     89 x196                               0                       0
+     90 x197                               0                       0
+     91 x199                               0                       0
+     92 x201                               0                       0
+     93 x203                               0                       0
+     94 x206                               0                       0
+     95 x208                               0                       0
+     96 x210                               0                       0
+     97 x212                               0                       0
+     98 x213                               0                       0
+     99 x215                               0                       0
+    100 x217                               0                       0
+    101 x219                               0                       0
+    102 x221                               0                       0
+    103 x224                               0                       0
+    104 ONE_VAR_CONSTANT                   1                       0
diff --git a/pyomo/solvers/tests/checks/data/fix_parsing_bug.out.lp b/pyomo/solvers/tests/checks/data/fix_parsing_bug.out.lp
new file mode 100644
--- /dev/null
+++ b/pyomo/solvers/tests/checks/data/fix_parsing_bug.out.lp
@@ -0,0 +1 @@
+left empty on purpose
\ No newline at end of file
diff --git a/pyomo/solvers/tests/checks/test_CBCplugin.py b/pyomo/solvers/tests/checks/test_CBCplugin.py
--- a/pyomo/solvers/tests/checks/test_CBCplugin.py
+++ b/pyomo/solvers/tests/checks/test_CBCplugin.py
@@ -313,6 +313,27 @@ def test_max_evaluations(self):
         self.assertEqual(results.solver.statistics.branch_and_bound.number_of_created_subproblems, 1)
         self.assertEqual(results.solver.statistics.black_box.number_of_iterations, 602)
 
+    def test_fix_parsing_bug(self):
+        """
+        The test wasn't generated using the method in the class docstring
+        See https://github.com/Pyomo/pyomo/issues/1001
+        """
+        lp_file = 'fix_parsing_bug.out.lp'
+        results = self.opt.solve(os.path.join(data_dir, lp_file))
+
+        self.assertEqual(3.0, results.problem.lower_bound)
+        self.assertEqual(3.0, results.problem.upper_bound)
+        self.assertEqual(SolverStatus.aborted, results.solver.status)
+        self.assertEqual(0.08, results.solver.system_time)
+        self.assertEqual(0.09, results.solver.wallclock_time)
+        self.assertEqual(TerminationCondition.other, results.solver.termination_condition)
+        self.assertEqual(
+            'Optimization terminated because the number of solutions found reached the value specified in the '
+            'maxSolutions parameter.', results.solver.termination_message)
+        self.assertEqual(results.solver.statistics.branch_and_bound.number_of_bounded_subproblems, 0)
+        self.assertEqual(results.solver.statistics.branch_and_bound.number_of_created_subproblems, 0)
+        self.assertEqual(results.solver.statistics.black_box.number_of_iterations, 0)
+
 
 if __name__ == "__main__":
     unittest.main()