3. Связь с линейным программированием.
В соответствие с введенным понятием цены игры и записи его для случая применения произвольных стратегий со стороны одного из игроков, решение данной матричной игры не изменяется от прибавления ко всем aij одной и той же положительной константы a, так что не будет ограничением рассматривать игры с положительной ценой V>0. В этом случае оптимальные стратегии p1,p2,…,pn; q1,q2,…,qm и цена игры v конечной игры двух партнеров с нулевой суммой с заданной матрицей выигрышей есть
где zmin, wmax, Xi, Yj определяются как решения двойственных задач линейного программирования
z=X1+X2+…+Xn=min
с ограничениями a1jX1+a2jX2+…+anjXn1 (j=1,2,…,m),
Xi0 (i=1,2,…,n),
и
w=Y1+Y2+…+Ym=max
с ограничениями ai1Y1+ai2Y2+…+aimYm1 (i=1,2,…,n),
Yj0 (j=1,2,…,m).
Текст программы:
#include<bios.h>
#include<iostream.h>
#include<conio.h>
#include<string.h>
#include<stdlib.h>
#include<stdio.h>
int** array;
int str,stb,f[100],f1[100];
//funkcii minmax i maxmin
int func(int n)
{array[str][n]=array[0][n];
for(int i=0;i<str;i++)
{if(array[str][n]<array[i][n])
array[str][n]=array[i][n];}
return array[str][n];}
int func1(int m)
{array[m][stb]=array[m][0];
for(int i=0;i<stb;i++)
{if(array[m][stb]>array[m][i])
array[m][stb]=array[m][i];}
return array[m][stb];}
void main()
{clrscr();
int i,j;
//Vvod
cout<<"\nVvedite razmer matrici [Nstolb*Mstrok]:\n";
cin>>stb>>str;
array=new int*[str+2];
for (i=0;i<str+2;i++)
{array[i]=new int [stb+2];}
cout<<"\n\nViberite vid vvoda(1_Manual. Other_Random.):";
for (i=0;i<str;i++)for(j=0;j<stb;j++)
{array[i][j]=0;}
cin>>i;
if(i==1)
{for (i=0;i<str;i++)
for(j=0;j<stb;j++)
{printf("Vvedite element[%d][%d]: ",i+1,j+1);
scanf("%d", &array[i][j]);}
}
else {randomize();
cout <<"\n\t Sluchaino!\n";
for (i=0;i<str;i++)
for(j=0;j<stb;j++)
{array[i][j]=(rand()%8+1);}}
//vivod
cout<<"\n";
printf("\n\t\tMatrica:\n");
for (i=0;i<str;i++)
{for (j=0;j<stb;j++)
{printf(" %d",array[i][j]);}
printf(" \n");}
for(i=0;i<str;i++){f[i]=0;} //massivi 0
for(j=0;j<stb;j++){f1[j]=0;}
while(1)
{int g=0; //flag
for(i=0;i<str;i++) //cikl po vsem strokam
{if(f[i]!=1) //cikl po strokam s prediduchei
for(int k=0;k<str;k++)
if(k!=i)
{if(f[k]!=1){
f[k]=1;g++;
for(int zz=0;zz<stb;zz++)if(f1[zz]!=1)
if(array[i][zz]<array[k][zz]){f[k]=0;g--;break;}}
}}
for(i=0;i<stb;i++)
{if(f1[i]!=1)
for(int k=0;k<stb;k++)
if(k!=i)
{if(f1[k]!=1)
{f1[k]=1;g++;
for(int zz=0;zz<str;zz++)if(f[zz]!=1)
if(array[zz][i]>array[zz][k]){f1[k]=0;g--;break;}}
}}
if(g==0){break;}
}
cout<<"Posle mazhorirovanija:\t\t\n";
for (i=0;i<str;i++)
if(f[i]!=1)
{for (j=0;j<stb;j++)
if(f1[j]!=1)
{printf(" %d",array[i][j]);}
printf(" \n");}
int maxmin=0,minmax=0;
cout<<"\nai ";
for (i=0;i<str;i++)
if(f[i]!=1)
{func1(i);cout<<"\n"<<func1(i);}
int n=func1(0);
for (i=1;i<str;i++)
if(f[i]!=1)
{if(n<func1(i))
{n=func1(i);maxmin=i;}}
cout<<"\n\nbi ";
for (j=0;j<stb;j++)
if(f1[j]!=1)
{func(j);cout<<func(j)<<" ";}
n=func(0);
for (j=1;j<stb;j++)
if(f1[j]!=1)
{if(n>func(j))
{n=func(j);minmax=j;}}
cout<<"\n"<<"Verhnaja cena igri: minmax= "<<array[str][minmax];
cout<<"\nNiznaja cena igri: maxmin= "<<array[maxmin][stb];
if(array[maxmin][stb]==array[str][minmax])
{cout<<"\n"<<"Sedlo!!!";}
int min=array[0][0];
for(i=0;i<str;i++)
for(j=0;j<stb;j++)
if(array[i][j]<min){min=array[i][j];}
if(min<0)
{for(i=0;i<str;i++)
for(j=0;j<stb;j++)
array[i][j]+=((-1)*min+1);}
else {min=0;}
int cs=0; //skol'ko strok ostalos'
for(i=0;i<str;i++)
if(f[i]!=1)cs++;
int cs1=0; //skol'ko stb ostalos'
for(i=0;i<stb;i++)
if(f1[i]!=1)cs1++;
double ox=0,oy=0,oc=0;
if(cs==2)
{int y1,y2;
for(i=0;i<str;i++)
if(f[i]!=1){y1=i;break;}
for(i=i+1;i<str;i++)
if(f[i]!=1){y2=i;break;}
for(i=0;i<stb;i++)
if(f1[i]!=1)
for(int k=i+1;k<stb;k++)
if(f1[k]!=1)
{double opred=array[y1][i]*array[y2][k]-array[y2][i]*array[y1][k];
if(opred==0) continue;
double lx=(array[y2][k]-array[y2][i])/opred;
double ly=(array[y1][i]-array[y1][k])/opred;
if((lx+ly)>oc)
{ox=lx;oy=ly;oc=lx+ly;}}
if(min==0)
{cout<<"\nPa1="<<ox/oc<<" \nPa2="<<oy/oc<<"\nCena igri V="<<1/oc;}
else cout<<"\nPa1="<<ox/oc<<" \nPa2="<<oy/oc<<"\nCena igri V="<<1/oc+min-1;}
cout<<"\n";ox=0,oy=0,oc=0;
if(cs1==2)
{int y1,y2;
for(i=0;i<stb;i++)
if(f1[i]!=1){y1=i;break;}
for(i=i+1;i<stb;i++)
if(f1[i]!=1){y2=i;break;}
for(i=0;i<str;i++)
if(f[i]!=1)
for(int k=i+1;k<str;k++)
if(f[k]!=1)
{double opred=array[i][y1]*array[k][y2]-array[k][y1]*array[i][y2];
if(opred==0) continue;
double lx=(array[k][y2]-array[i][y2])/opred;
double ly=(array[i][y1]-array[k][y1])/opred;
if((lx+ly)>oc)
{ox=lx;oy=ly;oc=lx+ly;}}
if(min==0)
{cout<<"\nPb1="<<ox/oc<<" Pb2="<<oy/oc<<"\nCena igri W="<<1/oc;}
else cout<<"\nPb1="<<ox/oc<<" Pb2="<<oy/oc<<"\nCena igri V="<<1/oc+min-1;}
for(i=0;i<str+1; i++)
{delete[] array[i];}
delete[] array;
while(1)
{switch(bioskey(0))
{case 0x11b :goto swq;}}
swq:}
Запишем матрицу выигрышей, найдем минимальный элемент (a=-5), прибавим его ко всем элементам матрицы.
2 |
-3 |
4 |
|
7 |
2 |
9 |
-3 |
4 |
-5 |
|
2 |
9 |
0 |
4 |
-5 |
6 |
|
9 |
0 |
11 |
Матрица симметрична, m=n=3.
Выигрыш первого игрока будет составлять:
7P1+2P2+9P3V
2P1+9P2+0P3V
9P1+0P2+11P3V
Поскольку V>0, то можно поделить на V с сохранением знаков неравенств. Обозначим Pi/V=Xi, тогда нас интересует min X1+X2+X3 при Xi0 (i=1,2,3) и
7X1+2X2+9X31
2X1+9X21
9X1+11X31
Приводим задачу к каноническому виду.
7X1+2X2+9X3-Y11
2X1+9X2-Y21
9X1+11X3-Y31
Вводим m дополнительных переменных для поиска допустимого начального приближения.
Z1=1-7X1-2X2-9X3+Y1
Z2=1-2X1-9X2+Y2
Z3=1-9X1-11X3+Y3
Z1+Z2+Z3=3-18X1-11X2-20X3+Y1+Y2+Y3 Решаем задачу линейного программирования:
Найти min Z1+Z2+Z3 при Z0, Y0, X0 и
Z1=1-7X1-2X2-9X3+Y1
Z2=1-2X1-9X2+Y2
Z3=1-9X1-11X3+Y3
Симплексная таблица |
До деления на опорный элемент |
||||||||||||||
|
1 |
X1 |
X2 |
X3 |
Y1 |
Y2 |
Y3 |
|
1 |
X1 |
X2 |
X3 |
Y1 |
Y2 |
Y3 |
Z1 |
1 |
-7 |
-2 |
-9 |
1 |
0 |
0 |
Z1 |
-2 |
-4 |
22 |
-9 |
-11 |
0 |
9 |
Z2 |
1 |
-2 |
-9 |
0 |
0 |
1 |
0 |
Z2 |
-11 |
22 |
99 |
0 |
0 |
-11 |
0 |
Z3 |
1 |
-9 |
0 |
-11 |
0 |
0 |
1 |
Z3 |
-1 |
9 |
0 |
1 |
0 |
0 |
-1 |
K |
3 |
-18 |
-11 |
-20 |
1 |
1 |
1 |
K |
-13 |
18 |
121 |
-20 |
-11 |
-11 |
9 |
|
|||||||||||||||
|
1 |
X1 |
X2 |
Z3 |
Y1 |
Y2 |
Y3 |
|
1 |
X1 |
X2 |
Z3 |
Y1 |
Y2 |
Y3 |
Z1 |
2/11 |
4/11 |
-2 |
9/11 |
1 |
0 |
-9/11 |
Z1 |
-2/11 |
-4/11 |
1 |
-9/11 |
-1 |
0 |
9/11 |
Z2 |
1 |
-2 |
-9 |
0 |
0 |
1 |
0 |
Z2 |
-4/11 |
80/11 |
-9 |
81/11 |
9 |
-2 |
-81/11 |
X3 |
1/11 |
-9/11 |
0 |
-1/11 |
0 |
0 |
1/11 |
X3 |
-2/11 |
18/11 |
0 |
2/11 |
0 |
0 |
-2/11 |
K |
13/11 |
-18/11 |
-11 |
20/11 |
1 |
1 |
-9/11 |
K |
-4/11 |
80/11 |
-11 |
59/11 |
9 |
-2 |
-81/11 |
|
|||||||||||||||
|
1 |
X1 |
Z1 |
Z3 |
Y1 |
Y2 |
Y3 |
|
1 |
X1 |
Z1 |
Z3 |
Y1 |
Y2 |
Y3 |
X2 |
1/11 |
2/11 |
-1/2 |
9/22 |
1/2 |
0 |
-9/22 |
X2 |
-4/11 |
2/11 |
1 |
-9/11 |
-1 |
-2/11 |
9/11 |
Z2 |
2/11 |
-40/11 |
9/2 |
-81/22 |
-9/2 |
1 |
81/22 |
Z2 |
-2/11 |
1 |
-9/2 |
81/22 |
9/2 |
-1 |
-81/22 |
X3 |
1/11 |
-9/11 |
0 |
-1/11 |
0 |
0 |
1/11 |
X3 |
-2/11 |
-9/11 |
81/22 |
-59/22 |
-81/22 |
9/11 |
59/22 |
K |
2/11 |
-40/11 |
11/2 |
-59/22 |
-9/2 |
1 |
81/22 |
K |
0 |
-40/11 |
-40/11 |
-40/11 |
0 |
0 |
0 |
|
|||||||||||||||
|
1 |
Z2 |
Z1 |
Z3 |
Y1 |
Y2 |
Y3 |
|
|||||||
X2 |
1/10 |
-1/20 |
-11/40 |
9/40 |
11/40 |
1/20 |
-9/40 |
||||||||
X1 |
1/20 |
-11/40 |
9/40 |
-81/80 |
-9/40 |
11/40 |
81/80 |
||||||||
X3 |
1/20 |
9/40 |
-81/80 |
59/80 |
81/80 |
-9/40 |
-59/80 |
||||||||
K |
0 |
1 |
1 |
1 |
0 |
0 |
0 |
X1+X2+X3=1/10+1/20+1/20=1/5 => V=5. P1=5/20=1/4 P2=5/10=1/2 P3=5/20=1/4
В силу симметричности матрицы выигрышей Q1=1/4, Q2=1/2, Q3=1/4.