- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我有一个计划生成任务,根据this question , 可以借助遗传算法求解。
我通过谷歌搜索找到了许多非常有用的文献和两个“Hello World!”例子。到目前为止,我已经尝试将它们翻译成 php,并重新封装以使代码可重用于我 future 的任务。
这里是关于 C++
的示例链接和 Java
(抱歉,最后一个是俄语,但那里的代码仍然有用)。
这是我的实现:
<?php
abstract class Creature
{
protected $fitness;
public function __construct()
{
$this->fitness = 0;
}
public function getFitness()
{
return $this->fitness;
}
abstract public function calculateFitness();
public function compareTo($creature)
{
return $this->fitness - $creature->fitness;
}
abstract public function mateWith($creature);
abstract public function mutate();
}
abstract class Population
{
protected $creatures;
protected $generation;
public function __construct()
{
$this->creatures = array();
$this->generation = 1;
$this->populate();
}
public function __destruct()
{
unset($this->creatures);
}
public function get($index)
{
return isset($this->creatures[$index]) ? $this->creatures[$index] : null;
}
public function getCount()
{
return count($this->creatures);
}
public function getGeneration()
{
return $this->generation;
}
abstract protected function populate();
public function sort($order = SORT_ASC)
{
switch($order)
{
case SORT_ASC:
$fn = function($c1, $c2){ return $c1->compareTo($c2); };
break;
case SORT_DESC:
$fn = function($c1, $c2){ return $c2->compareTo($c1); };
break;
default: return false;
}
return usort($this->creatures, $fn);
}
public function select(array $params)
{
$result = false;
if(isset($params['top']))
{
$length = round(abs($this->getCount() * $params['top']) / 100);
$this->creatures = array_slice($this->creatures, 0, $length);
$result = true;
}
if(isset($params['fn']) && is_callable($params['fn']))
{
$this->creatures = array_filter($this->creatures, $params['fn']);
$result = true;
}
return $result;
}
public function breed()
{
$candidates = $this->creatures;
shuffle($candidates);
$candidates = array_chunk($candidates, 2);
$result = 0;
foreach($candidates as &$pair)
{
if(count($pair) < 2)continue;
list($mother, $father) = $pair;
$children = $mother->mateWith($father);
$result += count($children);
$this->creatures = array_merge($this->creatures, $children);
}
$this->generation++;
return $result;
}
}
class HWCreature extends Creature
{
protected $string;
protected function randChar()
{
return chr(rand(0, 255));
}
protected function fill()
{
$length = strlen(Algorithm::TARGET);
for($i = 0; $i < $length; $i++)
{
$this->string .= $this->randChar();
}
}
public function __construct($fill = true)
{
parent::__construct();
$this->string = '';
if(!$fill)return;
$this->fill();
$this->calculateFitness();
}
public function __toString()
{
return $this->string;
}
public function calculateFitness()
{
$length = strlen($this->string);
$target = Algorithm::TARGET;
for($i = 0; $i < $length; $i++)
{
$this->fitness += abs(ord($this->string[$i]) - ord($target[$i]));
}
}
public function mateWith($creature)
{
$length = strlen(Algorithm::TARGET) - 1;
$place = rand(0, $length);
$child1 = new self(false);
$child1->string = substr($this->string, 0, $place) . substr($creature->string, $place);
$child1->mutate();
$child1->calculateFitness();
$child2 = new self(false);
$child2->string = substr($creature->string, 0, $place) . substr($this->string, $place);
$child2->mutate();
$child2->calculateFitness();
return array($child1, $child2);
}
public function mutate()
{
if(rand(1, 100) > Algorithm::MUTATION_RATE)return;
$char = $this->randChar();
$length = strlen(Algorithm::TARGET);
$place = rand(0, $length - 1);
$this->string = substr_replace($this->string, $char, $place, 1);
}
}
class HWPopulation extends Population
{
protected function populate()
{
for($i = 0; $i < Algorithm::POPULATION_SIZE; $i++)
{
$this->creatures[] = new HWCreature();
}
}
}
class Algorithm
{
const POPULATION_SIZE = 100; // 1000 in my original test
const ELITE_RATE = 50; // %
const MUTATION_RATE = 25; // %
const MAX_GENERATIONS = 1000;
const TARGET = 'Hello World!';
protected $population;
public function __construct()
{
$this->population = new HWPopulation();
}
public function __destruct()
{
unset($this->population);
}
public function __invoke()
{
do
{
$generation = $this->population->getGeneration();
$representer = $this->population->get(0);
echo sprintf(
'gen %d > %s',
$generation, $representer
),
'<br>',
PHP_EOL;
if($representer == self::TARGET)break;
$selector = array('top' => self::ELITE_RATE);
$this->population->sort();
$this->population->select($selector);
$this->population->breed();
}
while($generation < self::MAX_GENERATIONS);
}
}
$algorithm = new Algorithm();
$algorithm();
unset($algorithm);
?>
但是,我在配备 i7 @ 2.4 GHz CPU 的 16Gb RAM 机器上的结果是:
...
gen 739 > HfkkoWotlc!
gen 740 > HfkkoWotlc!
gen 741 > HfkkoWotlc!
gen 742 > HfkkoWotlc!
gen 743 > HfkkoWotlc!
gen 744 > HfkkoWotlc!
gen 745 > HfkkoWotlc!
Fatal error: Maximum execution time of 30 seconds exceeded in {script} on line 126
所以,看起来效率极低。我相信,这个问题可能出在选择或育种策略上……而我完全迷失在那里。
谁能解释一下,为什么会这样?另外,我只与精英基因/生物群交配是不是做错了什么?
我们将不胜感激。
最佳答案
至少为了调试/测试,您可能需要长时间运行算法,因此您应该增加 php.ini 中的 max_execution_time
的值(或使用 set_time_limit
函数)。
您的代码中的术语似乎有些困惑。从非常简短的一瞥来看,您似乎没有实现精英主义。你似乎拥有的是 truncation selection .这样选 parent 有错吗?好吧,它通常是次优的,因为它完全丢弃了较弱的候选者,这些候选者虽然本身不可行,但可能包含有助于最终解决方案的遗传物质。在这个简单的示例中,它可能无关紧要,但通常您会发现 fitness-proportionate selection strategy ,如轮盘赌选择,更有效。这种策略有利于强者,但也允许弱者被选为 parent 。
如果要实现精英主义,则应将精英候选者不加修改地复制到下一代中,然后通过从整个当前世代(包括精英个体)中选择 parent 来培育那一代的其余成员。通过精英主义保留的候选人的比例应该在5%左右(你可以通过实验找到最佳比例)。
一些其他观察:
关于php - 我的 GAHelloWorld 实现逻辑有什么问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19334237/
我在 JavaScript 文件中运行 PHP,例如...... var = '';). 我需要使用 JavaScript 来扫描字符串中的 PHP 定界符(打开和关闭 PHP 的 )。 我已经知道使
我希望能够做这样的事情: php --determine-oldest-supported-php-version test.php 并得到这个输出: 7.2 也就是说,php 二进制检查 test.
我正在开发一个目前不使用任何框架的大型 php 站点。我的大问题是,随着时间的推移慢慢尝试将框架融入应用程序是否可取,例如在创建的新部件和更新的旧部件中? 比如所有的页面都是直接通过url服务的,有几
下面是我的源代码,我想在同一页面顶部的另一个 php 脚本中使用位于底部 php 脚本的变量 $r1。我需要一个简单的解决方案来解决这个问题。我想在代码中存在的更新查询中使用该变量。 $name)
我正在制作一个网站,根据不同的情况进行大量 PHP 重定向。就像这样...... header("Location: somesite.com/redirectedpage.php"); 为了安全起见
我有一个旧网站,我的 php 标签从 因为短标签已经显示出安全问题,并且在未来的版本中将不被支持。 关于php - 如何避免在 php 文件中写入
我有一个用 PHP 编写的配置文件,如下所示, 所以我想用PHP开发一个接口(interface),它可以编辑文件值,如$WEBPATH , $ACCOUNTPATH和 const值(value)观
我试图制作一个登录页面来学习基本的PHP,首先我希望我的独立PHP文件存储HTML文件的输入(带有表单),但是当我按下按钮时(触发POST到PHP脚本) )我一直收到令人不愉快的错误。 我已经搜索了S
我正在寻找一种让 PHP 以一种形式打印任意数组的方法,我可以将该数组作为赋值包含在我的(测试)代码中。 print_r 产生例如: Array ( [0] => qsr-part:1285 [1]
这个问题已经有答案了: 已关闭11 年前。 Possible Duplicate: What is the max key size for an array in PHP? 正如标题所说,我想知道
我正在寻找一种让 PHP 以一种形式打印任意数组的方法,我可以将该数组作为赋值包含在我的(测试)代码中。 print_r 产生例如: Array ( [0] => qsr-part:1285 [1]
关闭。这个问题需要多问focused 。目前不接受答案。 想要改进此问题吗?更新问题,使其仅关注一个问题 editing this post . 已关闭 9 年前。 Improve this ques
我在 MySQL 数据库中有一个表,其中存储餐厅在每个工作日和时段提供的菜单。 表结构如下: i_type i_name i_cost i_day i_start i_
我有两页。 test1.php 和 test2.php。 我想做的就是在 test1.php 上点击提交,并将 test2.php 显示在 div 中。这实际上工作正常,但我需要向 test2.php
我得到了这个代码。我想通过textarea更新mysql。我在textarea中回显我的MySQL,但我不知道如何更新它,我应该把所有东西都放进去吗,因为_GET模式没有给我任何东西,我也尝试_GET
首先,我是 php 的新手,所以我仍在努力学习。我在 Wordpress 上创建了一个表单,我想将值插入一个表(data_test 表,我已经管理了),然后从 data_test 表中获取所有列(id
我有以下函数可以清理用户或网址的输入: function SanitizeString($var) { $var=stripslashes($var); $va
我有一个 html 页面,它使用 php 文件查询数据库,然后让用户登录,否则拒绝访问。我遇到的问题是它只是重定向到 php 文件的 url,并且从不对发生的事情提供反馈。这是我第一次使用 html、
我有一个页面充满了指向 pdf 的链接,我想跟踪哪些链接被单击。我以为我可以做如下的事情,但遇到了问题: query($sql); if($result){
我正在使用 从外部文本文件加载 HTML/PHP 代码 $f = fopen($filename, "r"); while ($line = fgets($f, 4096)) { print $l
我是一名优秀的程序员,十分优秀!