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

C# Discussion :

[Solver]Conversion Excel vers C# avec plusieurs Solver


Sujet :

C#

  1. #1
    Membre averti Avatar de megamario
    Homme Profil pro
    VB6/VB.net/C/C++/C#
    Inscrit en
    Septembre 2008
    Messages
    929
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : VB6/VB.net/C/C++/C#
    Secteur : Industrie

    Informations forums :
    Inscription : Septembre 2008
    Messages : 929
    Points : 312
    Points
    312
    Par défaut [Solver]Conversion Excel vers C# avec plusieurs Solver
    Bonjour à tous,

    J'ai mis le pied dans quelque chose

    Le Solver...

    Un terme que je ne connaissais pas du tout, mais je doit créer un logiciel qui en utilise plusieurs. C'est assez compliqué de trouver des tutos simple et fonctionnel. Du coup j'ai vraiment besoin de votre aide s'il vous plais.

    Le Projet:

    Je ne vais pas pouvoir m'étendre sur la finalité du projet, mais le but étant de récupérer des mesures, un tableau de x données, puis grâce à plusieurs formules "magique", interprété ces mesures.
    Actuellement tous les calculs se font dans Excel. Un gros fichier d'une 15 ene d'onglets avec des calculs partout, et une fois les résultats affiché, l'utilisateur lance une macro qui va lancer 6 solvers dans 6 des onglets. Afin de trouver des optimisations sur certains paramètres (le rôle des solver si j'ai bien compris).

    Mon problème:
    -Je part de loin sur ce sujet puisque j'en connaissais même pas l'existence.
    -Il n'y a pas énormément de sujet/tuto qui parle du solver par Microsoft solver Fondation (MSF), au point que Microsoft semble avoir abandonner ce projet depuis pas mal de temps.
    -La complexité de mon cas puisque le fichier Excel contient énormément de cellule avec des formules qui pointe sur d'autre cellules, elle même avec des formule etc. vous comprenez l'idée.

    -Je pense qu'une bonne parti de mon souci c'est déjà la transcription du fichier Excel vers vers C#, je m'explique, Afin de mieux debugger le programme, j'essaie pour le moment de coller parfaitement au fichier Excel. Pour le moment je me suis concentré sur un seul onglet et chaque cellule aillant une formule j'en ai fait une méthode en C# ainsi a la fin du calcul je sauvegarde mon résultat et je peux le comparer.

    Genre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    private double C12()
    {
        double res = DataU50/ (DataD50 * DataT50 * G11() * H11() * I11()) / TempsDeMesure;
        //sauvegarde de res ....
        return res;
    }
    DataU50, DataD50 etc sont des valeurs issus des mesures, elles sont fixées avant de lancer les calcules, TempsDeMesure aussi bien-sûr.


    Ce que j'ai déjà fait:

    J'ai déjà trouvé plusieurs tuto, mais à chaque fois, soit je trouve pas comment le faire dans Excel (peut être trop ancien) ou en C# il utilise une version de solver payante. Ou alors, et c'est bien plus fréquent, je vous l'accorde, d'autre modèle me permettent pas de comprendre.

    Voici quelques lien que j 'ai déjà utilisé:
    1)Solver.com
    2)mikejuniperhill
    3)codeproject-Solving-optimization-problems-with-Microsoft-Solve
    4)Ais.com

    A l'aide du 1, j'ai réussi a comprendre et reproduire la partie Excel, le solveur fonctionne et j'ai le même résultat, mais il utilise leur Dll pour C#.
    A l'aide du 4, j'ai réussi à reproduire le 1 en C# et j'ai le même résultat. J'était content de moi, mais j'ai du mal à l'adapter à mon projet et ces variables.

    Voici le code qui fonctionne en C#:
    Code : 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
     
    static void Main(string[] args)
            {
                // Initializing the solver.
                var solver = SolverContext.GetContext();
                var model = solver.CreateModel();
                // Defining our final outputs. These are referred to as our “decisions”.
                var numTahoe = new Decision(Domain.IntegerNonnegative, "Tahoe");
                var numPacific = new Decision(Domain.IntegerNonnegative, "Pacific");
                var numSavannah = new Decision(Domain.IntegerNonnegative, "Savannah");
                var numAspen = new Decision(Domain.IntegerNonnegative, "Aspen");
                // Adding these outputs to the model the solver will use.
                model.AddDecision(numTahoe);
                model.AddDecision(numPacific);
                model.AddDecision(numSavannah);
                model.AddDecision(numAspen);
     
                var maxBudget = 500;
                // Our costs
     
                var TahoeProfit = 450;
                var PacificProfit = 1150;
                var SavannahProfit = 800;
                var AspenProfit = 400;
     
                var maxGlue = 5800;
                var maxPressing = 730;
                var maxPinChips = 29200;
                var maxOakChips = 60500;
     
                // We define the expression of our cost < maxBudget
                model.AddConstraint("TotalGlue",
                    50 * numTahoe +
                    50 * numPacific +
                    100 * numSavannah +
                    50 * numAspen
                    <= maxGlue);
                model.AddConstraint("TotalPressing", 
                    5 * numTahoe +
                    15 * numPacific +
                    10 * numSavannah +
                    5 * numAspen
                    <= maxPressing);
                model.AddConstraint("TotalPineChips", 
                    500 * numTahoe +
                    400 * numPacific +
                    300 * numSavannah +
                    200 * numAspen
                    <= maxPinChips);
                model.AddConstraint("TotalOakChips",
                    500 * numTahoe +
                    750 * numPacific +
                    250 * numSavannah +
                    500 * numAspen
                    <= maxOakChips);
                // Define goal to maximize profit
                model.AddGoal("TotalProfit", GoalKind.Maximize,
                   TahoeProfit * numTahoe +
                    PacificProfit * numPacific +
                    SavannahProfit * numSavannah +
                    AspenProfit * numAspen);
     
                // Solve our problem
                var solution = solver.Solve();
                // Get our decisions
                Console.WriteLine("Solution found with a quality considered: " + solution.Quality.ToString());
                Console.WriteLine("You should produce {0} of ‘Tahoe'", numTahoe);
                Console.WriteLine("You should produce {0} ‘Pacific'", numPacific);
                Console.WriteLine("You should produce {0} ‘Savannah'", numSavannah);
                Console.WriteLine("You should produce {0} ‘Aspen'", numAspen);
                double TotalGlue = 50 * numTahoe.ToDouble() + 50 * numPacific.ToDouble() + 100 * numSavannah.ToDouble() + 50 * numAspen.ToDouble();
                double TotalPressing = 5 * numTahoe.ToDouble() + 15 * numPacific.ToDouble() + 10 * numSavannah.ToDouble() + 5 * numAspen.ToDouble();
                double TotalPineChips = 500 * numTahoe.ToDouble() + 400 * numPacific.ToDouble() + 300 * numSavannah.ToDouble() + 200 * numAspen.ToDouble();
                double TotalOakChips = 500 * numTahoe.ToDouble() + 750 * numPacific.ToDouble() + 250 * numSavannah.ToDouble() + 500 * numAspen.ToDouble();
                double TotalProfit = TahoeProfit * numTahoe.ToDouble() + PacificProfit * numPacific.ToDouble() + SavannahProfit * numSavannah.ToDouble() + AspenProfit * numAspen.ToDouble();
                Console.WriteLine("Glue used: {0}", TotalGlue);
                Console.WriteLine("Pressing used: {0}", TotalPressing);
                Console.WriteLine("Pin Chips user: {0}", TotalPineChips);
                Console.WriteLine("Oak Chips user: {0}", TotalOakChips);
                Console.WriteLine("Total Profit = {0}", TotalProfit);
                Console.ReadLine();


    Voici ce que j'ai tenté en C# pour mon projet et qui ne fonctionne pas.

    Code : 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
     
                    //Etat du solver dans Excel
                    //Objectif $M$28 MIN  (=H33+H23)
                    //Variable $M$22:$M$26
                    //Contraintes M22 <=4
                    //M22>=0
                    //M23<=2
                    //M23>=0.001
                    //M24<=2
                    //M24>=0
                    //M25<=2
                    //M25>=0
                    //M26<=2
                    //M26>=0.001
                    //Rendre les variables sans contrainte non négatives coché
                    //Sélect. une résolution = GRG non linéaire.
     
     
                    var solver = SolverContext.GetContext();
                    var model = solver.CreateModel();
                    mError = 20;
                    Solver_M22 = new Decision(Domain.IntegerNonnegative, "M22");
                    Solver_M23 = new Decision(Domain.IntegerNonnegative, "M23");
                    Solver_M24 = new Decision(Domain.IntegerNonnegative, "M24");
                    Solver_M25 = new Decision(Domain.IntegerNonnegative, "M25");
                    Solver_M26 = new Decision(Domain.IntegerNonnegative, "M26");
     
                    Solver_M22.SetInitialValue(0);
                    Solver_M23.SetInitialValue(0.001);
                    Solver_M24.SetInitialValue(0);
                    Solver_M25.SetInitialValue(0);
                    Solver_M26.SetInitialValue(0.001);
     
                    // pour test: Ici cela plante, m'indiquant :{"M25 does not yet have a value."}
                    double s = Solver_M25.ToDouble();
     
                    model.AddDecision(Solver_M22);
                    model.AddDecision(Solver_M23);
                    model.AddDecision(Solver_M24);
                    model.AddDecision(Solver_M25);
                    model.AddDecision(Solver_M26);
                    mError = 30;
                    model.AddConstraint("M22a", Solver_M22 <= 4);
                    model.AddConstraint("M22b", Solver_M22 >= 0);
                    model.AddConstraint("M23a", Solver_M23 <= 2);
                    model.AddConstraint("M23b", Solver_M23 >= 0.001);
                    model.AddConstraint("M24a", Solver_M24 <= 2);
                    model.AddConstraint("M24b", Solver_M24 >= 0);
                    model.AddConstraint("M25a", Solver_M25 <= 2);
                    model.AddConstraint("M25b", Solver_M25 >= 0);
                    model.AddConstraint("M26a", Solver_M26 <= 2);
                    model.AddConstraint("M26b", Solver_M26 <= 0.001);
                    mError = 40;
                    model.AddGoal("Somme des carrés des equarts global", GoalKind.Minimize, Cell_H33() + Cell_H23());
                    mError = 50;
                    // Solve our problem
                    var solution = solver.Solve();
                    mError = 60;
                    // Get our decisions
                    //Console.WriteLine("Solution found with a quality considered: " + solution.Quality.ToString());
     
                    //Console.WriteLine("You should produce {0} of ‘Tahoe'", Solver_M22);
                    //Console.WriteLine("You should produce {0} ‘Pacific'", Solver_M23);
                    //Console.WriteLine("You should produce {0} ‘Savannah'", Solver_M24);
                    //Console.WriteLine("You should produce {0} ‘Aspen'", Solver_M25);
                    //Console.WriteLine("You should produce {0} ‘Aspen'", Solver_M26);
                    double M28 = Cell_H33() + Cell_H23();

    Comme indiqué dans ce code au début j'ai repris ce qu'il y a dans le solver Excel, ici en commentaire.
    J'ai déclaré des variables 'Decision Solver_M22;' etc.. que j'ai déjà initialisé dans le constructeur, car elles sont utilisées dans les formules bien sûr, mais cela planté dans les formule.
    Pour les tests j'ai réinitialisé ces variables ici afin de mieux cerner leur comportements, je comptait sur SetInitialValue afin de pouvoir les utiliser, mais cela ne fonctionne pas, j'ai le même plantage avec le 'double s = Solver_M25.ToDouble();'


    Conclusion:

    Bon voila, j'ai essayé de mettre un max de chose, mais c'est clair que je n'ai pas du tous la maitrise de ce process et j'en ai besoin absolument.
    une autre potentiel possibilité, mettre un fichier Excel en background et travaillé dessus, mais j'ai peur que cela soit très lent vu la quantité de données que j'ai a lui envoyer puis à récupérer. Après les calculs et solver l'utilisateur aillant la possibilité d'ajuster certains paramètres suivant ces connaissances et du coups relancer de nouveau les calculs.


    Voilou, donc si une bonne âme peu me guider se serait vraimetn sympa car je suis un peu dans la panade pour le moment.

    Je vais continué à essayer de comprendre le fonctionnement cette aprèm, demain je suis absent, mais il faudrait vraiment que j'ai quelque chose pour la semaine prochaine, car je ne voudrais pas convertir tous les onglets d'Excel vers C# si ce que j'ai fait actuellement n'est pas viable (avec une cellule = une méthode).

    Merci beaucoupppppp.


    [EDIT] A la relecture je voudrais aussi préciser que j'essaie de me coller au plus proche du fichier Excel avec une méthode par cellule aillant une formule, car l'utilisateur final peut très bien changer son process et ainsi cela permet d'avoir une vision plus clair, vu la quantité de formule.

    [EDIT2] Correction...
    J'ai supprimé la partie Excel que je ne comprenais pas, car j'ai fait une boulette, enfin je vais dire mes lunettes mon fait faire une boulette, j'indiquais que des variables du solver contenaient des formules, mais ce n'est pas le cas, j'ai confondu le : et ; ce n'était pas un ensemble de cellule, mais uniquement 2 cellules, j'ai honte. Houuu

  2. #2
    Membre averti Avatar de megamario
    Homme Profil pro
    VB6/VB.net/C/C++/C#
    Inscrit en
    Septembre 2008
    Messages
    929
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : VB6/VB.net/C/C++/C#
    Secteur : Industrie

    Informations forums :
    Inscription : Septembre 2008
    Messages : 929
    Points : 312
    Points
    312
    Par défaut
    Bonjour,


    Personne pour m'aider s'il vous plaie ?

    J'ai fait une représentation simplifie de mon problème en Excel:
    Nom : Excel.png
Affichages : 56
Taille : 44,3 Ko

    J'ai vraiment essayé de simplifié les choses en mettant des valeurs fixe alors que la plupart sont des variables. J'ai laissé le tableau Data et Param1.
    Je vais essayer de vous mettre ce tableau Excel en lien.

    Mes variables Var1 à Var5

    Mon résultat, la valeur minimal sur "Somme Global".

    Le Solver Excel:

    Nom : 2022-07-03 10_58_14-Paramètres du solveur.png
Affichages : 73
Taille : 12,2 Ko


    Je tourne en rond, et je ne voie pas comment adapter ce que j'ai déjà réussi.
    J'ai pas les idées claire j'en dort pas la nuit.


    Les calculs:
    Je ne vais pas tous les faire, mais pour donnée l'idée de la liaison entre la somme global et les variables
    Somme global = Somme Test1 + Somme Test2

    Somme Test1 = =SOMME.CARRES(F28:F30;0) // j'ai laissé 0, c'est le résultat d'une multiplication.

    F28 = =SI(509734<500;0;SI(456<8;"";E28/87137))

    E28 = 81137-D28

    D28 = B28/C28

    B28 = =509734/(0,65*0,000755688325415091*B20*C20*D20)/471

    B20=EXP(-B3*$B$12)
    C20=EXP(-C3*$B$14)
    D20=((EXP(-7,5*$B$9*$B$13)-1)/(-7,5*$B$9*$B$13))


    Je ne voie pas comment Integer mes variables dans tout ces calculs.

    Si vous n'avez pas la réponse, mais que vous connaissez un lieux ou forum ou je pourrais demander, merci de me l'indiquer.


    Le fichier ExcelEssaie simplifié.xlsx

  3. #3
    Membre averti Avatar de megamario
    Homme Profil pro
    VB6/VB.net/C/C++/C#
    Inscrit en
    Septembre 2008
    Messages
    929
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : VB6/VB.net/C/C++/C#
    Secteur : Industrie

    Informations forums :
    Inscription : Septembre 2008
    Messages : 929
    Points : 312
    Points
    312
    Par défaut
    Bonjour,


    Bon j'ai trouvé, cela semble bien fonctionner, en faite toutes les cellules que j'ai représentées en C#, je dois les faire en double, je m'explique:

    Pour exemple la methode C12 (qui représente la Cellule C12 dans Excel, afin de mieux retrouvé les éventuelles erreurs):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    private double C12()
    {
        double res = DataU50/ (DataD50 * DataT50 * G11() * H11() * I11()) / TempsDeMesure;
        //sauvegarde de res ....
        return res;
    }
    Elle reste classique et me permettra de faire le calcul final quand les variables seront trouvées.

    Et la même méthode qui sera utilisé dans le solver, ce n'est plus des doubles qui sont utilisé mais des "Term".
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    private Term C12()
    {
        Term res= DataU50/ (DataD50 * DataT50 * G11() * H11() * I11()) / TempsDeMesure;
        return res;
    }
    Ainsi que les formules mathématiques aillant un calcul;
    Math.EXP est remplacé par Model.EXP, Math.Pow par Model.Power etc.... Pas Math.PI qui est une constante.


    Ainsi le AddGoal qui contient:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    model.AddGoal("Resultat", GoalKind.Minimize, Cell_H33() + Cell_H23());

    Les Cell_H33 et Cell_H23 retournent des Term et non plus des doubles et tout semble bien ce passer.

    Je dis "semble", car pour le moment je n'ai essayé qu'avec des variables non réels et approximatives, sans avoir des valeurs avec parfois plus de 5 chiffres aprés la virgule donc je n'ais pas de comparatif réel avec le vrai fichier Excel, pas encore de comparaison possible donc, mais les résultats semblent concluants.

    Une fois mes variables récupérer, je peux lancer le calcule réel.

    Maintenant plus qu'a mettre sa dans mon projet réel et vérifier que tout va bien.

    J'ai juste un doute, dans le solveur Excel, on indique c'est lineaire ou non. Dans ce que j'ai fait, je n'est rien vu de tel pour le moment.


    Autre petit détails, les instanciation des décisions. J'ai remplacé Domain.IntegerNonnegative
    new Decision(Domain.IntegerNonnegative, "Tahoe");

    Pour Domain.RealNonnegative, pour avoir un double en sortie.

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

Discussions similaires

  1. import excel vers access avec bouton "parcourir"
    Par zeloutre dans le forum Access
    Réponses: 3
    Dernier message: 04/04/2007, 19h06
  2. Réponses: 2
    Dernier message: 18/02/2007, 01h47
  3. Réponses: 2
    Dernier message: 12/02/2007, 13h39
  4. Conversion timestamp vers date avec oracle 9.2
    Par gaboo_bl dans le forum Oracle
    Réponses: 5
    Dernier message: 27/11/2006, 14h10
  5. [VBA-E] macro conversion excel vers csv
    Par baboune dans le forum Macros et VBA Excel
    Réponses: 9
    Dernier message: 15/07/2004, 09h23

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