scipy中的曲线拟合工具倾向于假设模型函数的参数是实值的。 当将依赖于复值参数的模型拟合到复值数据集时,首先必须创建模型的版本,其中每个复杂参数被两个真实参数替换。
首先,一个简单的例子:
var selectedIndexPath :NSIndexPath?{
didSet{
if let indexpath = selectedIndexPath {
collectionView.collectionViewLayout.invalidateLayout()
collectionView.scrollToItemAtIndexPath(indexpath, atScrollPosition: .CenteredHorizontally, animated: true)
}
}
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize{
if indexPath == selectedIndexPath {
return CGSizeMake(100, 50) // selected size
}
else{
return CGSizeMake(50, 50)// default size
}
}
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
selectedIndexPath = indexPath
}
// make sure the first and last cell is at the center of CollectionView most
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAtIndex section: Int) -> UIEdgeInsets{
let firstItemsize = self.collectionView(collectionView, layout: collectionViewLayout, sizeForItemAtIndexPath: NSIndexPath(forItem: 0, inSection: section))
let numberOfItemsInSection = self.collectionView(collectionView, numberOfItemsInSection: section)
let lastItemSize = self.collectionView(collectionView, layout: collectionViewLayout, sizeForItemAtIndexPath: NSIndexPath(forItem: numberOfItemsInSection-1, inSection: section))
return UIEdgeInsetsMake(0, collectionView.frame.size.width/2-firstItemsize.width/2, 0, collectionView.frame.size.width/2-lastItemSize.width/2)
}
//MARK : - UIScrollViewDelegate
func scrollViewDidScroll(scrollView: UIScrollView){
selectedIndexPath = nil;
}
func scrollViewDidEndDragging(scrollView: UIScrollView, willDecelerate decelerate: Bool){
if !decelerate {
var centerPoint = collectionView.contentOffset
centerPoint.x += collectionView.frame.width/2
centerPoint.y += collectionView.frame.height/2
selectedIndexPath = collectionView.indexPathForItemAtPoint(centerPoint)
}
}
func scrollViewDidEndDecelerating(scrollView: UIScrollView){
var centerPoint = collectionView.contentOffset
centerPoint.x += collectionView.frame.width/2
centerPoint.y += collectionView.frame.height/2
selectedIndexPath = collectionView.indexPathForItemAtPoint(centerPoint)
}
注意:模型的输出仍然是复值的,但通过适当地定义残差函数可以很容易地解决这个问题。
现在,我不想为每个函数# original function, representing a model where a,b may be complex-valued
def f(x, a, b):
return a+b*x
# modified function, complex parameters have been replaced by two real ones
def f_r(x, a_r, a_i, b_r, b_i):
return f(x, a_r + 1J*a_i, b_r+1J*b_i)
print( f(1,2+3J,4+5J) == f_r(1,2,3,4,5) )
编写新代码,而是希望有一个"函数工厂"我将函数对象f
与一个布尔列表f
一起传递给它,指定is_complex
的哪些参数被假定为复值(因此需要用两个实数替换)有价值的论据)。
这个布尔值列表可以是例如从与f
一起提供的初始值推断出来。
我是这类问题的新手,所以我在网上浏览了decorator module。在进入通用案例之前,以下是使用f
类的上述示例:
Functionmaker
对于通用情况,现在可以想象合成传递给函数制作者的两个字符串:
import decorator
def f(x, a, b):
return a+b*x
f_r = decorator.FunctionMaker.create(
'f_r(x, a_r, a_i, b_r, b_i)',
'return f(x, a_r + 1J*a_i, b_r + 1J*b_i)',
dict(f=f))
这似乎解决了这个问题。
我的问题是:这是一种合理的做法吗?在python中有更好/更简单的方法吗?
P.S。我不是计算机科学家,所以如果我使用的技术术语不正确,请随时修改。
答案 0 :(得分:0)
您不必执行任何讨厌的基于字符串的生成,您只需使用基本函数闭包来创建包装器:
def complex_unroll(f, are_complex):
# This function will have access to are_complex and f through python closure
# *args give us access to all parameters as a list
def g(*args, **kwargs):
# new_args stores new list of parameters, the complex ones
new_args = []
# arg_id is iterator used to keep track where are we in the original list
arg_id = 0
for is_complex in are_complex:
if is_complex:
# if we request complex unroll, we merge two consequtive params
new_args.append(args[arg_id] + 1J*args[arg_id+1])
# and move iterator 2 slots
arg_id += 2
else:
# otherwise, just copy the argument
new_args.append(args[arg_id])
arg_id += 1
# finally we return a call to original function f with new args
return f(*new_args, **kwargs)
# our unroll function returns a newly designed function g
return g
现在
def f(x, a, b):
return a+b*x
def f_r(x, a_r, a_i, b_r, b_i):
return f(x, a_r + 1J*a_i, b_r+1J*b_i)
f_u = complex_unroll(f, [False, True, True])
print f(1,2+3J,4+5J)
print f_r(1,2,3,4,5)
print f_u(1,2,3,4,5)
f_u2 = complex_unroll(f, [True, True, True])
print f_u2(1,0,2,3,4,5)
按需运作。
为什么我更喜欢这条路径而不是问题中提议的路径?
f(x, a, b, flag)
,你仍然可以使用g = complex_unroll(f, [False, True, True])
并调用g(0, 0, 0, 0, 0, flag = True)
,这会在你的代码中失败。不过,您可以添加对此的支持。