private void TransformCDFGToFunctionCDFG(CDFG toTransform, InlineProgramInfo programInfo) { for (int i = 0; i < toTransform.Nodes.Count; i++) { TransformDFGToFunctionDFG(toTransform.Nodes[i].dfg, programInfo); } }
public void TestCopyCDFG() { DFG <Block> dfg1 = new DFG <Block>(); dfg1.AddNode(new Constant(3, "a", "", false)); dfg1.AddNode(new SetNumberVariable((VariableBlock)dfg1.Nodes[0].value, "b", "")); dfg1.AddNode(new Constant(6, "g", "", false)); dfg1.AddNode(new Constant(6, "h", "", false)); dfg1.AddNode(new BoolOP((VariableBlock)dfg1.Nodes[2].value, (VariableBlock)dfg1.Nodes[3].value, "i", BoolOPTypes.EQ, "", true)); dfg1.FinishDFG(); DFG <Block> dfg2 = new DFG <Block>(); dfg2.AddNode(new Constant(6, "c", "", false)); dfg2.AddNode(new GetNumberVariable("b", "d", "", false)); dfg2.AddNode(new ArithOP((VariableBlock)dfg2.Nodes[0].value, (VariableBlock)dfg2.Nodes[1].value, "e", ArithOPTypes.ADD, "", false)); dfg2.AddNode(new SetNumberVariable((VariableBlock)dfg2.Nodes[2].value, "f", "")); dfg2.FinishDFG(); CDFG original = new CDFG(); original.AddNode(new While(new Conditional((VariableBlock)dfg1.Nodes[4].value, dfg2, null)), dfg1); original.AddNode(null, dfg2); original.StartDFG = dfg1; CDFG copy1 = original.Copy(); CheckCopyCDFG(original, copy1); CDFG copy2 = original.Copy(); CheckCopyCDFG(original, copy2); }
public Direct GetProgram(XmlNode currentProgramXml, ParserInfo parserInfo) { string id = ParseTools.ParseID(currentProgramXml); InlineProgramInfo programInfo = GetInlineProgramInfo(currentProgramXml, parserInfo); CDFG newProgram = ProgramCDFG.Copy(); TransformCDFGToFunctionCDFG(newProgram, programInfo); TransformVariableNames(newProgram, programInfo, parserInfo.GetUniquePostFix()); ChangeIDs(newProgram, id); //Add new variables that this program added programInfo.OutputsFromTo.ForEach(x => parserInfo.AddVariable(string.Empty, VariableType.FLUID, x.Value)); DFG <Block> nextDFG = XmlParser.ParseNextDFG(currentProgramXml, parserInfo); DFG <Block> endDFG = newProgram.GetEndDFGInFirstScope(); int i = newProgram.Nodes.FindIndex(x => x.dfg == endDFG); if (newProgram.Nodes[i].control == null) { newProgram.Nodes[i] = (new Direct(nextDFG), endDFG); } else { newProgram.Nodes[i] = (newProgram.Nodes[i].control.GetNewControlWithNewEnd(nextDFG), endDFG); } //merge the programs together nd return the link between then parserInfo.cdfg.AddCDFG(newProgram); return(new Direct(newProgram.StartDFG)); }
private static (DFG <Block>, List <string>) GetNextGraph(CDFG graph, DFG <Block> currentDFG, CommandExecutor <T> executor, Dictionary <string, float> variables, Stack <IControlBlock> controlStack, Stack <List <string> > scopeStack, Dictionary <string, BoardFluid> dropPositions) { List <string> variablesOutOfScope = new List <string>(); { IControlBlock control = graph.DfgToControl[currentDFG]; if (control != null) { DFG <Block> guardedDFG = control.GuardedDFG(variables, executor, dropPositions); if (guardedDFG != null) { controlStack.Push(control); scopeStack.Push(new List <string>()); return(guardedDFG, variablesOutOfScope); } DFG <Block> nextDFG = control.NextDFG(variables, executor, dropPositions); if (nextDFG != null) { return(nextDFG, variablesOutOfScope); } } } while (controlStack.Count > 1) { IControlBlock control = controlStack.Pop(); List <string> newVariablesOutOfScope = scopeStack.Pop(); variablesOutOfScope.AddRange(newVariablesOutOfScope); foreach (string variable in newVariablesOutOfScope) { if (variables.ContainsKey(variable)) { variables.Remove(variable); } else if (dropPositions.ContainsKey(variable)) { dropPositions.Remove(variable); } } DFG <Block> loopDFG = control.TryLoop(variables, executor, dropPositions); if (loopDFG != null) { controlStack.Push(control); scopeStack.Push(new List <string>()); return(loopDFG, variablesOutOfScope); } DFG <Block> nextDFG = control.NextDFG(variables, executor, dropPositions); if (nextDFG != null) { return(nextDFG, variablesOutOfScope); } } return(null, variablesOutOfScope); }
internal static (string nodes, string edges) CDFGToSimpleGraph(CDFG cdfg) { string nodes = ""; string edges = ""; Dictionary <DFG <Block>, string> dfgNames = CreateNodesAndEdgesForEachDFGInCDFG(cdfg, ref nodes, ref edges); edges = CreateEdgesBetweenDFGs(cdfg.StartDFG, cdfg, edges, dfgNames, new List <(DFG <Block>, DFG <Block>)>(), new Stack <DFG <Block> >()); nodes = "[" + nodes + "]"; edges = "[" + edges + "]"; return(nodes, edges); }
private void ChangeIDs(CDFG cdfg, string newID) { foreach (DFG <Block> dfg in cdfg.Nodes.Select(x => x.dfg)) { foreach (Node <Block> node in dfg.Nodes) { Block block = node.value; block.BlockID = newID; foreach (FluidInput input in block.InputFluids) { input.ID = newID; } } } }
private void RunSimulator(CDFG cdfg, bool alreadyOptimized) { lock (simulatorLocker) { if (CurrentlyExecutionProgram != null) { CurrentlyExecutionProgram.KeepRunning.Cancel(); } simulatorThread?.Join(); simulatorThread = new Thread(() => { try { int boardWidth = Settings.BoardWidth; int boardHeight = Settings.BoardHeight; int timeBetweenCommands = (int)((1f / Settings.CommandFrequency) * 1000); using (SimulatorConnector executor = new SimulatorConnector(Browser, boardWidth, boardHeight)) { CurrentlyExecutionProgram = new ProgramExecutor<string>(executor); CurrentlyExecutionProgram.TimeBetweenCommands = timeBetweenCommands; CurrentlyExecutionProgram.ShowEmptyRectangles = Settings.ShowEmptyRectangles; CurrentlyExecutionProgram.EnableOptimizations = Settings.EnableOptimizations; CurrentlyExecutionProgram.EnableGarbageCollection = Settings.EnableGC; CurrentlyExecutionProgram.EnableSparseElectrodes = Settings.EnableSparseBoard; CurrentlyExecutionProgram.Run(boardWidth, boardHeight, cdfg, alreadyOptimized); } } catch (InternalRuntimeException e) { Browser.ExecuteScriptAsync($"ShowUnexpectedError(\"{e.Message.Replace('\"', '\'')}\");"); } catch (RuntimeException e) { Browser.ExecuteScriptAsync($"ShowUnexpectedError(\"{e.Message.Replace('\"', '\'')}\");"); } catch (ThreadInterruptedException) { } catch (Exception e) { Debug.WriteLine(e.Message + Environment.NewLine + e.StackTrace); } }); simulatorThread.Start(); } }
private void CheckCopyCDFG(CDFG original, CDFG copy) { CheckCopyDFG(original.StartDFG, copy.StartDFG); Assert.AreEqual(original.Nodes.Count, copy.Nodes.Count); for (int i = 0; i < original.Nodes.Count; i++) { DFG <Block> oDFG = original.Nodes[i].dfg; DFG <Block> cDFG = copy.Nodes[i].dfg; CheckCopyDFG(oDFG, cDFG); IControlBlock oControl = original.Nodes[i].control; IControlBlock cControl = copy.Nodes[i].control; if (oControl != null) { Assert.IsNotNull(cControl); CheckCopyControl(oControl, cControl); } else { Assert.IsNull(cControl); } } }
public async void Update(string xml) { try { //xml = xml.Replace("<", "<"); //await JSExecutor.InvokeAsync<string>("alert", xml); //throw new Exception(xml); (CDFG cdfg, List <ParseException> exceptions) = XmlParser.Parse(xml); if (exceptions.Count == 0) { bool optimizedCDFG = false; if (Settings.CreateGraph) { if (ProgramExecutor <string> .CanOptimizeCDFG(cdfg) && Settings.EnableOptimizations) { int boardWidth = Settings.BoardWidth; int boardHeight = Settings.BoardHeight; cancelSource?.Cancel(); cancelSource = new CancellationTokenSource(); CDFG newCdfg = new CDFG(); newCdfg.StartDFG = ProgramExecutor <string> .OptimizeCDFG <string>(boardWidth, boardHeight, cdfg, cancelSource.Token, Settings.EnableGC); newCdfg.AddNode(null, newCdfg.StartDFG); if (cancelSource.IsCancellationRequested) { return; } cdfg = newCdfg; optimizedCDFG = true; } (string nodes, string edges) = SimpleGraph.CDFGToSimpleGraph(cdfg); await JSExecutor.InvokeAsync <string>("setGraph", nodes, edges); } await JSExecutor.InvokeAsync <string>("ClearErrors"); RunSimulator(cdfg, optimizedCDFG); } else { var errorInfos = exceptions.GroupBy(e => e.ID) .Select(e => $"{{id: \"{e.Key}\", message: \"{String.Join(@"\n", e.Select(ee => ee.Message))}\"}}"); await JSExecutor.InvokeAsync <string>("ShowBlocklyErrors", errorInfos.ToArray()); } } catch (ParseException e) { await JSExecutor.InvokeAsync <string>("ShowUnexpectedError", e.Message); Debug.WriteLine(e.Message + Environment.NewLine + e.StackTrace); } catch (Exception e) { await JSExecutor.InvokeAsync <string>("ShowUnexpectedError", e.Message); Debug.WriteLine(e.Message + Environment.NewLine + e.StackTrace); } }
public void Update(string xml) { try { (CDFG cdfg, List<ParseException> exceptions) = XmlParser.Parse(xml); if (exceptions.Count == 0) { string js = String.Empty; bool optimizedCDFG = false; if (Settings.CreateGraph) { if (ProgramExecutor<string>.CanOptimizeCDFG(cdfg) && Settings.EnableOptimizations) { int boardWidth = Settings.BoardWidth; int boardHeight = Settings.BoardHeight; cancelSource?.Cancel(); cancelSource = new CancellationTokenSource(); CDFG newCdfg = new CDFG(); newCdfg.StartDFG = ProgramExecutor<string>.OptimizeCDFG<string>(boardWidth, boardHeight, cdfg, cancelSource.Token, Settings.EnableGC); newCdfg.AddNode(null, newCdfg.StartDFG); if (cancelSource.IsCancellationRequested) { return; } cdfg = newCdfg; optimizedCDFG = true; } (string nodes, string edges) = SimpleGraph.CDFGToSimpleGraph(cdfg); js = $"setGraph({nodes}, {edges});"; } js += $"ClearErrors();"; Browser.ExecuteScriptAsync(js); RunSimulator(cdfg, optimizedCDFG); } else { var errorInfos = exceptions.GroupBy(e => e.ID) .Select(e => $"{{id: \"{e.Key}\", message: \"{String.Join(@"\n", e.Select(ee => ee.Message))}\"}}"); string ids = string.Join(", ", errorInfos); string js = $"ShowBlocklyErrors([{ids}]);"; Browser.ExecuteScriptAsync(js); } } catch (ParseException e) { string message = $"ShowUnexpectedError(\"{e.Message.Replace('\"', ' ').Replace('\'', ' ')}\");"; Browser.ExecuteScriptAsync(message); Debug.WriteLine(e.Message + Environment.NewLine + e.StackTrace); } catch (Exception e) { string message = $"ShowUnexpectedError(\"{e.Message.Replace('\"', ' ').Replace('\'', ' ')}\");"; Browser.ExecuteScriptAsync(message); Debug.WriteLine(e.Message + Environment.NewLine + e.StackTrace); } }
private void TransformVariableNames(CDFG cdfg, InlineProgramInfo programInfo, string postfix) { Stack <IEnumerator <DFG <Block> > > stack = new Stack <IEnumerator <DFG <Block> > >(); HashSet <string> readerBlacklist = new HashSet <string>(); HashSet <string> writerBlacklist = new HashSet <string>(); programInfo.InputsFromTo.ForEach(x => readerBlacklist.Add(x.Value.OriginalFluidName)); programInfo.VariablesFromTo.ForEach(x => GetVariableBlockDependencies(x.Value.GetVariableTreeList(new List <VariableBlock>())).ForEach(y => readerBlacklist.Add(y))); programInfo.VariablesFromTo.ForEach(x => readerBlacklist.Add(x.Key)); programInfo.OutputsFromTo.ForEach(x => writerBlacklist.Add(x.Value)); DFG <Block> currentDFG = cdfg.StartDFG; do { foreach (Node <Block> node in currentDFG.Nodes) { Block block = node.value; foreach (FluidInput fluidInput in block.InputFluids) { if (!readerBlacklist.Contains(fluidInput.OriginalFluidName) && !writerBlacklist.Contains(fluidInput.OriginalFluidName)) { fluidInput.OriginalFluidName += postfix; } } for (int i = 0; i < block.InputNumbers.Count; i++) { if (!readerBlacklist.Contains(block.InputNumbers[i])) { block.InputNumbers[i] = block.InputNumbers[i] + postfix; } } if (readerBlacklist.Contains(block.OutputVariable)) { readerBlacklist.Remove(block.OutputVariable); } if (!writerBlacklist.Contains(block.OutputVariable)) { block.OutputVariable += postfix; } } IControlBlock control = cdfg.DfgToControl[currentDFG]; if (control != null) { stack.Push(control.GetEnumerator()); } while (stack.Count > 0) { if (!stack.Peek().MoveNext()) { stack.Pop(); continue; } currentDFG = stack.Peek().Current; break; } } while (stack.Count > 0); }
public static DFG <Block> OptimizeCDFG <T>(int width, int height, CDFG graph, CancellationToken keepRunning, bool useGC) { DFG <Block> runningGraph = graph.StartDFG; Stack <IControlBlock> controlStack = new Stack <IControlBlock>(); Stack <List <string> > scopedVariables = new Stack <List <string> >(); controlStack.Push(null); scopedVariables.Push(new List <string>()); DFG <Block> bigDFG = new DFG <Block>(); Dictionary <string, string> renamer = new Dictionary <string, string>(); Dictionary <string, string> variablePostfixes = new Dictionary <string, string>(); Schedule scheduler = new Schedule(width, height); scheduler.SHOULD_DO_GARBAGE_COLLECTION = useGC; List <StaticDeclarationBlock> staticModuleDeclarations = runningGraph.Nodes.Where(node => node.value is StaticDeclarationBlock) .Select(node => node.value as StaticDeclarationBlock) .ToList(); if (staticModuleDeclarations.Count > 0) { scheduler.PlaceStaticModules(staticModuleDeclarations); scopedVariables.Peek().AddRange(scheduler.NewVariablesCreatedInThisScope.Distinct()); } int nameID = 0; while (runningGraph != null) { int time = scheduler.ListScheduling <T>(runningGraph, null); scopedVariables.Peek().AddRange(scheduler.NewVariablesCreatedInThisScope.Distinct().Where(x => !x.Contains("#@#Index"))); runningGraph.Nodes.ForEach(x => x.value.IsDone = false); Assay fisk = new Assay(runningGraph); foreach (Block toCopy in fisk) { if (toCopy is FluidBlock fluidBlockToCopy) { if (!variablePostfixes.ContainsKey(toCopy.OutputVariable)) { variablePostfixes.Add(toCopy.OutputVariable, $"##{nameID++}"); } Block copy = fluidBlockToCopy.CopyBlock(bigDFG, renamer, variablePostfixes[toCopy.OutputVariable]); bigDFG.AddNode(copy); } fisk.UpdateReadyOperations(toCopy); } runningGraph.Nodes.ForEach(x => x.value.Reset()); var dropPositionsCopy = scheduler.FluidVariableLocations.ToDictionary(); List <string> variablesOutOfScope; (runningGraph, variablesOutOfScope) = GetNextGraph(graph, runningGraph, null, scheduler.Variables, controlStack, scopedVariables, scheduler.FluidVariableLocations); if (useGC) { AddWasteBlocks(variablesOutOfScope, bigDFG, renamer, dropPositionsCopy, staticModuleDeclarations); } foreach (var item in variablesOutOfScope) { renamer.Remove(item); variablePostfixes.Remove(item); } if (keepRunning.IsCancellationRequested) { return(null); } } if (useGC) { AddWasteBlocks(scopedVariables.Pop(), bigDFG, renamer, scheduler.FluidVariableLocations, staticModuleDeclarations); } bigDFG.FinishDFG(); return(bigDFG); }
public static (string[] inputs, string[] outputs, string[] variableImports, string programXml, CDFG cdfg) LoadProgram(string programXml, CDFG cdfg) { var inputs = cdfg.StartDFG.Input.Where(x => x.value is InputDeclaration) .Select(x => x.value.OutputVariable) .ToArray(); var outputs = cdfg.StartDFG.Input.Where(x => x.value is OutputDeclaration) .Select(x => (x.value as OutputDeclaration).ModuleName) .ToArray(); var variableImports = cdfg.StartDFG.Input.Where(x => x.value is ImportVariable) .Select(x => (x.value as ImportVariable).VariableName) .ToArray(); return(inputs, outputs, variableImports, programXml, cdfg); }
public void Run(int width, int height, CDFG graph, bool alreadyOptimized) { if (CanOptimizeCDFG(graph) && EnableOptimizations && !alreadyOptimized) { CDFG optimizedCDFG = new CDFG(); optimizedCDFG.StartDFG = OptimizeCDFG <T>(width, height, graph, KeepRunning.Token, EnableGarbageCollection); optimizedCDFG.AddNode(null, optimizedCDFG.StartDFG); graph = optimizedCDFG; } DFG <Block> runningGraph = graph.StartDFG; Stack <IControlBlock> controlStack = new Stack <IControlBlock>(); Stack <List <string> > scopedVariables = new Stack <List <string> >(); Rectangle[] oldRectangles = null; bool firstRun = true; Dictionary <string, List <IDropletSource> > sumOutputtedDropelts = new Dictionary <string, List <IDropletSource> >(); controlStack.Push(null); scopedVariables.Push(new List <string>()); Schedule scheduler = new Schedule(width, height); scheduler.SHOULD_DO_GARBAGE_COLLECTION = EnableGarbageCollection; List <StaticDeclarationBlock> staticModuleDeclarations = runningGraph.Nodes.Where(node => node.value is StaticDeclarationBlock) .Select(node => node.value as StaticDeclarationBlock) .ToList(); if (staticModuleDeclarations.Count > 0) { scheduler.PlaceStaticModules(staticModuleDeclarations); scopedVariables.Peek().AddRange(scheduler.NewVariablesCreatedInThisScope.Distinct()); } while (runningGraph != null) { int time = scheduler.ListScheduling(runningGraph, Executor); scopedVariables.Peek().AddRange(scheduler.NewVariablesCreatedInThisScope.Distinct().Where(x => !x.Contains("#@#Index"))); foreach (var item in scheduler.OutputtedDroplets) { if (sumOutputtedDropelts.ContainsKey(item.Key)) { sumOutputtedDropelts[item.Key].AddRange(item.Value); } else { sumOutputtedDropelts.Add(item.Key, item.Value); } } List <Command>[] commandTimeline = CreateCommandTimeline(scheduler.ScheduledOperations, time); if (firstRun) { bool[] usedElectrodes = GetusedElectrodes(width, height, commandTimeline, EnableSparseElectrodes); StartExecutor(graph.StartDFG, scheduler.StaticModules.Select(pair => pair.Value).ToList(), usedElectrodes); firstRun = false; } SendCommands(commandTimeline, ref oldRectangles, scheduler.rectanglesAtDifferentTimes); if (KeepRunning.IsCancellationRequested) { return; } runningGraph.Nodes.ForEach(x => x.value.Reset()); (runningGraph, _) = GetNextGraph(graph, runningGraph, Executor, scheduler.Variables, controlStack, scopedVariables, scheduler.FluidVariableLocations); } Executor.UpdateDropletData(sumOutputtedDropelts.Values.SelectMany(x => x.Select(y => y.GetFluidConcentrations())).ToList()); }
private static Dictionary <DFG <Block>, string> CreateNodesAndEdgesForEachDFGInCDFG(CDFG cdfg, ref string nodes, ref string edges) { var dfgNames = new Dictionary <DFG <Block>, string>(); int dfgNameNumber = 0; int nodeNameID = 0; foreach (var node in cdfg.Nodes) { Dictionary <Node <Block>, string> nodeNamer = new Dictionary <Node <Block>, string>(); foreach (Node <Block> nodeBlock in node.dfg.Nodes) { nodeNamer.Add(nodeBlock, nodeNameID++.ToString()); } string dfgName = $"G{dfgNameNumber}"; var simpleGraph = DFGToSimpleGraph(node.dfg, dfgName, nodeNamer); nodes += simpleGraph.nodes; edges += simpleGraph.edges; dfgNames.Add(node.dfg, dfgName); dfgNameNumber++; } return(dfgNames); }
private static string CreateEdgesBetweenDFGs(DFG <Block> dfg, CDFG cdfg, string edges, Dictionary <DFG <Block>, string> dfgNames, List <(DFG <Block>, DFG <Block>)> edgesAlreadyCreated, Stack <DFG <Block> > nextDFGStack)
public static bool CanOptimizeCDFG(CDFG cdfg) { return(cdfg.Nodes.All(x => x.dfg.Nodes.All(y => !(y is INonDeterministic)))); }