using Enigmos.Boards; using Enigmos.Modules.InterlayerModules; using Enigmos.Modules.SubModules; using Enigmos.Ports.DataPorts; using Godot; using Nocturnis.DataStructures; using Nocturnis.DataStructures.ConfigurableParameters; using Nocturnis.DataStructures.DataPortGroups; using Nocturnis.Enigmos.Modules; using Nocturnis.Enigmos.Ports; using Nocturnis.Enigmos.Ports.DataPorts; using Nocturnis.Enigmos.Ports.DataPorts.Directions; using Nocturnis.GlobalManagement.Constants; using Nocturnis.GlobalManagement.Providers; namespace Enigmos.Modules.ProgrammableModules.OptimizationModule; public abstract partial class OptimizationModule : ProgrammableModule, IPolymorphismModule, IParameterizedModule, IInternalComputationalModule, IEnumerableProcessingModule { public bool ComputationFinished { get; set; } public bool ComputationStarted { get; set; } private double? CachedOptimizeValue { get; set; } public IDataInPort? ArrayInput { get; set; } public IData[] CachedInputArray { get; set; } = Array.Empty(); public int ProcessingIndex { get; set; } private IBoolParameter? UsingMax { get; set; } public IData CachedResult { get; set; } = GlobalProvider.DataStructureProvider!.NewData(0, EnigmosConstant.DataPortTypes.Null); public IDataInPort? InternalIterOut { get; set; } public IDataOutPort? InternalArrayIn { get; set; } private IDataPortGroup[] InterlayerGroups { get; set; } = Array.Empty(); private IDataPortGroup? OptimizationGroup { get; set; } private InterlayerDataInModule[] ExplicitInputs { get; set; } = Array.Empty(); private OptimizationSelectorModule? Selector { get; set; } private OutputSubModule? Output { get; set; } public new OptimizationModuleBoard UnderlyingBoard { get => (base.UnderlyingBoard as OptimizationModuleBoard)!; set => base.UnderlyingBoard = value; } public HashSet ConfigurableParameters { get; set; } = new(); public HashSet ConfigurablePortGroups { get; set; } = new(); public override IEnumerable ExplicitPorts => new IBasePort[] { ArrayInput!, Output!.Out! } .Union(ExplicitInputs.Select(c => c.DataIn)!); public override IEnumerable ImplicitPorts => new IBasePort[] { UnderlyingBoard.InputProvider!.Output!, UnderlyingBoard.Selector!.Selector! } .Union(UnderlyingBoard.ImplicitDataOuts.Select(c => c.DataOut))!; public override void Init() { base.Init(); UnderlyingBoard = GlobalProvider .AssetMapper.Scene .Instantiate(); UnderlyingBoard.Init(); InterlayerGroups = new IDataPortGroup[3]; ExplicitInputs = new InterlayerDataInModule[3]; InternalIterOut = this.GetPort("InternalIterOut"); Output = GetModule("Output"); Output.Init(); for (int i = 0; i < 3; i++) { ExplicitInputs[i] = GetModule($"EI{i + 1}"); ExplicitInputs[i].DualModule = UnderlyingBoard.ImplicitDataOuts[i]; UnderlyingBoard.ImplicitDataOuts[i].DualModule = ExplicitInputs[i]; } ComputationFinished = true; CachedInputArray = Array.Empty(); //CachedArray = Array.Empty(); ProcessingIndex = 0; CachedResult = GlobalProvider.DataStructureProvider!.NullData; CachedOptimizeValue = null; ArrayInput = this.GetPort("ArrayInput"); for (int i = 0; i < 3; i++) { InterlayerGroups[i] = GlobalProvider.DataStructureProvider.NewDataPortGroup( this, new IDataPort[] { ExplicitInputs[i].DataIn!, UnderlyingBoard.ImplicitDataOuts[i].DataOut! }, $"Exterior In -> Interior Out{i}", EnigmosConstant.DataPortTypes.Real, EnigmosConstant.DataPortTypes.AnyType ); ExplicitInputs[i].Board = Board; } OptimizationGroup = GlobalProvider.DataStructureProvider.NewDataPortGroup( this, new IDataPort[] { ArrayInput }, "Array Input Type", EnigmosConstant.DataPortTypes.AnyArrayType, EnigmosConstant.DataPortTypes.AnyArray ); UsingMax = GlobalProvider.DataStructureProvider.NewBoolParameter( "Method", "Max", "Min", true ); Output.Out!.SetDataType(EnigmosConstant.DataPortTypes.Real); Selector!.Selector!.SetDataType(EnigmosConstant.DataPortTypes.Real); ConfigurableParameters = new HashSet { UsingMax }; ConfigurablePortGroups = InterlayerGroups.Union(new[] { OptimizationGroup }).ToHashSet(); PostInit(); } public void Inference() { StringName elementType = GlobalProvider.DataTypeProvider!.ToElement(OptimizationGroup!.SelectedType); Output!.Out!.SetDataType(elementType); UnderlyingBoard.InputProvider!.Output!.SetDataType(elementType); } private void SoftReset() => UnderlyingBoard.Reset(); public void Compute() { if (ComputationFinished) { CachedOptimizeValue = null; CachedInputArray = InternalArrayIn!.OutData.Get!.Array; CachedResult = GlobalProvider.DataStructureProvider!.NewData(0, EnigmosConstant.DataPortTypes.Null); ProcessingIndex = 0; } while (ProcessingIndex < CachedInputArray.Length) { SoftReset(); UnderlyingBoard.InputProvider!.Output!.OutData.UpdateCalculation( cache => (CachedInputArray[ProcessingIndex].Data, CachedInputArray[ProcessingIndex].Type)! ); UnderlyingBoard.InputProvider.Output.OutData.Expire(); double currentValue = UnderlyingBoard.Selector!.Selector!.GetData.Get!.Double; IData currentOut = InternalIterOut!.GetData.Get!; if (UsingMax!.ParameterValue) { if (CachedOptimizeValue == null || (CachedOptimizeValue < currentValue)) { CachedOptimizeValue = currentValue; CachedResult.Assign(currentOut.Data!, currentOut.Type!); } } else { if (CachedOptimizeValue == null || CachedOptimizeValue > currentValue) { CachedOptimizeValue = currentValue; CachedResult.Assign(currentOut.Data!, currentOut.Type!); } } ProcessingIndex++; } Output!.Define(); ComputationFinished = true; } }