public static PredictDictionary GetInputsFromParentKeys(this PredictorPredictContext ctx, Dictionary <QueryToken, object?> parentKeyValues, PredictionOptions?options = null)
        {
            if (!ctx.Predictor.MainQuery.GroupResults)
            {
                var kvp = parentKeyValues.SingleEx();

                if (kvp.Key.FullKey() != "Entity")
                {
                    throw new InvalidOperationException("only Entity expected");
                }

                var filters = new List <Filter> {
                    new FilterCondition(kvp.Key, FilterOperation.EqualTo, kvp.Value)
                };

                return(ctx.FromFilters(filters, options).SingleEx());
            }
            else
            {
                var filters = ctx.Predictor.MainQuery.Columns
                              .Select(a => a.Token.Token)
                              .Where(t => !(t is AggregateToken))
                              .Select(t => (Filter) new FilterCondition(t, FilterOperation.EqualTo, parentKeyValues.GetOrThrow(t)))
                              .ToList();

                return(ctx.FromFilters(filters, options).SingleEx());
            }
        }
        public static PredictorPredictContext CreatePredictContext(this PredictorEntity p)
        {
            var codifications = p.RetrievePredictorCodifications();
            var ppc           = new PredictorPredictContext(p, PredictorLogic.Algorithms.GetOrThrow(p.Algorithm), codifications);

            ppc.Algorithm.LoadModel(ppc);
            return(ppc);
        }
        public static PredictDictionary GetInputsFromEntity(this PredictorPredictContext ctx, Lite <Entity> entity, PredictionOptions?options = null)
        {
            var qd = QueryLogic.Queries.QueryDescription(ctx.Predictor.MainQuery.Query.ToQueryName());

            var entityToken = QueryUtils.Parse("Entity", qd, 0);

            return(ctx.FromFilters(new List <Filter> {
                new FilterCondition(entityToken, FilterOperation.EqualTo, entity)
            }, options).SingleEx());
        }
        public static PredictDictionary GetInputsEmpty(this PredictorPredictContext ctx, PredictionOptions?options = null)
        {
            var result = new PredictDictionary(ctx.Predictor, options, null)
            {
                MainQueryValues = ctx.Predictor.MainQuery.Columns.Select((c, i) => KVP.Create(c, (object?)null)).ToDictionaryEx(),
                SubQueries      = ctx.Predictor.SubQueries.ToDictionary(sq => sq, sq => new PredictSubQueryDictionary(sq)
                {
                    SubQueryGroups = new Dictionary <object?[], Dictionary <PredictorSubQueryColumnEmbedded, object?> >(ObjectArrayComparer.Instance)
                })
            };

            return(result);
        }
        public static PredictorPredictContext GetPredictContext(this Lite <PredictorEntity> predictor)
        {
            lock (TrainedPredictorCache)
                return(TrainedPredictorCache.GetOrCreate(predictor, () =>
                {
                    using (ExecutionMode.Global())
                        using (var t = Transaction.ForceNew())
                        {
                            var p = predictor.RetrieveAndRemember();
                            if (p.State != PredictorState.Trained)
                            {
                                throw new InvalidOperationException($"Predictor '{p.Name}' not trained");
                            }

                            PredictorPredictContext ppc = CreatePredictContext(p);
                            return t.Commit(ppc);
                        }
                }));
        }
        public static List <PredictDictionary> FromFilters(this PredictorPredictContext ctx, List <Filter> filters, PredictionOptions?options = null)
        {
            var qd = QueryLogic.Queries.QueryDescription(ctx.Predictor.MainQuery.Query.ToQueryName());

            var qr = new QueryRequest
            {
                QueryName = qd.QueryName,

                GroupResults = ctx.Predictor.MainQuery.GroupResults,

                Filters = filters, /*Filters of Main Query not considered*/

                Columns = ctx.Predictor.MainQuery.Columns.Select(c => new Column(c.Token.Token, null)).ToList(),

                Pagination = new Pagination.All(),
                Orders     = Enumerable.Empty <Order>().ToList(),
            };

            var mainQueryKeys = PredictorLogic.GetParentKeys(ctx.Predictor.MainQuery);

            var rt = QueryLogic.Queries.ExecuteQuery(qr);

            var subQueryResults = ctx.Predictor.SubQueries.ToDictionaryEx(sq => sq, sqe =>
            {
                List <QueryToken> parentKeys = sqe.Columns.Where(a => a.Usage == PredictorSubQueryColumnUsage.ParentKey).Select(a => a.Token.Token).ToList();

                QueryDescription sqd = QueryLogic.Queries.QueryDescription(sqe.Query.ToQueryName());

                Dictionary <string, string> tokenReplacements = mainQueryKeys.ZipStrict(parentKeys, (m, p) => KVP.Create(m.FullKey(), p.FullKey())).ToDictionaryEx();

                Filter[] mainFilters = filters.Select(f => Replace(f, tokenReplacements, sqd)).ToArray();

                List <Filter> additionalFilters = sqe.Filters.ToFilterList();

                List <Column> allColumns = sqe.Columns.Select(c => new Column(c.Token.Token, null)).ToList();

                var qgr = new QueryRequest
                {
                    QueryName    = sqe.Query.ToQueryName(),
                    GroupResults = true,
                    Filters      = mainFilters.Concat(additionalFilters).ToList(),
                    Columns      = allColumns,
                    Orders       = new List <Order>(),
                    Pagination   = new Pagination.All(),
                };

                ResultTable resultTable = QueryLogic.Queries.ExecuteQuery(qgr);

                var tuples = sqe.Columns.Zip(resultTable.Columns, (sqc, rc) => (sqc: sqc, rc: rc)).ToList();
                ResultColumn[] entityGroupKey = tuples.Extract(t => t.sqc.Usage == PredictorSubQueryColumnUsage.ParentKey).Select(a => a.rc).ToArray();
                ResultColumn[] remainingKeys  = tuples.Extract(t => t.sqc.Usage == PredictorSubQueryColumnUsage.SplitBy).Select(a => a.rc).ToArray();
                var valuesTuples = tuples;

                return(resultTable.Rows.AgGroupToDictionary(
                           row => row.GetValues(entityGroupKey),
                           gr => gr.ToDictionaryEx(
                               row => row.GetValues(remainingKeys),
                               row => valuesTuples.ToDictionaryEx(t => t.sqc, t => row[t.rc]),
                               ObjectArrayComparer.Instance
                               )
                           ));
            });