public static void CreatePickMapCastAssignPlanEdges(PatternNode node, List<PlanEdge> planEdges, float zeroCost)
        {
            if(node.Storage != null && node.GetPatternElementThisElementDependsOnOutsideOfGraphConnectedness() != null)
            {
                PlanEdge storAccessPlanEdge = new PlanEdge(
                    node.StorageIndex != null ? SearchOperationType.MapWithStorageDependent : SearchOperationType.PickFromStorageDependent,
                    node.GetPatternElementThisElementDependsOnOutsideOfGraphConnectedness().TempPlanMapping, node.TempPlanMapping, zeroCost);
                planEdges.Add(storAccessPlanEdge);
                node.TempPlanMapping.IncomingEdges.Add(storAccessPlanEdge);
            }
            else if(node.IndexAccess != null && node.GetPatternElementThisElementDependsOnOutsideOfGraphConnectedness() != null)
            {
                PlanEdge indexAccessPlanEdge = new PlanEdge(
                    SearchOperationType.PickFromIndexDependent,
                    node.GetPatternElementThisElementDependsOnOutsideOfGraphConnectedness().TempPlanMapping, node.TempPlanMapping, zeroCost);
                planEdges.Add(indexAccessPlanEdge);
                node.TempPlanMapping.IncomingEdges.Add(indexAccessPlanEdge);
            }
            else if(node.NameLookup != null && node.GetPatternElementThisElementDependsOnOutsideOfGraphConnectedness() != null)
            {
                PlanEdge nameAccessPlanEdge = new PlanEdge(
                    SearchOperationType.PickByNameDependent,
                    node.GetPatternElementThisElementDependsOnOutsideOfGraphConnectedness().TempPlanMapping, node.TempPlanMapping, zeroCost);
                planEdges.Add(nameAccessPlanEdge);
                node.TempPlanMapping.IncomingEdges.Add(nameAccessPlanEdge);
            }
            else if(node.UniqueLookup != null && node.GetPatternElementThisElementDependsOnOutsideOfGraphConnectedness() != null)
            {
                PlanEdge uniqueAccessPlanEdge = new PlanEdge(
                    SearchOperationType.PickByUniqueDependent,
                    node.GetPatternElementThisElementDependsOnOutsideOfGraphConnectedness().TempPlanMapping, node.TempPlanMapping, zeroCost);
                planEdges.Add(uniqueAccessPlanEdge);
                node.TempPlanMapping.IncomingEdges.Add(uniqueAccessPlanEdge);
            }
            else if(node.ElementBeforeCasting != null)
            {
                PlanEdge castPlanEdge = new PlanEdge(SearchOperationType.Cast,
                    node.ElementBeforeCasting.TempPlanMapping, node.TempPlanMapping, zeroCost);
                planEdges.Add(castPlanEdge);
                node.TempPlanMapping.IncomingEdges.Add(castPlanEdge);
            }
            else if(node.AssignmentSource != null)
            {
                PlanEdge assignPlanEdge = new PlanEdge(SearchOperationType.Assign,
                    node.AssignmentSource.TempPlanMapping, node.TempPlanMapping, zeroCost);
                planEdges.Add(assignPlanEdge);
                node.TempPlanMapping.IncomingEdges.Add(assignPlanEdge);

                if(!node.AssignmentSource.TempPlanMapping.IsPreset)
                {
                    PlanEdge assignPlanEdgeOpposite = new PlanEdge(SearchOperationType.Assign,
                        node.TempPlanMapping, node.AssignmentSource.TempPlanMapping, zeroCost);
                    planEdges.Add(assignPlanEdgeOpposite);
                    node.AssignmentSource.TempPlanMapping.IncomingEdges.Add(assignPlanEdgeOpposite);
                }
            }
        }
        private static void CreatePlanNodeAndLookupPlanEdge(PatternNode node, int elemId, 
            LGSPGraphStatistics graphStatistics, PatternGraph patternGraph, bool isNegativeOrIndependent, bool isSubpatternLike, PlanNode planRoot, float zeroCost,
            IDictionary<PatternNode, PatternNode> originalToInlinedIndependent, IDictionary<PatternElement, SetValueType> presetsFromIndependentInlining,
            out PlanNode planNode, out PlanEdge rootToNodePlanEdge)
        {
            float cost;
            bool isPreset;
            SearchOperationType searchOperationType;
            if(node.DefToBeYieldedTo)
            {
                cost = zeroCost;
                isPreset = true;
                searchOperationType = SearchOperationType.DefToBeYieldedTo;
            }
            else if(node.PointOfDefinition == null)
            {
                cost = zeroCost;
                isPreset = true;
                searchOperationType = isSubpatternLike ? SearchOperationType.SubPreset : SearchOperationType.ActionPreset;
            }
            else if(node.PointOfDefinition != patternGraph && node.OriginalIndependentElement == null)
            {
                cost = zeroCost;
                isPreset = true;
                searchOperationType = isNegativeOrIndependent ? SearchOperationType.NegIdptPreset : SearchOperationType.SubPreset;
            }
            else if(presetsFromIndependentInlining.ContainsKey(node))
            {
                cost = zeroCost;
                isPreset = true;
                searchOperationType = SearchOperationType.NegIdptPreset;
                node.PresetBecauseOfIndependentInlining = true;
            }
            else if(node.Storage != null)
            {
                if(node.GetPatternElementThisElementDependsOnOutsideOfGraphConnectedness() != null)
                {
                    cost = zeroCost;
                    isPreset = false;
                    searchOperationType = SearchOperationType.Void; // the element we depend on is needed, so there is no lookup like operation
                }
                else
                {
                    cost = zeroCost;
                    isPreset = false;
                    searchOperationType = SearchOperationType.PickFromStorage; // pick from storage instead of lookup from graph
                }
            }
            else if(node.IndexAccess != null)
            {
                if(node.GetPatternElementThisElementDependsOnOutsideOfGraphConnectedness() != null)
                {
                    cost = zeroCost;
                    isPreset = false;
                    searchOperationType = SearchOperationType.Void; // the element we depend on is needed, so there is no lookup like operation
                }
                else
                {
                    cost = zeroCost;
                    isPreset = false;
                    searchOperationType = SearchOperationType.PickFromIndex; // pick from index instead of lookup from graph
                }
            }
            else if(node.NameLookup != null)
            {
                if(node.GetPatternElementThisElementDependsOnOutsideOfGraphConnectedness() != null)
                {
                    cost = zeroCost;
                    isPreset = false;
                    searchOperationType = SearchOperationType.Void; // the element we depend on is needed, so there is no lookup like operation
                }
                else
                {
                    cost = zeroCost;
                    isPreset = false;
                    searchOperationType = SearchOperationType.PickByName; // pick by name instead of lookup from graph
                }
            }
            else if(node.UniqueLookup != null)
            {
                if(node.GetPatternElementThisElementDependsOnOutsideOfGraphConnectedness() != null)
                {
                    cost = zeroCost;
                    isPreset = false;
                    searchOperationType = SearchOperationType.Void; // the element we depend on is needed, so there is no lookup like operation
                }
                else
                {
                    cost = zeroCost;
                    isPreset = false;
                    searchOperationType = SearchOperationType.PickByUnique; // pick by unique instead of lookup from graph
                }
            }
            else if(node.ElementBeforeCasting != null)
            {
                cost = zeroCost;
                isPreset = false;
                searchOperationType = SearchOperationType.Void; // the element before casting is needed, so there is no lookup like operation
            }
            else
            {
                cost = graphStatistics.nodeCounts[node.TypeID];
                cost = CostIncreaseForInlinedIndependent(node, cost);
                isPreset = false;
                searchOperationType = SearchOperationType.Lookup;
            }

            planNode = new PlanNode(node, elemId, isPreset);
            rootToNodePlanEdge = null;
            if(searchOperationType != SearchOperationType.Void)
                rootToNodePlanEdge = new PlanEdge(searchOperationType, planRoot, planNode, cost);
        }