全局比对:全局比对是指将参与比对的两条序列里面的所有字符进行比对。全局比对在全局范围内对两条序列进行比对打分,找出最佳比对,主要被用来寻找关系密切的序列。其可以用来鉴别或证明新序列与已知序列家族的同源性,是进行分子进化分析的重要前提。其代表是Needleman-Wunsch算法。
局部比对:与全局比对不同扰袜,局部比对不必对两个完整的序列进行比对,而是在每个序列中使用某些局部区域片段进行比对。其产生的需求在于、人们发现有的蛋白序列虽然在序列整体上表现出较大的差异性,但是在某些局部区域能独立的发挥相同的功能,序列相当保守。这时候依靠全局比对明显不能得到这些局部相似序列的。其次,在真核生物的基因中,内含子片段表现出了极大变异性,外显子区域却较为保守,这时候全局比对表现出了其局限性,无法找出这些局部相似性序列。其代表是Smith-Waterman局部比对算法。
双重序列比对:双序列比对是指对两条序列M和N进行比对,找到其相似性关系,这种寻找生物序列相似性关系的过程被称为双序列比对。其算法可以主要分成基于全局比对的Needleman-Wunsch算法和基于局部比对的Smith-Waterman局部比对算法
多重序列比对:多序列比对是双序列比对推广,即把两个以上字符序列对齐,逐列比较其字符的异同,使得每一列字符尽可能一致,以发现其共同的结构特征的方法称为多序列比对。多序列比对算法可以分成渐进法和同步法。其可以发现不同的序列之间的相似部分,从而推断它们在结构和功能上的相似关系,主要用于分子进化关系,预测蛋白质的二级结构和三级结构、估计蛋白质折叠类型的总数,基因组序列分析等。
基因组比对:是多序列比对的一种特例,指对基因组范围内的序列信息进行比对的过程。通过对不同亲缘关系物种的基因组序列进行比较,能够鉴定出编码序列、非编码调控序列及给定物种独有的序列。而基因组范围之内的序列比对,可以了解不同物在核苷酸组成、同线性关系和基因顺序方面的异同,进而得到基因分析预测与定位、生物系统发生进化关系等方面的信息。
BLAST:BLAST[1](Basic Local Alignment Search Tool)是在在1990年由Altschul等人提出的双序列局部比对算法,是一套在蛋白质数据库或DNA数据库中进行相似性比较的分析工具。BLAST是一种启发式算法,用于在大型数据库中寻找比对序列,是一种在局部比对基础上的近似比对算法,可以在保持早李罩较高精度的情况下大大减少程序运行的时间。
算法思想描述:
双重序列比对主要分成以Needleman-Wunsch算法为代表的全局比对和以Smith-Waterman局部比对算法为代表的局部比对,BLAST是局部比对的一种推广。多重比对算法可以主要分成动态规划算法、随机算法、迭代法和渐进比对算法。
(1)双重序列比对:
Needleman-Wunsch算法:该算法是基于动态规划思想的全局比对的基本算法,动态规划的比对算法的比对过程可以用一个以序列S为列,T为行的(m+1)×(n+1)的二维矩阵来表示,用
sigma表示置换矩阵。
在计算完矩阵后,从矩阵的右下角单元到左上单元回溯最佳陆闹路径(用箭头表示),根据最佳路径给出两序列的比对结果。其中,斜箭头表示2个残基匹配,水平箭头表示在序列S的相应位置插入一个空位,垂直方向的箭头表示在序列T的相应位置插入一个空位。
Smith-Waterman算法:该算法是一种用来寻找并比较具有局部相似性区域的动态规划算法,这种算法适用于亲缘关系较远、整体上不具有相似性而在一些较小的区域上存在局部相似性的两个序列。该算法的基本思想是:使用迭代方法计算出两个序列的相似分值,存在一个得分矩阵M中,然后根据这个得分矩阵,通过动态规划的方法回溯找到最优的比对序列。与全局比对相比,这种算法的改变是把矩阵单元值为负者一律取为0,这是因为分值为负的比对丧失了比对的生物学意义,因此把得分为负值的子序列丢弃。
BLAST: BLAST算法的基本思想是通过产生数量更少的但质量更好的增强点来提高比对的速度。算法的原理主要分为以下五步:(1)过滤:首先过滤掉低复杂度区域,即含有大量重复的序列;(2)Seeding:将Query序列中每k个字组合成一个表,即将一个序列拆分成多个连续的‘seed words’(通常蛋白质k=3,核酸k=11);(3)比对:列出我们所关心的所有可能的字组,再配合置换矩阵给出高分值的字组并组织成快速搜索树结构或者哈希索引,因此此步骤可以快速搜索出大数据集中的所有匹配序列,找到每个seed words在参考序列中的位置;(4)延伸:当找到seed words的位置后,接下来需要将seed word延伸成长片段,延伸过程中,得分值也在变化,当得分值小于阈值时即停止延伸,最后得到的片段成为高分片段对,HSP(High-scoring segment pair);(5)显著性分析,最后我们使用如下公式计算E值,E值衡量了在随机情况下,数据库存在的比当前匹配分数更好的比对的数目,因此可以用该值作为指标评价HSP比对序列的可信度。
其中,m是数据库长度,n是query的长度,S是HSP分数,其他两个参数是修正系数。
(2)多重序列比对
动态规划算法:其基本思想是将一个二维的动态规划矩阵扩展到三维或者多维,多序列比对的积分是n个序列中两两进行比对所得积分之和。矩阵的维度反映了参与比对的序列数。这种方法对计算资源要求比较高[6]。
随机算法:主要包括遗传算法和模拟退火算法,遗传算法是一类借鉴生物界进化规律演化来的全局意义上的自适应随机搜索方法。当用遗传算法进行生物序列分析时,每一代包含固定数量的个体,这些个体用他们的适应度来评价。变异则模拟了生物进化过程中的偶然残基突变现象。对产生的新一代群体进行重新评价、选择、交叉、变异,如此循环往复,使群体中最优个体的适应度不断提高,直到达到一个阈值,算法结束。模拟退火的基本思想是用一物质系统的退火过程来模拟优化问题的寻优方法,当物质系统达到最小能量状态时,优化问题的目标函数也相应地达到了全局最优解。这两种方法都是对构造好的目标函数进行最优解搜索,但实际比对效果并不好[6,7]。
迭代法:迭代法的代表是Muscle[8], Muscle是一个新的渐进比对和迭代比对的综合算法,主要由两部分构成,第一部分是迭代渐进比对:第一次渐进比对的目的是快速产生一个多序列比对而不强调准确率,以此为基础再对渐进比对进行改良。经过两次渐进比对,形成一个相对准确的多序列比对;第二部分是迭代比对:该过程类似于Prrp算法[9],即通过不断的迭代,逐步优化最终比对结果。其主要特点包括:使用kmer counting进行快速的距离测量,使用一个新的图谱比对打分函数进行渐进比对,使用依赖于数的有限分隔进行细化。
渐进比对算法:该算法以Feng和Doolittle提出的最为经典[10]。渐进比对算法的基本思想是迭代地利用两序列动态规划比对算法,先由两个序列的比对开始,逐渐添加新序列,直到所有序列都加入为止。但是不同的添加顺序会产生不同的比对结果。确定合适的比对顺序是渐进比对算法的一个关键问题。通常,整个序列的比对应该从最相似的两个序列开始,由近至远逐步完成。作为全局多序列比对的渐进比对算法有个基本的前提假设:所有要比对的序列是同源的,即由共同的祖先序列经过一系列的突变积累,并经自然选择遗传下来的,分化越晚的序列之间相似程度就越高。因此,在渐进比对过程中,应该对近期的进化事件比远期的进化事件给予更大的关注。由于同源序列是进化相关的,因此可以按着序列的进化顺序,即沿着系统发育树(指导树)的分支,由近至远将序列或已比对序列按双序列比对算法逐步进行比对,重复这一过程直到所有序列都己添加到这个比对中为止[10]。其三个步骤为:(1)利用双序列比对方法对所有的序列进行两两比对,得到相似性分值;(2)利用相似性矩阵(或距离矩阵)产生辅助导向树;(3)根据导向树进行渐进比对。渐进比对算法是最常用、简单又有效的启发式多序列比对方法,它所需时间较短、所占内存较小,其算法很多,主要有CLUSTAL W, T-Coffee和DiAlign等,其中 CLUSTAL W应用最广泛。
应用:
类型+应用
双重序列对比:判断两个序列的同源性和一致性。(1)全局多序列比对可以鉴别或证明新序列与己有序列家族的同源性帮助预测新蛋白质序列的二级和二级结构,是进行分子进化分析的重要前提。适合序列相似性较高,序列长度近似时的比对;(2)局部比对考虑序列部分区域的相似性。局部多序列比对可以用来刻画蛋白质家族和超家族。适合于未知两个序列相似程度的,可能存在一些片段极其相似而另一些片段相异的序列比对情况。
多重序列比对:多重比对经常用来研究序列间的进化关系,构建进化树;探究序列间的保守性。主要用于分子进化关系,预测蛋白质的二级结构和三级结构、估计蛋白质折叠类型的总数,基因组序列分析等。
基因组比对:通过对不同亲缘关系物种的基因组序列进行比较,能够鉴定出编码序列、非编码调控序列及给定物种独有的序列。而基因组范围之内的序列比对,可以了解不同物在核苷酸组成、同线性关系和基因顺序方面的异同,进而得到基因分析预测与定位、生物系统发生进化关系等方面的信息。
其中,BLAST作为最重要的比对工具,意义特殊,拿出来单独讨论。BLAST可以分成Basic BLAST和 Specialized BLAST, BLAST包括常规的nucleotide blast, Protein blast和Translating blast;Specialize blast可以对特殊生物或特殊研究领域的序列数据库进行检索。
动态规划解0-1背包:#include<iostream>
using namespace std
//显然定义为全局变量不好
const int item=3//物品数量
const int max_wgt=10//背包最大容量
int c[item+1][max_wgt+1]//从1…i…item物品中,背包剩余空间为0<=j<=max_wgt的最大价值
int w[item+1]={0,3,4,5}//物品质量
int vl[item+1]={0,4,5,6}//物品价值
int knapbag()
{
for (int i=0i<=itemi++)//初始化
{
for (int j=0j<=max_wgtj++)
{
c[i][j]=0
}
}
//c(i,j)=max{c(i-1,j), c(i-1,j-w[i])+vl(i)}
for (int i=1i<=itemi++)
{
蚂凳 for (int j=1j<=max_wgtj++)
{
if (w[i]<=j)
{
if (vl[i]+c[i-1][j-w[i]]>c[i-1][j])
{
c[i][j]=vl[i]+c[i-1][j-w[i]]//选择第i物品
}
else
c[i][j]=c[i-1][j]//不选择第i个物品
闷虚旅 }
else
c[i][j]=c[i-1][j]//剩余容量不够
}//endfor
}//endfor
return c[item][max_wgt]//返回最大值
}
int main()
{
cout<<knapbag()<<endl
return 0
}
void trackback()//算出是由哪几个物品组成
{
int temp_wei=max_wgt
int x[item+1]={0,0,0,0}
for (int i=itemi>0i--)
{
if (c[i][temp_wei]==c[i-1][temp_wei])//最后一个肯定是最大价值的
{
x[i]=0
}
else
{
x[i]=1
temp_wei-=w[i]
}
}
for (int i=0i<=itemi++)
{
if (x[i])
{
std::cout<<i<<","
}
}
std::cout<<std::endl
}
最长公共子序列:
最长公誉芦共子序列的定义是,一个数列z分别是已知数列的子序列(子序列不一定是连续序列,是在该序列中删去若干元素后得到的序列),且是所有符合此条件序列中最长的,则z成为最长公共子序列lcs(Longest Common Subsequences)。有些地方则说公共子串就是要求连续的子序列,有些地方则不是,这里要注意区分。下面是完整实现代码。
#include <iostream>
using namespace std
void LCS_Length(char *x,char *y,int **b,int m,int n)
{
//c[i][j]表示x[i-1],y[j-1]之前公共子序列的长度,i表示x数组前进,j表示y数组前进
//不用c[i][j]表示x[i],y[j]之前公共子序列的长度是因为需要使用c[0][0]来表示没有公共子序列,
//即c[0][0]恒等于0,因此c数组最大下标为c[m+1][n+1]
int **c
c=new int*[m+1]
for( int i=0i<m+1i++)
c[i]=new int[n+1]
for(int i=0i<m+1i++)
c[i][0]=0
for(int i=0i<n+1i++)
c[0][i]=0
for(int i=1i<=mi++)
{
for(int j=1j<=nj++)
{
if(x[i-1]==y[j-1])//找到一个公共“字符”
{
c[i][j]=c[i-1][j-1]+1//公共子序列的长度在原来的基础上加1
b[i][j]=0//做一个辅助标志,表示要达到目前的长度,x,y数组均需“前进”一步
//即x[i-1],y[j-1]都要作出贡献
}
//当前字符不相同,且x数组后退一步(即c[i-1][j])比y数组后退一步(即c[i][j-1])
//所得到的公共子序列的长度要长,隐含的意思是当前最长公共子序列可以不需要x[i-1]
else if(c[i-1][j]>=c[i][j-1])
{
c[i][j]=c[i-1][j]//当前最长公共子序列可以不需要x[i-1]
b[i][j]=-1
}
//和上面分析类似
else
{
c[i][j]=c[i][j-1]//当前最长公共子序列可以不需要y[j-1]
b[i][j]=1
}
}
}
for(int i=0i<m+1i++)
{
delete c[i]
c[i]=NULL
}
delete []c
c=NULL
}
//打印结果
void Print_LCS(int **b,char *x,int i,int j)
{
if(i==0||j==0)
return
if(b[i][j]==0)
{
Print_LCS(b,x,i-1,j-1)
cout<<x[i-1]
}
else if(b[i][j]==-1)
Print_LCS(b,x,i-1,j)
else
Print_LCS(b,x,i,j-1)
}
int _tmain(int argc, _TCHAR* argv[])
{
char x[]="ADAB"
char y[]="ADCA"
int m=strlen(x)
int n=strlen(y)
int **b
b=new int*[m+1]
for( int i=0i<m+1i++)
b[i]=new int[n+1]
LCS_Length(x,y,b,m,n)
Print_LCS(b,x,m,n)
for(int i=0i<m+1i++)
{
delete b[i]
b[i]=NULL
}
delete []b
b=NULL
return 0
}
A*算法
1.启发式搜索
广度优先搜索和双向广度优先搜索都属于盲目搜索,这在状态空间不大的情况下是很合适的算法,可是当状态空间十分庞大时,它们的效率实在太低,往往都是在搜索了大量无关的状态结点后才碰到解答,甚至更本不能碰到解答。
搜索是一种试探性的查寻过程,为了减少搜索的盲目性引,增加试探的准确性,就要采用启发式搜索了。所谓启发式搜索就是在搜索中要对每一个搜索的位置进行评估,从中选择最好、可能容易到达目标的位置,再从这个位置向前进行搜索,这样就可以在搜索中省略大量无关的结点,提高了效率。
2.A*算法
A*算法是一种常用的启发式搜索算法。
在A*算法中,一个结点位置的好坏用估价函数来对它进行评估。A*算法的估价函数可表示为:
f'(n) = g'(n) + h'(n)
这里,f'(n)是估价函数,g'(n)是起点到终点的最短路径值(也称为最小耗费或最小代价),h'(n)是n到目标的最短路经的启发值。由于这个f'(n)其实是无法预先知道的,所以实际上使用的是下面的估价函数:
f(n) = g(n) + h(n)
其中g(n)是从初始结点到节点n的实际代价,h(n)是从结点n到目标结点的最佳路径的估计代价。在这里主要是h(n)体现了搜索的启发信息,因为g(n)是已知的。用f(n)作为f'(n)的近似,也就是用g(n)代替g'(n),h(n)代替h'(n)。这样必须满足两个条件:(1)g(n)>=g'(n)(大多数情况下都是满足的,可以不用考虑),且f必须保持单调递增。(2)h必须小于等于实际的从当前节点到达目标节点的最小耗费h(n)<=h'(n)。第二点特别的重要。可以证明应用这样的估价函数是可以找到最短路径的。
3.A*算法的步骤
A*算法基本上与广度优先算法相同,但是在扩展出一个结点后,要计算它的估价函数,并根据估价函数对待扩展的结点排序,从而保证每次扩展的结点都是估价函数最小的结点。
A*算法的步骤如下:
1)建立一个队列,计算初始结点的估价函数f,并将初始结点入队,设置队列头和尾指针。
2)取出队列头(队列头指针所指)的结点,如果该结点是目标结点,则输出路径,程序结束。否则对结点进行扩展。
3)检查扩展出的新结点是否与队列中的结点重复,若与不能再扩展的结点重复(位于队列头指针之前),则将它抛弃;若新结点与待扩展的结点重复(位于队列头指针之后),则比较两个结点的估价函数中g的大小,保留较小g值的结点。跳至第五步。
4)如果扩展出的新结点与队列中的结点不重复,则按照它的估价函数f大小将它插入队列中的头结点后待扩展结点的适当位置,使它们按从小到大的顺序排列,最后更新队列尾指针。
5)如果队列头的结点还可以扩展,直接返回第二步。否则将队列头指针指向下一结点,再返回第二步。
4.八数码问题的A*算法的估价函数
估价函数中,主要是计算h,对于不同的问题,h有不同的含义。那么在八数码问题中,h的含意是各什么?八数码问题的一个状态实际上是数字0~8的一个排列,用一个数组p[9]来存储它,数组中每个元素的下标,就是该数在排列中的位置。例如,在一个状态中,p[3]=7,则数字7的位置是3。如果目标状态数字3的位置是8,那么数字7对目标状态的偏移距离就是3,因为它要移动3步才可以回到目标状态的位置。
八数码问题中,每个数字可以有9个不同的位置,因此,在任意状态中的每个数字和目标状态中同一数字的相对距离就有9*9种,可以先将这些相对距离算出来,用一个矩阵存储,这样只要知道两个状态中同一个数字的位置,就可查出它们的相对距离,也就是该数字的偏移距离:
0 1 2 3 4 5 6 7 8
0 0 1 2 1 2 3 2 3 4
1 1 0 1 2 1 2 3 2 3
2 2 1 0 3 2 1 4 3 2
3 1 2 3 0 1 2 1 2 3
4 2 1 2 1 0 1 2 1 2
5 3 2 1 2 1 0 3 2 1
6 2 3 4 1 2 3 0 1 2
7 3 2 3 2 1 2 1 0 1
8 4 3 2 3 2 1 2 1 0
例如在一个状态中,数字8的位置是3,在另一状态中位置是7,那么从矩阵的3行7列可找到2,它就是8在两个状态中的偏移距离。
估价函数中的h就是全体数字偏移距离之和。
显然,要计算两个不同状态中同一数字的偏移距离,需要知道该数字在每个状态中的位置,这就要对数组p[9]进行扫描。由于状态发生变化,个数字的位置也要变化,所以每次计算h都沿线扫描数组,以确定每个数字在数组中的位置。为了简化计算,这里用一个数组存储状态中各个数字的位置,并让它在状态改变时随着变化,这样就不必在每次计算h时,再去扫描状态数组。
例如,某个状态中,数字5的位置是8,如果用数组r[9]存储位置,那么就有r[5]=8。
现在用数组r[9]存储当前状态的数字位置,而用s[9]存储目标状态的数字位置,那么当前状态数字i对目标状态的偏移距离就是矩阵中r[i]行s[i]列对应的值。
5.A*算法的类结构
A*算法的类声明如下:
class TAstar:public TEight
{
public:
TAstar(){} //构造函数
TAstar(char *fname)//带参数构造函数
virtual void Search()//A*搜索法
private:
int f,g,h //估价函数
int r[Num]//存储状态中各个数字位置的辅助数组
static int s[Num] //存储目标状态中各个数字位置的辅助数组
static int e[];//存储各个数字相对距离的辅助数组
void Printl(TList<TAstar>L) //成员函数,输出搜索路径
int Expend(int i) //成员函数,A*算法的状态扩展函数
int Calcuf() //成员函数,计算估价函数
void Sort(TList<TAstar>&L,int k) //成员函数,将新扩展结点按f从小到大
//顺序插入待扩展结点队列
int Repeat(TList<TAstar>&L)//成员函数,检查结点是否重复
}
int TAstar::s[Num],TAstar::e[Num*Num]
TAstar::TAstar(char *fname):TEight(fname)
{
for(int i=0i<Num)
{
r[p[i]]=i //存储初始状态个个数字的位置
s[q[i]]=i++ //存储目标状态个个数字的位置
}
ifstream fin
fin.open(".\Eightd.txt",ios::in | ios::nocreate)//打开数据文件
if(!fin)
{
cout<<"不能打开数据文件!"<<endl
return
}
for(i=0i<Num*Numi++)//读入各个数字相对距离值
fin>>e[i]
fin.close()
f=g=h=0 //估价函数初始值
}
void TAstar::Printl(TList<TAstar>L)
{
TAstar T=*this
if(T.last==-1)
return
else
{
T=L.GetData(T.last)
T.Printl(L)
T.Printf()
}
}
int TAstar::Expend(int i)
{
if(Extend(i))//结点可扩展
{
int temp=r[p[r[0]]]//改变状态后数字位置变化,存储改变后的位置
r[p[r[0]]]=r[0]
r[0]=temp
return 1
}
return 0
}
int TAstar::Calcuf()
{
h=0
for(int i=0i<Numi++) //计算估价函数的h
h+=e[Num*r[i]+s[i]]
return ++g+h
}
void TAstar::Sort(TList<TAstar>&L,int k)
{
int n=L.Getlen()
for(int i=k+1i<ni++)
{
TAstar T=L.GetData(i)
if(this->f<=T.f)
break
}
L.Insert(*this,i)
}
int TAstar::Repeat(TList<TAstar>&L)
{
int n=L.Getlen()
for(int i=0i<ni++)
if(L.GetData(i)==*this)
break
return i
}
void TAstar::Search()
{
TAstar T=*this //初始结点
T.f=T.Calcuf() //初始结点的估价函数
TList<TAstar>L //建立队列
L.Append(T)//初始结点入队
int head=0,tail=0 //队列头和尾指针
while(head<=tail) //队列不空则循环
{
for(int i=0i<4i++)//空格可能移动方向
{
T=L.GetData(head) //去队列头结点
if(T.h==0) //是目标结点
{
T.Printl(L)//输出搜索路径
T.Print() //输出目标状态
return //结束
}
if(T.Expend(i)) //若结点可扩展
{
int k=T.Repeat(L)//返回与已扩展结点重复的序号 if(k<head) //如果是不能扩展的结点
continue//丢弃
T.last=head //不是不能扩展的结点,记录父结点
T.f=T.Calcuf()//计算f
if(k<=tail) //新结点与可扩展结点重复
{
TAstar Temp=L.GetData(k)
if(Temp.g>T.g) //比较两结点g值
L.SetData(T,k)//保留g值小的
continue
}
T.Sort(L,head)//新结点插入可扩展结点队列 tail++ //队列尾指针后移
}
}
head++//一个结点不能再扩展,队列头指针指向下一结点
}
}
n皇后问题
#include <iostream.h>
#include <math.h>
void Queue(int n)
{
for (i=1i<=ni++)//初始化
x[i]=0
k=1
while (k>=1)
{
x[k]=x[k]+1//在下一列放置第k个皇后
while (x[k]<=n &&!Place(k))
x[k]=x[k]+1//搜索下一列
if (x[k]<=n &&k= =n) { //得到一个解,输出
for (i=1i<=ni++)
cout<<x[i]
return
}
else if (x[k]<=n &&k<n)
k=k+1 //放置下一个皇后
else {
x[k]=0//重置x[k],回溯
k=k-1
}
}
}
bool Place(int k) //考察皇后k放置在x[k]列是否发生冲突
{
for (i=1i<ki++)
if (x[k]= =x[i] | | abs(k-i)= =abs(x[k]-x[i]))
return false
return true
}
符号主义(Symbolism)是一种基于逻辑推理的智能模拟方昌行宴法,又称为逻辑主义(Logicism)、心理学派(Psychlogism)或计算机学派(Computerism),其原理主要为物理符号系统(即符号 *** 作系统)假设和有限合理性原理,长期以来,一直在人工智能中处于主导地位,其代表人物是纽威尔、肖、西蒙和尼尔森。
认为人工智能源于数理逻辑,主张用公理和逻辑体系搭建一套人工智带迹能系统。代表的有支持向量机(SVM),长短期记忆(LSTM)算法。
数理逻辑从19世纪末起得以迅速发展,到20世纪30年代开始用于描述智能行为。计算机出现后,又在计算机上实现了逻辑演绎系统。其有代表性的成果为启发式程序LT逻辑理论家,它证明了38条数学定理,表明了可以应用计算机研究人的思维过程,模拟人类智能活动。
正是这些符号主义者:
早在1956年首先采用“人工智能”这个术语。后来又发展了启发式算法 >专家系统 >知识工程理论与技术,并在20世纪80年代取得很大发展。
符号主义曾长期一枝独秀,为人工智能的发展作出重要贡献,尤其是专家系统的成功开发与应用,为人工智能走向工程应用耐银和实现理论联系实际具有特别重要的意义。在人工智能的其他学派出现之后,符号主义仍然是人工智能的主流派别。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)