STK組件:探索函數(shù)(Exploring Functions)

翻譯:原文地址:http://help.agi.com/AGIComponents/html/ExploringFunctions.htm

在許多情況下,確定給定函數(shù)何時跨過閾值非常有用。當感興趣的閾值為0.0時,這被稱為求函數(shù)的根,任何閾值交叉問題都可以通過從方程的兩邊減去閾值來重新定義為求根問題。如果函數(shù)的數(shù)學(xué)公式可用,通??梢灾苯忧蠼飧?。然而,如果不是這樣的話,就必須用數(shù)字求根;換句話說,我們在獨立變量的離散值處對函數(shù)進行采樣,并檢查采樣值的趨勢,以便將根的位置縮小到所需的精度水平。

函數(shù)探索器

DoubleFunctionExplorerDurationFunctionExplorerJulianDateFunctionExplorer類分別用于對double、DurationJulianDate函數(shù)進行數(shù)值探索。除了找到閾值交叉點之外,這些函數(shù)探索器還報告了局部極小值和極大值,它們是函數(shù)具有零導(dǎo)數(shù)的位置,或者非正式地說,是函數(shù)改變方向的位置。JulianDateFunctionExplorer在STK組件內(nèi)部用于計算過境。

ExploringFunctionsFunctionExplorer.png

函數(shù)探索器的一些主要功能包括:

  • 同時探索多個函數(shù)。
  • 確定函數(shù)的局部極值。
  • 確定閾值的交叉點。每個函數(shù)可以指定多個閾值。
  • 函數(shù)的數(shù)學(xué)公式不是必需的。
  • 函數(shù)的導(dǎo)數(shù)不需要可用。
  • 完全控制函數(shù)的采樣方式。
  • 通過探索極值,即使沒有樣本落在閾值的另一側(cè),也可以找到閾值交叉點。
  • 即使對于具有平點和不連續(xù)性的函數(shù),只要該函數(shù)可以在探索區(qū)間內(nèi)進行求值,也可以預(yù)測其行為。
    以下是使用DoubleFunctionExplorer查找函數(shù)跨越特定閾值的值的基本示例:
var explorer = new DoubleFunctionExplorer
{
    FindAllCrossingsPrecisely = true
};
explorer.Functions.Add(x => 2 * x + 5, 10.0);
explorer.SampleSuggestionCallback = (start, stop, lastSample) => lastSample + 1.0;

var thresholdCrossings = new List<double>();
explorer.ThresholdCrossingFound += (sender, e) => thresholdCrossings.Add(e.Finding.CrossingVariable);

explorer.Explore(0.0, 10.0);

// thresholdCrossings列表包含函數(shù)跨越閾值時的X值。

首先,我們創(chuàng)建一個函數(shù)探索器,并通過設(shè)置FindAllCrossingsPrecision屬性指示它應(yīng)該精確地查找所有閾值交叉點。這將在下一節(jié)中進行更詳細的討論。接下來,我們添加我們感興趣的函數(shù),f(x)=2*x+5,并指出我們感興趣的閾值為10.0。在這里,函數(shù)是用lambda表達式表示的,但是可以使用任何接受double并返回double的函數(shù)。該函數(shù)作為委托提供。

函數(shù)探索器通過對函數(shù)值進行離散采樣來探索函數(shù)。因此,我們提供了一個SampleSuggestionCallback,用于確定函數(shù)采樣的變量值。回調(diào)給出了正在探索的間隔的開始和結(jié)束以及上一個變量值,并期望返回下一個要采樣的變量值。同樣,我們使用lambda表達式指定回調(diào)函數(shù),但是可以使用任何兼容的函數(shù)。我們將在后面的章節(jié)中更深入地討論采樣。

接下來,我們訂閱每次發(fā)現(xiàn)閾值交叉時由函數(shù)探索器引發(fā)的事件。事件處理程序(我們表示為匿名委托)只是將閾值交叉的變量值添加到列表中。

最后,我們調(diào)用Explore方法來探索給定間隔內(nèi)的函數(shù)。每當函數(shù)探索器發(fā)現(xiàn)一些有趣的東西時,它都會引發(fā)適當?shù)氖录?,并調(diào)用附加的事件處理程序(如果有的話)。在本例中,在Explore方法返回后,thresholdCrossings集合包含單個變量值2.5。

發(fā)現(xiàn)和事件

所有三個函數(shù)探索器都會根據(jù)以下發(fā)現(xiàn)引發(fā)事件:

  • FunctionSampled:每次對函數(shù)進行采樣時引發(fā)。
  • ThresholdCrossingIndicated:兩個連續(xù)的樣本位于閾值的兩側(cè),表示函數(shù)在兩個點之間的間隔內(nèi)穿過閾值。引發(fā)此事件時,尚未確定交叉口的準確位置。
  • ThresholdCrossingFound:已經(jīng)找到了閾值交叉口的精確位置。只有在ThresholdCrossingIndicated事件期間調(diào)用FindReciseCrossing方法,或者FindAllCrossingsPrecilitytrue時,才會精確地找到閾值交叉點。
  • LocalExtremumIndicated:三個連續(xù)的樣本形成兩個斜率相反的線段,表明函數(shù)在三個點的第一個點和最后一個點之間具有局部極值(最小值或最大值)。當這個事件發(fā)生時,還沒有確定局部極值的精確位置。
  • LocalExtremumFound:已找到極值(最小值或最大值)的精確位置。 只有在LocalExtremumIndicated事件期間調(diào)用FindPreciseExtremum方法或者FindAllExtremaPreciselytrue時,才能找到極值。 如果ExploreExtremaToFindCrossingstrue,并且極值(如果找到)可能位于閾值的另一側(cè),則會發(fā)現(xiàn)極值,從而導(dǎo)致發(fā)現(xiàn)其他閾值交叉點。

采樣

使用函數(shù)探索器時,必須提供一個回調(diào)來控制函數(shù)的采樣方式。良好的采樣對于獲得準確的結(jié)果至關(guān)重要。如果函數(shù)采樣頻率不夠高,可能會錯過閾值交叉點和局部極值。如果采樣太頻繁,性能就會受到影響。理想采樣在很大程度上取決于被采樣函數(shù)的性質(zhì)。

我們建議您使用DoubleFunctionSampling、JulianDateFunctionSamplingDurationFunctionSampling,而不是使用上面示例中所示的固定采樣步長。函數(shù)探索器可配置為使用這些采樣類,如下所示。

Function<double, double> function = GetAnyOldFunction();

DoubleFunctionSampling sampling = new DoubleFunctionSampling
{
    MinimumStep = 1.0,
    MaximumStep = 100.0,
    DefaultStep = 10.0,
    TrendingStep = 1.0
};

DoubleFunctionExplorer explorer = new DoubleFunctionExplorer();
explorer.SampleSuggestionCallback = sampling.GetFunctionSampler(function).GetNextSample;
explorer.Functions.Add(function.Evaluate, 1.234);

采樣類型確定傳遞給GetFunctionSamplerFunction <TIndependent,TDependent>實例上的GetNextSampleSuggestion方法的下一個樣本。 因此,函數(shù)本身控制著它的采樣方式。 此外,采樣類型具有MinimumStepMaximumStep屬性,這些屬性對函數(shù)可以建議的步長施加限制。 如果函數(shù)未提供有效建議,或者未向GetFunctionSampler提供任何函數(shù),則使用DefaultStep。

采樣類型還允許您指定TrendingStep的大小。趨勢步長發(fā)生在探索間隔的開始和結(jié)束時,其目的是確定函數(shù)在端點處的趨勢方向。

ExploringFunctionsTrendingStep.png

考慮探索上圖中顯示的函數(shù)。探測從最左邊的黃點開始,右邊的兩個黃點是接下來的兩個樣本。連接三個點的兩條線的斜率以紅色顯示。因為兩個線段都顯示出減小的斜率,所以函數(shù)探索器不知道該函數(shù)在這三個樣本之間的間隔內(nèi)具有局部最大值。更糟糕的是,局部最大值超過閾值,因此如果我們不認識到存在這個局部最大值,我們將錯過兩個閾值交叉。

這是一個問題,因為最左邊的黃點是第一個探索過的樣本。如果我們之前已經(jīng)開始探索(例如圖中的綠點),則由前三個點形成的斜率將相反,函數(shù)探索器將識別該斜率表示局部最大值。找到局部最大值也會導(dǎo)致找到兩個交叉點。但是,在我們從第一個黃點開始的情況下,我們可以做些什么來找到交叉點?

您可能已經(jīng)猜到,答案是使用趨勢步長。在間隔開始處的一小步,顯示為藍點,確定該函數(shù)在間隔開始時呈趨勢正向。然后,第二個黃點給出了兩個具有相反斜率的區(qū)段,表示局部最大值,我們找到了交叉點。

趨勢步長越小,函數(shù)可以在閾值的“另一”側(cè)花費的時間越短,而不會錯過兩個交叉。另一方面,如果趨勢步長太小,則在探索間隔開始時和趨勢步長中的函數(shù)值將是不可區(qū)分的。雖然函數(shù)探索器會考慮這種配置,其中前兩個樣本相等而第三個不同,以指示局部極值,在函數(shù)確實在間隔內(nèi)持續(xù)增加或減少的情況下,我們將浪費時間搜索最終位于一個端點或另一個端點的極值。

局部極值

在對函數(shù)進行采樣時,當三個采樣函數(shù)值形成具有相反斜率的兩個線段時,表示有局部極值(最小值或最大值)。此外,如果前兩個值或后兩個值相等,則表示為極值,但如果所有三個值相等則不表示為極值。當表示有極值時,將引發(fā)LocalExtremumIndicated事件,并保證局部極值存在于三個樣本中的第一個和最后一個之間。但是,如果采樣不充分,則第一個和最后一個樣本之間可能存在多個極值。

如果FindAllExtremaPreciselytrue,則立即找到指示的極值的確切位置。如果ExploreExtremaToFindCrossingstrue并且極值是最大值且所有三個樣本都低于閾值,或者最小值并且所有三個樣本都高于閾值,則還會找到極值的精確位置。最后,如果用戶在LocalExtremumIndicated事件期間顯式調(diào)用FindPreciseExtremum方法,則會精確找到極值。當找到極值的精確位置時,函數(shù)探索器會引發(fā)LocalExtremumFound。

使用BrentFindExtremum可以找到極值的精確位置。 ExtremumConvergenceCriteria屬性控制用于確定何時發(fā)現(xiàn)極值達到足夠精度的標準。當設(shè)置為ConvergenceCriteria.Variable時,當極值被小于ExtremumVariableTolerance的范圍時,極值搜索會收斂。當設(shè)置為ConvergenceCriteria.Function時,當最后一個采樣函數(shù)值在通過將曲線擬合到指示極值的三個點而估計的值的ExtremumValueTolerance范圍內(nèi)時,極值搜索收斂。 ConvergenceCriteria也可以允許融合。任何一個標準或者可以要求滿足ConvergenceCriteria.Both標準。

如果采樣不充分導(dǎo)致三個樣本之間存在多個局部極值標明為一個極值,則函數(shù)探索器將只發(fā)現(xiàn)一個極值,并且它們不能保證找到哪一個極值。

ReportExtremaAtEndpoints設(shè)置為true時,還會在探測間隔的開始和結(jié)束時報告局部極值。例如,如果函數(shù)在間隔開始時減小,則第一個樣本是局部最大值。類似地,如果函數(shù)在間隔結(jié)束時減少,則最后一個樣本是局部最小值。如果函數(shù)在端點處是平坦的,則不會報告極值。

閾值交叉

在對函數(shù)進行采樣時,當兩個采樣函數(shù)值位于閾值的相對側(cè)時,表示有閾值交叉。當采樣函數(shù)值恰好位于閾值上時,基于BehaviorWhenOnThreshold屬性的值確定閾值交叉時,將其視為高于還是低于閾值。

當出現(xiàn)極值時,將引發(fā)ThresholdCrossingIndicated事件,并保證交叉存在于兩點之間的某處。但是,如果采樣不充分,則兩個樣本之間可能存在多個交叉點。

如果FindAllCrossingsPreciselytrue,則立即找到標明交叉點的確切位置。如果用戶在ThresholdCrossingIndicated事件期間顯式調(diào)用FindPreciseCrossing方法,也會找到交叉點的精確位置。當找到交叉點的精確位置時,函數(shù)探索器會引發(fā)ThresholdCrossingFound事件。

使用BrentFindRoot找到交叉點的精確位置。 ConvergenceCriteria屬性控制用于確定何時發(fā)現(xiàn)交叉點達到足夠精度的標準。當設(shè)置為ConvergenceCriteria.Variable時,當交叉點被小于CrossingVariableTolerance的間隔范圍內(nèi)時,交叉搜索會收斂。當設(shè)置為ConvergenceCriteria.Function時,當最后一個采樣函數(shù)值在閾值的ValueTolerance范圍內(nèi)時,交叉搜索會收斂。 ConvergenceCriteria也可以允許融合。任何一個標準或者都可以要求滿足ConvergenceCriteria.Both標準。當識別的交叉點不完全等于閾值時,SolutionType屬性控制報告的交叉點是略高于還是略低于閾值。

當函數(shù)在閾值處是平坦的時,將平坦區(qū)域中的任意數(shù)量的樣本報告為閾值交叉是合理的。相反,函數(shù)探索器根據(jù)SolutionType屬性的值保證報告交叉的位置。當設(shè)置為ThresholdCrossingSolutionType.OnOrAboveThreshold,并且函數(shù)在增加時越過閾值時,報告的交叉是閾值上最早的采樣變量值。如果函數(shù)在減小時越過閾值,則報告的交叉是閾值上的最新采樣變量值。這與ThresholdCrossingSolutionType.OnOrAboveThreshold暗示應(yīng)將閾值上的值視為高于閾值的觀點一致;函數(shù)探索器首次報告它超過閾值并且最后一次超過閾值。類似地,當設(shè)置為ThresholdCrossingSolutionType.OnOrBelowThreshold,并且函數(shù)在增加時越過閾值時,報告的交叉是閾值上的最新采樣變量值。如果函數(shù)在減小時越過閾值,則報告的交叉是閾值上最早的采樣變量值。最后,當設(shè)置為ThresholdCrossingSolutionType.OnAboveOrBelowThreshold時,函數(shù)探索器會報告最早的交叉,無論方向如何。

如果采樣不充分導(dǎo)致兩個樣本之間出現(xiàn)多個交叉點表示為一個交叉點,則函數(shù)探索器只能找到其中一個交叉點,并且無法保證找到哪個交叉點。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容