# Maximize the sum of logistic curves subject to linear and piecewise linear constraints. # Approximate the logistic curves using piecewise linear functions. # # (C) 2020-2025 Fair Isaac Corporation import numpy as np import xpress as xp import matplotlib.pyplot as plt def logistic(x, K, r, c): return K / (1 + np.exp(-r * (x - c))) n_curves = 10 N = range(n_curves) U = 10 # Upper bound of the variables. # Create a problem and add these two vectors. p = xp.problem() # Create two numpy vectors of variables. x = p.addVariables(n_curves, ub=U, name='x') y = p.addVariables(n_curves, name='y') n_intervals = 100 # Define the breakpoints of the piecewise linear terms. breakpoints = np.array([(U / n_intervals) * i for i in range(n_intervals + 1)]) # Compute the function values at breakpoints. y_vals = [logistic(breakpoints, U, np.random.uniform(0.5, 3), U / 2) for _ in N] # Enable to visualize curves. for i in N: plt.plot(breakpoints, y_vals[i]) y_vals = np.array(y_vals).flatten().tolist() x_vals = np.array([]) for i in N: x_vals = np.concatenate((x_vals, breakpoints)) x_vals = x_vals.tolist() # Set the starting indices for the flattened piecewise linear function definitions. start = [i * (n_intervals + 1) for i in N] # Add piecewise linear functions. p.addPwlCons(x, y, start, x_vals, y_vals) # Add a constraint that limits the weighted sum of x variables. w = np.random.randint(1, 10, n_curves) p.addConstraint(xp.Dot(w, x) <= 10) # Maximize the sum of logistic functions. p.setObjective(xp.Dot(np.ones(n_curves), y), sense=xp.maximize) p.writeProb('test_logistic.mps') p.optimize()