Visual Studio und CPLEX - seltsame Ausgaben, "nicht deklarierter Bezeichner"
-
Hallo miteinander!
Ich bin mittlerweile völlig verzweifelt. Ich habe am Dienstag eine Ergebnispräsentation und mein Programm in c++ läuft noch immer nicht richtig.
Es geht darum, das lineare Programm MLCLSP zu implementieren und die Zielfunktion um eine Sanktion für nicht-Auslastung von Ressourcen (Kosten m_j) zu erweitern.Es sind scheinbar mehrere Dinge in meinem Programm verkehrt. Das - so vermute ich - am leichtesten zu lösende Problem ist folgendes: Ich habe 3 Nebenbedingungen im Programm und bekomme, wenn ich den Befehl "NB1.end();" (auch NB2 und NB3)verwenden möchte, die Fehlermeldung "nicht deklarierter Bezeichner". Ich vermute, dies hängt mit den "For"-Schleifen in den Nebenbedingungen zusammen, kann den Fehler aber nicht finden.

Des Weiteren erzeugt mein Programm zur Fehlerfindung eine Textdatei "Model.lp". Diese lässt sich mit der Musterlösung vergleichen und zeigt, dass bei mir durchaus einiges im Argen liegt. Meine Kenntnisse in c++ sind jedoch so begrenzt, dass ich an meine Grenzen stoße und daher Hilfe benötige. Entsprechend wäre es wahrscheinlich am Besten, wenn Vorschläge so einfach wie möglich formuliert sind, mit Fachtermina kenne ich mich nicht aus

Ich hoffe, irgendjemande kann mir helfen und ich bin schon im Voraus überaus dankbar, auch für jegliche Form von Teillösung oder Inspiration!
#include <ilcplex/ilocplex.h> #include <iostream> //fuer Ausgabe #include <fstream> //fuer Einlesen using namespace std; int main() { //Umgebung u Modell erzeugen, Modell Umgebung zuweisen IloEnv env; IloModel model(env); //Oeffnet Datei im Lesemodus. std::ifstream myfile ("small_instance.txt"); if (!myfile.good()){ std::cout << "instanz nicht gefunden!" << std::endl; system("pause"); return 1; } //Aenderung 2: Reihenfolge einlesen //Definition der Eingabeparameter IloIntArray s_k(env); //Rüstkosten für Produkt k IloIntArray h_k(env); //Lagerhaltungskosten für Produkt k IloIntArray z_k(env); //Vorlaufzeit für Produkt k IloIntArray tr_k(env); //Rüstzeit für Produkt k IloIntArray tb_k(env); //Produktionszeit für Produkt k IloArray<IloIntArray> d_k_t(env); //Primärbedarf für Produkt k in Periode t //NACHFRAGE IloArray<IloIntArray> a_k_i(env); //Direktbedarf zwischen Produkten k und i IloArray<IloIntArray> b_j_t(env); //Kapazität von Ressource j in Periode t IloArray<IloIntArray> K_j_k(env); //Zuordnung Produkt k an Ressource j produzierbar IloIntArray m_j(env); //Kosten pro Zeiteinheit für Nicht-Auslasten von ressource j // IloArray<IloIntArray> n_j_t(env); //Nichtauslasten der Ressource j in Periode t, hier? oder als Entscheidungsvariable? //Einlesen aus Datei mit Hilfe CPLEX Parser - REIHENFOLGE IN .txt BEACHTEN!!! myfile >> s_k; myfile >> h_k; myfile >> z_k; myfile >> tr_k; myfile >> tb_k; myfile >> d_k_t; myfile >> a_k_i; myfile >> b_j_t; myfile >> K_j_k; myfile >> m_j; // myfile >> n_j_t; int nProdukte = s_k.getSize(); //Abfrage Produkte int nRessourcen = b_j_t.getSize(); //Abfrage Ressourcen int nPerioden = b_j_t[0].getSize(); //Abfrage Perioden std::cout << "Ruestkosten fuer Produkt k: " << s_k << std::endl; //WICHTIG!!! std::cout << "Lagerhaltungskosten fuer Produkt k: " << h_k << std::endl; std::cout << "Vorlaufzeit fuer Produkt k: " << z_k << std::endl; std::cout << "Ruestzeit fuer Produkt k: " << tr_k << std::endl; std::cout << "Produktionszeit fuer Produkt k: " << tb_k << std::endl; IloInt n = d_k_t.getSize(); // Wäre hier Abfrage des Primärbedarfs std::cout << "Groesse des Primaerbedarfs fuer Produkt k in Periode t: " << n << std::endl; //Anzahl der Produkte IloInt m = a_k_i.getSize(); std::cout << "Direktbedarf zwischen Produkt k und i: " << m << std::endl; IloInt o = b_j_t.getSize(); std::cout << "Kapazität von Ressource j in Periode t: " << o << std::endl; IloInt p = K_j_k.getSize(); std::cout << "Produkt k an Ressource j produzierbar? " << p << std::endl; //ENTSCHEIDUNGSVARIABLEN //binäre Entscheidungsvariable x //IloNumVarArray x(env, 100, 0, 1, ILOBOOL) IloArray<IloNumVarArray> Gamma_k_t(env, nProdukte); //k in nProdukte for (int t = 0; t < nProdukte; ++t) { Gamma_k_t[t] = IloNumVarArray(env, nPerioden, 0, 1, ILOBOOL); } //Produktionsmenge des Produkts k in Periode t = q_k_t IloArray<IloNumVarArray> q_k_t(env, nProdukte); for (int t = 0; t < nProdukte; ++t) { q_k_t[t]=IloNumVarArray(env, nPerioden, 0, IloInfinity, ILOFLOAT); //untere Schranke = 0, daher NB 4 erfüllt } //Lagerbestand des Produktes k am Ende der Periode t = y_k_t IloArray<IloNumVarArray> y_k_t(env, nProdukte); for (int t = 0; t < nProdukte; ++t) { y_k_t[t]=IloNumVarArray(env, nPerioden, 0, IloInfinity, ILOFLOAT); //Untere Schranke = 0, daher NB 4 erfüllt } //NEBENBEDINGUNGEN 1-5 //Nebenbedingung 1 for (int k = 0; k < nProdukte; ++k) //k Element {1, ..., K} { for (int t = 0; t < nPerioden; ++t) // t Element {1, ..., T} { cout << "Fuege Nebenbedingung 1 ein fuer Produkt: " << k << " in Periode " << t << endl; IloExpr NB1(env); // erst hier IloExpr NB(env anlegen) for (int i = 0; i < nProdukte; ++i) { NB1-= a_k_i[k][i] * q_k_t[i][t]; //NB1 = NB1 - } NB1-= y_k_t[k][t]; if (t-1>=0) { NB1+= y_k_t[k][t-1]; } if(t-z_k[k] >= 0) { NB1+= q_k_t[k][t-z_k[k]]; } model.add(NB1 == d_k_t[k][t]); // model.add erst hier } } //Nebenbedingung 2 // Schranke auf Basis von Produktionszeit mal Produktionsmenge/t plus Rüstzeit mal Entscheidungsvariable for (int j = 0; j < nRessourcen; ++j) //Vergleiche mit zweiter NB in testcasegenerator.pdf //j Element {1, ..., j} { for (int t = 0; t < nPerioden; ++t) //t Element {1, ..., t} { IloExpr NB2(env); // erst hier IloExpr NB(env anlegen) for(int k = 0; k < nProdukte; ++k) { NB2+= tb_k[k] * q_k_t[k][t] + tr_k[k] * Gamma_k_t[k][t]; //sieht richtig aus } model.add(NB2 <= b_j_t[j][t]); } } //Nebenbedingung 3 for (int k = 0; k < nProdukte ; ++k) { IloExpr NB3(env); for(int t=0; t < nPerioden; ++t) { NB3+= q_k_t[k][t] - 10000 * Gamma_k_t[k][t]; //M auf RIESIG setzen } model.add(NB3 <= 0); } //Minimiere Z //ZIELFUNKTION IloExpr ZF(env); for (int k = 0; k < nProdukte; ++k) { for(int t = 0; t < nPerioden; ++t) { for (int j = 0; j < nRessourcen; ++j) { ZF+= s_k[k] * Gamma_k_t[k][t] + h_k[k] * y_k_t[k][t] + m_j[j] * (b_j_t[j][t] - tb_k[k] * q_k_t[k][t] + (tr_k[k] * Gamma_k_t[k][t])); //Klammern?! } } } IloObjective myObj(env, ZF, IloObjective::Minimize); //Zielfunktion //vgl.VL Folie 29 //Modell hinzufuegen model.add(myObj); //Loesen //vgl. Folie 32 CPLEX-VL IloCplex cplex(env); cplex.extract(model); cplex.exportModel("model.lp"); // Ergebnisse werden in eine datei model.lp exportiert, die wird automatisch erstellt, man kann die mit dem txt editor öffnen if (cplex.solve()) { std::cout << "Systemstatus " << cplex.getStatus() << std::endl; std::cout << "Zielfunktionswert = " << cplex.getObjValue() << std::endl; //Ausgabe for(int k = 0; k < nProdukte; ++k) { for (int t = 0; t < nPerioden; ++t) { IloNum value = cplex.getValue(q_k_t[k][t]); std::cout << "Produktionsmenge_Gesamt Produkt " << k << " Periode " << t << " : " << value << std::endl; } } } else { std::cout << "Keine Lösung" << std::endl; } ZF.end(); //NB3.end(); //NB2.end(); //NB1.end(); m_j.end(); K_j_k.end(); b_j_t.end(); a_k_i.end(); d_k_t.end(); tb_k.end(); tr_k.end(); z_k.end(); h_k.end(); s_k.end(); myfile.close(); env.end(); system("pause"); return 0; }Falls es etwas hilft: Die Ausgabe in der Datei "Model.lp" liest sich wie folgt:
\ENCODING=ISO-8859-1
\Problem name: IloCplexMinimize
obj: 6 x1 - 20 x2 + 6 x3 - 20 x4 + 6 x5 - 20 x6 + 6 x7 - 20 x8 + 14 x9
+ 14 x10 + 14 x11 + 14 x12 + x13
Subject To
c1: - x1 + x2 = 0
c2: x1 - x3 + x4 = 0
c3: - x2 - x5 + x6 = 2
c4: - x4 + x5 - x7 + x8 = 2
c5: 2 x2 + 2 x6 + x9 + x10 <= 15
c6: 2 x4 + 2 x8 + x11 + x12 <= 15
c7: 2 x2 + 2 x6 + x9 + x10 <= 10
c8: 2 x4 + 2 x8 + x11 + x12 <= 10
c9: x2 + x4 - 10000 x9 - 10000 x11 <= 0
c10: x6 + x8 - 10000 x10 - 10000 x12 <= 0
Bounds
0 <= x9 <= 1
0 <= x10 <= 1
0 <= x11 <= 1
0 <= x12 <= 1
x13 = 500
Binaries
x9 x10 x11 x12
End
-
Deine NBs sind schon lange nicht mehr gültig, wenn du NB1.end() aufrufen willst.
for(...) { int variable = 5; } variable = 45; // FEHLER! // jetzt existiert variable nicht mehr // sobald ein { }-Block verlassen wurde (z.B. von einer for-Schleife), existieren Variablen, die innerhalb des Blocks definiert wurden, nicht mehr. int variable = 5; for(...) { } variable = 12; // OK // jetzt gibt es variable noch, da es außerhalb von { } definiert wurdeWenn die Ausgabe nicht stimmt, hast du einen logischen Fehler. Wenn er konzeptionell falsch ist, solltest du vielleicht lieber mal deinen Betreuer fragen als hier. Sofern du denkst, dass du ihn theoretisch richtig hast, aber nur falsch in Code gegossen hast, solltest du mal abreißen, was er tun soll (u.U. Pseudo-Code).
Außerdem kannst du den Visual-Studio Debugger bemühen, der es dir erlaubt, Zeile für Zeile des Programms schrittweise durch zu gehen, während es läuft. Du kannst da die aktuellen Werte in den Variablen sehen und schauen, ob Erwartung und Realität übereinstimmen und gucken, ab wo es nicht mehr stimmt.
@ Mod: Ins C++-Forum damit bitte!
-
Dieser Thread wurde von Moderator/in SeppJ aus dem Forum Mathematik und Physik in das Forum C++ (alle ISO-Standards) verschoben.
Im Zweifelsfall bitte auch folgende Hinweise beachten:
C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?Dieses Posting wurde automatisch erzeugt.
-
cppdussel schrieb:
Das - so vermute ich - am leichtesten zu lösende Problem ist folgendes: Ich habe 3 Nebenbedingungen im Programm und bekomme, wenn ich den Befehl "NB1.end();" (auch NB2 und NB3)verwenden möchte, die Fehlermeldung "nicht deklarierter Bezeichner". Ich vermute, dies hängt mit den "For"-Schleifen in den Nebenbedingungen zusammen, kann den Fehler aber nicht finden.

Ja. Du musst das NB?.end() jeweils in den for-Schleifen hinzufügen.
Disclaimer: Ich kenn das Framework nicht und weiß insbesondere nicht, wie man damit arbeitet. Scheinbar haben die Klassen keine Destruktoren, insbesondere wird das end() nicht automatisch aufgerufen. Unter der Voraussetzung, dass man das dennoch braucht, gehört es in die for-Schleife. Vielleicht braucht man es auch nicht -- deine Entscheidung.
Des Weiteren erzeugt mein Programm zur Fehlerfindung eine Textdatei "Model.lp". Diese lässt sich mit der Musterlösung vergleichen und zeigt, dass bei mir durchaus einiges im Argen liegt. Meine Kenntnisse in c++ sind jedoch so begrenzt, dass ich an meine Grenzen stoße und daher Hilfe benötige.
Na so ein Glück, dass die model.lp nichts mit C++ zu tun hat, oder? Was genau liegt da denn "im Argen"?
-
alsoooo...vielen Dank erstmal! Sorry wegen der falschen Einordnung, dachte mir "lineare Programmierung, Mathematik...mh, passt"

Bashar schrieb:
Disclaimer: Ich kenn das Framework nicht und weiß insbesondere nicht, wie man damit arbeitet. Scheinbar haben die Klassen keine Destruktoren, insbesondere wird das end() nicht automatisch aufgerufen. Unter der Voraussetzung, dass man das dennoch braucht, gehört es in die for-Schleife. Vielleicht braucht man es auch nicht -- deine Entscheidung.
Na so ein Glück, dass die model.lp nichts mit C++ zu tun hat, oder? Was genau liegt da denn "im Argen"?
Das mit dem .end() ist - soweit ich weiß - nicht zwingend notwendig für das Programm, sondern dient der Speicherfreigabe. Da ich hier zum Test eine kleine Instanz habe, ist das nicht tragisch, aber könnte es werden... oder so ^^ ich verschiebe das einfach in die NB und seh mir das Ergebnis an

zu der Ausgabe bzw. der .txt:
Die Musterlösung sieht wie folgt aus:\ENCODING=ISO-8859-1 \Problem name: IloCplex Minimize obj: 3 x2 + 3 x4 + 3 x6 + 3 x8 + 2 x9 + 5 x10 + 2 x11 + 5 x12 + 2 x13 + 5 x14 + 2 x15 + 5 x16 + x17 Subject To c1: x1 - x2 = 0 c2: x2 + x3 - x4 = 0 c3: - x1 + x5 - x6 = 2 c4: - x3 + x6 + x7 - x8 = 2 c5: 2 x1 + x9 + x10 = 15 c6: 2 x3 + x11 + x12 = 15 c7: 2 x5 + x13 + x14 = 10 c8: 2 x7 + x15 + x16 = 10 c9: x1 - 15 x9 <= 0 c10: x3 - 15 x11 <= 0 c11: x5 - 10 x13 <= 0 c12: x7 - 10 x15 <= 0 Bounds 0 <= x9 <= 1 0 <= x11 <= 1 0 <= x13 <= 1 0 <= x15 <= 1 x17 = 0 Binaries x9 x11 x13 x15 EndZum Vergleich noch mal meine .txt:
\ENCODING=ISO-8859-1 \Problem name: IloCplex Minimize obj: 6 x1 - 20 x2 + 6 x3 - 20 x4 + 6 x5 - 20 x6 + 6 x7 - 20 x8 + 14 x9 + 14 x10 + 14 x11 + 14 x12 + x13 Subject To c1: - x1 + x2 = 0 c2: x1 - x3 + x4 = 0 c3: - x2 - x5 + x6 = 2 c4: - x4 + x5 - x7 + x8 = 2 c5: 2 x2 + 2 x6 + x9 + x10 <= 15 c6: 2 x4 + 2 x8 + x11 + x12 <= 15 c7: 2 x2 + 2 x6 + x9 + x10 <= 10 c8: 2 x4 + 2 x8 + x11 + x12 <= 10 c9: x2 + x4 - 10000 x9 - 10000 x11 <= 0 c10: x6 + x8 - 10000 x10 - 10000 x12 <= 0 Bounds 0 <= x9 <= 1 0 <= x10 <= 1 0 <= x11 <= 1 0 <= x12 <= 1 x13 = 500 Binaries x9 x10 x11 x12 EndGewisse Vorzeichenverdreher sind laut Betreuung (ich zitiere mein Gruppenmitglied, ich hoffe, er hat das richtig verstanden) nicht schlimm und darauf zurückzuführen, dass ich einfach eine andere Formulierung verwendet habe. Mir ist insbesondere aufgefallen, dass die Indizes oftmals genau um einen versetzt sind. Die 10000 bei c9 und c10 in meiner .txt sind Platzhalter für das "Big M" (Zur Linearisierung in einer der Nebenbedingungen), was ich noch näher bestimmen müsste.
Meine Ausgabe gibt mir als Zielfunktionswert 369 aus und alsProduktionsmenge_gesamt Produkt 0 Periode 0: 1
Produktionsmenge_gesamt Produkt 0 Periode 1: 1.5
Produktionsmenge_gesamt Produkt 1 Periode 0: 3
Produktionsmenge_gesamt Produkt 1 Periode 1: 3.5Das ist insofern unlogisch, als dass ja nichts halbes produziert werden kann und der ZF mir zu hoch erscheint.
edit: mir ist ein dummer Fehler unterlaufen, ich habe in der Musterlösung die Sanktion der nicht-auslastung der Ressource noch nicht, in meinem Modell schon. Das habe ich jetzt ausgeklammert und es kommen dann folgende Werte heraus:
Zielfunktionswert: 4
Produktionsmenge_gesamt Produkt 0 Periode 0: 0
Produktionsmenge_gesamt Produkt 0 Periode 1: 0
Produktionsmenge_gesamt Produkt 1 Periode 0: 2
Produktionsmenge_gesamt Produkt 1 Periode 1: 2