Пример #1
0
        public void LoadTurtle(string tfile)
        {
            DateTime tt0 = DateTime.Now;

            // ======== Загрузка первичных ячеек данными ========
            otriples.Clear();
            otriples.Fill(new object[0]);
            dtriples.Clear();
            dtriples.Fill(new object[0]);
            literals.Clear();
            literals.Fill(new object[0]);
            int i = 0;

            foreach (var triple in TripleInt.LoadGraph(tfile))
            {
                if (i % 100000 == 0)
                {
                    Console.Write("{0} ", i / 100000);
                }
                i++;
                if (triple is OTripleInt)
                {
                    var tr = (OTripleInt)triple;
                    otriples.Root.AppendElement(new object[]
                    {
                        tr.subject,
                        tr.predicate,
                        tr.obj
                    });
                }
                else
                {
                    var      tr  = (DTripleInt)triple;
                    Literal  lit = tr.data;
                    object[] da;
                    if (lit.Vid == LiteralVidEnumeration.integer)
                    {
                        da = new object[] { 1, lit.Value }
                    }
                    ;
                    else if (lit.Vid == LiteralVidEnumeration.date)
                    {
                        da = new object[] { 3, lit.Value }
                    }
                    ;
                    else if (lit.Vid == LiteralVidEnumeration.text)
                    {
                        Text t = (Text)lit.Value;
                        da = new object[] { 2, new object[] { t.Value, t.Lang } };
                    }
                    else
                    {
                        da = new object[] { 0, null }
                    };
                    var off = literals.Root.AppendElement(da);
                    dtriples.Root.AppendElement(new object[]
                    {
                        tr.subject,
                        tr.predicate,
                        off
                    });
                }
            }
            otriples.Flush();
            dtriples.Flush();
            literals.Flush();

            // ======== Формирование вторичных ячеек ========
            PaCell otriples_op = new PaCell(tp_otriples, path + "otriples_op.pac", false);

            otriples_op.Clear(); otriples_op.Fill(new object[0]); // Другой вариант - копирование файла
            otriples.Root.Scan((off, pobj) =>
            {
                otriples_op.Root.AppendElement(pobj);
                return(true);
            });
            otriples_op.Flush();

            Console.WriteLine("Additional files ok. duration={0}", (DateTime.Now - tt0).Ticks / 10000L); tt0 = DateTime.Now;

            // ======= Сортировки =======
            // Упорядочивание otriples по s-p-o
            SPOComparer spo_compare = new SPOComparer();

            otriples.Root.SortByKey <SubjPredObjInt>(rec => new SubjPredObjInt(rec), spo_compare);
            Console.WriteLine("otriples.Root.Sort ok. Duration={0} msec.", (DateTime.Now - tt0).Ticks / 10000L); tt0 = DateTime.Now;

            SPComparer sp_compare = new SPComparer();

            // Упорядочивание otriples_op по o-p
            otriples_op.Root.SortByKey <SubjPredInt>(rec =>
            {
                object[] r = (object[])rec;
                return(new SubjPredInt()
                {
                    pred = (int)r[1], subj = (int)r[2]
                });
            }, sp_compare);
            Console.WriteLine("otriples_op Sort ok. Duration={0} msec.", (DateTime.Now - tt0).Ticks / 10000L); tt0 = DateTime.Now;

            // Упорядочивание dtriples_sp по s-p
            dtriples.Root.SortByKey(rec =>
            {
                object[] r = (object[])rec;
                return(new SubjPredInt()
                {
                    pred = (int)r[1], subj = (int)r[0]
                });
            }, sp_compare);
            Console.WriteLine("dtriples.Root.Sort ok. Duration={0} msec.", (DateTime.Now - tt0).Ticks / 10000L); tt0 = DateTime.Now;

            // ==== Определение количества сущностей ====
            // Делаю три упрощенных сканера
            DiapasonScanner <int> i_fields  = new DiapasonScanner <int>(dtriples, ent => (int)((object[])ent.Get())[0]);
            DiapasonScanner <int> i_direct  = new DiapasonScanner <int>(otriples, ent => (int)((object[])ent.Get())[0]);
            DiapasonScanner <int> i_inverse = new DiapasonScanner <int>(otriples_op, ent => (int)((object[])ent.Get())[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, 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();

            // Заведем ячейку для результата сканирования
            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();
            Console.WriteLine("tree_fix ok. Duration={0} msec.", (DateTime.Now - tt0).Ticks / 10000L); tt0 = DateTime.Now;


            otriples.Close();
            otriples_op.Close();
            dtriples.Close();
            literals.Close();
        }
Пример #2
0
        public static IEnumerable <TripleInt> LoadGraph(string datafile)
        {
            int    ntriples = 0;
            string subject  = null;
            Dictionary <string, string> namespaces = new Dictionary <string, string>();

            System.IO.StreamReader sr = new System.IO.StreamReader(datafile);
            int count = 2000000000;

            for (int i = 0; i < count; i++)
            {
                string line = sr.ReadLine();
                //if (i % 10000 == 0) { Console.Write("{0} ", i / 10000); }
                if (line == null)
                {
                    break;
                }
                if (line == "")
                {
                    continue;
                }
                if (line[0] == '@')
                { // namespace
                    string[] parts = line.Split(' ');
                    if (parts.Length != 4 || parts[0] != "@prefix" || parts[3] != ".")
                    {
                        Console.WriteLine("Err: strange line: " + line);
                        continue;
                    }
                    string pref   = parts[1];
                    string nsname = parts[2];
                    if (nsname.Length < 3 || nsname[0] != '<' || nsname[nsname.Length - 1] != '>')
                    {
                        Console.WriteLine("Err: strange nsname: " + nsname);
                        continue;
                    }
                    nsname = nsname.Substring(1, nsname.Length - 2);
                    namespaces.Add(pref, nsname);
                }
                else if (line[0] != ' ')
                { // Subject
                    line    = line.Trim();
                    subject = GetEntityString(namespaces, line);
                    if (subject == null)
                    {
                        continue;
                    }
                }
                else
                { // Predicate and object
                    string line1       = line.Trim();
                    int    first_blank = line1.IndexOf(' ');
                    if (first_blank == -1)
                    {
                        Console.WriteLine("Err in line: " + line); continue;
                    }
                    string pred_line = line1.Substring(0, first_blank);
                    string predicate = GetEntityString(namespaces, pred_line);
                    string rest_line = line1.Substring(first_blank + 1).Trim();
                    // Уберем последний символ
                    rest_line = rest_line.Substring(0, rest_line.Length - 1).Trim();
                    bool isDatatype = rest_line[0] == '\"';
                    // объект может быть entity или данное, у данного может быть языковый спецификатор или тип
                    string entity   = null;
                    string sdata    = null;
                    string datatype = null;
                    string lang     = null;
                    if (isDatatype)
                    {
                        // Последняя двойная кавычка
                        int lastqu = rest_line.LastIndexOf('\"');

                        // Значение данных
                        sdata = rest_line.Substring(1, lastqu - 1);

                        // Языковый специализатор:
                        int dog = rest_line.LastIndexOf('@');
                        if (dog == lastqu + 1)
                        {
                            lang = rest_line.Substring(dog + 1, rest_line.Length - dog - 1);
                        }

                        int pp = rest_line.IndexOf("^^");
                        if (pp == lastqu + 1)
                        {
                            //  Тип данных
                            string qname = rest_line.Substring(pp + 2);
                            //  тип данных может быть "префиксным" или полным
                            if (qname[0] == '<')
                            {
                                datatype = qname.Substring(1, qname.Length - 2);
                            }
                            else
                            {
                                datatype = GetEntityString(namespaces, qname);
                            }
                        }
                        yield return(new DTripleInt()
                        {
                            subject = TripleInt.Code(subject),
                            predicate = TripleInt.Code(predicate),
                            data = // d
                                   datatype == "http://www.w3.org/2001/XMLSchema#integer" ?
                                   new Literal()
                            {
                                Vid = LiteralVidEnumeration.integer, Value = int.Parse(sdata)
                            } :
                            (datatype == "http://www.w3.org/2001/XMLSchema#date" ?
                             new Literal()
                            {
                                Vid = LiteralVidEnumeration.date, Value = DateTime.Parse(sdata).ToBinary()
                            } :
                             (new Literal()
                            {
                                Vid = LiteralVidEnumeration.text, Value = new Text()
                                {
                                    Value = sdata, Lang = "en"
                                }
                            }))
                        });
                    }
                    else
                    { // entity
                        entity = rest_line[0] == '<' ? rest_line.Substring(1, rest_line.Length - 2) : GetEntityString(namespaces, rest_line);

                        yield return(new OTripleInt()
                        {
                            subject = TripleInt.Code(subject),
                            predicate = TripleInt.Code(predicate),
                            obj = TripleInt.Code(entity)
                        });
                    }
                    ntriples++;
                }
            }
            Console.WriteLine("ntriples={0}", ntriples);
        }