.. _tutconditions: ========== Conditions ========== IfElse vs Switch ================ - Both ops build a condition over symbolic variables. - ``IfElse`` takes a *boolean* condition and two variables as inputs. - ``Switch`` takes a *tensor* as condition and two variables as inputs. ``switch`` is an elementwise operation and is thus more general than ``ifelse``. - Whereas ``switch`` evaluates both *output* variables, ``ifelse`` is lazy and only evaluates one variable with respect to the condition. **Example** .. testcode:: from pytensor import tensor as pt from pytensor.ifelse import ifelse import pytensor, time, numpy a,b = pt.scalars('a', 'b') x,y = pt.matrices('x', 'y') z_switch = pt.switch(pt.lt(a, b), pt.mean(x), pt.mean(y)) z_lazy = ifelse(pt.lt(a, b), pt.mean(x), pt.mean(y)) f_switch = pytensor.function([a, b, x, y], z_switch, mode=pytensor.compile.mode.Mode(linker='vm')) f_lazyifelse = pytensor.function([a, b, x, y], z_lazy, mode=pytensor.compile.mode.Mode(linker='vm')) val1 = 0. val2 = 1. big_mat1 = numpy.ones((10000, 1000)) big_mat2 = numpy.ones((10000, 1000)) n_times = 10 tic = time.perf_counter() for i in range(n_times): f_switch(val1, val2, big_mat1, big_mat2) print('time spent evaluating both values %f sec' % (time.perf_counter() - tic)) tic = time.perf_counter() for i in range(n_times): f_lazyifelse(val1, val2, big_mat1, big_mat2) print('time spent evaluating one value %f sec' % (time.perf_counter() - tic)) .. testoutput:: :hide: :options: +ELLIPSIS time spent evaluating both values ... sec time spent evaluating one value ... sec In this example, the ``IfElse`` op spends less time (about half as much) than ``Switch`` since it computes only one variable out of the two. .. code-block:: none $ python ifelse_switch.py time spent evaluating both values 0.6700 sec time spent evaluating one value 0.3500 sec Unless ``linker='vm'`` or ``linker='cvm'`` are used, ``ifelse`` will compute both variables and take the same computation time as ``switch``. Although the linker is not currently set by default to ``cvm``, it will be in the near future. There is no automatic rewrite replacing a ``switch`` with a broadcasted scalar to an ``ifelse``, as this is not always faster. See this `ticket `_.