2025-03-28 09:49:56 +08:00

682 lines
34 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using SuperMap.RealEstate.ServiceModel;
using HWSB = SuperMap.RealEstate.HighWay.Storage.Business;
using Google.OrTools.LinearSolver; // 引用 OR-Tools 库
using Microsoft.ML.Data;
using Microsoft.ML;
using Transmission.SDK;
using HZQR.Common;
namespace DataBaseProcessing
{
public partial class TestForm : Form
{
public TestForm()
{
InitializeComponent();
}
#region
public class RevenueData
{
public float TotalRevenue { get; set; } // 服务区总营收
public Dictionary<string, float> ProvinceVehicleCounts { get; set; } // 每个省份的车辆数
}
public class VehicleValuePrediction
{
[ColumnName("Score")]
public float EstimatedVehicleValue { get; set; } // 估算每辆车的价值
}
public class RevenueInput
{
public Dictionary<string, float> ProvinceVehicleCounts { get; set; } = new Dictionary<string, float>(); // 动态省份车辆数据
public float TotalRevenue { get; set; } // 总营收
}
static async Task<RevenueData> GetRevenueDataFromApiAsync(DateTime date, string serviceAreaId)
{
Transaction transaction = new Transaction();
string SQLString = string.Format(@"SELECT
SUM(REVENUE_AMOUNT)
FROM
PLATFORM_DASHBOARD.T_REVENUEMONTHLY
WHERE
SERVERPART_ID = {0} AND STATISTICS_MONTH = {1}",
serviceAreaId, date.ToString("yyyyMM"));
DataTable dtRevenue = new HWSB.SERVERPART(transaction).ExecuteDataTable(SQLString);
SQLString = string.Format(@"SELECT * FROM HIGHWAY_SELLDATA.T_BAYONETPROVINCEMONTH_AH
WHERE SERVERPART_ID = {0} AND STATISTICS_MONTH = {1} AND SERVERPART_REGION IS NULL AND VEHICLE_TYPE IS NULL",
serviceAreaId, date.ToString("yyyyMM"));
DataTable dtBayonet = new HWSB.SERVERPART(transaction).ExecuteDataTable(SQLString);
var result = new RevenueData();
result.TotalRevenue = float.Parse(dtRevenue.Rows[0][0].TryParseToDecimal() + "");
result.ProvinceVehicleCounts = new Dictionary<string, float>();
foreach (DataRow drBayonet in dtBayonet.Select("", "VEHICLE_COUNT desc"))
{
result.ProvinceVehicleCounts.Add(drBayonet["PROVINCE_NAME"] + "",
float.Parse(drBayonet["VEHICLE_COUNT"].TryParseToDecimal() + ""));
}
transaction.Release();
transaction.Dispose();
return result;
}
static Dictionary<string, float> provinceSingleVehicleValues = new Dictionary<string, float>();
static void TrainAndPredict(List<RevenueInput> revenueInputs)
{
var mlContext = new MLContext();
// 动态获取所有省份名称并清理名称
//var provinceNames = revenueInputs.SelectMany(r => r.ProvinceVehicleCounts.Keys).Distinct().Select(p => p.Trim()).ToList();
var provinceNames = new List<string> { "北京市", "天津市", "上海市", "重庆市", "河北省", "河南省", "云南省", "辽宁省", "黑龙江省",
"湖南省", "安徽省", "山东省", "新疆维吾尔自治区", "江苏省", "浙江省", "江西省", "湖北省", "广西壮族自治区",
"甘肃省", "山西省", "内蒙古自治区", "陕西省", "吉林省", "福建省", "贵州省", "广东省", "青海省", "西藏自治区",
"四川省", "宁夏回族自治区", "海南省" };
int maxFeatureLength = provinceNames.Count; // 确定特征向量的最大长度
LogUtil.WriteLog("动态获取的省份列名:" + string.Join(", ", provinceNames));
LogUtil.WriteLog($"特征向量的最大长度:{maxFeatureLength}");
// 手动构建特征数组,确保每个输入数据的特征长度一致
var list = revenueInputs.Select(r =>
{
// 构建特征数组,填充缺失的省份数据为 0
var featureArray = provinceNames.Select(p => r.ProvinceVehicleCounts.ContainsKey(p) ? r.ProvinceVehicleCounts[p] : 0).ToList();
// 确保所有特征向量长度一致如果不够最大长度用0填充
while (featureArray.Count < maxFeatureLength)
{
featureArray.Add(0);
}
return new ModelInput(maxFeatureLength)
{
Features = featureArray.ToArray(), // 转换为固定长度数组
TotalRevenue = r.TotalRevenue
};
}).ToList();
var data = mlContext.Data.LoadFromEnumerable(list);
// 输出数据预览
var preview = data.Preview();
LogUtil.WriteLog("模型数据预览: ");
foreach (var column in preview.Schema)
{
LogUtil.WriteLog($"列名: {column.Name}, 类型: {column.Type}");
}
// 定义线性回归模型,使用动态生成的 Features 列
var pipeline = mlContext.Transforms.CopyColumns("Features", "Features")
.Append(mlContext.Regression.Trainers.Sdca(
labelColumnName: "TotalRevenue",
featureColumnName: "Features",
l2Regularization: (float?)1.0)); // 你可以调整 L2 正则化权重
// 训练模型
var model = pipeline.Fit(data);
// 获取每个省份的单车价值
var coefficients = model.LastTransformer.Model.Weights.ToArray();
if (coefficients.Length != provinceNames.Count)
{
throw new Exception("权重与省份数量不匹配,无法继续。");
}
for (int i = 0; i < provinceNames.Count; i++)
{
provinceSingleVehicleValues[provinceNames[i]] = coefficients[i];
}
// 输出各省份的单车价值
var sb = new StringBuilder();
sb.AppendLine("各省份的单车价值:");
foreach (var kvp in provinceSingleVehicleValues)
{
sb.AppendLine($"{kvp.Key}: {kvp.Value}");
}
LogUtil.WriteLog(sb.ToString());
}
// 定义用于模型输入的类
public class ModelInput
{
public ModelInput(int featureLength)
{
Features = new float[featureLength]; // 确保特征向量的长度在构造时定义
}
[VectorType(31)] // 请将 13 替换为实际的最大特征长度
public float[] Features { get; set; }
public float TotalRevenue { get; set; }
}
static void CalculateAndCompare(RevenueData revenueData)
{
float predictedTotalRevenue = 0;
float actualTotalRevenue = revenueData.TotalRevenue;
// 计算预测的总营收
foreach (var province in revenueData.ProvinceVehicleCounts)
{
if (provinceSingleVehicleValues.ContainsKey(province.Key))
{
predictedTotalRevenue += province.Value * provinceSingleVehicleValues[province.Key];
}
}
// 计算偏差值和偏差比例
float deviation = actualTotalRevenue - predictedTotalRevenue;
float deviationPercentage = deviation / actualTotalRevenue * 100;
// 输出结果
LogUtil.WriteLog($"实际总营收: {actualTotalRevenue}");
LogUtil.WriteLog($"预测总营收: {predictedTotalRevenue}");
LogUtil.WriteLog($"偏差值: {deviation}");
LogUtil.WriteLog($"偏差比例: {deviationPercentage}%");
}
public static async Task AnalyzeMultipleServiceAreas(List<string> serviceAreaIds, List<DateTime> dates)
{
try
{
var allRevenueDataList = new List<RevenueInput>();
foreach (var serviceAreaId in serviceAreaIds)
{
LogUtil.WriteLog($"服务区内码:{ serviceAreaId }");
foreach (var date in dates)
{
LogUtil.WriteLog($"统计日期:{ date }");
// 获取服务区和日期的营收和车辆数据
RevenueData revenueData = await GetRevenueDataFromApiAsync(date, serviceAreaId);
// 转换为模型输入格式
var revenueInput = new RevenueInput
{
ProvinceVehicleCounts = revenueData.ProvinceVehicleCounts,
TotalRevenue = revenueData.TotalRevenue
};
allRevenueDataList.Add(revenueInput);
// 比较预测和实际的营收
CalculateAndCompare(revenueData);
}
}
// 进行模型训练和预测
TrainAndPredict(allRevenueDataList);
}
catch (Exception ex)
{
LogUtil.WriteLog(ex, "", DateTime.Now.ToString("yyyyMMdd") + "_error");
}
}
#endregion
#region
// 模拟从API中获取数据的函数
public static Dictionary<string, Dictionary<string, object>> FetchDataForMonth(
string startMonth, string endMonth, string serverpartId)
{
Transaction transaction = new Transaction();
string SQLString = string.Format(@"SELECT
*
FROM
PLATFORM_DASHBOARD.T_REVENUEMONTHLY
WHERE
SERVERPART_ID = {0} AND STATISTICS_MONTH BETWEEN {1} AND {2}",
serverpartId, startMonth, endMonth);
DataTable dtRevenue = new HWSB.SERVERPART(transaction).ExecuteDataTable(SQLString);
SQLString = string.Format(@"SELECT * FROM HIGHWAY_SELLDATA.T_BAYONETPROVINCEMONTH_AH
WHERE SERVERPART_ID = {0} AND STATISTICS_MONTH BETWEEN {1} AND {2} AND SERVERPART_REGION IS NULL",
serverpartId, startMonth, endMonth);
DataTable dtBayonet = new HWSB.SERVERPART(transaction).ExecuteDataTable(SQLString);
// 示例数据:省份内部具体地区的小型车、大型车和中型车的车辆数,以及总收入
Dictionary<string, Dictionary<string, object>> provinceData = new Dictionary<string, Dictionary<string, object>>();
foreach (string month in dtRevenue.AsEnumerable().Select(o => o["STATISTICS_MONTH"] + "").Distinct().OrderBy(o => o))
{
Dictionary<string, Dictionary<string, int>> regionData = new Dictionary<string, Dictionary<string, int>>();
foreach (DataRow drBayonet in dtBayonet.Select("VEHICLE_TYPE is null and STATISTICS_MONTH = " + month, "VEHICLE_COUNT desc"))
{
regionData.Add(drBayonet["PROVINCE_NAME"].ToString(), new Dictionary<string, int>
{
{ "Small", dtBayonet.Compute("sum(VEHICLE_COUNT)", "VEHICLE_TYPE = '小型车' and PROVINCE_NAME = '" +
drBayonet["PROVINCE_NAME"] + "'").TryParseToInt() },
{ "Medium", dtBayonet.Compute("sum(VEHICLE_COUNT)", "VEHICLE_TYPE = '中型车' and PROVINCE_NAME = '" +
drBayonet["PROVINCE_NAME"] + "'").TryParseToInt() },
{ "Large", dtBayonet.Compute("sum(VEHICLE_COUNT)", "VEHICLE_TYPE = '大型车' and PROVINCE_NAME = '" +
drBayonet["PROVINCE_NAME"] + "'").TryParseToInt() }
});
}
provinceData.Add(month, new Dictionary<string, object>
{
{ "Regions", regionData },
{ "TotalRevenue", dtRevenue.Compute("sum(REVENUE_AMOUNT)", "STATISTICS_MONTH = " + month).TryParseToDecimal() }
});
}
//{
// { "Anhui", new Dictionary<string, object>
// {
// { "Regions", new Dictionary<string, Dictionary<string, int>>
// {
// { "Hefei", new Dictionary<string, int> { { "Small", 50000 }, { "Medium", 1000 }, { "Large", 10000 } } },
// { "Wuhu", new Dictionary<string, int> { { "Small", 30000 }, { "Medium", 800 }, { "Large", 8000 } } },
// { "Others", new Dictionary<string, int> { { "Small", 20000 }, { "Medium", 500 }, { "Large", 5000 } } }
// // 增加安徽省其他地区的数据
// }
// },
// { "TotalRevenue", 1200000.0 } // 更新安徽省的总收入数据
// }
// },
// { "Jiangsu", new Dictionary<string, object>
// {
// { "Regions", new Dictionary<string, Dictionary<string, int>>
// {
// { "Nanjing", new Dictionary<string, int> { { "Small", 12000 }, { "Medium", 200 }, { "Large", 2000 } } },
// { "Suzhou", new Dictionary<string, int> { { "Small", 11000 }, { "Medium", 150 }, { "Large", 1800 } } },
// { "Others", new Dictionary<string, int> { { "Small", 8000 }, { "Medium", 100 }, { "Large", 1200 } } } // 增加江苏省其他地区的数据
// }
// },
// { "TotalRevenue", 500000.0 } // 更新江苏省的总收入数据
// }
// }
// // 可以继续添加其他省份的数据
//};
transaction.Release();
transaction.Dispose();
return provinceData;
}
// 计算单车价值的函数
public static void CalculateSingleVehicleValue(Dictionary<string, Dictionary<string, object>> provinceData)
{
// 设置迭代参数:容忍误差范围、最大迭代次数
decimal tolerance = (decimal)0.01; // 允许的误差范围(百分之一)
int maxIterations = 1000; // 最大迭代次数,防止无限循环
// 遍历每个省份的数据
foreach (var province in provinceData)
{
string provinceName = province.Key;
var regions = (Dictionary<string, Dictionary<string, int>>)province.Value["Regions"];
decimal totalRevenue = (decimal)province.Value["TotalRevenue"];
// 计算初始的平均单车价值(将总营收除以车辆数的总和)
int totalVehicleCount = regions.Values.Sum(region => region["Small"] + region["Medium"] + region["Large"]);
decimal initialVehicleValue = totalRevenue / totalVehicleCount;
// 初始化每个地区的小型车和大型车的单车价值为平均值
Dictionary<string, decimal> smallVehicleValues = regions.ToDictionary(region => region.Key, region => initialVehicleValue);
Dictionary<string, decimal> largeVehicleValues = regions.ToDictionary(region => region.Key, region => initialVehicleValue);
int iteration = 0;
bool converged = false;
// 迭代计算以优化单车价值
while (!converged && iteration < maxIterations)
{
// 使用当前单车价值计算总营收
decimal calculatedRevenue = regions.Sum(region =>
{
string regionName = region.Key;
int smallCount = region.Value["Small"] + region.Value["Medium"]; // 中型车归属于小型车
int largeCount = region.Value["Large"];
return smallCount * smallVehicleValues[regionName] + largeCount * largeVehicleValues[regionName];
});
// 计算计算出的总营收与实际总营收之间的误差
decimal error = totalRevenue - calculatedRevenue;
// 如果误差在容忍范围内,则停止迭代
if (Math.Abs(error) <= tolerance)
{
converged = true;
break;
}
// 根据误差比例调整小型车和大型车的单车价值
decimal adjustmentRatio = 1 + (error / calculatedRevenue);
foreach (var regionName in regions.Keys.ToList())
{
smallVehicleValues[regionName] *= adjustmentRatio;
largeVehicleValues[regionName] *= adjustmentRatio;
}
iteration++;
}
// 显示结果
LogUtil.WriteLog($"{provinceName} 小型车和大型车单车价值和营收分析:\n");
foreach (var region in regions)
{
string regionName = region.Key;
int smallCount = region.Value["Small"] + region.Value["Medium"]; // 中型车归属于小型车
int largeCount = region.Value["Large"];
decimal smallVehicleRevenue = smallCount * smallVehicleValues[regionName];
decimal largeVehicleRevenue = largeCount * largeVehicleValues[regionName];
LogUtil.WriteLog($"地区: {regionName}");
LogUtil.WriteLog($" 小型车车辆数: {smallCount}");
LogUtil.WriteLog($" 大型车车辆数: {largeCount}");
LogUtil.WriteLog($" 小型车单车价值: {smallVehicleValues[regionName]:F2} 元/车");
LogUtil.WriteLog($" 大型车单车价值: {largeVehicleValues[regionName]:F2} 元/车");
LogUtil.WriteLog($" 小型车计算的营收: {smallVehicleRevenue:F2} 元");
LogUtil.WriteLog($" 大型车计算的营收: {largeVehicleRevenue:F2} 元");
LogUtil.WriteLog($" 合计营收: {smallVehicleRevenue + largeVehicleRevenue:F2} 元\n");
}
// 显示迭代细节和收敛状态
LogUtil.WriteLog($"月份: {provinceName}");
LogUtil.WriteLog($" 迭代次数: {iteration}");
LogUtil.WriteLog($" 是否收敛: {converged}\n");
}
}
#endregion
#region
public class ProvinceData
{
public string Name { get; set; } // 省份名称
public double PerCapitaIncome { get; set; } // 人均可支配收入
public Dictionary<string, int> VehicleCounts { get; set; } // 各种车辆类型的车辆数量
public double ConsumptionCoefficient { get; set; } // 消费能力系数 c_i
public double InitialVehicleValueSmall { get; set; } // 小型车初始单车价值 y_i^(0)
public double InitialVehicleValueMedium { get; set; } // 中型车初始单车价值
public double InitialVehicleValueLarge { get; set; } // 大型车初始单车价值
public double AdjustedVehicleValueSmall { get; set; } // 小型车调整后单车价值 y_i
public double AdjustedVehicleValueMedium { get; set; } // 中型车调整后单车价值
public double AdjustedVehicleValueLarge { get; set; } // 大型车调整后单车价值
public double RevenueContributionSmall { get; set; } // 小型车营收贡献
public double RevenueContributionMedium { get; set; } // 中型车营收贡献
public double RevenueContributionLarge { get; set; } // 大型车营收贡献
public double AdjustmentSmall { get; set; } // 小型车调整量
public double AdjustmentMedium { get; set; } // 中型车调整量
public double AdjustmentLarge { get; set; } // 大型车调整量
public double MaxAdjustmentSmall { get; set; } // 小型车最大调整量 ±10%
public double MaxAdjustmentMedium { get; set; } // 中型车最大调整量 ±10%
public double MaxAdjustmentLarge { get; set; } // 大型车最大调整量 ±10%
}
public static void CalculateVehicleValues(string month, double totalRevenue, int totalVehicleCount,
Dictionary<string, Dictionary<string, int>> provinceVehicleCounts, ref List<Model.VEHICLEAMOUNTModel> resultList)
{
// 初始化省份数据,包括各类型车辆的数量和人均可支配收入
List<ProvinceData> provinces = InitializeProvinceData(provinceVehicleCounts);
// 全国人均可支配收入(根据最新数据)
double nationalPerCapitaIncome = 35100; // 2022年全国居民人均可支配收入举例值需替换为实际数据
// 指数参数 gamma
double gamma = 0.5;
// 计算全国平均单车价值
double averageVehicleValue = totalRevenue / totalVehicleCount;
// 计算各省份的消费能力系数 c_i 和初始单车价值 y_i^(0)
foreach (var province in provinces)
{
province.ConsumptionCoefficient = Math.Pow(province.PerCapitaIncome / nationalPerCapitaIncome, gamma);
province.InitialVehicleValueSmall = averageVehicleValue * province.ConsumptionCoefficient;
province.InitialVehicleValueMedium = averageVehicleValue * province.ConsumptionCoefficient;
province.InitialVehicleValueLarge = averageVehicleValue * province.ConsumptionCoefficient;
// 最大调整量 ±10%
province.MaxAdjustmentSmall = 0.10 * province.InitialVehicleValueSmall;
province.MaxAdjustmentMedium = 0.10 * province.InitialVehicleValueMedium;
province.MaxAdjustmentLarge = 0.10 * province.InitialVehicleValueLarge;
}
// 使用 OR-Tools 进行线性规划求解
Solver solver = Solver.CreateSolver("CBC_MIXED_INTEGER_PROGRAMMING");
if (solver == null)
{
LogUtil.WriteLog("无法创建求解器。");
return;
}
// 创建决策变量 delta_i并设置上下界
Variable[] deltasSmall = new Variable[provinces.Count];
Variable[] deltasMedium = new Variable[provinces.Count];
Variable[] deltasLarge = new Variable[provinces.Count];
for (int i = 0; i < provinces.Count; i++)
{
deltasSmall[i] = solver.MakeNumVar(-provinces[i].MaxAdjustmentSmall, provinces[i].MaxAdjustmentSmall, $"delta_small_{i}");
deltasMedium[i] = solver.MakeNumVar(-provinces[i].MaxAdjustmentMedium, provinces[i].MaxAdjustmentMedium, $"delta_medium_{i}");
deltasLarge[i] = solver.MakeNumVar(-provinces[i].MaxAdjustmentLarge, provinces[i].MaxAdjustmentLarge, $"delta_large_{i}");
}
// 创建约束sum(N_i * (y_i^(0) + delta_i)) = totalRevenue
Google.OrTools.LinearSolver.Constraint revenueConstraint = solver.MakeConstraint(0, 0); // 只优化目标
for (int i = 0; i < provinces.Count; i++)
{
revenueConstraint.SetCoefficient(deltasSmall[i], provinces[i].VehicleCounts["Small"]);
revenueConstraint.SetCoefficient(deltasMedium[i], provinces[i].VehicleCounts["Medium"]);
revenueConstraint.SetCoefficient(deltasLarge[i], provinces[i].VehicleCounts["Large"]);
}
// 目标函数:最小化调整量的平方和(为了平衡各省份的调整量)
Objective objective = solver.Objective();
for (int i = 0; i < provinces.Count; i++)
{
objective.SetCoefficient(deltasSmall[i], 1);
objective.SetCoefficient(deltasMedium[i], 1);
objective.SetCoefficient(deltasLarge[i], 1);
}
objective.SetMinimization();
// 求解问题
Solver.ResultStatus resultStatus = solver.Solve();
// 检查求解状态并更新各省份的调整量和调整后单车价值
if (resultStatus == Solver.ResultStatus.OPTIMAL)
{
for (int i = 0; i < provinces.Count; i++)
{
provinces[i].AdjustmentSmall = deltasSmall[i].SolutionValue();
provinces[i].AdjustmentMedium = deltasMedium[i].SolutionValue();
provinces[i].AdjustmentLarge = deltasLarge[i].SolutionValue();
provinces[i].AdjustedVehicleValueSmall = provinces[i].InitialVehicleValueSmall + provinces[i].AdjustmentSmall;
provinces[i].AdjustedVehicleValueMedium = provinces[i].InitialVehicleValueMedium + provinces[i].AdjustmentMedium;
provinces[i].AdjustedVehicleValueLarge = provinces[i].InitialVehicleValueLarge + provinces[i].AdjustmentLarge;
provinces[i].RevenueContributionSmall = provinces[i].AdjustedVehicleValueSmall * provinces[i].VehicleCounts["Small"];
provinces[i].RevenueContributionMedium = provinces[i].AdjustedVehicleValueMedium * provinces[i].VehicleCounts["Medium"];
provinces[i].RevenueContributionLarge = provinces[i].AdjustedVehicleValueLarge * provinces[i].VehicleCounts["Large"];
}
// 输出结果
LogUtil.WriteLog($"月份:{month}");
LogUtil.WriteLog("各省份单车价值和营收贡献计算结果:");
LogUtil.WriteLog("-----------------------------------------------------------------------------------------------------------------");
LogUtil.WriteLog("省份\t车辆类型\t车辆数\t人均收入\t消费系数\t初始单车价值\t调整量\t调整后单车价值\t营收贡献");
foreach (var province in provinces)
{
LogUtil.WriteLog($"{province.Name}\t小型车\t{province.VehicleCounts["Small"]}\t" +
$"{province.PerCapitaIncome}\t{province.ConsumptionCoefficient:F3}\t" +
$"{province.InitialVehicleValueSmall:F2}\t{province.AdjustmentSmall:F2}\t" +
$"{province.AdjustedVehicleValueSmall:F2}\t{province.RevenueContributionSmall:F2}");
resultList.Add(new Model.VEHICLEAMOUNTModel
{
PROVINCE_NAME = province.Name,
VEHICLE_TYPE = "小型车",
VEHICLE_COUNT = province.VehicleCounts["Small"],
PERCAPITA_INCOME = province.PerCapitaIncome,
CONSUMPTION_COEFFICIENT = province.ConsumptionCoefficient,
VEHICLE_AMOUNT = province.InitialVehicleValueSmall,
ADJUST_COUNT = province.AdjustmentSmall,
VEHICLE_ADJAMOUNT = province.AdjustedVehicleValueSmall,
REVENUE_ADJAMOUNT = province.RevenueContributionSmall,
VEHICLEAMOUNT_STATE = 1,
RECORD_DATE = DateTime.Now,
});
LogUtil.WriteLog($"{province.Name}\t中型车\t{province.VehicleCounts["Medium"]}\t" +
$"{province.PerCapitaIncome}\t{province.ConsumptionCoefficient:F3}\t" +
$"{province.InitialVehicleValueMedium:F2}\t{province.AdjustmentMedium:F2}\t" +
$"{province.AdjustedVehicleValueMedium:F2}\t{province.RevenueContributionMedium:F2}");
resultList.Add(new Model.VEHICLEAMOUNTModel
{
PROVINCE_NAME = province.Name,
VEHICLE_TYPE = "中型车",
VEHICLE_COUNT = province.VehicleCounts["Medium"],
PERCAPITA_INCOME = province.PerCapitaIncome,
CONSUMPTION_COEFFICIENT = province.ConsumptionCoefficient,
VEHICLE_AMOUNT = province.InitialVehicleValueMedium,
ADJUST_COUNT = province.AdjustmentMedium,
VEHICLE_ADJAMOUNT = province.AdjustedVehicleValueMedium,
REVENUE_ADJAMOUNT = province.RevenueContributionMedium,
VEHICLEAMOUNT_STATE = 1,
RECORD_DATE = DateTime.Now,
});
LogUtil.WriteLog($"{province.Name}\t大型车\t{province.VehicleCounts["Large"]}\t" +
$"{province.PerCapitaIncome}\t{province.ConsumptionCoefficient:F3}\t" +
$"{province.InitialVehicleValueLarge:F2}\t{province.AdjustmentLarge:F2}\t" +
$"{province.AdjustedVehicleValueLarge:F2}\t{province.RevenueContributionLarge:F2}");
resultList.Add(new Model.VEHICLEAMOUNTModel
{
PROVINCE_NAME = province.Name,
VEHICLE_TYPE = "大型车",
VEHICLE_COUNT = province.VehicleCounts["Large"],
PERCAPITA_INCOME = province.PerCapitaIncome,
CONSUMPTION_COEFFICIENT = province.ConsumptionCoefficient,
VEHICLE_AMOUNT = province.InitialVehicleValueLarge,
ADJUST_COUNT = province.AdjustmentLarge,
VEHICLE_ADJAMOUNT = province.AdjustedVehicleValueLarge,
REVENUE_ADJAMOUNT = province.RevenueContributionLarge,
VEHICLEAMOUNT_STATE = 1,
RECORD_DATE = DateTime.Now,
});
}
Model.VEHICLEAMOUNTModel ServerpartModel = new Model.VEHICLEAMOUNTModel
{
REVENUE_ADJAMOUNT = provinces.Sum(p => p.RevenueContributionSmall + p.RevenueContributionMedium + p.RevenueContributionLarge),
REVENUE_ACTAMOUNT = totalRevenue,
VEHICLE_TOTALCOUNT = totalVehicleCount,
VEHICLEAMOUNT_STATE = 1,
RECORD_DATE = DateTime.Now,
};
resultList.Insert(0, ServerpartModel);
LogUtil.WriteLog("-----------------------------------------------------------------------------------------------------------------");
LogUtil.WriteLog($"调整后总营收: {ServerpartModel.REVENUE_ADJAMOUNT:F2}");
LogUtil.WriteLog($"实际总营收: {totalRevenue:F2}");
LogUtil.WriteLog($"总营收差异: {totalRevenue - ServerpartModel.REVENUE_ADJAMOUNT:F2}");
LogUtil.WriteLog($"误差率: {(1 - ServerpartModel.REVENUE_ADJAMOUNT / totalRevenue) * 100:F2}");
}
else
{
LogUtil.WriteLog($"求解失败,状态码: {resultStatus}");
if (resultStatus == Solver.ResultStatus.FEASIBLE)
{
LogUtil.WriteLog("找到可行解,但不是最优解。");
}
else if (resultStatus == Solver.ResultStatus.INFEASIBLE)
{
LogUtil.WriteLog("模型不可行,请检查约束设置。");
}
else if (resultStatus == Solver.ResultStatus.UNBOUNDED)
{
LogUtil.WriteLog("模型无界,请检查变量的上下界设置。");
}
}
}
static List<ProvinceData> InitializeProvinceData(Dictionary<string, Dictionary<string, int>> provinceVehicleCounts)
{
// 省份人均可支配收入(根据最新数据,替换为实际值)
Dictionary<string, double> provincePerCapitaIncomes = new Dictionary<string, double>
{
{ "北京市", 75002 },
{ "天津市", 45337 },
{ "河北省", 27243 },
{ "山西省", 27682 },
{ "辽宁省", 34798 },
{ "上海市", 72232 },
{ "江苏省", 48126 },
{ "浙江省", 57541 },
{ "安徽省", 30156 },
{ "福建省", 38051 },
{ "江西省", 29056 },
{ "山东省", 35756 },
{ "河南省", 26125 },
{ "湖北省", 33215 },
{ "湖南省", 28763 },
{ "广东省", 44527 },
{ "其他省份", 35100 }
};
List<ProvinceData> provinces = new List<ProvinceData>();
foreach (var kvp in provinceVehicleCounts)
{
string provinceName = kvp.Key;
var vehicleCounts = kvp.Value;
double perCapitaIncome = provincePerCapitaIncomes.ContainsKey(provinceName) ?
provincePerCapitaIncomes[provinceName] : 35100; // 默认全国平均值
ProvinceData province = new ProvinceData
{
Name = provinceName,
PerCapitaIncome = perCapitaIncome,
VehicleCounts = vehicleCounts, // 车辆类型及其数量
InitialVehicleValueSmall = 0, // 初始值将通过后续计算确定
InitialVehicleValueMedium = 0,
InitialVehicleValueLarge = 0,
AdjustedVehicleValueSmall = 0,
AdjustedVehicleValueMedium = 0,
AdjustedVehicleValueLarge = 0,
RevenueContributionSmall = 0,
RevenueContributionMedium = 0,
RevenueContributionLarge = 0,
AdjustmentSmall = 0,
AdjustmentMedium = 0,
AdjustmentLarge = 0,
MaxAdjustmentSmall = 0,
MaxAdjustmentMedium = 0,
MaxAdjustmentLarge = 0,
};
provinces.Add(province);
}
return provinces;
}
#endregion
}
}