我正在尝试找到函数f(x) = (sin(x)/x)^2
的局部最大值。
对于近似解,我初始化了两个变量x
和y
,并首先绘制了一个图形以具有可视化表示。
x = np.linspace(-20.0, 20.0, num=int((20+20)/0.01))
y = np.power(np.sin(x)/x, 2)
plt.plot(x, y, 'r.', markersize= 1)
plt.show()
这显示graph。
然后我尝试创建一个算法来查找Maxima:
def returnMaxima(num, x, y):
"""
number, np.array, np.array -> list
num: number of maxima needed | x: x 1D array | y: y 1D array
returns [[x1,y1], [x2,y2]...] in descending order of y
"""
allMaximaPoints = [] # stores all Maxima points
reqMaximaPoints = [] # stores num Maxima points
for i in range(y.size):
# for first y value
if i == 0:
if y[i] > y[i+1]:
allMaximaPoints += [[x[i], y[i]], ]
# for last y value
elif i == y.size - 1:
if y[i] > y[i-1]:
allMaximaPoints += [[x[i], y[i]], ]
# for rest y values
else:
if y[i] > y[i-1] and y[i] > y[i+1]:
allMaximaPoints += [[x[i], y[i]], ]
# extract largest maximas from allMaximaPoints
while num > 0:
reqMaximaPoints += [max(allMaximaPoints, key=lambda item:item[1]),]
del allMaximaPoints[allMaximaPoints.index(max(allMaximaPoints, key=lambda item:item[1]))]
num -= 1
return reqMaximaPoints
当我尝试returnMaxima(2, x, y)
时,我得到[[-4.4961240310077528, 0.04719010162459622],
[4.4961240310077528, 0.04719010162459622]]
。
这是错误的,因为它跳过x = 0
处的局部最大值。我怀疑是因为y[i-1]
y[i+1]
处y[i]
附近的x=0
和y[i]
值大约等于导致代码的else:
if y[i] > y[i-1] and y[i] > y[i+1]:
allMaximaPoints += [[x[i], y[i]], ]
x = np.linspace(-20.0, 20.0, num=int((20+20)/0.01))
不考虑那一点。这是因为当我将x = np.linspace(-20.0, 20.0, num=int((20+20)/0.1))
更改为x=0
,即x中的较大步数时,才能正确找到>
处的局部最大值。但是,即使我将上述代码中的>=
符号更改为x=0
,{{1}}处的最大值仍未计算在内。
为什么会这样?我应该如何改进我的代码以获得正确的结果? 谢谢!
答案 0 :(得分:1)
使用scipy.signal.find_peaks_cwt
之类的东西可能会更好。类似的东西:
indices = scipy.signal.find_peaks_cwt(y, [1, 2, 3, 4], noise_perc=50)
plt.plot(x, y)
plt.plot(x[indices], y[indices], 'r.')
plt.show()
结果:
答案 1 :(得分:0)
简短回答:x永远不会为0(你可能也不希望它是。)
我们可以通过运行
进行测试public class AllLoxMap extends FragmentActivity implements OnMapReadyCallback {
private GoogleMap mMap;
LocationManager lm;
LocationListener ll;
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == 1) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if (ContextCompat.checkSelfPermission(this, Manifest.permission
.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, ll);
Location lastKnownLocation = lm.getLastKnownLocation(LocationManager
.GPS_PROVIDER);
if (lastKnownLocation != null) {
updateMap(lastKnownLocation);
}
}
}
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_all_lox_map);
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
@Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
lm = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
ll = new LocationListener() {
@Override
public void onLocationChanged(Location location) {
updateMap(location);
}
@Override
public void onStatusChanged(String s, int i, Bundle bundle) {
}
@Override
public void onProviderEnabled(String s) {
}
@Override
public void onProviderDisabled(String s) {
}
};
if (ContextCompat.checkSelfPermission(this, Manifest.permission
.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission
.ACCESS_FINE_LOCATION}, 1);
} else {
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, ll);
Location lastKnownLocation = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (lastKnownLocation != null) {
updateMap(lastKnownLocation);
}
}
}
public void updateMap(Location location) {
LatLng userLocation = new LatLng(location.getLatitude(), location.getLongitude());
mMap.clear();
mMap.addMarker(new MarkerOptions().position(userLocation).title("Marker"));
mMap.moveCamera(CameraUpdateFactory.newLatLng(userLocation));
}
}
这实际上是幸运的,因为x = 0会导致运行时警告,并且由于除以0而产生“nan”(非数字)值。问题是函数未定义为0。
否则,您基本上是正确的,为什么它不起作用。如果您将In [53]: 0 in x
Out[53]: False
替换为>
,您会看到输出不同:
>=
这实际上是“正确的”输出,因为它们是最大的值,并且是x最接近0的值。