人工智能-实验一策略迭代和值迭代

1.实验问题

在4x4矩阵中添加终点和障碍点,分别有一个或多个,并且满足以下属性:

终点:value值不变,始终为0,邻接点可到达用大写字母E表示

障碍点:表示该点在矩阵中“不存在”,邻接点不可到达该点,且该点没有value值跟状态,使用符号‘#’表示

以任意除以上两种结点之外的所有其它结点为起点,求解起点到终点的最短距离,存在多终点时,以相隔最近的终结点为准。

2.实验思路

1)  使用值Policy Iteration和Value Iteration算法分别计算问题产生的最佳策略

2)  设置奖励值r=-1,折扣值disc = 0.57f,使用新旧两个状态矩阵和两个Value矩阵用于迭代过程中保存状态变化和价值变化。

3) MDP模型描述:

S: 状态集合为{0…15},由4x4的矩阵S存储,状态与状态之间满足马尔可夫属性,因为当前状态可到达的状态最多四个,后继状态只受当前状态影响。

A:可采取的action集合,使用A={n,e,s,w},北东南西表示

P:状态转移概率矩阵:不在编程中显式出现,因为迭代时已知继承状态的value值

R : 因为求解最短距离,agent每行动一步可获的奖励为r=-1

γ : 折扣因子设置为 0.57,在0~1之间可调,但不能等于0或1,否则会造成无法收敛,无限循环的问题。

4) 值迭代:

a.初始化每个状态的value值为V(s) = 0;

b.然后最大化每个状态当前的value值,包括行动奖励和未来奖励,直到value值变化不明显为止

c.根据以上步骤求得的收敛值矩阵V,对每个状态遍历查找使得总奖励(行动奖励和未来奖励)最大的action,放入策略矩阵S,并打印输出。

5)策略迭代:

a.初始化V矩阵为0,状态矩阵中的每个状态随机选择四个方向之一进行初始化,并且在状态矩阵中添加障碍点’#’和终结点‘E’

b.根据选择的策略,最优化V矩阵

c.优化当前策略:如果当前策略并不使得当前状态的value值最大,那么把当前策略替换为最优策略

d如果对于所有状态,所有策略均未发生改变,那么输出当前的最佳策略,否则继续从b开始循环

3.实验结果

1)策略迭代

不同障碍及不同终节点下的收敛情况,其中 ‘#’表示障碍,‘E’表示终结点

2 )值迭代

不同障碍和终结点,折扣值为1.0

4.实验代码;

1)策略迭代:

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <set>
#include <queue>
#include <windows.h>
#include <string>

using namespace std;

const int MAX_N = 4;
const float INF = -999999999.0f;
float V[MAX_N][MAX_N];      //值矩阵
float OLDV[MAX_N][MAX_N];    //保存旧的val值
char S[MAX_N][MAX_N];      //状态矩阵,直观存储运动方向
char OLDS[MAX_N][MAX_N];   //旧的状态矩阵
char A[4] = { ‘n‘,‘e‘,‘s‘,‘w‘ };     //Action ,‘↑‘,‘→‘,‘↓‘,‘←‘
int dx[] = { -1,0,1,0 }, dy[]= { 0,1,0,-1 };  //四向移动
int r = -1;                  //奖励值
float disc = 0.57f;            //折扣值
float en = 0.00000001f;        //sub小于这个数时收敛

//  获取输出流的句柄
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);

//初始化
void init() {
    for (int i = 0; i < MAX_N; i++)
        for (int j = 0; j < MAX_N; j++) {
            S[i][j] = ‘n‘;                    //初始化为向右走
            OLDS[i][j] = ‘n‘;
        }
    OLDS[0][0] = S[0][0] = ‘#‘;
      OLDS[3][3] = S[3][3] = ‘E‘;                       //目标点    

      OLDS[2][2] = S[2][2] = ‘E‘;      //障碍
      OLDS[2][1] = S[2][1] = ‘#‘;
      OLDS[2][3] = S[2][3] = ‘#‘;

}

int getIndex(char ch) {
    switch (ch) {
    case ‘n‘:
        return 0;
    case ‘e‘:
        return 1;
    case ‘s‘:
        return 2;
    case ‘w‘:
        return 3;
    default:
        return -1;
    }
}

void printVal() {
    puts("----------------value-----------------");
    for (int i = 0; i < MAX_N; i++) {
        for (int j = 0; j < MAX_N; j++) {
            printf("%f ", V[i][j]);
        }
        puts("\n");
    }
}
void printState() {
    puts("----------------State-----------------");
    //打印策略
    for (int i = 0; i < MAX_N; i++) {
        printf("        ");
        for (int j = 0; j < MAX_N; j++) {
            switch (S[i][j]) {
            case ‘n‘:
                printf("↑  ");
                break;
            case ‘e‘:
                printf("→  ");
                break;
            case ‘s‘:
                printf("↓  ");
                break;
            case ‘w‘:
                printf("←  ");
                break;
            default:
                printf("%c   ", S[i][j]);
                break;
            }
        }
        puts("\n");
    }
}

void PolicyEvaluation(){
    float sub;
    int cnt = 0;
    do{
        sub = 0.0f;
        for (int i = 0; i < MAX_N; i++) {
            for (int j = 0; j < MAX_N; j++) {

                if (S[i][j] != ‘#‘ && S[i][j] != ‘E‘) {           //不是障碍物及终点
                    float val = V[i][j];
                    int k = getIndex(S[i][j]);       //根据状态得出移动下标
                    int x = i + dx[k], y = j + dy[k];
                    if (x >= 0 && x < MAX_N && y >= 0 && y < MAX_N && S[x][y] != ‘#‘) {
                        V[i][j] = r +  disc * OLDV[x][y];
                    }
                    sub = max(sub, fabs(val - V[i][j]));
                }
            }
       }

        //把新的val值拷贝到旧的数组中
        for (int i = 0; i < MAX_N; i++) {
            for (int j = 0; j < MAX_N; j++) {
                OLDV[i][j] = V[i][j];
            }
        }

        printf("cnt :   %d\n", ++cnt);
        printVal();

    } while (sub > en);
}

void PolicyImprovement() {

  while (true) {

    bool stable = true;
    for (int i = 0; i < MAX_N; i++) {
        for (int j = 0; j < MAX_N; j++) {
            if (OLDS[i][j] != ‘#‘ && OLDS[i][j] != ‘E‘) {
                char oldact = OLDS[i][j];
                int k = 4;
                float ma = INF;
                while (k--) {
                    int x = i + dx[k], y = j + dy[k];
                    if (x >= 0 && x < MAX_N && y >= 0 && y < MAX_N && OLDS[x][y] != ‘#‘) {
                        float round = r + disc * OLDV[x][y];
                        if (round - ma > en) {
                            ma = round;    //改变Val值
                            S[i][j] = A[k];    //改变当前状态的最佳策略
                            char ch = A[k];
                        }
                    }
                }

                if (oldact != S[i][j])
                    stable = false;
            }
        }
    }

    //将所有新状态拷贝至旧状态
    for (int i = 0; i < MAX_N; i++) {
        for (int j = 0; j < MAX_N; j++) {
            OLDS[i][j] = S[i][j];
        }
    }

    if (stable) {
       SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED);
       printf("\n--------------------------STOP-----------------------\n");

       printVal();
       SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0xA); //亮绿
       printState();
       break;
     }
     else {
        PolicyEvaluation();    //继续策略迭代
     }
   }
}

int main() {

    init();
    PolicyEvaluation();
    PolicyImprovement();
    return 0;
}

2)值迭代

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <Windows.h>

using namespace std;

const int MAX_N = 4;
const float INF = -999999999.0f;
float V[MAX_N][MAX_N];      //值矩阵
float OLDV[MAX_N][MAX_N];    //保存旧的val值
char S[MAX_N][MAX_N];      //状态矩阵,直观存储运动方向
                           //float P[MAX_N*MAX_N][MAX_N*MAX_N];    //状态转移概率矩阵
char A[4] = { ‘n‘,‘e‘,‘s‘,‘w‘ };     //Action ,‘↑‘,‘→‘,‘↓‘,‘←‘
int dx[] = { -1,0,1,0 }, dy[] = { 0,1,0,-1 };  //四向移动
int r = -1;                  //奖励值
float disc = 1.0f;            //折扣值
float en = 0.0000001f;        //sub小于这个数时收敛

 //初始化
void init() {
    for (int i = 0; i < MAX_N; i++)
        for (int j = 0; j < MAX_N; j++) {
            S[i][j] = ‘w‘;                    //初始化为向右走
        }
    S[0][2] = ‘#‘;                       //#障碍
    S[3][1] = ‘E‘;                       //E目标点
    S[2][2] = ‘#‘;
    S[1][2] = ‘E‘;
    S[1][2] = ‘#‘;
}

int getIndex(char ch) {
    switch (ch) {
    case ‘n‘:
        return 0;
    case ‘e‘:
        return 1;
    case ‘s‘:
        return 2;
    case ‘w‘:
        return 3;
    default:
        return -1;
    }
}

void printVal() {
    puts("----------------value-----------------");
    for (int i = 0; i < MAX_N; i++) {
        for (int j = 0; j < MAX_N; j++) {
            printf("%.4f ", V[i][j]);
        }
        puts("\n");
    }
}

void ValueIteration() {
    float sub = 0;
    int cnt = 0;
    do {
        sub = 0;
        for (int i = 0; i < MAX_N; i++) {
            for (int j = 0; j < MAX_N; j++) {
                if (S[i][j] != ‘#‘ && S[i][j] != ‘E‘) {           //不是障碍物及终点
                    float val = V[i][j];
                    int k = 4;
                    int ma = INF;
                    while (k--) {
                        int x = i + dx[k], y = j + dy[k];
                        if (x >= 0 && x < MAX_N && y >= 0 && y < MAX_N && S[x][y] != ‘#‘) {
                            float round = r + disc * OLDV[x][y];
                            if (ma < round) {
                                 ma = round;    //改变Val值
                            }
                        }
                    }
                    if (ma != INF)
                        V[i][j] = ma;                        //V[i][j]取得周围环境的最大值

                    sub = max(sub, fabs(val - V[i][j]));
                }
            }
        }

        //把新的val值拷贝到旧的数组中
        for (int i = 0; i < MAX_N; i++) {
            for (int j = 0; j < MAX_N; j++) {
                OLDV[i][j] = V[i][j];
            }
        }
        printf("cnt :   %d\n", ++cnt);
        printVal();

    } while (sub >= en);

    //更新最佳策略
    for (int i = 0; i < MAX_N; i++) {
        for (int j = 0; j < MAX_N; j++) {
            if (S[i][j] != ‘#‘ && S[i][j] != ‘E‘) {           //不是障碍物及终点
                int k = 4;
                int ma = INF;
                while (k--) {
                    int x = i + dx[k], y = j + dy[k];
                    if (x >= 0 && x < MAX_N && y >= 0 && y < MAX_N && S[x][y] != ‘#‘) {
                        float round = r + disc * OLDV[x][y];
                        if (ma < round) {
                            ma = round;    //改变Val值
                            S[i][j] = A[k];
                        }
                    }
                }
            }
        }
    }

    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0xA); //亮绿
    //打印策略
    for (int i = 0; i < MAX_N; i++) {
        for (int j = 0; j < MAX_N; j++) {
            char ch;
            switch (S[i][j]) {
              case ‘n‘:
                  printf("↑ ");
                  break;
              case ‘e‘:
                  printf("→ ");
                  break;
              case ‘s‘:
                  printf("↓ ");
                  break;
              case ‘w‘:
                  printf("← ");
                  break;
              default:
                  printf("%c ", S[i][j]);
                  break;
            }
        }
        puts("\n");
    }

}

int main() {

    init();
    ValueIteration();
    return 0;
}
时间: 2024-11-29 01:22:08

人工智能-实验一策略迭代和值迭代的相关文章

动态规划中 策略迭代 和 值迭代 的一个小例子

强化学习中动态规划是解决已知状态转移概率和奖励值情况下的解决方法,这种情况下我们一般可以采取动态规划中的 策略迭代和值迭代的方式来进行求解,下面给出一个具体的小例子. 原文地址:https://www.cnblogs.com/devilmaycry812839668/p/10314049.html

列表正向迭代、反向迭代要注意的问题

一.列表正向迭代取值 代码如下: 执行结果: i的取值为:0,1,2,3 二.反向迭代取值 代码如下: 执行结果: i的取值为:4.3.2.1

Python教程·迭代、可迭代对象、迭代器与生成器详解

iteration(迭代) 迭代是Python最强大的功能之一,是访问集合元素的一种方式. 只要是可迭代对象(Iterable),就可以通过for循环来遍历,这种遍历我们称为迭代. 也就是说所有可作用于for循环的对象都是可迭代对象(Iterable). 那么,如何判断一个对象是可迭代对象呢?方法是通过collections模块的Iterable类型判断: >>> from collections import Iterable >>> isinstance(123,I

多线性方程组迭代算法——Jacobi迭代算法的Python实现

多线性方程(张量)组迭代算法的原理请看这里:若想看原理部分请留言,不方便公开分享 Gauss-Seidel迭代算法:多线性方程组迭代算法——Gauss-Seidel迭代算法的Python实现 import numpy as np import time 1.1 Jacobi迭代算法 def Jacobi_tensor_V2(A,b,Delta,m,n,M): start=time.perf_counter()#开始计时 find=0#用于标记是否在规定步数内收敛 X=np.ones(n)#迭代起

多线性方程组迭代算法——Gauss-Seidel迭代算法的Python实现

多线性方程组(张量)迭代算法的原理请看这里:原理部分请留言,不方便公开分享 Jacobi迭代算法里有详细注释:多线性方程组迭代算法——Jacobi迭代算法的Python实现 import numpy as np import time 1.1 Gauss-Seidel迭代算法 def GaussSeidel_tensor_V2(A,b,Delta,m,n,M): start=time.perf_counter() find=0 X=np.ones(n) d=np.ones(n) m1=m-1 m

解决python疑难杂症—什么是迭代协议、迭代对象和迭代器?

什么是迭代协议 只要某个类型(类)定义了iter()和next()方法就表示支持迭代协议. iter()需要返回一个可迭代对象.只要定义了iter()就表示能够通过for/in/map/zip等迭代工具进行对应的迭代,也可以手动去执行迭代操作. 1 for x in Iterator 2 X in Iterator 同时,可迭代对象还可以作为某些函数参数,例如将可迭代对象构建成一个列表list(Iterator)来查看这个可迭代对象会返回哪些数据: L = list(Iterator) 需要注意

人工智能实验报告

课程名称: 人工智能         班级: 13 级计本     实验日期:   5 月5日 学号: 136201010496   姓名:  茅智强        成绩:  一.实验名称 线性回归预测系统 二.实验目的及要求 理解和掌握线性回归预测的基本方法,能够编程实现简单的线性回归预测系 统. 1.熟悉 Octave 编程语言: 2.线性回归预测函数.代价函数的设计和实现: 3.使用梯度下降算法进行参数学习 三.实验工具 Octave   notepad++ 四.实验内容与步骤 1.安装编

13计本人工智能实验报告

          贵州师范大学计算机科学与技术 实验报告               课程名称:人工智能         班级:13计本     实验日期:2016-4-27 学号:136201010507    姓名:任廷婷      成绩: 一·实验名称 线性回归预测系统 二·实验目的及要求 理解和掌握线性回归预测的基本方法,能够编程实现简单的线性回归预测系统 1.熟悉matlab 2.线性回归预测函数,代价函数的预测和实现 3.使用梯度下降算法进行参数学习 三·实验工具 Matlab,O

数据结构实验:计算表达式的值--顺序栈

实验题目:栈的应用-算术表达式求值 实验环境:    Visual C++ 6.0                   实验目的 : 1 .掌握栈的定义及实现: 2 .掌握利用栈求解算术表达式的方法. 实验内容: 通过修改完善教材中的算法3.4,利用栈来实现算术表达式求值的算法.对算法3.4中调用的几个函数要给出其实现过程: (1) 函数In(c):判断c是否为运算符: (2) 函数Precede(t1,t2):判断运算符t1和t2的优先级: (3) 函数Operate(a,theta,b):对