numexpr icon indicating copy to clipboard operation
numexpr copied to clipboard

Failed to evaluate simple expression '(a==1)| b'

Open semigodking opened this issue 6 years ago • 3 comments

The follow exception occurs when evaluating a simple expression.

>>> import numexpr as ne
>>> ne.evaluate('(a==1)| b', local_dict={'a': 0, 'b':1})
Traceback (most recent call last):
  File "/home/ubuntu/pes/venv/lib/python3.6/site-packages/numexpr/necompiler.py", line 813, in evaluate
    compiled_ex = _numexpr_cache[numexpr_key]
KeyError: ('(a==1)| b', (('optimization', 'aggressive'), ('truediv', False)), (('a', <class 'numpy.int64'>), ('b', <class 'numpy.int64'>)))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/ubuntu/pes/venv/lib/python3.6/site-packages/numexpr/necompiler.py", line 816, in evaluate
    NumExpr(ex, signature, **context)
  File "/home/ubuntu/pes/venv/lib/python3.6/site-packages/numexpr/necompiler.py", line 628, in NumExpr
    precompile(ex, signature, context)
  File "/home/ubuntu/pes/venv/lib/python3.6/site-packages/numexpr/necompiler.py", line 572, in precompile
    ast = typeCompileAst(ast)
  File "/home/ubuntu/pes/venv/lib/python3.6/site-packages/numexpr/necompiler.py", line 214, in typeCompileAst
    % (ast.value + '_' + retsig + basesig))
NotImplementedError: couldn't find matching opcode for 'or_bbl'

The following expression is okay.

>>> ne.evaluate('(a==1)| (b != 0)', local_dict={'a': 0, 'b':1})
array(True)

Tested with numexpr 2.6.5 with Python 3.6.2

semigodking avatar May 29 '18 07:05 semigodking

Logical operators (and, or) are only implemented for boolean type variables and not for integer type (even if the values are guaranteed to be always 0 or 1), so you have to somehow cast your integer variable to boolean. Unfortunately in numexpr 2.x there is no explicit casting possible, so you have to resort to comparing the value to cast it. I think this problem is solved by numexpr3 (either by supporting explicit casting or supporting logical operators on integers but I don't remember which).

See also https://github.com/pydata/numexpr/issues/96

gdementen avatar May 29 '18 08:05 gdementen

Cool. Let's wait for numexpr3. Thank you @gdementen . Should this ticket be closed?

semigodking avatar May 30 '18 06:05 semigodking

BTW, if it is still useful, you could use where to write that:

>>> numexpr.evaluate('where((a==1) | (b > 0), 1, 0)', local_dict={'a': 1, 'b':1})
array(1, dtype=int32)
>>> numexpr.evaluate('where((a==1) | (b > 0), 1, 0)', local_dict={'a': 1, 'b':0})
array(1, dtype=int32)
>>> numexpr.evaluate('where((a==1) | (b > 0), 1, 0)', local_dict={'a': 0, 'b':1})
array(1, dtype=int32)
>>> numexpr.evaluate('where((a==1) | (b > 0), 1, 0)', local_dict={'a': 0, 'b':0})
array(0, dtype=int32)

vallsv avatar Sep 28 '19 15:09 vallsv

Message to comment on stale issues. If none provided, will not mark issues stale

github-actions[bot] avatar Feb 19 '24 01:02 github-actions[bot]