Forum: Markt Projekthilfe gesucht - Parallela Cluster (Supercomputing :))


von Roman S. (sroman)


Lesenswert?

Hallo Zusammen,

ich bräuchte Hilfe bei einem Projekt. Es geht darum mit diesem (oder 
ähnlichem) Entwicklungsboards:
http://de.rs-online.com/web/c/halbleiter/entwicklungskits/entwicklungskits-prozessor-mikrocontroller/?searchTerm=Parallella
ein Cluster zu bauen, ähnlich wie hier sehen
https://www.google.de/search?q=parallela+cluster

Es geht darum dieses Programm erheblich zu beschleunigen
1
<?php
2
3
  $beginn = microtime(true);
4
  $counter = 0;
5
  $treffer = 0;
6
  $m =  array();
7
8
  $bestand[0]['inhaltsstoff_1'] = 6.95;
9
  $bestand[1]['inhaltsstoff_1'] = 65.7;
10
  $bestand[2]['inhaltsstoff_1'] = 12.2;
11
  $bestand[3]['inhaltsstoff_1'] = 2;
12
  $bestand[4]['inhaltsstoff_1'] = '';
13
14
15
  for ($m[0] = 0; $m[0] <= 100; $m[0]++) {
16
  for ($m[1] = 0; $m[1] <= (100 - $m[0]); $m[1]++) {
17
      for ($m[2] = 0; $m[2] <= (100 - $m[0] - $m[1]);  $m[2]++) {
18
      for ($m[3] = 0; $m[3] <= (100 - $m[0] - $m[1] - $m[2]);  $m[3]++) {
19
       
20
      $m[4] = (100 - $m[0] - $m[1] - $m[2] - $m[3]);
21
22
    $counter++;
23
24
    $inhaltsstoff_1 = ($m[0] * $bestand[0]['inhaltsstoff_1']) +
25
              ($m[1] * $bestand[1]['inhaltsstoff_1']) +
26
              ($m[2] * $bestand[2]['inhaltsstoff_1']) +
27
              ($m[3] * $bestand[3]['inhaltsstoff_1']) +
28
              ($m[4] * $bestand[4]['inhaltsstoff_1']);
29
    $inhaltsstoff_1 /= 100;
30
31
    if ($inhaltsstoff_1 <= 6) {
32
      $treffer++;
33
    }
34
35
  }
36
  }
37
  }
38
  }
39
40
  print('Loops: ' . number_format($counter, 0, '', '.') . '<br>');
41
  print('Hits: ' . number_format($treffer, 0, '', '.') .  '<br>');
42
  print('Seconds: ' . number_format((microtime(true) - $beginn), 3, ',', '') . ' sec.');
43
?>
Das ist jetzt PHP, aber wer C und C++ kann, wird sicherlich auch das 
Script verstehen.
Es gibt verschiedene Rohstoffe und Vorgaben (Menge, Inhaltstoffe). Ziel 
ist es das günstigste
Mischungsverhälntis zu finden. Im Grunde ganz einfach. Nur ineinander 
geschachtelte for Schleifen,
die alle möglichen Mischungsverhälntisse in Prozent berechnen.

Das Problem ist die Rechenzeit.
1
3 Rohstoffe  Loops: 5.151    Seconds: 0,012 sec.
2
4 Rohstoffe  Loops: 176.851    Seconds: 0,420 sec.
3
5 Rohstoffe  Loops: 4.598.126  Seconds: 14,165 sec.
4
...

Ideal wäre es, wenn man 30 Rohstoffe mit einer 1% Genauigkeit 
durchrechnen könnte.

Das man jemals da hinkommt, glaube ich nicht, aber man kann's ja mal 
versuchen, wie weit man mit
richtig Rechenpower kommt. Die Schleifen dürfte man eigentlich gut auf 
mehrere Prozessoren verteilen
können.

Er hier: 
http://www.rechenkraft.net/forum/viewtopic.php?f=83&t=12405&start=12
dürft schon deutlich schneller sein als die 2,8 Ghz (Single-Core) vom 
PHP Server. Zwei bis Vier
Board's dürften aber für den ersten Test erstmal reichen. Dann kann 
abschätzen wieviele Board's
Sinn machen würden.

Gibt es jemand der helfen könnte, dieses kleine Script auf so einem 
Cluster laufen zu lassen?
Ist kein Hobby-Projekt, würde natürlich auch bezahlt werden.

Viele Grüße
Roman

von Hannes W. (7nrn3ap3)


Lesenswert?

Exponentielle Komplexität mit linearer Skalierung erschlagen ;)
Das bekommen schon die richtigen HPC'ler nicht hin.

Lös' doch einfach das unterliegende DGL mit entsprechend optimierter 
Software, anstatt das selber machen zu wollen …

von Soeren K. (srkeingast)


Lesenswert?

Hi Roman,

PHP ist schonmal blöd. Habe das trotzdem mal auf 5.6 auf meinem i7-4770k 
laufen lassen: 2 Sekunden.

Mit PHP7 ist es noch eine Sekunde.

Mit einer "vernünftigen" Programmiersprache, sollte das ganze noch 
erheblich schneller gehen; auf einem Kern.

von Pic T. (pic)


Lesenswert?

Kannst du mal aufschlüsseln was das Ziel des Programmes ist?
Man mixt 0-6 Inhaltstoffe rein, welche prioritisiert werden,
es ist aber egal welche Zusammensetzung, es wird die Summe des 
Gewicht/Volumen begrenzt.

von Roman S. (sroman)


Lesenswert?

@Hannes W.
Je mehr Rechenpower desto mehr Komponenten sind möglich. Desto besser.
Rein softwareseitig, soll aus vielen verschiedenen Rohstoffen die 
günstigste Mischung gefunden werden, die den Produktanforderungen noch 
entspricht.
Außer Brute-Force (s.o.) gibt es keine Lösung. Bei Brute-Force haben wir 
schon sehr viele Filter im Einsatz die Schleifen einsparen, und auf 
X-Wegen abkürzen, aber auch das hat logisch, und von der Bedienung 
grenzen...

@Soeren
Ist alles bekannt. Die Zeiten stammen von einem Xamp System das maximal 
mit 10% unter Windows 10 laufen kann. Der LiveServer mit PHP7 ist 
nochmal deutlich schneller. Wenn wir auf C oder C++ umsteigen (eigene 
PHP Module), etwa 5-8 schneller. Relevant weiter hilft uns das nicht... 
aber 1.000x
schneller ggf. schon:
2,8Ghz mit PHP7 vs. 640 Cores (40x Parallela) a 800Mhz mit C
ganz grob 640 x 0.8 * 5(für C) / 2.8 = 914x
Die kleinen Boards können auch gut zwei Tage durchrechnen.

An dem Projekt arbeite ich schon seit Monaten -
Wir brauchen einen Supercomputer :)

von Roman S. (sroman)


Lesenswert?

@Pic Tech

Auf eine Produktgruppe bezogen:

Es gibt aktuell auf Lager 40 verschiedene Rohsstofftypen mit 5-12 
Inhaltsstoffen (einer davon ist Nutzinhalt), einer Menge und natürlich 
einem Preis.

Die Kunden bestellen immer einen Mix mit unterschiedlichen 
Spezifikationen (Inhaltsstoff 1. min 35% und max 37%, Inhaltsstoff 4 max 
0.02% usw.) und natürlich die Menge.

Je günstiger man den Mix herstellen kann, desto mehr Geld verdient die 
Firma.

: Bearbeitet durch User
von Alexander F. (alexf91)


Lesenswert?

Kann man dafür nicht existierende Tools verwenden, die schon allerlei 
Optimierungen eingebaut haben?
Optimierungsprobleme treten ja nicht gerade selten auf.

Faktor 5-8 in C kannst du mit mehreren Threads auch noch verfielfachen.

von Pic T. (pic)


Lesenswert?

av@av-1005HA:~/test/tmp/cnc$ php5 t1.php
Loops: 4.598.126    <br>
Hits: 400.800    <br>
Seconds: 10,360 sec.

Optimierung der Variablen , kein hash lookup, oder einer weniger
  $bestand[0]['inhaltsstoff_1'] = 6.95; =>  $bestand[0]=6.95;

av@av-1005HA:~/test/tmp/cnc$ php5 t1.php
Loops: 4.598.126    <br>
Hits: 400.800    <br>
Seconds: 8,434 sec.

Dasselbe mit tcc compiliert,

av@av-1005HA:~/test/tmp/cnc$ ./a.out
Loops: 4598126
Hits: 400800
Seconds: 0.249174 sec

sowie mit gcc

av@av-1005HA:~/test/tmp/cnc$ ./a.out
Loops: 4598126
Hits: 400754
Seconds: 0.118603 sec

Trotzdem würde ich da eher eine rechnerische Lösung vorziehen.
Muss es denn pnp sein ?

von Josef C. (josefc)


Lesenswert?

Das sieht wie ein typisches Problem der linearen Optimierung (linear 
programming) aus.
Das php programm ist das "Diet Problem", als einfuehrendes Beispiel in 
das
Gebiet.
Bewaehrter Algorithmus ist der Simplex Algorithmus.
Solver loesen Probleme mit Tausenden von Variablen problemlos.

Falls das Problem doch nicht so gut strukturiert ist lohnt sich
ein Blick auf "Constraint Programming".

von Mike B. (mike_b97) Benutzerseite


Lesenswert?

einen Beowulf-Cluster fürs Raytracing hatte ich mal auf einem 
Debian-Server mit 4 Nodes (alte Laptops) aufgestellt

die Clustersoftware war Kestrel-HPC
http://kestrelhpc.sourceforge.net/ (Vers. 2.0 damals verwendet, wird 
wohl leider nicht mehr gepflegt)

Programmiersprache war C++ mit dem Open-MPI-Zusatz mit der 
Code::Blocks-IDE

das ganze lief nach einiger Mühe mit PXE-Boot
und es lief ganze drei Tage, bis die (nicht gesicherte) 
Server-Hauptfestplatte sich verabschiedet hat (die einzige von meinen 50 
Platten die nicht hätte kaputt gehen dürfen..., Murphy halt)

sollte auch heute noch mit den alten Debian-Versionen (6.0 war es glaub 
ich) nochmal aufzubauen sein, Kestrel usw. kann man ja noch runterladen
Code nach C++ portieren, OpenMPI reinfrickeln und ab damit

in Sachen Performance aber lief meiner auf Maulwurf-Level, hätte 
rechnerisch 1.3GFlops haben sollen und hatte 300MFlops (ja, ist schon 
etwas länger her)

von Roman S. (sroman)


Lesenswert?

Pic Tech - Nein, PHP auf gar keinen Fall :) Das haben wir ja schon. Auf 
dem Linux LiveServer braucht das Script von oben, mit PHP7 und 2,8GHz

Loops: 4.598.126
Hits: 400.800
Seconds: 1,887 sec.

@Josef C. - "Bewaehrter Algorithmus ist der Simplex Algorithmus."
Ich kann mir im Moment nicht wirklich vorstellen, das es eine 
intelligente Lösung gibt, anstelle von Brute-Force. Denn ich habe 30 
Komponenten mit 8-15 Analysewerten mit eigenen Spezifikationen, einem 
Preis und einer maximal mischbaren Menge. Da gibt es keinen Roten Faden 
dem man folgen kann. Die einen Werte werden richtiger, die anderen 6 
falscher... was dann? Ich bin allerdings auch kein Mathematiker.

@Mike B. - Puh, kenne mich da garnicht aus. Gibt ja schon einige die 
solche Cluster gebaut haben. Die Kunst wird es wohl sein die ganzen 
Schleifen sinnvoll auf die Kerne zu verteilen und die Ergebnisse in zwei 
Tagen wieder abzuholen.

: Bearbeitet durch User
von Alexander F. (alexf91)


Lesenswert?

Alternativ kannst du in deinem PHP Programm eine Zielfunktion samt 
Nebenbedingungen für deinen Zaubertrank generieren:
Die Zielfunktion ist in deinem Fall die Kostenfunktion, die minimiert 
werden soll.
Die Nebenbedingungen sind die Anteile der Zutaten und sonstige 
Beschränkungen und Abhängigkeiten.
Diese Gleichungen gibst du dann in einem Standardformat (z.B. CPLEX) aus 
und jagst sie durch einen LP Solver.
Das erspart dir zumindest die Implementierung des Simplex Algorithmus.

von Josef C. (josefc)


Lesenswert?

Roman S. schrieb:
> Pic Tech - Nein, PHP auf gar keinen Fall :) Das haben wir ja schon. Auf
> dem Linux LiveServer braucht das Script von oben, mit PHP7 und 2,8GHz
>
> Loops: 4.598.126
> Hits: 400.800
> Seconds: 1,887 sec.
>
> @Josef C. - "Bewaehrter Algorithmus ist der Simplex Algorithmus."
> Ich kann mir im Moment nicht wirklich vorstellen, das es eine
> intelligente Lösung gibt, anstelle von Brute-Force. Denn ich habe 30
> Komponenten mit 8-15 Analysewerten mit eigenen Spezifikationen, einem
> Preis und einer maximal mischbaren Menge. Da gibt es keinen Roten Faden
> dem man folgen kann. Die einen Werte werden richtiger, die anderen 6
> falscher... was dann? Ich bin allerdings auch kein Mathematiker.
>

Um das zu klaeren solltest du dein Problem mal richtig formulieren.
Bis jetzt sieht es nach einem 
https://de.wikipedia.org/wiki/Lineare_Optimierung#Mischungsprobleme aus.

Es sollte geklaert werden, ob das Problem linear ist. Also z.B.
Inhaltsstoff = Menge * Faktor
und keine Potenz oder Wurzel oder sowas in den Variablen auftritt.

Dann ob die Loesung eine ganze Zahl sein muss oder ob auch Bruchzahlen
erlaubt sind. Z.B. von Material1 2.345kg etc.
Bei lebenden Tieren sind normal nur ganze Zahlen erlaubt. Ganzzahlige 
Probleme sind viel schwieriger zu loesen.
Ja und den Algorithmus musst du nicht programmieren. Es gibt genuegend 
Solver (glpk, lpsolve, cplex ...).

Da durch solche Optimierungen viel Geld verdient werden kann, wurde 
schon
eine Menge Hirnschmalz investiert.

von Mike B. (mike_b97) Benutzerseite


Lesenswert?

Roman S. schrieb:

> @Mike B. - Puh, kenne mich da garnicht aus. Gibt ja schon einige die
> solche Cluster gebaut haben. Die Kunst wird es wohl sein die ganzen
> Schleifen sinnvoll auf die Kerne zu verteilen und die Ergebnisse in zwei
> Tagen wieder abzuholen.

das macht OpenMPI automatisch
einfach die #pragma-lauseln an die richtige Stelle setzen
nicht effizient aber simple, fürs erste

von Roman S. (sroman)


Lesenswert?

Hallo Josef, hallo Alexander

Danke für die Nachricht. Hier findest Du ein ausführliches Beispiel
1
<?php
2
3
    $beginn = microtime(true);
4
    $counter = 0;
5
    $needed_quantity = 200000;
6
    $m =  array();
7
8
    // Iron Share in %
9
    $stock[0]['iron'] = 17.5;
10
    $stock[1]['iron'] = 60;
11
    $stock[2]['iron'] = 60;
12
    $stock[3]['iron'] = 68.6;
13
    $stock[4]['iron'] = 59.745;
14
15
    // rawmaterial quantity
16
    $stock[0]['quantity'] = 69148;
17
    $stock[1]['quantity'] = 25460;
18
    $stock[2]['quantity'] = 34020;
19
    $stock[3]['quantity'] = 69873;
20
    $stock[4]['quantity'] = 737299;
21
22
    // price per ton
23
    $stock[0]['price'] = 13.21;
24
    $stock[1]['price'] = 27.46;
25
    $stock[2]['price'] = 35.66;
26
    $stock[3]['price'] = 89.21;
27
    $stock[4]['price'] = 60.69;
28
29
    for ($m1 = 0; $m1 <= 100;                           $m1 += 2) {
30
    for ($m2 = 0; $m2 <= (100 - $m1);                   $m2 += 2) {
31
    for ($m3 = 0; $m3 <= (100 - $m1 - $m2);             $m3 += 2) {
32
    for ($m4 = 0; $m4 <= (100 - $m1 - $m2 - $m3);       $m4 += 2) {
33
                  $m5  = (100 - $m1 - $m2 - $m3 - $m4);
34
35
36
    $counter++;
37
38
    $iron = ($m1 * $stock[0]['iron']) +
39
            ($m2 * $stock[1]['iron']) +
40
            ($m3 * $stock[2]['iron']) +
41
            ($m4 * $stock[3]['iron']) +
42
            ($m5 * $stock[4]['iron']);
43
    $iron /= 100;
44
45
    // Check Iron Share first
46
    if ($iron < 60) {
47
        continue;
48
    }
49
50
    $price = ($m1 * $stock[0]['price']) +
51
             ($m2 * $stock[1]['price']) +
52
             ($m3 * $stock[2]['price']) +
53
             ($m4 * $stock[3]['price']) +
54
             ($m5 * $stock[4]['price']);
55
    $price /= 100;
56
57
    // Calculation the max. quantity for this mix. 
58
    // Extrapolate each rawmaterial quantity to find the smallest possible quantity 
59
    $quantity = 100000000000;
60
    if ($m1) { $temp = $stock[0]['quantity'] * (100 / $m1); if ($temp < $quantity) { $quantity = $temp; } }
61
    if ($m2) { $temp = $stock[1]['quantity'] * (100 / $m2); if ($temp < $quantity) { $quantity = $temp; } }
62
    if ($m3) { $temp = $stock[2]['quantity'] * (100 / $m3); if ($temp < $quantity) { $quantity = $temp; } }
63
    if ($m4) { $temp = $stock[3]['quantity'] * (100 / $m4); if ($temp < $quantity) { $quantity = $temp; } }
64
    if ($m5) { $temp = $stock[4]['quantity'] * (100 / $m5); if ($temp < $quantity) { $quantity = $temp; } }
65
66
    // Check Quantity
67
    if ($needed_quantity) {
68
        if ($quantity < $needed_quantity) {
69
            continue;
70
        }
71
    }
72
73
    // Calculate the used quantity 
74
    $m1_quantity = round($quantity * ($m1 / 100));
75
    $m2_quantity = round($quantity * ($m2 / 100));
76
    $m3_quantity = round($quantity * ($m3 / 100));
77
    $m4_quantity = round($quantity * ($m4 / 100));
78
    $m5_quantity = round($quantity * ($m5 / 100));
79
80
    // Caculate how many percent of stock we need 
81
    $m1_quantity_percent = round(($quantity * ($m1 / 100)) / $stock[0]['quantity'] * 100,2);
82
    $m2_quantity_percent = round(($quantity * ($m2 / 100)) / $stock[1]['quantity'] * 100,2);
83
    $m3_quantity_percent = round(($quantity * ($m3 / 100)) / $stock[2]['quantity'] * 100,2);
84
    $m4_quantity_percent = round(($quantity * ($m4 / 100)) / $stock[3]['quantity'] * 100,2);
85
    $m5_quantity_percent = round(($quantity * ($m5 / 100)) / $stock[4]['quantity'] * 100,2);
86
87
    // For ksort(), find unique price array keys
88
    $key = $price * 10000;
89
    while(isset($results[$key])) { $key += 1; }
90
91
    // Save the result
92
    $result[$key] = "<tr><td>$counter</td>
93
            <td>$m1 ($m1_quantity kg - $m1_quantity_percent %)</td>
94
            <td>$m2 ($m2_quantity kg - $m2_quantity_percent %)</td>
95
            <td>$m3 ($m3_quantity kg - $m3_quantity_percent %)</td>
96
            <td>$m4 ($m4_quantity kg - $m4_quantity_percent %)</td>
97
            <td>$m5 ($m5_quantity kg - $m5_quantity_percent %)</td>
98
            <td><b>" . round($iron,2) . "%</b></td>
99
            <td><b>" . round($quantity) . "kg</b></td>
100
            <td><b>" . round($price,2) . "</b></td></tr>";
101
102
}
103
}
104
}
105
}
106
107
ksort($result);
108
print("<table border=1 cellpadding=2>
109
<tr><td>Nr.</td>
110
    <td>m1</td>
111
    <td>m2</td>
112
    <td>m3</td>
113
    <td>m4</td>
114
    <td>m5</td>
115
    <td><b>Total Iron Share</b></td><td><b>Max.Quantity</b></td><td><b>Price\t</b></td></tr>");
116
foreach($result as $k => $v) {
117
    print($v);
118
}
119
print("</table>");
120
121
print('Loops: '   . number_format($counter, 0, '', '.') . '<br>');
122
print('Seconds: ' . number_format((microtime(true) - $beginn), 3, ',', '') . ' sec.');
123
124
?>

Gesucht wird die günstigste Mischung mit 2% Genauigkeit.
Menge > 200t, und Eisenanteil > 60%.

Neben Eisen "Iron Share" gibt es noch weitere solcher
Bedingungen die bei ein gültigen Mischung erfüllt sein müssen.
Ich denke was aus dem Rahmen fällt ist die theoretisch mischbare
Menge mit dem Mischungsverhältnis. Da muß man erst kleinste Menge
finden und diese dann hochrechnen. Siehe Beispiel. Sonst müßten alle 
Bedingungen 'Linear' wenn ich das richtig verstanden habe.

Wenn man ohne Brute-Force durchkommen könnte, wäre natürlich super.

Ansonsten habe ich noch das hier gefunden
http://www.nvidia.de/object/cuda-parallel-computing-de.html
(eine nvidia titan x hat 7 teraflops ... )

: Bearbeitet durch User
von Pic T. (pic)


Lesenswert?

Wenn ich das letzte Programm mit C compiliere, erhalte ich folgende 
Werte,
auf demselben langsamen Rechner wie die oben geposteten Werte.
Mit Ausgabe sind es 0.73 Sekunden, wobei 0.05 reine Rechenzeit.
Dies ohne Sortierung, die sollte aber nicht viel Zeit kosten.

Loops: 316251
Seconds: 0.046168 sec

real  0m0.730s
user  0m0.032s
sys  0m0.016s

Sortierte liste (command line):
Result:   Price: 53.838400 Iron: 60.170600 Quantity: 212166.666667 -- 
, m1 0 kg - 0 %    , m2 25460 kg - 12 %    , m3 33947 kg - 16 %    , m4 
8487 kg - 4 %    , m5 144273 kg - 68 %
Result:   Price: 54.339000 Iron: 60.165500 Quantity: 212166.666667 -- 
, m1 0 kg - 0 %    , m2 25460 kg - 12 %    , m3 29703 kg - 14 %    , m4 
8487 kg - 4 %    , m5 148517 kg - 70 %
Result:   Price: 54.408800 Iron: 60.347700 Quantity: 212166.666667 -- 
, m1 0 kg - 0 %    , m2 25460 kg - 12 %    , m3 33947 kg - 16 %    , m4 
12730 kg - 6 %    , m5 140030 kg - 66 %
Result:   Price: 54.503000 Iron: 60.165500 Quantity: 212625.000000 -- 
, m1 0 kg - 0 %    , m2 21263 kg - 10 %    , m3 34020 kg - 16 %    , m4 
8505 kg - 4 %    , m5 148838 kg - 70 %
Result:   Price: 54.839600 Iron: 60.160400 Quantity: 212166.666667 -- 
, m1 0 kg - 0 %    , m2 25460 kg - 12 %    , m3 25460 kg - 12 %    , m4 
8487 kg - 4 %    , m5 152760 kg - 72 %
Result:   Price: 54.909400 Iron: 60.342600 Quantity: 212166.666667 -- 
, m1 0 kg - 0 %    , m2 25460 kg - 12 %    , m3 29703 kg - 14 %    , m4 
12730 kg - 6 %    , m5 144273 kg - 68 %
Result:   Price: 54.979200 Iron: 60.524800 Quantity: 212166.666667 -- 
, m1 0 kg - 0 %    , m2 25460 kg - 12 %    , m3 33947 kg - 16 %    , m4 
16973 kg - 8 %    , m5 135787 kg - 64 %
Result:   Price: 55.003600 Iron: 60.160400 Quantity: 243000.000000 -- 
, m1 0 kg - 0 %    , m2 24300 kg - 10 %    , m3 34020 kg - 14 %    , m4 
9720 kg - 4 %    , m5 174960 kg - 72 %
Result:   Price: 55.073400 Iron: 60.342600 Quantity: 212625.000000 -- 
, m1 0 kg - 0 %    , m2 21263 kg - 10 %    , m3 34020 kg - 16 %    , m4 
12758 kg - 6 %    , m5 144585 kg - 68 %
Result:   Price: 55.167600 Iron: 60.160400 Quantity: 212625.000000 -- 
, m1 0 kg - 0 %    , m2 17010 kg - 8 %    , m3 34020 kg - 16 %    , m4 
8505 kg - 4 %    , m5 153090 kg - 72 %

von Josef C. (josefc)


Lesenswert?

Roman S. schrieb:
> Gesucht wird die günstigste Mischung mit 2% Genauigkeit.
> Menge > 200t, und Eisenanteil > 60%.

Hier ist eine Loesung mit lpsolve.
1
/* mix1.lp */
2
3
min: 13.21 x0 + 27.46 x1 + 35.66 x2 + 89.21 x3 + 60.69 x4;
4
5
x0 + x1 + x2 + x3 + x4 >= 200000;
6
7
x0 <= 69148;
8
x1 <= 25460;
9
x2 <= 34020;
10
x3 <= 69873;
11
x4 <= 737299;
12
13
-0.425 x0  + 0.086 x3 - 0.00255 x4 >= 0;
14
15
/* 0.175*x0 + 0.60*x1 + 0.60*x2 + 0.686*x3 + 0.59745*x4 >= (x0 + x1 + x2 + x3 + x4)*0.6   */
16
/* 0.175 x0 + 0.60 x1 + 0.60 x2 + 0.686 x3 + 0.59745 x4 >= 120000;  */

$> lp_solve mix1.lp
Value of objective function: 1.05559e+07

Actual values of the variables:
x0                              0
x1                          25460
x2                          34020
x3                         4046.6
x4                         136473

Fuer http://lpsolve.sourceforge.net/ gibt es auch eine php 
Schnittstelle.

Oder zum ausprobieren auch http://www.phpsimplex.com/en/help.htm.

P.S.:
Beim Ergebnis siehst du das die Summe nur 199999.6 ist. Die Genauigkeit 
laesst sich konfigurieren.

von Roman S. (sroman)


Lesenswert?

@Josef
Ich bin beindruckt. Das kannte ich so noch nicht.
Diese Bedingung vesteht ich allerdings nicht:

-0.425 x0  + 0.086 x3 - 0.00255 x4 >= 0;

Ich denke mal das gibt den Eisenanteil wieder (< 60%).
Gegeben war:

    $stock[0]['iron'] = 17.5;
    $stock[1]['iron'] = 60;
    $stock[2]['iron'] = 60;
    $stock[3]['iron'] = 68.6;
    $stock[4]['iron'] = 59.745;

x1 und x2 fällt weg. Ab wie kommst Du auf diese Bedingung?
Würde das gern mal mit 30 Komponenten und allen Bedingungen
ausprobieren. Danke!

: Bearbeitet durch User
von Pandur S. (jetztnicht)


Lesenswert?

Erstens wuerde ich die Mathematik anschauen, und nicht auf maximale 
Genuaigkeit, sondern auf maximale Geschwindigkeit trimmen. Besser als 
0.1% muss man keinen Inhaltsstoff einwiegen koennen.

Zweitens wuerde ich versuchen auf Hyperthreading, dann allenfalls auf 
eine GPU zu transportieren versuchen, weshalb geld fuer nichts ausgeben.

und dann versuchen floatingpoint durch integer zu ersetzen versuchen.

von Pic T. (pic)


Lesenswert?

poste dochmal einen Code mit 30 Variablen bzw Constraints sowie
benenn diese kurz.
Komischerweise ist das Resultat ein Eisengehalt von 70% bei der Rechnung
von oben, oder habe ich einen Fehler gemacht ?
Mein Code macht folgendes, eingestellt auf etwas mehr als 200kg und 60%.
Einfach iterative, basierend auf price-iron sowie iron, einfach kg für 
kg.

stock 1 price-iron = 75.485714 -- price = 13.210000 -- iron = 17.500000
stock 2 price-iron = 45.766667 -- price = 27.460000 -- iron = 60.000000
stock 3 price-iron = 59.433333 -- price = 35.660000 -- iron = 60.000000
stock 4 price-iron = 130.043732 -- price = 89.210000 -- iron = 68.600000
stock 5 price-iron = 101.581722 -- price = 60.690000 -- iron = 59.745000
m:   [0] 0.000%  [1] 12.730%  [2] 17.010%  [3] 0.150%  [4] 70.539%
t:   [0] 0.000   [1] 25.460   [2] 34.020   [3] 0.300   [4] 141.078
price: 52.505358 -- iron: 60.090426 % -- sum: 200.858000

von Roman S. (sroman)


Lesenswert?

@PicTec
Habe im Moment nur ein Beispiel mit 15 Rohstoffen. Und da geht schon 
mein Rechner in die Knie. Mit "$p = 1; // Precision" also 1% Genauigkeit 
sollte auch C am Ende sein. $p kann man Schrittweise runterschrauben. 
10, 5, 4, 2, 1 (muß gerade durch 100 teilbar sein).

Mit 10% sind es mit 15 Rohstoffen schon 1.961.256 Loops ...
Bei 30 Rohstoffen mit 1% dürfte es in Richtung while(true){} gehen :)
Zumindest bei Brute-Force.

1
<?php
2
3
  $beginn = microtime(true);
4
  $counter = 0;
5
  $results = 0;
6
  $needed_quantity = 200000;
7
  $p = 10; // Precision
8
  $m =  array();
9
10
  // Iron Share in %
11
  $stock[0]['iron'] = 17.5;
12
  $stock[1]['iron'] = 60;
13
  $stock[2]['iron'] = 60;
14
  $stock[3]['iron'] = 68.6;
15
  $stock[4]['iron'] = 59.745;
16
  $stock[5]['iron'] = 17.5;
17
  $stock[6]['iron'] = 60;
18
  $stock[7]['iron'] = 25;
19
  $stock[8]['iron'] = 68.6;
20
  $stock[9]['iron'] = 59.745;
21
  $stock[10]['iron'] = 17.5;
22
  $stock[11]['iron'] = 60;
23
  $stock[12]['iron'] = 30;
24
  $stock[13]['iron'] = 68.6;
25
  $stock[14]['iron'] = 59.745;
26
27
  // rawmaterial quantity
28
  $stock[0]['quantity'] = 69148;
29
  $stock[1]['quantity'] = 25460;
30
  $stock[2]['quantity'] = 34020;
31
  $stock[3]['quantity'] = 69873;
32
  $stock[4]['quantity'] = 737299;
33
  $stock[5]['quantity'] = 9148;
34
  $stock[6]['quantity'] = 25460;
35
  $stock[7]['quantity'] = 3050;
36
  $stock[8]['quantity'] = 6903;
37
  $stock[9]['quantity'] = 137299;
38
  $stock[10]['quantity'] = 29148;
39
  $stock[11]['quantity'] = 25260;
40
  $stock[12]['quantity'] = 30020;
41
  $stock[13]['quantity'] = 9873;
42
  $stock[14]['quantity'] = 7299;
43
44
  // price per ton
45
  $stock[0]['price'] = 13.21;
46
  $stock[1]['price'] = 27.46;
47
  $stock[2]['price'] = 35.66;
48
  $stock[3]['price'] = 89.21;
49
  $stock[4]['price'] = 60.69;
50
  $stock[5]['price'] = 23.21;
51
  $stock[6]['price'] = 37.46;
52
  $stock[7]['price'] = 45.66;
53
  $stock[8]['price'] = 89.21;
54
  $stock[9]['price'] = 70.69;
55
  $stock[10]['price'] = 14.21;
56
  $stock[11]['price'] = 28.46;
57
  $stock[12]['price'] = 36.66;
58
  $stock[13]['price'] = 90.21;
59
  $stock[14]['price'] = 50.69;
60
61
62
  for ($m0 = 0;  $m0  <= 100;   $m0 += $p) {
63
  for ($m1 = 0;  $m1  <= (100 - $m0);   $m1 += $p) {
64
    for ($m2 = 0;  $m2  <= (100 - $m0 - $m1);  $m2 += $p) {
65
    for ($m3 = 0;  $m3  <= (100 - $m0 - $m1 - $m2);    $m3 += $p) {
66
    for ($m4 = 0;  $m4  <= (100 - $m0 - $m1 - $m2 - $m3);    $m4 += $p) {
67
    for ($m5 = 0;  $m5  <= (100 - $m0 - $m1 - $m2 - $m3 - $m4);    $m5 += $p) {
68
    for ($m6 = 0;  $m6  <= (100 - $m0 - $m1 - $m2 - $m3 - $m4 - $m5);    $m6 += $p) {
69
    for ($m7 = 0;  $m7  <= (100 - $m0 - $m1 - $m2 - $m3 - $m4 - $m5 - $m6);    $m7 += $p) {
70
    for ($m8 = 0;  $m8  <= (100 - $m0 - $m1 - $m2 - $m3 - $m4 - $m5 - $m6 - $m7);    $m8 += $p) {
71
    for ($m9 = 0;  $m9  <= (100 - $m0 - $m1 - $m2 - $m3 - $m4 - $m5 - $m6 - $m7 - $m8);    $m9 += $p) {
72
    for ($m10 = 0; $m10 <= (100 - $m0 - $m1 - $m2 - $m3 - $m4 - $m5 - $m6 - $m7 - $m8 - $m9);    $m10 += $p) {
73
    for ($m11 = 0; $m11 <= (100 - $m0 - $m1 - $m2 - $m3 - $m4 - $m5 - $m6 - $m7 - $m8 - $m9 - $m10);    $m11 += $p) {
74
    for ($m12 = 0; $m12 <= (100 - $m0 - $m1 - $m2 - $m3 - $m4 - $m5 - $m6 - $m7 - $m8 - $m9 - $m10 - $m11);    $m12 += $p) {
75
    for ($m13 = 0; $m13 <= (100 - $m0 - $m1 - $m2 - $m3 - $m4 - $m5 - $m6 - $m7 - $m8 - $m9 - $m10 - $m11 - $m12);    $m13 += $p) {
76
77
    $m14  = (100 - $m0 - $m1 - $m2 - $m3 - $m4 - $m5 - $m6 - $m7 - $m8 - $m9 - $m10 - $m11 - $m12 - $m13);
78
79
    $counter++;
80
81
    $iron = ($m0 * $stock[0]['iron']) +
82
      ($m1 * $stock[1]['iron']) +
83
          ($m2 * $stock[2]['iron']) +
84
          ($m3 * $stock[3]['iron']) +
85
          ($m4 * $stock[4]['iron']) +
86
          ($m5 * $stock[5]['iron']) +
87
          ($m6 * $stock[6]['iron']) +
88
          ($m7 * $stock[7]['iron']) +
89
          ($m8 * $stock[8]['iron']) +
90
          ($m9 * $stock[9]['iron']) +
91
          ($m10 * $stock[10]['iron']) +
92
          ($m11 * $stock[11]['iron']) +
93
          ($m12 * $stock[12]['iron']) +
94
          ($m13 * $stock[13]['iron']) +
95
          ($m14 * $stock[14]['iron']);
96
    $iron /= 100;
97
98
    // Check Iron Share first
99
    if ($iron < 60) {
100
      continue;
101
    }
102
103
    $price =($m0 * $stock[0]['price']) +
104
        ($m1 * $stock[1]['price']) +
105
          ($m2 * $stock[2]['price']) +
106
          ($m3 * $stock[3]['price']) +
107
          ($m4 * $stock[4]['price']) +
108
          ($m5 * $stock[5]['price']) +
109
          ($m6 * $stock[6]['price']) +
110
          ($m7 * $stock[7]['price']) +
111
          ($m8 * $stock[8]['price']) +
112
          ($m9 * $stock[9]['price']) +
113
          ($m10 * $stock[10]['price']) +
114
          ($m11 * $stock[11]['price']) +
115
          ($m12 * $stock[12]['price']) +
116
          ($m13 * $stock[13]['price']) +
117
          ($m14 * $stock[14]['price']);
118
    $price /= 100;
119
120
    // Calculation the max. quantity for this mix.
121
    // Extrapolate each rawmaterial quantity to find the smallest possible quantity
122
    $quantity = 100000000000;
123
    if ($m0) { $temp = $stock[0]['quantity'] * (100 / $m0); if ($temp < $quantity) { $quantity = $temp; } }
124
    if ($m1) { $temp = $stock[1]['quantity'] * (100 / $m1); if ($temp < $quantity) { $quantity = $temp; } }
125
    if ($m2) { $temp = $stock[2]['quantity'] * (100 / $m2); if ($temp < $quantity) { $quantity = $temp; } }
126
    if ($m3) { $temp = $stock[3]['quantity'] * (100 / $m3); if ($temp < $quantity) { $quantity = $temp; } }
127
    if ($m4) { $temp = $stock[4]['quantity'] * (100 / $m4); if ($temp < $quantity) { $quantity = $temp; } }
128
    if ($m5) { $temp = $stock[5]['quantity'] * (100 / $m5); if ($temp < $quantity) { $quantity = $temp; } }
129
    if ($m6) { $temp = $stock[6]['quantity'] * (100 / $m6); if ($temp < $quantity) { $quantity = $temp; } }
130
    if ($m7) { $temp = $stock[7]['quantity'] * (100 / $m7); if ($temp < $quantity) { $quantity = $temp; } }
131
    if ($m8) { $temp = $stock[8]['quantity'] * (100 / $m8); if ($temp < $quantity) { $quantity = $temp; } }
132
    if ($m9) { $temp = $stock[9]['quantity'] * (100 / $m9); if ($temp < $quantity) { $quantity = $temp; } }
133
    if ($m10) { $temp = $stock[10]['quantity'] * (100 / $m10); if ($temp < $quantity) { $quantity = $temp; } }
134
    if ($m11) { $temp = $stock[11]['quantity'] * (100 / $m11); if ($temp < $quantity) { $quantity = $temp; } }
135
    if ($m12) { $temp = $stock[12]['quantity'] * (100 / $m12); if ($temp < $quantity) { $quantity = $temp; } }
136
    if ($m13) { $temp = $stock[13]['quantity'] * (100 / $m13); if ($temp < $quantity) { $quantity = $temp; } }
137
    if ($m14) { $temp = $stock[14]['quantity'] * (100 / $m14); if ($temp < $quantity) { $quantity = $temp; } }
138
139
140
    // Check Quantity
141
    if ($needed_quantity) {
142
      if ($quantity < $needed_quantity) {
143
        continue;
144
      }
145
    }
146
147
    // Count the result
148
    $results++;
149
150
  }
151
  }
152
  }
153
  }
154
  }
155
  }
156
  }
157
  }
158
  }
159
  }
160
  }
161
  }
162
  }
163
  }
164
165
  print('Loops: '   . number_format($counter, 0, '', '.') . '<br>');
166
  print('Results: '   . number_format($results, 0, '', '.') . '<br>');
167
  print('Seconds: ' . number_format((microtime(true) - $beginn), 3, ',', '') . ' sec.');
168
169
?>

: Bearbeitet durch User
von Lars K. (mrlaush)


Lesenswert?

Ich würde evt empfehlen ... wenn es nachher zum parallel prozessing 
kommt.. auf ada umzusteigen.

Hab mal gehört die Sprache ist oder war predestiniert für parallel 
processing.

Sonst interessant zu lesen :)

von Pic T. (pic)


Lesenswert?

Gleicher Code, nur die stock Variblen reinkopiert und STOCK_SZ auf 15 
geändert, wie gesagt, Code ist wirklich Alpha, Resultat ist dieses:
m sowie t, index is null basiert, also stock_1 ist index 0 .
Sollte eigentlich besser sein, aber als proof of concept sollte es 
reichen.

stock 1 price-iron = 75.485714 -- price = 13.210000 -- iron = 17.500000
stock 2 price-iron = 45.766667 -- price = 27.460000 -- iron = 60.000000
stock 3 price-iron = 59.433333 -- price = 35.660000 -- iron = 60.000000
stock 4 price-iron = 130.043732 -- price = 89.210000 -- iron = 68.600000
stock 5 price-iron = 101.581722 -- price = 60.690000 -- iron = 59.745000
stock 6 price-iron = 132.628571 -- price = 23.210000 -- iron = 17.500000
stock 7 price-iron = 62.433333 -- price = 37.460000 -- iron = 60.000000
stock 8 price-iron = 182.640000 -- price = 45.660000 -- iron = 25.000000
stock 9 price-iron = 130.043732 -- price = 89.210000 -- iron = 68.600000
stock 10 price-iron = 118.319525 -- price = 70.690000 -- iron = 
59.745000
stock 11 price-iron = 81.200000 -- price = 14.210000 -- iron = 17.500000
stock 12 price-iron = 47.433333 -- price = 28.460000 -- iron = 60.000000
stock 13 price-iron = 122.200000 -- price = 36.660000 -- iron = 
30.000000
stock 14 price-iron = 131.501458 -- price = 90.210000 -- iron = 
68.600000
stock 15 price-iron = 84.843920 -- price = 50.690000 -- iron = 59.745000
m:   [0] 0.000%  [1] 12.730%  [2] 17.010%  [3] 0.000%  [4] 41.220%  [5] 
0.000%  [6] 12.730%  [7] 0.000%  [8] 0.150%  [9] 0.000%  [10] 0.000% 
[11] 12.630%  [12] 0.000%  [13] 0.000%  [14] 3.650%
t:   [0] 0.000   [1] 25.460   [2] 34.020   [3] 0.000   [4] 82.440   [5] 
0.000   [6] 25.460   [7] 0.000   [8] 0.300   [9] 0.000   [10] 0.000 
[11] 25.260   [12] 0.000   [13] 0.000   [14] 7.299
price: 44.924745 -- iron: 59.970183 % -- sum: 200.239000
Seconds: 0.001786 sec

real  0m0.008s
user  0m0.000s
sys  0m0.000s

Da du bereits brute force gemacht hast, wie "gut" ist dieses Resultat 
denn?
real = extern gemessene reale Zeit inkl. Start des Programm sowie 
Beendigung, gemessen durch unix Time programm. Diesmals mit gnu 
optimierung,
gcc t4.c -std=gnu99  -mtune=pentium-m -mfpmath=sse -Ofast 
-funroll-loops  -march=native -flto
Der Grund für iron<60 ist, dass am Ende noch Berichtigungen
gemacht werden, und eigentlich die Optimierungen nach den Berichtigungen
nochmals durchlaufen werden sollten.
Wenn ich jetzt ein paar Zeilen kopiere, um dies zu berichtigen, dann 
kommt folgendes raus, wobei dies eigentlich nur ein Hack ist , und nicht 
korrekt
gemacht wird.

m:   [0] 0.000%  [1] 12.730%  [2] 17.010%  [3] 0.000%  [4] 41.220%  [5] 
0.000%  [6] 12.730%  [7] 0.000%  [8] 0.194%  [9] 0.000%  [10] 0.000% 
[11] 12.630%  [12] 0.000%  [13] 0.000%  [14] 3.650%
t:   [0] 0.000   [1] 25.460   [2] 34.020   [3] 0.000   [4] 82.440   [5] 
0.000   [6] 25.460   [7] 0.000   [8] 0.388   [9] 0.000   [10] 0.000 
[11] 25.260   [12] 0.000   [13] 0.000   [14] 7.299
price: 44.963997 -- iron: 60.000367 % -- sum: 200.327000
Seconds: 0.001504 sec

Anmerkung: Preis basiert auf Prozent und nicht auf realer kg, ist eine
Vereinfachung im Code, welche jedoch in der realen Applikation ein 
Unterschied sein kann.

: Bearbeitet durch User
von Pandur S. (jetztnicht)


Lesenswert?

Zur Aufgabenstellung. Sie ist extrem unvollstaendig. Muss man nun N 
Einheitsvolumen, resp N Gewichtseinheiten, moeglichst billig fuellen?

Reicht nicht, es muss nochmals ein paar Kriterien geben. Sonst pumpt man 
Fleisch mit Wassser auf, macht Pulver feucht, usw. Dh man wertet Abfall 
zum Qualitaetsprodukt auf.

Also nochmals.

von Roman S. (sroman)


Lesenswert?

@Pic Tech
Zu den Ergebnissen kann ich nur etwas zum Beispiel mit 5 Komponenten vom 
05.04.2016 23:35 sagen. (15 Komponenten ist zu viel für PHP)
Hier war mit 4% das beste Ergebnis:

m1 = 0
m2 = 25460 kg
m3 = 33947 kg
m4 = 8487 kg
m5 = 144273 kg
Total Iron Share = 60.17%
Max.Quantity = 212167kg
Price = 53.84

Josef C. war mit LPSolver noch besser (06.04.2016 09:14)
x0                              0
x1                          25460
x2                          34020
x3                         4046.6
x4                         136473
ergibt:
Total Iron Share = 59.999%
Max.Quantity = 199999kg
Price = 52.78

Weiß jemand wie er auf die Bedingung

-0.425 x0  + 0.086 x3 - 0.00255 x4 >= 0;

gekommen ist? (sorry ... alles etwas Neuland. Danke!)

: Bearbeitet durch User
von Josef C. (josefc)


Lesenswert?

Roman S. schrieb:
> Weiß jemand wie er auf die Bedingung
>
> -0.425 x0  + 0.086 x3 - 0.00255 x4 >= 0;
>
> gekommen ist?

Im Code sind die beiden Kommentare:

Josef C. schrieb:
> /* 0.175*x0 + 0.60*x1 + 0.60*x2 + 0.686*x3 + 0.59745*x4 >= (x0 + x1 + x2
> + x3 + x4)*0.6   */
> /* 0.175 x0 + 0.60 x1 + 0.60 x2 + 0.686 x3 + 0.59745 x4 >= 120000;  */

In der ersten Gleichung wird links der Inhaltsstoff fuer jedes x 
berechnet und summiert. Rechts steht Gesamtmenge * 0.6. Also was 
mindestens drinnen sein muss.
Dann wird nur noch umgeformt, alle Variablen auf die linke Seite.
Die zweite Gleichung hat rechts nur absolute Werte 200000*0.6 = 120000,
was nicht immer korrekt ist.

Das lp-format Format fuer den Solver ist etwas einfach gestrickt.
Es gibt bessere Formate.

Hier noch die Loesung fuer 15 Variablen:
1
/* mix2.lp */
2
3
min: 
4
  13.21 x0 + 27.46 x1 + 35.66 x2 + 89.21 x3 + 60.69 x4
5
+ 23.21 x5 + 37.46 x6 + 45.66 x7 + 89.21 x8 + 70.69 x9
6
+ 14.21 x10 + 28.46 x11 + 36.66 x12 + 90.21 x13 + 50.69 x14;
7
8
x0 + x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9 + x10 + x11 + x12 + x13 + x14 = 200000;
9
10
x0 <= 69148;
11
x1 <= 25460;
12
x2 <= 34020;
13
x3 <= 69873;
14
x4 <= 737299;
15
x5 <= 9148;
16
x6 <= 25460;
17
x7 <= 3050;
18
x8 <= 6903;
19
x9 <= 137299;
20
x10 <= 29148;
21
x11 <= 25260;
22
x12 <= 30020;
23
x13 <= 9873;
24
x14 <= 7299;
25
26
-0.425 x0  + 0.086 x3 - 0.00255 x4 - 0.425 x5 - 0.35 x7 + 0.086 x8 - 0.0025 x9 - 0.425 x10 - 0.3 x12 + 0.086 x13 - 0.00255 x14 >= 0;

$> lp_solve mix2.lp
Value of objective function: 9.03564e+06

Actual values of the variables:
x0                              0
x1                          25460
x2                          34020
x3                           2586
x4                          79915
x5                              0
x6                          25460
x7                              0
x8                              0
x9                              0
x10                             0
x11                         25260
x12                             0
x13                             0
x14                          7299

lp_solve ist kein besonders guter und kein besonders schneller Solver.
Aber damit wird er spielend fertig.
Solche Probleme wurden in den 60ern mit Rechnern in Schrankgroesse 
geloest.
Z.B. ist das MPS Eingabe Format noch fuer Lochkarten entwickelt worden.
Aber heutezutage waren das bessere Taschenrechner.

Gruss

von Pic T. (pic)


Lesenswert?

wenn ich die letzte Aufrundungsstufe wegmache, bekomme ich dieses
Ergebniss, voriges siehe weiter oben:

m:   [0] 0.000%  [1] 12.730%  [2] 17.010%  [3] 0.000%  [4] 70.239%
t:   [0] 0.000   [1] 25.460   [2] 34.020   [3] 0.000   [4] 140.478
price: 52.189473 -- iron: 59.808291 % -- sum: 199.958000

oder aber:
m:   [0] 0.000%  [1] 12.730%  [2] 17.010%  [3] 0.000%  [4] 70.539%
t:   [0] 0.000   [1] 25.460   [2] 34.020   [3] 0.000   [4] 141.078
price: 52.371543 -- iron: 59.987526 % -- sum: 200.558000

Diese -.425 hatte ich auch mal, denke es ist ein Fehler in der Formel, 
wenn
man diese zu vereinfacht, auch wenn das Resultat stimmt.

Denkst du wirklich, dass man bei ueber 100 Tonnen mit Genauigkeit von 
100
gramm rechnen sollte oder besser, ich habe die SW auf 1kg Genauigkeit 
limitiert, sowie wenn ein Wert unter 2kg rauskommt, wird dieser auf 0 
gesetzt.

von Roman S. (sroman)


Lesenswert?

@Josef C.

Danke!!

von Roman S. (sroman)


Lesenswert?

Hallo,

wäre es vielleicht auch möglich mit lpsolver oder einem anderen Programm 
für die lineare Optimierung mehrere Produktionen gleichzeitig "in 
Abhängigkeit zueinander" zu berechnen?

z.B.
- 200t mit Iron Share > 60%
- 50t mit Iron Share > 45%

nach dem Schema:
1
min: 13.21 x0 + 27.46 x1 + 35.66 x2 + 89.21 x3 + 60.69 x4;
2
min: 13.21 y0 + 27.46 y1 + 35.66 y2 + 89.21 y3 + 60.69 y4;
3
4
x0 + x1 + x2 + x3 + x4 >= 200000;
5
y0 + y1 + y2 + y3 + y4 >= 50000;
6
7
x0 <= 69148;
8
x1 <= 25460;
9
x2 <= 34020;
10
x3 <= 69873;
11
x4 <= 737299;
12
13
y0 <= 69148;
14
y1 <= 25460;
15
y2 <= 34020;
16
y3 <= 69873;
17
y4 <= 737299;
18
19
0.175*x0 + 0.60*x1 + 0.60*x2 + 0.686*x3 + 0.59745*x4 >= (x0 + x1 + x2 + x3 + x4)*0.6
20
0.175*y0 + 0.60*y1 + 0.60*y2 + 0.686*y3 + 0.59745*y4 >= (y0 + y1 + y2 + y3 + y4)*0.45

Da alle Produktionen auf den gleichen Bestand zurückgreifen, denke ich 
spielt auch Reihenfolge in der ich einzelne Produktionen kalkulieren 
später eine Rolle.

Dann verbrauche ich vielleicht in der ersten Produktion einen Rohstoff, 
denn ich in der zweiten Produktion dringend benötige, um nicht einen 
viel teureren Rostoff verwenden zu müssen.

(Das Beispiel oben ist vereinfach. Bei viel mehr Rohstoffen, Elementen 
und vielen von Produktion zu Produktion abweichenden Bedingungen wird 
das Problem deutlicher)

Oder geht das nur (wieder) mit Brute Force ... alle möglichen 
Reihenfolgen durchrechnen, bei drei Produktionen (1,2,3 und 2,3,1 und 
3,2,1 und 1,3,2 ... ) Je mehr Produktionen anstehen würden, desto 
schlimmer.

Danke & Viele Grüße

: Bearbeitet durch User
von Josef C. (josefc)


Lesenswert?

Hi,

normalerweise gibt es nur eine Zielfunktion.
Manchmal kann man aber mehrere Ziele in einer Funktion kombinieren.
Bei deinem Problem scheint das zu gehen.

Roman S. schrieb:
Problem A:
> - 200t mit Iron Share > 60%
Problem B:
> - 50t mit Iron Share > 45%
1
min: 13.21 y0a + 27.46 y1a + 35.66 y2a + 89.21 y3a + 60.69 y4a
2
   + 13.21 y0b + 27.46 y1b + 35.66 y2b + 89.21 y3b + 60.69 y4b;
3
4
x0a + x1a + x2a + x3a + x4a >= 200000;
5
y0a + y1a + y2a + y3a + y4a >= 50000;
6
7
x0a + x0b <= 69148;
8
x1a + x1b <= 25460;
9
x2a + x2b <= 34020;
10
x3a + x3b <= 69873;
11
x4a + x4b <= 737299;
12
13
0.175*x0a + 0.60*x1a + 0.60*x2a + 0.686*x3a + 0.59745*x4a >= (x0a + x1a + x2a + x3a + x4a)*0.6
14
0.175*y0b + 0.60*y1b + 0.60*y2b + 0.686*y3b + 0.59745*y4b >= (y0b + y1b + y2b + y3b + y4b)*0.45

Die letzten beiden Bedingungen fuer die Mischung hab ich jetzt nicht
nachgeprueft.
Aber es ist nur noch eine Zielfunktion und die Constraints wurden 
angepasst, wo noetig.

Literatur:
- irgendein Lehrbuch ueber Operations Research
- Model Building in Mathematical Programming von Paul Williams
- Gemischt-ganzzahlige Optimierung von J. Kallrath

Das Thema kann schnell theorielastig werden. Deshalb sollte man sich
die Buecher mal vorher anschauen, bevor man sie kauft.

Roman S. schrieb:
> Oder geht das nur (wieder) mit Brute Force ...
Es gibt viele Optimierungsverfahren und intelligente Suchverfahren...

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.