QuizGenerator 0.7.0__py3-none-any.whl → 0.8.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- QuizGenerator/contentast.py +6 -6
- QuizGenerator/generate.py +2 -1
- QuizGenerator/mixins.py +14 -100
- QuizGenerator/premade_questions/basic.py +24 -29
- QuizGenerator/premade_questions/cst334/languages.py +100 -99
- QuizGenerator/premade_questions/cst334/math_questions.py +112 -122
- QuizGenerator/premade_questions/cst334/memory_questions.py +621 -621
- QuizGenerator/premade_questions/cst334/persistence_questions.py +137 -163
- QuizGenerator/premade_questions/cst334/process.py +312 -322
- QuizGenerator/premade_questions/cst463/gradient_descent/gradient_calculation.py +34 -35
- QuizGenerator/premade_questions/cst463/gradient_descent/gradient_descent_questions.py +41 -36
- QuizGenerator/premade_questions/cst463/gradient_descent/loss_calculations.py +48 -41
- QuizGenerator/premade_questions/cst463/math_and_data/matrix_questions.py +285 -520
- QuizGenerator/premade_questions/cst463/math_and_data/vector_questions.py +149 -126
- QuizGenerator/premade_questions/cst463/models/attention.py +44 -50
- QuizGenerator/premade_questions/cst463/models/cnns.py +43 -47
- QuizGenerator/premade_questions/cst463/models/matrices.py +61 -11
- QuizGenerator/premade_questions/cst463/models/rnns.py +48 -50
- QuizGenerator/premade_questions/cst463/models/text.py +65 -67
- QuizGenerator/premade_questions/cst463/models/weight_counting.py +47 -46
- QuizGenerator/premade_questions/cst463/neural-network-basics/neural_network_questions.py +100 -156
- QuizGenerator/premade_questions/cst463/tensorflow-intro/tensorflow_questions.py +93 -141
- QuizGenerator/question.py +273 -202
- QuizGenerator/quiz.py +8 -5
- QuizGenerator/regenerate.py +128 -19
- {quizgenerator-0.7.0.dist-info → quizgenerator-0.8.0.dist-info}/METADATA +30 -2
- {quizgenerator-0.7.0.dist-info → quizgenerator-0.8.0.dist-info}/RECORD +30 -30
- {quizgenerator-0.7.0.dist-info → quizgenerator-0.8.0.dist-info}/WHEEL +0 -0
- {quizgenerator-0.7.0.dist-info → quizgenerator-0.8.0.dist-info}/entry_points.txt +0 -0
- {quizgenerator-0.7.0.dist-info → quizgenerator-0.8.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import abc
|
|
3
3
|
import logging
|
|
4
4
|
import math
|
|
5
|
+
import random
|
|
5
6
|
|
|
6
7
|
from QuizGenerator.question import Question, QuestionRegistry
|
|
7
8
|
import QuizGenerator.contentast as ca
|
|
@@ -22,45 +23,51 @@ class BitsAndBytes(MathQuestion):
|
|
|
22
23
|
MIN_BITS = MathRanges.DEFAULT_MIN_MATH_BITS
|
|
23
24
|
MAX_BITS = MathRanges.DEFAULT_MAX_MATH_BITS
|
|
24
25
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
def _get_body(self, **kwargs):
|
|
26
|
+
@classmethod
|
|
27
|
+
def _build_context(cls, *, rng_seed=None, **kwargs):
|
|
28
|
+
rng = random.Random(rng_seed)
|
|
29
|
+
from_binary = (0 == rng.randint(0, 1))
|
|
30
|
+
num_bits = rng.randint(cls.MIN_BITS, cls.MAX_BITS)
|
|
31
|
+
num_bytes = int(math.pow(2, num_bits))
|
|
32
|
+
return {
|
|
33
|
+
"from_binary": from_binary,
|
|
34
|
+
"num_bits": num_bits,
|
|
35
|
+
"num_bytes": num_bytes,
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
@classmethod
|
|
39
|
+
def _build_body(cls, context):
|
|
41
40
|
"""Build question body and collect answers."""
|
|
42
|
-
|
|
41
|
+
if context["from_binary"]:
|
|
42
|
+
answer = ca.AnswerTypes.Int(
|
|
43
|
+
context["num_bytes"],
|
|
44
|
+
label="Address space size",
|
|
45
|
+
unit="Bytes"
|
|
46
|
+
)
|
|
47
|
+
else:
|
|
48
|
+
answer = ca.AnswerTypes.Int(
|
|
49
|
+
context["num_bits"],
|
|
50
|
+
label="Number of bits in address",
|
|
51
|
+
unit="bits"
|
|
52
|
+
)
|
|
43
53
|
|
|
44
54
|
body = ca.Section()
|
|
45
55
|
body.add_element(
|
|
46
56
|
ca.Paragraph([
|
|
47
57
|
f"Given that we have "
|
|
48
|
-
f"{
|
|
49
|
-
f"
|
|
50
|
-
f"
|
|
58
|
+
f"{context['num_bits'] if context['from_binary'] else context['num_bytes']} "
|
|
59
|
+
f"{'bits' if context['from_binary'] else 'bytes'}, "
|
|
60
|
+
f"how many {'bits' if not context['from_binary'] else 'bytes'} "
|
|
61
|
+
f"{'do we need to address our memory' if not context['from_binary'] else 'of memory can be addressed'}?"
|
|
51
62
|
])
|
|
52
63
|
)
|
|
53
64
|
|
|
54
|
-
body.add_element(ca.AnswerBlock(
|
|
65
|
+
body.add_element(ca.AnswerBlock(answer))
|
|
55
66
|
|
|
56
|
-
return body, answers
|
|
57
|
-
|
|
58
|
-
def get_body(self, **kwargs) -> ca.Section:
|
|
59
|
-
"""Build question body (backward compatible interface)."""
|
|
60
|
-
body, _ = self._get_body(**kwargs)
|
|
61
67
|
return body
|
|
62
68
|
|
|
63
|
-
|
|
69
|
+
@classmethod
|
|
70
|
+
def _build_explanation(cls, context):
|
|
64
71
|
explanation = ca.Section()
|
|
65
72
|
|
|
66
73
|
explanation.add_element(
|
|
@@ -77,20 +84,19 @@ class BitsAndBytes(MathQuestion):
|
|
|
77
84
|
ca.Paragraph(["Therefore, we calculate:"])
|
|
78
85
|
)
|
|
79
86
|
|
|
80
|
-
if
|
|
87
|
+
if context["from_binary"]:
|
|
81
88
|
explanation.add_element(
|
|
82
|
-
ca.Equation(
|
|
89
|
+
ca.Equation(
|
|
90
|
+
f"2 ^ {{{context['num_bits']}bits}} = \\textbf{{{context['num_bytes']}}}\\text{{bytes}}"
|
|
91
|
+
)
|
|
83
92
|
)
|
|
84
93
|
else:
|
|
85
94
|
explanation.add_element(
|
|
86
|
-
ca.Equation(
|
|
95
|
+
ca.Equation(
|
|
96
|
+
f"log_{{2}}({context['num_bytes']} \\text{{bytes}}) = \\textbf{{{context['num_bits']}}}\\text{{bits}}"
|
|
97
|
+
)
|
|
87
98
|
)
|
|
88
99
|
|
|
89
|
-
return explanation, []
|
|
90
|
-
|
|
91
|
-
def get_explanation(self, **kwargs) -> ca.Section:
|
|
92
|
-
"""Build question explanation (backward compatible interface)."""
|
|
93
|
-
explanation, _ = self._get_explanation(**kwargs)
|
|
94
100
|
return explanation
|
|
95
101
|
|
|
96
102
|
|
|
@@ -100,47 +106,46 @@ class HexAndBinary(MathQuestion):
|
|
|
100
106
|
MIN_HEXITS = 1
|
|
101
107
|
MAX_HEXITS = 8
|
|
102
108
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
def
|
|
109
|
+
@classmethod
|
|
110
|
+
def _build_context(cls, *, rng_seed=None, **kwargs):
|
|
111
|
+
rng = random.Random(rng_seed)
|
|
112
|
+
from_binary = rng.choice([True, False])
|
|
113
|
+
number_of_hexits = rng.randint(1, 8)
|
|
114
|
+
value = rng.randint(1, 16**number_of_hexits)
|
|
115
|
+
hex_val = f"0x{value:0{number_of_hexits}X}"
|
|
116
|
+
binary_val = f"0b{value:0{4*number_of_hexits}b}"
|
|
117
|
+
return {
|
|
118
|
+
"from_binary": from_binary,
|
|
119
|
+
"number_of_hexits": number_of_hexits,
|
|
120
|
+
"value": value,
|
|
121
|
+
"hex_val": hex_val,
|
|
122
|
+
"binary_val": binary_val,
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
@classmethod
|
|
126
|
+
def _build_body(cls, context):
|
|
121
127
|
"""Build question body and collect answers."""
|
|
122
|
-
|
|
128
|
+
if context["from_binary"]:
|
|
129
|
+
answer = ca.AnswerTypes.String(context["hex_val"], label="Value in hex")
|
|
130
|
+
else:
|
|
131
|
+
answer = ca.AnswerTypes.String(context["binary_val"], label="Value in binary")
|
|
123
132
|
|
|
124
133
|
body = ca.Section()
|
|
125
134
|
|
|
126
135
|
body.add_element(
|
|
127
136
|
ca.Paragraph([
|
|
128
|
-
f"Given the number {
|
|
129
|
-
f"please convert it to {'hex' if
|
|
137
|
+
f"Given the number {context['hex_val'] if not context['from_binary'] else context['binary_val']} "
|
|
138
|
+
f"please convert it to {'hex' if context['from_binary'] else 'binary'}.",
|
|
130
139
|
"Please include base indicator all padding zeros as appropriate (e.g. 0x01 should be 0b00000001)",
|
|
131
140
|
])
|
|
132
141
|
)
|
|
133
142
|
|
|
134
|
-
body.add_element(ca.AnswerBlock(
|
|
135
|
-
|
|
136
|
-
return body, answers
|
|
143
|
+
body.add_element(ca.AnswerBlock(answer))
|
|
137
144
|
|
|
138
|
-
def get_body(self, **kwargs) -> ca.Section:
|
|
139
|
-
"""Build question body (backward compatible interface)."""
|
|
140
|
-
body, _ = self._get_body(**kwargs)
|
|
141
145
|
return body
|
|
142
146
|
|
|
143
|
-
|
|
147
|
+
@classmethod
|
|
148
|
+
def _build_explanation(cls, context):
|
|
144
149
|
explanation = ca.Section()
|
|
145
150
|
|
|
146
151
|
paragraph = ca.Paragraph([
|
|
@@ -148,7 +153,7 @@ class HexAndBinary(MathQuestion):
|
|
|
148
153
|
"Specifically, each hexit (hexadecimal digit) is equivalent to 4 bits. "
|
|
149
154
|
])
|
|
150
155
|
|
|
151
|
-
if
|
|
156
|
+
if context["from_binary"]:
|
|
152
157
|
paragraph.add_line(
|
|
153
158
|
"Therefore, we need to consider each group of 4 bits together and convert them to the appropriate hexit."
|
|
154
159
|
)
|
|
@@ -160,8 +165,8 @@ class HexAndBinary(MathQuestion):
|
|
|
160
165
|
explanation.add_element(paragraph)
|
|
161
166
|
|
|
162
167
|
# Generate translation table
|
|
163
|
-
binary_str = f"{
|
|
164
|
-
hex_str = f"{
|
|
168
|
+
binary_str = f"{context['value']:0{4*context['number_of_hexits']}b}"
|
|
169
|
+
hex_str = f"{context['value']:0{context['number_of_hexits']}X}"
|
|
165
170
|
|
|
166
171
|
explanation.add_element(
|
|
167
172
|
ca.Table(
|
|
@@ -175,7 +180,7 @@ class HexAndBinary(MathQuestion):
|
|
|
175
180
|
)
|
|
176
181
|
)
|
|
177
182
|
|
|
178
|
-
if
|
|
183
|
+
if context["from_binary"]:
|
|
179
184
|
explanation.add_element(
|
|
180
185
|
ca.Paragraph([
|
|
181
186
|
f"Which gives us our hex value of: 0x{hex_str}"
|
|
@@ -188,11 +193,6 @@ class HexAndBinary(MathQuestion):
|
|
|
188
193
|
])
|
|
189
194
|
)
|
|
190
195
|
|
|
191
|
-
return explanation, []
|
|
192
|
-
|
|
193
|
-
def get_explanation(self, **kwargs) -> ca.Section:
|
|
194
|
-
"""Build question explanation (backward compatible interface)."""
|
|
195
|
-
explanation, _ = self._get_explanation(**kwargs)
|
|
196
196
|
return explanation
|
|
197
197
|
|
|
198
198
|
|
|
@@ -201,40 +201,38 @@ class AverageMemoryAccessTime(MathQuestion):
|
|
|
201
201
|
|
|
202
202
|
CHANCE_OF_99TH_PERCENTILE = 0.75
|
|
203
203
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
if self.rng.random() < self.CHANCE_OF_99TH_PERCENTILE:
|
|
214
|
-
# Then let's make it very close to 99%
|
|
215
|
-
self.hit_rate = (99 + self.rng.random()) / 100
|
|
204
|
+
@classmethod
|
|
205
|
+
def _build_context(cls, *, rng_seed=None, **kwargs):
|
|
206
|
+
rng = random.Random(rng_seed)
|
|
207
|
+
orders_of_magnitude_different = rng.randint(1, 4)
|
|
208
|
+
hit_latency = rng.randint(1, 9)
|
|
209
|
+
miss_latency = int(rng.randint(1, 9) * math.pow(10, orders_of_magnitude_different))
|
|
210
|
+
|
|
211
|
+
if rng.random() < cls.CHANCE_OF_99TH_PERCENTILE:
|
|
212
|
+
hit_rate = (99 + rng.random()) / 100
|
|
216
213
|
else:
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
"
|
|
214
|
+
hit_rate = rng.random()
|
|
215
|
+
|
|
216
|
+
hit_rate = round(hit_rate, 4)
|
|
217
|
+
amat = hit_rate * hit_latency + (1 - hit_rate) * miss_latency
|
|
218
|
+
show_miss_rate = rng.random() > 0.5
|
|
219
|
+
|
|
220
|
+
return {
|
|
221
|
+
"hit_latency": hit_latency,
|
|
222
|
+
"miss_latency": miss_latency,
|
|
223
|
+
"hit_rate": hit_rate,
|
|
224
|
+
"amat": amat,
|
|
225
|
+
"show_miss_rate": show_miss_rate,
|
|
227
226
|
}
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
# At this point, everything in the question should be set.
|
|
233
|
-
pass
|
|
234
|
-
|
|
235
|
-
def _get_body(self, **kwargs):
|
|
227
|
+
|
|
228
|
+
@classmethod
|
|
229
|
+
def _build_body(cls, context):
|
|
236
230
|
"""Build question body and collect answers."""
|
|
237
|
-
|
|
231
|
+
answer = ca.AnswerTypes.Float(
|
|
232
|
+
context["amat"],
|
|
233
|
+
label="Average Memory Access Time",
|
|
234
|
+
unit="cycles"
|
|
235
|
+
)
|
|
238
236
|
|
|
239
237
|
body = ca.Section()
|
|
240
238
|
|
|
@@ -249,15 +247,15 @@ class AverageMemoryAccessTime(MathQuestion):
|
|
|
249
247
|
])
|
|
250
248
|
)
|
|
251
249
|
table_data = [
|
|
252
|
-
["Hit Latency", f"{
|
|
253
|
-
["Miss Latency", f"{
|
|
250
|
+
["Hit Latency", f"{context['hit_latency']} cycles"],
|
|
251
|
+
["Miss Latency", f"{context['miss_latency']} cycles"]
|
|
254
252
|
]
|
|
255
253
|
|
|
256
254
|
# Add in either miss rate or hit rate -- we only need one of them
|
|
257
|
-
if
|
|
258
|
-
table_data.append(["Miss Rate", f"{100 * (1 -
|
|
255
|
+
if context["show_miss_rate"]:
|
|
256
|
+
table_data.append(["Miss Rate", f"{100 * (1 - context['hit_rate']): 0.2f}%"])
|
|
259
257
|
else:
|
|
260
|
-
table_data.append(["Hit Rate", f"{100 *
|
|
258
|
+
table_data.append(["Hit Rate", f"{100 * context['hit_rate']: 0.2f}%"])
|
|
261
259
|
|
|
262
260
|
body.add_element(
|
|
263
261
|
ca.Table(
|
|
@@ -267,16 +265,12 @@ class AverageMemoryAccessTime(MathQuestion):
|
|
|
267
265
|
|
|
268
266
|
body.add_element(ca.LineBreak())
|
|
269
267
|
|
|
270
|
-
body.add_element(ca.AnswerBlock(
|
|
268
|
+
body.add_element(ca.AnswerBlock(answer))
|
|
271
269
|
|
|
272
|
-
return body, answers
|
|
273
|
-
|
|
274
|
-
def get_body(self, **kwargs) -> ca.Section:
|
|
275
|
-
"""Build question body (backward compatible interface)."""
|
|
276
|
-
body, _ = self._get_body(**kwargs)
|
|
277
270
|
return body
|
|
278
271
|
|
|
279
|
-
|
|
272
|
+
@classmethod
|
|
273
|
+
def _build_explanation(cls, context):
|
|
280
274
|
explanation = ca.Section()
|
|
281
275
|
|
|
282
276
|
# Add in General explanation
|
|
@@ -294,15 +288,11 @@ class AverageMemoryAccessTime(MathQuestion):
|
|
|
294
288
|
lhs="AMAT",
|
|
295
289
|
rhs=[
|
|
296
290
|
r"(hit\_rate)*(hit\_cost) + (1 - hit\_rate)*(miss\_cost)",
|
|
297
|
-
f"({
|
|
291
|
+
f"({context['hit_rate']: 0.{ca.Answer.DEFAULT_ROUNDING_DIGITS}f})*({context['hit_latency']}) + "
|
|
292
|
+
f"({1 - context['hit_rate']: 0.{ca.Answer.DEFAULT_ROUNDING_DIGITS}f})*({context['miss_latency']}) = "
|
|
293
|
+
f"{context['amat']: 0.{ca.Answer.DEFAULT_ROUNDING_DIGITS}f}\\text{{cycles}}"
|
|
298
294
|
]
|
|
299
295
|
)
|
|
300
296
|
)
|
|
301
297
|
|
|
302
|
-
return explanation, []
|
|
303
|
-
|
|
304
|
-
def get_explanation(self, **kwargs) -> ca.Section:
|
|
305
|
-
"""Build question explanation (backward compatible interface)."""
|
|
306
|
-
explanation, _ = self._get_explanation(**kwargs)
|
|
307
298
|
return explanation
|
|
308
|
-
|