示例#1
0
        private SpecificLayout inferredLayout(LayoutQuery query, SpecificLayout response)
        {
            this.inferred_queryResults[query] = response;
            LayoutQuery_And_Response pair = new LayoutQuery_And_Response(query, response);

            this.orderedResponses.Add(pair);
            //this.debugCheck(pair);
            return(response);
        }
示例#2
0
        private void debugCheck(LayoutQuery_And_Response queryAndResponse)
        {
            // make sure that each query likes its response at least as much as all others
            SpecificLayout result = queryAndResponse.Response;
            LayoutQuery    query  = queryAndResponse.Query;

            for (int i = 0; i < this.orderedResponses.Count; i++)
            {
                LayoutQuery_And_Response other = this.orderedResponses[i];
                if (other.Query.PreferredLayout(other.Response, result) != other.Response)
                {
                    ErrorReporter.ReportParadox("New response is a better solution to previous query than preexisting response.\n" +
                                                "Layout      : " + this.layoutToManage + "\n" +
                                                "Old query   : " + other.Query + "\n" +
                                                "Old response: " + other.Response + "\n" +
                                                "New query   : " + query + "\n" +
                                                "New response: " + result);
                    LayoutQuery query2 = other.Query.Clone();
                    query2.Debug = true;
                    query2.ProposedSolution_ForDebugging = result;
                    SpecificLayout oldQueryNewDebugResult = this.GetBestLayout(query2.Clone());
                    LayoutQuery    query1 = query.Clone();
                    query1.Debug = true;
                    SpecificLayout newQueryDebugResult = this.GetBestLayout(query1.Clone());
                    System.Diagnostics.Debug.WriteLine("Results from LayoutCache discrepancy: Old query new result = " + oldQueryNewDebugResult + ", New query new result = " + newQueryDebugResult);
                    this.layoutToManage.GetBestLayout(query2.Clone());
                    this.layoutToManage.GetBestLayout(query1.Clone());
                }
                if (query.PreferredLayout(result, other.Response) != result)
                {
                    ErrorReporter.ReportParadox("New response is a worse solution to new query than previous response.\n" +
                                                "Layout      : " + this.layoutToManage + "\n" +
                                                "Old query   : " + other.Query + "\n" +
                                                "Old response: " + other.Response + "\n" +
                                                "New query   : " + query + "\n" +
                                                "New response: " + result);

                    LayoutQuery query1 = query.Clone();
                    query1.Debug = true;
                    query1.ProposedSolution_ForDebugging = other.Response;
                    SpecificLayout newQueryDebugResult = this.GetBestLayout(query1);
                    LayoutQuery    query2 = other.Query.Clone();
                    query2.Debug = true;
                    SpecificLayout oldQueryNewDebugResult = this.GetBestLayout(query2);
                    System.Diagnostics.Debug.WriteLine("Results from LayoutCache discrepancy: Old query new result = " + oldQueryNewDebugResult + ", New query new result = " + newQueryDebugResult);
                    this.GetBestLayout(query1.Clone());
                    this.GetBestLayout(query2.Clone());
                }
            }
        }
示例#3
0
        // Attempts to find a query having results that are accepted by this query
        private LayoutQuery_And_Response FindExample(LayoutQuery query)
        {
            // look for the best response we've seen so far for this query
            LayoutQuery_And_Response best = null;

            foreach (LayoutQuery_And_Response candidate in this.orderedResponses)
            {
                if (best == null)
                {
                    if (query.Accepts(candidate.Response))
                    {
                        best = candidate;
                    }
                }
                else
                {
                    if (query.PreferredLayout(best.Response, candidate.Response) == candidate.Response)
                    {
                        best = candidate;
                    }
                }
            }
            return(best);
        }
示例#4
0
        private SpecificLayout GetBestLayout_Quickly(LayoutQuery query)
        {
            SpecificLayout result = null;

            // A layout of size 0 in one dimension doesn't get any points for being nonzero in the other dimension
            if ((query.MaxHeight == 0) != (query.MaxWidth == 0))
            {
                result = this.GetBestLayout_Quickly(this.SizeZeroQuery);
                if (query.Accepts(result))
                {
                    return(result);
                }
                return(null);
            }

            // check whether we've previously saved the result
            if (!query.Debug)
            {
                if (this.true_queryResults.TryGetValue(query, out result) || this.inferred_queryResults.TryGetValue(query, out result))
                {
                    if (result != null)
                    {
                        return(result);
                    }
                    return(null);
                }
            }
            // the result wasn't saved, so we need to delegate the layout query
            // However, we might first be able to make the query more strict

            LayoutQuery_And_Response broadened = this.Find_LargerQuery(query);

            if (broadened != null)
            {
                if (query.Debug)
                {
                    LayoutQuery debugQuery = query.Clone();
                    debugQuery.Debug = true;
                    SpecificLayout correct_subLayout = this.Query_SubLayout(debugQuery);
                    if (broadened.Query.PreferredLayout(broadened.Response, correct_subLayout) != broadened.Response)
                    {
                        ErrorReporter.ReportParadox("Error; incorrect result for broadened query: broadened query " + broadened.Query + " returned " + broadened.Response +
                                                    " whereas the response from the sublayout for debug query " + debugQuery + " is " + correct_subLayout);
                        LayoutQuery debugQuery2 = broadened.Query.DebugClone();
                        debugQuery2.ProposedSolution_ForDebugging = correct_subLayout;
                        this.GetBestLayout(debugQuery2);
                    }
                }
                return(this.inferredLayout(query, broadened.Response));
            }
            LayoutQuery_And_Response shrunken = this.FindExample(query);

            if (query.Debug)
            {
                if (shrunken != null)
                {
                    LayoutQuery debugQuery = shrunken.Query.Clone();
                    debugQuery.Debug = true;
                    SpecificLayout correct_subLayout = this.Query_SubLayout(debugQuery);
                    if (shrunken.Query.PreferredLayout(shrunken.Response, correct_subLayout) != shrunken.Response)
                    {
                        ErrorReporter.ReportParadox("Error; incorrect result for shrunken query");
                    }
                }
            }

            if (shrunken != null)
            {
                // If the existing example is already at the extreme, then use it
                if (query.MaximizesScore())
                {
                    if (shrunken.Response.Width >= query.MaxWidth && shrunken.Response.Height >= query.MaxHeight)
                    {
                        return(this.inferredLayout(query, shrunken.Response));
                    }
                }
                if (query.MinimizesWidth())
                {
                    if (shrunken.Response.Width <= 0)
                    {
                        return(this.inferredLayout(query, shrunken.Response));
                    }
                }
                if (query.MinimizesHeight())
                {
                    if (shrunken.Response.Height <= 0)
                    {
                        return(this.inferredLayout(query, shrunken.Response));
                    }
                }
            }
            // if we couldn't immediately return a result using the cache, we can still put a bound on the results we might get
            // They have to be at least as good as the sample we found
            if (shrunken != null)
            {
                // First, see if we can improve past what we currently have
                LayoutQuery strictlyImprovedQuery = query.OptimizedPastExample(shrunken.Response);
                bool        allowCache            = !strictlyImprovedQuery.Accepts(shrunken.Response);

                // Ask the sublayout for this result (or use the cache if we've already asked)
                if (allowCache)
                {
                    result = this.GetBestLayout_Quickly(strictlyImprovedQuery);
                }
                else
                {
                    result = this.Query_SubLayout(strictlyImprovedQuery);
                }
                if (result == null)
                {
                    result = shrunken.Response;
                }
                return(this.inferredLayout(query, result));
            }
            else
            {
                result = this.Query_SubLayout(query);
            }

            if (result == null)
            {
                if (shrunken != null && query.Accepts(shrunken.Response))
                {
                    ErrorReporter.ReportParadox("Error: cache contains an acceptable value for the current query, but the layout claims there are none");
                    result = shrunken.Response;
                }
            }

            // record that this is the exact answer to this query
            LayoutQuery_And_Response queryAndResponse = new LayoutQuery_And_Response(query, result);

            this.orderedResponses.Add(queryAndResponse);


            //this.debugCheck(queryAndResponse);

            if (result != null)
            {
                result = result.Clone();
            }
            return(result);
        }
示例#5
0
        // Attempts to find a strictly larger query so we can get an upper bound on the required size (and if possible, we want a query whose response is accepted by the original)
        private LayoutQuery_And_Response Find_LargerQuery(LayoutQuery query)
        {
            LayoutQuery_And_Response bestResult = null;

            // check each previous query and response to see if we can use one of them
            // TODO do something faster and more complicated that doesn't entail checking every query, using something like an R-tree
            foreach (LayoutQuery_And_Response queryAndResponse in this.orderedResponses)
            {
                LayoutQuery    otherQuery  = queryAndResponse.Query;
                SpecificLayout otherResult = queryAndResponse.Response;

                // check whether the answer to the previous query must also be the answer to the current query
                bool otherEncompassesInputs  = true;
                bool otherEncompassesOutputs = true;
                bool inputAccepted           = true;
                bool thisEncompassesInputs   = true;
                // If we're looking for the min width or min height, then tightening the score means we can't necessarily use the other result as the best result
                if (query.MaximizesScore())
                {
                    if (otherQuery.MaxWidth < query.MaxWidth)
                    {
                        otherEncompassesInputs = false;
                    }
                    if (otherQuery.MaxWidth > query.MaxWidth)
                    {
                        thisEncompassesInputs = false;
                    }

                    if (otherQuery.MaxHeight < query.MaxHeight)
                    {
                        otherEncompassesInputs = false;
                    }
                    if (otherQuery.MaxHeight > query.MaxHeight)
                    {
                        thisEncompassesInputs = false;
                    }

                    if (otherQuery.MinScore.CompareTo(query.MinScore) > 0)
                    {
                        otherEncompassesOutputs = false;
                    }

                    if (otherResult == null || otherResult.Width > query.MaxWidth)
                    {
                        inputAccepted = false;
                    }
                    if (otherResult == null || otherResult.Height > query.MaxHeight)
                    {
                        inputAccepted = false;
                    }
                }
                if (query.MinimizesWidth())
                {
                    if (otherQuery.MaxWidth < query.MaxWidth)
                    {
                        otherEncompassesOutputs = false;
                    }

                    if (otherQuery.MaxHeight < query.MaxHeight)
                    {
                        otherEncompassesInputs = false;
                    }
                    if (otherQuery.MaxHeight > query.MaxHeight)
                    {
                        thisEncompassesInputs = false;
                    }

                    if (otherQuery.MinScore.CompareTo(query.MinScore) > 0)
                    {
                        otherEncompassesInputs = false;
                    }
                    if (otherQuery.MinScore.CompareTo(query.MinScore) < 0)
                    {
                        thisEncompassesInputs = false;
                    }

                    if (otherResult == null || otherResult.Score.CompareTo(query.MinScore) < 0)
                    {
                        inputAccepted = false;
                    }
                    if (otherResult == null || otherResult.Height > query.MaxHeight)
                    {
                        inputAccepted = false;
                    }
                }
                if (query.MinimizesHeight())
                {
                    if (otherQuery.MaxWidth < query.MaxWidth)
                    {
                        otherEncompassesInputs = false;
                    }
                    if (otherQuery.MaxWidth > query.MaxWidth)
                    {
                        thisEncompassesInputs = false;
                    }

                    if (otherQuery.MaxHeight < query.MaxHeight)
                    {
                        otherEncompassesOutputs = false;
                    }

                    if (otherQuery.MinScore.CompareTo(query.MinScore) > 0)
                    {
                        otherEncompassesInputs = false;
                    }
                    if (otherQuery.MinScore.CompareTo(query.MinScore) < 0)
                    {
                        thisEncompassesInputs = false;
                    }

                    if (otherResult == null || otherResult.Width > query.MaxWidth)
                    {
                        inputAccepted = false;
                    }
                    if (otherResult == null || otherResult.Score.CompareTo(query.MinScore) < 0)
                    {
                        inputAccepted = false;
                    }
                }
                if (otherEncompassesInputs)
                {
                    if (query.SameType(otherQuery) && query.Accepts(otherResult))
                    {
                        // The previous query had looser inputs but its result was still in our range, so we know its result will be right for us too
                        return(queryAndResponse);
                    }
                    if (query.SameType(otherQuery) && inputAccepted && otherEncompassesOutputs)
                    {
                        if (!query.Accepts(otherResult))
                        {
                            // The previous query had looser inputs, and demonstrated that the best output is worse than our threshold
                            // So, our current query has no solution
                            return(new LayoutQuery_And_Response(otherQuery, null));
                        }
                    }
                    if (otherEncompassesOutputs && otherResult == null)
                    {
                        // The previous query had looser inputs and looser outputs but no solution, so the current query will also have no solution
                        return(queryAndResponse);
                    }
                    if (query.SameType(otherQuery) && thisEncompassesInputs)
                    {
                        if (otherResult != null)
                        {
                            // If we already asked the same question then we already know what the best answer is
                            // We just have to double-check whether the best answer is good enough
                            if (query.Accepts(otherResult))
                            {
                                return(queryAndResponse);
                            }
                            else
                            {
                                return(new LayoutQuery_And_Response(otherQuery, null));
                            }
                        }
                    }
                }
            }

            if (query.Debug)
            {
                if (bestResult != null && bestResult.Response != null && !bestResult.Query.Accepts(bestResult.Response))
                {
                    ErrorReporter.ReportParadox("Query does not accept its recorded answer");
                }
            }
            // return the most useful query+response that we found
            return(bestResult);
        }