人智大作业-四子棋实验报告

题目大意

带重力的四子棋(连成4个(横竖斜)胜利)

大致算法

预测:朴素搜索

通过判定一个必胜态的后继状态存在对手必败态,一个必败态后继状态必须全是对手必胜态。实现搜索算法,搜索深度可以达到6层左右。

朴素搜索只能对于短期一定必胜、必败的状态进行判断,故可用于

  1. 蒙特卡罗树新增一个节点时,如果该节点胜负短期可判,则不使用随机游走,而直接将固定胜率\败率100%返回
  2. 决策时跑预测防止出现一些蒙特卡洛故意走向一个必败态的情况

估值:随机下子

估计一个局面的情况可以通过随机下子的方式,双方随机在可能的位置等概率下子,判断最后谁胜,将随机下子次数增加可以非常“不准确”的估计出当前局面对谁有优势

决策:蒙特卡洛搜索树

对于上述算法,在短期无法判断局面的时候很难决策如何下子,因此使用信心上限树算法(UCT).

     $$I_j = X_j + \sqrt{\frac{2ln(n)}{T_j(n)}}$$

通过上面的式子得出决策树上每一个位置的信心上限[latex]I_j[\latex],其中n表示总的尝试次数,

    \[$T_j$\]

表示第j个状态(及其子状态)尝试次数。

显然,每次尝试I值最大的状态可以平衡所有状态的最小尝试次数以及对较优状态的多次尝试。

程序表现

与样例程序进行对抗,分数大约在30/200分左右。

一些细节

  1. 蒙特卡洛树的决策最好选择访问次数最多的而非期望权值最大的那一个,因为蒙特卡洛每次都会拓展期望权值L最大的那一个,并有一定概率使其变小。换句话说,蒙特卡洛的决策在某种意义下就是平衡L值得过程,所以L值并不能代表一个状态的优劣
  2. 比较神奇的是有些时候迭代次数较多的程序表现没有迭代次数较少的程序,可能是因为常数没有调好……
  3. 曾经尝试在随机游走的时候加入深度较小的特判,使得双方“稍微”有一点智能,但是发现这样会导致结果基本是平局
  4. 最开始程序使用new分配内存,然而Compete程序多次调用会出现segmentation fault,单独调用无误,改为预先分配就没有问题了。不知道是否和电脑的垃圾回收机制有关系。

makefile学习笔记&C++编译

静态链接库创建

  1. ar -rv maze.a BaseRouter.o ,将BaseRouter.o加入maze.a这个静态链接库中
  2. ranlib maze.a ,更新静态链接库符号表
  3. 库文件一般将.cpp改成.cxx

makefile笔记

  1. .PHONY: clean  表示clean为伪目标,否则如果文件夹下有clean文件会出错
  2. 而命令中的<</span> 和<span class="lang:default decode:true crayon-inline ">@ 则是自动化变量,<</span> 表示所有的依赖目标集(也就是<span class="lang:default decode:true crayon-inline ">BaseRouter.cxx</span> ),<span class="lang:default decode:true crayon-inline ">@ 表示目标集(就是BaseRouter.o ),参见样例1
  3. makefile在target为.o的时候,dependence可以自动省略.cc,可以使用类似于main.o : defs.h 的语法
  4. makefile只会完成第一个规则的第一个目标
  5. (objects)</span> 只是单纯的变量展开,一般表现为多条命令都是由于多目标的生成</li> </ol> <h3>样例</h3> <h4>OOPWeek9_Makefile</h4> <pre class="lang:default decode:true" title="makefile">lSOURCES=(wildcard *.cxx)
    sSOURCES=(wildcard *.cpp) HEADERS=(wildcard *.h)
    lOBJECTS=(lSOURCES:%.cxx=%.o) sOBJECTS=(sSOURCES:%.cpp=%.o)
    TARGET=maze.exe
    LIB=maze.a

    all: (TARGET)(LIB)
    (TARGET):(sOBJECTS) (HEADERS)(LIB)
    @echo “Now Generating (TARGET) ..." 	g++(sOBJECTS) (LIB) -o(TARGET)
    (LIB):(lOBJECTS) (HEADERS) 	@echo "Now Generating(LIB) …”
    ar -rv (LIB)(lOBJECTS)
    ranlib (LIB) %.o: %.cpp(HEADERS)
    @echo “Now Compiling < ..." 	g++ -c< -o @ %.o: %.cxx(HEADERS)
    @echo “Now Compiling < ..." 	g++ -c< -o @ clean: 	rm *.o *.exe *.bak *.a explain: 	@echo "Lib Sources:(lSOURCES)”
    @echo “User Sources: (sSOURCES)" 	@echo "Lib Objects:(lOBJECTS)”
    @echo “User Objects: (sOBJECTS)" 	@echo "Lib:(LIB)”
    @echo “Target: $(TARGET)”

    BaseRouter.cxx	BaseRouter.h	OptRouter.h	main.cpp	makefile

     

Tmux学习笔记

相关链接

tmux入门教程:http://blog.jobbole.com/87278/,http://blog.jobbole.com/87584/

一些感悟

网上教程之所以看起来比较痛苦,主要是没有讲清楚session的含义,让我误认为一个窗口就是一个session,浪费了许多时间,实际上session可以理解为一个场景,在这个场景中一般你就是要写一个工程,故同一个session中可以开多个窗口,而一般不存在session切换的问题。

常用命令

#窗格
Ctrl-b % #纵分
Ctrl-b " #橫分
Ctrl-b + <方向键> #切换
Ctrl-b Ctrl+<方向键> #调整大小
#窗口
Ctrl-b c #新建窗口
Ctrl-b <num_id> #切换窗口
Ctrl-b , #重命名
#会话
tmux ls & ctrl-b s #显示所有会话
tmux new -s session-name #新建会话
tmux attach  #attach接入会话
tmux detach  #detach断开会话

一些问题

  1. 错误sessions should be nested with care, unset $TMUX to force:
    个人理解是说必须先detach当前的session再attach新的session,否则就成了嵌套关系,是tmux里面不推荐的。实际上这个问题就是对session理解不够导致的,参见前文
  2. tmux导致vim的分栏不能通过鼠标拖动了,需要使用命令调整宽度
resize +N #高度+N
vertical resize +N #宽度+N

 

Flask学习笔记

各种链接

官方文档:http://docs.jinkan.org/docs/flask/,*有一点点枯燥……

教程:http://www.pythondoc.com/flask-mega-tutorial/index.html,*一个写的不错的民间教程,一步步介绍了怎么建立一个工程,对于代码结构有讲解

flask-WTF:http://docs.jinkan.org/docs/flask-wtf/,*flask表单库

jinjia2文档:http://docs.jinkan.org/docs/jinja2/

jinjia教程:https://zhuanlan.zhihu.com/p/23669244

flask-bootstrap:http://pythonhosted.org/Flask-Bootstrap/,*一个把flask和bootstrap结合的库

bootstrap官网:http://v3.bootcss.com/getting-started/,*里面有很多模板

Step1. virtualenv

道理我都懂,然而这tm到底有啥用啊……安装了那么多年的包,还没见过冲突的,而且我电脑里面python的包不就是venv里面的包么?外面如果要冲突里面就不了?最重要的是界面还那么丑……

其中一点比较有趣的是. bin/activate 命令激活venv虚拟环境,其中点和source命令相似,将bin目录下activate这个bash文件导入,bash文件中将bin目录路径加在了PATH命令之前,已完成重定向python相关路径.

Step2. Hello World

照着链接2一步一步写,比较有趣的一点是工程的架构。

这是官方文档的HelloWorld

from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'Hello World!'

if __name__ == '__main__':
    app.run()

这是工程化的Helloworld目录架构

app
|-- __init__.py
|-- static
|-- templates
|   `-- index.html
`-- views.py
run.py

__init__.py

from flask import Flask

app = Flask(__name__)
from app import views

views.py

from app import app

@app.route('/')
@app.route('/index')
def index():
    return "Hello, World!"

run.py

#!venv/bin/python
from app import app
app.run(debug = True,host='0.0.0.0')

by the way,里面的循环引用关系实在是没有弄懂

Step3.服务器编写

 

jinjia2

jinjia2是flask的渲染引擎,自动在app/templates里面搜寻模板文件。

Bootstrap

flask里面的bootstrap貌似比一般nodejs啥的要简单一些,不需要自己配置static文件,直接pip install flask-bootstrap 即可。

将__init__.py改写为

from flask import Flask
from flask_bootstrap import Bootstrap

app = Flask(__name__)
Bootstrap(app)
app.config.from_object('config')

from app import views

注意,之前将Bootstrap(app) 放在run.py中出现了问题,可能是import views的问题

发现现在debug模式没法及时刷新了……不知道啥原因

Docker通过Nginx容器实现域名转发

有些时候一台服务器上面需要架设多个网站,而同一个服务器又只有一个80端口,所以这是一个非常麻烦的事……

我在docker里面架设了两个wordpress,希望分别通过a.com和b.com转发到不同的容器中。

首先大致介绍一下nginx的转发配置

server {
    listen       80;
    server_name blog.mhy12345.xyz;

    location / {
		proxy_pass      http://wordpress_wordpress;
		proxy_set_header    Host host; 		proxy_set_header    X-Real-IPremote_addr;
		proxy_set_header    X-Forwarded-Proto http;
		proxy_set_header Connection keep-alive;
        proxy_connect_timeout   150;
        proxy_send_timeout  100;
        proxy_read_timeout  100;
        proxy_buffers       4 32k;
        client_max_body_size    8m;
        client_body_buffer_size 128;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

监听blog.mhy12345.xyz:80,对于任意的路径,转发到地址:http://wordpress_wordpress,后面那几行都在转发过程中修改header,具体是不是有用我也不知道。这个内容复制两遍,放入Nginx对应位置(/etc/nginx/conf.d/default.conf),就可以实现对于两个容器的转发了。

顺便给一下docker-compose.yml的写法

nginx-host:
        container_name: nginx-host
        image: nginx-host-image
        external_links:
                - wordpress_wordpress:wordpress_wordpress
                - hahaha_wordpress:hahaha_wordpress
        ports:
                - 80:80

这里解释了为什么之前的URL是http://wordpress_wordpress,这是由于docker内部容器链接的dns设置了wordpress_wordpress的ip地址。

参考:http://www.cnblogs.com/Jarvin/p/5796193.html

当然,这一部分相当糟糕,原因是:

缓存!

是的,就是这东西,缓存!

docker的image创建有缓存,这个可以直接通过添加–no-cache参数

docker build ./Image --no-cache -t nginx-host-image

解决。

还有更可怕的是“浏览器缓存”

谁tm想得到浏览器会把跳转页面缓存下来啊……

每次输入http://blog.mhy12345.xyz ,自动重定向到https://blog.mhy12345.xyz:8022 ,根本找不出哪里有问题……

最后吐槽腾讯云学生机真是坑,一个G内存,5个docker容器就撑爆了……之后扩成两个G,然后月租上百了……

Ipython Notebook 使用方法

ipython notebook是个人认为使用python处理课题研究的非常方便的工具。

使用浏览器巧妙解决了远程服务器编程的难题,真不知道设计者是怎么脑洞出来的。

而notebook的核心思想是维护一系列cell,每一个cell里面一句python语句,你可以非常方便的跳转到不同的cell执行下一句话。

下面简单总结一下常用的快捷键

编辑/运行块

Enter 编辑当前块
Alt-Enter 运行块,下方插入

复制粘贴块

X 剪切块
C 复制块
V 粘贴块

分裂合并块

Shift+M 合并当前块与下一块
Ctrl+Shift+- 按光标位置分割当前块

 

Tensorflow学习笔记1-源码学习

TensorFlow 编译

tensorflow可以通过pip安装,也可以通过源码安装,其中pip安装直接

[ccei]pip3 install tensorflow[/ccei]

即可

基于源码的安装教程在https://www.tensorflow.org/install/install_sources 可找到,核心难点在于处理包的依赖问题

[ccei]sudo pip install six numpy wheel
brew install coreutils[/ccei]

运行./configure检查是否完全安装依赖库

TensorFlow 使用

使用tensorflow解决MNIST问题

[cce_python]
import input_data
import tensorflow as tf

mnist = input_data.read_data_sets("data/",one_hot=True)
sess = tf.InteractiveSession()
x = tf.placeholder("float", shape=[None, 784])
y_ = tf.placeholder("float", shape=[None, 10])
W = tf.Variable(tf.zeros([784,10]))
b = tf.Variable(tf.zeros([10]))
sess.run(tf.global_variables_initializer())
cross_entropy = -tf.reduce_sum(y_*tf.log(y))
train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)
for i in range(1000):
    batch = mnist.train.next_batch(50)#随机选择50个
    train_step.run(feed_dict={x: batch[0], y_: batch[1]})
correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))


print(accuracy.eval(feed_dict={x: mnist.test.images, y_: mnist.test.labels}))
[/cce_python]

具体每一个函数都是干嘛的太麻烦,就不写了,反正代码也不是我写的,网上一查一大堆……

Ubuntu 16.04 & Docker 搭建 WordPress

我承认在半期考试前搭博客是非常颓,不过,whatever……

有尝试下载apache2+php+mysql的标准安装包安装方式,最后还是放弃了。大概原因是服务器上本身已经装了一些东西,各种安装包依赖关系炸了,最后直接把服务器整挂了>_<

之后突然想到,docker不就是用来隔离环境,解决各种冲突的么,是不是wordpress可以在docker里面搭?事实证明,在外部包爆炸后,docker内部也会受影响,在docker里面pull了mysql竟然都运行不了。各种调错未果之后,果断重装了服务器。果真在新系统下一切ok……

之后就相当简单,在dockerhub上面我们可以发现已经有一个叫做wordpress的镜像,而且有详细的安装说明,其中使用到了一个叫做的docker-compose工具,可以一键创建多个容器:

[cce]
wordpress:
    image: wordpress
    ports:
        - "80:80"
    environment:
        WORDPRESS_DB_PASSWORD: .....
    links:
        - mysql:mysql
mysql:
    image: mysql
    environment:
        MYSQL_ROOT_PASSWORD: .....
[/cce]

大概就是建立两个容器,分别是数据库mysql和wordpress,然后wordpress连接mysql

由于实在太简单,也没啥好说的了