我在这里制作了一个实现优化算法的库。这些是相关功能和特征的签名:
pub fn cmaes_loop<T>(object: &T, options: CMAESOptions) -> Option<Vec<f64>>
where T: 'static + FitnessFunction
pub trait FitnessFunction {
fn get_fitness(&self, parameters: &[f64]) -> f64;
}
如果我将函数库应用于一个简单的问题,我可以根据给定的参数计算适应度。但是,假设我想针对给定的尺寸和材料优化机翼的形状:
struct Wing<'a> {
material: String,
size: i32,
parameters: &'a [f64]
}
我可以实现适应度函数来读取其他字段并将它们分解到计算中,然后给cmaes_loop
函数一个Wing
实例,以优化特定的材料和尺寸。我正在制作另一个将使用这个的库。它优化了其他内容(如Wing
(,所以我有一个包装器特征可以使第二个库更易于使用:
pub trait WingFitnessFunction {
fn get_fitness(&self, wing: &Wing) -> f64;
}
我像这样实现FitnessFunction
特征:
impl FitnessFunction for Wing {
fn get_fitness(&self, parameters: &[f64]) -> f64 {
let wing = Wing {
parameters: parameters,
.. self
};
// error here
let result = WingFitnessFunction::get_fitness(wing);
}
}
WingFitnessFunction
有一个&self
论点,原因与FitnessFunction
相同。我希望我的第二个库的用户能够传递实现WingFitnessFunction
的其类型的实例。我将FitnessFunction
的impl
放入一个函数的主体中,该函数采用用户类型的实例:
fn foo<T: WingFitnessFunction>(object: T) {
impl FitnessFunction for Wing {
...
object.get_fitness(wing)
}
但是当我尝试调用get_fitness
方法object
时,出现此错误:
无法捕获 FN 项目中的动态环境;请使用 ||{ ... }改为关闭形式
我需要知道如何在特定实例上调用object
的get_fitness
方法(闭包可以做到这一点,但我不知道如何使其与 cmaes_loop
函数一起使用(。
我的问题的解决方案是添加一个包装器:
struct WingWrapper<'a, T: WingFitnessFunction> {
wing: Wing,
object: T
}
并为其实现FitnessFunction
:
impl<'a, T: WingFitnessFunction> FitnessFunction for WingWrapper<'a, T> {
fn get_fitness(&self, parameters: &[f64]) -> f64 {
let wing = Wing {
parameters: parameters,
.. self.wing
}
self.object.get_fitness(&wing)
}
}
在将实现WingFitnessFunction
的类型作为参数的函数中,首先构建一个WingWrapper
:
let wrapper = WingWrapper {
wing: // Instance of wing here
object: // Instance of object here (taken as an argument)
}
现在,您可以通过FitnessFunction
的方法从WingFitnessFunction
特征调用get_fitness
方法:
println!("{}", wrapper.get_fitness(&[1, 2, 3]));
这不会增加使用库的任何困难;从用户的角度来看,它是完全相同的。