Repository: Pyomo/pyomo

Issue:
Baron .bar writer error
The Baron file writer (**baron_writer.py**) in the expression tree parsing (class ToBaronVisitor, visit() method) seems to be checking "is" type as opposed to "is instance" of a type. Specifically, I have a certain constraint that has an "NPV_PowExpression" object that is being written as a string to the.bar file (meaning, the ** operator for power hasn't been replaced with the "^" Baron requires). I think this is happening at line 102 of the baron_writer.py where type is checked against "is EXPR.PowExpression," since NPV_PowExpression is an instance of PowExpression and not a PowExpression type itself.


Discussion:
Wow, you really dug in and figured out the root cause of the issue.

Resolving patch:
diff --git a/pyomo/repn/plugins/baron_writer.py b/pyomo/repn/plugins/baron_writer.py
--- a/pyomo/repn/plugins/baron_writer.py
+++ b/pyomo/repn/plugins/baron_writer.py
@@ -129,6 +129,9 @@ def visit(self, node, values):
                 else:
                     tmp.append(val)
 
+        if node.__class__ in EXPR.NPV_expression_types:
+            return _ftoa(value(node))
+
         if node.__class__ is EXPR.LinearExpression:
             for v in node.linear_vars:
                 self.variables.add(id(v))
diff --git a/pyomo/repn/plugins/gams_writer.py b/pyomo/repn/plugins/gams_writer.py
--- a/pyomo/repn/plugins/gams_writer.py
+++ b/pyomo/repn/plugins/gams_writer.py
@@ -113,6 +113,9 @@ def visit(self, node, values):
                 else:
                     tmp.append(val)
 
+        if node.__class__ in EXPR.NPV_expression_types:
+            return _ftoa(value(node))
+
         if node.__class__ is EXPR.PowExpression:
             # If the exponent is a positive integer, use the power() function.
             # Otherwise, use the ** operator.


Test patch:
diff --git a/pyomo/repn/tests/baron/exponential_NPV.bar.baseline b/pyomo/repn/tests/baron/exponential_NPV.bar.baseline
new file mode 100644
--- /dev/null
+++ b/pyomo/repn/tests/baron/exponential_NPV.bar.baseline
@@ -0,0 +1,19 @@
+OPTIONS {
+Summary: 0;
+}
+
+POSITIVE_VARIABLES ONE_VAR_CONST__;
+
+VARIABLES x;
+
+EQUATIONS c_e_FIX_ONE_VAR_CONST__, c;
+
+c_e_FIX_ONE_VAR_CONST__:  ONE_VAR_CONST__  == 1;
+c: x == 0;
+
+OBJ: minimize x ^ 2;
+
+STARTING_POINT{
+ONE_VAR_CONST__: 1;
+}
+
diff --git a/pyomo/repn/tests/baron/small5.pyomo.bar b/pyomo/repn/tests/baron/small5.pyomo.bar
--- a/pyomo/repn/tests/baron/small5.pyomo.bar
+++ b/pyomo/repn/tests/baron/small5.pyomo.bar
@@ -27,11 +27,11 @@ c3: x1 * (x2 - x3)/2 == 2;
 c4: x1 * (0.5 * x2 + (-0.5) * x3) == 2;
 c5: x1 * (x2 - x3) * 0.5 == 2;
 c6: x1 * (x2 - x3) == 4;
-c7: 1/2 * x1 * (x2 - x3) == 2;
-c8: 1/2 * x1 * (x2 - x3) == 2;
+c7: 0.5 * x1 * (x2 - x3) == 2;
+c8: 0.5 * x1 * (x2 - x3) == 2;
 c9: x1 * (x2 - x3)/2 == 2;
-c10: x1 * (1/2 * x2 + (- 1/2) * x3) == 2;
-c11: x1 * (x2 - x3) * (1/2) == 2;
+c10: x1 * (0.5 * x2 + (-0.5) * x3) == 2;
+c11: x1 * (x2 - x3) * (0.5) == 2;
 c12: x1 * (x2 - x3) == 4;
 
 OBJ: minimize x2 ^ 2/2 + x2 ^ 2/2;
diff --git a/pyomo/repn/tests/baron/test_baron.py b/pyomo/repn/tests/baron/test_baron.py
--- a/pyomo/repn/tests/baron/test_baron.py
+++ b/pyomo/repn/tests/baron/test_baron.py
@@ -150,6 +150,15 @@ def test_trig_generates_exception(self):
             m.write(test_fname, format="bar")
         self._cleanup(test_fname)
 
+    def test_exponential_NPV(self):
+        m = ConcreteModel()
+        m.x = Var()
+        m.obj = Objective(expr=m.x**2)
+        m.p = Param(initialize=1, mutable=True)
+        m.c = Constraint(expr=m.x * m.p ** 1.2 == 0)
+        self._check_baseline(m)
+
+
 #class TestBaron_writer(unittest.TestCase):
 class XTestBaron_writer(object):
     """These tests verified that the BARON writer complained loudly for
diff --git a/pyomo/repn/tests/gams/small5.pyomo.gms b/pyomo/repn/tests/gams/small5.pyomo.gms
--- a/pyomo/repn/tests/gams/small5.pyomo.gms
+++ b/pyomo/repn/tests/gams/small5.pyomo.gms
@@ -27,11 +27,11 @@ c3.. x1*(x2 - x3)/2 =e= 2 ;
 c4.. x1*(0.5*x2 + (-0.5)*x3) =e= 2 ;
 c5.. x1*(x2 - x3)*0.5 =e= 2 ;
 c6.. x1*(x2 - x3) =e= 4 ;
-c7.. 1/2*x1*(x2 - x3) =e= 2 ;
-c8.. 1/2*x1*(x2 - x3) =e= 2 ;
+c7.. 0.5*x1*(x2 - x3) =e= 2 ;
+c8.. 0.5*x1*(x2 - x3) =e= 2 ;
 c9.. x1*(x2 - x3)/2 =e= 2 ;
-c10.. x1*(1/2*x2 + (- 1/2)*x3) =e= 2 ;
-c11.. x1*(x2 - x3)*(1/2) =e= 2 ;
+c10.. x1*(0.5*x2 + (-0.5)*x3) =e= 2 ;
+c11.. x1*(x2 - x3)*(0.5) =e= 2 ;
 c12.. x1*(x2 - x3) =e= 4 ;
 c13.. GAMS_OBJECTIVE =e= power(x2, 2)/2 + power(x2, 2)/2 ;