add SCIP solver

This commit is contained in:
Lightczx
2024-06-11 12:31:51 +08:00
parent f0bfea51cf
commit 9ef0d8c57d
4 changed files with 64 additions and 2 deletions

View File

@@ -7,5 +7,7 @@ namespace Snap.Hutao.Model.Metadata.Abstraction;
internal interface ICultivationItemsAccess
{
string Name { get; }
List<MaterialId> CultivationItems { get; }
}
}

View File

@@ -59,9 +59,11 @@ internal sealed partial class InventoryService : IInventoryService
List<ICultivationItemsAccess> cultivationItemsEntryList =
[
.. await metadataService.GetAvatarListAsync().ConfigureAwait(false),
.. (await metadataService.GetWeaponListAsync().ConfigureAwait(false)).Where(weapon => weapon.Quality >= Model.Intrinsic.QualityType.QUALITY_BLUE),
.. await metadataService.GetWeaponListAsync().ConfigureAwait(false),
];
cultivationItemsEntryList = MinimalPromotionDelta.Find(cultivationItemsEntryList);
BatchConsumption? batchConsumption = default;
using (IServiceScope scope = serviceScopeFactory.CreateScope())
{

View File

@@ -0,0 +1,57 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Google.OrTools.LinearSolver;
using Snap.Hutao.Core.ExceptionService;
using Snap.Hutao.Model.Metadata.Abstraction;
using Snap.Hutao.Model.Primitive;
using System.Runtime.InteropServices;
namespace Snap.Hutao.Service.Inventory;
internal static class MinimalPromotionDelta
{
public static List<ICultivationItemsAccess> Find(List<ICultivationItemsAccess> cultivationItems)
{
using (Solver? solver = Solver.CreateSolver("SCIP"))
{
ArgumentNullException.ThrowIfNull(solver);
Objective objective = solver.Objective();
objective.SetMinimization();
Dictionary<ICultivationItemsAccess, Variable> itemVariableMap = [];
foreach (ref readonly ICultivationItemsAccess item in CollectionsMarshal.AsSpan(cultivationItems))
{
Variable variable = solver.MakeBoolVar(item.Name);
itemVariableMap[item] = variable;
objective.SetCoefficient(variable, 1);
}
Dictionary<MaterialId, Constraint> materialConstraintMap = [];
foreach (ref readonly ICultivationItemsAccess item in CollectionsMarshal.AsSpan(cultivationItems))
{
foreach (ref readonly MaterialId materialId in CollectionsMarshal.AsSpan(item.CultivationItems))
{
ref Constraint? constraint = ref CollectionsMarshal.GetValueRefOrAddDefault(materialConstraintMap, materialId, out _);
constraint ??= solver.MakeConstraint(1, double.PositiveInfinity, $"{materialId}");
constraint.SetCoefficient(itemVariableMap[item], 1);
}
}
Solver.ResultStatus status = solver.Solve();
HutaoException.ThrowIf(status != Solver.ResultStatus.OPTIMAL, "Unable to solve minimal item set");
List<ICultivationItemsAccess> results = [];
foreach ((ICultivationItemsAccess item, Variable variable) in itemVariableMap)
{
if (variable.SolutionValue() > 0.5)
{
results.Add(item);
}
}
return results;
}
}
}

View File

@@ -313,6 +313,7 @@
<PackageReference Include="CommunityToolkit.WinUI.Controls.TokenizingTextBox" Version="8.0.240109" />
<PackageReference Include="CommunityToolkit.WinUI.Media" Version="8.0.240109" />
<PackageReference Include="CommunityToolkit.WinUI.Notifications" Version="7.1.2" />
<PackageReference Include="Google.OrTools" Version="9.10.4067" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.5" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.5">
<PrivateAssets>all</PrivateAssets>