Пример #1
0
 private void TransformCDFGToFunctionCDFG(CDFG toTransform, InlineProgramInfo programInfo)
 {
     for (int i = 0; i < toTransform.Nodes.Count; i++)
     {
         TransformDFGToFunctionDFG(toTransform.Nodes[i].dfg, programInfo);
     }
 }
Пример #2
0
        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);
        }
Пример #3
0
        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));
        }
Пример #4
0
        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);
        }
Пример #5
0
        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);
        }
Пример #6
0
 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;
             }
         }
     }
 }
Пример #7
0
        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();
            }
        }
Пример #8
0
        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);
                }
            }
        }
Пример #9
0
        public async void Update(string xml)
        {
            try
            {
                //xml = xml.Replace("&lt", "<");
                //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);
            }
        }
Пример #10
0
        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);
            }
        }
Пример #11
0
        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);
        }
Пример #12
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);
        }
Пример #13
0
        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);
        }
Пример #14
0
        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());
        }
Пример #15
0
        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);
        }
Пример #16
0
 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)
Пример #17
0
 public static bool CanOptimizeCDFG(CDFG cdfg)
 {
     return(cdfg.Nodes.All(x => x.dfg.Nodes.All(y => !(y is INonDeterministic))));
 }