.. _jython_discrete:

# Jython discrete functions

.. note::
    The following sections describe using RiskScape-based code from within a *Jython* function.
    Most Python users will probably find it simpler to setup RiskScape to use :ref:`cpython-impl`
    and use standard Python maths packages instead.

A discrete function can be constructed from points, constants and other
functions, to form a single function for use with risk analysis.

### Using points

The simplest use of a discrete function is to join up a series of points to
create a continuous sequence of lines between them.

``` python
from nz.org.riskscape.engine.function import DiscreteFunction

ID = 'joined-points'
DESCRIPTION = 'Demonstrates a function built by connecting points to form a series of linear functions'

FUNCTION = DiscreteFunction.builder() \
           .addPoint(-1, 4) \
           .addPoint(1, 6) \
           .addPoint(4, 8) \
           .addPoint(10, 10) \
           .withLinearInterpolation() \
           .build()
```

### Constants

As well as adding a point, a constant value can be added for a range:

```none
# will return 0.45 when 0 <= x <= 10
DiscreteFunction.builder().addConstant(0, 10, 0.45)
```

### Joining functions

Arbitrary RiskScape functions can be joined up to form a single function.  Each function is
added along with the range for which it's applicable:

``` python
from nz.org.riskscape.engine.function import DiscreteFunction, Maths

ID = 'joined-polynomials'
DESCRIPTION = 'Demonstrates a function built by connecting polynomials'


quadratic = Maths.newPolynomial(0, 8, 0.25)
cubic = Maths.newPolynomial(10, 0, 4, 0.5)

FUNCTION = DiscreteFunction.builder() \
           .addFunction(-10, -5, cubic) \
           .addFunction(40, 1000, polynomial) \
           .withLinearInterpolation() \
           .build()
```

### Ranges

By default, a discrete function will 'close' any upper bound on a range that
isn't connected to a higher range.  For example, adding the range
`addFunction(0, 10, somePolynomial)` will make that polynomial
apply when `0 <= x <= 10`.  However, if a function is added from 10 onwards,
then `somePolynomial` applies when `0 <= x < 10`.

This closing behaviour can be disabled by calling `.withoutUpperBoundClosing`
on the function builder.
