/// <summary>
 /// Instantiates a new PatternCondition object as a copy from the original condition; for parallelization.
 /// </summary>
 public Object Clone()
 {
     PatternCondition condition = new PatternCondition(ConditionExpression.Copy(""), NeededNodes, NeededEdges, NeededVariables, NeededVariableTypes);
     condition.originalCondition = originalCondition;
     condition.originalSubpatternEmbedding = originalSubpatternEmbedding;
     return condition;
 }
 /// <summary>
 /// Instantiates a new PatternCondition object as a copy from an original condition, used for inlining.
 /// </summary>
 /// <param name="original">The original condition to be copy constructed.</param>
 /// <param name="inlinedSubpatternEmbedding">The embedding which just gets inlined.</param>
 /// <param name="renameSuffix">The rename suffix to be applied to all the nodes, edges, and variables used.</param>
 public PatternCondition(PatternCondition original, PatternGraphEmbedding inlinedSubpatternEmbedding, string renameSuffix)
 {
     originalCondition = original;
     originalSubpatternEmbedding = inlinedSubpatternEmbedding;
     ConditionExpression = (Expression)original.ConditionExpression.Copy(renameSuffix);
     NeededNodes = new String[original.NeededNodes.Length];
     for(int i = 0; i < original.NeededNodes.Length; ++i)
         NeededNodes[i] = original.NeededNodes[i] + renameSuffix;
     NeededEdges = new String[original.NeededEdges.Length];
     for(int i = 0; i < original.NeededEdges.Length; ++i)
         NeededEdges[i] = original.NeededEdges[i] + renameSuffix;
     NeededVariables = new String[original.NeededVariables.Length];
     for(int i = 0; i < original.NeededVariables.Length; ++i)
         NeededVariables[i] = original.NeededVariables[i] + renameSuffix;
     NeededVariableTypes = (VarType[])original.NeededVariableTypes.Clone();
 }
        /// <summary>
        /// Interpretation plan operations implementing the
        /// CheckCondition search plan operation
        /// are created and inserted into the interpretation plan at the insertion point
        /// </summary>
        private void buildCondition(
            InterpretationPlan insertionPoint, int index,
            PatternCondition condition)
        {
            // check condition
            expression.AreAttributesEqual aae = (expression.AreAttributesEqual)condition.ConditionExpression;
            foreach(SearchPlanNode spn in spg.Nodes)
            {
                if(spn.PatternElement == aae.thisInPattern)
                {
                    InterpretationPlanCheckCondition checkCondition;
                    if(spn is SearchPlanNodeNode)
                    {
                        SearchPlanNodeNode nodeNode = (SearchPlanNodeNode)spn;
                        checkCondition = new InterpretationPlanCheckCondition(
                            aae, nodeNode.nodeMatcher, Array.IndexOf(aae.thisInPattern.pointOfDefinition.nodes, aae.thisInPattern));
                    }
                    else
                    {
                        SearchPlanEdgeNode edgeNode = (SearchPlanEdgeNode)spn;
                        checkCondition = new InterpretationPlanCheckCondition(
                            aae, edgeNode.edgeMatcher, Array.IndexOf(aae.thisInPattern.pointOfDefinition.edges, aae.thisInPattern));
                    }

                    checkCondition.prev = insertionPoint;
                    insertionPoint.next = checkCondition;
                    insertionPoint = insertionPoint.next;

                    // continue with next operation
                    BuildInterpretationPlan(insertionPoint, index + 1);
                    return;
                }
            }
            throw new Exception("Internal error constructing interpretation plan!");
        }
        /// <summary>
        /// Inserts conditions into the schedule given by the operations list at their earliest possible position
        /// todo: set/map operations are potentially expensive, 
        /// they shouldn't be insertes asap, but depending an weight, 
        /// derived from statistics over set/map size for graph elements, quiet well known for anonymous rule sets
        /// </summary>
        public void InsertConditionsIntoSchedule(PatternCondition[] conditions, List<SearchOperation> operations)
        {
            // get needed (in order to evaluate it) elements of each condition 
            Dictionary<String, bool>[] neededElements = new Dictionary<String, bool>[conditions.Length];
            for(int i = 0; i < conditions.Length; ++i)
            {
                neededElements[i] = new Dictionary<string, bool>();
                foreach(String neededNode in conditions[i].NeededNodes)
                    neededElements[i][neededNode] = true;
                foreach(String neededEdge in conditions[i].NeededEdges)
                    neededElements[i][neededEdge] = true;
                foreach(String neededVariable in conditions[i].NeededVariables)
                    neededElements[i][neededVariable] = true;
            }

            // iterate over all conditions
            for(int i = 0; i < conditions.Length; ++i)
            {
                int j;
                float costToEnd = 0;

                // find leftmost place in scheduled search plan for current condition
                // by search from end of schedule forward until the first element the condition is dependent on is found
                for(j = operations.Count - 1; j >= 0; --j)
                {
                    SearchOperation op = operations[j];
                    if(op.Type == SearchOperationType.Condition
                        || op.Type == SearchOperationType.NegativePattern
                        || op.Type == SearchOperationType.IndependentPattern
                        || op.Type == SearchOperationType.DefToBeYieldedTo)
                    {
                        continue;
                    }

                    if(LazyNegativeIndependentConditionEvaluation)
                    {
                        break;
                    }

                    if(op.Type == SearchOperationType.AssignVar)
                    {
                        if(neededElements[i].ContainsKey(((PatternVariable)op.Element).Name))
                        {
                            costToEnd = op.CostToEnd;
                            break;
                        }
                        continue;
                    }

                    if(neededElements[i].ContainsKey(((SearchPlanNode)op.Element).PatternElement.Name))
                    {
                        costToEnd = op.CostToEnd;
                        break;
                    }
                }

                operations.Insert(j + 1, new SearchOperation(SearchOperationType.Condition,
                    conditions[i], null, costToEnd));
            }
        }
        /// <summary>
        /// Search program operations implementing the
        /// Condition search plan operation
        /// are created and inserted into search program
        /// </summary>
        private SearchProgramOperation buildCondition(
            SearchProgramOperation insertionPoint,
            int currentOperationIndex,
            PatternCondition condition)
        {
            // generate c#-code-string out of condition expression ast
            SourceBuilder conditionExpression = new SourceBuilder();
            condition.ConditionExpression.Emit(conditionExpression);

            // check condition with current partial match
            CheckPartialMatchByCondition checkCondition =
                new CheckPartialMatchByCondition(conditionExpression.ToString(),
                    condition.NeededNodes,
                    condition.NeededEdges,
                    condition.NeededVariables);
            insertionPoint = insertionPoint.Append(checkCondition);

            //---------------------------------------------------------------------------
            // build next operation
            insertionPoint = BuildScheduledSearchPlanOperationIntoSearchProgram(
                currentOperationIndex + 1,
                insertionPoint);
            //---------------------------------------------------------------------------

            return insertionPoint;
        }