与Knapsack Java代码类似的动态编程算法

时间:2016-02-26 23:11:45

标签: java algorithm iteration dynamic-programming knapsack-problem

任务关键型生产系统有n个阶段,必须按顺序执行;阶段i由机器M_i执行。

每台机器M_i具有可靠地运行的概率r_i和失败的概率1-r_i(并且故障是独立的)。因此,如果我们用一台机器实现每个阶段,整个系统工作的概率是r_1,r_2,...,r_n。为了提高这种可能性,我们通过使用执行阶段i的机器M_i的m_i个副本来添加冗余。

所有m_i副本同时失败的概率仅为(1-r_i)^(m_i),因此阶段i正确完成的概率为1-(1-r_i)^(mi)和整体概率系统工作是prod(i = 1,n){1-(1-r_i)^(m_i)}。

每台机器M_i的成本为c_i,购买机器的总预算为B. (假设B和c_i是正整数。)在给出概率r_1,...,r_n,成本c_1,...,c_n和预算B的java代码中写入算法,找到冗余m_1,... 。,m_n在可用预算范围内,并最大化系统正常工作的概率(确定可实现的最大可靠性)。此外,还要显示每种类型的机器在预算范围内达到可靠性的程度。

所以我读了一个文件,它给了我允许的总预算,然后是机器的数量,然后我读到的每台机器的成本和可靠性。我将成本和可靠性存储在两个链表中(不确定这是否最好)。

  try {
            BufferedReader newFileBuffer = new BufferedReader(new     FileReader(inputFile));
            budget = Integer.parseInt(newFileBuffer.readLine()); 
            numberOfMachines = Integer.parseInt(newFileBuffer.readLine()); 
            while ((fileLine  = newFileBuffer.readLine()) != null) 
            {       
                line = fileLine.split(" ");

                try 
                {
                    cost.add(Integer.parseInt(line[0]));
                    totalCostOfOneEach += Integer.parseInt(line[0]); 
                    reliability.add(Float.parseFloat(line[1]));
                } catch (NumberFormatException nfe) {};

            }
            newFileBuffer.close();
        } catch (Exception e) 
        {
            e.printStackTrace();
        }

从那里我知道每台机器中的一台必须使用一次,所以我按每台机器之一(totalCostOfOneEach)的总成本减去预算,如果你愿意,这会让我超出预算或冗余预算。

bRedundent = (budget - totalCostOfOneEach);

现在是我陷入困境的地方,我迷失了寻找解决方案的循环。我研究过并发现了这个solution,但我不理解这一行

Pr(b,j)=max{Pr(b-c_j*k, j-1)*(1-(1-r_j)^k}

所以我所知道的是我创建了一个双数组并且我将数组初始化为:

double[][] finalRel = new double[numberOfMachines][bRedundent]; 
for (int j = 0; j < numberOfMachines; j++)
{
    finalRel[0][j] = 0; 
}

for (int b = 1; b < budget; b++)
{
    finalRel[b][1] = reliability.get(0); 
}

现在是我被困的地方,我相信我应该循环机器的数量,然后成本,但这不起作用,我知道我需要以某种方式纳入预算。所以我现在所拥有的根本不起作用:

for (int i = 1; i < numberOfMachines; i++)
{
    for (int c = cost.get(i); c < budget; c++)
    {
        finalRel[i][c] = Math.min(finalRel[i-1][c], finalRel[i-1][c - cost.get(numberOfMachines)]*(l));
    }   
} 

我知道子问题表示为finalRel [i,b],这是机器1,2,...的最可靠配置。 。 。 ,i(每台机器中至少有一台)在预算范围内可用。期望的答案是finalRel [n,B]。

如果我们在预算之下再次发生,我们返回可靠性0(意味着不可能)。如果我们超出预算(b = 0),但仍然需要购买机器(i> 0),我们返回0(假设所有ci> 0)。如果i = 0,我们没有必须购买的机器,所以可靠性是1(如果它是0,那么一切都会乘以0,这是不好的)。如果剩下预算(b> 0)和剩余的机器购买(i> 0),我们尝试购买i型机器的所有可能性 - 我们必须购买至少m≥1,并且最多m ≤b≤floor(b / c_i)≤b≤B,其中。在每种情况下,剩余预算将为b - m·c_i。机器的最佳可靠性1 ,. 。 。 ,i - 1将是REL [i - 1,b - m·ci],需要乘以M_i的m个副本的贡献,(1 - (1 - ri)^ m)或总结{{3 }}。

我意识到这很多信息,但我已经被困了一段时间,所以任何帮助都表示赞赏。

1 个答案:

答案 0 :(得分:3)

您可以使用比此更简单的重复。对于i = 0, ..., nb = 0, ..., B,我们让R(i, b)成为从预算1阶段i到阶段B的子管道的最大可靠性。基本案例是

For b = 0, ..., B,
  R(0, b) = 1,

因为空管道永远不会失败并且不需要任何费用。此后我们有链接的重复,为了清楚起见,我稍作重写:

For i = 1, ..., n,
  For b = 0, ..., B,
    R(i, b) = max {R(i-1, b - k*c_i) * (1 - (1-r_i)^k)
                   for k = 0, ..., floor(b/c_i)},

其中k是我们正在考虑购买的i台机器的数量(如果机器可以完全可靠则定义0^0 = 1;您应该自己计算功率,然后强度 - 减少乘法,解决了这个问题并提高了性能)。因子(1 - (1-r_i)^k)是具有i台机器的阶段k的可靠性。考虑到剩余预算,因子R(i-1, b - k*c_i)是前一阶段的最大可靠性。限制floor(b/c_i)是最多花费i的{​​{1}}台计算机的最大数量。