2

Mathematica基於standard mathematical definition,對無限域上的函數具有內置函數ArgMaxposmax:與argmax類似,但給出了f [x]最大的元素x的位置

有限域的模擬是一個方便的效用函數。 給定一個函數和一個列表(稱之爲函數的域),返回列表中最大化函數的元素。 這裏是有限的argmax在行動的例子: Canonicalize NFL team names

這是我的執行它(連同argmin好措施):

(* argmax[f, domain] returns the element of domain for which f of 
    that element is maximal -- breaks ties in favor of first occurrence. *) 
SetAttributes[{argmax, argmin}, HoldFirst]; 
argmax[f_, dom_List] := Fold[If[f[#1]>=f[#2], #1, #2]&, First[dom], Rest[dom]] 
argmin[f_, dom_List] := argmax[-f[#]&, dom] 

首先,是最有效的方式來實現argmax? 如果你想要所有極大元素而不是第一個元素的列表?第二,相關函數posmax怎麼樣,它不是返回最大元素,而是返回最大元素的位置???????????????????????????????????????????????

回答

3

@dreeves,你是正確的在Ordering的關鍵是最快的實現ArgMax的在有限域:您使用Fold原來實行的問題

ArgMax[f_, dom_List] := dom[[Ordering[f /@ dom, -1]]] 

的部分是,你最終評估f是必要的兩倍,這是低效的,特別是當計算f慢時。在這裏,我們只爲域的每個成員評估f一次。當域中有很多重複的元素,我們可以進一步的fmemoizing值優化:

ArgMax[f_, dom_List] := 
    Module[{g}, 
    g[e___] := g[e] = f[e]; (* memoize *) 
    dom[[Ordering[g /@ dom, -1]]] 
    ] 

這是約30%的速度在10萬個隨機整數0和100之間的列表一些基本的測試。

對於posmax功能,這個有點不優雅的方法是最快的事我能想出:

PosMax[f_, dom_List] := 
    Module[{y = f/@dom}, 
    [email protected][y, Max[y]] 
    ] 

當然,我們可以再次申請記憶化:

PosMax[f_, dom_List] := 
    Module[{g, y}, 
    g[e___] := g[e] = f[e]; 
    y = g /@ dom; 
    [email protected][y, Max[y]] 
    ] 

要獲得全部最大元素,您現在可以根據PosMax實施ArgMax

ArgMax[f_, dom_List] := dom[[PosMax[f, dom]]] 
+0

我應該注意的是,作爲memoization的替代方法,只要使用'DeleteDuplicates'來代替應用程序。 – 2010-04-17 08:47:44

+0

您可能想要將其封裝在First中,例如,ArgMax [Abs,{1,-3,2}]返回-3而不是{-3}。 – dreeves 2011-08-03 00:37:05

0

對於posmax,您可以先將函數映射到列表上,然後詢問最大元素的位置。即:

posmax[f_, dom_List] := posmax[f /@ dom] 

其中posmax[list]被多態定義爲只返回最大元素(一個或多個)的位置。 原來有一個內置函數,Ordering實質上是這樣做的。 因此,我們可以定義posmax的單參數版本是這樣的:

posmax[dom_List] := Ordering[dom, -1][[1]] 

我只是測試,對一個循環爲基礎的版本和遞歸版本和訂購的快許多倍。 遞歸版本很漂亮,所以我會在這裏展示它,但千萬不要試圖在大型輸入上運行它!

(* posmax0 is a helper function for posmax that returns a pair with the position 
    and value of the max element. n is an accumulator variable, in lisp-speak. *) 
posmax0[{h_}, n_:0] := {n+1, h} 
posmax0[{h_, t___}, n_:0] := With[{best = posmax0[{t}, n+1]}, 
    If[h >= best[[2]], {n+1, h}, best]] 

posmax[dom_List] := [email protected][dom, 0] 
posmax[f_, dom_List] := [email protected][f /@ dom, 0] 
posmax[_, {}] := 0 

沒有這個地址如何找到所有的最大元素(或它們的位置)的問題。 這在實踐中通常不會出現,儘管我認爲這很好。

相關問題