我尝试创建一个简单的优化脚本。这是我的代码:
# 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
}
}
我创建了空数组,然后使用for
循环进行优化并将输出存储在数组中。但我得到了一些错误,如下所示:
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
我不太清楚如何修复错误。如何将值返回到数组? +=
是唯一的方法吗?我现在对阵列感到困惑。
答案 0 :(得分:1)
初始化这样的数组:$InputsArr = @()
时,powershell会创建一个长度为0的数组。因此,当您尝试使用$InputsArr[$innerloop]
对此数组进行寻址时,会抛出元素$innerloop
的错误不存在。
两种解决方案。您可以显式初始化特定类型和长度的数组:
$InputsArr = New-Object double[] $MaxLoop
或者,您可以在代码中使用+=
运算符向数组添加新值:
$InputsArr += $InputsArr[$Innerloop - 1] - $ScaleFactor * (2 * $InputsArr[$Innerloop - 1] - 3) #Calculate the second input
+=
创建一个长度为n + 1的新数组,复制旧数组,然后添加新值,因此对于大型数组效率非常低。请参阅here。
答案 1 :(得分:0)
@()
定义的PowerShell数组是动态调整大小的。除非实际包含元素,否则您无法对其中的内容进行索引访问。这就是为什么你得到"索引越界"在$array[$index]
循环中使用for
时出现异常。该数组还没有字段$index
。
基本上有两种方法可以填充PowerShell数组:
在循环中附加到现有数组:
$array = @()
for (...) {
$array += $foo
}
回显循环内的元素并将循环输出分配给变量:
$array = for (...) {
$foo
}
对于大量的数组元素应避免使用前者,因为每个追加操作(+=
)将创建一个大小增加的新数组,复制元素,然后将新数组分配给变量。后一种方法在性能方面要优越得多。后一种方法的唯一缺点是,除非循环产生至少两个元素,否则结果不会是一个数组。您可以通过强制执行数组输出来缓解此问题:@(for (...) {...})
。
PowerShell还允许您创建固定大小的数组:
$size = 100
$array = New-Object Object[] $size
然而,这样做通常没有优势。
另请注意,循环中的第一条指令假定数组已包含初始值:
$InputsArr[$innerloop] = $InputsArr[$Innerloop - 1] - $ScaleFactor * (2 * $InputsArr[$Innerloop - 1] - 3) #Calculate the second input
因此你需要在开始循环之前用一个元素预填充数组:
$InputsArr = @($initialValue)
据说,有更多的PoSh方法用数值填充数组,例如:像这样:
$i = $initialValue
$array = @($i)
$array += 1..$Maxloop | ForEach-Object {
$i -= $ScaleFactor * (2 * $i - 3)
$i
}
如果你想在同一个循环中填充多个数组(因为出于某种原因你不能为每个数组使用一个循环),附加可能是你最好的选择。像这样:
$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
}
或者像这样,如果您以后不需要$InputsArr
:
$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
}