public LSystemSymbolReplacementCompletable( Unity.Mathematics.Random randResult, LSystemState <float> lastSystemState, int totalNewSymbolSize, int totalNewParamSize, NativeArray <float> globalParamNative, NativeArray <float> tmpParameterMemory, NativeArray <LSystemSingleSymbolMatchData> matchSingletonData, DependencyTracker <SystemLevelRuleNativeData> nativeData, SymbolStringBranchingCache branchingCache, CustomRuleSymbols customSymbols) { this.lastSystemState = lastSystemState; this.matchSingletonData = matchSingletonData; this.branchingCache = branchingCache; UnityEngine.Profiling.Profiler.BeginSample("allocating"); target = new SymbolString <float>(totalNewSymbolSize, totalNewParamSize, Allocator.Persistent); UnityEngine.Profiling.Profiler.EndSample(); this.randResult = randResult; this.nativeData = nativeData; // 5 UnityEngine.Profiling.Profiler.BeginSample("generating replacements"); var replacementJob = new RuleReplacementJob { globalParametersArray = globalParamNative, parameterMatchMemory = tmpParameterMemory, matchSingletonData = matchSingletonData, sourceData = lastSystemState.currentSymbols.Data, structExpressionSpace = nativeData.Data.structExpressionMemorySpace, globalOperatorData = nativeData.Data.dynamicOperatorMemory, replacementSymbolData = nativeData.Data.replacementsSymbolMemorySpace, outcomeData = nativeData.Data.ruleOutcomeMemorySpace, targetData = target, blittableRulesByTargetSymbol = nativeData.Data.blittableRulesByTargetSymbol, branchingCache = branchingCache, customSymbols = customSymbols }; currentJobHandle = replacementJob.Schedule( matchSingletonData.Length, 100 ); if (customSymbols.hasDiffusion && !customSymbols.independentDiffusionUpdate) { diffusionHelper = new DiffusionWorkingDataPack(10, 5, 2, customSymbols, Allocator.TempJob); var diffusionJob = new ParallelDiffusionReplacementJob { matchSingletonData = matchSingletonData, sourceData = lastSystemState.currentSymbols.Data, targetData = target, customSymbols = customSymbols, working = diffusionHelper }; currentJobHandle = JobHandle.CombineDependencies( currentJobHandle, diffusionJob.Schedule() ); } // only parameter modifications beyond this point lastSystemState.currentSymbols.RegisterDependencyOnData(currentJobHandle); nativeData.RegisterDependencyOnData(currentJobHandle); currentJobHandle = JobHandle.CombineDependencies( JobHandle.CombineDependencies( ScheduleIdAssignmentJob(currentJobHandle, customSymbols, lastSystemState), ScheduleIndependentDiffusion(currentJobHandle, customSymbols) ), JobHandle.CombineDependencies( ScheduleAutophagyJob(currentJobHandle, customSymbols), ScheduleImmaturityJob(currentJobHandle) )); UnityEngine.Profiling.Profiler.EndSample(); }
/// <summary> /// Returns a random element with the chances of rolling based on <paramref name="weights"/> /// </summary> /// <param name="weights">Positive floats representing weights. Negative values may lead to unpredictable behaviour.</param> public static T GetRandom <T>(this IReadOnlyList <T> list, IReadOnlyList <float> weights, ref MRandom random) { if (list == null) { throw new ArgumentNullException(nameof(list)); } if (list.Count == 0) { throw new ArgumentException("Empty list"); } if (weights == null) { throw new ArgumentNullException(nameof(weights)); } if (weights.Count == 0) { throw new ArgumentException("Empty weights"); } if (list.Count != weights.Count) { throw new ArgumentException("Array sizes must be equal"); } if (list.Count == 1) { return(list[0]); } var cumulative = new List <float>(weights); for (int i = 1; i < cumulative.Count; i++) { cumulative[i] += cumulative[i - 1]; } float randomValue = random.NextFloat(0, cumulative[cumulative.Count - 1]); int index = cumulative.FindIndex(a => a >= randomValue); if (index == -1) { throw new ArgumentException("Weights must be positive"); } return(list[index]); }
/// <summary> /// Returns a random value from the dictionary /// </summary> public static TValue GetRandom <TKey, TValue>(this IDictionary <TKey, TValue> dictionary, ref MRandom random) { if (dictionary == null) { throw new ArgumentNullException(nameof(dictionary)); } var keys = dictionary.Keys; if (keys.Count == 0) { throw new ArgumentException("Empty dictionary"); } return(dictionary[new List <TKey>(keys).GetRandom(ref random)]); }
/// <summary> /// /// </summary> /// <param name="lastSystemState"></param> /// <param name="lSystemNativeData"></param> /// <param name="globalParameters"></param> /// <param name="maxMemoryRequirementsPerSymbol"></param> /// <param name="branchOpenSymbol"></param> /// <param name="branchCloseSymbol"></param> /// <param name="includedCharactersByRuleIndex"></param> /// <param name="customSymbols"></param> /// <param name="parameterModificationJobDependency">A dependency on a job which only makes changes to the parameters of the source symbol string. /// the symbols themselves must be constant</param> public LSystemRuleMatchCompletable( NativeArray <LSystemSingleSymbolMatchData> matchSingletonData, int parameterTotalSum, SymbolStringBranchingCache branchingCache, LSystemState <float> lastSystemState, DependencyTracker <SystemLevelRuleNativeData> lSystemNativeData, float[] globalParameters, CustomRuleSymbols customSymbols, JobHandle parameterModificationJobDependency) { this.customSymbols = customSymbols; this.lastSystemState = lastSystemState; randResult = lastSystemState.randomProvider; nativeData = lSystemNativeData; this.matchSingletonData = matchSingletonData; this.branchingCache = branchingCache; // 1. UnityEngine.Profiling.Profiler.BeginSample("allocating"); tmpParameterMemory = new NativeArray <float>(parameterTotalSum, Allocator.Persistent, NativeArrayOptions.UninitializedMemory); globalParamNative = new NativeArray <float>(globalParameters, Allocator.Persistent); UnityEngine.Profiling.Profiler.EndSample(); // 2. UnityEngine.Profiling.Profiler.BeginSample("matching"); var prematchJob = new RuleCompleteMatchJob { matchSingletonData = matchSingletonData, sourceData = lastSystemState.currentSymbols.Data, tmpParameterMemory = tmpParameterMemory, globalOperatorData = nativeData.Data.dynamicOperatorMemory, outcomes = nativeData.Data.ruleOutcomeMemorySpace, globalParams = globalParamNative, blittableRulesByTargetSymbol = nativeData.Data.blittableRulesByTargetSymbol, branchingCache = branchingCache, seed = randResult.NextUInt() }; var matchingJobHandle = prematchJob.ScheduleBatch( matchSingletonData.Length, 100, parameterModificationJobDependency); UnityEngine.Profiling.Profiler.EndSample(); // 4. UnityEngine.Profiling.Profiler.BeginSample("replacement counting"); UnityEngine.Profiling.Profiler.BeginSample("allocating"); totalSymbolCount = new NativeArray <int>(1, Allocator.Persistent); totalSymbolParameterCount = new NativeArray <int>(1, Allocator.Persistent); UnityEngine.Profiling.Profiler.EndSample(); var totalSymbolLengthJob = new RuleReplacementSizeJob { matchSingletonData = matchSingletonData, totalResultSymbolCount = totalSymbolCount, totalResultParameterCount = totalSymbolParameterCount, sourceData = lastSystemState.currentSymbols.Data, customSymbols = customSymbols }; currentJobHandle = totalSymbolLengthJob.Schedule(matchingJobHandle); lastSystemState.currentSymbols.RegisterDependencyOnData(currentJobHandle); nativeData.RegisterDependencyOnData(currentJobHandle); UnityEngine.Profiling.Profiler.EndSample(); }
unsafe int UpdateCentroids() { int *hassign = stackalloc int[k]; for (int i = 0; i < k; ++i) { hassign[i] = 0; } Debug.Assert(centroids.Length == d * k); for (int i = 0; i < centroids.Length; ++i) { centroids[i] = 0.0f; } for (int i = 0; i < numSamples; ++i) { int ci = distances[i].index; Debug.Assert(ci >= 0 && ci < k); hassign[ci]++; for (int j = 0; j < d; ++j) { centroids[ci * d + j] += features[i * d + j]; } } for (int ci = 0; ci < k; ci++) { var ni = hassign[ci]; if (ni != 0) { for (int j = 0; j < d; ++j) { centroids[ci * d + j] /= (float)ni; } } } // // Take care of void clusters // int nsplit = 0; var random = new Unity.Mathematics.Random(1234); for (int ci = 0; ci < k; ++ci) { // // need to redefine a centroid // if (hassign[ci] == 0) { int cj = 0; while (true) { // // probability to pick this cluster for split // float p = (hassign[cj] - 1.0f) / (float)(numSamples - k); float r = random.NextFloat(); if (r < p) { // // found our cluster to be split // break; } cj = (cj + 1) % k; } for (int j = 0; j < d; ++j) { centroids[ci * d + j] = centroids[cj * d + j]; } // // small symmetric perturbation // float eps = 1.0f / 1024.0f; for (int j = 0; j < d; ++j) { if (j % 2 == 0) { centroids[ci * d + j] *= 1 + eps; centroids[cj * d + j] *= 1 - eps; } else { centroids[ci * d + j] *= 1 - eps; centroids[cj * d + j] *= 1 + eps; } } // // assume even split of the cluster // hassign[ci] = hassign[cj] / 2; hassign[cj] -= hassign[ci]; nsplit++; } } return(nsplit); }
protected override void OnUpdate() { ComponentDataFromEntity <BugComponent> bugComponent = GetComponentDataFromEntity <BugComponent>(); BufferFromEntity <EntityBufferElement> entityBuffer = GetBufferFromEntity <EntityBufferElement>(); var time = Time.DeltaTime; timeSinceStart += time; var random = new Random((uint)(timeSinceStart * 1000f)); //Recursive method of finding chains of one color, some kind of flood fill void FindChainRec( Entity entity, BugComponent ball, BugColor neededColor, DynamicBuffer <EntityBufferElement> adjacentEntities, NativeHashMap <Entity, bool> chainMap) { if (!chainMap.ContainsKey(entity) && ball.Color == neededColor) { chainMap.Add(entity, true); } for (int i = 0; i < adjacentEntities.Length; i++) { var adjacentEntity = adjacentEntities[i].Value; var adjacentBall = bugComponent[adjacentEntity]; if (!chainMap.ContainsKey(adjacentEntity) && adjacentBall.Color == neededColor) { chainMap.Add(adjacentEntity, true); var nextBall = bugComponent[adjacentEntity]; var nextAdjacent = entityBuffer[adjacentEntity]; FindChainRec(adjacentEntity, nextBall, neededColor, nextAdjacent, chainMap); } } } var minChainSize = minimumChainSize; var commandBuffer = barrier.CreateCommandBuffer().ToConcurrent(); Dependency = Entities.ForEach((Entity entity, int nativeThreadIndex, int entityInQueryIndex, in BugComponent bug, in DynamicBuffer <EntityBufferElement> adjacentEntities, in ChainMarkComponent mark) => { commandBuffer.RemoveComponent <ChainMarkComponent>(nativeThreadIndex, entity); BugColor neededColor = mark.NeededColor; //Should be HashSet as we don't need value here, but there is no NativeHashSet at the moment NativeHashMap <Entity, bool> chainMap = new NativeHashMap <Entity, bool>(100, Allocator.Temp); FindChainRec(entity, bug, neededColor, adjacentEntities, chainMap); var keys = chainMap.GetKeyArray(Allocator.Temp); if (keys.Length >= minChainSize) { //Trigger spawning additional bugs commandBuffer.AddComponent <SpawnMarkComponent>(nativeThreadIndex, entity); commandBuffer.SetComponent(nativeThreadIndex, entity, new SpawnMarkComponent { Count = keys.Length }); for (var i = 0; i < keys.Length; i++) { //Remove popped bugs with delay commandBuffer.AddComponent <RemoveMarkComponent>(nativeThreadIndex, keys[i]); commandBuffer.SetComponent(nativeThreadIndex, keys[i], new RemoveMarkComponent { DelayMs = random.NextInt(0, 20) }); } } chainMap.Dispose(); })
protected override JobHandle OnUpdate(JobHandle inputDeps) { float deltaTime = Time.DeltaTime; uint seed = (uint)(UnityEngine.Random.value * 10000); Random random = new Random(seed); var entityCommandBuffer = _commandBufferSystem.CreateCommandBuffer().ToConcurrent(); JobHandle jobHandle = Entities.ForEach( (Entity entity, int entityInQueryIndex, ref UnitSpawnerData spawnerData) => { if (spawnerData._spawnInActive) { return; } // Spawn Light Enemy Update Time if (spawnerData._currentLightUnitTime <= 0) { if (spawnerData._currentLightEntityInBetweenTime <= 0) { float value = random.NextFloat(); if (value <= 0.5f) { entityCommandBuffer.Instantiate(entityInQueryIndex, spawnerData.lightEntityA); } else { entityCommandBuffer.Instantiate(entityInQueryIndex, spawnerData.lightEntityB); } spawnerData._currentLightEntityCount += 1; if (spawnerData._currentLightEntityCount >= spawnerData.lightEntityBurstCount) { spawnerData._currentLightUnitTime = spawnerData ._currentDeadPerSec .Map(spawnerData.minDeathPerSec, spawnerData.maxDeathPerSec, spawnerData.maxTimeBetweenLightEntity, spawnerData.minTimeBetweenLightEntity); spawnerData._currentLightEntityCount = 0; } else { spawnerData._currentLightEntityInBetweenTime = spawnerData.lightBurstTimeBetween; } } else { spawnerData._currentLightEntityInBetweenTime -= deltaTime; } } else { spawnerData._currentLightUnitTime -= deltaTime; } // Spawn Heavy Enemy Update Time if (spawnerData._currentHeavyUnitTime <= 0) { float value = random.NextFloat(); if (value <= 0.5f) { entityCommandBuffer.Instantiate(entityInQueryIndex, spawnerData.heavyEntityA); } else { entityCommandBuffer.Instantiate(entityInQueryIndex, spawnerData.heavyEntityB); } spawnerData._currentHeavyUnitTime = spawnerData ._currentDeadPerSec .Map(spawnerData.minDeathPerSec, spawnerData.maxDeathPerSec, spawnerData.maxTimeBetweenHeavyEntity, spawnerData.maxTimeBetweenHeavyEntity); } else { spawnerData._currentHeavyUnitTime -= deltaTime; } }).Schedule(inputDeps); _commandBufferSystem.AddJobHandleForProducer(jobHandle); return(jobHandle); }
// returns ushort in [1..ushort.MaxValue - 1] range public static ushort GetRandomUShort() { var rnd = new Unity.Mathematics.Random((uint)Stopwatch.GetTimestamp()); return((ushort)rnd.NextUInt(1, 0xffff)); }
/// <summary> /// Create a new <see cref="BaseRandom"/> instance with the given <paramref name="seed"/> /// </summary> /// <param name="seed">The seed that should be used to generate random numbers.</param> protected BaseRandom(uint seed) { Random = new Unity.Mathematics.Random(seed); }
/// <summary> /// Create a new <see cref="BaseRandom"/> instance with a random seed. /// </summary> protected BaseRandom() { Random = new Unity.Mathematics.Random((uint)DateTime.Now.Millisecond); }