Source code for BsplineQuantRegpy.examples.logistic_example

#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
Script de test avec la fonction logistique et différentes contraintes.
Peut être exécuté indépendamment ou appelé depuis la GUI.
"""

import numpy as np
import matplotlib.pyplot as plt
import sys
import os
"""
Script de test pour degrés 1
"""


# Ajouter le chemin du projet si exécuté indépendamment
if __name__ == "__main__":
    PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    SRC_PATH = os.path.join(PROJECT_ROOT, 'src')
    if SRC_PATH not in sys.path:
        sys.path.insert(0, SRC_PATH)



from BsplineQuantRegpy import (
    SplineLinearQuant,
    SplineQuadraticQuant,
    SplineCubicQuant,
    SplineQuarticQuant,
    quantile_spline
)




[docs] def run_logistic_example(show_plots=True, return_data=False,degree=3): """ Exécute le test avec la fonction logistique. Parameters ---------- show_plots : bool Afficher les graphiques return_data : bool Retourner les données générées Returns ------- dict or None Données si return_data=True """ print("=" * 70) print("TEST FONCTION LOGISTIQUE - RÉGRESSION QUANTILE CONTRAINTE") print("=" * 70) np.random.seed(42) n_points = 100 xtab =np.linspace(0, 1, n_points) # Fonction logistique: f(x) = exp(-5+10x) / (1 + exp(-5+10x)) ytab = np.exp(-5 + 10*xtab) / (1 + np.exp(-5 + 10*xtab)) + 0.2 * np.random.randn(n_points) kn = 12 knots = np.quantile(xtab, np.linspace(0, 1, kn + 1)) print(f"degré: {degree}") print(f"Nombre de points: {n_points}") print(f"Nombre de nœuds: {kn}") print(f"Point d'inflexion: 0.5") # Quantiles à tester quantiles = [0.1, 0.5, 0.9] solver = 'CLARABEL' # Définition des contraintes monot_uniform = 1 # Croissante partout # Convexité: concave puis convexe (point d'inflexion à 0.5) cv_mixed = np.zeros(kn + 1) for i in range(kn + 1): x_pos = knots[i] if i < len(knots) else knots[-1] if x_pos < 0.5: cv_mixed[i] = 1 # Concave avant 0.5 else: cv_mixed[i] = -1 # Convexe après 0.5 der3 = -1 results = { 'x': xtab, 'y': ytab, 'knots': knots, 'quantiles': quantiles, 'results': {} } # Exécuter les régressions pour chaque quantile for tau in quantiles: results['results'][tau] = {} # Sans contrainte try: res = quantile_spline(xtab, ytab, knots, tau, monot=0, cv=0, der3=0, solver=solver,degree=degree) results['results'][tau]['none'] = res print(f"✓ τ={tau}: Sans contrainte OK") except Exception as e: print(f"✗ τ={tau}: Sans contrainte {e}") results['results'][tau]['none'] = None # Croissante try: res = quantile_spline(xtab, ytab, knots, tau, monot=monot_uniform, cv=0, der3=0, solver=solver,degree=degree) results['results'][tau]['monot'] = res print(f"✓ τ={tau}: Croissante OK") except Exception as e: print(f"✗ τ={tau}: Croissante {e}") results['results'][tau]['monot'] = None # Convexité mixte try: res = quantile_spline(xtab, ytab, knots, tau, monot=0, cv=cv_mixed, der3=0, solver=solver,degree=degree) results['results'][tau]['cv_mixed'] = res print(f"✓ τ={tau}: Convexité mixte OK") except Exception as e: print(f"✗ τ={tau}: Convexité mixte {e}") results['results'][tau]['cv_mixed'] = None # Croissante + Convexité mixte try: res = quantile_spline(xtab, ytab, knots, tau, monot=monot_uniform, cv=cv_mixed, der3=0, solver=solver,degree=degree) results['results'][tau]['monot_cv'] = res print(f"✓ τ={tau}: Croissante+Convexité OK") except Exception as e: print(f"✗ τ={tau}: Croissante+Convexité {e}") results['results'][tau]['monot_cv'] = None # Contraintes derivee 3e négative try: res = quantile_spline(xtab, ytab, knots, tau, monot=0, cv=0, der3=der3, solver=solver,degree=degree) results['results'][tau]['all'] = res print(f"✓ τ={tau}: Contrainte dérivée 3e négative") except Exception as e: print(f"✗ τ={tau}: Contrainte Dérivée 3e {e}") results['results'][tau]['all'] = None if show_plots: # Créer la figure fig, axes = plt.subplots(2, 3, figsize=(16, 12)) x_eval = np.linspace(0, 1, 500) colors = ['blue', 'green', 'red'] # 1. Sans contraintes ax = axes[0, 0] ax.scatter(xtab, ytab, alpha=0.3, s=10, color='gray', label='Données') for tau, color in zip(quantiles, colors): res = results['results'][tau]['none'] if res is not None: ax.plot(x_eval, res(x_eval), color=color, linewidth=2, label=f'τ={tau}') ax.plot(knots, np.ones_like(knots)*max(ytab)*0.95, 'k|', markersize=8, label='Nœuds') ax.set_title('1. Sans contraintes') ax.set_xlabel('x') ax.set_ylabel('y') ax.legend(fontsize='small') ax.grid(True, alpha=0.3) # 2. Contrainte croissante ax = axes[0, 1] ax.scatter(xtab, ytab, alpha=0.3, s=10, color='gray', label='Données') ax.set_title('2. Contrainte croissante') ax.set_xlabel('x') ax.set_ylabel('y') for tau, color in zip(quantiles, colors): res = results['results'][tau]['monot'] if res is not None: ax.plot(x_eval, res(x_eval), color=color, linewidth=2, label=f'τ={tau}') ax.plot(knots, np.ones_like(knots)*max(ytab)*0.95, 'k|', markersize=8, label='Nœuds') ax.legend(fontsize='small') ax.grid(True, alpha=0.3) # 3. Convexité mixte ax = axes[0, 2] ax.scatter(xtab, ytab, alpha=0.3, s=10, color='gray', label='Données') ax.set_title('3. Convexité mixte (concave puis convexe)') ax.set_xlabel('x') ax.set_ylabel('y') ax.axvspan(0, 0.5, alpha=0.1, color='red', label='Concave') ax.axvspan(0.5, 1, alpha=0.1, color='blue', label='Convexe') for tau, color in zip(quantiles, colors): res = results['results'][tau]['cv_mixed'] if res is not None: ax.plot(x_eval, res(x_eval), color=color, linewidth=2, label=f'τ={tau}') ax.plot(knots, np.ones_like(knots)*max(ytab)*0.95, 'k|', markersize=8, label='Nœuds') ax.legend(fontsize='small') ax.grid(True, alpha=0.3) # 4. Croissante + Convexité mixte ax = axes[1, 0] ax.scatter(xtab, ytab, alpha=0.3, s=10, color='gray', label='Données') ax.set_title('4. Croissante + Convexité mixte') ax.set_xlabel('x') ax.set_ylabel('y') ax.axvspan(0, 0.5, alpha=0.1, color='red') ax.axvspan(0.5, 1, alpha=0.1, color='blue') for tau, color in zip(quantiles, colors): res = results['results'][tau]['monot_cv'] if res is not None: ax.plot(x_eval, res(x_eval), color=color, linewidth=2, label=f'τ={tau}') ax.plot(knots, np.ones_like(knots)*max(ytab)*0.95, 'k|', markersize=8, label='Nœuds') ax.legend(fontsize='small') ax.grid(True, alpha=0.3) # 5. Toutes les contraintes ax = axes[1, 1] ax.scatter(xtab, ytab, alpha=0.3, s=10, color='gray', label='Données') ax.set_title('5. Dérivée 3e négative') ax.set_xlabel('x') ax.set_ylabel('y') ax.axvspan(0, 0.5, alpha=0.1, color='red') ax.axvspan(0.5, 1, alpha=0.1, color='blue') for tau, color in zip(quantiles, colors): res = results['results'][tau]['all'] if res is not None: ax.plot(x_eval, res(x_eval), color=color, linewidth=2, label=f'τ={tau}') ax.plot(knots, np.ones_like(knots)*max(ytab)*0.95, 'k|', markersize=8, label='Nœuds') ax.legend(fontsize='small') ax.grid(True, alpha=0.3) # 6. Comparaison des contraintes (τ=0.5) ax = axes[1, 2] ax.scatter(xtab, ytab, alpha=0.3, s=10, color='gray', label='Données') ax.set_title('6. Comparaison des contraintes (τ=0.5)') ax.set_xlabel('x') ax.set_ylabel('y') configs = [ ('none', 'blue', 'Sans contrainte'), ('monot', 'green', 'Croissante'), ('cv_mixed', 'orange', 'Convexité mixte'), ('monot_cv', 'purple', 'Croiss.+Cvx mixte'), ('all', 'red', 'Dérivée 3e'), ] tau_mid = 0.5 for key, color, label in configs: res = results['results'][tau_mid][key] if res is not None: ax.plot(x_eval, res(x_eval), color=color, linewidth=2, label=label) ax.plot(knots, np.ones_like(knots)*max(ytab)*0.95, 'k|', markersize=8, label='Nœuds') ax.legend(fontsize='small') ax.grid(True, alpha=0.3) plt.tight_layout() plt.show() print("\n" + "=" * 70) print("TEST TERMINÉ") print("=" * 70) if return_data: return results else: return None
def main(): """Fonction principale pour exécution indépendante.""" run_logistic_example(show_plots=True,degree=1) if __name__ == "__main__": main()