/
GeekNerd
/
ServerModelingProject
Обзор
Документация
Войти
/
GeekNerd
/
ServerModelingProject
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
Assets/Tests/EditMode/OptimizationLogicCoreTests.cs
315 строк
11 KB
Gorney-Alex
Init
30 май 2026, 19:05
30 май 2026, 19:05
3cdcc49
Код
Авторство
О чём код?
using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using DataClasses; using DataClasses.Algorithm; using NUnit.Framework; using OptimizationLogic.Core; using UnityEngine; namespace OptimizationLogic.Tests.EditMode { public sealed class OptimizationLogicCoreTests { private static RoomConfig MakeSquareRoom(float size = 10f) { return new RoomConfig { PolygonVertices = new List<Vector2> { new Vector2(0f, 0f), new Vector2(size, 0f), new Vector2(size, size), new Vector2(0f, size) }, GridStep = 0.6f, MinAisleWidth = 1.0f, SupplyTemp = 18f, TempLimit = 27f }; } private static List<RackData> MakeOneRackModel(float width = 1f, float length = 1f, float heat = 5f, int qty = 1) { return new List<RackData> { new RackData { Width = width, Length = length, HeatOutput = heat, Quantity = qty } }; } [Test] public void ZonalThermalModel_ComputesExpectedTemperature() { RoomConfig room = MakeSquareRoom(); room.Cracs.Add(new CracData { Center = new Vector2(1f, 1f), SupplyTemperature = 18f, // Make mdot=1.0 kg/s: rho(1.2)*Ldot = 1 => Ldot = 1/1.2 VolumetricFlow = 1f / 1.2f }); var zones = new List<PlacementZone> { new PlacementZone { ZoneId = 0, Bounds = new Rect(0f, 0f, 10f, 10f) } }; var genes = new List<RackGene> { new RackGene { IsPlaced = true, ZoneId = 0, ModelIndex = 0, PositionX = 5f, PositionZ = 5f, Rotation = 0f } }; List<RackData> models = MakeOneRackModel(heat: 5f); ZonalThermalModel model = new ZonalThermalModel(); Dictionary<int, float> temps = model.ComputeZoneTemperatures(room, zones, genes, models); float expected = 18f + 5f / (1f * 1.006f); Assert.That(temps.ContainsKey(0), Is.True); Assert.That(Mathf.Abs(temps[0] - expected), Is.LessThan(0.03f)); } [Test] public void TopologyValidator_RI_IsZeroWhenAligned() { var zones = new List<PlacementZone> { new PlacementZone { ZoneId = 0, ColdAirDirection = Vector2.up }, new PlacementZone { ZoneId = 1, ColdAirDirection = Vector2.up } }; var genes = new List<RackGene> { new RackGene { IsPlaced = true, ZoneId = 0, Rotation = 0f }, new RackGene { IsPlaced = true, ZoneId = 1, Rotation = 0f } }; TopologyValidator v = new TopologyValidator(); float ri = v.ComputeRecirculationIndex(genes, zones); Assert.That(ri, Is.EqualTo(0f).Within(1e-6f)); } [Test] public void TopologyValidator_RI_IsOneWhenOpposite() { var zones = new List<PlacementZone> { new PlacementZone { ZoneId = 0, ColdAirDirection = Vector2.up }, new PlacementZone { ZoneId = 1, ColdAirDirection = Vector2.up } }; var genes = new List<RackGene> { new RackGene { IsPlaced = true, ZoneId = 0, Rotation = 180f }, new RackGene { IsPlaced = true, ZoneId = 1, Rotation = 180f } }; TopologyValidator v = new TopologyValidator(); float ri = v.ComputeRecirculationIndex(genes, zones); Assert.That(ri, Is.EqualTo(1f).Within(1e-6f)); } [Test] public void PlacementValidator_RejectsOutsidePolygon() { RoomConfig room = MakeSquareRoom(); List<RackData> models = MakeOneRackModel(width: 1f, length: 1f, heat: 0f); RackGene candidate = new RackGene { IsPlaced = true, ModelIndex = 0, ZoneId = 0, Rotation = 0f, PositionX = -1f, PositionZ = 5f }; PlacementValidator v = new PlacementValidator(); bool ok = v.IsPlacementValid(room, new List<RackGene>(), candidate, models); Assert.That(ok, Is.False); } [Test] public void PlacementValidator_RejectsCircularColumnCollision() { RoomConfig room = MakeSquareRoom(); room.Columns.Add(new ColumnData { Center = new Vector2(5f, 5f), IsCircular = true, RadiusOrHalfWidth = 1f }); List<RackData> models = MakeOneRackModel(width: 1f, length: 1f, heat: 0f); RackGene candidate = new RackGene { IsPlaced = true, ModelIndex = 0, ZoneId = 0, Rotation = 0f, PositionX = 5f, PositionZ = 5f }; PlacementValidator v = new PlacementValidator(); bool ok = v.IsPlacementValid(room, new List<RackGene>(), candidate, models); Assert.That(ok, Is.False); } [Test] public void PlacementValidator_RejectsDoorEvacuationZone() { RoomConfig room = MakeSquareRoom(); room.Doors.Add(new DoorData { EdgeIndex = 0, OffsetAlongEdge = 4f, Width = 2f, Thickness = 0.1f }); List<RackData> models = MakeOneRackModel(width: 1f, length: 1f, heat: 0f); RackGene candidate = new RackGene { IsPlaced = true, ModelIndex = 0, ZoneId = 0, Rotation = 0f, PositionX = 5f, PositionZ = 0.75f }; PlacementValidator v = new PlacementValidator(); bool ok = v.IsPlacementValid(room, new List<RackGene>(), candidate, models); Assert.That(ok, Is.False); } [Test] public void PlacementValidator_RejectsTooNarrowAisleDistance() { RoomConfig room = MakeSquareRoom(); room.MinAisleWidth = 1.0f; List<RackData> models = MakeOneRackModel(width: 1f, length: 1f, heat: 0f); var placed = new List<RackGene> { new RackGene { IsPlaced = true, ModelIndex = 0, ZoneId = 0, Rotation = 0f, PositionX = 2f, PositionZ = 5f } }; RackGene candidate = new RackGene { IsPlaced = true, ModelIndex = 0, ZoneId = 0, Rotation = 0f, // With 1x1 racks: separation between AABBs = (dx - 1.0). Here dx=1.8 => 0.8 < dmin. PositionX = 3.8f, PositionZ = 5f }; PlacementValidator v = new PlacementValidator(); bool ok = v.IsPlacementValid(room, placed, candidate, models); Assert.That(ok, Is.False); } [Test] public void GreedyPlacer_ProducesOnlyValidPlacements() { RoomConfig room = MakeSquareRoom(); room.Cracs.Add(new CracData { Center = new Vector2(1f, 5f) }); List<RackData> catalog = MakeOneRackModel(width: 1f, length: 1f, heat: 5f, qty: 3); ZonePartitioner partitioner = new ZonePartitioner(); List<PlacementZone> zones = partitioner.Partition(room, catalog); Assert.That(zones.Count, Is.GreaterThan(0)); GreedyPlacer greedy = new GreedyPlacer(); Chromosome c = greedy.Place(room, zones, catalog); Assert.That(c.Genes.Count, Is.GreaterThan(0)); Assert.That(c.PlacedCount, Is.GreaterThan(0)); PlacementValidator v = new PlacementValidator(); List<RackGene> placed = new(); for (int i = 0; i < c.Genes.Count; i++) { RackGene g = c.Genes[i]; if (!g.IsPlaced) continue; bool ok = v.IsPlacementValid(room, placed, g, catalog); Assert.That(ok, Is.True, $"Gene {i} invalid"); placed.Add(g); } } [Test] public async Task GeneticAlgorithm_ImprovesTopologyFitness_FromGreedy() { RoomConfig room = MakeSquareRoom(); room.Cracs.Add(new CracData { Center = new Vector2(0f, 5f), VolumetricFlow = 1f, SupplyTemperature = 18f }); List<RackData> catalog = MakeOneRackModel(width: 1f, length: 1f, heat: 1f, qty: 1); // Single zone with cold air direction pointing right. var zones = new List<PlacementZone> { new PlacementZone { ZoneId = 0, Bounds = new Rect(0f, 0f, 10f, 10f), ColdAirDirection = Vector2.right, CandidatePositions = new List<Vector2> { new Vector2(5f, 5f), new Vector2(5.6f, 5f), new Vector2(6.2f, 5f) } } }; // Greedy will pick rotation 0 first; with cold direction right, dot(up, right)=0 => RI=1 => fitness 0. GreedyPlacer greedy = new GreedyPlacer(); Chromosome greedyC = greedy.Place(room, zones, catalog); TopologyValidator topo = new TopologyValidator(); float greedyTopo = topo.ComputeTopologyFitness(greedyC.Genes, zones); GaSettings settings = new GaSettings { PopulationSize = 30, Generations = 20, MutationRate = 0.25f, CrossoverRate = 0.8f, EliteCount = 2, EarlyStopGenerations = 5, InitMutationProb = 1.0f, TournamentSize = 5, RandomSeed = 1337, WeightPlacement = 0f, WeightThermal = 0f, WeightAisle = 0f, WeightTopology = 1f }; GeneticAlgorithm ga = new GeneticAlgorithm(); Chromosome best = await ga.OptimizeAsync(room, zones, catalog, settings, progress: null, ct: CancellationToken.None); float bestTopo = topo.ComputeTopologyFitness(best.Genes, zones); Assert.That(bestTopo, Is.GreaterThan(greedyTopo)); Assert.That(bestTopo, Is.GreaterThanOrEqualTo(0.99f)); } } }