Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to generate a random convex piecewise-linear function

I want to generate a toy example to illustrate a convex piecewise linear function in python, but I couldn't figure out the best way to do this. What I want to do is to indicate the number of lines and generate the function randomly.

A convex piecewise-linear function is defined as:

1

For instance, if I want to have four linear lines, then I want to generate something as shown below.

enter image description here

Since there are four lines. I need to generate four increasing random integers to determine the intervals in x-axis.

import random 
import numpy as np
random.seed(1)

x_points = np.array(random.sample(range(1, 20), 4))
x_points.sort()
x_points = np.append(0, x_points)

x_points
[0 3 4 5 9]

I can now use the first two points and create a random linear function, but I don't know how I should continue from there to preserve the convexity. Note that a function is called convex if the line segment between any two points on the graph of the function does not lie below the graph between the two points.

like image 708
belcansi Avatar asked Dec 26 '21 19:12

belcansi


People also ask

What is convex piecewise linear function?

Piecewise-linear functions are functions for which there are defined intervals over which the function is linear. Definition 1. A function f : Rn → R is a convex piecewise-linear if there exist c1,...,cN ∈ Rn. and d1,...,dN ∈ R s.t. f(x) = maxi∈[N] cT. i x + di.

Are piecewise functions convex?

Yes, it can be convex. Take f(x) = |x|. It is a piecewise convex function, and overall, convex. Similarly, g(x) = -|x| is piecewise convex but not convex overall, when you consider the linear sections together.


1 Answers

The slope increases monotonously by a random value from the range [0,1), starting from 0. The first y value is also zero, see the comments.

import numpy as np
np.random.seed(0)

x_points = np.random.randint(low=1, high=20, size=4)
x_points.sort()
x_points = np.append(0, x_points)  # the first 0 point is 0

slopes = np.add.accumulate(np.random.random(size=3))
slopes = np.append(0,slopes)  # the first slope is 0

y_incr = np.ediff1d(x_points)*slopes
y_points = np.add.accumulate(y_incr)
y_points = np.append(0,y_points)  # the first y values is 0

A possible output looks like this:

print(x_points)
print(y_points)
# [ 0  1  4 13 16]
# [ 0.          0.          2.57383685 17.92061306 24.90689622]

enter image description here

To print this figure:

import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.plot(x_points,y_points, '-o', label="convex piecewise-linear function")
ax.legend()
fig.patch.set_facecolor('white')
plt.show()
like image 127
DanielTuzes Avatar answered Sep 21 '22 12:09

DanielTuzes