coursera课程discrete optimization课程笔记

第一周 背景

第一周主要介绍了一下课程背景,关于离散优化的一些概念。

假设一个即将倒塌的博物馆里有很多藏品,你有一个小包,可以选择一些物品背走,使得保存的价值最大。背包的最大capacity是K,每个物品有自己的value,和weight。也就是在选择物品的weight和小于等于K的条件下,使value的和最大。即knapsack问题。

这也就是最优化问题,是计算科学中最难的NP难问题之一。

NP难问题有两个属性:1.可以快速检查某个方法是不是NP问题的解
2.如果一个方法可以很快解决一个NP难问题,那么它肯定可以解决所有NP难问题。

在这里插入图片描述
两个思路解决NP难问题:1.将曲线右移2.处理前端近似线性关系的曲线。
最优化问题举例:肾移植匹配问题;灾难管理问题;电量储备问题

第二周 knapsack问题

greedy算法

根据第一周介绍的背景,如何使背包带走的藏品价值最大。
第一个很简单的思想就是价值贪婪思想。先挑最值钱的,再根据袋子里还剩多少空间,选择重量小于剩余capacity的价值最大的,以此类推。
选择最值钱的面具和一个兵马俑
对于一个问题,可以有多种贪婪算法。
第二种贪婪算法是背包能装的东西越多越好。
选三个不占体积的兵马俑和一块碑文
第三种最科学,优先选择单位重量价值最高的藏品。
根据价值密度来选择
然而以上都是不是最佳的选择,很明显,选择两块价值为10的碑文,符合背包容量的要求,可以带来最大的收益20。
贪婪算法的优点:1.很容易实现2.运算快
问题:1.无法保证最优2.只能解决简单问题3.根据输入的不同效果不同

going beyond greedy:1.constraint programming2.local search3.mixed ineger programming

knapsack问题建模

在这里插入图片描述
得到的可能结果为2^I,当I的数目越大时,计算复杂度呈指数增长。

DP算法

动态算法是应用广泛的优化技术,具有自下而上的计算思想。
算法思想
O(k,j)表示为背包容量为k,待选择物品数量为j时的获得价值的最优结果。

假设我们已知O(k,j-1),期望得到O(k,j),那么我们只需要考虑第j个物品。
If wj ≤ k:
•如果不选择j物品,最优解保持不变,仍为O(k,j-1)
•如果选择j物品,最优解变为vj + O(k-wj,j-1)
总而言之:
•O(k,j) = max(O(k,j-1), vj + O(k-wj,j-1)) if wj ≤ k
•O(k,j) = O(k,j-1) otherwise
其中O(k,0)=0

因此DP算法是一个不断迭代的算法,最终的优化结果取决于上一个最优结果,以此递推。
在这里插入图片描述
课中以 finding fibonacci numbers程序为例,说明了这种递归算法的效率:由于重复计算子问题,导致算法效率低下。

自下而上计算递归方程
通过逐一考虑待选择的物品,列表计算得到当前最优结果。(表中空处均为0)
在这里插入图片描述
从总体最优解回溯子问题的最优解,可以得到x的取值。

这种列表方法计算复杂率与k和n的乘积有关,但是对于计算机来说实际上复杂率与输入大小是成指数关系的(输入大小用logk表示)因此只有在k较小时,算法效率较高。

Branch and Bound

对于下图所示最优化问题:
在这里插入图片描述
应用穷举法可以得到树状图:
在这里插入图片描述
branching指把问题分解为一系列子问题,如树状图的多个枝杈。Bounding指用最乐观的估计结果作为子问题的最优解。
(课中老师把这个最乐观的估计称为relaxation,”最优化就是relaxation的艺术“)

把上述问题中的容量约束作为relaxation对象,得到下图
在这里插入图片描述
不考虑容量的约束,所获收益最乐观的估计为128(45+48+35),随着branch的进行,如果确定不选择某项物品,这个最乐观的估计值就会改变。在branch的过程中需要考虑容量约束,当所剩容量为负值时,往后的branch不再继续。其中,branch的顺序是有讲究的:比较当前所有节点的最乐观估计,选择其中最大的节点进行深入branch,然后再比较再选择,这种方法称之为depth-first。

那么还能relaxation其他对象吗?

课中以巧克力举例,思考能否将x在0到1之间任意取值,也就是带走某个物品的一部分。
在这里插入图片描述
那么当前问题下的估计值变为92,使用depth-first branch and bound得到如下结果:
在这里插入图片描述

branch and bound中的search策略
①depth-first:舍弃比当前最优值差的节点
在这里插入图片描述
②best-first:选择具有最佳估计的节点(图中星标错误)
在这里插入图片描述
③least-discrepancy:trust a greedy heuristic
用递增的错误数目(往右)来explore search space(LDS)
在这里插入图片描述

第二周作业

第二周作业是knapsack问题。
迭代dp算法代码实现如下

def opt(k,j,v,w):
    if j ==0:
        return 0
    elif int(w[j-1])<=k:
        old = opt(k,j-1,v,w)
        new = int(v[j-1])+opt(k-int(w[j-1]),j-1,v,w)
        now=max(old,new)

        return now
    else:
        return opt(k,j-1,v,w)

def way(s,k,j,v,w,taken):
    if j==0:
        return taken
    if s != opt(k,j-1,v,w):
        taken[j-1]=1
        s = opt(k-int(w[j-1]), j - 1, v, w)
        return way(s,k-int(w[j-1]),j-1,v,w,taken)
    s = opt(k,j-1,v,w)
    return way(s,k,j-1,v,w,taken)

迭代算法在n大于30之后计算效率非常低。因此我又尝试了列表dp算法:

def table(k,v,w):
    c = numpy.zeros((k+1,len(v)+1),dtype=int)
    for i in range(len(v)+1):
        for m in range(0,k+1,1):
            if i == 0 or m==0:
                c[m][i]=0
            elif int(w[i-1])>m:
                c[m][i] = c[m][i-1]
            else:
                c[m][i]=max(int(v[i-1])+c[m-int(w[i-1])][i-1],c[m][i-1])
    return c


def table_way(r,c,table,j,w,taken):
    if j ==0:
        return taken
    elif table[r-1][c-1]!=table[r-1][c-2]:
        taken[j-1]=1
        return table_way(r-int(w[j-1]),c-1,table,j-1,w,taken)
    else:
        taken[j-1]=0
        return table_way(r,c-1,table,j-1,w,taken)

当k*n大于1500w时,计算效率也有明显下降。

根据以上问题,最后提交的作业是dp列表算法和greedy算法的组合,最终得到了51分
在这里插入图片描述

课程指路:https://www.coursera.org/learn/discrete-optimization/home/welcome

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值