2016-06-07 4 views
0

Ich versuche, ein einfaches Optimierungsskript zu erstellen. Hier ist mein Code:Fehler beim Zurückgeben von Werten an das Array

# Analysis gives the initial inputs and outputs 
$initialinputs 
$initialoutputs 

# The objective function 
$F = ([math]::pow($initialinputs, 2)) * 2 - 3* $initialinputs 
# Differentiation of the objective function 
$DF = 2 * $initialinputs - 3 
$ScaleFactor = 0.2 

# If the optimum solution has been obtained, two termination measurements: 
# maximum iteration and termination criterion(gradient) 
$Maxloop = 100 
$Termi = 0.001 

# Create arrays 
$InputsArr = @() #The array of inputs 
$FunctionArr = @() #The array of function values 
$DFunctionArr = @() # The array of differentiation values (Gradient) 

# Calculations 
#$InputsArr[0] = $initialinputs #The first input 
#$FunctionArr[0] = $F[$InputsArr[0]] 
#$DFunctionArr[0] = $DF[$inputsArr[0]] 

for ($Innerloop = 1; $Innerloop -le $Maxloop; $Innerloop++) 
{ 
    # Calculate the second input 
    $InputsArr[$innerloop] = $InputsArr[$Innerloop - 1] - $ScaleFactor * (2 * $InputsArr[$Innerloop - 1] - 3) 

    $initialinputs = $InputsArr[$Innerloop] 

    # Calculate the function value 
    $FunctionArr[$innerloop] = ([math]::pow($initialinputs, 2)) * 2 - 3 * $initialinputs 
    Return, $FunctionArr 

    # Calculate the gradient value 
    $DFunctionArr[$innerloop] = 2 * $initialinputs - 3 
    return, $DFunctionArr 

    # If the gradient value less than the termination criterion (gradient), 
    # break the loop 
    if ($DFunctionArr[$innerloop] -le $Termi) 
    { 
     break 
    } 
} 

ich die leere Arrays erstellt und verwenden Sie dann die for Schleife um die Optimierung zu tun und die Ausgänge in der Arrays zu speichern. Aber ich habe einige Fehler wie unten dargestellt:

ERROR: +  $InputsArr[$Innerloop] = $initialinputs 
ERROR: +  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
ERROR:  + CategoryInfo   : OperationStopped: (:) [], IndexOutOfRangeException 
ERROR:  + FullyQualifiedErrorId : System.IndexOutOfRangeException 

ERROR: +  $FunctionArr[$innerloop] = $Functionoutput 
ERROR: +  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
ERROR:  + CategoryInfo   : OperationStopped: (:) [], IndexOutOfRangeException 
ERROR:  + FullyQualifiedErrorId : System.IndexOutOfRangeException

Ich bin nicht ganz sicher, wie die Fehler zu beheben. Wie gebe ich den Wert an die Arrays zurück? Ist += der einzige Weg, dies zu tun? Ich bin jetzt verwirrt über die Arrays.

Antwort

1

Wenn Sie ein Array wie folgt initialisieren: $InputsArr = @(), erstellt Powershell ein Array mit der Länge 0. Somit, wenn Sie dieses Array versuchen und Adresse mit $InputsArr[$innerloop] es einen Fehler wirft das Element $innerloop existiert nicht.

Zwei Lösungen.

$InputsArr = New-Object double[] $MaxLoop

Oder Sie += Operator in Ihrem Code verwenden können neue Werte in einem Array hinzuzufügen: Sie können entweder explizit ein Array von einer bestimmten Art und Länge initialisieren

$InputsArr += $InputsArr[$Innerloop - 1] - $ScaleFactor * (2 * $InputsArr[$Innerloop - 1] - 3) #Calculate the second input

+= erstellt ein neues Array der Länge n + 1, kopiert das alte Array und fügt dann den neuen Wert hinzu, ist also für große Arrays sehr ineffizient. Siehe here.

0

PowerShell-Arrays, die durch @() definiert sind, werden dynamisch skaliert. Sie können nicht auf Objekte in ihnen zugreifen, es sei denn, sie enthalten tatsächlich Elemente. Aus diesem Grund erhalten Sie Ausnahmen vom Typ "Index außerhalb des gültigen Bereichs", wenn Sie $array[$index] in Ihrer for-Schleife verwenden. Das Array hat einfach noch kein Feld $index.

Grundsätzlich gibt es zwei Möglichkeiten der Befüllung Power Arrays:

  • Anfügen an ein bestehendes Array in einer Schleife:

    $array = @() 
    for (...) { 
        $array += $foo 
    } 
    
  • Echo die Elemente innerhalb der Schleife, und weisen die Schleife ausgegeben eine Variable:

    $array = for (...) { 
        $foo 
    } 
    

Ersteres sollte für eine größere Anzahl von Array-Elementen vermieden werden, da jede Append-Operation (+=) ein neues Array mit vergrößerter Größe erstellt, die Elemente kopiert und dann das neue Array der Variablen zuweist. Der letztere Ansatz ist in Bezug auf die Leistung weit überlegen. Der einzige Nachteil des letzteren Ansatzes besteht darin, dass das Ergebnis kein Array sein wird, wenn die Schleife nicht mindestens zwei Elemente erzeugt. Sie können dies mindern, indem Sie die Array-Ausgabe erzwingen: @(for (...) {...}).

Powershell können Sie auch Arrays mit fester Größe erstellen:

$size = 100 
$array = New-Object Object[] $size 

Allerdings gibt es in der Regel keinen Vorteil, dies zu tun.

Beachten Sie auch, dass der erste Befehl in der Schleife geht davon aus, dass das Array bereits einen Anfangswert enthält:

$InputsArr[$innerloop] = $InputsArr[$Innerloop - 1] - $ScaleFactor * (2 * $InputsArr[$Innerloop - 1] - 3) #Calculate the second input 

so müssen Sie das Array mit einem Element prefill bevor die Schleife beginnen:

$InputsArr = @($initialValue) 

Mit diesem gesagt gibt es mehr Möglichkeiten, ein Array mit Werten zu füllen, z dies wie:

$i = $initialValue 
$array = @($i) 
$array += 1..$Maxloop | ForEach-Object { 
    $i -= $ScaleFactor * (2 * $i - 3) 
    $i 
} 

Wenn Sie mehrere Arrays in derselben Schleife füllen wollen Anfügen (weil Sie nicht eine Schleife pro Array aus irgendeinem Grund verwenden) ist wahrscheinlich die beste Wahl. Wie folgt aus:

$InputsArr = @($initialinputs) 
$FunctionArr = @($initialinputs) 
$DFunctionArr = @($initialinputs) 
for ($i = 1; $i -le $Maxloop -and $DFunctionsArr[-1] -le $Termi; $i++) { 
    $InputsArr += $InputsArr[-1] - $ScaleFactor * (2 * $InputsArr[-1] - 3) 
    $FunctionArr += ([Math]::Pow($InputsArr[-1], 2)) * 2 - 3 * $InputsArr[-1] 
    $DFunctionArr += 2 * $InputsArr[-1] - 3 
} 

oder wie diese, wenn Sie nicht brauchen, $InputsArr später:

$FunctionArr = @($initialinputs) 
$DFunctionArr = @($initialinputs) 
$v = $initialinputs 
for ($i = 1; $i -le $Maxloop -and $DFunctionsArr[-1] -le $Termi; $i++) { 
    $v -= $ScaleFactor * (2 * $v - 3) 

    $FunctionArr += [Math]::Pow($v, 2) * 2 - 3 * $v 
    $DFunctionArr += 2 * $v - 3 
} 
+0

Die letzte Methode, die Sie nur die Werte in einem Array speichern gesagt kann. Ich möchte drei Berechnungen durchführen und die Werte getrennt speichern. '$ InputsArr, $ FunctionArr und $ DfunctionArr' diese drei Arrays müssen verschiedene Werte von $ initialinputs = $ InputsArr [$ Innerloop]', $ $ FunctionArr [$ innerloop] = ([math] :: pow ($ initialputs, 2)) * 2 - 3 * $ initialinputs' und '$ DFunctionArr [$ innerloop] = 2 * $ initialinputs - 3'. Ist es möglich, die letzte Methode zu verwenden, um dies zu erreichen? – rock

+0

An vorhandene Arrays in einer Schleife anhängen, wenn Sie natürlich mehrere Arrays in derselben Schleife füllen möchten. –

Verwandte Themen