algorithm - 收敛于元素的最佳组合

标签 algorithm combinations convergence

您有 10,000 美元用于投资股票。给你一张包含 200 只股票的 list ,你被告知要从中选择 8 只股票进行购买,并指出你想购买其中的多少只股票。你不能单独在一只股票上花费超过 2,500 美元,每只股票都有自己的价格,从 100 美元到 1000 美元不等。您不能购买股票的一小部分,只能购买整数。每只股票也有一个附加值,表明它的盈利能力。这是 0-100 之间的任意数字,用作简单的评级系统。

最终目标是列出 8 只股票的最佳选择,并指出每只股票的最佳购买数量,而不超过每只股票 2,500 美元的限额。

• 我不是在征求投资建议,我选择股票是因为它可以很好地比喻我要解决的实际问题。

• 我看到的似乎是 0/1 背包问题的更复杂版本:https://en.wikipedia.org/wiki/Knapsack_problem .

• 不,这不是家庭作业。

最佳答案

这里是经过简单测试的代码,可以准确及时地解决您的问题,该问题是可用货币数量、您拥有的股票数量以及您可以购买的最大股票数量的多项式。

#! /usr/bin/env python
from collections import namedtuple

Stock = namedtuple('Stock', ['id', 'price', 'profit'])

def optimize (stocks, money=10000, max_stocks=8, max_per_stock=2500):
    Investment = namedtuple('investment', ['profit', 'stock', 'quantity', 'previous_investment'])
    investment_transitions = []
    last_investments = {money: Investment(0, None, None, None)}
    for _ in range(max_stocks):
        next_investments = {}
        investment_transitions.append([last_investments, next_investments])
        last_investments = next_investments


    def prioritize(stock):
        # This puts the best profit/price, as a ratio, first.
        val = [-(stock.profit + 0.0)/stock.price, stock.price, stock.id]
        return val

    for stock in sorted(stocks, key=prioritize):
        # We reverse transitions so we have not yet added the stock to the
        # old investments when we add it to the new investments.
        for transition in reversed(investment_transitions):
            old_t = transition[0]
            new_t = transition[1]
            for avail, invest in old_t.iteritems():
                for i in range(int(min(avail, max_per_stock)/stock.price)):
                    quantity = i+1
                    new_avail = avail - quantity*stock.price
                    new_profit = invest.profit + quantity*stock.profit
                    if new_avail not in new_t or new_t[new_avail].profit < new_profit:
                        new_t[new_avail] = Investment(new_profit, stock, quantity, invest)
    best_investment = investment_transitions[0][0][money]
    for transition in investment_transitions:
        for invest in transition[1].values():
            if best_investment.profit < invest.profit:
                best_investment = invest

    purchase = {}
    while best_investment.stock is not None:
        purchase[best_investment.stock] = best_investment.quantity
        best_investment = best_investment.previous_investment

    return purchase


optimize([Stock('A', 100, 10), Stock('B', 1040, 160)])

这里是删除投资的微小优化,一旦我们看到继续向其添加股票无法改善。这可能比使用您的数据的旧代码运行速度快几个数量级。

#! /usr/bin/env python
from collections import namedtuple

Stock = namedtuple('Stock', ['id', 'price', 'profit'])

def optimize (stocks, money=10000, max_stocks=8, max_per_stock=2500):
    Investment = namedtuple('investment', ['profit', 'stock', 'quantity', 'previous_investment'])
    investment_transitions = []
    last_investments = {money: Investment(0, None, None, None)}
    for _ in range(max_stocks):
        next_investments = {}
        investment_transitions.append([last_investments, next_investments])
        last_investments = next_investments


    def prioritize(stock):
        # This puts the best profit/price, as a ratio, first.
        val = [-(stock.profit + 0.0)/stock.price, stock.price, stock.id]
        return val

    best_investment = investment_transitions[0][0][money]
    for stock in sorted(stocks, key=prioritize):
        profit_ratio = (stock.profit + 0.0) / stock.price
        # We reverse transitions so we have not yet added the stock to the
        # old investments when we add it to the new investments.
        for transition in reversed(investment_transitions):
            old_t = transition[0]
            new_t = transition[1]
            for avail, invest in old_t.items():
                if avail * profit_ratio + invest.profit <= best_investment.profit:
                    # We cannot possibly improve with this or any other stock.
                    del old_t[avail]
                    continue
                for i in range(int(min(avail, max_per_stock)/stock.price)):
                    quantity = i+1
                    new_avail = avail - quantity*stock.price
                    new_profit = invest.profit + quantity*stock.profit
                    if new_avail not in new_t or new_t[new_avail].profit < new_profit:
                        new_invest = Investment(new_profit, stock, quantity, invest)
                        new_t[new_avail] = new_invest
                        if best_investment.profit < new_invest.profit:
                            best_investment = new_invest

    purchase = {}
    while best_investment.stock is not None:
        purchase[best_investment.stock] = best_investment.quantity
        best_investment = best_investment.previous_investment

    return purchase

关于algorithm - 收敛于元素的最佳组合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48911410/

相关文章:

python - 从关键字列表中查找所有句子到字典

R - 是否有一种矢量化方式/预制函数可以快速生成两个向量之间的唯一集?

algorithm - 数值不稳定?

algorithm - 多核 - 如何合并在每个核心上找到的本地数据组?

algorithm - 集合的每个子集的最小和最大元素的或之和

algorithm - 图中的索林算法

hierarchical-data - 检查复杂层次模型 JAGS 中的收敛性

php - 始终使用值获取 $media

Python itertools 获取列表列表的排列和组合

r - 相关矩阵收敛之和