精华内容
下载资源
问答
  • 极大值极小值搜索设计五子棋

    千次阅读 2018-07-26 11:49:30
    极大值极小值搜索设计五子棋 源代码可在这里下载 摘要: 设计一个五子棋对战AI,使用极大值极小值搜索,并使用α-β剪枝减少复杂度。采用启发式函数对整个棋局形式进行评估,并作为极大值极小值搜索的依据。 一...

    极大值极小值搜索设计五子棋

    源代码可在这里下载

    摘要:

    设计一个五子棋对战AI,使用极大值极小值搜索,并使用α-β剪枝减少复杂度。采用启发式函数对整个棋局形式进行评估,并作为极大值极小值搜索的依据。

    一、导言

    1.1 问题描述:

    本次实验要求设计一个五子棋的AI,要求能与人类对战,并具有较好的用户交互界面。

    1.2 背景介绍:

    五子棋是世界智力运动会竞技项目之一,是一种两人对弈的纯策略型棋类游戏,是世界智力运动会竞技项目之一,通常双方分别使用黑白两色的棋子,下在棋盘直线与横线的交叉点上,先形成5子连线者获胜。棋盘由横纵各15条等距离,垂直交叉的平行线构成,在棋盘上,横纵线交叉形成了225个交叉点为对弈时的落子点。

    尽管五子棋先后于1992年、2001年被计算机证明原始无禁手、原始有禁手规则下先手必胜,在五子棋专业比赛中采用现代开局规则(如基于无禁手的两次交换规则(Swap-2),基于有禁手的索索夫-8规则(Soosorv-8))远比原始规则复杂,并未被终结。然而,相比电脑象棋,电脑五子棋的发展是缓慢的。顶级五子棋程序虽长于局部计算,但缺乏大局观,因此很多五子棋专家相信目前的五子棋程序依旧无法超越最强的人类棋手。

    1.3 使用方法:

    极大极小搜索算法、α-β剪枝算法。

    1.4 方法介绍:

    极大极小策略是考虑双方对弈若干步之后,从可能的步中选一步相对好的步法来走,即在有限的搜索深度范围内进行求解。

    定义一个静态估价函数f,以便对棋局的态势做出优劣评估。

    规定:
    max和min代表对弈双方;
    p代表一个棋局(即一个状态);
    有利于MAX的态势,f(p)取正值;
    有利于MIN的态势,f(p)取负值;
    态势均衡,f(p)取零值;

    1.5 MINMAX的基本思想:

    • 当轮到MIN走步时,MAX应该考虑最坏的情况(即f(p)取极小值)
    • 当轮到MAX走步时,MAX应该考虑最好的情况(即f(p)取极大值)
    • 相应于两位棋手的对抗策略,交替使用上面两种方法传递倒推值。

    α-β剪枝算法是采用有界深度优先策略进行搜索,当生成节点达到规定的深度时,就立即进行静态估计,而一旦某个非端节点有条件确定倒推值时,就立即赋值。

    定义:

    • α值:有或后继的节点,取当前子节点中的最大倒推值为其下界,称为α值。节点倒推值>=α;
    • β值:有与后继的节点,取当前子节点中的最小倒推值为其上界,称为β值。节点倒推值<=β;

    α-β 剪枝:

    • β剪枝:节点x的α值不能降低其父节点的β值,x以下的分支可停止搜索,且x的倒推值为α;
    • α 剪枝:节点x的β值不能升高其父节点的α值,x以下的分支可停止搜索,且x的倒推值为β;

    二、对弈AI落子的程序设计

    AI落子的函数如下。当前落子轮到AI时,进行落子。如果是先手第一步,直接下天元位置,否则调用choose函数选择一个落子位置。最后改变下棋的次序状态。

    void AI::putChess()
    {
        if(AIBoard->now) return;        //不是AI下时,跳过 
        if(first == 1 && AIBoard->chess[7][7] == 0)
        {           //先手第一步直接下中间 
            AIBoard->chess[7][7] = 1;
        }
        else
        {
            choose();       //选择一个位置 
            AIBoard->chess[chooseX][chooseY] = first;   //将这个位置放置我们的棋子 
        }
        AIBoard->now = !AIBoard->now;       //改变下棋次序的状态 
    }

    在计算落子位置之前,有两个预备的函数。一个是就算某一条线的分值,一个是计算整个棋盘的分值,后者需调用前者。而计算落子时,又需要计算整个棋盘的分值。

    int AI::getGoalOfPoint(int *a, int color)
    {
        if(a[0] == color && a[1] == color && a[2] == color && a[3] == color && a[4] == color) return 100000;  //五子 
        if(a[0] == 0 && a[1] == color && a[2] == color && a[3] == color && a[4] == color && a[5] == 0) return 10000;  //活四子 
        if(a[0] == 0 && a[1] == color && a[2] == color && a[3] == color && a[4] == 0) return 1000;              //活三子 
        if((a[0] == -1*color && a[1] == color && a[2] == color && a[3] == color && a[4] == color && a[5] == 0) ||
            (a[0] == 0 && a[1] == color && a[2] == color && a[3] == color && a[4] == color && a[5] == -1*color)) return 1000;   //死四子 
        if(a[0] == 0 && a[1] == color && a[2] == color && a[3] == 0) return 100;    //活二子 
        if((a[0] == -1*color && a[1] == color && a[2] == color && a[3] == color && a[4] == 0) ||
            (a[0] == 0 && a[1] == color && a[2] == color && a[3] == color && a[4] == -1*color)) return 100; //死三子 
        if(a[0] == 0 && a[1] == color && a[2] == 0) return 10;  //活一子 
        if((a[0] == -1*color && a[1] == color && a[2] == color && a[3] == 0) ||
            (a[0] == 0 && a[1] == color && a[2] == color && a[3] == -1*color)) return 10;   //死二子 
        return 0; 
    }

    计算棋盘的分值的函数如下。SumGoal为总分数,然后遍历每一个点。

    int AI::getGoalOfChess(board nowBoard, int color)
    {
        int sumGoal = 0;
        for(int i = 0; i < ROW; i++)
        {
            for(int j = 0; j < COL; j++)        
            {                       //扫描所有的点 

    每一个点的处理如下。

    int line[6];        //记录该点出发的线,一个六个 
    line[0] = nowBoard.chess[i][j];     //第一个是当前点 
    int x1 = i, y1 = j;
    int x2 = i, y2 = j;
    int x3 = i, y3 = j;
    int x4 = i, y4 = j;     //朝四个方向变化的x,y坐标 
    for(int it = 1; it < 6; it++)
    {
        y1--;
        if(y1 >= 0) line[it] = nowBoard.chess[i][y1];   //如果有棋子,就赋值 
        else line[it] = -2;     //没有就赋一个无效值,下同 
    }
    sumGoal += getGoalOfPoint(line,color);      //计算这一点的分值后相加 
    for(int it = 1; it < 6; it++)
    {
        x2++; y2--;
        if(y2 >= 0 && x2 < 15) line[it] = nowBoard.chess[x2][y2];
        else line[it] = -2;
    }
    sumGoal += getGoalOfPoint(line,color);
    for(int it = 1; it < 6; it++)
    {
        x3++;
        if(x3 < 15) line[it] = nowBoard.chess[x3][y3];
        else line[it] = -2;
    }
    sumGoal += getGoalOfPoint(line,color);
    for(int it = 1; it < 6; it++)
    {
        x4++; y4++;
        if(x4 < 15 && y4 < 15) line[it] = nowBoard.chess[x4][y4];
        else line[it] = -2;
    }
    sumGoal += getGoalOfPoint(line,color);

    对于每一个点,我们朝其四个方向取6个点(含其自身)。如果某一方向超出棋盘范围,就设一个无效值。每取一次,就调用刚刚那个函数计算一次分值,加到sumGoal。四个方向均如此,遍历的每个子均如此,最后得出当前棋局对于color方的局势分数。

    接下来是使用极大值极小值搜索和α-β剪枝搜索落子位置。首先,深拷贝一个棋盘,用来进行预估。

        board virtual0;     
        srand(time(0)); 
        for(int i = 0; i < ROW; i++)
        {
            for(int j = 0; j < COL; j++)
                virtual0.chess[i][j] = AIBoard->chess[i][j];
        }           //拷贝一个棋盘用来预估 

    然后是第一层极大值的搜索,首先将MAX值设一个最小值。然后遍历棋盘,如果某一点无子且其周围有子,则为一个预估点,假设这一点放置了本方的棋子。然后进行局势判断,如果已经赢了,就直接将MAX设为一个最大的值(添加了一个非常小的随机因子)。然后给落子位置chooseX和chooseY赋值。最后取消这个落子,恢复棋盘。

    int MAX = -1000000;         //极大值先设为最小 
    for(int i0 = 0; i0 < ROW; i0++)
    {
        for(int j0 = 0; j0 < COL; j0++)
        {
            if(virtual0.chess[i0][j0] == 0 && isAround(virtual0, i0, j0))
            {           //如果该处没有棋子,并且周围有棋子 
                virtual0.chess[i0][j0] = first;     //放置棋子预测 
                if(getGoalOfChess(virtual0,first) >= 100000) 
                {
                    MAX = 1000000-rand()%100;
                    chooseX = i0;
                    chooseY = j0;       //如果能获胜,直接将MAX值设最大 
                    virtual0.chess[i0][j0] = 0;     //取消刚刚放置的棋子 

    如果没有直接获胜,就进行下一步预测,也就是极小值层的搜索。先将MIN设为最大,变量cut1用于剪枝以及判断对方是否直接获胜时使用。同样遍历棋盘,如果五子且其周围有子,则为一个预估点,放置对手方的棋子。

    int MIN = 1000000;          //极小值先设为最小 
                bool cut1 = false;
                for(int p0 = 0; p0 < ROW; p0++)
                {
                    for(int q0 = 0; q0 < COL; q0++)
                    {
                        if(virtual0.chess[p0][q0] == 0 && isAround(virtual0, p0, q0))
                        {
                            virtual0.chess[p0][q0] = -1*first;      //放置一个棋子 
                            if(getGoalOfChess(virtual0,-1*first) >= 100000 && getGoalOfChess(virtual0,first) < 10000) 
                            {
                                MIN = -1000000+rand()%100;      //如果对手方能赢,将极小值设为最小 
                                cut1 = true;            //跳出此次预测 
                                virtual0.chess[p0][q0] = 0;     //恢复棋盘 
                                break;
                            }

    然后判断对手方能否直接获胜且本方无法获胜。如果是则将MIN改为一个最小值。然后修改cut1的值,使这次极小层的搜索结束,还原棋盘,然后跳出循环。

    如果对手方没有直接取胜的点,继续向下进行一层极大值的搜索,MAX1也是先设为最小。变量Cut2用来剪枝。同样遍历棋盘,如果五子且其周围有子,则为一个预估点,放置本方的棋子。然后计算本方棋盘局势减去对方棋盘局势的分数(评估函数)。如果这个极大值小于这个分数,就重新为其赋值,最后还原这一步的棋盘。

    int MAX1 = -1000000;
    bool cut2 = false; 
    for(int i1 = 0; i1 < ROW; i1++)         //又一层极大值的搜索 
    {
        for(int j1 = 0; j1 < ROW; j1++)
        {
            if(virtual0.chess[i1][j1] == 0 && isAround(virtual0, i1, j1))
            {
                virtual0.chess[i1][j1] = first;     //预测放置棋子 
                if(MAX1 < getGoalOfChess(virtual0,first)-getGoalOfChess(virtual0,-1*first)) 
                    MAX1 = getGoalOfChess(virtual0,first)-getGoalOfChess(virtual0,-1*first);
                                    //如果极大值小于启发式函数,就重新赋值 
                virtual0.chess[i1][j1] = 0;     //恢复棋盘 
            }

    接下来是一个β剪枝

        if(MIN < MAX1)      //剪枝 
        {
            cut2 = true;
            break;      
        }   
    }
    if(cut2) break;

    然后是第二层的极小值与第三层的极大值的一个倒推值的比较。如果极小值大,则重新赋值。最后恢复棋盘

    if(MIN > MAX1) MIN = MAX1;  //如果极小值大于倒推值,重新赋值 
    virtual0.chess[p0][q0]  = 0;    //恢复棋盘 

    然后是一个α剪枝。

        if(MAX > MIN)               //剪枝 
        {
            cut1 = true;
            break;
        }
    }
    if(cut1) break;

    然后是最外一层的极大值和第二层的极小值的倒推值的比较。如果极大值小,则重新赋值,并且修改落子的坐标为当前预估落子的坐标。最后恢复棋盘。

    if(MAX < MIN)       //如果极大值小于倒推值 
    {
        MAX = MIN;      //重新赋值 
        chooseX = i0;   //改变放置的x,y坐标 
        chooseY = j0;
    }
    virtual0.chess[i0][j0] = 0;

    以上就是AI落子的搜索过程。接下来是一些界面的设计和棋盘有关的代码。

    三、人类落子的相关代码

    人类落子的代码和AI的基本思想是相同的,不同的是AI要通过算法计算落子坐标,而人类是根据鼠标点击位置计算落子坐标。

    如下,形参x,y为鼠标点击的像素点的位置,我们通过计算将其转化为棋盘下标。并且这个下标处没有棋子时,放置人类的棋子。最后也要修改落子次序的状态。

    void human::putChess(int x, int y)
    {
        if(!humanBoard->now) return;        //如果不是人类下,则放置棋子无效 
        int index_x = 0;
        int index_y = 0;
        if(x > 50) index_x = (x-50)/40+1;
        if(y > 50) index_y = (y-50)/40+1;       //根据鼠标点击的位置,计算放置棋子的下标 
        if(humanBoard->chess[index_x][index_y] == 0)
        {
            humanBoard->chess[index_x][index_y] = first;        //将该坐标放置上我们的棋子 
            humanBoard->now = !humanBoard->now;             //改变下棋次序的状态 
        }
    }

    四、与绘制棋盘,胜负判断有关的代码

    有一个棋盘的board类,负责绘制棋盘,存储棋局信息,判定胜负等。这个类的构造函数如下。

    首先是声明一个二维数组用以存储棋局信息。变量now代表当前应为哪方下,前文已用到。变量runState代表当前棋局是已经结束还是在正常对弈。RED_PEN是一个自定义的红色画笔。

    接下来是绘制棋盘和棋子。绘制棋盘的代码如下。hdc为窗口句柄,chooseX和chooseY为AI落子位置,默认为一个无效位置,我们要为AI的落子画一个红圈方便我们识别其先前落子位置。然后是两个for循环,绘制了棋盘的横线和竖线。

    接下来是绘制棋子的过程。首先是获取系统的黑色和白色画刷。然后选择黑色画刷为天元点画一个小黑点。

    接下来遍历棋盘画棋子,每次遍历棋盘,如果落子为1,则画一个黑色圆圈,如果是-1则画一个白色圆圈。(先手为黑子,后手为白子)画完棋子后,再选择红色画笔根据chooseX和chooseY画一个圆圈作为AI落子提示。(如果chooseX和chooseY取值无效,这个红色圆圈是画不出来的,chooseX和chooseY默认值是一个无效值。)每次画完红圈后,要恢复默认的黑色画笔。

    接下来是检测棋盘当中是否有一方(color方)已经获胜,其思想与AI评估棋盘局势基本相同,也是遍历棋盘,每个点朝四个方向延伸,观察是否有已成五子的线。如下是进行遍历。

    然后是每个点的处理,先是定义朝四个方向变化的x,y坐标,已经用于计数的count。首先,判断当前的子是不是color颜色,如果不是直接过掉。如果是进行四次迭代,朝四个方向取四子,每有一子为color色,则count++,如果count最终为4,说明此线五子连珠,则sum++。最后如果sum大于0,则说明color色的棋子已有连成五子的线,则棋局结束,将代表棋局运行状态的变量runState改为false。最后返回sum值,可以根据sum值,判断某一方是否获胜。

    下边是重置棋盘的reset函数,就是将整个二维数组置0,相关变量再度初始化。

    五、与MFC、鼠标点击相关的部分代码

    本次实验是使用了win32程序,以及相关的MFC库,用以实现界面和鼠标监听等。先前已提到过少许界面方面的代码,下边将剩余代码展示。

    WM_PAINT是MFC中绘制窗口的消息,在窗口被创建时会被调用,也可以通过发送该条消息进行调用。每次调用时,先绘制棋盘,然后我们使用MessageBox语句弹出消息,询问是否选择先手,并根据其选择,为AI和人类的先手变量first赋值,以及下棋次序的变量now赋值。如果是AI先手,则先让AI落一子,然后再画一次棋盘。

    消息WM_LBUTTONDOWN,代表鼠标左键被按下。

    监听到此消息后,我们先获取点击的像素值。如果棋局尚未结束,我们将点击的位置做为形参传入到人类落子的函数中供其落子使用。然后绘制棋盘,判断落子之后人类是否获胜,如果获胜则弹出消息框提示,否则就继续进行。

    紧接着便是AI落子的代码,步骤与人类落子基本相同,不过无需获取鼠标点击位置。最终游戏结束时也是弹出消息框提醒。

    如果检测到棋局已经结束,我们再度弹出消息框,询问是否再来一次。如果是,则重置棋盘,发送绘制棋盘的消息。否则就直接销毁窗口。

    以上为整个五子棋项目设计的主要部分。

    六、结果分析

    实验环境:

    本次实验使用DEV C++编译器,创建了DEV win32项目程序,并使用了MFC的库进行界面和功能的设计。在代码上,使用了多文件编辑,共有main.cpp, board.h, board.cpp, AI.h, AI.cpp, human.h, human.cpp等文件,以及board、AI、human等自定义类。

    算法性能:

    本次实验采用极大极小搜索算法。搜索了三层(两层极大值,一层极小值)。每次搜索均需要遍历棋盘,棋盘大小为15*15,故三层搜索的复杂度为15的6次方。最后还需要遍历棋盘进行局势评估,所以最复杂的情况时,复杂度为15的8次方。这样每走一步棋需要大约25.6亿次左右的计算。对于目前的CPU处理速度,基本上在一秒钟左右下一步棋,可以满足与人正常对弈的时间需求。另外,由于使用了α-β剪枝算法,实际所需时间应当少于最复杂的时间。

    对于本次的AI,三层的极大极小搜索基本可以在时间和对战性能上取得平衡。

    如果想要在对战性能上取得更为突破性的进步,一种情况是进行更深层次的搜索,但是时间和计算能力上已无法满足此需求,考虑可以使用多线程编程以加快计算。另一种情况是优化评估函数,根据网上的知识,大多数的五子棋AI在搜索上是大同小异的,真正产生差距的是评估函数的优化,所以改进对战能力的更好的方法是优化评估函数,使其更能适应五子棋的规则,这方面所需要的是对于五子棋的一个深入了解。

    主要参考文献
    展开全文
  • 请问Python如何实现对Excel按行进行极大值极小值归一化处理?(请附一下代码谢谢啦。)
  • 该程序将计算一个变量的函数的最大和最小值点。
  • 这个评价函数应该从什么角度来写,极大值极小值叶子节点的评价函数是不是需要评价角度不同? 如果AI方是极大者,按照极大值叶子节点评价极大者方的落子利益,值取正; 极小值叶子节点评价极小值方的落子效益,值取...
  • I=imread('c:/lena.jpg'); imshow(I); [m n]=size(I); min=256; max=0; avg=0; for i=1:m for j=1:n if I(i,j) min=I(i,j); end if I(i,j)>max max=I(i,j
    I=imread('c:/lena.jpg');
    imshow(I);
    [m n]=size(I);
    min=256;
    max=0;
    
    avg=0;
    for i=1:m
        for j=1:n
            if I(i,j)<min
                min=I(i,j);
            end
            if I(i,j)>max
                max=I(i,j);
            end
            avg=avg+double(I(i,j));
        end
    end
    mean(mean(I))
    avg=avg/(m*n)

    展开全文
  • 这棵函数是N次函数,经过观察发现,在闭区间[l,r]内函数存在一个极大值点,请求出这个极大值点x。 输入输出格式 输入格式: 第一行,一个正整数N和两个实数l、r,表示闭区间范围。 第二行,N+1个实数,从左到右...

    题目背景

    tz大佬从遥远的喜马拉雅山挖出了一个N阶的函数,为了研究这个神奇的函数,tzdalao把函数拉到了编程俱乐部。

    题目描述

    这棵函数是N次函数,经过观察发现,在闭区间[l,r]内函数存在一个极大值点,请求出这个极大值点x。

    输入输出格式

    输入格式:
    第一行,一个正整数N和两个实数l、r,表示闭区间范围。

    第二行,N+1个实数,从左到右依次表示函数的系数。

    输出格式:
    输出x的值,四舍五入保留5位小数。

    输入输出样例

    输入样例#1:
    3 -0.9981 0.5
    1 -3 -3 1
    输出样例#1:
    -0.41421
    

    说明

    上述样例是n = 3,x3 -3x2 - 3x + 1

    思路:

    假设求闭区间l到r中的极大值,取l和r的中间值mid,再取左半边l和mid的中间值midmid:如果f(midmid)<f(mid),那么极大值肯定在midmid到r之间,就更新左边界就好了,让l=midmid。如果f(midmid)>f(mid),那么极大值肯定在l到mid之间,就更新右边界就好了,让r=mid。如果f(midmid)==f(mid),更新左右边界,l=midmid,r=mid。

    AC代码:

    #include<bits/stdc++.h>
    using namespace std;
    int n;
    double l,r;
    double I[1000];
    double o(double a,int b)//求a的b次方,double
    {
        double ans=1.00000;
        for(int i=0;i<b;i++)
            ans *= a;
        return ans;
    }
    double f(double x)//求函数值
    {
        double ans=0;
        for(int i=0;i<=n;i++)
            ans += I[i]*o(x,n-i);
        return ans;
    }
    
    
    int main()
    {
        scanf("%d%lf%lf",&n,&l,&r);
        for(int i=0;i<=n;i++)
            scanf("%lf",&I[i]);
        while(r-l>1e-6) //精度
        {
            double mid=(l+r)/2.0;
            double midmid=(l+mid)/2.0;
            if(f(midmid)<f(mid))
                l=midmid;
            else if(f(midmid)>f(mid))
                r=mid;
            else
            {
                l=midmid;
                r=mid;
            }
        }
        printf("%.5lf",l);
        return 0;
    }
    
    展开全文
  • 引言 对于一个与节点MIN,若能估计出其上确界beta,以及MIN的父节点的下确界alpha,如果alpha>=beta,则不必扩展MIN的剩余子节点,这个过程称为alpha剪枝。 对于一个或节点MAX,若能估计出其下确界alpha,以及...

    引言

    • 对于一个与节点MIN,若能估计出其上确界beta,以及MIN的父节点的下确界alpha,如果alpha>=beta,则不必扩展MIN的剩余子节点,这个过程称为alpha剪枝。
    • 对于一个或节点MAX,若能估计出其下确界alpha,以及MAX的父节点的上确界beta,如果alpha>=beta,则不必扩展MAX的剩余子节点,这个过程称为beta剪枝。

    在这里插入图片描述

    1. F的第一个节点K=4,那么作为MIN节点F的上确界是beta=4,现在拿出L和M来比较,发现都大于4,此时确定F的上确界beta=4。那么F的父节点,作为MAX节点的C,其下确界alpha=4,将4沿C—G传递给G。
    2. G的第一个子节点N=1,那么更新作为MIN的G的上确界beta=1,此时发现,G的父节点C,下确界alpah=4,发现4>1,所以不必扩展G的剩余子节点,通过alpha剪枝剪掉。
    3. C的下确界alpah=4,父节点A的上确界beta=4,将4沿A—D---H传递给H,H的第一个节点P=5,那么更新MIN的H的上确界beta=5,此时发现4<5,所以仍需要扩展H的剩余子节点Q,Q=8,所以作为MIN的H的上确界仍然为5。
    4. 更新H的MAX父节点D,其下确界alpha=5,此时发现5>4,所以不必扩展D的剩余子节点,通过beta剪枝剪掉。
    5. 此时C下确界alpha=4,D下确界alpha=5,那么确定作为MIN的A的上确界beta=4,作为MAX的父节点的S0下确界alpha=4。
    6. 将4沿S0—B---E—I传递给I。I的第一个子节点R=0,然后更新作为MIN的父节点I的上确界beta=0,此时发现1>0,所以不必再探索I的剩余子节点,通过alpha剪枝剪掉。
    7. 更新作为MAX的E的下确界alpha=0,将0沿E—J传递给J。首先看J的第一个子节点S=-6,更新J的上确界beta=-6,发现0>6,所以不必探索J的剩余子节点,通过alpha剪枝剪掉。
    8. I上确界beta=0,J上确界beta=-6,所以更新E的下确界alpha=0。更新E的MIN父节点B的上确界beta=0,发现4>0,所以不必探索B的剩余子节点,通过alpha剪枝剪掉。
    9. 最终完成搜索。
    展开全文
  • 数值软件的思维果然和mma那种软件很不一样呢,记录一下。 from numpy import diff,sign,argwhere,linspace x=linspace(-10,10,200) f=27*x+130 g=-12-58*x+x**2+x**3 idz=argwhere(diff(sign(g))).flatten() ...
  • 极大值山峰峰顶,极小值就是谷底,a、b两点不算旁边不是深渊就是悬崖,那也不是峰顶也不是谷底。
  • 本程序使用matlab求取二维数组的极大值极小值
  • 判断极值点是极大值还是极小值

    万次阅读 2018-10-18 14:40:49
    ①求函数的二阶导数,将极值点代入,...0, 为极小值点,反之为极大值点 二级导数值=0,有可能不是极值点; ②判断极值点左右邻域的导数值的正负:左+右- 为极大值点,左-右+ 为极小值点,左右正负不变,不是极值点。...
  • 今天小编就为大家分享一篇python取数作为临时极大值(极小值)的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
  • 极小值极大值井字棋

    2017-11-26 00:02:21
    //如果计算机赢了,返回最大 if (isWin() == MAN) return -MAX_NUM;//如果计算机输了,返回最小值 //for (i = 0; i ; i++) // for (j = 0; j ; j++) // if (board[i][j] == 0) // { // flag = false...
  • 场景中有地形图层,通过鼠标绘制一个区域,计算该区域内地形的极大值极小值
  • Matlab中已知自变量和因变量,怎么求极大值极小值? 若diff(y)<0时,sign(diff(y))=-1,要想让y点为极大值,前面diff(y)要大于0,sign(diff(y))=1,也就是前后异号。 第二次diff等于-1-1=-2。因此代码如下,也可...
  • 中国象棋项目中的极大值极小值算法以及α-β剪枝技术技术极大值极小值算法1. 问题提出2. 代码实现α-β剪枝优化1. 代码实现,注意和上面的代码进行比较(其实差别并不大)2. 代码分析3.其他可优化点 极大值...
  • MATLAB 源码 - 分析波形数据,实现最大值,极值的标识和检出; 具体实现介绍,可以参考博文...MATLAB 波形分析,分析最大值,极小值极大值,并在图上标识出来 文件包括波形数据, 波形为一组连续正弦波的采样数据值。
  • 极小值极大值算法-井字棋

    千次阅读 2015-08-24 08:56:56
    极小值极大值算法写的井字棋: #include #include #define COM -1 #define MAN 1 #define STEP 9 #define DRAW 0 #define ROW 3 #define COL 3 #define MAX_NUM 1000; struct Move { int x; int y; }; ...
  • 本实例为约束条件下最值问题的matlab编程实例,抛开复杂绕口的算法名称和推导,从分配的角度来分析解决问题的方法,直观清晰,简明易懂,并给出matlab源代码,值得一看。
  • 波模极大值边缘检测程序
  • eg:x/y,当x==0时,打印结果是极小值 nan 当y==0时,打印结果是极大值 inf 从数学的角度上看,分母不能为0,0除以任何数都为0,。 而在编程的中,程序并没有做这种处理。所以就需要我们在代码中做出相应的条件...
  • 编程中有时候需要一个初始极大值(或极小值)作为temp,当然可以自定义设置为10000(whatever),不过python中有一个值可以代替之:在python2.7中可以用这个(不过python3版本就没得了)>>> import sys >>> sys....
  • 极大极小值算法

    万次阅读 2013-08-24 18:32:30
    极小极大的定义 Minimax算法 又名极小极大算法,是一种找出失败的最大可能性中的最小值的算法(即最小化对手的最大得益)。通常以递归形式来实现。 Minimax算法常用于棋类等由两方较量的游戏和程序。该算法是...
  • 题目链接:点击打开链接题目大意:给出一个4*4棋盘,问你x先手的情况下,是否能实现必胜(胜利条件是横着或竖着或斜着出现四连)题目思路:第一道极大极小值搜索题目...首先一个强大的剪枝,如果下的步数小于等于4,...
  • 找到极大值极小值

    千次阅读 2014-01-08 17:07:07
    那么last.pos若为极大值,则wait.pos应该为极小值;反之亦然。 但是存在的问题是: (1)对于单调上升或者下降趋势无法判定,这种情况也可以认为只有最大值和最小值,而没有极值点 #在图上 显示特...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,490
精华内容 1,796
关键字:

极大值极小值