
蚁群算法(ant colony optimization, ACO),又称蚂蚁算法,是一种用来在图中寻找优化路径的机率型技术。它由Marco Dorigo于1992年在他的博士论文中引入,其灵感来源于蚂蚁在寻找食物过程中发现路径的行为。
蚁群算法是一种模拟进化算法,初步的研究表明该算法具有许多优良的性质.针对PID控制器参数优化设计问题,将蚁群算法设计的结果与遗传算法设计的结果进行了比较,数值仿真结果表明,蚁群算法具有一种新的模拟进化优化方法的有效性和应用价值.
蚁群算法是一种求解组合最优化问题的新型通用启发式方法,该方法具有正反馈、分布式计算和富于建设性的贪婪启发式搜索的特点。通过建立适当的数学模型,基于故障过电流的配电网故障定位变为一种非线性全局寻优问题。由柳洪平亩漏创建。
预期的结果:
各个蚂蚁在没有事先告诉他们食物在什么地方的前提下开始寻找食物。当一只找到食物以后,它会向环境释放一种信息素,吸引其他的蚂蚁过来,这样越来越多的蚂蚁会找到食物!有些蚂蚁并没有象其它蚂蚁一样总重复同样的路,他们会另辟蹊径,如果令开辟的道路比原来的其他道路更短,那么,渐渐,更多的蚂蚁被吸引到这条较短的路上来。最后,经过一段时间运行,可能会出现一条最短的路径被大多数蚂蚁重复着。
原理:
为什么小小的蚂蚁能够找到食物?他们具有智能么?设想,如果我们要为蚂蚁设计一个人工智能的程序,那么这个程序要多么复杂呢?首先,你要让蚂蚁能够避开障碍物,就必须根据适当的地形给它编进指令让他们能够巧妙的避开障碍物,其次,要让蚂蚁找到食物,就需要让他们遍历空间上的所有点;再次,如果要让蚂蚁找到最短的路径,那么需要计算所有可能的路径并且比较它们的大小,而且更重要的是,你要小心翼翼的编程,因为程序的错误也许会让你前功尽弃。这是多么不可思议的程序!太复杂了,恐怕没人能够完成这样繁琐冗余的程序。
然而,事实并没有你想得那么复杂,上面这个程序每个蚂蚁的核心程序编码不过100多行!为什么这么简单的程序会让蚂蚁干这样复杂的事情?答案是:简单规则的涌现。事实上,每只蚂蚁并不是像我们想象的需要知道整个世界的信息,他们其实只关心很小范围内的眼前信息,而且根据这些局部信息利用几条简单的规则进行决策,这样,在蚁群这个集体里,复杂性的行为就会凸现出来。这就是人工生命、复杂性科学解释的规律!那么,这些简单规则是什么呢?下面详细说明:
1、范围:
蚂蚁观察到的范围是一个方格世界,蚂蚁有一个参数为速度半径(一般是3),那么它能观察到的范围就是3*3个方格世界,并且能移动的距离也在这个范围之内。
2、环境:
蚂蚁所在的环境是一个虚拟的世界,其中有障碍物,有别的蚂蚁,还有信息素,信息素有两种,一种是找到食物的蚂蚁没耐桥洒下的食物信息素,一种是找到窝的蚂蚁洒下的窝的信息素。每个蚂蚁都仅仅能感知它范围内的环境信息。环境以一定的速率让信息素消失。
3、觅食规则:
在每只蚂蚁能感知的范围内寻找是否有食物,如果有就直接过去。否则看是否有信息素,并且比较在能感知的范围内哪一点的信息素最多,这样,它就朝信息素多的地方走,并且每只蚂蚁多会以小概率犯错误,从而并不是往信息素最多的点移动。蚂蚁找窝的规则和上面一样,只不过它对窝的信息素做出反应,而对食物信息素没反应。
4、移动规则:
每只蚂蚁都朝向信息素最多的方向移,并且,当周围没有信息素指引的时候,蚂蚁会按照自己原来运动的方向惯性的运动下去,并且,在运动的方向有一个随机的小的扰动。为了防止蚂蚁原地转圈,它会记住最近刚走过了哪些点,如果发现要走的下一点已经在最近走过了,它就会尽量避开。
5、避障规则:
如果蚂蚁要移动的方向有障碍物挡住,它会随机的选择另一个方向,并且有信息素指引的话,它会按照觅食的规则行为。
7、播撒信息素规则:
每只蚂蚁在刚找到食物或者窝的时候撒发的信息枯猛素最多,并随着它走远的距离,播撒的信息素越来越少。
根据这几条规则,蚂蚁之间并没有直接的关系,但是每只蚂蚁都和环境发生交互,而通过信息素这个纽带,实际上把各个蚂蚁之间关联起来了。比如,当一只蚂蚁找到了食物,它并没有直接告诉其它蚂蚁这儿有食物,而是向环境播撒信息素,当其它的蚂蚁经过它附近的时候,就会感觉到信息素的存在,进而根据信息素的指引找到了食物。
问题:
说了这么多,蚂蚁究竟是怎么找到食物的呢?
在没有蚂蚁找到食物的时候,环境没有有用的信息素,那么蚂蚁为什么会相对有效的找到食物呢?这要归功于蚂蚁的移动规则,尤其是在没有信息素时候的移动规则。首先,它要能尽量保持某种惯性,这样使得蚂蚁尽量向前方移动(开始,这个前方是随机固定的一个方向),而不是原地无谓的打转或者震动;其次,蚂蚁要有一定的随机性,虽然有了固定的方向,但它也不能像粒子一样直线运动下去,而是有一个随机的干扰。这样就使得蚂蚁运动起来具有了一定的目的性,尽量保持原来的方向,但又有新的试探,尤其当碰到障碍物的时候它会立即改变方向,这可以看成一种选择的过程,也就是环境的障碍物让蚂蚁的某个方向正确,而其他方向则不对。这就解释了为什么单个蚂蚁在复杂的诸如迷宫的地图中仍然能找到隐蔽得很好的食物。
当然,在有一只蚂蚁找到了食物的时候,其他蚂蚁会沿着信息素很快找到食物的。
蚂蚁如何找到最短路径的?这一是要归功于信息素,另外要归功于环境,具体说是计算机时钟。信息素多的地方显然经过这里的蚂蚁会多,因而会有更多的蚂蚁聚集过来。假设有两条路从窝通向食物,开始的时候,走这两条路的蚂蚁数量同样多(或者较长的路上蚂蚁多,这也无关紧要)。当蚂蚁沿着一条路到达终点以后会马上返回来,这样,短的路蚂蚁来回一次的时间就短,这也意味着重复的频率就快,因而在单位时间里走过的蚂蚁数目就多,洒下的信息素自然也会多,自然会有更多的蚂蚁被吸引过来,从而洒下更多的信息素……;而长的路正相反,因此,越来越多地蚂蚁聚集到较短的路径上来,最短的路径就近似找到了。也许有人会问局部最短路径和全局最短路的问题,实际上蚂蚁逐渐接近全局最短路的,为什么呢?这源于蚂蚁会犯错误,也就是它会按照一定的概率不往信息素高的地方走而另辟蹊径,这可以理解为一种创新,这种创新如果能缩短路途,那么根据刚才叙述的原理,更多的蚂蚁会被吸引过来。
引申
跟着蚂蚁的踪迹,你找到了什么?通过上面的原理叙述和实际 *** 作,我们不难发现蚂蚁之所以具有智能行为,完全归功于它的简单行为规则,而这些规则综合起来具有下面两个方面的特点:
1、多样性
2、正反馈
多样性保证了蚂蚁在觅食的时候不置走进死胡同而无限循环,正反馈机制则保证了相对优良的信息能够被保存下来。我们可以把多样性看成是一种创造能力,而正反馈是一种学习强化能力。正反馈的力量也可以比喻成权威的意见,而多样性是打破权威体现的创造性,正是这两点小心翼翼的巧妙结合才使得智能行为涌现出来了。
引申来讲,大自然的进化,社会的进步、人类的创新实际上都离不开这两样东西,多样性保证了系统的创新能力,正反馈保证了优良特性能够得到强化,两者要恰到好处的结合。如果多样性过剩,也就是系统过于活跃,这相当于蚂蚁会过多的随机运动,它就会陷入混沌状态;而相反,多样性不够,正反馈机制过强,那么系统就好比一潭死水。这在蚁群中来讲就表现为,蚂蚁的行为过于僵硬,当环境变化了,蚂蚁群仍然不能适当的调整。
既然复杂性、智能行为是根据底层规则涌现的,既然底层规则具有多样性和正反馈特点,那么也许你会问这些规则是哪里来的?多样性和正反馈又是哪里来的?我本人的意见:规则来源于大自然的进化。而大自然的进化根据刚才讲的也体现为多样性和正反馈的巧妙结合。而这样的巧妙结合又是为什么呢?为什么在你眼前呈现的世界是如此栩栩如生呢?答案在于环境造就了这一切,之所以你看到栩栩如生的世界,是因为那些不能够适应环境的多样性与正反馈的结合都已经死掉了,被环境淘汰了!
参数说明:
最大信息素:蚂蚁在一开始拥有的信息素总量,越大表示程序在较长一段时间能够存在信息素。信息素消减的速度:随着时间的流逝,已经存在于世界上的信息素会消减,这个数值越大,那么消减的越快。
错误概率表示这个蚂蚁不往信息素最大的区域走的概率,越大则表示这个蚂蚁越有创新性。
速度半径表示蚂蚁一次能走的最大长度,也表示这个蚂蚁的感知范围。
记忆能力表示蚂蚁能记住多少个刚刚走过点的坐标,这个值避免了蚂蚁在本地打转,停滞不前。而这个值越大那么整个系统运行速度就慢,越小则蚂蚁越容易原地转圈。
二,可以建立图的数据结构,然后用广度,或者深度优先搜索也许能改进算法
你没说清楚,我猜这个方法可行
宽度优先搜索 BFS
宽度优先搜索算法(又称广度优先搜索)是最简便的图的搜索算法之一,这一算法也是很多重要的图的算法的原型。Dijkstra单源最短路径算法和Prim最小生成树算法都采用了和宽度优先搜索类似的思想。
已知图G=(V,E)和一个源顶点s,宽度优先搜索以一种系统的方式探寻G的边,从而“发现”s所能到达的所有顶点,并计算s到所有这些顶点的距离(最少边数),该算法同时能生成一棵根为s且包括所有可达顶点的宽度优先树。对从s可达的任意顶点v,宽度优先树中从s到v的路径对应于图G中从s到v的最短路径,即包含最小边数的路径。该算法对有向图和无向图同样适用。
之所以称之为宽度优先算法,是因为算法自始至终一直通过已找到和末找到顶点之间的边界向外扩展,就是说,算法首先搜索和s距离为k的所有顶点,然后再去搜索和S距离为k+l的其他顶点。
为了保持搜索的轨迹,宽度优先搜索为每个顶点着色:白色、灰色或黑色。算法开始前所有顶点都是白色,随着搜索的进行,各顶点会逐渐变成灰色,然后成为黑色。在搜索中第一次碰到一顶点时,我们说该顶点被发现,此时该顶点变为非白色顶点。因此,灰色和黑色顶点都已被发现,但是,宽度优先搜索算法对它们加以区分以保证搜索以宽度优先的方式执行。若(u,v)∈E且顶点u为黑色,那么顶点v要么是灰色,要么是黑色,就是说,所有和黑色顶点邻接的顶点都已被发现。灰色顶点可以与一些白色顶点相邻接,它们代表着已找到和未找到顶点之间的边界。
在宽度优先搜索过程中建立了一棵宽度优先树,起始时只包含根节点,即源顶点s.在扫描已发现顶点u的邻接表的过程中每发现一个白色顶点v,该顶点v及边(u,v)就被添加到树中。在宽度优先树中,我们称结点u 是结点v的先辈或父母结点。因为一个结点至多只能被发现一次,因此它最多只能有--个父母结点。相对根结点来说祖先和后裔关系的定义和通常一样:如果u处于树中从根s到结点v的路径中,那么u称为v的祖先,v是u的后裔。
下面的宽度优先搜索过程BFS假定输入图G=(V,E)采用邻接表表示,对于图中的每个顶点还采用了几种附加的数据结构,对每个顶点u∈V,其色彩存储于变量color[u]中,结点u的父母存于变量π[u]中。如果u没有父母(例如u=s或u还没有被检索到),则 π[u]=NIL,由算法算出的源点s和顶点u之间的距离存于变量d[u]中,算法中使用了一个先进先出队列Q来存放灰色节点集合。其中head[Q]表示队列Q的队头元素,Enqueue(Q,v)表示将元素v入队, Dequeue(Q)表示对头元素出队;Adj[u]表示图中和u相邻的节点集合。
procedure BFS(G,S)
begin
1. for 每个节点u∈V[G]- do
begin
2.color[u]←White
3.d[u]←∞
4.π[u]←NIL
end
5. color[s]←Gray
6. d[s]←0
7. π[s]←NIL
8. Q←
9. while Q≠φ do
begin
10. u←head[Q]
11. for 每个节点v∈Adj[u] do
12.if color[v]=White then
begin
13. color[v]←Gray
14. d[v]←d[v]+1
15. π[v]←u
16. Enqueue(Q,v)
end
17. Dequeue(Q)
18. color[u]←Black
end
end
图1展示了用BFS在例图上的搜索过程。黑色边是由BFS产生的树枝。每个节点u内的值为d[u],图中所示的队列Q是第9-18行while循环中每次迭代起始时的队列。队列中每个结点下面是该结点与源结点的距离。
图1 BFS在一个无向图上的执行过程
过程BFS按如下方式执行,第1-4行置每个结点为白色,置d[u]为无穷大,每个结点的父母置为NIL,第5行置源结点S为灰色,即意味着过程开始时源结点已被发现。第6行初始化d[s]为0,第7行置源结点的父母结点为NIL,第8行初始化队列0,使其仅含源结点s,以后Q队列中仅包含灰色结点的集合。
程序的主循环在9-18行中,只要队列Q中还有灰色结点,即那些已被发现但还没有完全搜索其邻接表的结点,循环将一直进行下去。第10行确定队列头的灰色结点为u。第11-16行的循环考察u的邻接表中的每一个顶点v。如果v是白色结点,那么该结点还没有被发现过,算法通过执行第13-16行发现该结点。首先它被置为灰色,距离d[v]置为d[u]+1,而后u被记为该节点的父母,最后它被放在队列Q的队尾。当结点u的邻接表中的所有结点都被检索后,第17 -18行使ud出队列并置成黑色。
分析
在证明宽度优先搜索的各种性质之前,我们先做一些相对简单的工作 ——分析算法在图G=(V,E)之上的运行时间。在初始化后,再没有任何结点又被置为白色。因此第12行的测试保证每个结点至多只能迸人队列一次,因而至多只能d出队列一次。入队和出队 *** 作需要O(1)的时间,因此队列 *** 作所占用的全部时间为O(V),因为只有当每个顶点将被d出队列时才会查找其邻接表,因此每个顶点的邻接表至多被扫描一次。因为所有邻接表的长度和为Q(E),所以扫描所有邻接表所花费时间至多为O(E)。初始化 *** 作的开销为O(V),因此过程BFS的全部运行时间为O(V+E),由此可见,宽度优先搜索的运行时间是图的邻接表大小的一个线性函数。
蚂蚁庄园小鸡答题, *** 作方法如下:
工具/原料:华为nova8、EMUI11、支付宝10.2.36。
方法/步骤:
1、在手机中打开支付宝应用程序,找到蚂蚁庄园,是一款养小鸡的小程序。
2、领取饲料,喂养小毕坦渗鸡获取爱心,进行公益项目捐献,集齐5颗心就可以参加一次。
3、在领饲料下,庄园小课堂进行小鸡今日答题,可以获取饲料,每天答题,有一次获取饲料的机会。
4、每天随机答题,不管答案是否正确,都会信陵有饲料可以领取,答对可以领180g,答错就只有30g。
5、答完一次后,庄园小课堂点击更多惊喜,可以进入答答星球,获取手脊更多答题。
6、进行各种知识挑战,获取不同的奖励。
方法一:系统任务栏上鼠标右键启动任务管理器---进程选项中可查到你要的!方法二:键盘按Ctrl+Alt+Delete 直接启动任务管理器
错了 你说的是VB中 我看错了呵呵 我查查再回答哈
Private Sub Form_Load()
If App.PrevInstance Then
End
End If
End Sub
用DDE实现窗体防止运行多个实例并传递命令
上网的朋友一定都用过网络蚂蚁(Net Ants)的吧?不知你在使用过程中有没有注意过,那就是如果你想调动两个“蚂蚁”为您效力是不可能的——它总会把新运行的关闭。这点在VB中很洞银容易实现:
Private Sub Form_Load()
If App.PrevInstance Then
MsgBox "你已经运行这个应用程序了"
End ' 退出新运行的程序
End If
End Sub
这样如果你运行这个程序后在运行它,它会d出一个消息框并拒绝再次运行。这非常容易。 而“蚂蚁”程序的妙处就在于:在重复运行“蚂蚁”时它不仅拒绝运行,而且能把已经运行的“蚂蚁”激活,这样用上面的程序就无能为力了。但事实上实现拒绝运行并激活已运行的
程序有多种方法:
1、用FindWindow函数得到已经运行窗体的句柄(HWND),然后用SetActiveWindow等API函数将其激活。其缺点也很明显,那就是没法传递参数。
2、用FindWindow函数得到已运行窗体的句柄后用SendMessage的方法给窗体传送一个自定义消息(附带参数),然后在窗体中拦截并进行处理,但这样做要修改窗体的标准消息处理程序,用在VC,BC或DELPHI编写的程序中还行,但在VB中工作量太大,并且容易发生“一般保护行错误”使VB崩溃,不太可取(当然,如果你有足够的信心和不怕崩溃的精神,也可以试一下 ^_^ )。
3、使用DDE技术。
所谓DDE技术,就是动辩咐态数据交换技术。也许你很奇怪,这与本文所讨论的内容有什么相干的?
且听我慢慢讲来。
为了实现拒绝运行并把已经运行的程序激活并实现各种功能,我们可以先用本文开头提到的方法,检测一下程序有没有被运行过,如果没有,就正常运行,如果已经被运行过,就打通与它的DDE通道,传给它一个(或一些)数据,然后由已经运行的程序对数据进行处理,再去实现各种“意想不到”的功能,这时也许就有人对这你的程序喊:“酷、酷……” ^_^
好了,耳听为虚,眼见为实,下面让我们动点真格的。
打开VB,新建一个工程,选择菜单中的“工程->工程1 属性”,把工程名称携颤纯改为“P1”(我爱偷懒,能短则短 ^_^ ),把已有的一个窗体的“LinkTopic”属性改为“FormDDE”,把“LinkMode”属性改为“1 - Source”,添加一个PictureBox控件作为DDE执行控件,命名为picDDE。然后添加一个TextBox控件,命名为“txtInfo”,并把“MultiLine”属性设置为“True”,以便显示多行文本,作为消息显示控件。
最后在窗体代码区输入以下代码:
Const COMMANDLINE = "CommandLine=" ' 还是为了省事,定义一个常量
Private Sub Form_LinkExecute(CmdStr As String, Cancel As Integer)
Static lngCount As Long
Dim Info As String
Info = txtInfo.Text ' 保留原有信息
Select Case CmdStr ' CmdStr 是DDE程序传送过来的参数
Case "Max"
Me.WindowState = 2
Info = Info + vbNewLine + "窗体已被最大化"
Case "ShowTime"
Info = Info + vbNewLine + "最后一次运行这个程序的时间是:" + Str(Now)
Case "Count"
lngCount = lngCount + 1
Info = Info + vbNewLine + "你已经第" + Str(lngCount) + "次重复调用这个程序。" _
+ vbNewLine + "但怕您不多给工资,所以只运行了一个 ^_^"
End Select
If Left(CmdStr, Len(COMMANDLINE)) = COMMANDLINE Then
Info = Info + vbNewLine + "新程序曾以命令行形式运行" + vbNewLine + "命令行为:" _
+ vbNewLine + Right(CmdStr, Len(CmdStr) - Len(COMMANDLINE))
End If
txtInfo.Text = Info ' 把信息显示出来
Cancel = False
End Sub
Private Sub LinkAndSendMessage(ByVal Msg As String)
Dim t As Long
picDDE.LinkMode = 0 '--
picDDE.LinkTopic = "P1|FormDDE" ' |______连接DDE程序并发送数据/参数
picDDE.LinkMode = 2 ' | “|”为管道符,是“退格键”旁边的竖线,
picDDE.LinkExecute Msg '-- 不是字母或数字!
t = picDDE.LinkTimeout '--
picDDE.LinkTimeout = 1 ' |______终止DDE通道。当然,也可以用别的方法
picDDE.LinkMode = 0 ' | 这里用的是超时强制终止的方法
picDDE.LinkTimeout = t '--
End Sub
Private Sub Form_Load()
If App.PrevInstance Then ' 程序是否已经运行
Me.LinkTopic = "" ' 这两行用于清除新运行的程序的DDE服务器属性,
Me.LinkMode = 0 ' 否则在连接DDE程序时会出乱子的
LinkAndSendMessage "Max" '--
LinkAndSendMessage "Count" ' |-----连接DDE接受程序并传送数据/参数
LinkAndSendMessage "ShowTime" '--
If Command <>"" Then ' 如果有命令行参数,就传递过去
LinkAndSendMessage COMMANDLINE + Command
End If
End ' 结束新程序的运行
End If
End Sub
测试一下:
把工程“P1”编译成EXE文件(设名称为 P1.EXE )
1、打开“我的电脑”,找到 P1.EXE 并执行。可以看到程序正常运行了。
2、再运行一次,这次新程序没有运行成功,而原来运行的程序却被最大化了,而且文本框中有以下
字符:
窗体已被最大化
你已经第 1次重复调用这个程序。
但怕您不多给工资,所以只运行了一个 ^_^
最后一次运行这个程序的时间是:00-2-6 7:11:01
3、打开 MS-DOS方式 ,用命令行方式再次运行程序,如 “P1 How Are You?”
这时原来运行的程序文本框中又多了几行字:
窗体已被最大化
你已经第 2次重复调用这个程序。
但怕您不多给工资,所以只运行了一个 ^_^
最后一次运行这个程序的时间是:00-2-6 7:14:32
新程序曾以命令行形式运行
命令行为:
How Are You?
OK,运行完全正确,然后你就可以把它应用的你的程序中了。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)