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:
DataU50, DataD50 etc sont des valeurs issus des mesures, elles sont fixées avant de lancer les calcules, TempsDeMesure aussi bien-sûr.
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; }
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
Partager