‘МІНІСТЕРСТВО ОСВІТИ І НАУКИ УКРАЇНИ
НАЦІОНАЛЬНИЙ УНІВЕРСИТЕТ „ЛЬВІВСЬКА ПОЛІТЕХНІКА”
/
Лабораторна робота №4
з дисципліни " Теорія інтелектуальних систем"
на тему:
«Дослідження та моделювання марківського процесу прийняття рішень (Markov Decision Process, MDP)»
Львів 2017
Мета: Дослідити модель марківського процесу прийняття рішень (Markov Decision Process, MDP).
Порядок виконання роботи
1. Реалізувати модель марківського процесу прийняття рішень (Markov Decision Process, MDP) (кількість станів обрати згідно варіанту).
2. Реалізувати модель взаємодії агента з середовищем у вигляді марківського процесу прийняття рішень (кількість доступних агенту дій обрати згідно варіанту). Модель оптимальної поведінки (цільова функція): сумарний виграш з відступаючим горизонтом (receding-horizon model).
3. Реалізувати алгоритм роботи "ідеального" агента (агента, який володіє повною інформацією про характеристики середовища) для випадку марківського процесу прийняття рішень.
4. Реалізувати програму обчислювального експерименту по дослідженню моделі взаємодії агента з стаціонарним випадковим середовищем.
5. Провести обчислювальний експеримент. Отримати усереднені залежності значень цільової функції від часу для 1) випадкового агента та 2) "ідеального" агента.
6. Порівняти отримані залежності та зробити висновки.
Варіант: №2
N
Кількість станів MDP
Кількість доступних агенту дій
2
3
3
Код програми:
// tis.lab4.2016
// lab4.c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <tchar.h>
#include <math.h>
#define ENVTYPE 1
#define NACTIONS 3
#define NSTATES 3
#define NSTEPS 500
#define NREPLICAS 1000
#define REWARD 10//+1
#define PENALTY 0//-1
#define RLTYPE 5 //3 //4
#define RLEPSILON 0.1f
#define RLTAU 0.12f
// ---------------------------------------
// global parameters and values
int t; // current time step
int T = NSTEPS; // number of time steps = number of interactions between agent and environment
int n = NREPLICAS; // number of replicas
int nA = NACTIONS; // number of actions
int nS = NSTATES;// number of states
// ---------------------------------------
// environment
int env = 1; // type of environment:
// env = 0 -> se (stationary environment)
// env = 1 -> mdp
float sePa[NACTIONS];// se: probabilities of rewards for each action
int ceState; // ce: current state of commutative environment
float cePa[NSTATES][NACTIONS]; // ce: probabilities of reward for each action for each state of environment
float cePs[NSTATES][NSTATES]; // ce: probabilities of transition from one state to another
int mdpState;
int mdpR[NSTATES][NACTIONS];
float mdpT[NSTATES][NACTIONS][NSTATES];
// ---------------------------------------
// agent
int agt ; // type of agent:
// agt = 0 -> random agent
// agt = 1 -> perfect agent
// agt = 2 -> greedy RL
// agt = 3 -> epsilon-greedy RL
// agt = 4 -> softmax action selection
// agt = 5 -> TD(0)
// agt = 6 -> Q-learning
int action = 0; // current action = {0, ... ,(nA-1)}
int response; // current response of environment = {0;1}/{-1;+1}
int paction[NSTATES]; // actions of perfect agent (per state) (MDP)
float gammaVI = 0.1f; // learning rate for value iteration (MDP)
float e = RLEPSILON; // epsilon value (epsilon-greedy RL)
float tau = RLTAU; // tau value (softmax action selection)
float k[NSTATES][NACTIONS]; // number of realizations for each action
float r[NSTATES][NACTIONS]; // total reward for each action
float Q[NSTATES][NACTIONS]; // estimated action value Q[i]=r[i]/k[i] for each action;
float p[NACTIONS]; // selection probability for each action (softmax);
int mdpPrevState;// previous state of MDP
// ---------------------------------------
// results for current replica
float sumR; // total reward over time sumR(t)
float avrR; // average reward over time avrR(t) = sumR(t)/t
// ---------------------------------------
// tabulated results
float _sumR[NSTEPS][NREPLICAS];
float _avrR[NSTEPS][NREPLICAS];
// ---------------------------------------
// final simulation results
float sumRm[NSTEPS]; // mean values of sumR(t)
float sumRv[NSTEPS]; // corresponding variances
float avrRm[NSTEPS]; // mean values of avrR(t)
float avrRv[NSTEPS]; // corresponding variances
// ---------------------------------------
// files for parameters and results
char * par_file_name = "d:\\lab4.parameters.txt";
FILE * par_file;
char * RA_res_file_name = "d:\\lab4.RA.results.txt";
FILE * RA_res_file;
char * PA_res_file_name = "d:\\lab4.PA.results.txt";
FILE * PA_res_file;
// ---------------------------------------// uniform discrete probability distribution
int uRand(int x)
{
int _rnum = (int)((float)x * (float)rand() / (float)RAND_MAX);
return _rnum;
}
// ---------------------------------------
// discrete probability distribution specified by probabilities from <_array>
int dRand(float* _array, int size)
{
int _rnum = size - 1;
float _left = 0;
float _right = _array[0];
float ftmp = (float)rand() / (float)RAND_MAX;
for (int i = 0; i < size - 1; i++)
{
if ((ftmp >= _left) && (ftmp < _right)) { _rnum = i; break; }
_left = _right;
_right += _array[i + 1];
}
return _rnum;
}
// ---------------------------------------
// initialization of stationary environment
void seInit(void)
{
for (int i = 0; i < nA; i++)
sePa[i] = (float)rand() / (float)RAND_MAX;
}
// ---------------------------------------
// response of stationary environment
int seResponse(void)
{
int _r;
float rnum = (float)rand() / (float)RAND_MAX;
if (rnum < sePa[action]) _r = REWARD;
else _r = PENALTY;
return _r;
}
// ---------------------------------------
// initialization of mdp
void mdpInit(void)
{
int i, j, v;
int maxReward = REWARD;
float _sum1, _sum2;
// probabilities of rewards
for (i = 0; i < nS; i++)
for (j = 0; j < nA; j++)
mdpR[i][j] = uRand(maxReward);
// probabilities of state transition
for (i = 0; i < nS; i++)
for (j = 0; j < nA; j++)
{
_sum1 = 0;
_sum2 = 0;
for (v = 0; v < nS; v++)
{
mdpT[i][j][v] = (float)rand() / (float)RAND_MAX;
_sum1 += mdpT[i][j][v];
}
for (v = 0; v < nS - 1; v++)
{
mdpT[i][j][v] = mdpT[i][j][v] / _sum1;
_sum2 += mdpT[i][j][v];
}
mdpT[i][j][nS - 1] = 1.0f - _sum2;
}
// initial state
mdpState = uRand(nS);
}
// ---------------------------------------
// response of mdp & state transition
int mdpResponse(void)
{
int _r;
// get response in current state
_r = mdpR[mdpState][action];
// commutate states
mdpState = dRand(mdpT[ceState][action], nS);
return _r;
}
// ---------------------------------------
// environment
int environment(int _en)
{
int _r = 0;
switch (_en)
{
case 0: _r = seResponse(); break;
case 1: _r = mdpResponse(); break;
default: printf("lab3 error: wrong env code specified\n");
}
return _r;
}
// ---------------------------------------
// save parameters in file
void saveParameters(void)
{
int i, j, v;
if ((par_file = fopen(par_file_name, "w")) == NULL) {
fprintf(stderr, "Cannot open file <%s> for parameters of experiment.\n", par_file_name);
}
fprintf(par_file, "T = %d\n", T);
fprintf(par_file, "n = %d\n", n);
fprintf(par_file, "env = %d\n", env);
fprintf(par_file, "nA = %d\n", nA);
if (env) fprintf(par_file, "nS = %d\n", nS);
fprintf(par_file, "====================\n");
switch (env)
{
case 0: // se (stationary environment)
for (i = 0; i < nA; i++)
fprintf(par_file, "p(a%d) = %f\n", i, sePa[i]);
break;
case 1: // mdp
// values of reward function
for (i = 0; i < nS; i++)
{
for (j = 0; j < nA; j++)
fprintf(par_file, "R(s%d,a%d) = %d\n", i, j, mdpR[i][j]);
if (i < nS - 1) fprintf(par_file, "--------------------\n");
}
fprintf(par_file, "\n====================\n");
// probabilities of state transition (values of the state transition function)
for (i = 0; i < nS; i++)
{
for (j = 0; j < nA; j++)
{
for (v = 0; v < nS; v++)
fprintf(par_file, "T(s%d,a%d,s%d) = %f\n", i, j, v, mdpT[i][j][v]);
fprintf(par_file, "--------------------\n");
}
}
break;
default: printf("lab3 error: wrong env model code specified\n");
}
fclose(par_file);
}
// ---------------------------------------
// save results of random agent
void saveResultsRA(void)
{
int i;
if ((RA_res_file = fopen(RA_res_file_name, "w")) == NULL)
fprintf(stderr, "Cannot open file <%s> for experimental results.\n", RA_res_file_name);
for (i = 0; i < T; i++)
fprintf(RA_res_file, "%f,%f,%f,%f\n", sumRm[i], sumRv[i], avrRm[i], avrRv[i]);
fclose(RA_res_file);
}
// ---------------------------------------
// save results of perfect agent
void saveResultsPA(void)
{
int i;
if ((PA_res_file = fopen(PA_res_file_name, "w")) == NULL)
fprintf(stderr, "Cannot open file <%s> for experimental results.\n", PA_res_file_name);
for (i = 0; i < T; i++)
fprintf(PA_res_file, "%f,%f,%f,%f\n", sumRm[i], sumRv[i], avrRm[i], avrRv[i]);
fclose(PA_res_file);
}
// ---------------------------------------
// return maximum value from <_array> of <size> elements
float max(float* _array, int size)
{
int _arg = uRand(size);
float _max = _array[_arg];
for (int i = 0; i < size; i++)
if (_array[i] > _max) _max = _array[i];
return _max;
}
// ---------------------------------------
// return index of maximum value in <_array> of <size> elements
int argmax(float* _array, int size)
{
int _arg = uRand(size);
float _max = _array[_arg];
for (int i = 0; i < size; i++)
if (_array[i] > _max) { _max = _array[i]; _arg = i; }
return _arg;
}
// ---------------------------------------
// init perfect agent (for MDP)
void initPerfectAgent(void)
{
int i, j, z;
float sum = 0.0f, V[10], Qsa[100][100];
// perform value iteration --> optimal value function V*(s)
for (z = 0; z < nS; z++) V[z] = 1.0f;
for (t = 0; t < T * 30; t++)
{
for (i = 0; i < nS; i++)
{
for (j = 0; j < nA; j++)
{
sum = 0.0f;
for (z = 0; z < nS; z++) sum = sum + mdpT[i][j][z] * V[z];
Qsa[i][j] = mdpR[i][j] + gammaVI * sum;
}
V[i] = max(Qsa[i], nA);
}
}
// determine the optimal policy given the optimal value function
for (i = 0; i < nS; i++)
{
for (j = 0; j < nA; j++)
{
sum = 0.0f;
for (z = 0; z < nS; z++) sum = sum + mdpT[i][j][z] * V[z];
Qsa[i][j] = mdpR[i][j] + gammaVI * sum;
}
paction[i] = argmax(Qsa[i], nA);
}
}
// ---------------------------------------
// init agent
void initAgent(int _ag)
{
// int i;
switch (_ag)
{
case 0: break;
case 1: initPerfectAgent(); break;
default: printf("lab3 error: wrong agent code specified\n");
}
}
// ---------------------------------------
// random agent
int randomAgent(void)
{
return uRand(nA);
}
// ---------------------------------------
// perfect agent (for MDP)
int perfectAgent(void)
{
return paction[mdpState];
}
// ---------------------------------------
// agent
int agent(int _ag)
{
int _a = 0;
switch (_ag)
{
case 0: _a = randomAgent(); break;
case 1: _a = perfectAgent(); break;
default: printf("lab3 error: wrong agent code specified\n");
}
return _a;
}
// ---------------------------------------
// simulation
void simulation(int _i)
{
initAgent(agt);
sumR = 0.0f;
avrR = 0.0f;
for (t = 0; t < T; t++) {
// get action of agent
action = agent(agt);
// get response of environment
response = environment(env);
// calculate cumulative results
sumR = sumR + (float)response;
// save results
_sumR[t][_i] = sumR;
}
}
// ---------------------------------------
// get mean values of simulation results
void getMeanValues(void)
{
for (t = 0; t < T; t++)
{
float tmps1 = 0.0f;
float tmps2 = 0.0f;
for (int i = 0; i < n; i++)
{
tmps1 += _sumR[t][i];
}
sumRm[t] = (float)tmps1 / (float)n;
}
}
// ---------------------------------------
// get variances of simulation results
void getVarianceValues(void)
{
for (t = 0; t < T; t++)
{
float tmps1 = 0.0f;
float tmps2 = 0.0f;
for (int i = 0; i < n; i++)
{
tmps1 += (sumRm[t] - _sumR[t][i]) * (sumRm[t] - _sumR[t][i]);
}
sumRv[t] = (float)tmps1 / (float)(n - 1);
}}
// ---------------------------------------
// main
int main(int argc, char* argv[])
{
int i;
// init random-number generator
srand((unsigned)time(NULL));
// init environment
mdpInit();
// save parameters of experiment
saveParameters();
// run experiment for random agent
agt = 0;
for (i = 0; i < n; i++) simulation(i);
getMeanValues();
getVarianceValues();
saveResultsRA();
// run experiment for perfect agent
agt = 1;
for (i = 0; i < n; i++) simulation(i);
getMeanValues();
getVarianceValues();
saveResultsPA();
return 0;
}Параметри експерименту:
R(s0,a0) = 9
R(s0,a1) = 3
R(s0,a2) = 8
--------------------
R(s1,a0) = 4
R(s1,a1) = 8
R(s1,a2) = 6
--------------------
R(s2,a0) = 5
R(s2,a1) = 2
R(s2,a2) = 7
====================
T(s0,a0,s0) = 0.319793
T(s0,a0,s1) = 0.461738
T(s0,a0,s2) = 0.218469
--------------------
T(s0,a1,s0) = 0.300504
T(s0,a1,s1) = 0.673674
T(s0,a1,s2) = 0.025822
--------------------
T(s0,a2,s0) = 0.422344
T(s0,a2,s1) = 0.400310
T(s0,a2,s2) = 0.177346
--------------------
T(s1,a0,s0) = 0.124942
T(s1,a0,s1) = 0.421120
T(s1,a0,s2) = 0.453938
--------------------
T(s1,a1,s0) = 0.236471
T(s1,a1,s1) = 0.215213
T(s1,a1,s2) = 0.548315
--------------------
T(s1,a2,s0) = 0.441073
T(s1,a2,s1) = 0.118767
T(s1,a2,s2) = 0.440160
--------------------
T(s2,a0,s0) = 0.140270
T(s2,a0,s1) = 0.318959
T(s2,a0,s2) = 0.540772
--------------------
T(s2,a1,s0) = 0.852562
T(s2,a1,s1) = 0.052136
T(s2,a1,s2) = 0.095302
--------------------
T(s2,a2,s0) = 0.367007
T(s2,a2,s1) = 0.559048
T(s2,a2,s2) = 0.073945
Результати графічних залежностей:
/
Рис.1. Діаграма для RA і PA
/
Рис.2. Діаграма для RA і PA
Висновок: виконуючи дану лабораторну роботу я дослідила модель марківського процесу прийняття рішень (Markov Decision Process, MDP).