zotos
User des Jahres 2007
- Beiträge
- 4.501
- Reaktionspunkte
- 1.201
-> Hier kostenlos registrieren
...
also ich mache es in meinem Programm bereits so, dass ich nur bei den zulässiges Kombinationen was die Einzelwertmenge betrifft weiterrechne.
Anzahl_p_P_min und Anzahl_p_P_max sind die min und max Stückzahl pro Packung. (z.B. 3 oder 2-4 Schnitzel pro 500g Pack)
...
dann übergebe ich die Werte an den FC63 der mir den minimalen den maximalen und die Summe der Einzelwerte zurück liefert.
...
Also ich denke eben das es nicht sinnvoll ist alle 2^20 Kombinationen überhaupt in betracht zu ziehen.
Wenn Du jeden Wert darauf prüfst ob er nur aus z.B. 3 Bit besteht musst Du ja immer noch über eine Million Prüfungen machen.
Ich würde nur die Kombinationen ansteuern die aus z.B. 3 Bit bestehen.
Wenn man dann noch die Durchläufe auf mehrere SPS-Zyklen verteilt ist die Aufgabe schon gar nicht mehr so groß.
Wenn die Werte nun noch sortiert vorhanden wären, wäre das ganze noch leicht zu optimieren. Aber das lasse ich hier mal außen vor da dies jetzt die Übersichtlichkeit nicht fördern würde.
Ich habe das ganze mal für die Aufgabe 3 aus 20 (also 1140 Möglichkeiten) in CoDeSys Programmiert. Die Varianten 2 bzw. 4 aus 20 müssten da noch rein.
Die Umsetzung von diesem ST-Code nach SCL sollte eigentlich nicht so schwer sein.
Bei myDWORD_C.0 müsste eben ein Array über 20 BOOL mit dem AT auf das myDWORD_C gesetzt werden das man z.B. myDWORD_Array[0] schreiben kann. Da könnte man dann die IF-THEN-ELSE Batterie auch schnell noch durch eine FOR-Schleife ersetzen. (* Ich schweife ab ;o( *)
So hier mal mein Code:
Code:
PROGRAM Opti
VAR_INPUT
ENABLE :BOOL;
Target :REAL;
ValueArray :ARRAY[0..19] OF REAL;
END_VAR
VAR
myENABLE :BOOL;
myOptimum :REAL;
myOptimumCom :DWORD;
myDWORD_1 :DWORD;
myDWORD_2 :DWORD;
myDWORD_3 :DWORD;
myDWORD_C :DWORD;
myActual :REAL;
myRealArray :ARRAY[0..19] OF REAL;
myCount :INT;
END_VAR
VAR_OUTPUT
BUSY :BOOL;
Optimum :REAL;
OptimumCom :DWORD;
END_VAR
IF ENABLE AND NOT myENABLE THEN (* Eine positive Flanke am Enable dient als Startsignal *)
(* Initialisierung *)
myRealArray := ValueArray;
myActual := 0.0;
myOptimum := 0.0;
myOptimumCom := 0;
myDWORD_1 := 1; (* Kleinstwertige Variation von drei Bits *)
myDWORD_2 := 2; (* " *)
myDWORD_3 := 4; (* " *)
BUSY := TRUE;
myCount := 0;
ELSIF BUSY THEN
WHILE myCount <= 255 DO (* Schleife wie viele Durchläufe max. pro SPS Zyklus gemacht werden *)
(* Kombiniertes DWORD erstellen *)
myDWORD_C := myDWORD_1 OR myDWORD_2 OR myDWORD_3;
(* Gewichtsberechnung der aktuellen Kombination *)
myActual := 0.0;
IF myDWORD_C.0 THEN myActual := myActual + myRealArray[ 0]; END_IF;
IF myDWORD_C.1 THEN myActual := myActual + myRealArray[ 1]; END_IF;
IF myDWORD_C.2 THEN myActual := myActual + myRealArray[ 2]; END_IF;
IF myDWORD_C.3 THEN myActual := myActual + myRealArray[ 3]; END_IF;
IF myDWORD_C.4 THEN myActual := myActual + myRealArray[ 4]; END_IF;
IF myDWORD_C.5 THEN myActual := myActual + myRealArray[ 5]; END_IF;
IF myDWORD_C.6 THEN myActual := myActual + myRealArray[ 6]; END_IF;
IF myDWORD_C.7 THEN myActual := myActual + myRealArray[ 7]; END_IF;
IF myDWORD_C.8 THEN myActual := myActual + myRealArray[ 8]; END_IF;
IF myDWORD_C.9 THEN myActual := myActual + myRealArray[ 9]; END_IF;
IF myDWORD_C.10 THEN myActual := myActual + myRealArray[10]; END_IF;
IF myDWORD_C.11 THEN myActual := myActual + myRealArray[11]; END_IF;
IF myDWORD_C.12 THEN myActual := myActual + myRealArray[12]; END_IF;
IF myDWORD_C.13 THEN myActual := myActual + myRealArray[13]; END_IF;
IF myDWORD_C.14 THEN myActual := myActual + myRealArray[14]; END_IF;
IF myDWORD_C.15 THEN myActual := myActual + myRealArray[15]; END_IF;
IF myDWORD_C.16 THEN myActual := myActual + myRealArray[16]; END_IF;
IF myDWORD_C.17 THEN myActual := myActual + myRealArray[17]; END_IF;
IF myDWORD_C.18 THEN myActual := myActual + myRealArray[18]; END_IF;
IF myDWORD_C.19 THEN myActual := myActual + myRealArray[19]; END_IF;
(* Kombination bewerten *)
IF ABS(myActual - Target) < ABS(myOptimum - Target) THEN
myOptimum := myActual;
myOptimumCom := myDWORD_C;
END_IF;
IF myDWORD_C.19 AND myDWORD_C.18 AND myDWORD_C.17 THEN (* Fertig *)
Optimum := myOptimum;
OptimumCom := myOptimumCom;
BUSY := FALSE;
ELSE
IF myDWORD_C.19 AND myDWORD_C.18 THEN (* Schiebe alle drei Bits *)
myDWORD_1 := SHL(myDWORD_1,1);
myDWORD_2 := SHL(myDWORD_1,1);
myDWORD_3 := SHL(myDWORD_2,1);
ELSE
IF myDWORD_C.19 THEN (* Schiebe die zwei hochwertigen Bits *)
myDWORD_2 := SHL(myDWORD_2,1);
myDWORD_3 := SHL(myDWORD_2,1);
ELSE
myDWORD_3 := SHL(myDWORD_3,1); (* Schiebe nur das höchstwertige Bit *)
END_IF
END_IF
END_IF
myCount := myCount + 1; (* Zähler zur Zyklus Verteilung inkrementieren *)
END_WHILE;
myCount := 0; (* Zähler zur Zyklus Verteilung nullen *)
END_IF;
myENABLE := ENABLE; (* Wert für Flankenerkennung *)
Ich denke das dort schon die Grundlegenden Ideen ersichtlich sind.