2011-10-08 20 views
48

我正在學習編程(python和algo's),並試圖在一個我感興趣的項目上工作。我已經創建了幾個基本的Python腳本,但我不確定如何解決我嘗試構建的遊戲的解決方案。如何處理猜謎遊戲(帶扭曲)算法?

這裏的比賽將如何工作:

用戶,將得到一個價值的物品。例如

Apple = 1 
Pears = 2 
Oranges = 3 

然後他們將有機會選擇他們喜歡的任何組合(即100個蘋果,20個梨和1個桔子)。計算機唯一的輸出是總價值(在這個例子中,它現在是143美元)。電腦會試圖猜測他們有什麼。這顯然無法在第一回閤中正確得到。

  Value quantity(day1) value(day1) 
Apple 1  100    100 
Pears 2  20    40 
Orange 3  1    3 
Total   121    143 

下轉用戶可以修改自己的電話號碼,但總量不超過5%(或其他一些百分比,我們可以選擇。我會用例如5%)。水果的價格可以隨機變化,所以總價值也可能會因此而改變(爲簡單起見,本例中我不改變水果價格)。使用上面的例子,在遊戲的第2天,用戶在第3天返回價值152美元和164美元。下面是一個例子。

quantity(day2) %change(day2) value(day2) quantity(day3) %change(day3) value(day3) 
104        104   106        106 
21        42   23        46 
2        6   4        12 
127    4.96%   152   133    4.72%   164 

*(我希望表顯示正確的,我不得不手動空間他們,所以希望它不只是做我的屏幕上,如果它不工作,讓我知道,我會試着上傳截圖)。

我想知道我是否能夠計算出數量隨時間的變化(假設用戶將有耐心保持輸入數字)。我現在知道我唯一的限制就是總價值不能超過5%,所以我現在的準確率不能超過5%,所以用戶會永遠輸入。

我做了什麼至今

這裏是我的解決方案至今(不要太多)。基本上我把所有的價值都拿出來,弄清楚他們所有可能的組合(我完成了這部分)。然後,我將所有可能的組合放在一個數據庫中作爲一個字典(例如143美元,可能會有一個字典條目{apple:143,Pears:0,Oranges:0} ..一路{apple :0,Pears:1,Oranges:47}。每當我得到一個新號碼時,我都會這樣做,所以我列出了所有的可能性。 ?我找出最佳的解決方案,我認爲我需要一個健身功能,可自動兩天數據進行比較,並刪除具有前幾天的數據超過5%的變異任何可能性

問題:

所以我的問題與用戶改變總數和我有一個所有概率列表,我應該如何處理這個?我需要學習什麼?是否有任何算法或我可以使用的理論適用?或者,爲了幫助我理解我的錯誤,你能否提出我可以添加什麼規則來實現這個目標(如果它不在目前的狀態中,我想增加更多的水果並且說他們必須至少選擇3個等)。 ?此外,我只對遺傳算法有一個模糊的理解,但我認爲我可以在這裏使用它們,如果有什麼我可以使用的?

我非常非常渴望學習,所以任何意見或建議,將不勝感激(只是請你不要告訴我,這個遊戲是不可能的)。

在此先感謝。

更新:得到反饋,這很難解決。所以我想我會在遊戲中添加另一個條件,不會干擾玩家的行爲(遊戲對他們來說保持不變),但每天水果的價值會隨着價格的變化而變化。這會讓它更容易解決嗎?因爲在5%的運動和某些水果價值的變化中,隨着時間的推移,只有少數組合是可能的。第一天,任何事情都是可能的,並且獲得足夠接近的範圍幾乎是不可能的,但是隨着水果價格變化並且用戶只能選擇5%的變化,那麼不應該(隨着時間的推移)範圍狹窄和狹窄。在上面的例子中,如果價格足夠波動,我想我可以蠻橫逼迫一個解決方案,讓我有一個猜測的範圍,但我試圖找出是否有更優雅的解決方案或其他解決方案來繼續縮小這個範圍時間。

UPDATE2:經過閱讀和詢問,我認爲這是一個隱藏的markov /維特比問題,跟蹤水果價格變化以及總額(加權最後一個數據點最重)。我不知道如何應用這種關係。我認爲是這樣,可能是錯誤的,但至少我開始懷疑這是一種機器學習問題。

UPDATE3:我創建了一個測試案例(較小的數字)和一臺發電機,以幫助自動化用戶生成的數據,我想從它創建一個圖表,看看有什麼更容易。 下面是代碼,以及用戶實際水果數量的總值和評論。

#!/usr/bin/env python 
import itertools 

#Fruit price data 
fruitPriceDay1 = {'Apple':1,'Pears':2,'Oranges':3} 
fruitPriceDay2 = {'Apple':2,'Pears':3,'Oranges':4} 
fruitPriceDay3 = {'Apple':2,'Pears':4,'Oranges':5} 

#generate possibilities for testing(Warning..will not scale with large numbers) 
def possibilityGenerator(target_sum, apple, pears, oranges): 
    allDayPossible = {} 
    counter = 1 
    apple_range = range(0, target_sum + 1, apple) 
    pears_range = range(0, target_sum + 1, pears) 
    oranges_range = range(0, target_sum + 1, oranges) 
    for i, j, k in itertools.product(apple_range, pears_range, oranges_range): 
     if i + j + k == target_sum: 
      currentPossible = {} 
      #print counter 
      #print 'Apple', ':', i/apple, ',', 'Pears', ':', j/pears, ',', 'Oranges', ':', k/oranges 
      currentPossible['apple'] = i/apple 
      currentPossible['pears'] = j/pears 
      currentPossible['oranges'] = k/oranges 
      #print currentPossible 
      allDayPossible[counter] = currentPossible 
      counter = counter +1 
    return allDayPossible 

#total sum being returned by user for value of fruits    
totalSumDay1=26 # computer does not know this but users quantities are apple: 20, pears 3, oranges 0 at the current prices of the day 
totalSumDay2=51 # computer does not know this but users quantities are apple: 21, pears 3, oranges 0 at the current prices of the day 
totalSumDay3=61 # computer does not know this but users quantities are apple: 20, pears 4, oranges 1 at the current prices of the day 
graph = {} 
graph['day1'] = possibilityGenerator(totalSumDay1, fruitPriceDay1['Apple'], fruitPriceDay1['Pears'], fruitPriceDay1['Oranges']) 
graph['day2'] = possibilityGenerator(totalSumDay2, fruitPriceDay2['Apple'], fruitPriceDay2['Pears'], fruitPriceDay2['Oranges']) 
graph['day3'] = possibilityGenerator(totalSumDay3, fruitPriceDay3['Apple'], fruitPriceDay3['Pears'], fruitPriceDay3['Oranges']) 
#sample of dict = 1 : {'oranges': 0, 'apple': 0, 'pears': 0}..70 : {'oranges': 8, 'apple': 26, 'pears': 13} 
print graph 
+7

1爲一個很好的問題是清楚和格式化。 – SpeedBirdNine

+1

非常感謝SpeedBirdNine。第一次有人在這裏對我說。通常我會得到完全相反的結果:-) – Lostsoul

+3

您可能想試試http://math.stackexchange.com/ –

回答

11

我們將結合圖形理論和概率:

在第1天,打造一個集所有可行的解決方案。讓我們將解設爲A1 = {a1(1),a1(2),...,a1(n)}。

第二天可以再次新的解決方案集合A2。現在

,在A2每一個元素,你需要檢查它是否能夠從A1(定x%容差)的每個元素到達。如果是這樣 - 將A2(n)連接到A1(m)。如果無法從A1(m)中的任何節點到達 - 您可以刪除此節點。

基本上,我們正在建立一個連接的向無環圖。

圖中的所有路徑具有相同的可能性。只有在從Am到Am + 1的單個邊(從Am中的節點到Am + 1中的節點)時,才能找到確切的解。

當然,一些節點出現在比其他節點更多的路徑。每個節點的概率可以根據包含此節點的路徑的數量直接推導出來。

通過爲每個節點分配一個權重,該權值等於導向此節點的路徑數量,不需要保留所有歷史記錄,而只需保留前一天。

另外,看看non-negative-values linear diphantine equations - 我剛纔問的一個問題。接受的答案是在每一步都能讓所有組合成爲可能的好方法。

+0

可能的套件尺寸有額外的減少。在A1 + A2步驟後,如果添加下一組可能的配置A3,則可以基於「不可在5%範圍內」標準修剪組A2和A3,但也可以將其「級聯」回A1 -A2結。最終的結果是,A1組只能變小。但是集合An + 1將「可能」大於集合An。但我不認爲gaim的目標是僅僅猜測A1組合的合適人選。 – wildplasser

+0

@Lostsoul:如果你發現我的答案不清楚 - 請讓我知道,我會盡力解釋。 –

+0

@LiorKogan我理解你的解決方案,但一直試圖成功實施它。我理解你的邏輯,這是有道理的,但我開始思考,因爲所有的數字都有相同的成功可能性,它如何區分正確的解決方案,出於如此多的可能性。我最終看着隱藏的馬爾科夫模型,這似乎是正確的,但它只是衡量最後一次成功的匹配(不是A1,A2,...)。 – Lostsoul

7

這個問題是不可能解決的。 可以說,你確切地知道什麼比率項目的數量增加,而不僅僅是這個最大比例。

用戶有N個水果,你有D天的猜測。

在每一天你會得到N個新的變量,然後你有總共D * N個變量。

對於每一天,您只能生成2個方程。一個方程是n_item *價格的總和,另一個方程是基於已知比率。如果它們都是獨立的,那麼總共至多有2 * D個方程。

2 * d < N * d對所有N> 2

+0

感謝Ralu,數學網站上的某個人說了一些simlair,所以我更新了問題以添加一個新的條件(無需更改用戶的流程)。如果果實的價值每天隨機變化(我無法控制它,因爲我可以很容易地將極端值分離出可能性)呢?如果水果價格在變化,那麼不會有某些可能性減少,隨着時間的推移,這種可能性實際上會降低到更準確的程度。 – Lostsoul

+0

有沒有這樣的事情越少越可能。這是關於可能/不可能的。是的,如果你知道它們是整數解決方案,你可能會拋出一些解決方案,但僅此而已。 想象一下,用戶開始惠普1000000,1000000和1000000,然後它可以每次更改每個值+/- 50000。因此,如果限制每個步驟的差異,則無關緊要。 –

+0

我同意你的意見並感謝你的解釋。我只是在想,爲了得到答案,我需要解決兩件事情。一個是限制可能性。如果總價值是5,蘋果的價格跳到100美元,那麼顯然用戶沒有蘋果,所以我可以消除,等等..直到也許我有一個範圍。一旦我有了這個範圍,那麼我認爲可能會出現一個簡單的猜測遊戲結構,但這個問題的關鍵並不是要得到最準確的答案(這將是很好的),而是現實的如何獲得最窄的範圍。 – Lostsoul

6

聲明:我以後暫時刪除我的答案和重新閱讀的問題仔細,因爲我誤解了問題的一些關鍵部分顯着改變了我的答案。雖然仍然參考了類似的主題和算法,但在我嘗試自己解決C#中的一些問題後,答案大大改善了。

好萊塢版本

  • 的問題是Dynamic constraint satisfaction problem(DCSP),上Constraint satisfaction problems的變化(CSP)
  • 使用Monte Carlo找到某一天可能的解決方案,如果價值和數量範圍不小。否則,使用蠻力找到每個可能的解決方案。
  • 使用約束記錄(與DCSP有關),與前幾天級聯應用以限制潛在的解決方案集。
  • 橫渡你的手指,目標和拍攝(猜測),基於概率。
  • (可選)布魯斯威利斯獲勝。

原始版本

首先,我想說明什麼,我在這裏看到的兩個主要問題:

  1. 可能的解決方案的數量之多。只知道物品的數量和總價值,比如說3和143,將會產生很多的可能解決方案。另外,它是不容易有一種算法選擇有效的解決方案,而不可避免的嘗試無效的解決方案(總不等於143)

  2. 如果可能的解決方案被發現某一天d ,必須找到一種方法通過{D i + 1 .. D i + n}給出的附加信息消除潛在的解決方案。

讓我們放下一些基地,爲即將到來的例子:

  • 讓我們保持相同的項目值,整場比賽。它可以是隨機的或由用戶選擇。
  • 可能的項目值綁定到非常有限的[1-10]範圍,其中沒有兩個項目可以具有相同的值。
  • 沒有商品的數量可能大於100.這意味着:[0-100]。

爲了解決這個問題更容易我冒昧地改變一個約束,這使得算法收斂速度快:

  • 的「總量」的規則此規則重寫:您可以在一天內添加或刪除[1-10]範圍內的任意數量的項目。但是,您無法添加或刪除相同數量的項目,總計超過兩次。這也爲遊戲提供了20天的最長生命週期。

該規則使我們能夠更輕鬆地排除解決方案。而且,在非微小範圍內,呈現Backtracking algorithms仍然無用,就像您最初的問題和規則一樣。

在我看來,這個規則並不是本質的遊戲,但只有一個協助者,使計算機解決問題。

問題1:尋找可能的解決方案

對於初學者來說,問題1.可以使用Monte Carlo algorithm找到一個組可能的方案來解決。該技術很簡單:爲項目值和數量生成隨機數(在各自可接受的範圍內)。重複所需數量的項目的過程。驗證解決方案是否可接受。這意味着如果檢驗項目具有不同的值,總等於我們的目標總(比如143)

雖然這種技術具有易於實現它的優勢,也有一些缺點:

  • 的用戶的解決方案不保證出現在我們的結果中。
  • 有很多「錯過」。例如,考慮到我們的限制,需要或多或少地嘗試找到1,000個潛在解決方案。
  • 它需要很多時間:我的懶惰筆記本電腦上大約需要4到5秒。

如何解決這些缺點?嗯......

  • 限制的範圍內,以更小的值和
  • 查找可能的解決方案提供足夠數量的所以是一個很好的機會,用戶的解決方案出現在您的解決方案集。
  • 使用啓發式來尋找解決方案更容易(稍後更多)

注意,你越限制範圍內,不太實用,而成爲蒙特卡洛算法,因爲會有足夠的幾個有效解決方案在合理的時間內對它們進行迭代。對於約束{3,[1-10],[0-100]},大約有741,000,000個有效解(不限於目標總值)。蒙特卡羅在那裏可用。對於{3,[1-5],[0-10]},只有大約80,000。不需要使用蒙特卡羅;蠻力for循環會做得很好。

我相信問題1是你所說的Constraint satisfaction problem(或CSP。)

問題2:限制設定鑑於問題1是一個CSP,我會繼續前進,並呼籲問題2,和一般的問題的潛在解決方案

,一Dynamic CSP(或直流正接)

[DCSPs]當 問題的原始製劑以某種方式被改變,通常是因爲該組 約束考慮,因爲環境的演變是有用的。 DCSP 被視爲靜態CSP序列,每個變量都是前一個可以添加變量和約束條件 (限制)或刪除(放寬)的變換。與通信服務提供商使用

的一種技術,可能是解決這個問題有用稱爲約束記錄

  • 與環境中的每一個變化(d 用戶輸入的值i + 1的),找到有關新約束的信息:添加刪除約束可能「使用」的數量是多少。
  • 將約束應用於級聯中的每個前一天。漣漪效應可能顯着減少可能的解決方案。

爲了這個工作,你需要每天獲得一套新的可能的解決方案;使用蠻力或蒙特卡羅。然後,比較D i與D i-1的解決方案,並且只保留能夠在前一天的解決方案中取得成功而不違反約束的解決方案。

你可能會保持什麼樣的解決方案導致什麼其他解決方案(可能有向圖)約束記錄,您可以記得可能的附加去除量並拒絕基於該解決方案的歷史。

還有很多其他步驟可以用來進一步改進您的解決方案。這裏有一些想法:

  • 在前幾天的解決方案中找到的項目 - 值組合的記錄約束。立即拒絕其他解決方案(因爲項目值不得更改)。您甚至可以使用特定於解決方案的約束來爲每個現有解決方案找到更小的解決方案集,以便早日拒絕無效解決方案。
  • 每天都會生成一些「突變」全歷史解決方案,以便「修復」解決方案集不包含用戶解決方案的情況。您可以使用遺傳算法來找到基於現有解決方案組的突變體羣體。)
  • 使用啓發式以便輕鬆找到解決方案(例如,當找到有效的解決方案時,嘗試通過替換周圍的數量來找到此解決方案的變體。 )
  • 使用行爲啓發式來預測某些用戶操作(例如,每個項目的相同數量,極端模式等)
  • 在用戶輸入新數量時繼續進行一些計算。

考慮到所有這些,試着找出一個基於解決方案和啓發式發生的排名系統來確定候選解決方案。

+2

你應該給出一個證明,證明它是NP難... –

+0

我會盡力明天,但我不太擅長形式化的證明。然而,我可以放心地說,這個問題看起來像是一個優化問題,這個問題通常不是NP而不是P. –

+0

我終於刪除了NP-hard的假設(並且重構了我的答案),因爲我最初雖然問題是一個優化問題。問題可能仍然是NP- *複雜性,但我不確定。 –

1

爲您最初的規則: 從我的學校裏,我會說,如果我們的5點%的變化的抽象,我們每天有3個未知值的公式(對不起,我不知道數學詞彙英文),與前一天的價值相同。 在第3天,您有3個方程,3個未知值,解決方案應該是直接的。

我猜如果3個元素的值足夠不同,那麼每天5%的變化可能會被遺忘,因爲如您所說,我們將使用近似值和數字四捨五入。

爲了您的適應規則: 太多的未知數 - 和不斷變化的 - 在這種情況下的值,所以沒有直接的解決方案,我知道的。我相信Lior,他的方法看起來不錯! (如果您的價格和數量範圍有限)

3

我寫了一個程序來玩遊戲。當然,我必須讓人類自動化,但我相信我做到了這一切,以至於當我與真人對戰時,我不應該使我的方法失效。

我從機器學習的角度來看待這個問題,並將問題看作隱藏的馬爾可夫模型,其總價就是觀察值。我的解決方案是使用粒子濾波器。該解決方案使用NumPy和SciPy以Python 2.7編寫。

我聲明瞭任何假設,我明確地在評論中或隱含在代碼中。爲了讓代碼以自動化的方式運行,我還設置了一些額外的限制。這並不是特別優化,因爲我試圖在側面理解而不是速度上犯錯。

每次迭代輸出當前的真實量和猜測。我只是將輸出輸出到一個文件,以便我可以輕鬆查看它。一個有趣的擴展將是在2D(2果)或3D(3果)上繪製輸出圖。然後,您將能夠在解決方案中看到粒子濾波器。

更新:

編輯代碼以包含調整後更新的參數。包括使用matplotlib繪圖調用(通過pylab)。在Linux-Gnome上繪製工程,你的里程可能會有所不同。默認NUM_FRUITS爲2來繪製支持。只需註釋掉所有的pylab調用即可移除繪圖,並且可以將NUM_FRUITS更改爲任何內容。

做一個好的工作估計由UnknownQuantities X價格= TotalPrice代表的當前fxn。在二維(2水果)這是一條線,在3D(3水果)這將是一架飛機。似乎粒子濾波器的數據太少,無法正確地處理正確的數量。在粒子濾波器之上需要更多智能來真正地彙集歷史信息。您可以嘗試將粒子濾波器轉換爲二階或三階。

更新2:

我一直在玩我的代碼,很多。我嘗試了一堆東西,現在提出我將要製作的最終節目(開始燒掉這個想法)。

更改:

粒子現在使用浮點而不是整數。不知道這是否有任何有意義的效果,但它是一個更一般的解決方案。舍入到整數僅在猜測時完成。

繪圖顯示爲綠色方塊和當前猜測的真實數量爲紅色正方形。目前認爲顆粒顯示爲藍色點(根據我們相信它們的大小來確定)。這使得很容易看出算法的工作效果。 (繪圖也測試並在Win 7 64位上運行)。

增加了關閉/打開數量變化和價格變化的參數。當然,'關'都不是很有趣。

它做得很好,但是,正如已經指出的那樣,這是一個非常棘手的問題,因此獲得確切的答案是困難的。關閉CHANGE_QUANTITIES會產生最簡單的情況。您可以通過關閉CHANGE_QUANTITIES運行2個水果來獲得問題難度。看看它在正確的答案中有多快,然後看看你增加水果的數量有多難。

您也可以通過保持CHANGE_QUANTITIES開啓,但將MAX_QUANTITY_CHANGE從非常小的值(.001)調整爲「大」值(.05)來獲得難度的透視圖。

如果維數(一個水果數量)接近於零,那麼它掙扎的一種情況是。因爲它使用的是粒子的平均值來猜測它總是偏離像零這樣的硬邊界。

一般來說,這使得一個偉大的粒子濾波教程。


from __future__ import division 
import random 
import numpy 
import scipy.stats 
import pylab 

# Assume Guesser knows prices and total 
# Guesser must determine the quantities 

# All of pylab is just for graphing, comment out if undesired 
# Graphing only graphs first 2 FRUITS (first 2 dimensions) 

NUM_FRUITS = 3 
MAX_QUANTITY_CHANGE = .01 # Maximum percentage change that total quantity of fruit can change per iteration 
MAX_QUANTITY = 100 # Bound for the sake of instantiating variables 
MIN_QUANTITY_TOTAL = 10 # Prevent degenerate conditions where quantities all hit 0 
MAX_FRUIT_PRICE = 1000 # Bound for the sake of instantiating variables 
NUM_PARTICLES = 5000 
NEW_PARTICLES = 500 # Num new particles to introduce each iteration after guessing 
NUM_ITERATIONS = 20 # Max iterations to run 
CHANGE_QUANTITIES = True 
CHANGE_PRICES = True 

''' 
    Change individual fruit quantities for a random amount of time 
    Never exceed changing fruit quantity by more than MAX_QUANTITY_CHANGE 
''' 
def updateQuantities(quantities): 
    old_total = max(sum(quantities), MIN_QUANTITY_TOTAL) 
    new_total = old_total 
    max_change = int(old_total * MAX_QUANTITY_CHANGE) 

    while random.random() > .005: # Stop Randomly  
    change_index = random.randint(0, len(quantities)-1) 
    change_val = random.randint(-1*max_change,max_change) 

    if quantities[change_index] + change_val >= 0: # Prevent negative quantities 
     quantities[change_index] += change_val 
     new_total += change_val 

     if abs((new_total/old_total) - 1) > MAX_QUANTITY_CHANGE: 
     quantities[change_index] -= change_val # Reverse the change 

def totalPrice(prices, quantities): 
    return sum(prices*quantities) 

def sampleParticleSet(particles, fruit_prices, current_total, num_to_sample): 
    # Assign weight to each particle using observation (observation is current_total) 
    # Weight is the probability of that particle (guess) given the current observation 
    # Determined by looking up the distance from the hyperplane (line, plane, hyperplane) in a 
    # probability density fxn for a normal distribution centered at 0 
    variance = 2 
    distances_to_current_hyperplane = [abs(numpy.dot(particle, fruit_prices)-current_total)/numpy.linalg.norm(fruit_prices) for particle in particles] 
    weights = numpy.array([scipy.stats.norm.pdf(distances_to_current_hyperplane[p], 0, variance) for p in range(0,NUM_PARTICLES)]) 

    weight_sum = sum(weights) # No need to normalize, as relative weights are fine, so just sample un-normalized 

    # Create new particle set weighted by weights 
    belief_particles = [] 
    belief_weights = [] 
    for p in range(0, num_to_sample): 
    sample = random.uniform(0, weight_sum) 
    # sum across weights until we exceed our sample, the weight we just summed is the index of the particle we'll use 
    p_sum = 0 
    p_i = -1 
    while p_sum < sample: 
     p_i += 1 
     p_sum += weights[p_i] 
    belief_particles.append(particles[p_i]) 
    belief_weights.append(weights[p_i]) 

    return belief_particles, numpy.array(belief_weights) 

''' 
    Generates new particles around the equation of the current prices and total (better particle generation than uniformly random) 
''' 
def generateNewParticles(current_total, fruit_prices, num_to_generate): 
    new_particles = [] 
    max_values = [int(current_total/fruit_prices[n]) for n in range(0,NUM_FRUITS)] 
    for p in range(0, num_to_generate): 
    new_particle = numpy.array([random.uniform(1,max_values[n]) for n in range(0,NUM_FRUITS)]) 
    new_particle[-1] = (current_total - sum([new_particle[i]*fruit_prices[i] for i in range(0, NUM_FRUITS-1)]))/fruit_prices[-1] 
    new_particles.append(new_particle) 
    return new_particles 


# Initialize our data structures: 
# Represents users first round of quantity selection 
fruit_prices = numpy.array([random.randint(1,MAX_FRUIT_PRICE) for n in range(0,NUM_FRUITS)]) 
fruit_quantities = numpy.array([random.randint(1,MAX_QUANTITY) for n in range(0,NUM_FRUITS)]) 
current_total = totalPrice(fruit_prices, fruit_quantities) 
success = False 

particles = generateNewParticles(current_total, fruit_prices, NUM_PARTICLES) #[numpy.array([random.randint(1,MAX_QUANTITY) for n in range(0,NUM_FRUITS)]) for p in range(0,NUM_PARTICLES)] 
guess = numpy.average(particles, axis=0) 
guess = numpy.array([int(round(guess[n])) for n in range(0,NUM_FRUITS)]) 

print "Truth:", str(fruit_quantities) 
print "Guess:", str(guess) 

pylab.ion() 
pylab.draw() 
pylab.scatter([p[0] for p in particles], [p[1] for p in particles]) 
pylab.scatter([fruit_quantities[0]], [fruit_quantities[1]], s=150, c='g', marker='s') 
pylab.scatter([guess[0]], [guess[1]], s=150, c='r', marker='s') 
pylab.xlim(0, MAX_QUANTITY) 
pylab.ylim(0, MAX_QUANTITY) 
pylab.draw() 

if not (guess == fruit_quantities).all(): 
    for i in range(0,NUM_ITERATIONS): 
    print "------------------------", i 

    if CHANGE_PRICES: 
     fruit_prices = numpy.array([random.randint(1,MAX_FRUIT_PRICE) for n in range(0,NUM_FRUITS)]) 

    if CHANGE_QUANTITIES: 
     updateQuantities(fruit_quantities) 
     map(updateQuantities, particles) # Particle Filter Prediction 

    print "Truth:", str(fruit_quantities) 
    current_total = totalPrice(fruit_prices, fruit_quantities) 

    # Guesser's Turn - Particle Filter: 
    # Prediction done above if CHANGE_QUANTITIES is True 

    # Update 
    belief_particles, belief_weights = sampleParticleSet(particles, fruit_prices, current_total, NUM_PARTICLES-NEW_PARTICLES) 
    new_particles = generateNewParticles(current_total, fruit_prices, NEW_PARTICLES) 

    # Make a guess: 
    guess = numpy.average(belief_particles, axis=0, weights=belief_weights) # Could optimize here by removing outliers or try using median 
    guess = numpy.array([int(round(guess[n])) for n in range(0,NUM_FRUITS)]) # convert to integers 
    print "Guess:", str(guess) 

    pylab.cla() 
    #pylab.scatter([p[0] for p in new_particles], [p[1] for p in new_particles], c='y') # Plot new particles 
    pylab.scatter([p[0] for p in belief_particles], [p[1] for p in belief_particles], s=belief_weights*50) # Plot current particles 
    pylab.scatter([fruit_quantities[0]], [fruit_quantities[1]], s=150, c='g', marker='s') # Plot truth 
    pylab.scatter([guess[0]], [guess[1]], s=150, c='r', marker='s') # Plot current guess 
    pylab.xlim(0, MAX_QUANTITY) 
    pylab.ylim(0, MAX_QUANTITY) 
    pylab.draw() 

    if (guess == fruit_quantities).all(): 
     success = True 
     break 

    # Attach new particles to existing particles for next run: 
    belief_particles.extend(new_particles) 
    particles = belief_particles 
else: 
    success = True 

if success: 
    print "Correct Quantities guessed" 
else: 
    print "Unable to get correct answer within", NUM_ITERATIONS, "iterations" 

pylab.ioff() 
pylab.show() 
+0

哇..我只是要寫我自己的問題的答案,說答案是好的,但我認爲解決方案是一個隱藏的markov或viterbi算法。我收到一條消息,說已經發布了一個新的答案,並且我對此進行了更新。很好的答案。我會做一些測試,並讓你知道它是如何..謝謝凱爾 – Lostsoul

+0

它看起來很有趣。我明白你的邏輯,但我有幾個問題。這似乎是隨機猜測。是否有辦法不僅包括過去的總和,而且包括所有過去的總和(最後一個更重)。似乎每個答案都只是接近最後一個答案,但看起來幾個回來的結果似乎並不相關。 – Lostsoul

+0

它只代表一階隱馬爾可夫模型,所以它只關心一步。一個改進將是把它變成二階或三階。現在我正在調整參數以獲得更好的結果。從理論上講,經過良好調整的一階HMM應該沒問題,因爲粒子「代表」它們來自哪裏的歷史。希望我會很快收到一份調整後的更新,效果更好。 – Kyle