// Была Площадка для тестирования, а теперь это главный метод public int MakeTreeFix() { DateTime tt0 = DateTime.Now; // Служебная часть. Она не нужна, если параметрами будут PaCell otriples, PaCell otriples_op, PaCell dtriples_sp PType tp_entity = new PType(PTypeEnumeration.integer); PType tp_otriple_seq = new PTypeSequence(new PTypeRecord( new NamedType("subject", tp_entity), new NamedType("predicate", tp_entity), new NamedType("object", tp_entity))); //PType tp_dtriple_seq = new PTypeSequence(new PTypeRecord( // new NamedType("subject", tp_entity), // new NamedType("predicate", tp_entity), // new NamedType("data", tp_literal))); PType tp_dtriple_spf = new PTypeSequence(new PTypeRecord( new NamedType("subject", tp_entity), new NamedType("predicate", tp_entity), new NamedType("offset", new PType(PTypeEnumeration.longinteger)))); otriples = new PaCell(tp_otriple_seq, path + "otriples.pac", true); PaCell otriples_op = new PaCell(tp_otriple_seq, path + "otriples_op.pac", true); PaCell dtriples_sp = new PaCell(tp_dtriple_spf, path + "dtriples.pac", true); // ==== Определение количества сущностей ==== // Делаю три упрощенных сканера DiapasonScanner <int> i_fields = new DiapasonScanner <int>(dtriples_sp, ent => { object[] v = (object[])ent.Get(); return((int)v[0]); }); DiapasonScanner <int> i_direct = new DiapasonScanner <int>(otriples, ent => { object[] v = (object[])ent.Get(); return((int)v[0]); }); DiapasonScanner <int> i_inverse = new DiapasonScanner <int>(otriples_op, ent => { object[] v = (object[])ent.Get(); return((int)v[2]); }); int n_entities = 0; i_fields.Start(); i_direct.Start(); i_inverse.Start(); while (i_fields.HasValue || i_direct.HasValue || i_inverse.HasValue) { n_entities++; int id0 = i_fields.HasValue ? i_fields.KeyCurrent : Int32.MaxValue; int id1 = i_direct.HasValue ? i_direct.KeyCurrent : Int32.MaxValue; int id2 = i_inverse.HasValue ? i_inverse.KeyCurrent : Int32.MaxValue; // Минимальное значение кода идентификатора int id = Math.Min(id0, Math.Min(id1, id2)); if (id0 == id) { i_fields.Next(); } if (id1 == id) { i_direct.Next(); } if (id2 == id) { i_inverse.Next(); } } Console.WriteLine("Scan3count ok. Duration={0} msec. cnt_e={1} ", (DateTime.Now - tt0).Ticks / 10000L, n_entities); tt0 = DateTime.Now; // ==== Построение дерева слиянием отрех ячеек ==== // Делаю три сканера из трех ячеек DiapasonElementsScanner <SubjPredInt> fields = new DiapasonElementsScanner <SubjPredInt>(dtriples_sp, ob => { object[] v = (object[])ob; return(new SubjPredInt() { subj = (int)v[0], pred = (int)v[1] }); }); DiapasonElementsScanner <SubjPredInt> direct = new DiapasonElementsScanner <SubjPredInt>(otriples, ob => { object[] v = (object[])ob; return(new SubjPredInt() { subj = (int)v[0], pred = (int)v[1] }); }); DiapasonElementsScanner <SubjPredInt> inverse = new DiapasonElementsScanner <SubjPredInt>(otriples_op, ob => { object[] v = (object[])ob; return(new SubjPredInt() { subj = (int)v[2], pred = (int)v[1] }); }); // Стартуем сканеры fields.Start(); direct.Start(); inverse.Start(); // Заведем ячейку для результата сканирования PxCell tree_fix = this.entitiesTree; //new PxCell(tp_entitiesTree, path + "tree_fix.pxc", false); tree_fix.Clear(); tree_fix.Root.SetRepeat(n_entities); Console.WriteLine("tree_fix length={0}", tree_fix.Root.Count()); long longindex = 0; int cnt_e = 0; // для отладки long c1 = 0, c2 = 0, c3 = 0; // для отладки //PaEntry ent_dtriples = dtriples.Root.Element(0); // вход для доступа к литералам // Начинаем тройное сканирование while (fields.HasValue || direct.HasValue || inverse.HasValue) { // Здесь у нас НОВОЕ значение идентификатора cnt_e++; if (cnt_e % 10000000 == 0) { Console.Write("{0} ", cnt_e / 10000000); } int id0 = fields.HasValue ? fields.KeyCurrent.subj : Int32.MaxValue; int id1 = direct.HasValue ? direct.KeyCurrent.subj : Int32.MaxValue; int id2 = inverse.HasValue ? inverse.KeyCurrent.subj : Int32.MaxValue; // Минимальное значение кода идентификатора int id = Math.Min(id0, Math.Min(id1, id2)); // массив для получения "однородных" элементов из сканнеров object[] elements; List <object[]> list_fields = new List <object[]>(); while (fields.HasValue && fields.KeyCurrent.subj == id) { int su = fields.KeyCurrent.subj; int pr = fields.KeyCurrent.pred; var diap = fields.Next(out elements); c3 += diap.numb; list_fields.AddRange(elements.Cast <object[]>().Select(e3 => new object[] { e3[1], e3[2] })); } List <object[]> list_direct = new List <object[]>(); while (direct.HasValue && direct.KeyCurrent.subj == id) { int su = direct.KeyCurrent.subj; int pr = direct.KeyCurrent.pred; var diap = direct.Next(out elements); c1 += diap.numb; list_direct.AddRange(elements.Cast <object[]>().Select(e3 => new object[] { e3[1], e3[2] })); } List <object[]> list_inverse = new List <object[]>(); while (inverse.HasValue && inverse.KeyCurrent.subj == id) { int su = inverse.KeyCurrent.subj; int pr = inverse.KeyCurrent.pred; var diap = inverse.Next(out elements); c2 += diap.numb; object[] pr_sources_pair = new object[2]; pr_sources_pair[0] = pr; pr_sources_pair[1] = elements.Cast <object[]>().Select(e3 => e3[0]).ToArray(); list_inverse.Add(pr_sources_pair); } //Собираем полную запись object[] record = new object[] { id, list_fields.ToArray(), list_direct.ToArray(), list_inverse.ToArray() }; // Записываем в качестве элемента последовательности tree_fix.Root.Element(longindex).Set(record); longindex++; } tree_fix.Close(); this.entitiesTree = new PxCell(tp_entitiesTree, path + "entitiesTree.pxc", false); Console.WriteLine("Scan3fix ok. Duration={0} msec. cnt_e={1} ", (DateTime.Now - tt0).Ticks / 10000L, cnt_e); tt0 = DateTime.Now; return(cnt_e); }
private int MakeTreeFree(PaCell otriples, PaCell otriples_op, PaCell dtriples_sp) { // Делаю три сканера из трех ячеек DiapasonScanner <SubjPredInt> fields = new DiapasonScanner <SubjPredInt>(dtriples_sp, ent => { object[] v = (object[])ent.Get(); return(new SubjPredInt() { subj = (int)v[0], pred = (int)v[1] }); }); DiapasonScanner <SubjPredInt> direct = new DiapasonScanner <SubjPredInt>(otriples, ent => { object[] v = (object[])ent.Get(); return(new SubjPredInt() { subj = (int)v[0], pred = (int)v[1] }); }); DiapasonScanner <SubjPredInt> inverse = new DiapasonScanner <SubjPredInt>(otriples_op, ent => { object[] v = (object[])ent.Get(); return(new SubjPredInt() { subj = (int)v[2], pred = (int)v[1] }); }); // Стартуем сканеры fields.Start(); direct.Start(); inverse.Start(); // Заведем ячейку для результата сканирования PaCell tree_free = new PaCell(tp_entitiesTree, path + "tree_free.pac", false); tree_free.Clear(); int cnt_e = 0, cnt_ep = 0; // для отладки long c1 = 0, c2 = 0, c3 = 0; // для отладки //PaEntry ent_dtriples = dtriples.Root.Element(0); // вход для доступа к литералам // Начинаем тройное сканирование tree_free.StartSerialFlow(); tree_free.S(); while (fields.HasValue || direct.HasValue || inverse.HasValue) { // Здесь у нас НОВОЕ значение идентификатора cnt_e++; if (cnt_e % 10000000 == 0) { Console.Write("{0} ", cnt_e / 10000000); } int id0 = fields.HasValue ? fields.KeyCurrent.subj : Int32.MaxValue; int id1 = direct.HasValue ? direct.KeyCurrent.subj : Int32.MaxValue; int id2 = inverse.HasValue ? inverse.KeyCurrent.subj : Int32.MaxValue; // Минимальное значение кода идентификатора int id = Math.Min(id0, Math.Min(id1, id2)); // Начало записи tree_free.R(); // Запись идентификатора tree_free.V(id); tree_free.S(); while (fields.HasValue && fields.KeyCurrent.subj == id) { int su = fields.KeyCurrent.subj; int pr = fields.KeyCurrent.pred; var diap = fields.Next(); c3 += diap.numb; for (long ind = diap.start; ind < diap.start + diap.numb; ind++) { object[] row = (object[])dtriples_sp.Root.Element(ind).Get(); int subj = (int)row[0]; int prop = (int)row[1]; long off = (long)row[2]; if (subj != su || prop != pr) { throw new Exception("Assert err: 287282"); } tree_free.V(new object[] { prop, off }); } } tree_free.Se(); tree_free.S(); while (direct.HasValue && direct.KeyCurrent.subj == id) { int su = direct.KeyCurrent.subj; int pr = direct.KeyCurrent.pred; var diap = direct.Next(); c1 += diap.numb; for (long ind = diap.start; ind < diap.start + diap.numb; ind++) { object[] row = (object[])otriples.Root.Element(ind).Get(); int subj = (int)row[0]; int prop = (int)row[1]; int obj = (int)row[2]; if (subj != su || prop != pr) { throw new Exception("Assert err: 287283"); } tree_free.V(new object[] { prop, obj }); } } tree_free.Se(); tree_free.S(); while (inverse.HasValue && inverse.KeyCurrent.subj == id) { int su = inverse.KeyCurrent.subj; int pr = inverse.KeyCurrent.pred; var diap = inverse.Next(); c2 += diap.numb; tree_free.R(); tree_free.V(pr); tree_free.S(); for (long ind = diap.start; ind < diap.start + diap.numb; ind++) { object[] row = (object[])otriples_op.Root.Element(ind).Get(); int subj = (int)row[0]; int prop = (int)row[1]; int obj = (int)row[2]; if (obj != su || prop != pr) { throw new Exception("Assert err: 287284"); } tree_free.V(subj); } tree_free.Se(); tree_free.Re(); } tree_free.Se(); // Конец записи tree_free.Re(); } tree_free.Se(); tree_free.EndSerialFlow(); return(cnt_e); }