• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

LearnLib / learnlib / 7308474359

23 Dec 2023 01:13PM UTC coverage: 93.347% (-0.008%) from 93.355%
7308474359

push

github

mtf90
drop Java 8 configs

11757 of 12595 relevant lines covered (93.35%)

1.69 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

80.0
/api/src/main/java/de/learnlib/query/Query.java
1
/* Copyright (C) 2013-2023 TU Dortmund
2
 * This file is part of LearnLib, http://www.learnlib.de/.
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
package de.learnlib.query;
17

18
import java.util.Objects;
19

20
import de.learnlib.algorithm.LearningAlgorithm;
21
import de.learnlib.oracle.MembershipOracle;
22
import net.automatalib.automaton.fsa.DFA;
23
import net.automatalib.automaton.transducer.MealyMachine;
24
import net.automatalib.word.Word;
25
import org.checkerframework.checker.nullness.qual.Nullable;
26

27
/**
28
 * A query is the basic form of interaction between a {@link LearningAlgorithm learner} and a {@link MembershipOracle
29
 * (membership) oracle}, or teacher.
30
 * <p>
31
 * In LearnLib, queries are performed in a callback-like fashion: an oracle does not <i>return</i> the responses to the
32
 * queries, but rather invokes the {@link #answer(Object)} method on the query objects it was provided with. This allows
33
 * for implementing queries which directly react to an answered query (e.g., by modifying some internal data structure),
34
 * without the need for buffering answers. It also allows for a more efficient parallel processing of queries, as there
35
 * is no need for maintaining a common (synchronized) result data structure such as a map. However, this means that a
36
 * learner cannot rely on the {@link #answer(Object)} method of a query being called from the same thread which invoked
37
 * {@link MembershipOracle#processQueries(java.util.Collection)}. If this causes concurrency issues, a safe choice is to
38
 * use queries of class {@link DefaultQuery}, which simply store the response and make it accessible via {@link
39
 * DefaultQuery#getOutput()} for processing after the {@link MembershipOracle#processQueries(java.util.Collection)} call
40
 * returns, guaranteeing thread-safety.
41
 * <p>
42
 * Conceptually, a query is divided into a {@link #getPrefix() prefix} and a {@link #getSuffix()} suffix. The prefix
43
 * part of a query identifies a state in the (unknown) target system, whereas the suffix is the "experiment" which is
44
 * conducted on the system starting from the state to which it was transferred by the prefix. While the prefix
45
 * influences the response of the target system to a query, the answer is the <i>directly observable</i> reaction to
46
 * executing the suffix.
47
 * <p>
48
 * <b>Example 1:</b> when learning {@link MealyMachine Mealy machines}, the prefix transfers the target system to a
49
 * certain state. The outputs produced by the system while executing the prefix are <i>not</i> part of the answer, as
50
 * the role of the prefix is limited to reaching a certain state. The reaction of the target system consists of the
51
 * output word produced while executing the suffix. Therefore, in the setting of Mealy machine learning, a valid oracle
52
 * will call the {@link #answer(Object)} method with a word of the same length as the suffix.
53
 * <p>
54
 * <b>Example 2:</b> when learning {@link DFA}s, the reaction of the target system is fully determined by the state
55
 * reached by an input word. Since both prefix and suffix have the same effect on producing this output (by transferring
56
 * the system to a certain state), the response will always be a single {@link Boolean}, and, furthermore, for every
57
 * input word {@code w}, the response to a query will always be the same regardless of the subdivision of {@code w = uv}
58
 * into prefix {@code u} and suffix {@code v} (including the corner cases <code>u = &epsilon;</code> and <code>v =
59
 * &epsilon;</code>).
60
 *
61
 * @param <I>
62
 *         input symbol type
63
 * @param <D>
64
 *         output domain type
65
 */
66
public abstract class Query<I, D> {
1✔
67

68
    private int hashCode;
69

70
    /**
71
     * Answers the query. This method should be called by a {@link MembershipOracle}, and only once per query to
72
     * process. Calling this method more than once may result in undefined behavior, possibly (but not necessarily)
73
     * throwing an exception.
74
     *
75
     * @param output
76
     *         the output, i.e., the directly observable response to the query's suffix (cf. {@link Query main
77
     *         documentation})
78
     */
79
    public abstract void answer(D output);
80

81
    /**
82
     * Retrieves the input word of this query. The input word corresponding to a query is the concatenation of its
83
     * prefix and suffix.
84
     *
85
     * @return the input word of this query
86
     */
87
    public Word<I> getInput() {
88
        return getPrefix().concat(getSuffix());
1✔
89
    }
90

91
    /**
92
     * Returns the prefix part of this query. The prefix of a query is responsible for transferring the system into a
93
     * certain state, but (apart from that) does not directly influence the output.
94
     *
95
     * @return the prefix of this query
96
     */
97
    public abstract Word<I> getPrefix();
98

99
    /**
100
     * Returns the suffix part of this query. The suffix of a query is the experiment performed on the system when in
101
     * the state it was transferred into by the prefix, and thus directly influences the output.
102
     *
103
     * @return the suffix of this query
104
     */
105
    public abstract Word<I> getSuffix();
106

107
    @Override
108
    public final int hashCode() {
109
        if (hashCode != 0) {
1✔
110
            return hashCode;
1✔
111
        }
112

113
        hashCode = 1;
1✔
114
        hashCode = 31 * hashCode + Objects.hashCode(getPrefix());
1✔
115
        hashCode = 31 * hashCode + Objects.hashCode(getSuffix());
1✔
116
        return hashCode;
1✔
117
    }
118

119
    @Override
120
    public final boolean equals(@Nullable Object o) {
121
        if (this == o) {
1✔
122
            return true;
×
123
        }
124
        if (!(o instanceof Query)) {
1✔
125
            return false;
×
126
        }
127

128
        final Query<?, ?> that = (Query<?, ?>) o;
1✔
129
        return Objects.equals(getPrefix(), that.getPrefix()) && Objects.equals(getSuffix(), that.getSuffix());
1✔
130
    }
131

132
    /**
133
     * Returns the string representation of this query.
134
     *
135
     * @return A string of the form {@code "Query[<prefix>|<suffix>]"} for queries not containing an answer or {@code
136
     * "Query[<prefix>|<suffix> / <answer>]"} if an answer may be specified.
137
     */
138
    @Override
139
    public String toString() {
140
        return "Query[" + getPrefix() + '|' + getSuffix() + ']';
×
141
    }
142

143
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc