<commit_before>﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using Common;
using MaxSearchAlg;

namespace Grid.Domain
{
    public class ReachableSymmetryDetectionPrunning : IPrunningMethod
    {
        private Dictionary<long, List<RsdGridSearchNode>> HistoryNodes;
        private SortedList<int, INode> aStarOpenList;

        public ReachableSymmetryDetectionPrunning()
        {
            HistoryNodes = new Dictionary<long, List<RsdGridSearchNode>>();
        }

        public void setAstarOpenList(SortedList<int, INode> openList)
        {
            if (aStarOpenList != null)
            {
                throw new ApplicationException("setAstarOpenList must be called only once");
            }
            aStarOpenList = openList;
        }

        public bool ShouldPrune(INode node)
        {
            //The algorithms add current node if this method returns false.
            //in case this node is needs pruning because it is "smaller" then existin we return TRUE
            //when the node in OPEN is smaller we return FALSE and this method will REPLACE the nodes
            //That way the alg. will count the prunning nodes correctly
            if (aStarOpenList == null)
            {
                throw new ApplicationException("setAstarOpenList must be called once before this method");
            }
            var newGridNode = node as RsdGridSearchNode;
            Log.WriteLineIf($"[ShouldPrune - new node] {newGridNode.GetBitsString()}", TraceLevel.Info);
            var hash = GetLinearHeadLocation(newGridNode);
            if (!HistoryNodes.ContainsKey(hash))
            {
                HistoryNodes[hash] = new List<RsdGridSearchNode>();
                HistoryNodes[hash].Add(newGridNode);
                Log.WriteLineIf("[ShouldPrune - No list] - creating new", TraceLevel.Info);
            }
            else
            {
                var relevantList = HistoryNodes[hash];
                for (int i = relevantList.Count - 1; i >= 0; i--)
                {
                    var historyNode = relevantList[i];
                    Log.WriteLineIf($"[ShouldPrune] - checking history node{historyNode.GetBitsString()}", TraceLevel.Info);
                    //historyNode.Visited >= newGridNode.visited   ---- Simple case
                    if (ContainsOrEqualBitArray(historyNode.Visited, newGridNode.Visited))
                    {
                        if (ContainsOrEqualBitArray(historyNode.Reachable, newGridNode.Reachable))
                        {
                            Log.WriteLineIf("[ShouldPrune]- true1", TraceLevel.Info);
                            return true;
                        }
                    }
                    //historyNode.Visited < newGridNode.visited
                    else if (ContainsOrEqualBitArray(newGridNode.Visited, historyNode.Visited))
                    {
                        if (ContainsOrEqualBitArray(newGridNode.Reachable, historyNode.Reachable)) 
                        {
                            if (newGridNode.g > historyNode.g)
                            {
                                Log.WriteLineIf("[ShouldPrune] - remove and add", TraceLevel.Info);
                                //In this special case we replace the old node with new, we return true for pruning in order to count the old node as pruned
                                relevantList.RemoveAt(i);
                                relevantList.Add(newGridNode);
                                ReplaceInOpenList(historyNode, newGridNode);
                            }
                            Log.WriteLineIf("[ShouldPrune]- true2", TraceLevel.Info);
                            return true;
                        }
                    }
                }

                relevantList.Add(newGridNode);
            }
            Log.WriteLineIf("[ShouldPrune] - false", TraceLevel.Info);
            return false;
        }

        private void ReplaceInOpenList(RsdGridSearchNode oldNode, RsdGridSearchNode newNode)
        {
            try
            var a = aStarOpenList.Values.IndexOf(oldNode);
            aStarOpenList.RemoveAt(a);
            aStarOpenList.Add(newNode);
        }

        private long GetLinearHeadLocation(RsdGridSearchNode node)
        {<commit_msg>continue of previous commit<commit_after>﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using Common;
using MaxSearchAlg;

namespace Grid.Domain
{
    public class ReachableSymmetryDetectionPrunning : IPrunningMethod
    {
        private Dictionary<long, List<RsdGridSearchNode>> HistoryNodes;
        private SortedList<int, INode> aStarOpenList;

        public ReachableSymmetryDetectionPrunning()
        {
            HistoryNodes = new Dictionary<long, List<RsdGridSearchNode>>();
        }

        public void setAstarOpenList(SortedList<int, INode> openList)
        {
            if (aStarOpenList != null)
            {
                throw new ApplicationException("setAstarOpenList must be called only once");
            }
            aStarOpenList = openList;
        }

        public bool ShouldPrune(INode node)
        {
            //The algorithms add current node if this method returns false.
            //in case this node is needs pruning because it is "smaller" then existin we return TRUE
            //when the node in OPEN is smaller we return FALSE and this method will REPLACE the nodes
            //That way the alg. will count the prunning nodes correctly
            if (aStarOpenList == null)
            {
                throw new ApplicationException("setAstarOpenList must be called once before this method");
            }
            var newGridNode = node as RsdGridSearchNode;
            Log.WriteLineIf($"[ShouldPrune - new node] {newGridNode.GetBitsString()}", TraceLevel.Info);
            var hash = GetLinearHeadLocation(newGridNode);
            if (!HistoryNodes.ContainsKey(hash))
            {
                HistoryNodes[hash] = new List<RsdGridSearchNode>();
                HistoryNodes[hash].Add(newGridNode);
                Log.WriteLineIf("[ShouldPrune - No list] - creating new", TraceLevel.Info);
            }
            else
            {
                var relevantList = HistoryNodes[hash];
                for (int i = relevantList.Count - 1; i >= 0; i--)
                {
                    var historyNode = relevantList[i];
                    Log.WriteLineIf($"[ShouldPrune] - checking history node{historyNode.GetBitsString()}", TraceLevel.Info);
                    //historyNode.Visited >= newGridNode.visited   ---- Simple case
                    if (ContainsOrEqualBitArray(historyNode.Visited, newGridNode.Visited))
                    {
                        if (ContainsOrEqualBitArray(historyNode.Reachable, newGridNode.Reachable))
                        {
                            Log.WriteLineIf("[ShouldPrune]- true1", TraceLevel.Info);
                            return true;
                        }
                    }
                    //historyNode.Visited < newGridNode.visited
                    else if (ContainsOrEqualBitArray(newGridNode.Visited, historyNode.Visited))
                    {
                        if (ContainsOrEqualBitArray(newGridNode.Reachable, historyNode.Reachable)) 
                        {
                            if (newGridNode.g > historyNode.g)
                            {
                                Log.WriteLineIf("[ShouldPrune] - remove and add", TraceLevel.Info);
                                //In this special case we replace the old node with new, we return true for pruning in order to count the old node as pruned
                                relevantList.RemoveAt(i);
                                relevantList.Add(newGridNode);
                                ReplaceInOpenList(historyNode, newGridNode);
                            }
                            Log.WriteLineIf("[ShouldPrune]- true2", TraceLevel.Info);
                            return true;
                        }
                    }
                }

                relevantList.Add(newGridNode);
            }
            Log.WriteLineIf("[ShouldPrune] - false", TraceLevel.Info);
            return false;
        }

        private void ReplaceInOpenList(RsdGridSearchNode oldNode, RsdGridSearchNode newNode)
        {
            var a = aStarOpenList.Values.IndexOf(oldNode);
            aStarOpenList.RemoveAt(a);
            aStarOpenList.Add(newNode);
        }

        private long GetLinearHeadLocation(RsdGridSearchNode node)
        {
{'fraction_non_alphanumeric': 0.07596970392471884, 'fraction_numerical': 0.0009180628873077806, 'mean_word_length': 1.5504828797190517, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7582734', 'n_tokens_mistral': 2131, 'n_tokens_neox': 2050, 'n_words': 508}