Repository: Pyomo/pyomo

Issue:
Reaffirm changes to basic step code
## Summary
I am implementing a GDP Basic Steps example. So far, none of the basic steps examples I found actually reformulated/solved the problem. When I tried to solve the problem, the problem turned out to be infeasible after applying the basic step.
Originally the problem was solved by going to [the basic_steps.py file](/RomeoV/pyomo/blob/implementing_basic_step_example/pyomo/gdp/basic_step.py) and replacing `d.deactivate()` by `d._deactivate_without_fixing_indicator()`: [see here](https://github.com/RomeoV/pyomo/blob/8acaa8135e2cd2d9afc61324a75cc3637cb18fc9/pyomo/gdp/basic_step.py#L113-L119)
This originally fixed the problem, until I merged the current master branch (f93e439ce51350c26f62bf66ee6164ad13560635). Afterwards the probem reappeared. After consulting with @qtothec, I changed a line in the [gdp_var_mover.py file](/RomeoV/pyomo/blob/implementing_basic_step_example/pyomo/gdp/plugins/gdp_var_mover.py), see [here](https://github.com/RomeoV/pyomo/blob/b9b6cd9010f35e60d4520bc69ac2aeac7ece8ce2/pyomo/gdp/plugins/gdp_var_mover.py#L103).
Now the example works so far, but I would prefer for someone to recheck if those changes can be made like this or influence something else.

## Steps to reproduce
Check out [the branch on my fork](/RomeoV/pyomo/tree/implementing_basic_step_example) and run [the example file](/RomeoV/pyomo/blob/implementing_basic_step_example/examples/gdp/small_lit/basic_step.py)


Discussion:

Resolving patch:
diff --git a/examples/gdp/small_lit/basic_step.py b/examples/gdp/small_lit/basic_step.py
new file mode 100644
--- /dev/null
+++ b/examples/gdp/small_lit/basic_step.py
@@ -0,0 +1,78 @@
+""" Example from Section 3.2 in paper of Pseudo Basic Steps
+
+Ref:
+    Pseude basic steps: bound improvement guarantess from Lagrangian 
+    decomposition in convex disjunctive programming
+    Papageorgiou and Trespalacios, 2017
+
+Solution is 2.99 with (x1,x2) = (-0.1, 3.01)
+
+Pyomo model implementation by @RomeoV
+"""
+from pyomo.environ import *
+from pyomo.gdp import *
+from pyomo.gdp.basic_step import apply_basic_step
+
+def build_gdp_model():
+    model = ConcreteModel()
+
+    model.x1 = Var(bounds=(-1,6), initialize=0)
+    model.x2 = Var(bounds=( 0,7), initialize=3.5)
+
+    model.objective = Objective(expr=0.2*model.x1 + model.x2)
+    model.disjunction_set = RangeSet(1,3)
+
+    model.disjuncts = Disjunct([1,2,3],[1,2])
+    model.disjuncts[1,1].c = Constraint(expr=model.x1**2 + (1/4)*(model.x2 - 5)**2 <= 1)
+    model.disjuncts[2,1].c = Constraint(expr=model.x1**2 + (1/4)*(model.x2 - 2)**2 <= 1)
+    model.disjuncts[3,1].c = Constraint(expr=model.x1**2 + (1/4)*(model.x2 - 3.5)**2 <= 1)
+
+    model.disjuncts[1,2].c = Constraint(expr=(model.x1 - 5)**2 + (1/4)*(model.x2 - 2)**2 <= 1)
+    model.disjuncts[2,2].c = Constraint(expr=(model.x1 - 5)**2 + (1/4)*(model.x2 - 5)**2 <= 1)
+    model.disjuncts[3,2].c = Constraint(expr=(model.x1 - 5)**2 + (1/4)*(model.x2 - 3.5)**2 <= 1)
+
+    @model.Disjunction(model.disjunction_set, xor=True)
+    def disjunctions(model,i):
+        return [model.disjuncts[i,1], model.disjuncts[i,2]]
+
+    return model
+
+def solve_base_model():
+    m_base = build_gdp_model()
+    m_chull = TransformationFactory('gdp.chull').create_using(m_base)
+    #m_bigm = TransformationFactory('gdp.bigm').create_using(m_base, bigM=100)
+    solver = SolverFactory('gams')
+    solver.solve(m_chull, solver='baron')
+    #m_chull.pprint()
+    m_chull.objective.display()
+    m_chull.x1.display()
+    m_chull.x2.display()
+
+
+def solve_basic_step_model():
+    m_base = build_gdp_model()
+    m_base.BS = apply_basic_step([m_base.disjunctions[1],m_base.disjunctions[2]])
+
+    # crux to pprint component
+    #with open('pprint.log','w') as outputfile: 
+    #    m_base.disjunctions.pprint(outputfile)
+
+    #m_bs_chull = TransformationFactory('gdp.chull').create_using(m_base)
+    m_bigm = TransformationFactory('gdp.bigm').create_using(m_base, bigM=100)
+    m_bigm.pprint()
+
+    solver = SolverFactory('gams')
+    solver.solve(m_bigm, tee=True, solver='baron')
+
+    m_bigm.objective.display()
+    m_bigm.x1.display()
+    m_bigm.x2.display()
+
+if __name__ == '__main__':
+    print('################################')
+    print('[1] Sanity check: solving base model')
+    solve_base_model()
+
+    print('################################')
+    print('[2] Solving basic step model')
+    solve_basic_step_model()
diff --git a/pyomo/gdp/basic_step.py b/pyomo/gdp/basic_step.py
--- a/pyomo/gdp/basic_step.py
+++ b/pyomo/gdp/basic_step.py
@@ -111,7 +111,7 @@ def apply_basic_step(disjunctions_or_constraints):
     for i in ans.DISJUNCTIONS:
         disjunctions[i].deactivate()
         for d in disjunctions[i].disjuncts:
-            d.deactivate()
+            d._deactivate_without_fixing_indicator()
 
     return ans
 
diff --git a/pyomo/gdp/plugins/gdp_var_mover.py b/pyomo/gdp/plugins/gdp_var_mover.py
--- a/pyomo/gdp/plugins/gdp_var_mover.py
+++ b/pyomo/gdp/plugins/gdp_var_mover.py
@@ -100,7 +100,7 @@ def _apply_to(self, instance, **kwds):
             # deactivated.
             for disjunct in itervalues(disjunct_component._data):
                 if self._disjunct_not_relaxed(disjunct):
-                    disjunct.deactivate()
+                    disjunct._deactivate_without_fixing_indicator()
                 else:
                     disjunct._activate_without_unfixing_indicator()
 


Test patch: