mirror of
https://github.com/3b1b/manim.git
synced 2025-08-26 08:14:21 +08:00
Posterior update animations in eop/bayes
This commit is contained in:
615
eop/bayes.py
615
eop/bayes.py
@ -43,7 +43,7 @@ class BayesOpeningQuote(OpeningQuote):
|
||||
class IntroducePokerHand(PiCreatureScene, SampleSpaceScene):
|
||||
CONFIG = {
|
||||
"community_cards_center" : 1.5*DOWN,
|
||||
"community_card_values" : ["AS", "QH", "10H", "2C", "5H"],
|
||||
"community_card_values" : ["10S", "QH", "AH", "2C", "5H"],
|
||||
"your_hand_values" : ["JS", "KC"],
|
||||
}
|
||||
def construct(self):
|
||||
@ -118,6 +118,7 @@ class IntroducePokerHand(PiCreatureScene, SampleSpaceScene):
|
||||
straight_cards.submobjects.sort(card_cmp)
|
||||
straight_cards.arrange_submobjects(RIGHT, buff = SMALL_BUFF)
|
||||
straight_cards.next_to(community_cards, UP, aligned_edge = LEFT)
|
||||
you.hand.target.shift(MED_SMALL_BUFF*UP)
|
||||
|
||||
self.play(LaggedStart(
|
||||
MoveToTarget,
|
||||
@ -125,7 +126,6 @@ class IntroducePokerHand(PiCreatureScene, SampleSpaceScene):
|
||||
run_time = 1.5
|
||||
))
|
||||
self.play(MoveToTarget(you.hand))
|
||||
self.play(you.change, "hooray", straight_cards)
|
||||
self.play(LaggedStart(
|
||||
ApplyMethod,
|
||||
straight_cards,
|
||||
@ -135,12 +135,14 @@ class IntroducePokerHand(PiCreatureScene, SampleSpaceScene):
|
||||
lag_ratio = 0.5,
|
||||
remover = True,
|
||||
))
|
||||
self.play(you.change, "hooray", straight_cards)
|
||||
self.dither(2)
|
||||
self.play(
|
||||
selected_community_cards.restore,
|
||||
you.hand.restore,
|
||||
you.change_mode, "happy"
|
||||
)
|
||||
self.dither()
|
||||
|
||||
def show_flush_potential(self):
|
||||
you, her = self.you, self.her
|
||||
@ -156,6 +158,10 @@ class IntroducePokerHand(PiCreatureScene, SampleSpaceScene):
|
||||
her.hand.target.next_to(heart_cards, UP)
|
||||
her.hand.target.to_edge(UP)
|
||||
|
||||
her.glasses.save_state()
|
||||
her.glasses.move_to(her.hand.target)
|
||||
her.glasses.set_fill(opacity = 0)
|
||||
|
||||
heart_qs = VGroup()
|
||||
hearts = VGroup()
|
||||
q_marks = VGroup()
|
||||
@ -177,7 +183,7 @@ class IntroducePokerHand(PiCreatureScene, SampleSpaceScene):
|
||||
self.play(LaggedStart(DrawBorderThenFill, heart_qs))
|
||||
self.play(
|
||||
her.change, "happy",
|
||||
DrawBorderThenFill(her.glasses)
|
||||
her.glasses.restore,
|
||||
)
|
||||
self.pi_creatures.remove(her)
|
||||
new_suit_pairs = [
|
||||
@ -272,19 +278,20 @@ class IntroducePokerHand(PiCreatureScene, SampleSpaceScene):
|
||||
sample_space.divide_horizontally(
|
||||
p, colors = [SuitSymbol.CONFIG["red"], BLUE_E]
|
||||
)
|
||||
top_label, bottom_label = sample_space.get_side_labels([
|
||||
braces, labels = sample_space.get_side_braces_and_labels([
|
||||
percentage.get_tex_string(), "95.5\\%"
|
||||
])
|
||||
top_label, bottom_label = labels
|
||||
|
||||
self.play(
|
||||
FadeIn(sample_space),
|
||||
ReplacementTransform(percentage, top_label[1])
|
||||
ReplacementTransform(percentage, top_label)
|
||||
)
|
||||
self.play(*map(GrowFromCenter, [
|
||||
label[0] for label in top_label, bottom_label
|
||||
brace for brace in braces
|
||||
]))
|
||||
self.dither(2)
|
||||
self.play(Write(bottom_label[1]))
|
||||
self.play(Write(bottom_label))
|
||||
self.dither(2)
|
||||
|
||||
self.sample_space = sample_space
|
||||
@ -297,7 +304,7 @@ class IntroducePokerHand(PiCreatureScene, SampleSpaceScene):
|
||||
flush_hands, non_flush_hands = hand_lists = [
|
||||
[self.get_hand(her, keys) for keys in key_list]
|
||||
for key_list in [
|
||||
[("3H", "8H"), ("4H", "AH"), ("JH", "KH")],
|
||||
[("3H", "8H"), ("4H", "5H"), ("JH", "KH")],
|
||||
[("AC", "6D"), ("3D", "6S"), ("JH", "4C")],
|
||||
]
|
||||
]
|
||||
@ -343,10 +350,7 @@ class IntroducePokerHand(PiCreatureScene, SampleSpaceScene):
|
||||
self.money = money
|
||||
|
||||
def change_belief(self):
|
||||
numbers = VGroup(*[
|
||||
label[1]
|
||||
for label in self.sample_space.horizontal_parts.labels
|
||||
])
|
||||
numbers = self.sample_space.horizontal_parts.labels
|
||||
rect = Rectangle(stroke_width = 0)
|
||||
rect.set_fill(BLACK, 1)
|
||||
rect.stretch_to_fit_width(numbers.get_width())
|
||||
@ -354,11 +358,12 @@ class IntroducePokerHand(PiCreatureScene, SampleSpaceScene):
|
||||
rect.move_to(numbers, UP)
|
||||
|
||||
self.play(FadeIn(rect))
|
||||
self.change_horizontal_division(
|
||||
0.2,
|
||||
anims = self.get_horizontal_division_change_animations(0.2)
|
||||
anims.append(Animation(rect))
|
||||
self.play(
|
||||
*anims,
|
||||
run_time = 3,
|
||||
rate_func = there_and_back,
|
||||
added_anims = [Animation(rect)]
|
||||
rate_func = there_and_back
|
||||
)
|
||||
self.play(FadeOut(rect))
|
||||
|
||||
@ -371,7 +376,7 @@ class IntroducePokerHand(PiCreatureScene, SampleSpaceScene):
|
||||
cards.target.move_to(self.deck)
|
||||
cards.target.to_edge(LEFT)
|
||||
|
||||
self.sample_space.add(self.sample_space.horizontal_parts.labels)
|
||||
self.sample_space.add_braces_and_labels()
|
||||
|
||||
self.play(
|
||||
self.deck.scale, 0.7,
|
||||
@ -389,9 +394,7 @@ class IntroducePokerHand(PiCreatureScene, SampleSpaceScene):
|
||||
subtitle.scale(0.8)
|
||||
subtitle.next_to(title, DOWN)
|
||||
prior_word = subtitle.get_part_by_tex("prior")
|
||||
numbers = VGroup(*[
|
||||
label[1] for label in self.sample_space.horizontal_parts.labels
|
||||
])
|
||||
numbers = self.sample_space.horizontal_parts.labels
|
||||
rect = SurroundingRectangle(numbers, color = GREEN)
|
||||
arrow = Arrow(prior_word.get_bottom(), rect.get_top())
|
||||
arrow.highlight(GREEN)
|
||||
@ -431,15 +434,9 @@ class IntroducePokerHand(PiCreatureScene, SampleSpaceScene):
|
||||
her.to_corner(UP+RIGHT)
|
||||
you.make_eye_contact(her)
|
||||
|
||||
glasses = SVGMobject(file_name = "sunglasses")
|
||||
glasses.set_stroke(WHITE, width = 0)
|
||||
glasses.set_fill(GREY, 1)
|
||||
glasses.scale_to_fit_width(
|
||||
1.1*her.eyes.get_width()
|
||||
)
|
||||
glasses.move_to(her.eyes, UP)
|
||||
|
||||
glasses = SunGlasses(her)
|
||||
her.glasses = glasses
|
||||
|
||||
self.you = you
|
||||
self.her = her
|
||||
return VGroup(you, her)
|
||||
@ -464,7 +461,6 @@ class IntroducePokerHand(PiCreatureScene, SampleSpaceScene):
|
||||
)
|
||||
return hand
|
||||
|
||||
|
||||
class HowDoesPokerWork(TeacherStudentsScene):
|
||||
def construct(self):
|
||||
self.student_says(
|
||||
@ -484,7 +480,566 @@ class YourGutKnowsBayesRule(TeacherStudentsScene):
|
||||
self.change_student_modes("confused", "gracious", "guilty")
|
||||
self.dither(3)
|
||||
|
||||
|
||||
class UpdatePokerPrior(SampleSpaceScene):
|
||||
CONFIG = {
|
||||
"double_heart_template" : "HH",
|
||||
"cash_string" : "\\$\\$\\$",
|
||||
}
|
||||
def construct(self):
|
||||
self.force_skipping()
|
||||
|
||||
self.add_sample_space()
|
||||
self.add_top_conditionals()
|
||||
self.react_to_top_conditionals()
|
||||
self.add_bottom_conditionals()
|
||||
# self.ask_where_conditionals_come_from()
|
||||
# self.vary_conditionals()
|
||||
self.show_restricted_space()
|
||||
self.write_P_flush_given_bet()
|
||||
self.reshape_rectangles()
|
||||
self.compare_prior_to_posterior()
|
||||
self.tweak_estimates()
|
||||
self.compute_posterior()
|
||||
|
||||
def add_sample_space(self):
|
||||
p = 1./22
|
||||
sample_space = SampleSpace(fill_opacity = 0)
|
||||
sample_space.shift(LEFT)
|
||||
sample_space.divide_horizontally(p, colors = [
|
||||
SuitSymbol.CONFIG["red"], BLUE_E
|
||||
])
|
||||
labels = self.get_prior_labels(p)
|
||||
braces_and_labels = sample_space.get_side_braces_and_labels(labels)
|
||||
|
||||
self.play(
|
||||
DrawBorderThenFill(sample_space),
|
||||
Write(braces_and_labels)
|
||||
)
|
||||
self.dither()
|
||||
|
||||
sample_space.add(braces_and_labels)
|
||||
self.sample_space = sample_space
|
||||
|
||||
def add_top_conditionals(self):
|
||||
top_part = self.sample_space.horizontal_parts[0]
|
||||
color = average_color(YELLOW, GREEN, GREEN)
|
||||
p = 0.97
|
||||
top_part.divide_vertically(p, colors = [color, BLUE])
|
||||
label = self.get_conditional_label(p, True)
|
||||
brace, _ignore = top_part.get_top_braces_and_labels([label])
|
||||
|
||||
explanation = TextMobject(
|
||||
"Probability of", "high bet", "given", "flush"
|
||||
)
|
||||
explanation.highlight_by_tex("high bet", GREEN)
|
||||
explanation.highlight_by_tex("flush", RED)
|
||||
explanation.scale(0.6)
|
||||
explanation.next_to(label, UP)
|
||||
|
||||
self.play(
|
||||
FadeIn(top_part.vertical_parts),
|
||||
Write(explanation, run_time = 3),
|
||||
GrowFromCenter(brace),
|
||||
)
|
||||
self.play(LaggedStart(FadeIn, label, run_time = 2, lag_ratio = 0.7))
|
||||
self.dither(2)
|
||||
|
||||
self.sample_space.add(brace, label)
|
||||
|
||||
self.top_explanation = explanation
|
||||
self.top_conditional_rhs = label[-1]
|
||||
|
||||
def react_to_top_conditionals(self):
|
||||
her = PiCreature(color = BLUE_B).flip()
|
||||
her.next_to(self.sample_space, RIGHT)
|
||||
her.to_edge(RIGHT)
|
||||
glasses = SunGlasses(her)
|
||||
glasses.save_state()
|
||||
glasses.shift(UP)
|
||||
glasses.set_fill(opacity = 0)
|
||||
her.glasses = glasses
|
||||
|
||||
self.play(FadeIn(her))
|
||||
self.play(glasses.restore)
|
||||
self.play(
|
||||
her.change_mode, "happy",
|
||||
Animation(glasses)
|
||||
)
|
||||
self.dither(2)
|
||||
|
||||
self.her = her
|
||||
|
||||
def add_bottom_conditionals(self):
|
||||
her = self.her
|
||||
bottom_part = self.sample_space.horizontal_parts[1]
|
||||
p = 0.3
|
||||
bottom_part.divide_vertically(p, colors = [GREEN_E, BLUE_E])
|
||||
label = self.get_conditional_label(p, False)
|
||||
brace, _ignore = bottom_part.get_bottom_braces_and_labels([label])
|
||||
|
||||
explanation = TextMobject(
|
||||
"Probability of", "high bet", "given", "no flush"
|
||||
)
|
||||
explanation.highlight_by_tex("high bet", GREEN)
|
||||
explanation.highlight_by_tex("no flush", RED)
|
||||
explanation.scale(0.6)
|
||||
explanation.next_to(label, DOWN)
|
||||
|
||||
self.play(DrawBorderThenFill(bottom_part.vertical_parts))
|
||||
self.play(GrowFromCenter(brace))
|
||||
self.play(
|
||||
her.change_mode, "shruggie",
|
||||
MaintainPositionRelativeTo(her.glasses, her.eyes)
|
||||
)
|
||||
self.play(Write(explanation))
|
||||
self.dither()
|
||||
self.play(*[
|
||||
ReplacementTransform(
|
||||
VGroup(explanation[j].copy()),
|
||||
VGroup(*label[i1:i2]),
|
||||
run_time = 2,
|
||||
rate_func = squish_rate_func(smooth, a, a+0.5)
|
||||
)
|
||||
for a, (i1, i2, j) in zip(np.linspace(0, 0.5, 4), [
|
||||
(0, 1, 0),
|
||||
(1, 2, 1),
|
||||
(2, 3, 2),
|
||||
(3, 6, 3),
|
||||
])
|
||||
])
|
||||
self.play(Write(VGroup(*label[-2:])))
|
||||
self.dither(2)
|
||||
self.play(*map(FadeOut, [her, her.glasses]))
|
||||
|
||||
self.sample_space.add(brace, label)
|
||||
self.bottom_explanation = explanation
|
||||
self.bottom_conditional_rhs = label[-1]
|
||||
|
||||
def ask_where_conditionals_come_from(self):
|
||||
randy = Randolph().flip()
|
||||
randy.scale(0.75)
|
||||
randy.to_edge(RIGHT)
|
||||
randy.shift(2*DOWN)
|
||||
words = TextMobject("Where do these \\\\", "numbers", "come from?")
|
||||
numbers_word = words.get_part_by_tex("numbers")
|
||||
numbers_word.highlight(YELLOW)
|
||||
words.scale(0.7)
|
||||
bubble = ThoughtBubble(height = 3, width = 4)
|
||||
bubble.pin_to(randy)
|
||||
bubble.shift(MED_LARGE_BUFF*RIGHT)
|
||||
bubble.add_content(words)
|
||||
|
||||
numbers = VGroup(
|
||||
self.top_conditional_rhs,
|
||||
self.bottom_conditional_rhs
|
||||
)
|
||||
numbers.save_state()
|
||||
arrows = VGroup(*[
|
||||
Arrow(
|
||||
numbers_word.get_left(),
|
||||
num.get_right(),
|
||||
buff = 2*SMALL_BUFF
|
||||
)
|
||||
for num in numbers
|
||||
])
|
||||
|
||||
questions = VGroup(*map(TextMobject, [
|
||||
"Does she bluff?",
|
||||
"How much does she have?",
|
||||
"Does she take risks?",
|
||||
"What's her model of me?",
|
||||
"\\vdots"
|
||||
]))
|
||||
questions.arrange_submobjects(DOWN, aligned_edge = LEFT)
|
||||
questions[-1].next_to(questions[-2], DOWN)
|
||||
questions.scale(0.7)
|
||||
questions.next_to(randy, UP)
|
||||
questions.shift_onto_screen()
|
||||
|
||||
self.play(
|
||||
randy.change_mode, "confused",
|
||||
ShowCreation(bubble),
|
||||
Write(words, run_time = 2)
|
||||
)
|
||||
self.play(*map(ShowCreation, arrows))
|
||||
self.play(numbers.highlight, YELLOW)
|
||||
self.play(Blink(randy))
|
||||
self.play(randy.change_mode, "maybe")
|
||||
self.play(*map(FadeOut, [
|
||||
bubble, words, arrows
|
||||
]))
|
||||
for question in questions:
|
||||
self.play(
|
||||
FadeIn(question),
|
||||
randy.look_at, question
|
||||
)
|
||||
self.dither()
|
||||
self.play(Blink(randy))
|
||||
self.dither()
|
||||
self.play(
|
||||
randy.change_mode, "pondering",
|
||||
FadeOut(questions)
|
||||
)
|
||||
|
||||
self.randy = randy
|
||||
|
||||
def vary_conditionals(self):
|
||||
randy = self.randy
|
||||
rects = VGroup(*[
|
||||
SurroundingRectangle(
|
||||
VGroup(explanation),
|
||||
buff = SMALL_BUFF,
|
||||
)
|
||||
for explanation, rhs in zip(
|
||||
[self.top_explanation, self.bottom_explanation],
|
||||
[self.top_conditional_rhs, self.bottom_conditional_rhs],
|
||||
)
|
||||
])
|
||||
|
||||
new_conditionals = [
|
||||
(0.91, 0.4),
|
||||
(0.83, 0.1),
|
||||
(0.99, 0.2),
|
||||
(0.97, 0.3),
|
||||
]
|
||||
|
||||
self.play(*map(ShowCreation, rects))
|
||||
self.play(FadeOut(rects))
|
||||
for i, value in enumerate(it.chain(*new_conditionals)):
|
||||
self.play(
|
||||
randy.look_at, rects[i%2],
|
||||
*self.get_conditional_change_anims(i%2, value)
|
||||
)
|
||||
if i%2 == 1:
|
||||
self.dither()
|
||||
self.play(FadeOut(randy))
|
||||
|
||||
def show_restricted_space(self):
|
||||
high_bet_space, low_bet_space = [
|
||||
VGroup(*[
|
||||
self.sample_space.horizontal_parts[i].vertical_parts[j]
|
||||
for i in range(2)
|
||||
])
|
||||
for j in range(2)
|
||||
]
|
||||
words = TexMobject("P(", self.cash_string, ")")
|
||||
words.highlight_by_tex(self.cash_string, GREEN)
|
||||
words.next_to(self.sample_space, RIGHT)
|
||||
low_bet_space.generate_target()
|
||||
for submob in low_bet_space.target:
|
||||
submob.highlight(average_color(
|
||||
submob.get_color(), *[BLACK]*4
|
||||
))
|
||||
arrows = VGroup(*[
|
||||
Arrow(
|
||||
words.get_left(),
|
||||
submob.get_edge_center(vect),
|
||||
color = submob.get_color()
|
||||
)
|
||||
for submob, vect in zip(high_bet_space, [DOWN, RIGHT])
|
||||
])
|
||||
|
||||
self.play(MoveToTarget(low_bet_space))
|
||||
self.play(
|
||||
Write(words),
|
||||
*map(ShowCreation, arrows)
|
||||
)
|
||||
self.dither()
|
||||
for rect in high_bet_space:
|
||||
self.play(Indicate(rect, scale_factor = 1))
|
||||
self.play(*map(FadeOut, [words, arrows]))
|
||||
|
||||
self.high_bet_space = high_bet_space
|
||||
|
||||
def write_P_flush_given_bet(self):
|
||||
posterior_tex = TexMobject(
|
||||
"P(", self.double_heart_template,
|
||||
"|", self.cash_string, ")"
|
||||
)
|
||||
posterior_tex.scale(0.7)
|
||||
posterior_tex.highlight_by_tex(self.cash_string, GREEN)
|
||||
self.insert_double_heart(posterior_tex)
|
||||
rects = self.high_bet_space.copy()
|
||||
rects = [rects[0].copy()] + list(rects)
|
||||
for rect in rects:
|
||||
rect.generate_target()
|
||||
numerator = rects[0].target
|
||||
plus = TexMobject("+")
|
||||
denominator = VGroup(rects[1].target, plus, rects[2].target)
|
||||
denominator.arrange_submobjects(RIGHT, buff = SMALL_BUFF)
|
||||
frac_line = TexMobject("\\over")
|
||||
frac_line.stretch_to_fit_width(denominator.get_width())
|
||||
fraction = VGroup(numerator, frac_line, denominator)
|
||||
fraction.arrange_submobjects(DOWN)
|
||||
|
||||
arrow = TexMobject("\\downarrow")
|
||||
group = VGroup(posterior_tex, arrow, fraction)
|
||||
group.arrange_submobjects(DOWN)
|
||||
group.to_corner(UP+RIGHT)
|
||||
|
||||
self.play(Write(posterior_tex))
|
||||
self.play(Write(arrow))
|
||||
self.play(MoveToTarget(rects[0]))
|
||||
self.dither()
|
||||
self.play(*it.chain(
|
||||
map(Write, [frac_line, plus]),
|
||||
map(MoveToTarget, rects[1:])
|
||||
))
|
||||
self.dither(3)
|
||||
|
||||
self.posterior_tex = posterior_tex
|
||||
self.to_fade = VGroup(arrow, frac_line, plus)
|
||||
self.to_post_rects = VGroup(VGroup(*rects[:2]),rects[2])
|
||||
|
||||
def reshape_rectangles(self):
|
||||
post_rects = self.get_posterior_rectangles()
|
||||
braces, labels = self.get_posterior_rectangle_braces_and_labels(
|
||||
post_rects, [self.posterior_tex.copy()]
|
||||
)
|
||||
height_rect = SurroundingRectangle(braces)
|
||||
|
||||
self.play(
|
||||
FadeOut(self.to_fade),
|
||||
ReplacementTransform(
|
||||
self.to_post_rects, post_rects,
|
||||
run_time = 2,
|
||||
),
|
||||
)
|
||||
self.dither(2)
|
||||
self.play(ReplacementTransform(self.posterior_tex, labels[0]))
|
||||
self.posterior_tex = labels[0]
|
||||
self.play(GrowFromCenter(braces))
|
||||
self.dither()
|
||||
self.play(ShowCreation(height_rect))
|
||||
self.play(FadeOut(height_rect))
|
||||
self.dither()
|
||||
|
||||
self.post_rects = post_rects
|
||||
|
||||
def compare_prior_to_posterior(self):
|
||||
prior_tex = self.sample_space.horizontal_parts.labels[0]
|
||||
post_tex = self.posterior_tex
|
||||
prior_rect, post_rect = [
|
||||
SurroundingRectangle(tex, stroke_width = 2)
|
||||
for tex in [prior_tex, post_tex]
|
||||
]
|
||||
|
||||
post_words = TextMobject("Posterior", "probability")
|
||||
post_words.scale(0.8)
|
||||
post_words.to_corner(UP+RIGHT)
|
||||
post_arrow = Arrow(
|
||||
post_words[0].get_bottom(), post_tex.get_top(),
|
||||
color = WHITE
|
||||
)
|
||||
|
||||
self.play(ShowCreation(prior_rect))
|
||||
self.dither()
|
||||
self.play(ReplacementTransform(prior_rect, post_rect))
|
||||
self.dither()
|
||||
self.play(FadeOut(post_rect))
|
||||
self.play(Indicate(post_tex.get_part_by_tex(self.cash_string)))
|
||||
self.dither()
|
||||
self.play(
|
||||
Write(post_words),
|
||||
ShowCreation(post_arrow)
|
||||
)
|
||||
self.dither()
|
||||
self.play(post_words[1].fade, 0.8)
|
||||
self.dither(2)
|
||||
self.play(*map(FadeOut, [post_words, post_arrow]))
|
||||
|
||||
def tweak_estimates(self):
|
||||
post_rects = self.post_rects
|
||||
self.revert_to_original_skipping_status()
|
||||
self.preview_tweaks(post_rects)
|
||||
|
||||
def preview_tweaks(self, post_rects):
|
||||
new_value_lists = [
|
||||
(0.85, 0.1, 0.11),
|
||||
(0.97, 0.3, 1./22),
|
||||
]
|
||||
for new_values in new_value_lists:
|
||||
for i, value in zip(range(2), new_values):
|
||||
self.play(*self.get_conditional_change_anims(
|
||||
i, value, post_rects
|
||||
))
|
||||
self.play(*self.get_prior_change_anims(
|
||||
new_values[-1], post_rects
|
||||
))
|
||||
self.dither()
|
||||
|
||||
def compute_posterior(self):
|
||||
pass
|
||||
|
||||
######
|
||||
|
||||
def get_prior_labels(self, value):
|
||||
p_str = "%0.3f"%value
|
||||
q_str = "%0.3f"%(1-value)
|
||||
labels = [
|
||||
TexMobject(
|
||||
"P(", s, self.double_heart_template, ")",
|
||||
"= ", num
|
||||
)
|
||||
for s, num in ("", p_str), ("\\text{not }", q_str)
|
||||
]
|
||||
for label in labels:
|
||||
label.scale(0.7)
|
||||
self.insert_double_heart(label)
|
||||
return labels
|
||||
|
||||
def get_conditional_label(self, value, given_flush = True):
|
||||
label = TexMobject(
|
||||
"P(", self.cash_string, "|",
|
||||
"" if given_flush else "\\text{not }",
|
||||
self.double_heart_template, ")",
|
||||
"=", str(value)
|
||||
)
|
||||
self.insert_double_heart(label)
|
||||
label.highlight_by_tex(self.cash_string, GREEN)
|
||||
label.scale(0.7)
|
||||
return label
|
||||
|
||||
def insert_double_heart(self, tex_mob):
|
||||
double_heart = SuitSymbol("hearts")
|
||||
double_heart.add(SuitSymbol("hearts"))
|
||||
double_heart.arrange_submobjects(RIGHT, buff = SMALL_BUFF)
|
||||
double_heart.get_tex_string = lambda : self.double_heart_template
|
||||
template = tex_mob.get_part_by_tex(self.double_heart_template)
|
||||
double_heart.replace(template)
|
||||
tex_mob.submobjects[tex_mob.index_of_part(template)] = double_heart
|
||||
return tex_mob
|
||||
|
||||
def get_prior_change_anims(self, value, post_rects = None):
|
||||
space = self.sample_space
|
||||
parts = space.horizontal_parts
|
||||
anims = self.get_horizontal_division_change_animations(
|
||||
value, new_label_kwargs = {
|
||||
"labels" : self.get_prior_labels(value)
|
||||
}
|
||||
)
|
||||
if post_rects is not None:
|
||||
anims += self.get_posterior_rectangle_change_anims(post_rects)
|
||||
return anims
|
||||
|
||||
def get_conditional_change_anims(
|
||||
self, sub_sample_space_index, value,
|
||||
post_rects = None
|
||||
):
|
||||
parts = self.sample_space.horizontal_parts
|
||||
sub_sample_space = parts[sub_sample_space_index]
|
||||
given_flush = (sub_sample_space_index == 0)
|
||||
label = self.get_conditional_label(value, given_flush)
|
||||
|
||||
anims = self.get_division_change_animations(
|
||||
sub_sample_space, sub_sample_space.vertical_parts, value,
|
||||
dimension = 0,
|
||||
new_label_kwargs = {"labels" : [label]},
|
||||
)
|
||||
|
||||
if post_rects is not None:
|
||||
anims += self.get_posterior_rectangle_change_anims(post_rects)
|
||||
|
||||
return anims
|
||||
|
||||
def get_top_conditional_change_anims(self, *args, **kwargs):
|
||||
return self.get_conditional_change_anims(0, *args, **kwargs)
|
||||
|
||||
def get_bottom_conditional_change_anims(self, *args, **kwargs):
|
||||
return self.get_conditional_change_anims(1, *args, **kwargs)
|
||||
|
||||
def get_prior_rectangles(self):
|
||||
return VGroup(*[
|
||||
self.sample_space.horizontal_parts[i].vertical_parts[0]
|
||||
for i in range(2)
|
||||
])
|
||||
|
||||
def get_posterior_rectangles(self):
|
||||
prior_rects = self.get_prior_rectangles()
|
||||
areas = [
|
||||
rect.get_width()*rect.get_height()
|
||||
for rect in prior_rects
|
||||
]
|
||||
total_area = sum(areas)
|
||||
total_height = prior_rects.get_height()
|
||||
|
||||
post_rects = prior_rects.copy()
|
||||
for rect, area in zip(post_rects, areas):
|
||||
rect.stretch_to_fit_height(total_height * area/total_area)
|
||||
rect.stretch_to_fit_width(
|
||||
area/rect.get_height()
|
||||
)
|
||||
post_rects.arrange_submobjects(DOWN, buff = 0)
|
||||
post_rects.next_to(
|
||||
self.sample_space.full_space, RIGHT, MED_LARGE_BUFF
|
||||
)
|
||||
return post_rects
|
||||
|
||||
def get_posterior_rectangle_braces_and_labels(self, post_rects, labels):
|
||||
braces = VGroup()
|
||||
label_mobs = VGroup()
|
||||
for label, rect in zip(labels, post_rects):
|
||||
if not isinstance(label, Mobject):
|
||||
label_mob = TexMobject(label)
|
||||
label_mob.scale(0.7)
|
||||
else:
|
||||
label_mob = label
|
||||
brace = Brace(
|
||||
rect, RIGHT,
|
||||
buff = SMALL_BUFF,
|
||||
min_num_quads = 2
|
||||
)
|
||||
label_mob.next_to(brace, RIGHT, SMALL_BUFF)
|
||||
|
||||
label_mobs.add(label_mob)
|
||||
braces.add(brace)
|
||||
post_rects.braces = braces
|
||||
post_rects.labels = label_mobs
|
||||
return VGroup(braces, label_mobs)
|
||||
|
||||
def update_posterior_braces(self, post_rects):
|
||||
braces = post_rects.braces
|
||||
labels = post_rects.labels
|
||||
for rect, brace, label in zip(post_rects, braces, labels):
|
||||
brace.stretch_to_fit_height(rect.get_height())
|
||||
brace.next_to(rect, RIGHT, SMALL_BUFF)
|
||||
label.next_to(brace, RIGHT, SMALL_BUFF)
|
||||
|
||||
def get_posterior_rectangle_change_anims(self, post_rects):
|
||||
def update_rects(rects):
|
||||
new_rects = self.get_posterior_rectangles()
|
||||
Transform(rects, new_rects).update(1)
|
||||
if hasattr(rects, "braces"):
|
||||
self.update_posterior_braces(rects)
|
||||
return rects
|
||||
|
||||
anims = [UpdateFromFunc(post_rects, update_rects)]
|
||||
if hasattr(post_rects, "braces"):
|
||||
anims += map(Animation, [
|
||||
post_rects.labels, post_rects.braces
|
||||
])
|
||||
return anims
|
||||
|
||||
|
||||
class NextVideoWrapper(TeacherStudentsScene):
|
||||
def construct(self):
|
||||
title = TextMobject("Next video: Bayesian networks")
|
||||
title.scale(0.8)
|
||||
title.to_edge(UP, buff = SMALL_BUFF)
|
||||
screen = ScreenRectangle(height = 4)
|
||||
screen.next_to(title, DOWN)
|
||||
title.save_state()
|
||||
title.shift(DOWN)
|
||||
title.set_fill(opacity = 0)
|
||||
|
||||
self.play(
|
||||
title.restore,
|
||||
self.teacher.change, "raise_right_hand"
|
||||
)
|
||||
self.play(ShowCreation(screen))
|
||||
self.change_student_modes(*["pondering"]*3)
|
||||
self.play(Animation(screen))
|
||||
self.dither(5)
|
||||
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user