chrome浏览本地页面发生Failded to load file

有时候从网上下载一堆静态页面, 在本地打开, 如果你用的是chrome(别的应该也不行), 会遇到错误:Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https. 这种问题其实是chrome的安全机制, 不允许网页访问本地的文件. 有一种解决方案是禁用chrome的安全机制, 但是风险显而易见就是chrome不安全了. 其实, 本地查看静态页面, 最好的方式就是开启一个静态页面的服务器, 看似复杂, 其实就一条命令搞定.

Read More

python win32com开发office插件时问题汇总

####

事先我用如下代码开发并注册了一个COM:

1
2
3
4
5
6
7
8
9
10
11
12
import pythoncom
class PythonUtilities:
_public_methods_ = [ 'add_watermark' ]
_reg_progid_ = "PythonDemo.Utilities"
# NEVER copy the following ID
# Use "print pythoncom.CreateGuid()" to make a new one.
_reg_clsid_ = "{B7E3EE50-5E2A-4044-8241-4F76B1DAB885}"
if __name__=='__main__':
print( "Registering COM server...")
import win32com.server.register
win32com.server.register.UseCommandLine(PythonUtilities)

在python种使用win32com.client.Dipatch可以调用该COM, 但是在VBA种却报错:specific module coundn't be found:

1
2
3
4
5
Sub Test()
' Create the Python COM objects.
Set stringmod = CreateObject("PythonDemo.Utilities")
' Call string.split
End Sub

解决方法就是, 没有找到pythoncom35.dllpywintypes35.dll这两个DLL导致的.

这两个文件位于Lib/site-packages/pywin32_system32下, 把他们复制到pythondir/Scripts这个文件夹下就行了. 因为通常这个文件夹是添加到环境变量Path种的.

有啥问题可以直接在下面留言奥.

jupyter notebook 扩展开发之 文件保存钩子

这是jupyter notebook 插件开发的系列文档之一, 文章最末尾列出了这个系列的所有博客连接.

Read More

jupyter notebook 扩展开发之 Custom bundler extensions

这是jupyter notebook 插件开发的系列文档之一, 文章最末尾列出了这个系列的所有博客连接.

Read More

jupyter notebook扩展开发之前端插件开发

这是jupyter notebook 插件开发的系列文档之一, 文章最末尾列出了这个系列的所有博客连接.

Read More

jupyter notebook 扩展开发之内容API

这是jupyter notebook 插件开发的系列文档之一, 文章最末尾列出了这个系列的所有博客连接.

Read More

jupyter notebook 扩展开发之自定义请求处理程序

这是jupyter notebook 插件开发的系列文档之一, 文章最末尾列出了这个系列的所有博客连接.

Read More

jupyter notebook 扩展开发之 将Jupyter扩展作为Python包分发

这是jupyter notebook 插件开发的系列文档之一, 文章最末尾列出了这个系列的所有博客连接.

Read More

求取最小二范数解的具体过程

推导一遍案例中求取最小二范数解的具体过程

Read More

Q-learning人工智能玩推箱子小游戏

基本已知条件

1, 舞台情景: 16x16的方格, 游戏中用一个16x16的矩阵表示, 如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 第一关的数据
levels[0]=[
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0],
[0,0,0,0,0,0,1,2,1,0,0,0,0,0,0,0],
[0,0,0,0,0,0,1,0,1,1,1,1,0,0,0,0],
[0,0,0,0,1,1,1,3,0,3,2,1,0,0,0,0],
[0,0,0,0,1,2,0,3,4,1,1,1,0,0,0,0],
[0,0,0,0,1,1,1,1,3,1,0,0,0,0,0,0],
[0,0,0,0,0,0,0,1,2,1,0,0,0,0,0,0],
[0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]];
//...

下图是第一关真实场景.

round01.png

看这个数据, 对照实际图, 可以知道各个单元格数字代表的意义:

  • 0 代表空格
  • 1 代表树, 是推不动的
  • 2 代表目标位置
  • 3 代表箱子
  • 4 代表悟空

游戏的规则就是控制悟空, 推动箱子, 最终把所有箱子放置到目标位置.

设计思路

不知道Qlearning的请自行搜索相关理论, 我这里假设你已经知道了Qlearning.

Qlearning中最重要的两个概念: State和Action. State表示游戏状态, Action表示可能采取的动作.

Qlearning种的两个最重要的矩阵: R矩阵和Q矩阵.

先来说Q矩阵:

在推箱子游戏中, State有多少种? 计算过程如下:

- 游戏场地的方格数: 16x16
- 每个方格可能的情况: 5
- 假设每个方格的情况是相互独立的(不考虑一个游戏只可能有一个悟空等情况)
- count(state) = 5^(16x16)

这是个很大的数字, 显然这种方法不合适构建Q矩阵. 但是我们知道, 这种算法是不严谨的, 不可能有这么多情况, 还有很多已知条件没有考虑. 但是我并不想考虑那么多, 怎么办?

我们建立一个State和Action的映射字典Q = {state->actions}. 遇到一种state的时候, 先去Q中查找有没有这种情况出现过, 如果没有, 我们假设actions={上:0, 下:0, 左:0, 右:0}, 也就是假设所有的行为都等价. 并把state->actions作为一个键值对存入字典. 下次再遇到这种情况, 就可以更新里面的值了. 所以初始的Q字典只是一个空字典而已.

那么R矩阵怎么得到? 也就是说怎么决定悟空的每一步奖励值.

我们不妨设默认初始值都是-1, 因为我们不管悟空往哪里走, 我们不想让悟空移动太多. 同时每次action总会有产生一些后果, 每种后果都会有不同的奖励值.

- 如果悟空推树, 奖励值是-10, 树怎么能推动呢?
- 如果什么都没有推, 只是移动了一下, 奖励值是默认值-1
- 如果推箱子奖励值是-2, 因为移动箱子是很危险的, 要谨慎
- 如果把箱子推到了目标位置, 奖励10
- 如果任务成功, 所有箱子都达到了目标位置, 奖励是1000
- 如果任务失败(箱子不能推/或被困住), 奖励是-1000

前5条都好办, 但是我们如何识别任务失败呢? 为了思考简单些, 我们定义失败为:

- 有一个箱子不能再推动, 但是所在位置又不是目标位置; 
- 所有箱子不能再被推动(箱子的对面都是空的才能被推动)
- 走了1w步还没有完成任务. 

那么怎么定义一个箱子无法被推动呢? 我们简单的认为两个挨着的面都是树, 也就是卡在角落里了. 这种定义不太严谨, 有时候一堆箱子堆在一起不能动也算失败, 但是我们程序写起来就难了, 所以不能这么定义.

所以我们这样来计算任务是否失败:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function failed(matrix){
// 找到所有箱子及其坐标
boxes=[]
for (let i=0;i<matrix.length;i++){
row = matrix[i];
up_row = matrix[i-1] or []
below_row = matrix[i+1] or []
for(let j=0;j<row.length;j++){
me = row[j]
around=[below_row[j], row[j-1], up_row[j], row[j+1], below_row[j]]
if (me==3){
// 有一个箱子不能再推动, 但是所在位置又不是目标位置;
for(let c=0;c<4;c++){
if(around[c]==1 or around[c]==3)
}
}
}
}
}