Repository: sympy/sympy

Issue:
simplification of Unions of ComplexRegions
```
>>> c1 = ComplexRegion(Interval(1, 2)*Interval(2, 3))
>>> c2 = ComplexRegion(Interval(1, 5)*Interval(1, 3))
>>> simplify(Union(c1, c2))
---------------------------------------------------------------------------
UnboundLocalError                         Traceback (most recent call last)
<ipython-input-20-c14828895520> in <module>()
----> 1 simplify(Union(c1, c2))

/home/gxyd/Public/sympy/sympy/simplify/simplify.py in simplify(expr, ratio, measure, fu)
    516     if not isinstance(expr, (Add, Mul, Pow, ExpBase)):
    517         return expr.func(*[simplify(x, ratio=ratio, measure=measure, fu=fu)
--> 518                          for x in expr.args])
    519 
    520     # TODO: Apply different strategies, considering expression pattern:

/home/gxyd/Public/sympy/sympy/sets/fancysets.py in __new__(cls, sets, polar)
    673                                    r*(cos(theta) + I*sin(theta))),
    674                                    sets)
--> 675         return obj
    676 
    677     @property

UnboundLocalError: local variable 'obj' referenced before assignment
```

Discussion:

Patch:
diff --git a/sympy/printing/latex.py b/sympy/printing/latex.py
index 46d81b7cd8..4b8e799d92 100644
--- a/sympy/printing/latex.py
+++ b/sympy/printing/latex.py
@@ -1574,9 +1574,9 @@ def _print_ConditionSet(self, s):
             self._print(s.condition.as_expr()))
 
     def _print_ComplexRegion(self, s):
-        vars_print = ', '.join([self._print(var) for var in s.args[0].variables])
+        vars_print = ', '.join([self._print(var) for var in s.variables])
         return r"\left\{%s\; |\; %s \in %s \right\}" % (
-            self._print(s.args[0].expr),
+            self._print(s.expr),
             vars_print,
             self._print(s.sets))
 
diff --git a/sympy/printing/pretty/pretty.py b/sympy/printing/pretty/pretty.py
index dc910fc4ce..644c00953f 100644
--- a/sympy/printing/pretty/pretty.py
+++ b/sympy/printing/pretty/pretty.py
@@ -1567,8 +1567,8 @@ def _print_ComplexRegion(self, ts):
             inn = u("\N{SMALL ELEMENT OF}")
         else:
             inn = 'in'
-        variables = self._print_seq(ts.args[0].variables)
-        expr = self._print(ts.args[0].expr)
+        variables = self._print_seq(ts.variables)
+        expr = self._print(ts.expr)
         bar = self._print("|")
         prodsets = self._print(ts.sets)
 
diff --git a/sympy/sets/fancysets.py b/sympy/sets/fancysets.py
index 1a45f9ae70..3cb2827588 100644
--- a/sympy/sets/fancysets.py
+++ b/sympy/sets/fancysets.py
@@ -568,7 +568,7 @@ class ComplexRegion(Set):
     >>> c = Interval(1, 8)
     >>> c1 = ComplexRegion(a*b)  # Rectangular Form
     >>> c1
-    ComplexRegion(Lambda((_x, _y), _x + _y*I), [2, 3] x [4, 6])
+    ComplexRegion([2, 3] x [4, 6], False)
 
     * c1 represents the rectangular region in complex plane
       surrounded by the coordinates (2, 4), (3, 4), (3, 6) and
@@ -576,8 +576,7 @@ class ComplexRegion(Set):
 
     >>> c2 = ComplexRegion(Union(a*b, b*c))
     >>> c2
-    ComplexRegion(Lambda((_x, _y), _x + _y*I),
-                 [2, 3] x [4, 6] U [4, 6] x [1, 8])
+    ComplexRegion([2, 3] x [4, 6] U [4, 6] x [1, 8], False)
 
     * c2 represents the Union of two rectangular regions in complex
       plane. One of them surrounded by the coordinates of c1 and
@@ -593,8 +592,7 @@ class ComplexRegion(Set):
     >>> theta = Interval(0, 2*S.Pi)
     >>> c2 = ComplexRegion(r*theta, polar=True)  # Polar Form
     >>> c2  # unit Disk
-    ComplexRegion(Lambda((_r, _theta), _r*(I*sin(_theta) + cos(_theta))),
-                 [0, 1] x [0, 2*pi))
+    ComplexRegion([0, 1] x [0, 2*pi), True)
 
     * c2 represents the region in complex plane inside the
       Unit Disk centered at the origin.
@@ -608,7 +606,7 @@ class ComplexRegion(Set):
     >>> upper_half_unit_disk = ComplexRegion(Interval(0, 1)*Interval(0, S.Pi), polar=True)
     >>> intersection = unit_disk.intersect(upper_half_unit_disk)
     >>> intersection
-    ComplexRegion(Lambda((_r, _theta), _r*(I*sin(_theta) + cos(_theta))), [0, 1] x [0, pi])
+    ComplexRegion([0, 1] x [0, pi], True)
     >>> intersection == upper_half_unit_disk
     True
 
@@ -621,14 +619,14 @@ class ComplexRegion(Set):
     is_ComplexRegion = True
 
     def __new__(cls, sets, polar=False):
-        from sympy import symbols, Dummy
+        from sympy import symbols, Dummy, sympify, sin, cos
 
         x, y, r, theta = symbols('x, y, r, theta', cls=Dummy)
         I = S.ImaginaryUnit
+        polar = sympify(polar)
 
         # Rectangular Form
-        if polar is False:
-
+        if polar == False:
             if all(_a.is_FiniteSet for _a in sets.args) and (len(sets.args) == 2):
 
                 # ** ProductSet of FiniteSets in the Complex Plane. **
@@ -639,34 +637,38 @@ def __new__(cls, sets, polar=False):
                     for y in sets.args[1]:
                         complex_num.append(x + I*y)
                 obj = FiniteSet(*complex_num)
-
             else:
                 obj = ImageSet.__new__(cls, Lambda((x, y), x + I*y), sets)
+            obj._variables = (x, y)
+            obj._expr = x + I*y
 
         # Polar Form
-        elif polar is True:
+        elif polar == True:
             new_sets = []
-
             # sets is Union of ProductSets
             if not sets.is_ProductSet:
                 for k in sets.args:
                     new_sets.append(k)
-
             # sets is ProductSets
             else:
                 new_sets.append(sets)
-
             # Normalize input theta
             for k, v in enumerate(new_sets):
                 from sympy.sets import ProductSet
                 new_sets[k] = ProductSet(v.args[0],
                                          normalize_theta_set(v.args[1]))
             sets = Union(*new_sets)
-
-            from sympy import cos, sin
             obj = ImageSet.__new__(cls, Lambda((r, theta),
                                    r*(cos(theta) + I*sin(theta))),
                                    sets)
+            obj._variables = (r, theta)
+            obj._expr = r*(cos(theta) + I*sin(theta))
+
+        else:
+            raise ValueError("polar should be either True or False")
+
+        obj._sets = sets
+        obj._polar = polar
         return obj
 
     @property
@@ -689,7 +691,19 @@ def sets(self):
         [2, 3] x [4, 5] U [4, 5] x [1, 7]
 
         """
-        return self.args[1]
+        return self._sets
+
+    @property
+    def args(self):
+        return (self._sets, self._polar)
+
+    @property
+    def variables(self):
+        return self._variables
+
+    @property
+    def expr(self):
+        return self._expr
 
     @property
     def psets(self):
@@ -711,11 +725,11 @@ def psets(self):
         ([2, 3] x [4, 5], [4, 5] x [1, 7])
 
         """
-        if self.args[1].is_ProductSet:
+        if self.sets.is_ProductSet:
             psets = ()
-            psets = psets + (self.args[1], )
+            psets = psets + (self.sets, )
         else:
-            psets = self.args[1].args
+            psets = self.sets.args
         return psets
 
     @property
@@ -795,7 +809,7 @@ def polar(self):
         >>> C2.polar
         True
         """
-        return self.args[0].args[1].is_Mul
+        return self._polar
 
     @property
     def _measure(self):


Test patch:
diff --git a/sympy/sets/tests/test_fancysets.py b/sympy/sets/tests/test_fancysets.py
index 002f5d7537..d8d5028f98 100644
--- a/sympy/sets/tests/test_fancysets.py
+++ b/sympy/sets/tests/test_fancysets.py
@@ -3,6 +3,7 @@
                                   ComplexRegion)
 from sympy.sets.sets import (FiniteSet, Interval, imageset, EmptySet, Union,
                              Intersection)
+from sympy.simplify.simplify import simplify
 from sympy import (S, Symbol, Lambda, symbols, cos, sin, pi, oo, Basic,
                    Rational, sqrt, tan, log, Abs, I)
 from sympy.utilities.pytest import XFAIL, raises
@@ -460,3 +461,13 @@ def test_ComplexRegion_FiniteSet():
 def test_union_RealSubSet():
     assert (S.Complexes).union(Interval(1, 2)) == S.Complexes
     assert (S.Complexes).union(S.Integers) == S.Complexes
+
+
+def test_issue_9980():
+    c1 = ComplexRegion(Interval(1, 2)*Interval(2, 3))
+    c2 = ComplexRegion(Interval(1, 5)*Interval(1, 3))
+    R = Union(c1, c2)
+    assert simplify(R) == ComplexRegion(Union(Interval(1, 2)*Interval(2, 3), \
+                                    Interval(1, 5)*Interval(1, 3)), False)
+    assert c1.func(*c1.args) == c1
+    assert R.func(*R.args) == R