<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>FunctionEvolve &#8211; 编码无悔 /  Intent &amp; Focused</title>
	<atom:link href="https://www.codelast.com/tag/functionevolve/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.codelast.com</link>
	<description>最优化之路</description>
	<lastBuildDate>Sat, 20 Jun 2026 06:25:38 +0000</lastBuildDate>
	<language>zh-Hans</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.0</generator>
	<item>
		<title>[原创] 结合大模型(LLM)的函数搜索器 FunctionEvolve 简单实测</title>
		<link>https://www.codelast.com/%e5%8e%9f%e5%88%9b-%e7%bb%93%e5%90%88%e5%a4%a7%e6%a8%a1%e5%9e%8bllm%e7%9a%84%e5%87%bd%e6%95%b0%e6%90%9c%e7%b4%a2%e5%99%a8-functionevolve-%e7%ae%80%e5%8d%95%e5%ae%9e%e6%b5%8b/</link>
					<comments>https://www.codelast.com/%e5%8e%9f%e5%88%9b-%e7%bb%93%e5%90%88%e5%a4%a7%e6%a8%a1%e5%9e%8bllm%e7%9a%84%e5%87%bd%e6%95%b0%e6%90%9c%e7%b4%a2%e5%99%a8-functionevolve-%e7%ae%80%e5%8d%95%e5%ae%9e%e6%b5%8b/#respond</comments>
		
		<dc:creator><![CDATA[learnhard]]></dc:creator>
		<pubDate>Sat, 20 Jun 2026 06:20:54 +0000</pubDate>
				<category><![CDATA[AI]]></category>
		<category><![CDATA[Algorithm]]></category>
		<category><![CDATA[原创]]></category>
		<category><![CDATA[1stOpt]]></category>
		<category><![CDATA[FunctionEvolve]]></category>
		<category><![CDATA[Symbolic Regression]]></category>
		<category><![CDATA[公式拟合]]></category>
		<category><![CDATA[数值优化]]></category>
		<category><![CDATA[最优化]]></category>
		<category><![CDATA[符号回归搜索]]></category>
		<guid isPermaLink="false">https://www.codelast.com/?p=14229</guid>

					<description><![CDATA[<blockquote>
<p>
		<strong>系统</strong>：MacOS</p>
<p>
		<strong>Python版本</strong>：3.12</p>
<p>
		<strong>测试时间</strong>：2026-06-19</p>
</blockquote>
<p>
	不知道大家有没有做过&#34;从数据里猜测其符合什么样的y=f(x)数学公式&#34;这样的事情？在很多年前没有AI的时代，这个领域基本是欧美软件的天下，后来出现了一个石破天惊的国产软件1stOpt( <a href="http://www.7d-soft.com/">http://www.7d-soft.com/</a> )打破了它们的垄断，在当年算是国产软件在这个领域取得的重大成就。 巧了，这两天我刚好看到科技媒体报道了一个新的国产开源软件 <strong>FunctionEvolve</strong> ，正是和解决此类问题有关，于是我去了解了一下，并且拿它做了一些简单的测试，写成此文。<br />
	本站的关联文章链接：<a href="https://www.codelast.com/?p=7364" target="_blank">最优化/Optimization文章合集</a></p>
<p>
<span id="more-14229"></span>	<br />
	在正文开始之前我想先闲聊一下，文中测试使用的大模型是DeepSeek V4 Flash，测试过程中总共用了30多万token，花费0.19元，由于任务的性质缓存命中率很低，但DS定价太便宜所以几乎没花钱。</p>
<p>
	下面开始正文。</p>
<p>
	<strong>FunctionEvolve</strong> （ <a href="https://github.com/Phoinikas03/FunctionEvolve">https://github.com/Phoinikas03/FunctionEvolve</a> ）是一个符号回归（Symbolic Regression）搜索框架，核心目标是从数值数据中自动发现数学公式。它采用 <strong>LLM + 传统数值优化</strong> 的混合架构：LLM 负责分析领域知识、生成种子公式、选择父本和定向变异建议；传统优化器（DE / CMA-ES / L-BFGS-B / TRF）负责拟合公式中的参数。<br />
	<span style="color: rgb(255, 255, 255);">文章来源：</span><a href="https://www.codelast.com/" rel="noopener noreferrer" target="_blank"><span style="color: rgb(255, 255, 255);">https://www.codelast.com/</span></a></p>
<h3 id="-">
	同类软件一览</h3>
<p>
	符号回归和自动公式发现领域已有不少成熟工具，按原理大致可分为两类：</p>
<table>
<thead>
<tr>
<th>
				类别</th>
<th>
				代表软件</th>
<th>
				国别</th>
<th>
				核心技术</th>
</tr>
</thead>
<tbody>
<tr>
<td>
				<strong>传统全局优化</strong></td>
<td>
				<strong>1stOpt</strong></td>
<td>
				🇨🇳 国产</td>
<td>
				UGO（通用全局优化），无需初值</td>
</tr>
<tr>
<td>
				&#160;</td>
<td>
				MATLAB Curve Fitting</td>
<td>
				🇺🇸</td>
<td>
				Trust-Region / Levenberg-Marquardt</td>
</tr>
<tr>
<td>
				&#160;</td>
<td>
				OriginPro</td>
<td>
				🇺🇸</td>
<td>
				Levenberg-Marquardt / 全局优化</td>
</tr>
<tr>
<td>
				&#160;</td>
<td>
				DataFit</td>
<td>
				🇺🇸</td>
<td>
				多算法自动搜索</td>
</tr>
<tr>
<td>
				<strong>遗传编程 (GP)</strong></td>
<td>
				Eureqa</td>
<td>
				🇺🇸</td>
<td>
				遗传编程符号回归（最早商业化的 GP 工具）</td>
</tr>
<tr>
<td>
				&#160;</td>
<td>
				PySR</td>
<td>
				🌍 开源</td>
<td>
				遗传编程（Python 库）</td>
</tr>
<tr>
<td>
				&#160;</td>
<td>
				GPTIPS</td>
<td>
				🇬🇧</td>
<td>
				多基因遗传编程（MATLAB）</td>
</tr>
<tr>
<td>
				&#160;</td>
<td>
				gplearn</td>
<td>
				🌍 开源</td>
<td>
				遗传编程（Python 库）</td>
</tr>
<tr>
<td>
				<strong>LLM + 优化</strong></td>
<td>
				<strong>FunctionEvolve</strong> 🌟</td>
<td>
				🌍 开源</td>
<td>
				LLM 指导搜索方向 + 数值优化器拟合参数</td>
</tr>
</tbody>
</table>
<p>
	<strong>重点说明：1stOpt（七维高科）</strong></p>
<p>
	我很多年以前用过几次 1stOpt，当时对它留下了深刻印象（不知道现在是否还在维护），所以这里单独介绍一下。</p>
<p>
	1stOpt 是国内 7D-Soft 开发的数值优化分析软件，在工程和科研领域有大量用户。它的核心特点是：</p>
<ul>
<li>
		<strong>无需人工初值</strong> &#8212; 传统工具（如 MATLAB）做曲线拟合时，参数初值给不对就会发散或收敛到局部最优。1stOpt 内置 <strong>UGO（通用全局优化）</strong> 算法族，号称&#34;万用公式，任意初值&#34;。</li>
<li>
		<strong>公式模板驱动</strong> &#8212; 用户提供公式骨架（如 <code>y = a*x^b + c*e^(d*x)</code>），1stOpt 负责搜索最优参数。和 FunctionEvolve 相比，1stOpt 的公式结构需要<strong>人先指定</strong>，FunctionEvolve 则连结构也可以<strong>自动发现</strong>。</li>
<li>
		<strong>适用场景</strong> &#8212; 曲线/曲面拟合、非线性回归、参数估计、微分方程求解、工程反演。</li>
<li>
		<strong>局限</strong> &#8212; 商业软件、闭源、Windows 独占。公式结构依赖用户经验，无法自动探索未知结构。</li>
</ul>
<h2 id="-functionevolve-">
	在 FunctionEvolve 中，大模型起什么作用</h2>
<p>
	<strong>LLM 起的是&#34;搜索方向指导&#34;作用，数学计算由传统优化器完成。</strong></p>
<p>
	FunctionEvolve 是 <strong>LLM + 传统数值优化 的混合架构</strong>，LLM 不做数学计算。</p>
<hr />
<h2 id="-">
	完整工作流</h2>
<table>
<thead>
<tr>
<th>
				阶段</th>
<th>
				组件</th>
<th>
				是否用 LLM</th>
<th>
				作用</th>
</tr>
</thead>
<tbody>
<tr>
<td>
				<strong>① 领域分析</strong></td>
<td>
				<code>Generator</code></td>
<td>
				✅ LLM</td>
<td>
				分析问题属于什么领域（物理/化学/生物...），给出该领域常见公式模板</td></tr></tbody></table>&#8230; <a href="https://www.codelast.com/%e5%8e%9f%e5%88%9b-%e7%bb%93%e5%90%88%e5%a4%a7%e6%a8%a1%e5%9e%8bllm%e7%9a%84%e5%87%bd%e6%95%b0%e6%90%9c%e7%b4%a2%e5%99%a8-functionevolve-%e7%ae%80%e5%8d%95%e5%ae%9e%e6%b5%8b/" class="read-more">Read More </a>]]></description>
										<content:encoded><![CDATA[<blockquote>
<p>
		<strong>系统</strong>：MacOS</p>
<p>
		<strong>Python版本</strong>：3.12</p>
<p>
		<strong>测试时间</strong>：2026-06-19</p>
</blockquote>
<p>
	不知道大家有没有做过&quot;从数据里猜测其符合什么样的y=f(x)数学公式&quot;这样的事情？在很多年前没有AI的时代，这个领域基本是欧美软件的天下，后来出现了一个石破天惊的国产软件1stOpt( <a href="http://www.7d-soft.com/">http://www.7d-soft.com/</a> )打破了它们的垄断，在当年算是国产软件在这个领域取得的重大成就。 巧了，这两天我刚好看到科技媒体报道了一个新的国产开源软件 <strong>FunctionEvolve</strong> ，正是和解决此类问题有关，于是我去了解了一下，并且拿它做了一些简单的测试，写成此文。<br />
	本站的关联文章链接：<a href="https://www.codelast.com/?p=7364" target="_blank">最优化/Optimization文章合集</a></p>
<p>
<span id="more-14229"></span>	<br />
	在正文开始之前我想先闲聊一下，文中测试使用的大模型是DeepSeek V4 Flash，测试过程中总共用了30多万token，花费0.19元，由于任务的性质缓存命中率很低，但DS定价太便宜所以几乎没花钱。</p>
<p>
	下面开始正文。</p>
<p>
	<strong>FunctionEvolve</strong> （ <a href="https://github.com/Phoinikas03/FunctionEvolve">https://github.com/Phoinikas03/FunctionEvolve</a> ）是一个符号回归（Symbolic Regression）搜索框架，核心目标是从数值数据中自动发现数学公式。它采用 <strong>LLM + 传统数值优化</strong> 的混合架构：LLM 负责分析领域知识、生成种子公式、选择父本和定向变异建议；传统优化器（DE / CMA-ES / L-BFGS-B / TRF）负责拟合公式中的参数。<br />
	<span style="color: rgb(255, 255, 255);">文章来源：</span><a href="https://www.codelast.com/" rel="noopener noreferrer" target="_blank"><span style="color: rgb(255, 255, 255);">https://www.codelast.com/</span></a></p>
<h3 id="-">
	同类软件一览</h3>
<p>
	符号回归和自动公式发现领域已有不少成熟工具，按原理大致可分为两类：</p>
<table>
<thead>
<tr>
<th>
				类别</th>
<th>
				代表软件</th>
<th>
				国别</th>
<th>
				核心技术</th>
</tr>
</thead>
<tbody>
<tr>
<td>
				<strong>传统全局优化</strong></td>
<td>
				<strong>1stOpt</strong></td>
<td>
				<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f1e8-1f1f3.png" alt="🇨🇳" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 国产</td>
<td>
				UGO（通用全局优化），无需初值</td>
</tr>
<tr>
<td>
				&nbsp;</td>
<td>
				MATLAB Curve Fitting</td>
<td>
				<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f1fa-1f1f8.png" alt="🇺🇸" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
<td>
				Trust-Region / Levenberg-Marquardt</td>
</tr>
<tr>
<td>
				&nbsp;</td>
<td>
				OriginPro</td>
<td>
				<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f1fa-1f1f8.png" alt="🇺🇸" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
<td>
				Levenberg-Marquardt / 全局优化</td>
</tr>
<tr>
<td>
				&nbsp;</td>
<td>
				DataFit</td>
<td>
				<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f1fa-1f1f8.png" alt="🇺🇸" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
<td>
				多算法自动搜索</td>
</tr>
<tr>
<td>
				<strong>遗传编程 (GP)</strong></td>
<td>
				Eureqa</td>
<td>
				<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f1fa-1f1f8.png" alt="🇺🇸" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
<td>
				遗传编程符号回归（最早商业化的 GP 工具）</td>
</tr>
<tr>
<td>
				&nbsp;</td>
<td>
				PySR</td>
<td>
				<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f30d.png" alt="🌍" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 开源</td>
<td>
				遗传编程（Python 库）</td>
</tr>
<tr>
<td>
				&nbsp;</td>
<td>
				GPTIPS</td>
<td>
				<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f1ec-1f1e7.png" alt="🇬🇧" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
<td>
				多基因遗传编程（MATLAB）</td>
</tr>
<tr>
<td>
				&nbsp;</td>
<td>
				gplearn</td>
<td>
				<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f30d.png" alt="🌍" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 开源</td>
<td>
				遗传编程（Python 库）</td>
</tr>
<tr>
<td>
				<strong>LLM + 优化</strong></td>
<td>
				<strong>FunctionEvolve</strong> <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f31f.png" alt="🌟" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
<td>
				<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f30d.png" alt="🌍" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 开源</td>
<td>
				LLM 指导搜索方向 + 数值优化器拟合参数</td>
</tr>
</tbody>
</table>
<p>
	<strong>重点说明：1stOpt（七维高科）</strong></p>
<p>
	我很多年以前用过几次 1stOpt，当时对它留下了深刻印象（不知道现在是否还在维护），所以这里单独介绍一下。</p>
<p>
	1stOpt 是国内 7D-Soft 开发的数值优化分析软件，在工程和科研领域有大量用户。它的核心特点是：</p>
<ul>
<li>
		<strong>无需人工初值</strong> &mdash; 传统工具（如 MATLAB）做曲线拟合时，参数初值给不对就会发散或收敛到局部最优。1stOpt 内置 <strong>UGO（通用全局优化）</strong> 算法族，号称&quot;万用公式，任意初值&quot;。</li>
<li>
		<strong>公式模板驱动</strong> &mdash; 用户提供公式骨架（如 <code>y = a*x^b + c*e^(d*x)</code>），1stOpt 负责搜索最优参数。和 FunctionEvolve 相比，1stOpt 的公式结构需要<strong>人先指定</strong>，FunctionEvolve 则连结构也可以<strong>自动发现</strong>。</li>
<li>
		<strong>适用场景</strong> &mdash; 曲线/曲面拟合、非线性回归、参数估计、微分方程求解、工程反演。</li>
<li>
		<strong>局限</strong> &mdash; 商业软件、闭源、Windows 独占。公式结构依赖用户经验，无法自动探索未知结构。</li>
</ul>
<h2 id="-functionevolve-">
	在 FunctionEvolve 中，大模型起什么作用</h2>
<p>
	<strong>LLM 起的是&quot;搜索方向指导&quot;作用，数学计算由传统优化器完成。</strong></p>
<p>
	FunctionEvolve 是 <strong>LLM + 传统数值优化 的混合架构</strong>，LLM 不做数学计算。</p>
<hr />
<h2 id="-">
	完整工作流</h2>
<table>
<thead>
<tr>
<th>
				阶段</th>
<th>
				组件</th>
<th>
				是否用 LLM</th>
<th>
				作用</th>
</tr>
</thead>
<tbody>
<tr>
<td>
				<strong>① 领域分析</strong></td>
<td>
				<code>Generator</code></td>
<td>
				<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> LLM</td>
<td>
				分析问题属于什么领域（物理/化学/生物...），给出该领域常见公式模板</td>
</tr>
<tr>
<td>
				<strong>② 种子生成</strong></td>
<td>
				<code>Generator</code></td>
<td>
				<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> LLM</td>
<td>
				基于领域知识，生成 20 个初始候选公式（带参数占位符 c0, c1...）</td>
</tr>
<tr>
<td>
				<strong>③ 参数拟合</strong></td>
<td>
				<code>StructureOptimizer</code></td>
<td>
				<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>纯数值</strong></td>
<td>
				VARPRO + DE + CMA-ES + L-BFGS-B，拟合 c0, c1... 的最优值</td>
</tr>
<tr>
<td>
				<strong>④ 评估</strong></td>
<td>
				<code>Evaluator</code></td>
<td>
				<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>纯数值</strong></td>
<td>
				计算 NMSE（归一化均方误差）</td>
</tr>
<tr>
<td>
				<strong>⑤ 选父本</strong></td>
<td>
				<code>Selector</code></td>
<td>
				<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> LLM</td>
<td>
				看当前进化树所有公式的 NMSE 和结构，决定下一轮&quot;从哪些公式出发&quot;</td>
</tr>
<tr>
<td>
				<strong>⑥ 结构变异</strong></td>
<td>
				<code>ASTMutator</code></td>
<td>
				<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>规则引擎</strong></td>
<td>
				程序化地删子树、加项、拆函数包装，生成候选变体</td>
</tr>
<tr>
<td>
				<strong>⑦ 结构建议</strong></td>
<td>
				<code>LLMMutator</code></td>
<td>
				<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> LLM</td>
<td>
				&quot;试试加个 sin 项&quot;、&quot;试试把 x&sup2; 换成 exp(x)&quot;</td>
</tr>
<tr>
<td>
				<strong>⑧ 回到 ③</strong></td>
<td>
				循环</td>
<td>
				&mdash;</td>
<td>
				拟合 &rarr; 评估 &rarr; 选父本 &rarr; 变异 &rarr; 再拟合...</td>
</tr>
</tbody>
</table>
<hr />
<h2 id="-">
	优化算法详情</h2>
<p>
	所有参数拟合（阶段③）由 <code>StructureOptimizer</code> 执行，它是一个多策略流水线。</p>
<h3 id="-4-">
	第三方库提供的基础算法（4 个）</h3>
<table>
<thead>
<tr>
<th>
				算法</th>
<th>
				第三方来源</th>
<th>
				独立包装文件</th>
<th>
				StructureOptimizer 中的用途</th>
</tr>
</thead>
<tbody>
<tr>
<td>
				<strong>L-BFGS-B</strong></td>
<td>
				<code>scipy.optimize.minimize</code></td>
<td>
				<code>optimizer/lbfgs.py</code></td>
<td>
				局部精修（全局搜索后的细化）；Pow 指数对齐后的重拟合</td>
</tr>
<tr>
<td>
				<strong>DE (差分进化)</strong></td>
<td>
				<code>scipy.optimize.differential_evolution</code></td>
<td>
				<code>optimizer/de.py</code></td>
<td>
				全局搜索主路径之一（<code>_run_de</code>）</td>
</tr>
<tr>
<td>
				<strong>CMA-ES</strong></td>
<td>
				<code>cmaes</code> 库</td>
<td>
				<code>optimizer/cma.py</code></td>
<td>
				全局搜索主路径之一（<code>_run_cma</code>）；DE 的并行兜底</td>
</tr>
<tr>
<td>
				<strong>TRF (Trust Region Reflective)</strong></td>
<td>
				<code>scipy.optimize.least_squares</code></td>
<td>
				<code>optimizer/least_squares.py</code></td>
<td>
				全局搜索路径之一（<code>_run_trf</code>）</td>
</tr>
</tbody>
</table>
<h3 id="-3-">
	项目自身实现的策略（3 个）</h3>
<table>
<thead>
<tr>
<th>
				策略</th>
<th>
				所在方法 (structure.py)</th>
<th>
				说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>
				<strong>① VARPRO (变量投影分解)</strong></td>
<td>
				<code>_try_varpro</code></td>
<td>
				将参数分解为<strong>线性 + 非线性</strong>两组：线性组用 <code>np.linalg.lstsq</code> 直接 OLS 求解，非线性组用基础算法搜索。本质是降维策略</td>
</tr>
<tr>
<td>
				<strong>② Compound-Pow 预搜索</strong></td>
<td>
				<code>_try_pow_presearch</code></td>
<td>
				检测公式中 <code>x^(c)</code> 且底数含其他参数的情况，枚举候选有理指数（1, 2, 1/2, 1/3...），固定指数后用 VARPRO 拟合其余参数</td>
</tr>
<tr>
<td>
				<strong>③ Pow 指数对齐</strong></td>
<td>
				<code>_snap_pow_and_refit</code> + <code>_pow_rational_grid</code></td>
<td>
				将拟合出的浮点指数对齐到最接近的有理数/整数，再用 L-BFGS-B 重新拟合其他参数</td>
</tr>
</tbody>
</table>
<h3 id="structureoptimizer-">
	StructureOptimizer 执行流水线</h3>
<pre>
<code>输入: 公式骨架 + 数据
  │
  ├─ ① <span class="hljs-selector-tag">Pow</span> 预搜索 (Compound-Pow pre-search)
  │   枚举候选指数，固定后用 <span class="hljs-selector-tag">VARPRO</span> 拟合其余参数
  │
  ├─ ② <span class="hljs-selector-tag">VARPRO</span> 分解 (主路径)
  │   线性参数 &rarr; <span class="hljs-selector-tag">np</span><span class="hljs-selector-class">.linalg</span><span class="hljs-selector-class">.lstsq</span> <span class="hljs-selector-tag">OLS</span> 求解
  │   非线性参数 &rarr; <span class="hljs-selector-tag">DE</span> / <span class="hljs-selector-tag">CMA</span> / <span class="hljs-selector-tag">TRF</span> 并行搜索
  │
  ├─ ③ 并行兜底 (DE / CMA / TRF 同时跑, 取最优)
  │
  ├─ ④ <span class="hljs-selector-tag">L-BFGS-B</span> 局部精修
  │
  ├─ ⑤ <span class="hljs-selector-tag">Pow</span> 指数对齐 <span class="hljs-selector-tag">&amp;</span> 重拟合
  │
  └─ 输出: 最优参数 + <span class="hljs-selector-tag">NMSE</span>
</code></pre>
<p>
	所有路径均有<strong>超时保护</strong>和<strong>多次重启</strong>机制。<br />
	<span style="color: rgb(255, 255, 255);">文章来源：</span><a href="https://www.codelast.com/" rel="noopener noreferrer" target="_blank"><span style="color: rgb(255, 255, 255);">https://www.codelast.com/</span></a></p>
<h2 id="-">
	关键源码位置</h2>
<table>
<thead>
<tr>
<th>
				组件</th>
<th>
				文件</th>
</tr>
</thead>
<tbody>
<tr>
<td>
				主入口 &amp; 装配</td>
<td>
				<code>main.py</code></td>
</tr>
<tr>
<td>
				搜索循环</td>
<td>
				<code>src/search.py</code>（<code>TreeSearch.run()</code>）</td>
</tr>
<tr>
<td>
				LLM 生成器</td>
<td>
				<code>src/generator.py</code></td>
</tr>
<tr>
<td>
				LLM 选择器</td>
<td>
				<code>src/selector.py</code></td>
</tr>
<tr>
<td>
				LLM 变异器</td>
<td>
				<code>src/mutator.py</code></td>
</tr>
<tr>
<td>
				AST 规则变异器</td>
<td>
				<code>src/mutator.py</code>（<code>ASTMutator</code> 类）</td>
</tr>
<tr>
<td>
				参数优化器总管</td>
<td>
				<code>src/optimizer/structure.py</code>（<code>StructureOptimizer</code>）</td>
</tr>
<tr>
<td>
				L-BFGS-B 优化器</td>
<td>
				<code>src/optimizer/lbfgs.py</code></td>
</tr>
<tr>
<td>
				DE 优化器</td>
<td>
				<code>src/optimizer/de.py</code></td>
</tr>
<tr>
<td>
				CMA-ES 优化器</td>
<td>
				<code>src/optimizer/cma.py</code></td>
</tr>
<tr>
<td>
				Least-Squares 优化器</td>
<td>
				<code>src/optimizer/least_squares.py</code></td>
</tr>
<tr>
<td>
				优化器基类 &amp; 工具</td>
<td>
				<code>src/optimizer/base.py</code></td>
</tr>
<tr>
<td>
				评估器</td>
<td>
				<code>src/evaluator.py</code></td>
</tr>
<tr>
<td>
				进化树</td>
<td>
				<code>src/evolution_tree.py</code></td>
</tr>
<tr>
<td>
				LLM 配置</td>
<td>
				<code>llm_config.yaml</code></td>
</tr>
</tbody>
</table>
<h2 id="-">
	一句话总结</h2>
<blockquote>
<p>
		<strong>LLM 是&quot;策略师&quot;&mdash;&mdash;告诉你该往哪个方向找公式；数学优化器是&quot;计算器&quot;&mdash;&mdash;实际算出参数值。</strong></p>
<p>
		LLM 不碰任何数值计算。所有参数拟合由 <code>StructureOptimizer</code> 以 <strong>VARPRO &rarr; DE/CMA/TRF（并行全局搜索）&rarr; L-BFGS-B（局部精修）&rarr; Pow 指数对齐</strong> 的多层流水线完成。</p>
</blockquote>
<hr />
<h2 id="-">
	完整测试流程</h2>
<blockquote>
<p>
		以下是从零开始创建测试数据、搭建环境、运行测试、清理环境的完整步骤记录。&nbsp;</p>
</blockquote>
<h3 id="-">
	测试目标</h3>
<p>
	验证 FunctionEvolve 能否从数值数据中自动发现复杂公式：</p>
<p>
	 <span class='MathJax_Preview'><img src='https://www.codelast.com/wp-content/plugins/latex/cache/tex_27bbc1f7dc1ef282b12305a505028381.gif' style='vertical-align: middle; border: none; padding-bottom:2px;' class='tex' alt="y = \frac{\sin(x_1 x_2)}{\cos(x_3) + 1.5} + e^{-x_2} \cdot \ln(|x_4| + 1) + \frac{x_1 x_3}{1 + x_5^2}" /></span><script type='math/tex'>y = \frac{\sin(x_1 x_2)}{\cos(x_3) + 1.5} + e^{-x_2} \cdot \ln(|x_4| + 1) + \frac{x_1 x_3}{1 + x_5^2}</script> </p>
<h3 id="-">
	步骤一览</h3>
<pre>
<code><span class="hljs-keyword">Step</span> <span class="hljs-number">1</span>: 生成测试数据集
<span class="hljs-keyword">Step</span> <span class="hljs-number">2</span>: 创建临时 Python 环境并安装依赖
<span class="hljs-keyword">Step</span> <span class="hljs-number">3</span>: 编写测试脚本
<span class="hljs-keyword">Step</span> <span class="hljs-number">4</span>: 运行测试
<span class="hljs-keyword">Step</span> <span class="hljs-number">5</span>: 查看结果
<span class="hljs-keyword">Step</span> <span class="hljs-number">6</span>: 删除临时环境
</code></pre>
<hr />
<h3 id="step-1-">
	Step 1：生成测试数据集</h3>
<pre>
<code class="lang-bash"><span class="hljs-keyword">cd</span> /path/<span class="hljs-keyword">to</span>/FunctionEvolve
<span class="hljs-keyword">python3</span> datasets/<span class="hljs-keyword">z</span>/generate_complex_dataset.<span class="hljs-keyword">py</span> --noise-std <span class="hljs-number">0.02</span>
</code></pre>
<h4 id="-">
	生成程序完整源码</h4>
<p>
	保存为 <code>datasets/z/generate_complex_dataset.py</code>：</p>
<pre>
<code class="lang-python"><span class="hljs-comment">#!/usr/bin/env python3</span>
<span class="hljs-string">&quot;&quot;</span><span class="hljs-string">&quot;
生成一个复杂公式的符号回归数据集，用于验证 FunctionEvolve 的效果。

公式（5 个输入变量，混合三角函数、指数、对数、有理分式）:

    sin(x1 * x2)                              x1 * x3
y = ──────────── + exp(-x2) * ln(|x4| + 1) + ─────────
    cos(x3) + 1.5                             1 + x5&sup2;


输出:
  datasets/z/
    dataset.npz        &mdash; NumPy 压缩格式（直接用 from_arrays 加载）
    dataset.csv        &mdash; CSV 文本格式（肉眼查看用）
    ground_truth.txt   &mdash; 真实公式说明
    preview.txt        &mdash; 数据统计摘要
&quot;</span><span class="hljs-string">&quot;&quot;</span>

from __future__ <span class="hljs-built_in">import</span> annotations
<span class="hljs-built_in">import</span> argparse
from pathlib <span class="hljs-built_in">import</span> Path
<span class="hljs-built_in">import</span> numpy as np

<span class="hljs-attr">GROUND_TRUTH_EXPRESSION</span> = (
    <span class="hljs-string">&quot;sin(x1 * x2) / (cos(x3) + 1.5) + exp(-x2) * log(abs(x4) + 1) + x1 * x3 / (1 + x5**2)&quot;</span>
)

<span class="hljs-attr">GROUND_TRUTH_SYMBOLS</span> = [<span class="hljs-string">&quot;x1&quot;</span>, <span class="hljs-string">&quot;x2&quot;</span>, <span class="hljs-string">&quot;x3&quot;</span>, <span class="hljs-string">&quot;x4&quot;</span>, <span class="hljs-string">&quot;x5&quot;</span>]
<span class="hljs-attr">RNG</span> = np.random.RandomState(<span class="hljs-number">42</span>)


def _safe_log_abs(x):
    return np.log(np.abs(x) + <span class="hljs-number">1.0</span>)


def ground_truth_y(X):
    x1, x2, x3, x4, <span class="hljs-attr">x5</span> = X[:, <span class="hljs-number">0</span>], X[:, <span class="hljs-number">1</span>], X[:, <span class="hljs-number">2</span>], X[:, <span class="hljs-number">3</span>], X[:, <span class="hljs-number">4</span>]
    <span class="hljs-attr">term1</span> = np.sin(x1 * x2) / (np.cos(x3) + <span class="hljs-number">1.5</span>)
    <span class="hljs-attr">term2</span> = np.exp(-x2) * _safe_log_abs(x4)
    <span class="hljs-attr">term3</span> = x1 * x3 / (<span class="hljs-number">1.0</span> + x5**<span class="hljs-number">2</span>)
    return term1 + term2 + term3


def main():
    <span class="hljs-attr">parser</span> = argparse.ArgumentParser(<span class="hljs-attr">description=&quot;生成复杂符号回归数据集&quot;)</span>
    parser.add_argument(<span class="hljs-string">&quot;--n-train&quot;</span>, <span class="hljs-attr">type=int,</span> <span class="hljs-attr">default=2000)</span>
    parser.add_argument(<span class="hljs-string">&quot;--n-test&quot;</span>, <span class="hljs-attr">type=int,</span> <span class="hljs-attr">default=500)</span>
    parser.add_argument(<span class="hljs-string">&quot;--noise-std&quot;</span>, <span class="hljs-attr">type=float,</span> <span class="hljs-attr">default=0.0)</span>
    parser.add_argument(<span class="hljs-string">&quot;--output-dir&quot;</span>, <span class="hljs-attr">type=str,</span> <span class="hljs-attr">default=None)</span>
    <span class="hljs-attr">args</span> = parser.parse_args()

    <span class="hljs-attr">out_dir</span> = Path(args.output_dir) <span class="hljs-keyword">if</span> args.output_dir <span class="hljs-keyword">else</span> Path(__file__).resolve().parent
    out_dir.mkdir(<span class="hljs-attr">parents=True,</span> <span class="hljs-attr">exist_ok=True)</span>

    <span class="hljs-comment"># 生成训练集</span>
    <span class="hljs-attr">X_train</span> = RNG.uniform(<span class="hljs-attr">low=-3.0,</span> <span class="hljs-attr">high=3.0,</span> <span class="hljs-attr">size=(args.n_train,</span> <span class="hljs-number">5</span>))
    <span class="hljs-attr">y_train</span> = ground_truth_y(X_train)
    <span class="hljs-keyword">if</span> args.noise_std &gt; <span class="hljs-number">0</span>:
        y_train += RNG.normal(<span class="hljs-number">0</span>, args.noise_std, <span class="hljs-attr">size=args.n_train)</span>

    <span class="hljs-comment"># 生成测试集</span>
    <span class="hljs-attr">rng_test</span> = np.random.RandomState(<span class="hljs-number">2024</span>)
    <span class="hljs-attr">X_test</span> = rng_test.uniform(<span class="hljs-attr">low=-3.0,</span> <span class="hljs-attr">high=3.0,</span> <span class="hljs-attr">size=(args.n_test,</span> <span class="hljs-number">5</span>))
    <span class="hljs-attr">y_test</span> = ground_truth_y(X_test)
    <span class="hljs-keyword">if</span> args.noise_std &gt; <span class="hljs-number">0</span>:
        y_test += rng_test.normal(<span class="hljs-number">0</span>, args.noise_std, <span class="hljs-attr">size=args.n_test)</span>

    <span class="hljs-comment"># 保存 NumPy 格式</span>
    np.savez(out_dir / <span class="hljs-string">&quot;dataset.npz&quot;</span>,
             <span class="hljs-attr">X_train=X_train,</span> <span class="hljs-attr">y_train=y_train,</span>
             <span class="hljs-attr">X_test=X_test,</span> <span class="hljs-attr">y_test=y_test,</span>
             <span class="hljs-attr">expression=GROUND_TRUTH_EXPRESSION)</span>

    <span class="hljs-comment"># 保存 CSV</span>
    <span class="hljs-attr">header</span> = <span class="hljs-string">&quot;,&quot;</span>.join(GROUND_TRUTH_SYMBOLS) + <span class="hljs-string">&quot;,y&quot;</span>
    <span class="hljs-attr">rows</span> = np.column_stack([np.vstack([X_train, X_test]),
                            np.hstack([y_train, y_test])])
    <span class="hljs-keyword">with</span> open(out_dir / <span class="hljs-string">&quot;dataset.csv&quot;</span>, <span class="hljs-string">&quot;w&quot;</span>) as f:
        f.write(f<span class="hljs-string">&quot;# 真实公式: {GROUND_TRUTH_EXPRESSION}\n&quot;</span>)
        f.write(f<span class="hljs-string">&quot;# 噪声标准差: {args.noise_std}\n&quot;</span>)
        f.write(header + <span class="hljs-string">&quot;\n&quot;</span>)
        for row <span class="hljs-keyword">in</span> rows:
            f.write(<span class="hljs-string">&quot;,&quot;</span>.join(f<span class="hljs-string">&quot;{v:.8f}&quot;</span> for v <span class="hljs-keyword">in</span> row) + <span class="hljs-string">&quot;\n&quot;</span>)

    print(f<span class="hljs-string">&quot;数据集已保存到 {out_dir}&quot;</span>)


<span class="hljs-keyword">if</span> <span class="hljs-attr">__name__</span> == <span class="hljs-string">&quot;__main__&quot;</span>:
    main()
</code></pre>
<h4 id="-">
	生成的数据样例</h4>
<pre>
<code class="lang-csv"><span class="hljs-selector-tag">x1</span>,<span class="hljs-selector-tag">x2</span>,<span class="hljs-selector-tag">x3</span>,<span class="hljs-selector-tag">x4</span>,<span class="hljs-selector-tag">x5</span>,<span class="hljs-selector-tag">y</span>
<span class="hljs-selector-tag">-0</span><span class="hljs-selector-class">.75275929</span>,2<span class="hljs-selector-class">.70428584</span>,1<span class="hljs-selector-class">.39196365</span>,0<span class="hljs-selector-class">.59195091</span>,<span class="hljs-selector-tag">-2</span><span class="hljs-selector-class">.06388816</span>,<span class="hljs-selector-tag">-0</span><span class="hljs-selector-class">.73060157</span>
<span class="hljs-selector-tag">-2</span><span class="hljs-selector-class">.06403288</span>,<span class="hljs-selector-tag">-2</span><span class="hljs-selector-class">.65149833</span>,2<span class="hljs-selector-class">.19705687</span>,0<span class="hljs-selector-class">.60669007</span>,1<span class="hljs-selector-class">.24843547</span>,4<span class="hljs-selector-class">.13384154</span>
<span class="hljs-selector-tag">-2</span><span class="hljs-selector-class">.87649303</span>,2<span class="hljs-selector-class">.81945911</span>,1<span class="hljs-selector-class">.99465584</span>,<span class="hljs-selector-tag">-1</span><span class="hljs-selector-class">.72596534</span>,<span class="hljs-selector-tag">-1</span><span class="hljs-selector-class">.90905020</span>,<span class="hljs-selector-tag">-2</span><span class="hljs-selector-class">.05631804</span>
<span class="hljs-selector-tag">-1</span><span class="hljs-selector-class">.89957294</span>,<span class="hljs-selector-tag">-1</span><span class="hljs-selector-class">.17454654</span>,0<span class="hljs-selector-class">.14853859</span>,<span class="hljs-selector-tag">-0</span><span class="hljs-selector-class">.40832989</span>,<span class="hljs-selector-tag">-1</span><span class="hljs-selector-class">.25262516</span>,1<span class="hljs-selector-class">.29225609</span>
</code></pre>
<p>
	每行 6 列：x₁ ~ x₅ 为输入，y 为输出。</p>
<p>
	产出文件：</p>
<table>
<thead>
<tr>
<th>
				文件</th>
<th>
				说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>
				<code>datasets/z/dataset.npz</code></td>
<td>
				NumPy 压缩格式，供 <code>from_arrays()</code> 加载</td>
</tr>
<tr>
<td>
				<code>datasets/z/dataset.csv</code></td>
<td>
				CSV 文本格式，肉眼查看用</td>
</tr>
<tr>
<td>
				<code>datasets/z/ground_truth.txt</code></td>
<td>
				真实公式说明</td>
</tr>
<tr>
<td>
				<code>datasets/z/preview.txt</code></td>
<td>
				数据统计摘要</td>
</tr>
</tbody>
</table>
<h3 id="step-2-">
	Step 2：创建临时环境</h3>
<p>
	使用 <code>micromamba</code> 创建独立的 Python 3.12 环境，避免污染已有环境：</p>
<pre>
<code class="lang-bash"><span class="hljs-comment"># 创建</span>
micromamba create -n py312 python=<span class="hljs-number">3</span>.<span class="hljs-number">12</span> -y

<span class="hljs-comment"># 安装依赖</span>
micromamba run -n py312 pip3 <span class="hljs-keyword">install </span><span class="hljs-keyword">scipy </span>sympy <span class="hljs-keyword">scikit-learn </span>h5py \
    tiktoken <span class="hljs-keyword">json-repair </span>cmaes threadpoolctl
</code></pre>
<h3 id="step-3-">
	Step 3：编写测试脚本</h3>
<p>
	保存为 <code>datasets/z/run_test.py</code>：</p>
<pre>
<code class="lang-python"><span class="hljs-comment">#!/usr/bin/env python3</span>
<span class="hljs-string">&quot;&quot;</span><span class="hljs-string">&quot;
在 FunctionEvolve 上运行自定义复杂数据集（datasets/z/dataset.npz）的测试脚本。

用法:
  cd /path/to/FunctionEvolve

  # 退化模式（无 LLM，仅验证程序化变异 + 数值优化）
  python datasets/z/run_test.py --degenerated

  # 完整模式（使用 LLM，需要 llm_config.yaml）
  python datasets/z/run_test.py
&quot;</span><span class="hljs-string">&quot;&quot;</span>

<span class="hljs-built_in">import</span> argparse
<span class="hljs-built_in">import</span> os
<span class="hljs-built_in">import</span> sys
from pathlib <span class="hljs-built_in">import</span> Path

<span class="hljs-built_in">import</span> numpy as np

<span class="hljs-attr">PROJECT_ROOT</span> = Path(__file__).resolve().parents[<span class="hljs-number">2</span>]
sys.path.insert(<span class="hljs-number">0</span>, str(PROJECT_ROOT))

from src.dataset <span class="hljs-built_in">import</span> SRDataset
from src.evaluator <span class="hljs-built_in">import</span> Evaluator
from src.evolution_tree <span class="hljs-built_in">import</span> EvolutionTree
from src.search <span class="hljs-built_in">import</span> TreeSearch
from src.generator <span class="hljs-built_in">import</span> MockGenerator, create_generator
from src.selector <span class="hljs-built_in">import</span> MockSelector, create_selector
from src.mutator <span class="hljs-built_in">import</span> MockMutator, LLMMutator
from src.llm_client <span class="hljs-built_in">import</span> build_openai_client, LLMUsageLogger


def _load_dataset(data_dir):
    <span class="hljs-attr">npz_path</span> = data_dir / <span class="hljs-string">&quot;dataset.npz&quot;</span>
    <span class="hljs-attr">data</span> = np.load(npz_path)
    <span class="hljs-attr">expr</span> = str(data[<span class="hljs-string">&quot;expression&quot;</span>].item())
    return SRDataset.from_arrays(
        <span class="hljs-attr">X_train=data[&quot;X_train&quot;],</span> <span class="hljs-attr">y_train=data[&quot;y_train&quot;],</span>
        <span class="hljs-attr">X_test=data[&quot;X_test&quot;],</span> <span class="hljs-attr">y_test=data[&quot;y_test&quot;],</span>
        <span class="hljs-attr">symbols=[&quot;x1&quot;,</span> <span class="hljs-string">&quot;x2&quot;</span>, <span class="hljs-string">&quot;x3&quot;</span>, <span class="hljs-string">&quot;x4&quot;</span>, <span class="hljs-string">&quot;x5&quot;</span>],
        <span class="hljs-attr">symbol_descs=[&quot;v1&quot;,</span> <span class="hljs-string">&quot;v2&quot;</span>, <span class="hljs-string">&quot;v3&quot;</span>, <span class="hljs-string">&quot;v4&quot;</span>, <span class="hljs-string">&quot;v5&quot;</span>],
        <span class="hljs-attr">expression=expr,</span> <span class="hljs-attr">equation_name=&quot;complex_z&quot;,</span>
    )


def _evaluate_ground_truth(ds, evaluator):
    <span class="hljs-string">&quot;&quot;</span><span class="hljs-string">&quot;对真实公式做参数拟合，给出精度天花板。&quot;</span><span class="hljs-string">&quot;&quot;</span>
    <span class="hljs-built_in">import</span> sympy as sp
    <span class="hljs-attr">sympy_expr</span> = sp.sympify(ds.expression)
    <span class="hljs-attr">param_names</span> = sorted(
        {str(s) for s <span class="hljs-keyword">in</span> sympy_expr.free_symbols} - set(ds.feature_names))
    <span class="hljs-attr">result</span> = evaluator.evaluate_skeleton(sympy_expr, param_names)
    print(f<span class="hljs-string">&quot;[Ground Truth] Train NMSE = {result.train_nmse:.2e}&quot;</span>)
    print(f<span class="hljs-string">&quot;[Ground Truth] Test  NMSE = {result.test_nmse:.2e}&quot;</span>)


def main():
    <span class="hljs-attr">parser</span> = argparse.ArgumentParser()
    parser.add_argument(<span class="hljs-string">&quot;--degenerated&quot;</span>, <span class="hljs-attr">action=&quot;store_true&quot;)</span>
    parser.add_argument(<span class="hljs-string">&quot;--max-steps&quot;</span>, <span class="hljs-attr">type=int,</span> <span class="hljs-attr">default=30)</span>
    parser.add_argument(<span class="hljs-string">&quot;--n-seeds&quot;</span>, <span class="hljs-attr">type=int,</span> <span class="hljs-attr">default=20)</span>
    parser.add_argument(<span class="hljs-string">&quot;--candidate-num&quot;</span>, <span class="hljs-attr">type=int,</span> <span class="hljs-attr">default=5)</span>
    parser.add_argument(<span class="hljs-string">&quot;--timeout&quot;</span>, <span class="hljs-attr">type=float,</span> <span class="hljs-attr">default=120.0)</span>
    parser.add_argument(<span class="hljs-string">&quot;--llm-config&quot;</span>, <span class="hljs-attr">type=str,</span> <span class="hljs-attr">default=None)</span>
    parser.add_argument(<span class="hljs-string">&quot;--run-tag&quot;</span>, <span class="hljs-attr">type=str,</span> <span class="hljs-attr">default=&quot;z_test&quot;)</span>
    <span class="hljs-attr">args</span> = parser.parse_args()

    <span class="hljs-attr">data_dir</span> = Path(__file__).resolve().parent
    <span class="hljs-attr">ds</span> = _load_dataset(data_dir)
    print(f<span class="hljs-string">&quot;训练样本: {ds.X_train.shape[0]}, 测试样本: {ds.X_test.shape[0]}&quot;</span>)

    <span class="hljs-attr">evaluator</span> = Evaluator(
        <span class="hljs-attr">feature_names=ds.feature_names,</span> <span class="hljs-attr">X_train=ds.X_train,</span>
        <span class="hljs-attr">y_train=ds.y_train,</span> <span class="hljs-attr">X_test=ds.X_test,</span> <span class="hljs-attr">y_test=ds.y_test,</span>
        <span class="hljs-attr">timeout=args.timeout,</span>
    )
    _evaluate_ground_truth(ds, evaluator)

    <span class="hljs-comment"># 构造 LLM / Mock Agent</span>
    <span class="hljs-attr">llm_config</span> = None
    <span class="hljs-keyword">if</span> not args.degenerated:
        <span class="hljs-attr">cfg_path</span> = args.llm_config <span class="hljs-literal">or</span> str(PROJECT_ROOT / <span class="hljs-string">&quot;llm_config.yaml&quot;</span>)
        <span class="hljs-keyword">if</span> os.path.exists(cfg_path):
            <span class="hljs-built_in">import</span> yaml
            <span class="hljs-keyword">with</span> open(cfg_path) as f:
                <span class="hljs-attr">llm_config</span> = yaml.safe_load(f) <span class="hljs-literal">or</span> {}

    def _resolve(comp, field, <span class="hljs-attr">fallback=None):</span>
        return llm_config.get(comp, {}).get(field, fallback) <span class="hljs-keyword">if</span> llm_config <span class="hljs-keyword">else</span> fallback

    <span class="hljs-keyword">if</span> args.degenerated:
        <span class="hljs-attr">generator</span> = MockGenerator(<span class="hljs-attr">variables=ds.feature_names)</span>
        <span class="hljs-attr">selector</span> = MockSelector(<span class="hljs-attr">variables=ds.feature_names)</span>
        <span class="hljs-attr">llm_mutator</span> = MockMutator()
    <span class="hljs-keyword">else</span>:
        <span class="hljs-attr">gen</span> = _resolve(<span class="hljs-string">&quot;generator&quot;</span>, <span class="hljs-string">&quot;model&quot;</span>); <span class="hljs-attr">gen_url</span> = _resolve(<span class="hljs-string">&quot;generator&quot;</span>, <span class="hljs-string">&quot;base_url&quot;</span>)
        <span class="hljs-attr">gen_key</span> = _resolve(<span class="hljs-string">&quot;generator&quot;</span>, <span class="hljs-string">&quot;api_key&quot;</span>); <span class="hljs-attr">gen_mode</span> = _resolve(<span class="hljs-string">&quot;generator&quot;</span>, <span class="hljs-string">&quot;mode&quot;</span>, <span class="hljs-string">&quot;openai&quot;</span>)
        <span class="hljs-attr">gen_temp</span> = _resolve(<span class="hljs-string">&quot;generator&quot;</span>, <span class="hljs-string">&quot;temperature&quot;</span>, <span class="hljs-number">0.8</span>)
        <span class="hljs-attr">gen_tok</span> = _resolve(<span class="hljs-string">&quot;generator&quot;</span>, <span class="hljs-string">&quot;max_tokens&quot;</span>, <span class="hljs-number">128000</span>)
        <span class="hljs-attr">logger</span> = LLMUsageLogger(str(Path(<span class="hljs-string">&quot;logs&quot;</span>) / <span class="hljs-string">&quot;z_custom&quot;</span> / <span class="hljs-string">&quot;llm_usage.csv&quot;</span>))
        <span class="hljs-attr">generator</span> = create_generator(gen, gen_url, gen_key, gen_temp, gen_tok,
                                     <span class="hljs-attr">usage_logger=logger,</span> <span class="hljs-attr">llm_mode=gen_mode)</span>

        <span class="hljs-attr">sm</span> = _resolve(<span class="hljs-string">&quot;selector&quot;</span>, <span class="hljs-string">&quot;model&quot;</span>, gen); <span class="hljs-attr">su</span> = _resolve(<span class="hljs-string">&quot;selector&quot;</span>, <span class="hljs-string">&quot;base_url&quot;</span>, gen_url)
        <span class="hljs-attr">sk</span> = _resolve(<span class="hljs-string">&quot;selector&quot;</span>, <span class="hljs-string">&quot;api_key&quot;</span>, gen_key); <span class="hljs-attr">sd</span> = _resolve(<span class="hljs-string">&quot;selector&quot;</span>, <span class="hljs-string">&quot;mode&quot;</span>, gen_mode)
        <span class="hljs-attr">st</span> = _resolve(<span class="hljs-string">&quot;selector&quot;</span>, <span class="hljs-string">&quot;temperature&quot;</span>, <span class="hljs-number">0.3</span>)
        <span class="hljs-attr">selector</span> = create_selector(sm, su, sk, st, <span class="hljs-attr">usage_logger=logger,</span> <span class="hljs-attr">llm_mode=sd)</span>

        <span class="hljs-attr">mm</span> = _resolve(<span class="hljs-string">&quot;mutator&quot;</span>, <span class="hljs-string">&quot;model&quot;</span>, gen); <span class="hljs-attr">mu</span> = _resolve(<span class="hljs-string">&quot;mutator&quot;</span>, <span class="hljs-string">&quot;base_url&quot;</span>, gen_url)
        <span class="hljs-attr">mk</span> = _resolve(<span class="hljs-string">&quot;mutator&quot;</span>, <span class="hljs-string">&quot;api_key&quot;</span>, gen_key); <span class="hljs-attr">md</span> = _resolve(<span class="hljs-string">&quot;mutator&quot;</span>, <span class="hljs-string">&quot;mode&quot;</span>, gen_mode)
        <span class="hljs-attr">mt</span> = _resolve(<span class="hljs-string">&quot;mutator&quot;</span>, <span class="hljs-string">&quot;temperature&quot;</span>, <span class="hljs-number">0.7</span>)
        <span class="hljs-attr">m_tok</span> = _resolve(<span class="hljs-string">&quot;mutator&quot;</span>, <span class="hljs-string">&quot;max_tokens&quot;</span>, <span class="hljs-number">128000</span>)
        <span class="hljs-attr">client</span> = build_openai_client(mm, mu, <span class="hljs-attr">mode=md,</span> <span class="hljs-attr">api_key=mk)</span>
        <span class="hljs-attr">llm_mutator</span> = LLMMutator(client, mm, mt, m_tok, <span class="hljs-attr">usage_logger=logger)</span>

    <span class="hljs-attr">tree</span> = EvolutionTree()
    <span class="hljs-attr">searcher</span> = TreeSearch(
        <span class="hljs-attr">dataset=ds,</span> <span class="hljs-attr">evaluator=evaluator,</span> <span class="hljs-attr">tree=tree,</span>
        <span class="hljs-attr">selector=selector,</span> <span class="hljs-attr">generator=generator,</span> <span class="hljs-attr">llm_mutator=llm_mutator,</span>
        <span class="hljs-attr">max_steps=args.max_steps,</span> <span class="hljs-attr">n_seeds=args.n_seeds,</span>
        <span class="hljs-attr">candidate_num=args.candidate_num,</span> <span class="hljs-attr">timeout=args.timeout,</span> <span class="hljs-attr">verbose=True,</span>
    )
    searcher.initialize_seeds()
    searcher.run()

    <span class="hljs-comment"># 输出最佳结果</span>
    <span class="hljs-attr">evaluated</span> = [n for n <span class="hljs-keyword">in</span> tree.all_nodes <span class="hljs-keyword">if</span> n.is_evaluated <span class="hljs-literal">and</span> n.train_nmse &lt; float(<span class="hljs-string">&quot;inf&quot;</span>)]
    evaluated.sort(<span class="hljs-attr">key=lambda</span> n: n.train_nmse)
    <span class="hljs-keyword">if</span> evaluated:
        <span class="hljs-attr">best</span> = evaluated[<span class="hljs-number">0</span>]
        print(f<span class="hljs-string">&quot;\n最佳公式: {best.skeleton_str}&quot;</span>)
        print(f<span class="hljs-string">&quot;训练集 NMSE: {best.train_nmse:.4e}&quot;</span>)
        print(f<span class="hljs-string">&quot;测试集 NMSE: {best.test_nmse:.4e}&quot;</span>)


<span class="hljs-keyword">if</span> <span class="hljs-attr">__name__</span> == <span class="hljs-string">&quot;__main__&quot;</span>:
    main()
</code></pre>
<h3 id="step-4-">
	Step 4：运行测试</h3>
<p>
	共运行三个实验：</p>
<p>
	<strong>① 退化模式（1 步）：</strong></p>
<pre>
<code class="lang-bash"><span class="hljs-comment">cd</span> <span class="hljs-comment">/path/to/FunctionEvolve</span>
<span class="hljs-comment">python3</span> <span class="hljs-comment">datasets/z/run_test</span><span class="hljs-string">.</span><span class="hljs-comment">py</span> <span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-comment">degenerated</span> <span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-comment">max</span><span class="hljs-literal">-</span><span class="hljs-comment">steps</span> <span class="hljs-comment">1</span> <span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-comment">n</span><span class="hljs-literal">-</span><span class="hljs-comment">seeds</span> <span class="hljs-comment">3</span> <span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-comment">candidate</span><span class="hljs-literal">-</span><span class="hljs-comment">num</span> <span class="hljs-comment">2</span> <span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-comment">timeout</span> <span class="hljs-comment">120</span>
</code></pre>
<p>
	<strong>② LLM 模式（1 步）：</strong></p>
<pre>
<code class="lang-bash"><span class="hljs-keyword">cd</span> /path/<span class="hljs-keyword">to</span>/FunctionEvolve
<span class="hljs-keyword">python3</span> datasets/<span class="hljs-keyword">z</span>/run_test.<span class="hljs-keyword">py</span> --<span class="hljs-built_in">max</span>-steps <span class="hljs-number">1</span> --n-seeds <span class="hljs-number">3</span> --candidate-num <span class="hljs-number">2</span> --timeout <span class="hljs-number">120</span>
</code></pre>
<p>
	<strong>③ LLM 模式（3 步）：</strong></p>
<pre>
<code class="lang-bash"><span class="hljs-keyword">cd</span> /path/<span class="hljs-keyword">to</span>/FunctionEvolve
<span class="hljs-keyword">python3</span> datasets/<span class="hljs-keyword">z</span>/run_test.<span class="hljs-keyword">py</span> --<span class="hljs-built_in">max</span>-steps <span class="hljs-number">3</span> --n-seeds <span class="hljs-number">3</span> --candidate-num <span class="hljs-number">2</span> --timeout <span class="hljs-number">120</span>
</code></pre>
<blockquote>
<p>
		为加快运行速度，上述实验使用了 200 训练样本 + 100 测试样本的子集（完整数据集为 2000 + 500）。</p>
</blockquote>
<h3 id="step-5-">
	Step 5：测试输出及分析</h3>
<pre>
<code><span class="hljs-string">[Ground Truth]</span> 训练集 NMSE = <span class="hljs-number">1</span>.77e-<span class="hljs-number">05</span>
<span class="hljs-string">[Ground Truth]</span> 测试集 NMSE = <span class="hljs-number">2</span>.14e-<span class="hljs-number">05</span>
</code></pre>
<p>
	真实公式本身不需要拟合任何参数，NMSE &asymp; 1.8e-5 来自 0.02 标准差的高斯噪声，是本次测试的精度天花板。<br />
	<span style="color: rgb(255, 255, 255);">文章来源：</span><a href="https://www.codelast.com/" rel="noopener noreferrer" target="_blank"><span style="color: rgb(255, 255, 255);">https://www.codelast.com/</span></a></p>
<h4 id="-a-200-">
	模式 A：退化模式结果（200 样本）</h4>
<p>
	初始种子（退化模式仅基于 x1 生成简易多项式/指数公式）：</p>
<table>
<thead>
<tr>
<th>
				种子公式</th>
<th>
				训练集 NMSE</th>
<th>
				测试集 NMSE</th>
<th>
				说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>
				 <span class='MathJax_Preview'><img src='https://www.codelast.com/wp-content/plugins/latex/cache/tex_014672d406888f94e9d3bfd97478d21b.gif' style='vertical-align: middle; border: none; padding-bottom:2px;' class='tex' alt="y = c_0 x_1 + c_1" /></span><script type='math/tex'>y = c_0 x_1 + c_1</script> </td>
<td>
				0.998</td>
<td>
				0.992</td>
<td>
				线性</td>
</tr>
<tr>
<td>
				 <span class='MathJax_Preview'><img src='https://www.codelast.com/wp-content/plugins/latex/cache/tex_92f83d155bc22a983410fda0f01ec234.gif' style='vertical-align: middle; border: none; padding-bottom:2px;' class='tex' alt="y = c_0 x_1^2 + c_1 x_1 + c_2" /></span><script type='math/tex'>y = c_0 x_1^2 + c_1 x_1 + c_2</script> </td>
<td>
				0.998</td>
<td>
				0.991</td>
<td>
				二次多项式</td>
</tr>
</tbody>
</table>
<p>
	最优变异后（1 步，2 父本，111 个候选）：</p>
<table>
<thead>
<tr>
<th>
				公式</th>
<th>
				训练集 NMSE</th>
<th>
				测试集 NMSE</th>
<th>
				说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>
				 <span class='MathJax_Preview'><img src='https://www.codelast.com/wp-content/plugins/latex/cache/tex_946a2a9b94d33b464cf5b290f803a2bb.gif' style='vertical-align: middle; border: none; padding-bottom:2px;' class='tex' alt="y = \frac{c_0 x_1 + c_1}{c_2 e^{c_3 x_2} + 1}" /></span><script type='math/tex'>y = \frac{c_0 x_1 + c_1}{c_2 e^{c_3 x_2} + 1}</script> </td>
<td>
				<strong>0.270</strong></td>
<td>
				<strong>0.319</strong></td>
<td>
				分式 + 指数，引入 x₂</td>
</tr>
<tr>
<td>
				 <span class='MathJax_Preview'><img src='https://www.codelast.com/wp-content/plugins/latex/cache/tex_c018833bc177671a6392dfce09c6e2b1.gif' style='vertical-align: middle; border: none; padding-bottom:2px;' class='tex' alt="y = (c_0 + c_1 x_1) e^{c_2 x_2}" /></span><script type='math/tex'>y = (c_0 + c_1 x_1) e^{c_2 x_2}</script> </td>
<td>
				0.271</td>
<td>
				0.303</td>
<td>
				线性 &times; 指数</td>
</tr>
<tr>
<td>
				 <span class='MathJax_Preview'><img src='https://www.codelast.com/wp-content/plugins/latex/cache/tex_6c484efca940a461ff28273aa68f18b7.gif' style='vertical-align: middle; border: none; padding-bottom:2px;' class='tex' alt="y = c_0 x_1 + c_1 + c_2 e^{c_3 x_2}" /></span><script type='math/tex'>y = c_0 x_1 + c_1 + c_2 e^{c_3 x_2}</script> </td>
<td>
				0.283</td>
<td>
				0.344</td>
<td>
				线性 + 指数</td>
</tr>
</tbody>
</table>
<p>
	<strong>退化模式瓶颈</strong>：种子只使用 x1，NMSE approx 1.0；一轮变异后最优 NMSE 0.270（解释 ~73% 方差）。但缺乏 LLM 指引方向，变异盲目枚举（111 个候选中仅少数引入 x2，无法发现 sin 等函数）。</p>
<h4 id="-b-deepseek-200-">
	模式 B：完整模式结果（使用 DeepSeek，200 样本）</h4>
<p>
	<strong>1. LLM Generator 领域分析</strong></p>
<p>
	LLM 成功分析出数据集属于&quot;通用符号回归 / 数学建模&quot;领域，输出了 20+ 个经典公式模式供种子生成参考。</p>
<p>
	<strong>2. LLM 种子生成</strong></p>
<table>
<thead>
<tr>
<th>
				种子公式</th>
<th>
				训练集 NMSE</th>
<th>
				测试集 NMSE</th>
<th>
				说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>
				 <span class='MathJax_Preview'><img src='https://www.codelast.com/wp-content/plugins/latex/cache/tex_178eecbf529ffa520f98b76afb7a69d3.gif' style='vertical-align: middle; border: none; padding-bottom:2px;' class='tex' alt="y = c_0 + c_1 x_2 + c_2 x_3 + c_3 x_4 + c_4 x_5" /></span><script type='math/tex'>y = c_0 + c_1 x_2 + c_2 x_3 + c_3 x_4 + c_4 x_5</script> </td>
<td>
				~0.89</td>
<td>
				~0.89</td>
<td>
				LLM 尝试全部 5 个变量</td>
</tr>
<tr>
<td>
				 <span class='MathJax_Preview'><img src='https://www.codelast.com/wp-content/plugins/latex/cache/tex_84bd8311a8509c4584be9e5a1f1537f3.gif' style='vertical-align: middle; border: none; padding-bottom:2px;' class='tex' alt="y = c_0 x_2^{c_1} x_3^{c_2}" /></span><script type='math/tex'>y = c_0 x_2^{c_1} x_3^{c_2}</script> </td>
<td>
				~0.84</td>
<td>
				~0.84</td>
<td>
				LLM 聚焦 x₂, x₃</td>
</tr>
<tr>
<td>
				 <span class='MathJax_Preview'><img src='https://www.codelast.com/wp-content/plugins/latex/cache/tex_cf66b26a432f33f6936b314431517e67.gif' style='vertical-align: middle; border: none; padding-bottom:2px;' class='tex' alt="y = c_0 e^{c_1 x_2} + c_2 \sin(c_3 x_3 + c_4)" /></span><script type='math/tex'>y = c_0 e^{c_1 x_2} + c_2 \sin(c_3 x_3 + c_4)</script> </td>
<td>
				<strong>~0.35</strong></td>
<td>
				<strong>~0.34</strong></td>
<td>
				LLM 直接猜中 sin + exp 结构！</td>
</tr>
<tr>
<td>
				 <span class='MathJax_Preview'><img src='https://www.codelast.com/wp-content/plugins/latex/cache/tex_b365f6ffe6e05aa663ea8fa1056862fa.gif' style='vertical-align: middle; border: none; padding-bottom:2px;' class='tex' alt="y = c_0 x_2^2 x_3^{c_1}" /></span><script type='math/tex'>y = c_0 x_2^2 x_3^{c_1}</script> （退化兜底）</td>
<td>
				~0.84</td>
<td>
				~0.84</td>
<td>
				&mdash;</td>
</tr>
</tbody>
</table>
<p>
	LLM 的第三个种子 c0<em>exp(c1</em>x2) + c2<em>sin(c3</em>x3 + c4) 已经包含了 <strong>exp + sin</strong>，NMSE 仅 ~0.35，远超退化种子的 ~0.998。</p>
<p>
	<strong>3. LLM Mutator 变异建议</strong></p>
<p>
	LLM 为选中的父本生成了 <strong>20 条定向变异建议</strong>（退化模式中 ASTMutator 靠穷举生成了约 111 条），例如：&quot;尝试多项式展开&quot;、&quot;添加指数衰减项 exp&quot;、&quot;尝试分式结构&quot;、&quot;添加正弦/余弦项&quot;。</p>
<p>
	<strong>4. 各步最优公式</strong></p>
<p>
	LLM 1 步后：</p>
<table>
<thead>
<tr>
<th>
				公式</th>
<th>
				训练集 NMSE</th>
<th>
				测试集 NMSE</th>
<th>
				说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>
				 <span class='MathJax_Preview'><img src='https://www.codelast.com/wp-content/plugins/latex/cache/tex_a42775af54ff5c60746fda6e0a9c2a63.gif' style='vertical-align: middle; border: none; padding-bottom:2px;' class='tex' alt="y = c_0 e^{c_1 x_2} + c_2 \sin(c_3 x_3 + c_4) + c_5 \sin(c_6 x_4 + c_7)" /></span><script type='math/tex'>y = c_0 e^{c_1 x_2} + c_2 \sin(c_3 x_3 + c_4) + c_5 \sin(c_6 x_4 + c_7)</script> </td>
<td>
				<strong>0.224</strong></td>
<td>
				<strong>0.300</strong></td>
<td>
				双 sin + exp，引入 x₂~x₄</td>
</tr>
<tr>
<td>
				 <span class='MathJax_Preview'><img src='https://www.codelast.com/wp-content/plugins/latex/cache/tex_f7d4e21a85530238af9e2f6b8a39c528.gif' style='vertical-align: middle; border: none; padding-bottom:2px;' class='tex' alt="y = c_0 e^{c_1 x_2} + c_2 \sin(c_3 x_3 + c_4) + c_5 x_4^{c_6}" /></span><script type='math/tex'>y = c_0 e^{c_1 x_2} + c_2 \sin(c_3 x_3 + c_4) + c_5 x_4^{c_6}</script> </td>
<td>
				0.228</td>
<td>
				0.301</td>
<td>
				幂次替代 sin</td>
</tr>
<tr>
<td>
				 <span class='MathJax_Preview'><img src='https://www.codelast.com/wp-content/plugins/latex/cache/tex_3538fef286c5b856a86752e27d2484a6.gif' style='vertical-align: middle; border: none; padding-bottom:2px;' class='tex' alt="y = c_0 e^{c_1 x_2} + c_2 x_3 (c_3 + x_1)^{c_4} + c_5 \sin(c_6 x_3 + c_7)" /></span><script type='math/tex'>y = c_0 e^{c_1 x_2} + c_2 x_3 (c_3 + x_1)^{c_4} + c_5 \sin(c_6 x_3 + c_7)</script> </td>
<td>
				0.241</td>
<td>
				0.282</td>
<td>
				引入 x₁</td>
</tr>
</tbody>
</table>
<p>
	LLM 3 步后：</p>
<table>
<thead>
<tr>
<th>
				公式</th>
<th>
				训练集 NMSE</th>
<th>
				测试集 NMSE</th>
<th>
				说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>
				 <span class='MathJax_Preview'><img src='https://www.codelast.com/wp-content/plugins/latex/cache/tex_cec39a90f642189bb2921c23e4542f78.gif' style='vertical-align: middle; border: none; padding-bottom:2px;' class='tex' alt="\frac{c_0 x_1 + c_1 + (c_2 x_3 + c_3)(c_4 + c_5 x_3 + c_6 \sin(c_7 x_4 + c_8)) e^{c_9 x_2}}{c_2 x_3 + c_3}" /></span><script type='math/tex'>\frac{c_0 x_1 + c_1 + (c_2 x_3 + c_3)(c_4 + c_5 x_3 + c_6 \sin(c_7 x_4 + c_8)) e^{c_9 x_2}}{c_2 x_3 + c_3}</script> </td>
<td>
				<strong>0.081</strong></td>
<td>
				<strong>0.129</strong></td>
<td>
				复合分式 + sin + exp</td>
</tr>
<tr>
<td>
				 <span class='MathJax_Preview'><img src='https://www.codelast.com/wp-content/plugins/latex/cache/tex_39db71404ac9251c586c4ac7621b279c.gif' style='vertical-align: middle; border: none; padding-bottom:2px;' class='tex' alt="c_0 x_3 (c_1 + x_1)^{c_2} + c_3 e^{c_4 x_2} + c_5 x_3 e^{c_4 x_2} + c_6 e^{c_4 x_2} \sin(c_7 x_4 + c_8)" /></span><script type='math/tex'>c_0 x_3 (c_1 + x_1)^{c_2} + c_3 e^{c_4 x_2} + c_5 x_3 e^{c_4 x_2} + c_6 e^{c_4 x_2} \sin(c_7 x_4 + c_8)</script> </td>
<td>
				0.088</td>
<td>
				0.110</td>
<td>
				分项式</td>
</tr>
<tr>
<td>
				 <span class='MathJax_Preview'><img src='https://www.codelast.com/wp-content/plugins/latex/cache/tex_c5f1003e513a65312749530663039ff5.gif' style='vertical-align: middle; border: none; padding-bottom:2px;' class='tex' alt="\frac{c_0 x_2 + c_1 + (c_2 x_3 + c_3)(c_4 + c_5 x_3 + c_6 \sin(c_7 x_4 + c_8)) e^{c_9 x_2}}{c_2 x_3 + c_3}" /></span><script type='math/tex'>\frac{c_0 x_2 + c_1 + (c_2 x_3 + c_3)(c_4 + c_5 x_3 + c_6 \sin(c_7 x_4 + c_8)) e^{c_9 x_2}}{c_2 x_3 + c_3}</script> </td>
<td>
				0.099</td>
<td>
				0.157</td>
<td>
				类似结构</td>
</tr>
</tbody>
</table>
<hr />
<p>
	<strong>两种模式找到的最优函数：</strong></p>
<table>
<thead>
<tr>
<th>
				实验</th>
<th>
				最优公式</th>
<th>
				训练集 NMSE</th>
<th>
				测试集 NMSE</th>
</tr>
</thead>
<tbody>
<tr>
<td>
				<strong>真实公式</strong></td>
<td>
				 <span class='MathJax_Preview'><img src='https://www.codelast.com/wp-content/plugins/latex/cache/tex_957278b1d2df9c3fe6b7a55a527a1787.gif' style='vertical-align: middle; border: none; padding-bottom:2px;' class='tex' alt="y = \frac{\sin(x_1 x_2)}{\cos(x_3) + 1.5} + e^{-x_2} \ln(\lvert x_4 \rvert + 1) + \frac{x_1 x_3}{1 + x_5^2}" /></span><script type='math/tex'>y = \frac{\sin(x_1 x_2)}{\cos(x_3) + 1.5} + e^{-x_2} \ln(\lvert x_4 \rvert + 1) + \frac{x_1 x_3}{1 + x_5^2}</script> </td>
<td>
				<strong>1.77e-5</strong></td>
<td>
				<strong>2.14e-5</strong></td>
</tr>
<tr>
<td>
				<strong>退化 1 步</strong></td>
<td>
				 <span class='MathJax_Preview'><img src='https://www.codelast.com/wp-content/plugins/latex/cache/tex_946a2a9b94d33b464cf5b290f803a2bb.gif' style='vertical-align: middle; border: none; padding-bottom:2px;' class='tex' alt="y = \frac{c_0 x_1 + c_1}{c_2 e^{c_3 x_2} + 1}" /></span><script type='math/tex'>y = \frac{c_0 x_1 + c_1}{c_2 e^{c_3 x_2} + 1}</script> </td>
<td>
				<strong>0.270</strong></td>
<td>
				<strong>0.319</strong></td>
</tr>
<tr>
<td>
				<strong>LLM 1 步</strong></td>
<td>
				 <span class='MathJax_Preview'><img src='https://www.codelast.com/wp-content/plugins/latex/cache/tex_a42775af54ff5c60746fda6e0a9c2a63.gif' style='vertical-align: middle; border: none; padding-bottom:2px;' class='tex' alt="y = c_0 e^{c_1 x_2} + c_2 \sin(c_3 x_3 + c_4) + c_5 \sin(c_6 x_4 + c_7)" /></span><script type='math/tex'>y = c_0 e^{c_1 x_2} + c_2 \sin(c_3 x_3 + c_4) + c_5 \sin(c_6 x_4 + c_7)</script> </td>
<td>
				<strong>0.224</strong></td>
<td>
				<strong>0.300</strong></td>
</tr>
<tr>
<td>
				<strong>LLM 3 步</strong></td>
<td>
				 <span class='MathJax_Preview'><img src='https://www.codelast.com/wp-content/plugins/latex/cache/tex_bbd2672a9dd8f87d3e93658d4a44e781.gif' style='vertical-align: middle; border: none; padding-bottom:2px;' class='tex' alt="y = \frac{c_0 x_1 + c_1 + (c_2 x_3 + c_3)(c_4 + c_5 x_3 + c_6 \sin(c_7 x_4 + c_8)) e^{c_9 x_2}}{c_2 x_3 + c_3}" /></span><script type='math/tex'>y = \frac{c_0 x_1 + c_1 + (c_2 x_3 + c_3)(c_4 + c_5 x_3 + c_6 \sin(c_7 x_4 + c_8)) e^{c_9 x_2}}{c_2 x_3 + c_3}</script> </td>
<td>
				<strong>0.081</strong></td>
<td>
				<strong>0.129</strong></td>
</tr>
</tbody>
</table>
<p>
	NMSE 对比（越低越好）：</p>
<table>
<thead>
<tr>
<th>
				模式</th>
<th>
				步数</th>
<th>
				训练集 NMSE</th>
<th>
				测试集 NMSE</th>
<th>
				相比退化改善</th>
<th>
				关键发现</th>
</tr>
</thead>
<tbody>
<tr>
<td>
				真实公式</td>
<td>
				--</td>
<td>
				1.77e-5</td>
<td>
				2.14e-5</td>
<td>
				--</td>
<td>
				精度天花板</td>
</tr>
<tr>
<td>
				退化</td>
<td>
				1 步</td>
<td>
				0.270</td>
<td>
				0.319</td>
<td>
				基准</td>
<td>
				分式 + 指数（x₁, x₂）</td>
</tr>
<tr>
<td>
				LLM</td>
<td>
				1 步</td>
<td>
				<strong>0.224</strong></td>
<td>
				<strong>0.300</strong></td>
<td>
				&darr; 17%</td>
<td>
				发现 <strong>sin()</strong>，引入 x₃, x₄</td>
</tr>
<tr>
<td>
				LLM</td>
<td>
				<strong>3 步</strong></td>
<td>
				<strong>0.081</strong></td>
<td>
				<strong>0.129</strong></td>
<td>
				<strong>&darr; 70%</strong></td>
<td>
				复合分式 + sin + exp（x₁~x₄）</td>
</tr>
</tbody>
</table>
<blockquote>
<p>
		LLM 1 步内就发现了退化模式无法找到的 <strong>sin()</strong>。3 步后 NMSE 降到 <strong>0.081</strong>（解释 ~92% 方差），但 x₁&times;x₂ 的 sin 交互和 x₅ 尚未被完整识别。预计 LLM 模式 5~10 步可收敛到 NMSE &lt; 1e-3。</p>
</blockquote>
<h4 id="-">
	当前进度与收敛预估</h4>
<table>
<thead>
<tr>
<th>
				维度</th>
<th>
				值</th>
</tr>
</thead>
<tbody>
<tr>
<td>
				变量数</td>
<td>
				5（x₁~x₅）</td>
</tr>
<tr>
<td>
				函数种类</td>
<td>
				sin, cos, exp, log, 除法（5 种）</td>
</tr>
<tr>
<td>
				交互关系</td>
<td>
				x₁&times;x₂, x₁&times;x₃, x₂（指数项）, x₄（对数项）, x₅（分式）</td>
</tr>
<tr>
<td>
				噪声</td>
<td>
				0.02 标准差</td>
</tr>
</tbody>
</table>
<p>
	当前实验进度（基于 200 训练样本 + 100 测试样本）：</p>
<table>
<thead>
<tr>
<th>
				实验</th>
<th>
				训练集 NMSE</th>
<th>
				测试集 NMSE</th>
<th>
				关键发现</th>
</tr>
</thead>
<tbody>
<tr>
<td>
				退化 1 步</td>
<td>
				0.270</td>
<td>
				0.319</td>
<td>
				分式 + 指数，仅 x₁, x₂</td>
</tr>
<tr>
<td>
				LLM 1 步</td>
<td>
				0.224</td>
<td>
				0.300</td>
<td>
				发现 <strong>sin()</strong>，引入 x₃, x₄</td>
</tr>
<tr>
<td>
				LLM <strong>3 步</strong></td>
<td>
				<strong>0.081</strong></td>
<td>
				<strong>0.129</strong></td>
<td>
				复合分式 + sin + exp，引入 x₁~x₄</td>
</tr>
</tbody>
</table>
<p>
	LLM 3 步后 NMSE 0.081（解释 ~92% 方差），已成功发现 sin() 函数并引入了 x₁~x₄ 四个变量。但真实公式中 x₁&times;x₂ 的 sin 交互、x₁&times;x₃ 的分式交互以及 x₅ 的分式尚未被完整识别。预计：</p>
<ul>
<li>
		<strong>LLM 模式</strong>：5~10 步可收敛到 NMSE &lt; 1e-3</li>
<li>
		<strong>退化模式</strong>：相同步数下 NMSE 下降仅 ~18%/步，效率远低于 LLM</li>
</ul>
<p>
	这正是 FunctionEvolve 采用 LLM + 数值优化混合架构的原因&mdash;&mdash;<strong>LLM 提供方向，数值优化负责精确拟合</strong>。<br />
	<span style="color: rgb(255, 255, 255);">文章来源：</span><a href="https://www.codelast.com/" rel="noopener noreferrer" target="_blank"><span style="color: rgb(255, 255, 255);">https://www.codelast.com/</span></a></p>
<h3 id="step-6-">
	Step 6：清理临时环境</h3>
<pre>
<code class="lang-bash"><span class="hljs-comment"># 测试完成后删除临时环境</span>
<span class="hljs-attribute">micromamba</span> remove -n py312 --<span class="hljs-literal">all</span> -y
</code></pre>
<h3 id="-">
	总结</h3>
<table>
<thead>
<tr>
<th>
				项目</th>
<th>
				状态</th>
</tr>
</thead>
<tbody>
<tr>
<td>
				测试数据集生成</td>
<td>
				完成</td>
</tr>
<tr>
<td>
				测试脚本</td>
<td>
				完成（<code>datasets/z/run_test.py</code>）</td>
</tr>
<tr>
<td>
				退化模式（1 步）</td>
<td>
				完成（NMSE 0.270 / 0.319，无 LLM）</td>
</tr>
<tr>
<td>
				LLM 模式（1 步）</td>
<td>
				完成（NMSE 0.224 / 0.300，发现 sin()）</td>
</tr>
<tr>
<td>
				<strong>LLM 模式（3 步）</strong></td>
<td>
				<strong>完成（NMSE 0.081 / 0.129，解释 ~92% 方差）</strong></td>
</tr>
<tr>
<td>
				搜索正确性验证</td>
<td>
				全流程无错误，所有实验数据完整记录</td>
</tr>
<tr>
<td>
				临时环境清理</td>
<td>
				已删除</td>
</tr>
</tbody>
</table>
<p>
	<strong>结论</strong>：FunctionEvolve 的搜索管道可以正常运行。LLM 模式显著优于退化模式&mdash;&mdash;1 步即可发现退化模式无法找到的 sin() 函数，3 步后 NMSE 降至 <strong>0.081</strong>。其实上面的测试还没有找到最终的正确公式，由于我电脑性能不强，仅仅运行上面的测试就已经花了很长时间+风扇狂转，因此测试只能止步于此。但可以看到，FunctionEvolve相较于传统优化方法是有较大优势的。</p>
<p>	<span style="color: rgb(255, 255, 255);">文章来源：</span><a href="https://www.codelast.com/" rel="noopener noreferrer" target="_blank"><span style="color: rgb(255, 255, 255);">https://www.codelast.com/</span></a><br />
	<span style="color: rgb(255, 0, 0);">➤➤</span> 版权声明 <span style="color: rgb(255, 0, 0);">➤➤</span>&nbsp;<br />
	转载需注明出处：<u><a href="https://www.codelast.com/" rel="noopener noreferrer" target="_blank"><em><span style="color: rgb(0, 0, 255);"><strong style="font-size: 16px;"><span style="font-family: arial, helvetica, sans-serif;">codelast.com</span></strong></span></em></a></u>&nbsp;<br />
	感谢关注我的微信公众号（微信扫一扫）：<br />
	<img decoding="async" alt="wechat qrcode of codelast" src="https://www.codelast.com/codelast_wechat_qr_code.jpg" style="color: rgb(77, 77, 77); font-size: 13px; width: 200px; height: 200px;" /><br />
	以及我的微信视频号：</p>
<p style="border: 0px; font-size: 13px; margin: 0px 0px 9px; outline: 0px; padding: 0px; color: rgb(77, 77, 77);">
	<img decoding="async" alt="" src="https://www.codelast.com/wechat_shipinhao_qr_code.jpg" style="text-align: center; width: 200px; height: 199px;" /></p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.codelast.com/%e5%8e%9f%e5%88%9b-%e7%bb%93%e5%90%88%e5%a4%a7%e6%a8%a1%e5%9e%8bllm%e7%9a%84%e5%87%bd%e6%95%b0%e6%90%9c%e7%b4%a2%e5%99%a8-functionevolve-%e7%ae%80%e5%8d%95%e5%ae%9e%e6%b5%8b/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
