在Python中实现montecarlo-Markov链时的错误

2024-10-03 11:12:57 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图在python2.7中使用numpy实现一个简单的Markov链montecarlo。我们的目标是找到“背包问题”的解决方案,即给定一组m个物品,价值vi和重量wi,以及一个容量b的袋子,你可以找到能放进你袋子里的物品的最大价值,以及这些物品是什么。我在夏天开始编写代码,我的知识非常不平衡,所以如果我遗漏了一些明显的东西,我很抱歉,我是自学成才的,到处乱跳。你知道吗

系统的代码如下(我把它分成几个部分,试图找出哪里出了问题)。你知道吗

import numpy as np
import random


def flip_z(sackcontents): 
    ##This picks a random object, and changes whether it's been selected or not.
    pick=random.randint(0,len(sackcontents)-1)
    clone_z=sackcontents
    np.put(clone_z,pick,1-clone_z[pick])
    return clone_z

def checkcompliance(checkedz,checkedweights,checkedsack):
    ##This checks to see whether a given configuration is overweight
    weightVector=np.dot(checkedz,checkedweights)
    weightSum=np.sum(weightVector)
    if (weightSum > checkedsack):
        return False
    else:
        return True

def getrandomz(length):
    ##I use this to get a random starting configuration.
    ##It's not really important, but it does remove the burden of choice.       
    z=np.array([])
    for i in xrange(length):
        if random.random() > 0.5:
            z=np.append(z,1)
        else:
            z=np.append(z,0)
    return z

def checkvalue(checkedz,checkedvalue):
    ##This checks how valuable a given configuration is.
    wealthVector= np.dot(checkedz,checkedvalue)
    wealthsum= np.sum(wealthVector)
    return wealthsum

def McKnapsack(weights, values, iterations,sack): 
    z_start=getrandomz(len(weights))
    z=z_start
    moneyrecord=0.
    zrecord=np.array(["error if you see me"])
    failures=0.
    for x in xrange(iterations):
        current_z= np.array ([])
        current_z=flip_z(z)
        current_clone=current_z
        if (checkcompliance(current_clone,weights,sack))==True:
            z=current_clone
            if checkvalue(current_z,values)>moneyrecord:
                moneyrecord=checkvalue(current_clone,values)
                zrecord= current_clone
        else:failures+=1
    print "The winning knapsack configuration is %s" %(zrecord)
    print "The highest value of objects contained is %s" %(moneyrecord)

testvalues1=np.array([3,8,6])
testweights1= np.array([1,2,1])

McKnapsack(testweights1,testvalues1,60,2.)

发生的情况如下:最大承载能力为2时,应在不同的潜在行李承载配置之间随机切换,其中有2^3=8,测试重量和值为我输入的重量和值,z中的每个1或0表示有或没有给定的物品。它应该抛弃权重过大的选项,同时跟踪那些具有最高值和可接受权重的选项。正确的答案是将1,0,1视为配置,将9视为最大值。当我每次使用中等数量的迭代时,我都会得到9的值,但是配置看起来完全是随机的,并且以某种方式打破了权重规则。我已经用很多测试数组仔细检查了我的“checkcompliance”函数,它似乎可以工作。这些错误的、超重的配置是如何通过if语句进入zrecord的?你知道吗


Tags: returnifcloneisdefnprandomcurrent
1条回答
网友
1楼 · 发布于 2024-10-03 11:12:57

诀窍是z(因此也current_zzrecord)总是引用内存中完全相同的对象。flip_z通过np.put就地修改此对象。你知道吗

一旦你发现一个新的组合增加了你的moneyrecord,你就给它设置了一个引用,但是在随后的迭代中你继续在同一个引用中改变数据。你知道吗

换句话说,像

current_clone=current_z
zrecord= current_clone

不要复制,它们只会对内存中的同一数据生成另一个别名。你知道吗

解决这个问题的一种方法是,一旦你发现它是赢家,就显式地复制它:

if checkvalue(current_z, values) > moneyrecord:
    moneyrecord = checkvalue(current_clone, values)
    zrecord = current_clone.copy()

相关问题 更多 >