# Case disjunction

## Limitations

Built-in python conditionnal structures are not compatible with vector calculus.
The following formula would for instance break:

# THIS IS NOT A VALID OPENFISCA FORMULA
def formula(person, period):
salary = person('salary', period)
if salary < 1000:
return 200
else:
return 0

Some solutions though exist to emulate these structures.

## Simple multiplication

Applying a condition is in many cases equivalent to a simple multiplication. For instance, our previous example can be rewritten:

def formula(person, period):
condition_salary = person('salary', period) < 1000
return condition_salary * 200

For a person, if condition_salary is True (equivalent to 1 in logical algebra), the returned result will be 200. However, if condition_salary is False (equivalent to 0), the returned result will be 0.

## Ternary condition

Let's now write a formula that still returns 200 if the person salary is lower than 1000, but 100 if this condition is not met.

The helper function where offers a simple syntax to handle these cases.

def formula(person, period):
condition_salary = person('salary', period) < 1000
return where(condition_salary, 200, 100)

where takes 3 arguments: the condition, the value to return if the condition is met, and the value to return otherwise.

## Multiples conditions

Let's consider a more complex case, where we want to attribute to a person:

• 200 if their salary is less than 500
• 100 if their salary is strictly more than 500, but less than 1000
• 50 if their salary is strictly more than 1000, but less than 1500
• 0 otherwise

We can use the helper function select to implement this behaviour:

def formula(person, period):
salary = person('salary', period)
return select(
[salary <= 500, salary <= 1000, salary <= 1500, salary > 1500],
[200, 100, 50, 0],
)

select takes two arguments:

• A list of conditions
• A list of values

If the first condition is met, the first value will be returned, without considering the other conditions. For instance, if salary = 100, salary <= 500 is true and therefore 200 will be returned. It doesn't matter that salary <= 1000 is also true.

If the first condition is not met, then only the second condition will be considered.

If no condition is met, 0 will be returned. The previous formula is thus strictly equivalent to:

def formula(person, period):
salary = person('salary', period)
return select(
[salary <= 500, salary <= 1000, salary <= 1500],
[200, 100, 50],
)

## Complex conditions

Complex conditions can be coded combining * as and and + as or.

For instance, let's consider that a person will be granted 200 if either:

- They are more than 25 *and* make less than `1000` per month
- They are in a situation of handicap
def formula(person, period):
condition_age = person('age') >= 25
condition_salary = person('salary', period) < 1000
condition_handicap = person('handicap')
condition = condition_age * condition_salary + condition_handicap
return condition * 200

It is considered a good practice to always use helpers where and select when they are relevant, and not to emulate their behaviour manually with logical operations.

## Using a dynamic parameter calculation

If the result of your formula depends on a variable that can take only a finite amount of values, check out the Computing a parameter that depends on a variable section.