Repository: nv-legate/cunumeric

Issue:
[BUG] Einstein summation errors when bool passed to 'optimize' arg
### Software versions

.

### Jupyter notebook / Jupyter Lab version

_No response_

### Expected behavior

.

### Observed behavior

.

### Example code or instructions

```Python
import cunumeric as cn

w = cn.zeros(10)
cn.einsum('i->i', w, optimize=True)
```


### Stack traceback or browser console output
[0 - 7f8f6183b000]    1.896067 {6}{python}: python exception occurred within task:
Traceback (most recent call last):
  File "/home/nfs/rorym/anaconda3/envs/legate-test/lib/python3.10/site-packages/legion_top.py", line 475, in legion_python_main
    run_path(args[start], '__main__')
  File "/home/nfs/rorym/anaconda3/envs/legate-test/lib/python3.10/site-packages/legion_top.py", line 295, in run_path
    exec(code, module.__dict__, module.__dict__)
  File "random_experiments/einsum_repro.py", line 4, in <module>
    cn.einsum('i->i', w, optimize=True)
  File "/home/nfs/rorym/anaconda3/envs/legate-test/lib/python3.10/site-packages/legate/core/runtime.py", line 2153, in wrapper
    result = func(*args, **kwargs)
  File "/home/nfs/rorym/anaconda3/envs/legate-test/lib/python3.10/site-packages/cunumeric/coverage.py", line 119, in wrapper
    return func(*args, **kwargs)
  File "/home/nfs/rorym/anaconda3/envs/legate-test/lib/python3.10/site-packages/cunumeric/module.py", line 4665, in einsum
    computed_operands, contractions = oe.contract_path(
  File "/home/nfs/rorym/anaconda3/envs/legate-test/lib/python3.10/site-packages/opt_einsum/contract.py", line 276, in contract_path
    for cnum, contract_inds in enumerate(path):
TypeError: 'bool' object is not iterable


Discussion:

Resolving patch:
diff --git a/cunumeric/module.py b/cunumeric/module.py
--- a/cunumeric/module.py
+++ b/cunumeric/module.py
@@ -4587,7 +4587,7 @@ def einsum(
     out: Optional[ndarray] = None,
     dtype: Optional[np.dtype[Any]] = None,
     casting: CastingKind = "safe",
-    optimize: Union[bool, str] = False,
+    optimize: Union[bool, Literal["greedy", "optimal"]] = True,
 ) -> ndarray:
     """
     Evaluates the Einstein summation convention on the operands.
@@ -4628,9 +4628,10 @@ def einsum(
 
         Default is 'safe'.
     optimize : ``{False, True, 'greedy', 'optimal'}``, optional
-        Controls if intermediate optimization should occur. No optimization
-        will occur if False. Uses opt_einsum to find an optimized contraction
-        plan if True.
+        Controls if intermediate optimization should occur. If False then
+        arrays will be contracted in input order, one at a time. True (the
+        default) will use the 'greedy' algorithm. See ``cunumeric.einsum_path``
+        for more information on the available optimization algorithms.
 
     Returns
     -------
@@ -4654,7 +4655,9 @@ def einsum(
     if out is not None:
         out = convert_to_cunumeric_ndarray(out, share=True)
 
-    if not optimize:
+    if optimize is True:
+        optimize = "greedy"
+    elif optimize is False:
         optimize = NullOptimizer()
 
     # This call normalizes the expression (adds the output part if it's


Test patch:
diff --git a/tests/integration/test_einsum.py b/tests/integration/test_einsum.py
--- a/tests/integration/test_einsum.py
+++ b/tests/integration/test_einsum.py
@@ -272,7 +272,7 @@ def test_cast(expr, dtype):
         False,
         "optimal",
         "greedy",
-        pytest.param(True, marks=pytest.mark.xfail),
+        True,
     ],
 )
 def test_optimize(optimize):
@@ -282,8 +282,6 @@ def test_optimize(optimize):
     np_res = np.einsum("ik,kj->ij", a, b, optimize=optimize)
     num_res = num.einsum("ik,kj->ij", a, b, optimize=optimize)
     assert allclose(np_res, num_res)
-    # when optimize=True, cunumeric raises
-    # TypeError: 'bool' object is not iterable
 
 
 def test_expr_opposite():