Repository: Pyomo/pyomo

Issue:
Issue exporting model to gams with power operator
Hi,
I am exporting an expression with a negative power operator to gams:
pyomo exports: m.Eq1=Constraint(expr=m.B+ m.A * m.T1**-1.0==0)
gams receives:   Eq1..        B+ A* T1**- 1.0 =e= 0.0 

And I am getting the following error in gams:

445  More than one operator in a row. You need to use parenthesis
       if you want to use such statements. For example
           x := x + - not y;  ->  x := x + (- (not y));
           sum(i$not x, ..)   ->  sum(i$(not x),..)
Best, 
Paz



Discussion:
@gseastream Didn't we fix something similar not too long ago?
Yes, there was a similar issue when variables were fixed to negative values. The fix for this should be very similar.
Ok. Relevant issues are #306 and #510. I'll get to this after I'm finished putting out fires, if nobody else does first.

Resolving patch:
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
@@ -54,7 +54,11 @@ def visit(self, node, values):
             if arg is None:
                 tmp.append('Undefined')
             elif arg.__class__ in native_numeric_types:
-                tmp.append(val)
+                if arg < 0:
+                    # Wrap negative values in parens to avoid double operator
+                    tmp.append("(%s)" % val)
+                else:
+                    tmp.append(val)
             elif arg.__class__ in native_types:
                 tmp.append("'{0}'".format(val))
             elif arg.is_variable_type():


Test patch:
diff --git a/pyomo/repn/tests/gams/small13.pyomo.gms b/pyomo/repn/tests/gams/small13.pyomo.gms
--- a/pyomo/repn/tests/gams/small13.pyomo.gms
+++ b/pyomo/repn/tests/gams/small13.pyomo.gms
@@ -10,9 +10,9 @@ VARIABLES
 	GAMS_OBJECTIVE
 	x1;
 
-c1.. power(x1, 3) - x1 =e= 0.0 ;
-c2.. 10*(power(x1, 3) - x1) =e= 0.0 ;
-c3.. (power(x1, 3) - x1)*0.1 =e= 0.0 ;
+c1.. power(x1, 3) + (-1)*x1 =e= 0.0 ;
+c2.. 10*(power(x1, 3) + (-1)*x1) =e= 0.0 ;
+c3.. (power(x1, 3) + (-1)*x1)*0.1 =e= 0.0 ;
 c4.. GAMS_OBJECTIVE =e= x1 ;
 
 x1.l = 0.5;
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
@@ -21,18 +21,18 @@ VARIABLES
 	x2
 	x3;
 
-c1.. 0.5*x1*(x2 - x3) =e= 2.0 ;
-c2.. 0.5*x1*(x2 - x3) =e= 2.0 ;
-c3.. x1*(x2 - x3)*0.5 =e= 2.0 ;
-c4.. x1*(0.5*x2 - 0.5*x3) =e= 2.0 ;
-c5.. x1*(x2 - x3)*0.5 =e= 2.0 ;
-c6.. x1*(x2 - x3) =e= 4.0 ;
-c7.. (1/2.0)*x1*(x2 - x3) =e= 2.0 ;
-c8.. (1/2.0)*x1*(x2 - x3) =e= 2.0 ;
-c9.. x1*(x2 - x3)*(1/2.0) =e= 2.0 ;
+c1.. 0.5*x1*(x2 + (-1)*x3) =e= 2.0 ;
+c2.. 0.5*x1*(x2 + (-1)*x3) =e= 2.0 ;
+c3.. x1*(x2 + (-1)*x3)*0.5 =e= 2.0 ;
+c4.. x1*(0.5*x2 + (-0.5)*x3) =e= 2.0 ;
+c5.. x1*(x2 + (-1)*x3)*0.5 =e= 2.0 ;
+c6.. x1*(x2 + (-1)*x3) =e= 4.0 ;
+c7.. (1/2.0)*x1*(x2 + (-1)*x3) =e= 2.0 ;
+c8.. (1/2.0)*x1*(x2 + (-1)*x3) =e= 2.0 ;
+c9.. x1*(x2 + (-1)*x3)*(1/2.0) =e= 2.0 ;
 c10.. x1*((1/2.0)*x2 - (1/2.0)*x3) =e= 2.0 ;
-c11.. x1*(x2 - x3)*(1/2.0) =e= 2.0 ;
-c12.. x1*(x2 - x3) =e= 4.0 ;
+c11.. x1*(x2 + (-1)*x3)*(1/2.0) =e= 2.0 ;
+c12.. x1*(x2 + (-1)*x3) =e= 4.0 ;
 c13.. GAMS_OBJECTIVE =e= power(x2, 2)*0.5 + power(x2, 2)*(1/2.0) ;
 
 x1.lo = -1.0;
diff --git a/pyomo/repn/tests/gams/small6.pyomo.gms b/pyomo/repn/tests/gams/small6.pyomo.gms
--- a/pyomo/repn/tests/gams/small6.pyomo.gms
+++ b/pyomo/repn/tests/gams/small6.pyomo.gms
@@ -15,12 +15,12 @@ VARIABLES
 	x2
 	x3;
 
-c1.. (1/(2.0))*x1*(x2 - x3) =e= 2.0 ;
-c2.. x1*(1/(2.0))*(x2 - x3) =e= 2.0 ;
-c3.. x1*(x2 - x3)*(1/(2.0)) =e= 2.0 ;
+c1.. (1/(2.0))*x1*(x2 + (-1)*x3) =e= 2.0 ;
+c2.. x1*(1/(2.0))*(x2 + (-1)*x3) =e= 2.0 ;
+c3.. x1*(x2 + (-1)*x3)*(1/(2.0)) =e= 2.0 ;
 c4.. x1*(x2*(1/(2.0)) - x3*(1/(2.0))) =e= 2.0 ;
-c5.. x1*(x2 - x3)*(1/(2.0)) =e= 2.0 ;
-c6.. x1*(x2 - x3) - 2.0*(2.0) =e= 0.0 ;
+c5.. x1*(x2 + (-1)*x3)*(1/(2.0)) =e= 2.0 ;
+c6.. x1*(x2 + (-1)*x3) + (-2.0)*(2.0) =e= 0.0 ;
 c7.. GAMS_OBJECTIVE =e= x2 ;
 
 x1.lo = -1.0;
diff --git a/pyomo/repn/tests/gams/small7.pyomo.gms b/pyomo/repn/tests/gams/small7.pyomo.gms
--- a/pyomo/repn/tests/gams/small7.pyomo.gms
+++ b/pyomo/repn/tests/gams/small7.pyomo.gms
@@ -33,30 +33,30 @@ VARIABLES
 	x2
 	x3;
 
-c1.. (1/(2.0))*0.5*x1*(x2 - x3) =e= 2.0 ;
-c2.. x1*(1/(2.0))*(1/(2.0))*(x2 - x3) =e= 2.0 ;
-c3.. x1*(x2 - x3)*(1/(2.0))*0.5 =e= 2.0 ;
+c1.. (1/(2.0))*0.5*x1*(x2 + (-1)*x3) =e= 2.0 ;
+c2.. x1*(1/(2.0))*(1/(2.0))*(x2 + (-1)*x3) =e= 2.0 ;
+c3.. x1*(x2 + (-1)*x3)*(1/(2.0))*0.5 =e= 2.0 ;
 c4.. x1*(x2*(1/(2.0))*0.5 - x3*(1/(2.0))*0.5) =e= 2.0 ;
-c5.. x1*(x2 - x3)*(1/(2.0))*0.5 =e= 2.0 ;
-c6.. x1*(x2 - x3) - 4.0*(2.0) =e= 0.0 ;
-c7.. (1/(2.0*(2.0)))*x1*(x2 - x3) =e= 2.0 ;
-c8.. x1*(1/((2.0)*(2.0)))*(x2 - x3) =e= 2.0 ;
-c9.. x1*(x2 - x3)*(1/(2.0*(2.0))) =e= 2.0 ;
+c5.. x1*(x2 + (-1)*x3)*(1/(2.0))*0.5 =e= 2.0 ;
+c6.. x1*(x2 + (-1)*x3) + (-4.0)*(2.0) =e= 0.0 ;
+c7.. (1/(2.0*(2.0)))*x1*(x2 + (-1)*x3) =e= 2.0 ;
+c8.. x1*(1/((2.0)*(2.0)))*(x2 + (-1)*x3) =e= 2.0 ;
+c9.. x1*(x2 + (-1)*x3)*(1/(2.0*(2.0))) =e= 2.0 ;
 c10.. x1*(x2*(1/(2.0*(2.0))) - x3*(1/(2.0*(2.0)))) =e= 2.0 ;
-c11.. x1*(x2 - x3)*(1/(2.0*(2.0))) =e= 2.0 ;
-c12.. x1*(x2 - x3) - 4.0*(2.0) =e= 0.0 ;
-c13.. (1/((2.0) + 2.0))*x1*(x2 - x3) =e= 2.0 ;
-c14.. x1*(1/((2.0) + (2.0)))*(x2 - x3) =e= 2.0 ;
-c15.. x1*(x2 - x3)*(1/((2.0) + 2.0)) =e= 2.0 ;
+c11.. x1*(x2 + (-1)*x3)*(1/(2.0*(2.0))) =e= 2.0 ;
+c12.. x1*(x2 + (-1)*x3) + (-4.0)*(2.0) =e= 0.0 ;
+c13.. (1/((2.0) + 2.0))*x1*(x2 + (-1)*x3) =e= 2.0 ;
+c14.. x1*(1/((2.0) + (2.0)))*(x2 + (-1)*x3) =e= 2.0 ;
+c15.. x1*(x2 + (-1)*x3)*(1/((2.0) + 2.0)) =e= 2.0 ;
 c16.. x1*(x2*(1/((2.0) + 2.0)) - x3*(1/((2.0) + 2.0))) =e= 2.0 ;
-c17.. x1*(x2 - x3)*(1/((2.0) + 2.0)) =e= 2.0 ;
-c18.. x1*(x2 - x3) - 2.0*((2.0) + 2.0) =e= 0.0 ;
-c19.. (1/power(((2.0) + 2.0), 2))*x1*(x2 - x3) =e= 2.0 ;
-c20.. x1*(1/power(((2.0) + (2.0)), 2))*(x2 - x3) =e= 2.0 ;
-c21.. x1*(x2 - x3)*(1/power(((2.0) + 2.0), 2)) =e= 2.0 ;
+c17.. x1*(x2 + (-1)*x3)*(1/((2.0) + 2.0)) =e= 2.0 ;
+c18.. x1*(x2 + (-1)*x3) - 2.0*((2.0) + 2.0) =e= 0.0 ;
+c19.. (1/power(((2.0) + 2.0), 2))*x1*(x2 + (-1)*x3) =e= 2.0 ;
+c20.. x1*(1/power(((2.0) + (2.0)), 2))*(x2 + (-1)*x3) =e= 2.0 ;
+c21.. x1*(x2 + (-1)*x3)*(1/power(((2.0) + 2.0), 2)) =e= 2.0 ;
 c22.. x1*(x2*(1/power(((2.0) + 2.0), 2)) - x3*(1/power(((2.0) + 2.0), 2))) =e= 2.0 ;
-c23.. x1*(x2 - x3)*(1/power(((2.0) + 2.0), 2)) =e= 2.0 ;
-c24.. x1*(x2 - x3) - 2.0*power(((2.0) + 2.0), 2) =e= 0.0 ;
+c23.. x1*(x2 + (-1)*x3)*(1/power(((2.0) + 2.0), 2)) =e= 2.0 ;
+c24.. x1*(x2 + (-1)*x3) - 2.0*power(((2.0) + 2.0), 2) =e= 0.0 ;
 c25.. GAMS_OBJECTIVE =e= x2 ;
 
 x1.lo = -1.0;
diff --git a/pyomo/repn/tests/gams/small8.pyomo.gms b/pyomo/repn/tests/gams/small8.pyomo.gms
--- a/pyomo/repn/tests/gams/small8.pyomo.gms
+++ b/pyomo/repn/tests/gams/small8.pyomo.gms
@@ -15,7 +15,7 @@ VARIABLES
 	x3;
 
 c1_lo.. 2.0 =l= x1*x1 ;
-c2_hi.. x1 - 0.5*x2 =l= 0.0 ;
+c2_hi.. x1 + (-0.5)*x2 =l= 0.0 ;
 c3_hi.. x3 - (x1 + 2.0) =l= 0.0 ;
 c4.. GAMS_OBJECTIVE =e= x3 + x2*x2 + x1 ;
 
diff --git a/pyomo/repn/tests/gams/test_gams.py b/pyomo/repn/tests/gams/test_gams.py
--- a/pyomo/repn/tests/gams/test_gams.py
+++ b/pyomo/repn/tests/gams/test_gams.py
@@ -13,10 +13,15 @@
 
 import os
 
-import pyutilib.th as unittest
+from six import StringIO
 
-from pyomo.environ import *
-import pyomo.opt
+import pyutilib.th as unittest
+from pyomo.core.base import NumericLabeler, SymbolMap
+from pyomo.environ import (Block, ConcreteModel, Connector, Constraint,
+                           Objective, TransformationFactory, Var, exp, log)
+from pyomo.repn.plugins.gams_writer import (StorageTreeChecker,
+                                            expression_to_string,
+                                            split_long_line)
 
 thisdir = os.path.dirname(os.path.abspath(__file__))
 
@@ -32,7 +37,7 @@ def _cleanup(self, fname):
     def _get_fnames(self):
         class_name, test_name = self.id().split('.')[-2:]
         prefix = os.path.join(thisdir, test_name.replace("test_", "", 1))
-        return prefix+".gams.baseline", prefix+".gams.out"
+        return prefix + ".gams.baseline", prefix + ".gams.out"
 
     def _check_baseline(self, model, **kwds):
         baseline_fname, test_fname = self._get_fnames()
@@ -94,7 +99,7 @@ def test_no_row_ordering(self):
         components["con1"] = Constraint(expr=model.a >= 0)
         components["con2"] = Constraint(expr=model.a <= 1)
         components["con3"] = Constraint(expr=(0, model.a, 1))
-        components["con4"] = Constraint([1,2], rule=lambda m, i: model.a == i)
+        components["con4"] = Constraint([1, 2], rule=lambda m, i: model.a == i)
 
         for key in components:
             model.add_component(key, components[key])
@@ -107,7 +112,7 @@ def test_var_on_deactivated_block(self):
         model.other = Block()
         model.other.a = Var()
         model.other.deactivate()
-        model.c = Constraint(expr=model.other.a + 2*model.x <= 0)
+        model.c = Constraint(expr=model.other.a + 2 * model.x <= 0)
         model.obj = Objective(expr=model.x)
         self._check_baseline(model)
 
@@ -123,28 +128,135 @@ def test_expr_xfrm(self):
 
         expr = M.abc**2.0
         self.assertEqual(str(expr), "abc**2.0")
-        self.assertEqual(expression_to_string(expr, tc, smap=smap), "power(abc, 2.0)")
+        self.assertEqual(expression_to_string(
+            expr, tc, smap=smap), "power(abc, 2.0)")
 
-        expr = log( M.abc**2.0 )
+        expr = log(M.abc**2.0)
         self.assertEqual(str(expr), "log(abc**2.0)")
-        self.assertEqual(expression_to_string(expr, tc, smap=smap), "log(power(abc, 2.0))")
+        self.assertEqual(expression_to_string(
+            expr, tc, smap=smap), "log(power(abc, 2.0))")
 
-        expr = log( M.abc**2.0 ) + 5
+        expr = log(M.abc**2.0) + 5
         self.assertEqual(str(expr), "log(abc**2.0) + 5")
-        self.assertEqual(expression_to_string(expr, tc, smap=smap), "log(power(abc, 2.0)) + 5")
+        self.assertEqual(expression_to_string(
+            expr, tc, smap=smap), "log(power(abc, 2.0)) + 5")
 
-        expr = exp( M.abc**2.0 ) + 5
+        expr = exp(M.abc**2.0) + 5
         self.assertEqual(str(expr), "exp(abc**2.0) + 5")
-        self.assertEqual(expression_to_string(expr, tc, smap=smap), "exp(power(abc, 2.0)) + 5")
+        self.assertEqual(expression_to_string(
+            expr, tc, smap=smap), "exp(power(abc, 2.0)) + 5")
 
-        expr = log( M.abc**2.0 )**4
+        expr = log(M.abc**2.0)**4
         self.assertEqual(str(expr), "log(abc**2.0)**4")
-        self.assertEqual(expression_to_string(expr, tc, smap=smap), "power(log(power(abc, 2.0)), 4)")
+        self.assertEqual(expression_to_string(
+            expr, tc, smap=smap), "power(log(power(abc, 2.0)), 4)")
 
-        expr = log( M.abc**2.0 )**4.5
+        expr = log(M.abc**2.0)**4.5
         self.assertEqual(str(expr), "log(abc**2.0)**4.5")
-        self.assertEqual(expression_to_string(expr, tc, smap=smap), "log(power(abc, 2.0)) ** 4.5")
-
+        self.assertEqual(expression_to_string(
+            expr, tc, smap=smap), "log(power(abc, 2.0)) ** 4.5")
+
+    def test_power_function_to_string(self):
+        m = ConcreteModel()
+        m.x = Var()
+        lbl = NumericLabeler('x')
+        smap = SymbolMap(lbl)
+        tc = StorageTreeChecker(m)
+        self.assertEqual(expression_to_string(
+            m.x ** -3, tc, lbl, smap=smap), "power(x1, (-3))")
+        self.assertEqual(expression_to_string(
+            m.x ** 0.33, tc, smap=smap), "x1 ** 0.33")
+        self.assertEqual(expression_to_string(
+            pow(m.x, 2), tc, smap=smap), "power(x1, 2)")
+
+    def test_fixed_var_to_string(self):
+        m = ConcreteModel()
+        m.x = Var()
+        m.y = Var()
+        m.z = Var()
+        m.z.fix(-3)
+        lbl = NumericLabeler('x')
+        smap = SymbolMap(lbl)
+        tc = StorageTreeChecker(m)
+        self.assertEqual(expression_to_string(
+            m.x + m.y - m.z, tc, lbl, smap=smap), "x1 + x2 + (-1)*(-3)")
+        m.z.fix(-400)
+        self.assertEqual(expression_to_string(
+            m.z + m.y - m.z, tc, smap=smap), "(-400) + x2 + (-1)*(-400)")
+        m.z.fix(8.8)
+        self.assertEqual(expression_to_string(
+            m.x + m.z - m.y, tc, smap=smap), "x1 + (8.8) + (-1)*x2")
+        m.z.fix(-8.8)
+        self.assertEqual(expression_to_string(
+            m.x * m.z - m.y, tc, smap=smap), "x1*(-8.8) + (-1)*x2")
+
+    def test_gams_connector_in_active_constraint(self):
+        m = ConcreteModel()
+        m.b1 = Block()
+        m.b2 = Block()
+        m.b1.x = Var()
+        m.b2.x = Var()
+        m.b1.c = Connector()
+        m.b1.c.add(m.b1.x)
+        m.b2.c = Connector()
+        m.b2.c.add(m.b2.x)
+        m.c = Constraint(expr=m.b1.c == m.b2.c)
+        m.o = Objective(expr=m.b1.x)
+        os = StringIO()
+        with self.assertRaises(RuntimeError):
+            m.write(os, format="gams")
+
+    def test_gams_expanded_connectors(self):
+        m = ConcreteModel()
+        m.x = Var()
+        m.y = Var()
+        m.CON1 = Connector()
+        m.CON1.add(m.x, 'v')
+        m.CON2 = Connector()
+        m.CON2.add(m.y, 'v')
+        m.c = Constraint(expr=m.CON1 + m.CON2 >= 10)
+        TransformationFactory("core.expand_connectors").apply_to(m)
+        m.o = Objective(expr=m.x)
+        os = StringIO()
+        io_options = dict(symbolic_solver_labels=True)
+        m.write(os, format="gams", io_options=io_options)
+        # no error if we're here, but check for some identifying string
+        self.assertIn("x + y", os.getvalue())
+
+    def test_split_long_line(self):
+        pat = "var1 + log(var2 / 9) - "
+        line = (pat * 10000) + "x"
+        self.assertEqual(split_long_line(line),
+                         pat * 3478 + "var1 +\nlog(var2 / 9) - " +
+                         pat * 3477 + "var1 +\nlog(var2 / 9) - " +
+                         pat * 3043 + "x")
+
+    def test_solver_arg(self):
+        m = ConcreteModel()
+        m.x = Var()
+        m.c = Constraint(expr=m.x == 2)
+        m.o = Objective(expr=m.x)
+        os = StringIO()
+        m.write(os, format="gams", io_options=dict(solver="gurobi"))
+        self.assertIn("option lp=gurobi", os.getvalue())
+
+    def test_negative_float_double_operator(self):
+        m = ConcreteModel()
+        m.x = Var()
+        m.y = Var()
+        m.z = Var(bounds=(0, 6))
+        m.c = Constraint(expr=(m.x * m.y * -2) == 0)
+        m.c2 = Constraint(expr=m.z ** -1.5 == 0)
+        m.o = Objective(expr=m.z)
+        m.y.fix(-7)
+        m.x.fix(4)
+        lbl = NumericLabeler('x')
+        smap = SymbolMap(lbl)
+        tc = StorageTreeChecker(m)
+        self.assertEqual(expression_to_string(
+            m.c.body, tc, smap=smap), "(4)*(-7)*(-2)")
+        self.assertEqual(expression_to_string(
+            m.c2.body, tc, smap=smap), "x1 ** (-1.5)")
 
 
 class TestGams_writer(unittest.TestCase):
@@ -158,7 +270,7 @@ def _cleanup(self, fname):
     def _get_fnames(self):
         class_name, test_name = self.id().split('.')[-2:]
         prefix = os.path.join(thisdir, test_name.replace("test_", "", 1))
-        return prefix+".gams.baseline", prefix+".gams.out"
+        return prefix + ".gams.baseline", prefix + ".gams.out"
 
     def test_var_on_other_model(self):
         other = ConcreteModel()
@@ -166,7 +278,7 @@ def test_var_on_other_model(self):
 
         model = ConcreteModel()
         model.x = Var()
-        model.c = Constraint(expr=other.a + 2*model.x <= 0)
+        model.c = Constraint(expr=other.a + 2 * model.x <= 0)
         model.obj = Objective(expr=model.x)
 
         baseline_fname, test_fname = self._get_fnames()
@@ -179,14 +291,14 @@ def test_var_on_other_model(self):
     def test_var_on_nonblock(self):
         class Foo(Block().__class__):
             def __init__(self, *args, **kwds):
-                kwds.setdefault('ctype',Foo)
-                super(Foo,self).__init__(*args, **kwds)
+                kwds.setdefault('ctype', Foo)
+                super(Foo, self).__init__(*args, **kwds)
 
         model = ConcreteModel()
         model.x = Var()
         model.other = Foo()
         model.other.a = Var()
-        model.c = Constraint(expr=model.other.a + 2*model.x <= 0)
+        model.c = Constraint(expr=model.other.a + 2 * model.x <= 0)
         model.obj = Objective(expr=model.x)
 
         baseline_fname, test_fname = self._get_fnames()
@@ -196,5 +308,6 @@ def __init__(self, *args, **kwds):
             model.write, test_fname, format='gams')
         self._cleanup(test_fname)
 
+
 if __name__ == "__main__":
     unittest.main()
diff --git a/pyomo/repn/tests/test_gams.py b/pyomo/repn/tests/test_gams.py
deleted file mode 100644
--- a/pyomo/repn/tests/test_gams.py
+++ /dev/null
@@ -1,108 +0,0 @@
-#  ___________________________________________________________________________
-#
-#  Pyomo: Python Optimization Modeling Objects
-#  Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
-#  Under the terms of Contract DE-NA0003525 with National Technology and
-#  Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
-#  rights in this software.
-#  This software is distributed under the 3-clause BSD License.
-#  ___________________________________________________________________________
-
-import pyutilib.th as unittest
-from pyomo.core.base import NumericLabeler, SymbolMap
-from pyomo.environ import (Block, ConcreteModel, Connector, Constraint,
-                           Objective, Var, TransformationFactory)
-from pyomo.repn.plugins.gams_writer import (
-    expression_to_string, split_long_line, StorageTreeChecker)
-from six import StringIO
-
-
-class GAMSTests(unittest.TestCase):
-
-    def test_power_function_to_string(self):
-        m = ConcreteModel()
-        m.x = Var()
-        lbl = NumericLabeler('x')
-        smap = SymbolMap(lbl)
-        tc = StorageTreeChecker(m)
-        self.assertEqual(expression_to_string(
-            m.x ** -3, tc, lbl, smap=smap), "power(x1, -3)")
-        self.assertEqual(expression_to_string(
-            m.x ** 0.33, tc, smap=smap), "x1 ** 0.33")
-        self.assertEqual(expression_to_string(
-            pow(m.x, 2), tc, smap=smap), "power(x1, 2)")
-
-    def test_fixed_var_to_string(self):
-        m = ConcreteModel()
-        m.x = Var()
-        m.y = Var()
-        m.z = Var()
-        m.z.fix(-3)
-        lbl = NumericLabeler('x')
-        smap = SymbolMap(lbl)
-        tc = StorageTreeChecker(m)
-        self.assertEqual(expression_to_string(
-            m.x + m.y - m.z, tc, lbl, smap=smap), "x1 + x2 - (-3)")
-        m.z.fix(-400)
-        self.assertEqual(expression_to_string(
-            m.z + m.y - m.z, tc, smap=smap), "(-400) + x2 - (-400)")
-        m.z.fix(8.8)
-        self.assertEqual(expression_to_string(
-            m.x + m.z - m.y, tc, smap=smap), "x1 + (8.8) - x2")
-        m.z.fix(-8.8)
-        self.assertEqual(expression_to_string(
-            m.x * m.z - m.y, tc, smap=smap), "x1*(-8.8) - x2")
-
-    def test_gams_connector_in_active_constraint(self):
-        m = ConcreteModel()
-        m.b1 = Block()
-        m.b2 = Block()
-        m.b1.x = Var()
-        m.b2.x = Var()
-        m.b1.c = Connector()
-        m.b1.c.add(m.b1.x)
-        m.b2.c = Connector()
-        m.b2.c.add(m.b2.x)
-        m.c = Constraint(expr=m.b1.c == m.b2.c)
-        m.o = Objective(expr=m.b1.x)
-        os = StringIO()
-        with self.assertRaises(RuntimeError):
-            m.write(os, format="gams")
-
-    def test_gams_expanded_connectors(self):
-        m = ConcreteModel()
-        m.x = Var()
-        m.y = Var()
-        m.CON1 = Connector()
-        m.CON1.add(m.x, 'v')
-        m.CON2 = Connector()
-        m.CON2.add(m.y, 'v')
-        m.c = Constraint(expr=m.CON1 + m.CON2 >= 10)
-        TransformationFactory("core.expand_connectors").apply_to(m)
-        m.o = Objective(expr=m.x)
-        os = StringIO()
-        io_options = dict(symbolic_solver_labels=True)
-        m.write(os, format="gams", io_options=io_options)
-        # no error if we're here, but check for some identifying string
-        self.assertIn("x + y", os.getvalue())
-
-    def test_split_long_line(self):
-        pat = "var1 + log(var2 / 9) - "
-        line = (pat * 10000) + "x"
-        self.assertEqual(split_long_line(line),
-            pat * 3478 + "var1 +\nlog(var2 / 9) - " +
-            pat * 3477 + "var1 +\nlog(var2 / 9) - " +
-            pat * 3043 + "x")
-
-    def test_solver_arg(self):
-        m = ConcreteModel()
-        m.x = Var()
-        m.c = Constraint(expr=m.x == 2)
-        m.o = Objective(expr=m.x)
-        os = StringIO()
-        m.write(os, format="gams", io_options=dict(solver="gurobi"))
-        self.assertIn("option lp=gurobi", os.getvalue())
-
-
-if __name__ == "__main__":
-    unittest.main()