} // relax_spelling(...)

        private static HashSet <String> Relax(HashSet <String> names)
        {
            var result = new HashSet <String>(names);

            foreach (var name in names)
            {
                var stage1 = NameDatabase <T, TKey> .RelaxToLowercase(name);

                var stage2 = NameDatabase <T, TKey> .RelaxSpelling(stage1);

                result.Add(stage1);
                result.Add(stage2);
            } // for (...)
            return(result);
        }
        public T Find(String query, Func <T, Boolean> filter)
        {
            var lowercase = NameDatabase <T, TKey> .RelaxToLowercase(query);

            var misspelled = NameDatabase <T, TKey> .RelaxSpelling(lowercase);

            bool isValid = false;

            // Stage 0: prefix tree search.
            this.suggestions.Clear();
            var searchA = this.nameTree.Search(query);

            if (!Object.ReferenceEquals(searchA, null))
            {
                var unit = this.AsSingle(searchA, filter, ref isValid);
                if (isValid)
                {
                    return(unit);
                }
                else
                {
                    foreach (var synonymKey in searchA.SynonymKeys)
                    {
                        var maybe = this.database[synonymKey];
                        var names = this.BuildNames(maybe);
                        var name  = names.Count == 0 ? "??" : names.First();
                        if (filter == null || filter(maybe))
                        {
                            this.suggestions.Add(name);
                        }
                    }
                }
            } // if (...)

            // Stage 1: lowercase lookup.
            var searchB = this.nameTree.Search(lowercase);

            if (!Object.ReferenceEquals(searchB, null))
            {
                var unit = this.AsSingle(searchB, filter, ref isValid);
                if (isValid)
                {
                    this.suggestions.Clear();
                    return(unit);
                }
                App.Suggestions.Push($"Multiple units match the specified query: {lowercase}.");
                return(default(T));
            } // if (...)

            // Stage 2: misspelled lookup.
            var searchC = this.nameTree.Search(misspelled);

            if (!Object.ReferenceEquals(searchC, null))
            {
                var unit = this.AsSingle(searchC, filter, ref isValid);
                if (isValid)
                {
                    this.suggestions.Clear();
                    return(unit);
                }
                App.Suggestions.Push($"Multiple units match the specified query: {misspelled}.");
                return(default(T));
            } // if (...)

            return(default(T));
        } // try_find(...)