Repository: Pyomo/pyomo

Issue:
Incorrect statistics on Model
In Model.compute_statistics() the computed statics object often contains incorrect results when using Blocks.
```
        model = ConcreteModel()
        model.x = Var([1])

        model.B = Block()
        model.B.c = ConstraintList()
        model.B.c.add(model.x[1] == 0)
        print(model.nvariables())
        print(model.nconstraints())
```
The variable count is evaluated to 2 even though there is only one variable and the constraint count is evaluated to 0.

Also no recalculation is performed.
```
        model = ConcreteModel()
        model.x = Var([1])

        print(model.nvariables())
        model.clear()
        print(model.nvariables())
```
The statistic is only evaluated on the first use. Both times nvariables evaluates to 2.


Discussion:

Resolving patch:
diff --git a/pyomo/core/base/PyomoModel.py b/pyomo/core/base/PyomoModel.py
--- a/pyomo/core/base/PyomoModel.py
+++ b/pyomo/core/base/PyomoModel.py
@@ -596,17 +596,15 @@ def compute_statistics(self, active=True):
         """
         Compute model statistics
         """
-        if len(self.statistics) > 0:
-            return
         self.statistics.number_of_variables = 0
         self.statistics.number_of_constraints = 0
         self.statistics.number_of_objectives = 0
         for block in self.block_data_objects(active=active):
-            for data in self.component_map(Var, active=active).itervalues():
+            for data in block.component_map(Var, active=active).itervalues():
                 self.statistics.number_of_variables += len(data)
-            for data in self.component_map(Objective, active=active).itervalues():
+            for data in block.component_map(Objective, active=active).itervalues():
                 self.statistics.number_of_objectives += len(data)
-            for data in self.component_map(Constraint, active=active).itervalues():
+            for data in block.component_map(Constraint, active=active).itervalues():
                 self.statistics.number_of_constraints += len(data)
 
     def nvariables(self):


Test patch:
diff --git a/pyomo/core/tests/unit/test_model.py b/pyomo/core/tests/unit/test_model.py
--- a/pyomo/core/tests/unit/test_model.py
+++ b/pyomo/core/tests/unit/test_model.py
@@ -432,6 +432,26 @@ def c_rule(model, i):
         self.assertEqual(model.nobjectives(), 4)
         self.assertEqual(model.nconstraints(), 4)
 
+    def test_stats4(self):
+        model = ConcreteModel()
+        model.x = Var([1])
+
+        model.B = Block()
+        model.B.x = Var([1, 2, 3])
+        model.B.o = ObjectiveList()
+        model.B.o.add(model.B.x[1])
+        model.B.c = ConstraintList()
+        model.B.c.add(model.B.x[1] == 0)
+        model.B.c.add(model.B.x[2] == 0)
+        model.B.c.add(model.B.x[3] == 0)
+        self.assertEqual(model.nvariables(), 4)
+        self.assertEqual(model.nobjectives(), 1)
+        self.assertEqual(model.nconstraints(), 3)
+        model.clear()
+        self.assertEqual(model.nvariables(), 0)
+        self.assertEqual(model.nobjectives(), 0)
+        self.assertEqual(model.nconstraints(), 0)
+
     @unittest.skipIf(not 'glpk' in solvers, "glpk solver is not available")
     def test_solve_with_pickle(self):
         model = ConcreteModel()