Quiero generar un ejemplo de juguete para ilustrar una función lineal convexa por partes en python , pero no pude encontrar la mejor manera de hacerlo. Lo que quiero hacer es indicar el número de líneas y generar la función aleatoriamente.
Una función lineal por partes convexa se define como:
Por ejemplo, si quiero tener cuatro líneas lineales, quiero generar algo como se muestra a continuación.
Ya que hay cuatro líneas. Necesito generar cuatro enteros aleatorios crecientes para determinar los intervalos en el eje x.
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]Ahora puedo usar los primeros dos puntos y crear una función lineal aleatoria, pero no sé cómo debo continuar desde allí para preservar la convexidad. Tenga en cuenta que una función se llama convexa si el segmento de línea entre dos puntos en el gráfico de la función no se encuentra debajo del gráfico entre los dos puntos.
La pendiente aumenta monótonamente en un valor aleatorio del rango [0,1), a partir de 0. El primer valor de y también es cero, ver los comentarios.
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 0Una posible salida se ve así:
print(x_points) print(y_points) # [ 0 1 4 13 16] # [ 0. 0. 2.57383685 17.92061306 24.90689622]Para imprimir esta figura:
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()asegúrese de que el gradiente (=dx/dy) esté aumentando. Pseudocódigo:
s = 1; x = 0; y = 0; n = 4; while(--n>0) { //increase x randomly dx = rand(3); dy = dx * s; x += dx; y += dy; //increase gradient randomly s += rand(3); print x + "/" +y; }