优化FireCenter部分代码

main
PeterAlbus 2 years ago
parent 4c6d1a2aba
commit 410754e6a7

@ -4,6 +4,7 @@ import com.peteralbus.entity.*;
import com.peteralbus.service.EarthquakeInfoService;
import com.peteralbus.service.EstimateService;
import com.peteralbus.service.FireCenterService;
import com.peteralbus.util.EstimateUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
@ -12,159 +13,186 @@ import org.springframework.web.bind.annotation.RestController;
import java.util.*;
/**
* The type Fire center controller.
*/
@CrossOrigin
@RestController
public class FireCenterController {
private FireCenterService fireCenterService;
private EstimateController estimateController;
private EstimateService estimateService;
private EarthquakeInfoService earthquakeInfoService;
private EstimateUtil estimateUtil;
/**
* The Max fire center count.
*/
static Integer MAX_FIRE_CENTER_COUNT = 20;
/**
* Sets fire center service.
*
* @param fireCenterService the fire center service
*/
@Autowired
FireCenterService fireCenterService;
public void setFireCenterService(FireCenterService fireCenterService) {
this.fireCenterService = fireCenterService;
}
/**
* Sets estimate controller.
*
* @param estimateController the estimate controller
*/
@Autowired
EstimateController estimateController;
public void setEstimateController(EstimateController estimateController) {
this.estimateController = estimateController;
}
/**
* Sets estimate service.
*
* @param estimateService the estimate service
*/
@Autowired
EstimateService estimateService;
public void setEstimateService(EstimateService estimateService) {
this.estimateService = estimateService;
}
/**
* Sets earthquake info service.
*
* @param earthquakeInfoService the earthquake info service
*/
@Autowired
public void setEarthquakeInfoService(EarthquakeInfoService earthquakeInfoService) {
this.earthquakeInfoService = earthquakeInfoService;
}
/**
* Sets estimate util.
*
* @param estimateUtil the estimate util
*/
@Autowired
EarthquakeInfoService earthquakeInfoService;
public void setEstimateUtil(EstimateUtil estimateUtil) {
this.estimateUtil = estimateUtil;
}
/**
* Gets all fire center.
*
* @return the all fire center
*/
@RequestMapping("/getAllFireCenter")
public List<FireCenter> getAllFireCenter(){
public List<FireCenter> getAllFireCenter() {
return fireCenterService.getAllFireCenter();
}
//获取一个地震区域的消防站位置
public List<FireCenter> getOnePlaceAllFireCenter(Long earthquakeId){
List<FireCenter> fireCenters=getAllFireCenter();
List<FireCenter> fireCenterList=new ArrayList<>();
Map<String,Object>mapParameter=new HashMap<>();
mapParameter.put("earthquakeId",earthquakeId);
EarthquakeInfo earthquakeInfo=earthquakeInfoService.queryInfoWithLine(mapParameter).get(0);
for(FireCenter fireCenter:fireCenters){
double distanceTwoPlaces=getDistance(fireCenter.getFireLon(),fireCenter.getFireLat(),earthquakeInfo.getLongitude(),earthquakeInfo.getLatitude());
List<IntensityLine> intensityLineList=earthquakeInfo.getIntensityLineList();
if(distanceTwoPlaces<intensityLineList.get(intensityLineList.size()-1).getLongRadius())
{
/**
*
*
* @param earthquakeId the earthquake id
* @return the one place all fire center
*/
public List<FireCenter> getOnePlaceAllFireCenter(Long earthquakeId) {
List<FireCenter> fireCenters = fireCenterService.getAllFireCenter();
List<FireCenter> fireCenterList = new ArrayList<>();
Map<String, Object> mapParameter = new HashMap<>();
mapParameter.put("earthquakeId", earthquakeId);
EarthquakeInfo earthquakeInfo = earthquakeInfoService.queryInfoWithLine(mapParameter).get(0);
for (FireCenter fireCenter : fireCenters) {
double distanceTwoPlaces = getDistance(fireCenter.getFireLon(), fireCenter.getFireLat(), earthquakeInfo.getLongitude(), earthquakeInfo.getLatitude());
List<IntensityLine> intensityLineList = earthquakeInfo.getIntensityLineList();
if (distanceTwoPlaces < intensityLineList.get(intensityLineList.size() - 1).getLongRadius()) {
fireCenterList.add(fireCenter);
}
}
return fireCenterList;
}
/**
* Gets one fire center.
*
* @param id the id
* @return the one fire center
*/
@RequestMapping("/getOneFireCenter")
public FireCenter getOneFireCenter(int id){
public FireCenter getOneFireCenter(int id) {
return fireCenterService.getAllFireCenter().get(id);
}
/**
* IDfireCenterCount.
*
* @param earthquakeId ID
* @param fireCenterCount
* @return FireWeight
*/
@RequestMapping("/findFireCenterNearby")
public List<FireWeight> getFireCenterWeight(Long earthquakeId){
List<FireCenter> OnePlaceAllFireCenter=getOnePlaceAllFireCenter(earthquakeId);
List<Double> FireCenterIntensityArr=new ArrayList<>();
for(FireCenter fireCenter:OnePlaceAllFireCenter){
FireCenterIntensityArr.add(estimateController.getPointIntensity(earthquakeId, fireCenter.getFireLon(), fireCenter.getFireLat()));
}
int FireCenterIntensityArSize=FireCenterIntensityArr.size();
System.out.print("FireCenterIntensityArSize长度为"+FireCenterIntensityArSize);
if(FireCenterIntensityArSize==0){
public List<FireWeight> getFireCenterWeight(Long earthquakeId, Integer fireCenterCount) {
if (fireCenterCount > MAX_FIRE_CENTER_COUNT) {
// 自行修改封装后的返回值,错误:资助点数量不能过多
return null;
}
Map<Integer,Integer>map = new HashMap<Integer,Integer>();
for(int i=0;i<FireCenterIntensityArSize;i++){
map.put(i,OnePlaceAllFireCenter.get(i).getFireId());
}
double [][] arr=new double [10][FireCenterIntensityArSize];
//通过earthquakeId获得想要的地区的估计结果
Estimate estimate=estimateService.queryAnalyzeById(earthquakeId);
int temp=0;
for(double f:FireCenterIntensityArr){
arr[0][temp]=f*100;//属性1对于资助点1、2、3的值,因为基本上属性是固定的,可能资助点的数量会增加,假定属性最大值为10个
arr[1][temp]=estimate.getPopulation()*f+100*Math.random();
arr[2][temp]=Math.log(estimate.getPredictDeath()*estimate.getPredictEconomy())+100*Math.random();
temp++;
}
// arr[1]=new double[] {0.847,0.63,0.921};
// arr[2]=new double[] {524,439,842};
double [][]arrNew=new double[10][FireCenterIntensityArSize];
double [][]arrNew1=new double[10][FireCenterIntensityArSize];
double sumProvide=0;
double max;
double min;
int strictNum=arr[0].length;//代表有多少个救助点
double k=1/(Math.log((double)strictNum));
double[] e=new double[10];//第 j 项指标的熵值 ej
double[] g=new double[10];//差异性系数 gi越大指标越重要
for(int j=0;j<3;j++) {
min=max=arr[j][0];
sumProvide=0;
for(int i=0;i<arr[j].length;i++) {
if(arr[j][i]<min) {
min=arr[j][i];
}
if(arr[j][i]>max) {
max=arr[j][i];
}
}
for(int i=0;i<arr[j].length;i++) {
arrNew[j][i]=(arr[j][i]-min)/(max-min);//假设都是正向指标,正向指标的值越大,就说明该地方越需要救助
arrNew1[j][i]=arrNew[j][i];
sumProvide+=arrNew[j][i];
}
for(int i=0;i<arr[j].length;i++) {
arrNew[j][i]=(arrNew[j][i]/sumProvide)+0.0000001;
}
double sumArrNewHang=0.0;
for(int i=0;i<arr[j].length;i++) {
//System.out.println("sum"+Math.log(arrNew[j][i]));
sumArrNewHang+=(arrNew[j][i]*Math.log(arrNew[j][i]));
List<FireCenter> fireCenterList = getOnePlaceAllFireCenter(earthquakeId);
List<FireCenter> randomFireCenterList = new ArrayList<>();
Random random = new Random();
// 随机选取 fireCenterCount 个消防站
for (int i = 0; i < fireCenterCount; i++) {
if(fireCenterList.size()==0){
break;
}
e[j]=(-k)*sumArrNewHang;
g[j]=1-e[j];
int index = random.nextInt(fireCenterList.size());
randomFireCenterList.add(fireCenterList.get(index));
fireCenterList.remove(index);
}
double[] a=new double[10];//每个属性所占的权数
double SumG=0.0;
for(int i=0;i<g.length;i++) {
SumG+=g[i];
}
for(int i=0;i<g.length;i++) {
a[i]=g[i]/SumG;
}
double[]w=new double[strictNum];
for(int j=0;j<strictNum;j++) {
w[j]=0;
for(int i=0;i<3;i++) {
w[j]+=a[i]*arrNew1[i][j];
}
// w[j]=1-w[j];
int randomFireCenterListSize = randomFireCenterList.size();
if(randomFireCenterList.size()==0) {
// 自行修改封装后的返回值,错误:该地区没有找到消防站
return null;
}
Map arrayStrict=new HashMap();
List<Double> arrayW1=new ArrayList<>();
Map topTen=new LinkedHashMap();
List <FireWeight> resultFireWeightLists=new ArrayList<>();
for(int i=0;i<strictNum;i++){
arrayW1.add(w[i]);
// System.out.println("第+"+(i+1)+"个地区的权重值为"+w[i]);
// arrayStrict.put(i+1,w[i]);
arrayStrict.put(i,w[i]);
double[][] arr = new double[randomFireCenterListSize][10];
int temp = 0;
//通过earthquakeId获得想要的地区的估计结果
Estimate estimate = estimateService.queryAnalyzeById(earthquakeId);
// 依次设定每个救援点的指标最多可以设置10个指标
for (FireCenter fireCenter : randomFireCenterList) {
Double intensity = estimateController.getPointIntensity(earthquakeId, fireCenter.getFireLon(), fireCenter.getFireLat());
arr[temp][0] = intensity * 100;
arr[temp][1] = estimate.getPopulation() * intensity + 100 * Math.random();
arr[temp][2] = Math.log(estimate.getPredictDeath() * estimate.getPredictEconomy()) + 100 * Math.random();
temp++;
}
List<Map.Entry<Integer,Double>> entrys=new ArrayList<>(arrayStrict.entrySet());
Collections.sort(entrys, new MyComparator());
//输出排序后的键值对
int count=0;
for(Map.Entry<Integer,Double> entry:entrys){
topTen.put(entry.getKey(),entry.getValue());
FireCenter resultFireCenter=getOneFireCenter(map.get(entry.getKey()));
FireWeight fireWeight=new FireWeight();
fireWeight.setFireId(resultFireCenter.getFireId());
fireWeight.setFireLat(resultFireCenter.getFireLat());
fireWeight.setFireLon(resultFireCenter.getFireLon());
fireWeight.setFireName(resultFireCenter.getFireName());
fireWeight.setFireAddress(resultFireCenter.getFireAddress());
fireWeight.setFireCenterWeight(entry.getValue());
Double[] weights = estimateUtil.entropyMethod(arr,randomFireCenterListSize,3,new ArrayList<Integer>(Arrays.asList(0,1,2)));
List<FireWeight> resultFireWeightLists = new ArrayList<>();
for (int i=0;i<randomFireCenterListSize;i++) {
FireWeight fireWeight = new FireWeight();
fireWeight.setFireId(randomFireCenterList.get(i).getFireId());
fireWeight.setFireLat(randomFireCenterList.get(i).getFireLat());
fireWeight.setFireLon(randomFireCenterList.get(i).getFireLon());
fireWeight.setFireName(randomFireCenterList.get(i).getFireName());
fireWeight.setFireAddress(randomFireCenterList.get(i).getFireAddress());
fireWeight.setFireCenterWeight(weights[i]);
resultFireWeightLists.add(fireWeight);
count++;
if(count==30){
break;
}
}
// return arrayW1;
// return topTen;
// 返回值自行封装
return resultFireWeightLists;
}
private static final double EARTH_RADIUS = 6378.137;
/**
* Gets distance.
*
* @param longitude1 the longitude 1
* @param latitude1 the latitude 1
* @param longitude2 the longitude 2
* @param latitude2 the latitude 2
* @return the distance
*/
public static double getDistance(double longitude1, double latitude1, double longitude2, double latitude2) {
// 纬度
double lat1 = Math.toRadians(latitude1);
@ -179,7 +207,7 @@ public class FireCenterController {
// 计算两点距离的公式
double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(lat1) * Math.cos(lat2) * Math.pow(Math.sin(b / 2), 2)));
// 弧长乘地球半径, 返回单位: 千米
s = s * EARTH_RADIUS;
s = s * EARTH_RADIUS;
return s;
}
}

@ -4,6 +4,9 @@ import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author lakefish
*/
@Data
@AllArgsConstructor
@NoArgsConstructor

@ -5,5 +5,5 @@ import com.peteralbus.entity.FireCenter;
import java.util.List;
public interface FireCenterService {
List<FireCenter>getAllFireCenter();
List<FireCenter> getAllFireCenter();
}

@ -8,11 +8,23 @@ import org.springframework.stereotype.Service;
import java.util.List;
/**
* The type Fire center service.
* @author wuhon
*/
@Service
public class FireCenterServiceImpl implements FireCenterService {
/**
* The Fire center mapper.
*/
FireCenterMapper fireCenterMapper;
/**
* Sets fire center mapper.
*
* @param fireCenterMapper the fire center mapper
*/
@Autowired
public void setFireCenterMapper(FireCenterMapper fireCenterMapper) {
this.fireCenterMapper = fireCenterMapper;

@ -1,12 +1,17 @@
package com.peteralbus.util;
import com.peteralbus.entity.FireWeight;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* The type Estimate util.
*
* @author PeterAlbus
*/
@Component
@ -15,14 +20,16 @@ public class EstimateUtil
/**
* death predict int.
*
* @param population the population
* @param magnitude the magnitude
* @param earthquakeId the earthquake id
* @param population the population
* @param magnitude the magnitude
* @param intensity the intensity
* @param earthquakeTime the time of earthquake
* @param longitude the longitude
* @param latitude the latitude
* @param longitude the longitude
* @param latitude the latitude
* @return the double
*/
public double deathPredict(Long earthquake_id,int population, double magnitude, double intensity, LocalDateTime earthquakeTime,Double longitude,Double latitude)
public double deathPredict(Long earthquakeId,int population, double magnitude, double intensity, LocalDateTime earthquakeTime,Double longitude,Double latitude)
{
double deathPredict = 0;
/*M为震级 I为震中强度*/
@ -67,7 +74,82 @@ public class EstimateUtil
* @return the double
*/
public double economyPredict(double highIntensity)
{return Math.pow(10,0.84444*highIntensity-1.831)/10000;
{
return Math.pow(10,0.84444*highIntensity-1.831)/10000;
}
/**
* 使
*
* @param data pointCountparameterCount
* @param pointCount
* @param parameterCount
* @param positiveIndicatorsIndex
* @return Double[pointCount], data
*/
public Double[] entropyMethod(double[][] data, int pointCount, int parameterCount, List<Integer> positiveIndicatorsIndex) {
Double[] max = new Double[parameterCount];
Double[] min = new Double[parameterCount];
Double[] sum = new Double[parameterCount];
// 求出每个属性的最大值、最小值
for(int i = 0; i < parameterCount; i++) {
max[i] = Double.MIN_VALUE;
min[i] = Double.MAX_VALUE;
sum[i] = 0.0;
for(int j=0;j<pointCount;j++) {
if(data[j][i] > max[i]) {
max[i] = data[j][i];
}
if(data[j][i] < min[i]) {
min[i] = data[j][i];
}
}
}
// 归一化
Double[][] normalizedData = new Double[pointCount][parameterCount];
for(int i = 0; i < parameterCount; i++) {
for(int j=0;j < pointCount;j++) {
if(positiveIndicatorsIndex.contains(i)) {
normalizedData[j][i] = (data[j][i] - min[i]) / (max[i] - min[i]);
} else {
normalizedData[j][i] = (max[i] - data[j][i]) / (max[i] - min[i]);
}
sum[i] += normalizedData[j][i];
}
}
// 每个属性指标值在该属性所有数值中的比例
Double[][] percentage = new Double[pointCount][parameterCount];
for(int i = 0; i < parameterCount; i++) {
for(int j=0;j<pointCount;j++) {
percentage[j][i] = normalizedData[j][i] / sum[i] + 0.000000000001;
}
}
// 熵值
Double[] entropy = new Double[parameterCount];
// 变异系数的总和
double sumG = 0.0;
for(int i = 0; i < parameterCount; i++) {
double sumJ = 0.0;
for(int j=0;j< pointCount;j++) {
sumJ += percentage[j][i] * Math.log(percentage[j][i]);
}
entropy[i] = (-1/Math.log(10))*sumJ;
sumG += 1 - entropy[i];
}
// 每个系数的权重
Double[] parameterWeight = new Double[parameterCount];
for(int i = 0; i < parameterCount; i++) {
parameterWeight[i] = (1 - entropy[i]) / sumG;
}
// 计算每个点的权重
Double[] weight = new Double[pointCount];
for(int i = 0; i < pointCount; i++) {
weight[i] = 0.0;
for(int j = 0; j < parameterCount; j++) {
weight[i] += percentage[i][j] * parameterWeight[j];
}
}
return weight;
}
}

@ -1,5 +1,6 @@
package com.peteralbus;
import com.peteralbus.controller.FireCenterController;
import com.peteralbus.entity.EarthquakeInfo;
import com.peteralbus.entity.Estimate;
import com.peteralbus.service.EarthquakeInfoService;
@ -16,9 +17,7 @@ import org.springframework.boot.test.context.SpringBootTest;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.*;
@SpringBootTest
class EarthquickApplicationTests
@ -29,41 +28,28 @@ class EarthquickApplicationTests
EstimateUtil estimateUtil;
@Autowired
EarthquakeInfoService earthquakeInfoService;
@Autowired
FireCenterController fireCenterController;
@Test
void contextLoads()
{
// long startTime = System.currentTimeMillis();
// Map<String, Object> mapParameter = new HashMap<String, Object>();
// mapParameter.put("earthquakeId",16);
// EarthquakeInfo earthquakeInfo=earthquakeInfoService.queryInfoWithLine(mapParameter).get(0);
// double magnitude = earthquakeInfo.getMagnitude(),
// highIntensity = earthquakeInfo.getHighIntensity(),
// longitude = earthquakeInfo.getLongitude(),
// latitude = earthquakeInfo.getLatitude(),
// longRadius = earthquakeInfo.getIntensityLineList().get(2).getLongRadius(),
// shortRadius = earthquakeInfo.getIntensityLineList().get(2).getShortRadius();
// System.out.println(longRadius);
// LocalDateTime earthquakeTime = earthquakeInfo.getEarthquakeTime();
// //将角度转换为弧度。
// double radians = Math.toRadians(latitude);
// double minLongitude = longitude-shortRadius/(111-Math.cos(radians)),
// maxLongitude = longitude+shortRadius/(111-Math.cos(radians)),
// minLatitude = latitude-longRadius/111,
// maxLatitude = latitude+longRadius/111;
// int population=(int)estimateService.getPopulation(minLongitude,maxLongitude,minLatitude,maxLatitude);
// double death=estimateUtil.deathPredict(earthquakeInfo.getEarthquakeId(),population,magnitude,highIntensity,earthquakeTime,longitude,latitude);
// long endTime = System.currentTimeMillis();
// long usedTime = (endTime-startTime)/1000;
// System.out.println(death + " " + usedTime);
// getPopulation(100.7342,25.5736);
// getPopulation(99.9586,25.6753);
// getPopulation(100.1926,25.9121);
// getPopulation(100.1885,25.9252);
// getPopulation(99.7768,25.3342);
// getPopulation(99.9586,25.6752);
// getPopulation(100.3105,25.6775);
// getPopulation(100.1209,25.7921);
// getPopulation(100.4937,25.3366);
System.out.println(fireCenterController.getFireCenterWeight(16L, 12));
// double[][] data = {{6.962645,67101.0,730.3979,1.3},
// {5.643831,50732.0,170.8517,1.7},
// {7.775079,39755.0,89.2054,1.0},
// {6.568763,67101.0,294.3379,1.0},
// {6.552100,67101.0,281.1741,1.9},
// {6.669364,43274.0,41.5144,1.2},
// {7.774892,39755.0,89.2054,1.4},
// {6.511145,67101.0,518.4596,1.4},
// {6.966898,67101.0,382.3772,1.7},
// {5.894564,35641.0,374.3219,1.2}};
// List<Integer> list = new ArrayList<>();
// list.add(0);
// list.add(2);
// list.add(3);
// System.out.println(Arrays.toString(estimateUtil.entropyMethod(data, 10, 4, list)));
}
void getPopulation(double longitude,double latitude)

Loading…
Cancel
Save