매개 변수 공간 검색 루틴이 너무 빠릅니까?
함수가 (좌표 공간) 도메인의 모든 곳에서 특정 관계를 충족시키는 위치를 찾는 함수의 매개 변수 공간을 샅샅이 뒤지는 작은 스크립트를 작성했습니다. 그러나 매개 변수 공간을 양자화하기 때문에 41 조 격자 점과 같은 격자로 끝납니다. 또한이 격자의 각 지점에서 대략 500 개의 좌표 공간에 대한 조건을 확인하고 있습니다. 따라서 실제로 Mathematica는 20 조개의 개별 포인트를 살펴 봐야합니다.
그래서 시간이 오래 걸릴 것으로 예상 합니다! 하지만 코드를 실행하면 12 초 정도면 끝납니다! 훨씬 간단한 함수와 훨씬 더 작은 매개 변수 공간에서 스크립트를 테스트했으며 예상대로 정확하게 작동합니다. 따라서 Mathematica가 매우 효율적이거나 코딩 천재가 아니라면 스크립트를 이렇게 빠르게 완성하는 방법을 알 수 없습니다.
병렬 처리를 스크립트의 주요 검색 루틴에 통합했지만 각 커널은 기본적으로 4 조 개의 격자 지점을 통과해야합니다. 이제이 격자 점의 수는 내가 엉망이 된 가장 합리적인 함수보다 더 큰쪽에 있지만 여전히 살펴 봐야 할 매개 변수 공간 크기입니다.
설정
아래 코드의 관련 부분을 배치하겠습니다. 스크립트를 통해 제공하는 함수는 다음과 같습니다. 함수 자체는 방대하기 때문에 붙여 넣지는 않겠지 만 함수를 생성하는 코드는 붙여 넣을 것입니다.
\[Phi] = z (Sech[2*(x^2 + y^2 + (z)^2 + 1)] -
Sech[2*(x^2 + y^2 + (z)^2)]);
expr = e*(z - \[Alpha])*(
Tanh[s*(x^2 + y^2 + (z - \[Alpha])^2 + l)] -
Tanh[s*(x^2 + y^2 + (z - \[Alpha])^2 - l)])/(
2*Tanh[s*l]) {-y, x, 0} +
f*(y - \[Beta]) (
Tanh[r*(x^2 + (y - \[Beta])^2 + (z)^2 + m)] -
Tanh[r*(x^2 + (y - \[Beta])^2 + (z)^2 - m)])/(
2*Tanh[r*m]) {0, -z, y} +
g*(x - \[Chi])*(
Tanh[t*((x - \[Chi])^2 + (y)^2 + (z)^2 + n)] -
Tanh[t*((x - \[Chi])^2 + (y)^2 + (z)^2 - n)])/(
2*Tanh[t*n]) {z, 0, -x};
Curlexpr = Curl[expr, {x, y, z}];
func = (-Derivative[0, 0, 0, 1][Subscript[N, 3]][t, x, y, z]^2 - Derivative[0, 0, 1, 0][Subscript[N, 2]][t, x, y, z]^2 -
(Derivative[0, 0, 0, 1][Subscript[N, 2]][t, x, y, z] + Derivative[0, 0, 1, 0][Subscript[N, 3]][t, x, y, z])^2/2 -
Derivative[0, 1, 0, 0][Subscript[N, 1]][t, x, y, z]^2 + (Derivative[0, 0, 0, 1][Subscript[N, 3]][t, x, y, z] +
Derivative[0, 0, 1, 0][Subscript[N, 2]][t, x, y, z] + Derivative[0, 1, 0, 0][Subscript[N, 1]][t, x, y, z])^2 -
(Derivative[0, 0, 1, 0][Subscript[N, 1]][t, x, y, z] + Derivative[0, 1, 0, 0][Subscript[N, 2]][t, x, y, z])^2/2 -
(Derivative[0, 0, 0, 1][Subscript[N, 1]][t, x, y, z] + Derivative[0, 1, 0, 0][Subscript[N, 3]][t, x, y, z])^2/2)/.Table[Subscript[N, i] ->
Evaluate@Function[{t, x, y, z},
Evaluate@(D[\[Phi], {{x, y, z}, 1}] + Curlexpr)[[i]]], {i, 1, 3}]
func
양자화 된 공간에서 내가 평가하는 함수도 마찬가지 입니다.
다음은 스크립트 설정입니다.
function = Func; (*test function: x*Exp[-x^2/\[Sigma]]-s;*)
Quantifier = function >= 0; (*what condition are we trying to satisfy over the entire domain*)
variables = {x, y, z};
Complement[Variables@Level[function, -1], variables];
Parameters = {e, f, g, l, m, n, r, s, t, \[Alpha], \[Beta], \[Chi]};
(*Complement[Variables@Level[function,-1], variables];
(*ORDERED*)*)(*extract the parameters from the test function, not including the co-ordinate variables*)
ParameterSpaceSizes = {{-3, 3}, {-3, 3}, {-3, 3}, {-3, 3}, {-3, 3}, {-3, 3}, {0.1, 4}, {0.1,4}, {0.1, 4}, {-1, 1}, {-1, 1}, {-1,1}}; (*ORDERED*)
CoordinateSpaceBounds = {{-2, 2}, {-2, 2}, {-2, 2}};(*ORDERED*)
ParameterSpaceResolution = 0.3; (* How accurate should the parameter search be*)
CoordinateSpaceResolution = 0.5;
수량자는 함수가 전체 도메인에서 만족하기를 원하는 관계입니다. parameterspacesizes는 좌표에 대해 동일한 매개 변수의 범위입니다. 해상도는 매개 변수 / 좌표 공간에 대한 격자 간격입니다.
기능
다음은 몇 가지 관련 기능입니다. Meshify는 입력 간격이 목록으로 주어지면 격자 격자를 생성합니다. 예를 들어 {{a, b}, {c, d}}는 간격 [a, b] 및 [c, d]를 나타내고 격자 간격도 나타냅니다. 목록으로.
Meshify[ParameterSpaceIntervals_, ParameterSpaceResolutions_]:=
(*Discretize the parameter space, specified by bounds of the individual parameters, with a given resolution*)
Module[{
ListofDiscretizedIntervals = Array[(Array[(N@#&), Round@((ParameterSpaceIntervals[[All,2]][[#1]]-ParameterSpaceIntervals[[All,1]][[#1]])/ParameterSpaceResolutions[[#1]]+1), {ParameterSpaceIntervals[[All,1]][[#1]], ParameterSpaceIntervals[[All,2]][[#1]]}]&), Length@ParameterSpaceResolutions] (*discretize the intervals and store the output in the temporary variable [ListofDiscretizedIntervals]*)
},
Return[Tuples@ListofDiscretizedIntervals, Module];
(*Take the cartesian product of the discretized intervals to get a discretized parameter space and return the output as the return value of the Module function*)
]
nPartition은 최대 균등 한 방식으로 집합을 n 개의 파티션으로 분할합니다. 즉, 모든 파티션의 크기가 거의 같습니다.
nPartitions[set_,
n_] := (*Partition the input set in n maximally-even partitions*)
Module[{
residual = Mod[Length@set, n], LenSet = Length@set
},
If[residual != 0,
ReducedSet =
set[[1 ;;
LenSet -
residual]]; (*If the number of partitions doesnt divide the \
norm of the set,
then we partition a reduced set into n partitions and append the \
remaining elements to the nth partition in an even way,
thus creating a maximally even partition. Note,
the set wont be maximally evenly partitioned if the number of \
partitions is larger than half the norm of the set.*)
ReducedPartition = Partition[ReducedSet, Length@ReducedSet/n]; (*
define the reduced partition*)
Do[AppendTo[ReducedPartition[[-residual + ii]],
ReducedPartition[[-residual + ii + 1]][[1]]], {ii, 0,
residual - 2}];(*
Move over the first elements of one partition to the end of there \
left neighbor*)
Do[ReducedPartition =
Delete[ReducedPartition, {-residual + ii, 1}], {ii, 1,
residual -
1}];(*remove the shifted over elements from their previous \
position*)
Do[AppendTo[ReducedPartition[[-1]],
set[[ii]]], {ii, -residual, -1}]; (*append the residual elements \
to the last partition*)
Return[ReducedPartition,
Module](*return the maximally even partitioned set*)
,
Return[Partition[set, Length@set/n],
Module] (*if the number of partitions divides the norm of the \
set, then we can partition evenly*)
]
]
PartitionIntervals는 일련의 간격을 취하고 각 간격을 n 조각으로 분할 한 다음 i 번째 조각을 단일 파티션으로 결합합니다.
PartitionIntervals[Intervals_,
nPartitions_] :=(* Partitions a set of intervals of the form \
{{a,b}, {c,d},{e,f},...} into nPartitions partitions*)
Array[
(Table[{Intervals[[ii]][[
1]] + (# - 1)*(Intervals[[ii]][[2]] - Intervals[[ii]][[1]])/
nPartitions,
Intervals[[ii]][[
1]] + #*(Intervals[[ii]][[2]] - Intervals[[ii]][[1]])/
nPartitions}, {ii, 1, Length@Intervals}] &), nPartitions
]
scanObjectUntilCondition 함수는 실제로이 검색 루틴의 실제 고기와 감자입니다. 수량자를 관계 집합으로 취합니다 ( 'for all x, f (x)> 3'는 '각 격자 점에서 f (격자 점)> 3'과 같이 격자로 변환되므로 각 위치는 집합은 각 격자 점에 해당함), 함수의 매개 변수, 매개 변수 값의 간격 및 격자 간격. 그런 다음 단일 매개 변수가 취할 수있는 값의 수를 반복합니다 (격자 간격이 일정하기 때문에 1 / 격자 간격, 즉 격자의 가장자리에있는 격자 점의 수). 에지의 격자 점 수 (단일 매개 변수가 취할 수있는 가능한 값의 수)를 반복합니다.이 내부 루프의 각 패스에 대해 매개 변수 값이 수량 자 세트에 연결됩니다. 한정자 집합의 관계 중 하나가 거짓으로 평가되면 (즉, 한정자가 충족되지 않음) 내부 루프의 다음 패스에서 다음 매개 변수를 1 격자 간격만큼 증가시킵니다. (즉, 내부 루프는 (1,1,1)-> (2,1,1)-> (2,2,1)-> (2,2,2)로 진행된 다음 외부 루프의 다음 반복) 전체 매개 변수 공간을 스캔 할 때까지 (3,2,2)-> (3,3,2)-> (3,3,3) 등으로 이동합니다.)
기본적으로 함수가 수량화 매개 변수 공간을 스캔하여 수량자가 만족되는 지점을 찾는다는 말은 많은 단어입니다.
scanObjectUntilCondition[Quantifier_, params_, intervals_,
ress_] := (*Scan the parameters params through the intervals \
intervals with resolution ress until quantifier is satisfied at every \
element*)Module[{paramVals = intervals[[All, 1]],
EndPoints = intervals[[All, 2]],
StartPoints = intervals[[All, 1]], con = Quantifier},
Result = Catch[
For[\[Lambda]\[Lambda]\[Lambda] =
1, \[Lambda]\[Lambda]\[Lambda] <=
Round@(1/
ress), \[Lambda]\[Lambda]\[Lambda]++,(*Loop over the bins,
given by 1/ress*)
Array[(*loop over the parameters*)
(
If[
AllTrue[(*If the Quantifier is satisfied at each of its \
elements, then immediately return the point where this is achieved*)
con /. Thread[params -> paramVals], TrueQ],
Throw[{"Condition met at point: ",
Thread[params -> paramVals]}, o],
paramVals =
ReplacePart[
paramVals, # ->
paramVals[[#]] + (EndPoints[[#]] - StartPoints[[#]])*
ress](*If the quantifier contains a point where it \
evaluates to False,
then increment the parameter values by one bin width and \
continue searching*)
]
) &, Length@intervals]
], o (*Catch Throw Tag*)
];
If[TrueQ[Result[[0]] == List], Return[Result, Module],
Return[$Failed, Module]]
]
병렬화
이제 병렬화 루틴의 매개 변수를 설정했습니다. QuantifierOverCoordSpace는 양자화 된 좌표 공간에서 함수를 평가하는 변수이므로 매개 변수는 유일한 자유 변수입니다. 이 세트는 단일 변수에 캡처 된 "For all x, f (x)> 0"의 양자화 된 버전입니다.
(*construct the discretized co-ordinate space and extract the number \
of CPU cores to run on *)
NumParams =
Length@Parameters; (*number of parameters*)
NumParamSpacePartitions \
= $ProcessorCount; (*how many partitions should we make*)
DiscretizedCoordinateSpace =
Meshify[CoordinateSpaceBounds,
ConstantArray[CoordinateSpaceResolution,
Length@CoordinateSpaceBounds]];
PartitionParameterIntervals =
PartitionIntervals[ParameterSpaceSizes, NumParamSpacePartitions];
(*Setup parallelization*)
Off[LaunchKernels::nodef]
LaunchKernels[]; (*make sure multiple kernels are running *)
On[
LaunchKernels::nodef]
QuantifierOverCoordSpace =
ParallelMap[Quantifier /. Thread[variables -> #] &,
DiscretizedCoordinateSpace];
DistributeDefinitions[Off[General::munfl], Off[GreaterEqual::nord],
Parameters, PartitionParameterIntervals, ParameterSpaceResolution,
QuantifierOverCoordSpace, scanObjectUntilCondition];
여기에 병렬 검색 루틴을 실행하는 스크립트 부분이 있습니다.
Print["Executing over ", Length@Kernels[], " Kernels"]
ClearAll[result];
ParallelTry[
(result =
scanObjectUntilCondition[QuantifierOverCoordSpace, Parameters,
PartitionParameterIntervals[[#]], ParameterSpaceResolution];
If[TrueQ[Result[[0]] == List], result, $Failed]
) &, Range[NumParamSpacePartitions]] // Timing
문제
이제 위의 코드를 모두 실행 Timing
하면 코드가 7 초 안에 완료된다고합니다! 그러나 나를 매우 당황하게하는 것은 1 개 또는 2 개의 매개 변수와 1 개의 좌표를 사용하여 훨씬 더 간단한 함수를 시도하면 예상대로 실행되고 수량 자 관계를 충족하는 첫 번째 매개 변수 집합을 다시 얻게된다는 것입니다.
예를 들어, 변경하는 경우 function
처럼 뭔가에 변수를 function =x*Exp[-x^2/\[Sigma]] - s
,
에 대한 variables
변수 variables={x}
,
에 대한 Parameters
변수 Parameters={s,\[sigma]}
,
에 대한 ParameterSpaceSizes
변수 ParameterSpaceSizes={{-10,10}, {0.1, 5}}
,
에 대한 CoordinateSpaceBounds
변수 CoordinateSpaceBounds={-5,5}
,
코드는 완벽하게 실행 function\[greaterequal] 0
되고 범위에 대한 관계를 충족하는 매개 변수를 제공 합니다 {x,-5,5}
.
따라서 저에게 알리지 않고 거대한 매개 변수 공간에서 실행할 때 서브 커널이 평가를 중단 하지 않는 한 , Mathematica는 빠른 속도로 빠른 속도 로 실행되거나 내 코드가 매우 효율적 (가능성 이 낮음 )되지 않는 한 Mathematica가 ~ 7에서 12 천조 포인트 이상의 스캔을 완료하는 방법을 알 수 없습니다. 6 코어 CPU보다 초.
스크립트가 훨씬 작은 매개 변수 공간과 기능에 대해 완벽하게 작동하기 때문에 내 코드의 버그라고 생각하지 않지만 완전히 가능합니다. 아마도 Mathematica는 비교해야 할 숫자가 거대하다는 것을 알았을 때 평가를 중단할까요?
다음은 이러한 숫자의 크기를 이해하기 위해 수행 한 봉투 계산의 작은 뒷면입니다.
내 6 코어 CPU는 일반적으로 스크립트 작업시 약 3.7 기가 헤르츠에 도달합니다. 스크립트는 내가 사용한 가장 큰 매개 변수 공간에서 작업 할 때 완료하는 데 60 초 정도 걸립니다. 각 코어가주기마다 1 개의 격자 점을 확인하면 3 기가 헤르츠에서 60 초 후에 CPU는 약 1-2 조 개의 격자 점을 확인합니다. 이것은 전체 공간의 격자 점 수보다 4 만 배 더 적습니다! 이 클럭 속도로 전체 공간을 확인하려면 1 개월 동안 실행해야합니다! 하지만 1 분만에 끝납니다. 무슨 일이야?
업데이트 (여전히 문제)
그래서 이것은 정말 흥미 롭습니다. 다음과 같은 간단한 기능을 사용하면
$$ F (x) = x * e ^ {-\ frac {x ^ 2} {\ sigma + \ tau + \ zeta + \ Upsilon}} + s $$
그리고 가우시안 가중치를 중요하지 않은 간격에서 변경하고 s를 $ [-10, 2] $ 에서 변경하도록하겠습니다 . 그러면 수량 자 관계 $ \ forall x $ , $ F (x) \ geq 0 $ 가 충족 될 것으로 예상됩니다. 예를 들어 , 매개 변수 포인트 $ s = 1.7 $ . 이제 검색 루틴 이 변덕 스럽습니다 . 때로는 결과를 뱉어 내지 만, 어떤 때는 일어나서는 안되는 결과를 내기도합니다 $Failed
. 코드를 실행할 때마다 결과가 뒤집 힙니다. 또한 개별적으로 검색해야 할 격자 포인트가 2 천억 개에 달하지만 포인트를 찾았는지 여부에 관계없이 루틴은 약 0.06 초 내에 완료됩니다.
업데이트 2 (약간 문제 감소)
따라서 아래의 내 의견에 따르면 기질 문제 는 중요한 섹션의 문제였습니다. 내 함수 가 아무것도 찾지 못하면 이미 반환하기 때문에 인수 의 If
문 ParallelTry
은 실제로 중복 됩니다. 멍청한 실수입니다. 아마도 내 코드가 무엇을하는지 알아야합니다! 그럼에도 불구하고 문제가 해결되었습니다. 이제 매번 위의 간단한 함수의 예상 결과를 반환합니다. 그러나 그것은 여전히 내가 기대하는 것보다 훨씬 더 빨리 작동합니다. 단일 서브 커널은 여전히 약 0.1 초 동안 약 500 조 포인트를 스캔합니다. 내 CPU는 3.7GHZ로 실행되므로 단일 코어는 실제로 그 시간에 3 억 7 천만 포인트 만 검색 할 수 있어야합니다. 여전히 이유를 알 수 없지만 훨씬 더 크고 중요한 기능에 대한 향후 결과를 신뢰할 수 있도록 알아야합니다.scanObjectUntilCondition
$Failed
위의 샘플 함수를 실행하는 업데이트 된 코드는 다음과 같습니다. 다른 사람이 문제를 찾는 데 도움이 될 수 있도록이 게시물에 원본 코드를 남겨 둘 것입니다.
function =x*Exp[-x^2/(\[Sigma] + \[Tau] + \[Upsilon] + \[Zeta])] + s;
Quantifier = function >= 0; (*what condition are we trying to satisfy over the entire domain*)
variables = {x};
Complement[Variables@Level[function, -1], variables];
Parameters = {s, \[Sigma], \[Tau], \[Upsilon], \[Zeta]};
(*Complement[Variables@Level[function,-1], variables]; \
(*ORDERED*)*)(*extract the parameters from the test function, not \
including the co-ordinate variables*)
ParameterSpaceSizes = {{-10,2}, {0.1, 5}, {0.1, 5}, {0.1, 5}, {0.1,5}};(*ORDERED*)(* s can range from -5 to 5 and \[Sigma] and run \
from 0.001 to 5*)
CoordinateSpaceBounds = {{-2, 2}}; {{-2, 2}, {-2,2}, {-2, 2}};(*ORDERED*)
ParameterSpaceResolution = 0.01; (* How accurate should the parameter search be*)
CoordinateSpaceResolution = 0.1;
(*Some functions to use in setting up and discretizing the parameter space and coordinate space*)
Meshify[ParameterSpaceIntervals_, ParameterSpaceResolutions_] := (*Discretize the parameter space, specified by bounds of the individual parameters, with a given resolution*)
Module[{ListofDiscretizedIntervals =
Array[(Array[(N@# &),
Round@((ParameterSpaceIntervals[[All, 2]][[#1]] -
ParameterSpaceIntervals[[All, 1]][[#1]])
ParameterSpaceResolutions[[#1]] +
1), {ParameterSpaceIntervals[[All, 1]][[#1]],
ParameterSpaceIntervals[[All, 2]][[#1]]}] &),
Length@ParameterSpaceResolutions] (*discretize the intervals and store the output in the temporary variable [
ListofDiscretizedIntervals]*)
},
Return[Tuples@ListofDiscretizedIntervals, Module]; (*Take the cartesian product of the discretized intervals to get a discretized parameter space and return the output as the return value of the Module function*)
]
nPartitions[set_, n_] := (*Partition the input set in n maximally-even partitions*)
Module[{residual = Mod[Length@set, n], LenSet = Length@set},
If[residual != 0,ReducedSet = set[[1 ;; LenSet - residual]]; (*If the number of partitions doesnt divide the norm of the set,
then we partition a reduced set into n partitions and append the
remaining elements to the last few partitions in an even way, thus creating a maximally even partition. Note, the set wont be maximally evenly partitioned if the number of partitions is larger than half the norm of the set.*)
ReducedPartition = Partition[ReducedSet, Length@ReducedSet/n]; (*
define the reduced partition*)
Do[AppendTo[ReducedPartition[[-residual + ii]],
ReducedPartition[[-residual + ii + 1]][[1]]], {ii, 0, residual - 2}];(* Move over the first elements of one partition to the end of there left neighbor*)
Do[ReducedPartition = Delete[ReducedPartition, {-residual + ii, 1}], {ii, 1, residual - 1}];(*remove the shifted over elements from their previous position*)
Do[AppendTo[ReducedPartition[[-1]], set[[ii]]], {ii, -residual, -1}]; (*append the residual elements to the last partition*)
Return[ReducedPartition, Module](*return the maximally even partitioned set*),
Return[Partition[set, Length@set/n], Module] (*if the number of partitions divides the norm of the set, then we can partition evenly*)
]
]
PartitionIntervals[Intervals_, nPartitions_] :=(* Partitions a set of intervals of the form {{a,b}, {c,d},{e,f},...} into nPartitions partitions*)
Array[
(Table[{Intervals[[ii]][[ 1]] + (# - 1)*(Intervals[[ii]][[2]] - Intervals[[ii]][[1]]) nPartitions, Intervals[[ii]][[1]] + #*(Intervals[[ii]][[2]] - Intervals[[ii]][[1]])/nPartitions}, {ii, 1, Length@Intervals}] &), nPartitions
]
scanObjectUntilCondition[Quantifier_, params_, intervals_, ress_] := (*Scan the parameters params through the intervals intervals with resolution ress until quantifier is satisfied at every element*)
Module[{paramVals = intervals[[All, 1]], EndPoints = intervals[[All, 2]],
StartPoints = intervals[[All, 1]], con = Quantifier},
Result = Check[
Catch[
For[\[Lambda]\[Lambda]\[Lambda] =
1, \[Lambda]\[Lambda]\[Lambda] <=
Round@(1/ress), \[Lambda]\[Lambda]\[Lambda]++,(*Loop over the bins,
given by 1/ress*)
Array[(*loop over the parameters*)
(
If[
AllTrue[(*If the Quantifier is satisfied at each of its elements, then immediately return the point where this is achieved*)
con /. Thread[params -> paramVals], TrueQ],
Throw[{"Condition met at point: ",
Thread[params -> paramVals]}, o],
paramVals = ReplacePart[paramVals, # -> paramVals[[#]] + (EndPoints[[#]] - StartPoints[[#]])*ress](*If the quantifier contains a point where it evaluates to False, then increment the parameter values by one bin width and continue searching*)
]
) &, Length@intervals]
], o (*Catch Throw Tag*)
],
err
];
If[TrueQ[Result[[0]] == List], Return[Result, Module],
Return[$Failed, Module]]
]
(*construct the discretized co-ordinate space and extract the number of CPU cores to run on *)
NumParams = Length@Parameters; (*number of parameters*)
NumParamSpacePartitions = $ProcessorCount; (*how many partitions should we make*)
DiscretizedCoordinateSpace =
Meshify[CoordinateSpaceBounds,
ConstantArray[CoordinateSpaceResolution,
Length@CoordinateSpaceBounds]];
PartitionParameterIntervals =
PartitionIntervals[ParameterSpaceSizes, NumParamSpacePartitions];
(*Setup parallelization*)
Off[LaunchKernels::nodef]
LaunchKernels[]; (*make sure multiple kernels are running *)
On[
LaunchKernels::nodef]
QuantifierOverCoordSpace =
ParallelMap[Quantifier /. Thread[variables -> #] &,
DiscretizedCoordinateSpace];
DistributeDefinitions[Parameters, PartitionParameterIntervals,
ParameterSpaceResolution, QuantifierOverCoordSpace,
scanObjectUntilCondition];
Print["Executing over ", NumParamSpacePartitions, " Kernels"]
(*Run the parallelized search routine*)
ParallelizedResult =
ParallelTry[
(scanObjectUntilCondition[QuantifierOverCoordSpace, Parameters,
PartitionParameterIntervals[[#]], ParameterSpaceResolution]) &,
Range[NumParamSpacePartitions]
] // AbsoluteTiming
Print["Times in seconds for the parameter space to be searched with \
given resolution and bounds: \n\t\t",
ParallelizedResult[[1]], "\nResult of search: \n\t\t",
ParallelizedResult[[2]]]
```
답변
아, 알아 냈어. 그 이유는 함수가 scanObjectUntilCondition
실제로 매개 변수를 격자 간격으로 증가 시키지 않기 때문 입니다. 대신, "격자 간격 ', 즉 해상도가 유효 크기 및 씩 파라미터 각 매개 변수에 대해 간격의 길이를 나누고 이 값. 따라서이 값은 매개 변수의 각 개별 간격에 대한 실제 빈 너비입니다. 즉, 상호 작용은 다음과 같습니다.
a
간격에 정의 된 경우$[-1,1]$해상도 크기를 0.1로 지정하면 다음 a
과 같이 증가합니다.$$a = -1 $$$$\downarrow$$$$ -1 + (1-(-1))*0.1 =-.8 $$$$\downarrow$$$$ -0.8 + (1 - (-1))*0.1 = -0.6 $$$$\downarrow$$$$etc.$$
이것은 검색 루틴이 실제로 수조 개의 격자 점을 검색하는 것이 아니라 훨씬 작은 하위 집합을 검색한다는 것을 의미합니다. 재미있게도 코드를 작성할 때 함수가 이런 식으로 증가한다는 것을 알고 있었지만 스캔하는 격자 점 수를 계산할 때 잊어 버렸습니다.
CriticalSection
마지막 업데이트 의 문제 와 결합하여 문제가 해결되었습니다.
scanObjectUntilCondition
누군가가 그것을 사용할 수 있다면 업데이트 된 기능이 있습니다. :)
scanObjectUntilCondition[Quantifier_, params_, intervals_,
ress_] := (*Scan the parameters params through the intervals \
intervals with resolution ress until quantifier is satisfied at every \
element*)Module[{paramVals = intervals[[All, 1]],
EndPoints = intervals[[All, 2]],
StartPoints = intervals[[All, 1]], con = Quantifier,
nPointsSearched = 0},
Result = Check[
Catch[
For[\[Lambda]\[Lambda]\[Lambda] =
1, \[Lambda]\[Lambda]\[Lambda] <=
Round@(Max[EndPoints - StartPoints]/
ress), \[Lambda]\[Lambda]\[Lambda]++,(*Loop over the bins,
given by 1/ress*)
Array[(*loop over the parameters*)
(If[
AllTrue[con /. Thread[params -> paramVals],
TrueQ],(*If the Quantifier is satisfied at each of its \
elements, then immediately return the point where this is achieved*)
Throw["Condition met at point: \n\t\t" <>
ToString@Thread[params -> paramVals] <>
"\n Number of Points Searched:\n\t\t" <>
ToString@ nPointsSearched, o],
If[\[Not] (paramVals[[#]] + ress > EndPoints[[#]]),
paramVals =
ReplacePart[paramVals, # -> paramVals[[#]] + ress];
nPointsSearched += 1
](*If the quantifier contains a point where it evaluates \
to False,
then increment the parameter values by one bin width and \
continue searching*)
]
) &, Length@intervals]
], o (*Catch Throw Tag*)
],
err
];
If[TrueQ[Result[[0]] == String], Return[Result, Module],
Return[$Failed, Module]]
]
이제 각 매개 변수가 해상도 크기만큼 증가하므로 격자는 더 이상 정사각형이 아니지만 실제 격자 간격은 이제 사용자 정의 해상도 변수에 의해 제공됩니다. 작은 해상도로 큰 매개 변수 공간을 스캔 할 때 염두에 두어야 할 사항입니다.
기본적으로이 문제를 직접 해결했지만 다른 사람이 도움이 될 경우를 대비하여이 게시물을 남겨 두겠습니다.