IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Mathématiques Discussion :

Chercher la combinaison linaire et satisfaction de contrainte


Sujet :

Mathématiques

  1. #1
    Membre actif Avatar de SKone
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2004
    Messages
    333
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2004
    Messages : 333
    Points : 250
    Points
    250
    Par défaut Chercher la combinaison linaire et satisfaction de contrainte
    Bonjour,

    J'ai N vecteur (v_i) et un vecteur T de dimension C.
    Je cherche les coefficients a_i à appliquer à chaque vecteur i pour que la combinaison linaire de des v_i pondérés par les a_i soit le plus proche possible de T.

    n = N - 1

    S = a_0*v_0 + a_1*v_1 + ... + a_n*v_n
    S = T (le plus proche possible).

    J'ai des contraintes sur les a_i il doivent être entre 0 et 1 compris. Et que la distance entre S et T soit inférieur à 10^-2.

    Il y a surement des valeurs numériques avec des v_i et T donnée où il n'y a pas de solution mais dans mon cas il existe une solution (obtenu empiriquement) je cherche une formalisation mathématique, algorithmique... Pour trouver le plus précisément et rapidement possible ma (ou mes) solution(s). Sachant que dès que j'ai une solution assez proche je m'en contente...

    Merci

  2. #2
    Membre émérite
    Avatar de prgasp77
    Homme Profil pro
    Ingénieur en systèmes embarqués
    Inscrit en
    Juin 2004
    Messages
    1 306
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Eure (Haute Normandie)

    Informations professionnelles :
    Activité : Ingénieur en systèmes embarqués
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Juin 2004
    Messages : 1 306
    Points : 2 466
    Points
    2 466
    Par défaut
    Bonjour,

    dans un premier temps, une solution naïve est à envisager. Si C est grand (>10) ou que tu es un peu chanceux, elle sera très performante. L'idée est de partir de A = (0,...,0) (A : vecteur des a_i) et de « remplir » ce vecteur indice par indice. À chaque itération, on rempli l'indice nul « le plus à gauche ».


    1. i ← 0 ;
    2. ;
    3. - (E comme erreur) ;
    4. Si , FIN.
    5. (voir détail plus bas sur ce que représente epsilon) ;
    6. a_i ← ;
    7. Ajuster a_i pour qu'il soit dans [0;1] ;
    8. Insérer a_i dans A ;
    9. i ← i+1 ;
    10. GOTO 2.



    Pour obtenir ces valeurs, je me suis placé dans le triangle formé par les vecteurs E (Erreur courante) et v_i (le vecteur utilisé à cette irération). Le vecteur epsilon est le vecteur orthodoxe au vecteur v_i tel que avec a_i idéal.
    Ainsi, la définition du produit scalaire nous donne l'angle alpha := (E, v_i) ; la définition du sinus nous donne epsilon en fonction d'alpha et E ; et enfin pythagore nous donne a_i en fonction de v_i, epsilon et E.

    Pense à refaire les calculs.
    -- Yankel Scialom

  3. #3
    Membre expérimenté Avatar de davcha
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 258
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 258
    Points : 1 539
    Points
    1 539
    Par défaut
    Faut aller chercher du côté de ces mots-clefs : quadratic programming, bound constrained (linear) least squares.

  4. #4
    Membre actif Avatar de SKone
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2004
    Messages
    333
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2004
    Messages : 333
    Points : 250
    Points
    250
    Par défaut
    prgasp77> je crois que j'ai mal expliqué le problème A est un vecteur de C éléments.
    J'ai C v_i de C éléments.

    Dans les v_i il y a des données présentés comme ça :
    x_0
    y_0
    z_0
    x_1
    y_1
    z_1
    ...
    x_C/3
    y_C/3
    z_C/3

    Donc fait un triangle avec le vecteur v_i devient difficile dans avec un vecteur de dimension C.
    v_i représente un ensemble de position de point dans l'espace à un temps donnée.
    Je cherche à combiner toute ces positions pour m'approcher le plus possible d'un ensemble de point cible T.

    Le LeastSquares ne donne rien avec un rapide test sous mathematica je me retrouve à une distance de 16 alors que mon objectif est de 10^-2 (-1 est toléré)
    Dans le quadratic programming j'ai testé le Gradient Conjugué, stabilisé... Et d'autre variable en posant le problème sous forme d'équation linéaire :

    On place dans une matrice M les v_i comme colonnes
    et on obtient :
    M*A = T

    Or je sais que mon problème que avec mes données il existe une solution (même plusieurs) (un A a été trouvé autrement avec les mêmes M et T mais la méthode utilisé n'est plus utilisable pour diverse raison ni communicable...).

    Si vous avez d'autre voie d'exploration, quelque commande mathematica a tester...
    Je suis preneur.

    Merci

  5. #5
    Membre émérite
    Avatar de prgasp77
    Homme Profil pro
    Ingénieur en systèmes embarqués
    Inscrit en
    Juin 2004
    Messages
    1 306
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Eure (Haute Normandie)

    Informations professionnelles :
    Activité : Ingénieur en systèmes embarqués
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Juin 2004
    Messages : 1 306
    Points : 2 466
    Points
    2 466
    Par défaut
    Citation Envoyé par SKone Voir le message
    fait un triangle avec le vecteur v_i devient difficile dans avec un vecteur de dimension C.
    Heu ... non pourquoi ?

    En passant, j'ai revu ma copie, on peut faire plus simplement. Mais reprenons toutes les définitions pour être bien sûrs que l'on parle de la même chose.

    • : C vecteurs, chacun de dimension C ;
    • : C réels compris entre 0 et 1 que l'on cherche à déterminer ;
    • : la combinaison linéaire (que l'on peut noter avec V et A les matrices formées des familles de vecteurs et de coef) ;
    • : le vecteur objectif ( étant la condition d'acceptance).



    On procède alors comme suit :
    • À l'étape k, on se place dans le plan formé par les vecteurs et .
    • On se rappelle ce qu'on a apprit au lycée concernant le produit scalaire des vecteurs (ça marche en 2D, en 3D, en 56D, …) :
      .
      Or, le troisième facteur vaut, par définition du cosinus dans un triangle rectangle (on est dans un plan, il n'y a plus que deux dimensions) :
    • Ainsi,
    • En prenant cette valeur pour le k-ième coefficient, on s'assure d'être aussi proche de que le permet la seule modification d'.



    Cdlt,
    -- Yankel Scialom

  6. #6
    Membre émérite
    Avatar de prgasp77
    Homme Profil pro
    Ingénieur en systèmes embarqués
    Inscrit en
    Juin 2004
    Messages
    1 306
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Eure (Haute Normandie)

    Informations professionnelles :
    Activité : Ingénieur en systèmes embarqués
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Juin 2004
    Messages : 1 306
    Points : 2 466
    Points
    2 466
    Par défaut
    Voici un proof of concept, écrit en OCaml (je n'ai pas de matlab sous la main).

    Code ocaml : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    #!/usr/bin/ocaml
     
    (* Vector type *)
    type vec = float list
     
    (* Vector operators *)
    let vec_to_string = function
    	| x::y::z::t::w::[] ->	Printf.sprintf "(%.2f, %.2f, %.2f, %.2f, %.2f)" x y z t w
    	| _ -> failwith "vec_to_string: bad format."
    let vec_add =
    	List.map2 ( +. )
    let vec_scal_prod r =
    	List.map ( ( *.)  r)
    let vec_outer_prod u v =
    	let w = List.map2 ( *. ) u v in
    	List.fold_left (+.) 0. w
    let vec_norme u =
    	sqrt (vec_outer_prod u u)
     
    (* Vector generator *)
    let vec_nul () =
    	[0.;0.;0.;0.;0.]
    let vec_random () =
    	List.map (fun _ -> Random.float 10.) (vec_nul ())
     
     
    (* Algorithm functions *)
    let compute_linear_combination a v =
    	let rec loop acc k =
    		if k < 0
    		then acc
    		else
    			let akvk = vec_scal_prod a.(k) v.(k) in
    			loop (vec_add acc akvk) (pred k)
    	in
    	loop (vec_nul ()) (Array.length a - 1)
     
    let comute_error a v t =
    	let s = compute_linear_combination a v in
    	let minus_s = vec_scal_prod (-1.) s in
    	vec_add t minus_s
     
    let compute_coefficient k a v t =
    	let a' = Array.mapi (fun i x -> if i = k then 0. else x) a in
    	let e = comute_error a' v t in
    	let sq x = x *. x in
    	let perfect_coef = (vec_outer_prod e v.(k)) /. (sq (vec_norme v.(k))) in
    	match perfect_coef with
    	| x when x < 0. -> 0.
    	| x when x > 1. -> 1.
    	| x -> x
     
     
     
    let main () =
    	Random.self_init () ;
     
    	(* Make 42 random vectors *)
    	let v = Array.init 42 (fun _ -> vec_random ()) in
     
    	(* Initiate the 42 coef to zero (0) *)
    	let a = Array.make (Array.length v) 0. in
     
    	(* Make the target vector *)
    	let t = vec_random () in
     
    	(* Compute all the coefficients *)
    	let pass () =
    		let rec loop k =
    			if k >= (Array.length a)
    			then ()
    			else begin
    				a.(k) <- compute_coefficient k a v t ;
    				loop (succ k)
    			end
    		in
    		loop 0
    	in
     
    	(* make a new pass until target acquired or maxiter reached *)
    	let print_pass n =
    		Printf.printf "Pass #%d, Delta: %.3f\n" n (vec_norme (comute_error a v t))
    	in
    	let rec make_pass maxiter =
    		if (maxiter <= 0) || (vec_norme (comute_error a v t) < 1e-2)
    		then ()
    		else begin pass () ; print_pass maxiter ; make_pass (pred maxiter) end
    	in
     
    	make_pass 50 ;
    	print_pass 0
     
    let _ = main ()

    À l'exécution, en fonction des vecteurs générés au début du programme, on parvient à la précision souhaitée ou nous. Mais il est important de noter qu'à chaque passe, l'erreur diminue.
    yscialom@Lucy:/tmp$ ./combi.ml 
    Pass #50, Delta: 7.092
    Pass #49, Delta: 3.594
    Pass #48, Delta: 2.331
    Pass #47, Delta: 1.751
    Pass #46, Delta: 1.364
    Pass #45, Delta: 1.040
    Pass #44, Delta: 0.783
    Pass #43, Delta: 0.584
    Pass #42, Delta: 0.431
    Pass #41, Delta: 0.321
    Pass #40, Delta: 0.251
    Pass #39, Delta: 0.195
    Pass #38, Delta: 0.150
    Pass #37, Delta: 0.115
    Pass #36, Delta: 0.086
    Pass #35, Delta: 0.063
    Pass #34, Delta: 0.045
    Pass #33, Delta: 0.031
    Pass #32, Delta: 0.022
    Pass #31, Delta: 0.015
    Pass #30, Delta: 0.010
    Pass #29, Delta: 0.007
    Pass #0, Delta: 0.007
    
    Le temps d'exécution est négligeable à échelle humaine (C=42, exec en moins d'un centième).

    Cdlt,
    -- Yankel Scialom

  7. #7
    Membre expérimenté Avatar de davcha
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 258
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 258
    Points : 1 539
    Points
    1 539
    Par défaut
    Posons les choses clairement.
    Tu cherches :

    a* = argmin_a ||Va - t||^2 s.t. a^2 - 1 = 0
    avec V in R^{n x c}, a in R^c, t in R^n

    C'est ça ?

  8. #8
    Membre actif Avatar de SKone
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2004
    Messages
    333
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2004
    Messages : 333
    Points : 250
    Points
    250
    Par défaut
    davcha> Presque, je veux que chaque a soit entre 0 et 1.
    Or si a^2-1 = 0 alors a == 1 ou -1

    Je cherche plutôt :

    a* = argmin_a ||Va - t||^2 s.t. sqrt(a^2) = a et a^2 < 1 (positif et dans le cercle)

    avec V in R^{n x c}, a in R^c, t in R^n (Et là oui...)

    prgasp77> Mon (O)Caml est vraiment rouillé j'ai suivi les équations, en C++ ça donne :
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
        u32 uIdx = 0;
        do 
        {
            // S = Sum( x_i.b_i )
            MatrixTool::SetZero( s );
            // Get v_i
            MatrixTool::GetColumns( mCurrentColumn, A, uIdx );
            for ( u32 i = 0; i < uIdx; ++i )
            {
                // Get v_k_=v_k
                MatrixTool::GetColumns( mColumnK, A, i );
                // v_k_=v_k_*a_k
                MatrixTool::ScalarMultEqual( mColumnK, x[ i ][ 0 ] );
                // S += v_k_*a_k
                MatrixTool::AddEqual( s, mColumnK );
            }
            // E = B - S
            MatrixTool::Sub( e, b, s );
            fNormE = MatrixTool::Norm( e );
            if ( fNormE <= 1e-1 )
            {
                break;
            }
            // epsilon = norm(e)*sin(acos((e.v_i)/(norm(e).norm(v_i))))
            epsilon = fNormE*std::sin( std::acos( MatrixTool::Dot( e, mCurrentColumn )/( fNormE*MatrixTool::Norm( mCurrentColumn ) ) ) );
            //x[ uIdx ][ 0 ] = std::sqrt( ( fNormE*fNormE - epsilon )/MatrixTool::NormSqr( mCurrentColumn ) );
            x[ uIdx ][ 0 ] = ( MatrixTool::Dot( e, mCurrentColumn ) )/MatrixTool::NormSqr( mCurrentColumn );
            MatrixTool::Sub( mResult, b, s );
     
            std::cout << "Epsilon : " << MatrixTool::NormSqr( mResult ) << " Norm : " << MatrixTool::NormSqr( mResult ) << std::endl;
     
            ++uIdx;
            //uIdx >= uColumnsCount ? uIdx = 0 : uIdx;
            uIdx %= uColumnsCount;
        } while ( true );

    Dans mon cas j'ai 3 cas N>C, N<C & N=C.

    Dans tous les cas d'utilisation j'ai un epsilon constant et une norme constante sauf quand uIdx == 0.

    Dit moi si j'ai bien retranscrit tes formules ?

    PS : ta méthode semble correct, simple et surtout devrait fonctionner...

  9. #9
    Membre émérite
    Avatar de prgasp77
    Homme Profil pro
    Ingénieur en systèmes embarqués
    Inscrit en
    Juin 2004
    Messages
    1 306
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Eure (Haute Normandie)

    Informations professionnelles :
    Activité : Ingénieur en systèmes embarqués
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Juin 2004
    Messages : 1 306
    Points : 2 466
    Points
    2 466
    Par défaut
    Citation Envoyé par SKone Voir le message
    Dit moi si j'ai bien retranscrit tes formules ?
    Salut,
    utilises plutôt les « formules » de mon second message.

    Si tu n'est plus capable de relire de l'objective caml, voici une version en pseudo code :
    // Aucune de ces trois fonctions ne modifie ses arguments (const powa!!!)
    fonction compute_linear_combination(coefficients A, famille de vecteurs V)
    	calculer et retourner S = _^tV.A
    
    fonction compute_error(coefficients A, famille de vecteurs V, vecteur target T)
    	S ← compute_linear_combination(A, V)
    	calculer et retourner E = T - S
    
    fonction compute_coefficient(indice k, coefficients A, famille de vecteurs V, vecteur target T)
    	A' ← A ; A'[k] ← 0
    	E ← compute_error(A', V, T) // On calcule l'erreur mais en supposant l'a_k courant nul,\
    puisqu'on va ici calculer sa valeur optimale
    	a[k] ← (E scalaire v[k]) / (||v[k]||^2)
    	Si a[k] < 0 alors a[k] ← 0
    	Si a[k] > 1 alors a[k] ← 1
    	Retourner a[k]
    
    // ENTRY POINT
    
    // 1. Ici je génère des vecteurs, dans le cas concret, il existent déjà
    Génération de V : famille de vecteurs aléatoires
    Génération de A : famille de coefficients nuls
    Génération de T : vecteur
    
    // 2. L'algo à proprement parler
    entier iter ← 0
    Tant que la précision souhaitée n'est pas obtenue ou que la limite d'itérations n'est pas atteinte, faire
    	Pour k de 0 à dim(A)-1, faire
    		A[k] ← compute_coefficient(k, A, V, T)
    	Fin Pour
    	iter ← iter + 1
    Fin Tant Que
    
    FIN.
    
    -- Yankel Scialom

  10. #10
    Membre actif Avatar de SKone
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2004
    Messages
    333
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2004
    Messages : 333
    Points : 250
    Points
    250
    Par défaut
    Bonjour,

    Désolé pour le temps de réponse. J'ai testé, modifié mon code, re-testé.
    Et globalement ça fonctionne. J'ai quelques autres problèmes qui viennent de mon code mais la combinaison linéaire fonctionne.

    Merci

    [Résolu]

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Satisfaction de contraintes] - Problème de formalisme
    Par Crahash dans le forum Intelligence artificielle
    Réponses: 1
    Dernier message: 24/01/2013, 19h22
  2. Réponses: 11
    Dernier message: 18/01/2013, 16h13
  3. Problèmes de satisfaction de contraintes
    Par devhercule dans le forum Algorithmes et structures de données
    Réponses: 5
    Dernier message: 15/07/2012, 12h08
  4. Combinaison linéaire de fonctions
    Par erwanBert dans le forum MATLAB
    Réponses: 1
    Dernier message: 28/09/2011, 19h20
  5. Algorithme Bayesien/Combinaison linéaire de gaussiennes
    Par buichi dans le forum Probabilités
    Réponses: 1
    Dernier message: 01/06/2011, 14h40

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo