using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using miew.Tally; using miew.Debugging; using miew.Enumerable; using miew.String; using miew.Tokenization; namespace agree { /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public sealed partial class TargetTfs : BootstrapTfs//, ITargetTfs { public TargetTfs(TypeMgr tm, int c_edge_hint) : base(tm, c_edge_hint) { c_corefs = 0; } public Dictionary<Int64, Unification.UnifCoref> corefs = null; public int c_corefs = 0; #if true /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Prune a sub-graph, and then remove any unused coreferences (and unmark the edge coreference bit) which /// have only a single use remaining. /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public bool _prune_below(int i_feat, int m) { Edge e; if (!TryGetEdge(i_feat, m, out e)) return false; int c_reentrancies = 0; Unification.UnifCoref uc = null; if (e.FlagsId < 0) { /// find coreference for this edge corefs.TryGetValue(((long)id << 32) | (uint)e.Mark, out uc); while (uc.f_redirect) uc = uc.next; /// if we are pruning the opportunistic reentrancy hint, then clear it if (uc.single_fm.i_feat == i_feat && uc.single_fm.m == m) uc.single_fm = default(FeatMark); c_reentrancies = --uc.c_fm; e = uc.e_cur; } /// only remove *below* a coreferenced edge if it has no reentrancies remaining. This allows sub-graphs to /// be pruned without disturbing the coreferenced portions that are still accessible from without. if (c_reentrancies == 0 && (e.FlagsId & agree.Edge.Flag.EtmNonBareType) != 0) foreach (int fix in tm.rgrgfix_by_type[(int)(e.FlagsId & Edge.Flag.MultiIdMask)]) _prune_below(fix, e.Mark); /// remove the edge if (!RemoveEdge(i_feat, m)) Debug.Assert(false); /// all done if not coreferenced, or if additional reentrancies still point to this edge. if (uc == null || c_reentrancies > 1) return true; /// 0 or 1 reentrancies remain. we will decrement the coreference count at the end of this function. if (c_reentrancies == 1) { /// if there's were 2 reentrancies and now there's just 1 remaining, we're retaining *this* edge, /// so clear its coreference bit, as stored by the *other* reentrancy, and discard the equivalence /// class. We make these adjustments now, because that other edge might not be getting pruned, /// so we might never encounter it. First, find out if the opportunistic hint is any good. FeatMark fm = uc.single_fm; if (fm.m == 0) { /// hint is no good; we must find the other reentrancy by exhaustive search ulong ul = d.First(kvp => { if (kvp.Value.FlagsId >= 0) return false; var ux = corefs[((long)id << 32) | (uint)kvp.Value.Mark]; while (ux.f_redirect) ux = ux.next; return ux == uc; }).Key; fm = new FeatMark((int)(ul >> 32), (int)ul); } Debug.Assert(ContainsFeatMark(fm.i_feat, fm.m)); uc.c_fm = 0; #if DEBUG uc.single_fm = default(FeatMark); #endif /// clear coreference bit (or remove) in the other reentrancy. Edge.Flag nf = e.FlagsId & ~Edge.Flag.Coreference; if (nf == 0) RemoveEdge(fm.i_feat, fm.m); else SetEdge(fm.i_feat, fm.m, new Edge(nf, (nf & Edge.Flag.EtmNonBareType) == 0 ? 0 : e.Mark)); } c_corefs--; return true; } #endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public Tfs ToArrayTfs() { #if DEBUG CheckCoreferences(); #endif ArrayTfs tfs = new ArrayTfs(tm.da, this, null); //MarkingArrayTfs tfs = new MarkingArrayTfs(tm, this.Edge, d, id, corefs, ref c_corefs); d = null; tfs.Name = this.Name; return tfs; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public MotherDaughterTfs ToMotherDaughterTfs(int[] rg_feat_delete) { #if DEBUG CheckCoreferences(); #endif MotherDaughterTfs tfs = new MotherDaughterTfs(tm.da, this, rg_feat_delete); d = null; tfs.Name = this.Name; return tfs; } #if DEBUG public override void CheckCoreferences() { //if (d == null) //{ // base.CheckCoreferences(); // return; //} ///// walking method: //var walk = GetReentrancies(Edge) // .Select(kvp => new KeyValuePair<Edge, ReentrancyFinder.Entry>(corefs[((long)id << 32) | (uint)kvp.Key.Mark].LoopMaster.e_cur, kvp.Value)) /// apply coref info // .GroupBy(kvp => kvp.Key) // .ToDictionary( // grp => grp.Key, // grp => grp.SelectMany(ue => ue.Value).Select(cref => cref.FeatMark).ToHashSet().Count); /// ignore types since they might not be updated yet //if (walk.Count == 0) // return; ///// table scan method: //var table = d.Values // .Where(e => e.FlagsId < 0) // .Select(e => corefs[((long)id << 32) | (uint)e.Mark].LoopMaster.e_cur) /// apply coref info // .GroupBy(e => e.Mark) // .ToDictionary(grp => grp.First(), grp => grp.Count()); //if (walk.Count > table.Count) //{ // var ex = walk.Keys.Except(table.Keys).ToArray(); // if (Debugger.IsAttached) // Debugger.Break(); // else // throw new Exception(); //} //if (table.Count > walk.Count) //{ // var ex = table.Keys.Except(walk.Keys).ToArray(); // if (Debugger.IsAttached) // Debugger.Break(); // else // throw new Exception(); //} //var dqe = table.Where(kvp => walk[kvp.Key] != kvp.Value).ToArray(); //if (dqe.Length > 0) //{ // if (Debugger.IsAttached) // Debugger.Break(); // else // throw new Exception(); //} } #endif }; #if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public sealed partial class MarkingArrayTargetTfs : MarkingArrayTfs { public MarkingArrayTargetTfs(TypeMgr tm, int c_edge_hint) : base(tm, c_edge_hint) { } public Dictionary<Int64, Unification.UnifCoref> corefs = null; /// Number of distinct coreferences //public int c_corefs = 0; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Prune a sub-graph, and then remove any unused coreferences (and unmark the edge coreference bit) which /// have only a single use remaining. /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #if false public bool _prune_below(int i_feat, int m) { Edge e; if (!TryGetEdge(i_feat, m, out e)) return false; int c_reentrancies = 0; Unification.UnifCoref uc = null; if (e.FlagsId < 0) { /// find coreference for this edge corefs.TryGetValue(((long)id << 32) | (uint)e.Mark, out uc); while (uc.f_redirect) uc = uc.next; /// if we are pruning the opportunistic reentrancy hint, then clear it if (uc.single_fm.i_feat == i_feat && uc.single_fm.m == m) uc.single_fm = default(FeatMark); c_reentrancies = --uc.c_fm; e = uc.e_cur; } /// only remove *below* a coreferenced edge if it has no reentrancies remaining. This allows sub-graphs to /// be pruned without disturbing the coreferenced portions that are still accessible from without. if (c_reentrancies == 0 && (e.FlagsId & agree.Edge.Flag.EtmNonBareType) != 0) foreach (int fix in tm.rgrgfix_by_type[(int)(e.FlagsId & Edge.Flag.MultiIdMask)]) _prune_below(fix, e.Mark); /// remove the edge if (!RemoveEdge(i_feat, m)) Debug.Assert(false); /// all done if not coreferenced, or if additional reentrancies still point to this edge. if (uc == null || c_reentrancies > 1) return true; /// 0 or 1 reentrancies remain. we will decrement the coreference count at the end of this function. if (c_reentrancies == 1) { /// if there's were 2 reentrancies and now there's just 1 remaining, we're retaining *this* edge, /// so clear its coreference bit, as stored by the *other* reentrancy, and discard the equivalence /// class. We make these adjustments now, because that other edge might not be getting pruned, /// so we might never encounter it. First, find out if the opportunistic hint is any good. FeatMark fm = uc.single_fm; if (fm.m == 0) { /// hint is no good; we must find the other reentrancy by exhaustive search fm = this.FeatMarkEdges.First(fme => { if (fme.e.FlagsId >= 0) return false; var ux = corefs[((long)id << 32) | (uint)fme.e.Mark]; while (ux.f_redirect) ux = ux.next; return ux == uc; }).FeatMark; } Debug.Assert(ContainsFeatMark(fm.i_feat, fm.m)); uc.c_fm = 0; #if DEBUG uc.single_fm = default(FeatMark); #endif /// clear coreference bit (or remove) in the other reentrancy. Edge.Flag nf = e.FlagsId & ~Edge.Flag.Coreference; if (nf == 0) RemoveEdge(fm.i_feat, fm.m); else SetEdge(fm.i_feat, fm.m, new Edge(nf, (nf & Edge.Flag.EtmNonBareType) == 0 ? 0 : e.Mark)); } this.c_corefs--; return true; } #endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public Tfs ToArrayTfs() { var matfs = new MarkingArrayTfs(this); matfs.Name = this.Name; return matfs; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public MotherDaughterTfs ToMotherDaughterTfs() { var tfs = new MotherDaughterTfs(this); tfs.Name = this.Name; return tfs; } }; #endif }