Repository: QuantEcon/QuantEcon.py

Issue:
Error Raised in `qe.random.draw`
Hi @Smit-create,

I encountered this error in the intermediate lecture (full error report [here](https://github.com/QuantEcon/lecture-python.myst/suites/12947474113/artifacts/703752939). It is related to the `draw` function in [`random.utilities`](https://github.com/QuantEcon/QuantEcon.py/blob/main/quantecon/random/utilities.py#L173). 

The error appears in this function and is temporarily resolved by changing `qe.random.draw(cdf)` to `qe.random.draw(cdf, 1)`.

```
cdf = np.cumsum(q_default)

@jit(nopython=True)
def compute_stopping_time(w_bar, seed=1234):

    np.random.seed(seed)
    t = 1
    while True:
        # Generate a wage draw
        w = w_default[qe.random.draw(cdf)]
        # Stop when the draw is above the reservation wage
        if w >= w_bar:
            stopping_time = t
            break
        else:
            t += 1
    return stopping_time

@jit(nopython=True)
def compute_mean_stopping_time(w_bar, num_reps=100000):
    obs = np.empty(num_reps)
    for i in range(num_reps):
        obs[i] = compute_stopping_time(w_bar, seed=i)
    return obs.mean()

c_vals = np.linspace(10, 40, 25)
stop_times = np.empty_like(c_vals)
for i, c in enumerate(c_vals):
    mcm = McCallModel(c=c)
    w_bar = compute_reservation_wage_two(mcm)
    stop_times[i] = compute_mean_stopping_time(w_bar)

fig, ax = plt.subplots()

ax.plot(c_vals, stop_times, label="mean unemployment duration")
ax.set(xlabel="unemployment compensation", ylabel="months")
ax.legend()

plt.show()
```
The error message is
```
[0;31mTypingError[0m: Failed in nopython mode pipeline (step: nopython frontend)
[1m[1m[1m[1mFailed in nopython mode pipeline (step: nopython frontend)
[1m[1m[1mNo implementation of function Function(<function draw at 0x7f88556a4af0>) found for signature:
 
 >>> draw(readonly array(float64, 1d, C))
 
There are 2 candidate implementations:
[1m   - Of which 2 did not match due to:
   Overload in function 'ol_draw': File: quantecon/random/utilities.py: Line 213.
     With argument(s): '(readonly array(float64, 1d, C))':[0m
[1m    Rejected as the implementation raised a specific error:
      TypingError: [1mmissing a required argument: 'size'[0m[0m
  raised from /opt/conda/envs/quantecon/lib/python3.10/site-packages/numba/core/typing/templates.py:791
[0m
[0m[1mDuring: resolving callee type: Function(<function draw at 0x7f88556a4af0>)[0m
[0m[1mDuring: typing of call at /tmp/ipykernel_4408/474854781.py (10)
[0m
[1m
File "../../../../tmp/ipykernel_4408/474854781.py", line 10:[0m
[1m<source missing, REPL/exec in use?>[0m

[0m[1mDuring: resolving callee type: type(CPUDispatcher(<function compute_stopping_time at 0x7f884d71c280>))[0m
[0m[1mDuring: typing of call at /tmp/ipykernel_4408/474854781.py (23)
[0m
[0m[1mDuring: resolving callee type: type(CPUDispatcher(<function compute_stopping_time at 0x7f884d71c280>))[0m
[0m[1mDuring: typing of call at /tmp/ipykernel_4408/474854781.py (23)
[0m
[1m
File "../../../../tmp/ipykernel_4408/474854781.py", line 23:[0m
[1m<source missing, REPL/exec in use?>[0m

TypingError: Failed in nopython mode pipeline (step: nopython frontend)
[1m[1m[1m[1mFailed in nopython mode pipeline (step: nopython frontend)
[1m[1m[1mNo implementation of function Function(<function draw at 0x7f88556a4af0>) found for signature:
 
 >>> draw(readonly array(float64, 1d, C))
 
There are 2 candidate implementations:
[1m   - Of which 2 did not match due to:
   Overload in function 'ol_draw': File: quantecon/random/utilities.py: Line 213.
     With argument(s): '(readonly array(float64, 1d, C))':[0m
[1m    Rejected as the implementation raised a specific error:
      TypingError: [1mmissing a required argument: 'size'[0m[0m
  raised from /opt/conda/envs/quantecon/lib/python3.10/site-packages/numba/core/typing/templates.py:791
[0m
[0m[1mDuring: resolving callee type: Function(<function draw at 0x7f88556a4af0>)[0m
[0m[1mDuring: typing of call at /tmp/ipykernel_4408/474854781.py (10)
[0m
[1m
File "../../../../tmp/ipykernel_4408/474854781.py", line 10:[0m
[1m<source missing, REPL/exec in use?>[0m

[0m[1mDuring: resolving callee type: type(CPUDispatcher(<function compute_stopping_time at 0x7f884d71c280>))[0m
[0m[1mDuring: typing of call at /tmp/ipykernel_4408/474854781.py (23)
[0m
[0m[1mDuring: resolving callee type: type(CPUDispatcher(<function compute_stopping_time at 0x7f884d71c280>))[0m
[0m[1mDuring: typing of call at /tmp/ipykernel_4408/474854781.py (23)
[0m
[1m
File "../../../../tmp/ipykernel_4408/474854781.py", line 23:[0m
[1m<source missing, REPL/exec in use?>[0m
```
Would you mind having a look into this error?

Many thanks in advance.

Discussion:

Patch:
diff --git a/quantecon/random/utilities.py b/quantecon/random/utilities.py
index a94fbc0..f1b53f5 100644
--- a/quantecon/random/utilities.py
+++ b/quantecon/random/utilities.py
@@ -211,16 +211,16 @@ def draw(cdf, size=None):
 
 # Overload for the `draw` function
 @overload(draw)
-def ol_draw(cdf, size):
+def ol_draw(cdf, size=None):
     if isinstance(size, types.Integer):
-        def draw_impl(cdf, size):
+        def draw_impl(cdf, size=None):
             rs = np.random.random(size)
             out = np.empty(size, dtype=np.int_)
             for i in range(size):
                 out[i] = searchsorted(cdf, rs[i])
             return out
     else:
-        def draw_impl(cdf, size):
+        def draw_impl(cdf, size=None):
             r = np.random.random()
             return searchsorted(cdf, r)
     return draw_impl


Test patch:
diff --git a/quantecon/random/tests/test_utilities.py b/quantecon/random/tests/test_utilities.py
index f743064..430c7a1 100644
--- a/quantecon/random/tests/test_utilities.py
+++ b/quantecon/random/tests/test_utilities.py
@@ -108,3 +108,14 @@ class TestDraw:
             pmf_computed = hist * np.diff(bin_edges)
             atol = 1e-2
             assert_allclose(pmf_computed, self.pmf, atol=atol)
+
+
+@njit
+def draw_jitted_w_o_size(n):
+    cdf = np.linspace(1/n, 1, n)
+    return draw(cdf)
+
+
+def test_draw_jitted_w_o_size():
+    n = 3
+    assert_(draw_jitted_w_o_size(n) in range(n))