from big_ol_pile_of_manim_imports import * from old_projects.eoc.chapter4 import ThreeLinesChainRule class ExpFootnoteOpeningQuote(OpeningQuote): CONFIG = { "quote" : [ "Who has not been amazed to learn that the function", "$y = e^x$,", "like a phoenix rising again from its own", "ashes, is its own derivative?", ], "highlighted_quote_terms" : { "$y = e^x$" : MAROON_B }, "author" : "Francois le Lionnais" } class LastVideo(TeacherStudentsScene): def construct(self): series = VideoSeries() series.to_edge(UP) last_video = series[2] last_video.save_state() this_video = series[3] known_formulas = VGroup(*list(map(TexMobject, [ "\\frac{d(x^n)}{dx} = nx^{n-1}", "\\frac{d(\\sin(x))}{dx} = \\cos(x)", ]))) known_formulas.arrange( DOWN, buff = MED_LARGE_BUFF, ) known_formulas.set_height(2.5) exp_question = TexMobject("2^x", ", 7^x, ", "e^x", " ???") last_video_brace = Brace(last_video) known_formulas.next_to(last_video_brace, DOWN) known_formulas.shift(MED_LARGE_BUFF*LEFT) last_video_brace.save_state() last_video_brace.shift(3*LEFT) last_video_brace.set_fill(opacity = 0) self.add(series) self.play( last_video_brace.restore, last_video.set_color, YELLOW, self.get_teacher().change_mode, "raise_right_hand", ) self.play(Write(known_formulas)) self.wait() self.student_says( exp_question, student_index = 1, added_anims = [self.get_teacher().change_mode, "pondering"] ) self.wait(3) e_to_x = exp_question.get_part_by_tex("e^x") self.play( self.teacher.change_mode, "raise_right_hand", e_to_x.scale, 1.5, e_to_x.set_color, YELLOW, e_to_x.next_to, self.teacher.get_corner(UP+LEFT), UP ) self.wait(2) class PopulationSizeGraphVsPopulationMassGraph(Scene): def construct(self): pass class DoublingPopulation(PiCreatureScene): CONFIG = { "time_color" : YELLOW, "pi_creature_grid_dimensions" : (8, 8), "pi_creature_grid_height" : 6, } def construct(self): self.remove(self.get_pi_creatures()) self.introduce_expression() self.introduce_pi_creatures() self.count_through_days() self.ask_about_dM_dt() self.growth_per_day() self.relate_growth_rate_to_pop_size() def introduce_expression(self): f_x = TexMobject("f(x)", "=", "2^x") f_t = TexMobject("f(t)", "=", "2^t") P_t = TexMobject("P(t)", "=", "2^t") M_t = TexMobject("M(t)", "=", "2^t") functions = VGroup(f_x, f_t, P_t, M_t) for function in functions: function.scale(1.2) function.to_corner(UP+LEFT) for function in functions[1:]: for i, j in (0, 2), (2, 1): function[i][j].set_color(self.time_color) t_expression = TexMobject("t", "=", "\\text{Time (in days)}") t_expression.to_corner(UP+RIGHT) t_expression[0].set_color(self.time_color) pop_brace, mass_brace = [ Brace(function[0], DOWN) for function in (P_t, M_t) ] for brace, word in (pop_brace, "size"), (mass_brace, "mass"): text = brace.get_text("Population %s"%word) text.to_edge(LEFT) brace.text = text self.play(Write(f_x)) self.wait() self.play( Transform(f_x, f_t), FadeIn( t_expression, run_time = 2, lag_ratio = 0.5 ) ) self.play(Transform(f_x, P_t)) self.play( GrowFromCenter(pop_brace), Write(pop_brace.text, run_time = 2) ) self.wait(2) self.function = f_x self.pop_brace = pop_brace self.t_expression = t_expression self.mass_function = M_t self.mass_brace = mass_brace def introduce_pi_creatures(self): creatures = self.get_pi_creatures() total_num_days = self.get_num_days() num_start_days = 4 self.reset() for x in range(num_start_days): self.let_one_day_pass() self.wait() self.play( Transform(self.function, self.mass_function), Transform(self.pop_brace, self.mass_brace), Transform(self.pop_brace.text, self.mass_brace.text), ) self.wait() for x in range(total_num_days-num_start_days): self.let_one_day_pass() self.wait() self.joint_blink(shuffle = False) self.wait() def count_through_days(self): self.reset() brace = self.get_population_size_descriptor() days_to_let_pass = 3 self.play(GrowFromCenter(brace)) self.wait() for x in range(days_to_let_pass): self.let_one_day_pass() new_brace = self.get_population_size_descriptor() self.play(Transform(brace, new_brace)) self.wait() self.population_size_descriptor = brace def ask_about_dM_dt(self): dM_dt_question = TexMobject("{dM", "\\over dt}", "=", "???") dM, dt, equals, q_marks = dM_dt_question dM_dt_question.next_to(self.function, DOWN, buff = LARGE_BUFF) dM_dt_question.to_edge(LEFT) self.play( FadeOut(self.pop_brace), FadeOut(self.pop_brace.text), Write(dM_dt_question) ) self.wait(3) for mob in dM, dt: self.play(Indicate(mob)) self.wait() self.dM_dt_question = dM_dt_question def growth_per_day(self): day_to_day, frac = self.get_from_day_to_day_label() self.play( FadeOut(self.dM_dt_question), FadeOut(self.population_size_descriptor), FadeIn(day_to_day) ) rect = self.let_day_pass_and_highlight_new_creatures(frac) for x in range(2): new_day_to_day, new_frac = self.get_from_day_to_day_label() self.play(*list(map(FadeOut, [rect, frac]))) frac = new_frac self.play(Transform(day_to_day, new_day_to_day)) rect = self.let_day_pass_and_highlight_new_creatures(frac) self.play(*list(map(FadeOut, [rect, frac, day_to_day]))) def let_day_pass_and_highlight_new_creatures(self, frac): num_new_creatures = 2**self.get_curr_day() self.let_one_day_pass() new_creatures = VGroup( *self.get_on_screen_pi_creatures()[-num_new_creatures:] ) rect = Rectangle( color = GREEN, fill_color = BLUE, fill_opacity = 0.3, ) rect.replace(new_creatures, stretch = True) rect.stretch_to_fit_height(rect.get_height()+MED_SMALL_BUFF) rect.stretch_to_fit_width(rect.get_width()+MED_SMALL_BUFF) self.play(DrawBorderThenFill(rect)) self.play(Write(frac)) self.wait() return rect def relate_growth_rate_to_pop_size(self): false_deriv = TexMobject( "{d(2^t) ", "\\over dt}", "= 2^t" ) difference_eq = TexMobject( "{ {2^{t+1} - 2^t} \\over", "1}", "= 2^t" ) real_deriv = TexMobject( "{ {2^{t+dt} - 2^t} \\over", "dt}", "= \\, ???" ) VGroup( false_deriv[0][3], false_deriv[2][-1], difference_eq[0][1], difference_eq[0][-2], difference_eq[2][-1], difference_eq[2][-1], real_deriv[0][1], real_deriv[0][-2], ).set_color(YELLOW) VGroup( difference_eq[0][3], difference_eq[1][-1], real_deriv[0][3], real_deriv[0][4], real_deriv[1][-2], real_deriv[1][-1], ).set_color(GREEN) expressions = [false_deriv, difference_eq, real_deriv] text_arg_list = [ ("Tempting", "...",), ("Rate of change", "\\\\ over one full day"), ("Rate of change", "\\\\ in a small time"), ] for expression, text_args in zip(expressions, text_arg_list): expression.next_to( self.function, DOWN, buff = LARGE_BUFF, aligned_edge = LEFT, ) expression.brace = Brace(expression, DOWN) expression.brace_text = expression.brace.get_text(*text_args) time = self.t_expression[-1] new_time = TexMobject("3") new_time.move_to(time, LEFT) fading_creatures = VGroup(*self.get_on_screen_pi_creatures()[8:]) self.play(*list(map(FadeIn, [ false_deriv, false_deriv.brace, false_deriv.brace_text ]))) self.wait() self.play( Transform(time, new_time), FadeOut(fading_creatures) ) self.wait() for x in range(3): self.let_one_day_pass(run_time = 2) self.wait(2) for expression in difference_eq, real_deriv: expression.brace_text[1].set_color(GREEN) self.play( Transform(false_deriv, expression), Transform(false_deriv.brace, expression.brace), Transform(false_deriv.brace_text, expression.brace_text), ) self.wait(3) self.reset() for x in range(self.get_num_days()): self.let_one_day_pass() self.wait() rect = Rectangle(color = YELLOW) rect.replace(real_deriv) rect.stretch_to_fit_width(rect.get_width()+MED_SMALL_BUFF) rect.stretch_to_fit_height(rect.get_height()+MED_SMALL_BUFF) self.play(*list(map(FadeOut, [ false_deriv.brace, false_deriv.brace_text ]))) self.play(ShowCreation(rect)) self.play(*[ ApplyFunction( lambda pi : pi.change_mode("pondering").look_at(real_deriv), pi, run_time = 2, rate_func = squish_rate_func(smooth, a, a+0.5) ) for pi in self.get_pi_creatures() for a in [0.5*random.random()] ]) self.wait(3) ########### def create_pi_creatures(self): width, height = self.pi_creature_grid_dimensions creature_array = VGroup(*[ VGroup(*[ PiCreature(mode = "plain") for y in range(height) ]).arrange(UP, buff = MED_LARGE_BUFF) for x in range(width) ]).arrange(RIGHT, buff = MED_LARGE_BUFF) creatures = VGroup(*it.chain(*creature_array)) creatures.set_height(self.pi_creature_grid_height) creatures.to_corner(DOWN+RIGHT) colors = color_gradient([BLUE, GREEN, GREY_BROWN], len(creatures)) random.shuffle(colors) for creature, color in zip(creatures, colors): creature.set_color(color) return creatures def reset(self): time = self.t_expression[-1] faders = [time] + list(self.get_on_screen_pi_creatures()) new_time = TexMobject("0") new_time.next_to(self.t_expression[-2], RIGHT) first_creature = self.get_pi_creatures()[0] self.play(*list(map(FadeOut, faders))) self.play(*list(map(FadeIn, [first_creature, new_time]))) self.t_expression.submobjects[-1] = new_time def let_one_day_pass(self, run_time = 2): all_creatures = self.get_pi_creatures() on_screen_creatures = self.get_on_screen_pi_creatures() low_i = len(on_screen_creatures) high_i = min(2*low_i, len(all_creatures)) new_creatures = VGroup(*all_creatures[low_i:high_i]) to_children_anims = [] growing_anims = [] for old_pi, pi in zip(on_screen_creatures, new_creatures): pi.save_state() child = pi.copy() child.scale(0.25, about_point = child.get_bottom()) child.eyes.scale(1.5, about_point = child.eyes.get_bottom()) pi.move_to(old_pi) pi.set_fill(opacity = 0) index = list(new_creatures).index(pi) prop = float(index)/len(new_creatures) alpha = np.clip(len(new_creatures)/8.0, 0, 0.5) rate_func = squish_rate_func( smooth, alpha*prop, alpha*prop+(1-alpha) ) to_child_anim = Transform(pi, child, rate_func = rate_func) to_child_anim.update(1) growing_anim = ApplyMethod(pi.restore, rate_func = rate_func) to_child_anim.update(0) to_children_anims.append(to_child_anim) growing_anims.append(growing_anim) time = self.t_expression[-1] total_new_creatures = len(on_screen_creatures) + len(new_creatures) new_time = TexMobject(str(int(np.log2(total_new_creatures)))) new_time.move_to(time, LEFT) growing_anims.append(Transform(time, new_time)) self.play(*to_children_anims, run_time = run_time/2.0) self.play(*growing_anims, run_time = run_time/2.0) def get_num_pi_creatures_on_screen(self): mobjects = self.get_mobjects() return sum([ pi in mobjects for pi in self.get_pi_creatures() ]) def get_population_size_descriptor(self): on_screen_creatures = self.get_on_screen_pi_creatures() brace = Brace(on_screen_creatures, LEFT) n = len(on_screen_creatures) label = brace.get_text( "$2^%d$"%int(np.log2(n)), "$=%d$"%n, ) brace.add(label) return brace def get_num_days(self): x, y = self.pi_creature_grid_dimensions return int(np.log2(x*y)) def get_curr_day(self): return int(np.log2(len(self.get_on_screen_pi_creatures()))) def get_from_day_to_day_label(self): curr_day = self.get_curr_day() top_words = TextMobject( "From day", str(curr_day), "to", str(curr_day+1), ":" ) top_words.set_width(4) top_words.next_to( self.function, DOWN, buff = MED_LARGE_BUFF, aligned_edge = LEFT, ) top_words[1].set_color(GREEN) bottom_words = TexMobject( str(2**curr_day), "\\text{ creatures}", "\\over {1 \\text{ day}}" ) bottom_words[0].set_color(GREEN) bottom_words.next_to(top_words, DOWN, buff = MED_LARGE_BUFF) return top_words, bottom_words class GraphOfTwoToT(GraphScene): CONFIG = { "x_axis_label" : "$t$", "y_axis_label" : "$M$", "x_labeled_nums" : list(range(1, 7)), "y_labeled_nums" : list(range(8, 40, 8)), "x_max" : 6, "y_min" : 0, "y_max" : 32, "y_tick_frequency" : 2, "graph_origin" : 2.5*DOWN + 5*LEFT, } def construct(self): self.setup_axes() example_t = 3 graph = self.get_graph(lambda t : 2**t, color = BLUE_C) self.graph = graph graph_label = self.get_graph_label( graph, "M(t) = 2^t", direction = LEFT, ) label_group = self.get_label_group(example_t) v_line, brace, height_label, ss_group, slope_label = label_group self.animate_secant_slope_group_change( ss_group, target_dx = 1, run_time = 0 ) self.remove(ss_group) #Draw graph and revert to tangent self.play(ShowCreation(graph)) self.play(Write(graph_label)) self.wait() self.play(Write(ss_group)) self.wait() for target_dx in 0.01, 1, 0.01: self.animate_secant_slope_group_change( ss_group, target_dx = target_dx ) self.wait() #Mark up with values self.play(ShowCreation(v_line)) self.play( GrowFromCenter(brace), Write(height_label, run_time = 1) ) self.wait() self.play( FadeIn( slope_label, run_time = 4, lag_ratio = 0.5 ), ReplacementTransform( height_label.copy(), slope_label.get_part_by_tex("2^") ) ) self.wait() #Vary value threes = VGroup(height_label[1], slope_label[2][1]) ts = VGroup(*[ TexMobject("t").set_color(YELLOW).scale(0.75).move_to(three) for three in threes ]) self.play(Transform(threes, ts)) alt_example_t = example_t+1 def update_label_group(group, alpha): t = interpolate(example_t, alt_example_t, alpha) new_group = self.get_label_group(t) Transform(group, new_group).update(1) for t, three in zip(ts, threes): t.move_to(three) Transform(threes, ts).update(1) return group self.play(UpdateFromAlphaFunc( label_group, update_label_group, run_time = 3, )) self.play(UpdateFromAlphaFunc( label_group, update_label_group, run_time = 3, rate_func = lambda t : 1 - 1.5*smooth(t) )) def get_label_group(self, t): graph = self.graph v_line = self.get_vertical_line_to_graph( t, graph, color = YELLOW, ) brace = Brace(v_line, RIGHT) height_label = brace.get_text("$2^%d$"%t) ss_group = self.get_secant_slope_group( t, graph, dx = 0.01, df_label = "dM", dx_label = "dt", dx_line_color = GREEN, secant_line_color = RED, ) slope_label = TexMobject( "\\text{Slope}", "=", "2^%d"%t, "(%.7f\\dots)"%np.log(2) ) slope_label.next_to( ss_group.secant_line.point_from_proportion(0.65), DOWN+RIGHT, buff = 0 ) slope_label.set_color_by_tex("Slope", RED) return VGroup( v_line, brace, height_label, ss_group, slope_label ) class SimpleGraphOfTwoToT(GraphOfTwoToT): CONFIG = { "x_axis_label" : "", "y_axis_label" : "", } def construct(self): self.setup_axes() func = lambda t : 2**t graph = self.get_graph(func) line_pairs = VGroup() for x in 1, 2, 3, 4, 5: point = self.coords_to_point(x, func(x)) x_axis_point = self.coords_to_point(x, 0) y_axis_point = self.coords_to_point(0, func(x)) line_pairs.add(VGroup( DashedLine(x_axis_point, point), DashedLine(y_axis_point, point), )) self.play(ShowCreation(graph, run_time = 2)) for pair in line_pairs: self.play(ShowCreation(pair)) self.wait() class FakeDiagram(TeacherStudentsScene): def construct(self): gs = GraphScene(skip_animations = True) gs.setup_axes() background_graph, foreground_graph = graphs = VGroup(*[ gs.get_graph( lambda t : np.log(2)*2**t, x_min = -8, x_max = 2 + dx ) for dx in (0.25, 0) ]) for graph in graphs: end_point = graph.points[-1] axis_point = end_point[0]*RIGHT + gs.graph_origin[1]*UP for alpha in np.linspace(0, 1, 20): point = interpolate(axis_point, graph.points[0], alpha) graph.add_line_to(point) graph.set_stroke(width = 1) graph.set_fill(opacity = 1) graph.set_color(BLUE_D) background_graph.set_color(YELLOW) background_graph.set_stroke(width = 0.5) graphs.next_to(self.teacher, UP+LEFT, LARGE_BUFF) two_to_t = TexMobject("2^t") two_to_t.next_to( foreground_graph.get_corner(DOWN+RIGHT), UP+LEFT ) corner_line = Line(*[ graph.get_corner(DOWN+RIGHT) for graph in graphs ]) dt_brace = Brace(corner_line, DOWN, buff = SMALL_BUFF) dt = dt_brace.get_text("$dt$") side_brace = Brace(graphs, RIGHT, buff = SMALL_BUFF) deriv = side_brace.get_text("$\\frac{d(2^t)}{dt}$") circle = Circle(color = RED) circle.replace(deriv, stretch = True) circle.scale_in_place(1.5) words = TextMobject("Not a real explanation") words.to_edge(UP) arrow = Arrow(words.get_bottom(), two_to_t.get_corner(UP+LEFT)) arrow.set_color(WHITE) diagram = VGroup( graphs, two_to_t, dt_brace, dt, side_brace, deriv, circle, words, arrow ) self.play(self.teacher.change_mode, "raise_right_hand") self.play( Animation(VectorizedPoint(graphs.get_right())), DrawBorderThenFill(foreground_graph), Write(two_to_t) ) self.wait() self.play( ReplacementTransform( foreground_graph.copy(), background_graph, ), Animation(foreground_graph), Animation(two_to_t), GrowFromCenter(dt_brace), Write(dt) ) self.play(GrowFromCenter(side_brace)) self.play(Write(deriv, run_time = 2)) self.wait() self.play( ShowCreation(circle), self.teacher.change_mode, "hooray" ) self.change_student_modes(*["confused"]*3) self.play( Write(words), ShowCreation(arrow), self.teacher.change_mode, "shruggie" ) self.wait(3) self.play( FadeOut(diagram), *[ ApplyMethod(pi.change_mode, "plain") for pi in self.get_pi_creatures() ] ) self.teacher_says( "More numerical \\\\ than visual..." ) self.wait(2) self.diagram = diagram class AnalyzeExponentRatio(PiCreatureScene): CONFIG = { "base" : 2, "base_str" : "2", } def construct(self): base_str = self.base_str func_def = TexMobject("M(", "t", ")", "= ", "%s^"%base_str, "t") func_def.to_corner(UP+LEFT) self.add(func_def) ratio = TexMobject( "{ {%s^"%base_str, "{t", "+", "dt}", "-", "%s^"%base_str, "t}", "\\over \\,", "dt}" ) ratio.shift(UP+LEFT) lhs = TexMobject("{dM", "\\over \\,", "dt}", "(", "t", ")", "=") lhs.next_to(ratio, LEFT) two_to_t_plus_dt = VGroup(*ratio[:4]) two_to_t = VGroup(*ratio[5:7]) two_to_t_two_to_dt = TexMobject( "%s^"%base_str, "t", "%s^"%base_str, "{dt}" ) two_to_t_two_to_dt.move_to(two_to_t_plus_dt, DOWN+LEFT) exp_prop_brace = Brace(two_to_t_two_to_dt, UP) one = TexMobject("1") one.move_to(ratio[5], DOWN) lp, rp = parens = TexMobject("()") parens.stretch(1.3, 1) parens.set_height(ratio.get_height()) lp.next_to(ratio, LEFT, buff = 0) rp.next_to(ratio, RIGHT, buff = 0) extracted_two_to_t = TexMobject("%s^"%base_str, "t") extracted_two_to_t.next_to(lp, LEFT, buff = SMALL_BUFF) expressions = [ ratio, two_to_t_two_to_dt, extracted_two_to_t, lhs, func_def ] for expression in expressions: expression.set_color_by_tex("t", YELLOW) expression.set_color_by_tex("dt", GREEN) #Apply exponential property self.play( Write(ratio), Write(lhs), self.pi_creature.change_mode, "raise_right_hand" ) self.wait(2) self.play( two_to_t_plus_dt.next_to, exp_prop_brace, UP, self.pi_creature.change_mode, "pondering" ) self.play( ReplacementTransform( two_to_t_plus_dt.copy(), two_to_t_two_to_dt, run_time = 2, path_arc = np.pi, ), FadeIn(exp_prop_brace) ) self.wait(2) #Talk about exponential property add_exp_rect, mult_rect = rects = [ Rectangle( stroke_color = BLUE, stroke_width = 2, ).replace(mob).scale_in_place(1.1) for mob in [ VGroup(*two_to_t_plus_dt[1:]), two_to_t_two_to_dt ] ] words = VGroup(*[ TextMobject(s, " ideas") for s in ("Additive", "Multiplicative") ]) words[0].move_to(words[1], LEFT) words.set_color(BLUE) words.next_to(two_to_t_plus_dt, RIGHT, buff = 1.5*LARGE_BUFF) arrows = VGroup(*[ Arrow(word.get_left(), rect, color = words.get_color()) for word, rect in zip(words, rects) ]) self.play(ShowCreation(add_exp_rect)) self.wait() self.play(ReplacementTransform( add_exp_rect.copy(), mult_rect )) self.wait() self.change_mode("happy") self.play(Write(words[0], run_time = 2)) self.play(ShowCreation(arrows[0])) self.wait() self.play( Transform(*words), Transform(*arrows), ) self.wait(2) self.play(*list(map(FadeOut, [ words[0], arrows[0], add_exp_rect, mult_rect, two_to_t_plus_dt, exp_prop_brace, ]))) #Factor out 2^t self.play(*[ FadeIn( mob, run_time = 2, rate_func = squish_rate_func(smooth, 0.5, 1) ) for mob in (one, lp, rp) ] + [ ReplacementTransform( mob, extracted_two_to_t, path_arc = np.pi/2, run_time = 2, ) for mob in (two_to_t, VGroup(*two_to_t_two_to_dt[:2])) ] + [ lhs.next_to, extracted_two_to_t, LEFT ]) self.change_mode("pondering") shifter = VGroup(ratio[4], one, *two_to_t_two_to_dt[2:]) stretcher = VGroup(lp, ratio[7], rp) self.play( shifter.next_to, ratio[7], UP, stretcher.stretch_in_place, 0.9, 0 ) self.wait(2) #Ask about dt -> 0 brace = Brace(VGroup(extracted_two_to_t, ratio), DOWN) alt_brace = Brace(parens, DOWN) dt_to_zero = TexMobject("dt", "\\to 0") dt_to_zero.set_color_by_tex("dt", GREEN) dt_to_zero.next_to(brace, DOWN) self.play(GrowFromCenter(brace)) self.play(Write(dt_to_zero)) self.wait(2) #Who cares randy = Randolph() randy.scale(0.7) randy.to_edge(DOWN) self.play( FadeIn(randy), self.pi_creature.change_mode, "plain", ) self.play(PiCreatureSays( randy, "Who cares?", bubble_kwargs = {"direction" : LEFT}, target_mode = "angry", )) self.wait(2) self.play( RemovePiCreatureBubble(randy), FadeOut(randy), self.pi_creature.change_mode, "hooray", self.pi_creature.look_at, parens ) self.play( Transform(brace, alt_brace), dt_to_zero.next_to, alt_brace, DOWN ) self.wait() #Highlight separation rects = [ Rectangle( stroke_color = color, stroke_width = 2, ).replace(mob, stretch = True).scale_in_place(1.1) for mob, color in [ (VGroup(parens, dt_to_zero), GREEN), (extracted_two_to_t, YELLOW), ] ] self.play(ShowCreation(rects[0])) self.wait(2) self.play(ReplacementTransform(rects[0].copy(), rects[1])) self.change_mode("happy") self.wait() self.play(*list(map(FadeOut, rects))) #Plug in specific values static_constant = self.try_specific_dt_values() constant = static_constant.copy() #Replace with actual constant limit_term = VGroup( brace, dt_to_zero, ratio[4], one, rects[0], *ratio[7:]+two_to_t_two_to_dt[2:] ) self.play(FadeIn(rects[0])) self.play(limit_term.to_corner, DOWN+LEFT) self.play( lp.stretch, 0.5, 1, lp.stretch, 0.8, 0, lp.next_to, extracted_two_to_t[0], RIGHT, rp.stretch, 0.5, 1, rp.stretch, 0.8, 0, rp.next_to, lp, RIGHT, SMALL_BUFF, rp.shift, constant.get_width()*RIGHT, constant.next_to, extracted_two_to_t[0], RIGHT, MED_LARGE_BUFF ) self.wait() self.change_mode("confused") self.wait() #Indicate distinction between dt group and t group again for mob in limit_term, extracted_two_to_t: self.play(FocusOn(mob)) self.play(Indicate(mob)) self.wait() #hold_final_value derivative = VGroup( lhs, extracted_two_to_t, parens, constant ) func_def_rhs = VGroup(*func_def[-2:]).copy() func_lp, func_rp = func_parens = TexMobject("()") func_parens.set_fill(opacity = 0) func_lp.next_to(func_def_rhs[0], LEFT, buff = 0) func_rp.next_to(func_lp, RIGHT, buff = func_def_rhs.get_width()) func_def_rhs.add(func_parens) M = lhs[0][1] self.play( FadeOut(M), func_def_rhs.move_to, M, LEFT, func_def_rhs.set_fill, None, 1, ) lhs[0].submobjects[1] = func_def_rhs self.wait() self.play( derivative.next_to, self.pi_creature, UP, derivative.to_edge, RIGHT, self.pi_creature.change_mode, "raise_right_hand" ) self.wait(2) for mob in extracted_two_to_t, constant: self.play(Indicate(mob)) self.wait() self.wait(2) def try_specific_dt_values(self): expressions = [] for num_zeros in [1, 2, 4, 7]: dt_str = "0." + num_zeros*"0" + "1" dt_num = float(dt_str) output_num = (self.base**dt_num - 1) / dt_num output_str = "%.7f\\dots"%output_num expression = TexMobject( "{%s^"%self.base_str, "{%s}"%dt_str, "-1", "\\over \\,", "%s}"%dt_str, "=", output_str ) expression.set_color_by_tex(dt_str, GREEN) expression.set_color_by_tex(output_str, BLUE) expression.to_corner(UP+RIGHT) expressions.append(expression) curr_expression = expressions[0] self.play( Write(curr_expression), self.pi_creature.change_mode, "pondering" ) self.wait(2) for expression in expressions[1:]: self.play(Transform(curr_expression, expression)) self.wait(2) return curr_expression[-1] class ExponentRatioWithThree(AnalyzeExponentRatio): CONFIG = { "base" : 3, "base_str" : "3", } class ExponentRatioWithSeven(AnalyzeExponentRatio): CONFIG = { "base" : 7, "base_str" : "7", } class ExponentRatioWithEight(AnalyzeExponentRatio): CONFIG = { "base" : 8, "base_str" : "8", } class ExponentRatioWithE(AnalyzeExponentRatio): CONFIG = { "base" : np.exp(1), "base_str" : "e", } class CompareTwoConstantToEightConstant(PiCreatureScene): def construct(self): two_deriv, eight_deriv = derivs = VGroup(*[ self.get_derivative_expression(base) for base in (2, 8) ]) derivs.arrange( DOWN, buff = 1.5, aligned_edge = LEFT ) derivs.to_edge(LEFT, LARGE_BUFF).shift(UP) arrow = Arrow(*[deriv[-2] for deriv in derivs]) times_three = TexMobject("\\times 3") times_three.next_to(arrow, RIGHT) why = TextMobject("Why?") why.next_to(self.pi_creature, UP, MED_LARGE_BUFF) self.add(eight_deriv) self.wait() self.play(ReplacementTransform( eight_deriv.copy(), two_deriv )) self.wait() self.play(ShowCreation(arrow)) self.play( Write(times_three), self.pi_creature.change_mode, "thinking" ) self.wait(3) self.play( Animation(derivs), Write(why), self.pi_creature.change, "confused", derivs ) self.wait() for deriv in derivs: for index in -5, -2: self.play(Indicate(deriv[index])) self.wait() self.wait(2) def get_derivative_expression(self, base): base_str = str(base) const_str = "%.4f\\dots"%np.log(base) result = TexMobject( "{d(", base_str, "^t", ")", "\\over", "dt}", "=", base_str, "^t", "(", const_str, ")" ) tex_color_paris = [ ("t", YELLOW), ("dt", GREEN), (const_str, BLUE) ] for tex, color in tex_color_paris: result.set_color_by_tex(tex, color) return result def create_pi_creature(self): self.pi_creature = Randolph().flip() self.pi_creature.to_edge(DOWN).shift(3*RIGHT) return self.pi_creature class AskAboutConstantOne(TeacherStudentsScene): def construct(self): note = TexMobject( "{ d(a^", "t", ")", "\\over \\,", "dt}", "=", "a^", "t", "(\\text{Some constant})" ) note.set_color_by_tex("t", YELLOW) note.set_color_by_tex("dt", GREEN) note.set_color_by_tex("constant", BLUE) note.to_corner(UP+LEFT) self.add(note) self.student_says( "Is there a base where\\\\", "that constant is 1?" ) self.change_student_modes( "pondering", "raise_right_hand", "thinking", # look_at_arg = self.get_students()[1].bubble ) self.wait(2) self.play(FadeOut(note[-1], run_time = 3)) self.wait() self.teacher_says( "There is!\\\\", "$e = 2.71828\\dots$", target_mode = "hooray" ) self.change_student_modes(*["confused"]*3) self.wait(3) class WhyPi(PiCreatureScene): def construct(self): circle = Circle(radius = 1, color = MAROON_B) circle.rotate(np.pi/2) circle.to_edge(UP) ghost_circle = circle.copy() ghost_circle.set_stroke(width = 1) diam = Line(circle.get_left(), circle.get_right()) diam.set_color(YELLOW) one = TexMobject("1") one.next_to(diam, UP) circum = diam.copy() circum.set_color(circle.get_color()) circum.scale(np.pi) circum.next_to(circle, DOWN, LARGE_BUFF) circum.insert_n_curves(circle.get_num_curves()-2) circum.make_jagged() pi = TexMobject("\\pi") pi.next_to(circum, UP) why = TextMobject("Why?") why.next_to(self.pi_creature, UP, MED_LARGE_BUFF) self.add(ghost_circle, circle, diam, one) self.wait() self.play(Transform(circle, circum, run_time = 2)) self.play( Write(pi), Write(why), self.pi_creature.change_mode, "confused", ) self.wait(3) ####### def create_pi_creature(self): self.pi_creature = Randolph() self.pi_creature.to_corner(DOWN+LEFT) return self.pi_creature class GraphOfExp(GraphScene): CONFIG = { "x_min" : -3, "x_max" : 3, "x_tick_frequency" : 1, "x_axis_label" : "t", "x_labeled_nums" : list(range(-3, 4)), "x_axis_width" : 11, "graph_origin" : 2*DOWN + LEFT, "example_inputs" : [1, 2], "small_dx" : 0.01, } def construct(self): self.setup_axes() self.show_slopes() def show_slopes(self): graph = self.get_graph(np.exp) graph_label = self.get_graph_label( graph, "e^t", direction = LEFT ) graph_label.shift(MED_SMALL_BUFF*LEFT) start_input, target_input = self.example_inputs ss_group = self.get_secant_slope_group( start_input, graph, dx = self.small_dx, dx_label = "dt", df_label = "d(e^t)", secant_line_color = YELLOW, ) v_lines = [ self.get_vertical_line_to_graph( x, graph, color = WHITE, ) for x in self.example_inputs ] height_labels = [ TexMobject("e^%d"%x).next_to(vl, RIGHT, SMALL_BUFF) for vl, x in zip(v_lines, self.example_inputs) ] slope_labels = [ TextMobject( "Slope = $e^%d$"%x ).next_to(vl.get_top(), UP+RIGHT).shift(0.7*RIGHT/x) for vl, x in zip(v_lines, self.example_inputs) ] self.play( ShowCreation(graph, run_time = 2), Write( graph_label, rate_func = squish_rate_func(smooth, 0.5, 1), ) ) self.wait() self.play(*list(map(ShowCreation, ss_group))) self.play(Write(slope_labels[0])) self.play(ShowCreation(v_lines[0])) self.play(Write(height_labels[0])) self.wait(2) self.animate_secant_slope_group_change( ss_group, target_x = target_input, run_time = 2, added_anims = [ Transform( *pair, path_arc = np.pi/6, run_time = 2 ) for pair in [ slope_labels, v_lines, height_labels, ] ] ) self.wait(2) self.graph = graph self.ss_group = ss_group class Chapter4Wrapper(Scene): def construct(self): title = TextMobject("Chapter 4 chain rule intuition") title.to_edge(UP) rect = Rectangle(width = 16, height = 9) rect.set_height(1.5*FRAME_Y_RADIUS) rect.next_to(title, DOWN) self.add(title) self.play(ShowCreation(rect)) self.wait(3) class ApplyChainRule(TeacherStudentsScene): def construct(self): deriv_equation = TexMobject( "{d(", "e^", "{3", "t}", ")", "\\over", "dt}", "=", "3", "e^", "{3", "t}", ) deriv_equation.next_to(self.teacher, UP+LEFT) deriv_equation.shift(UP) deriv_equation.set_color_by_tex("3", BLUE) deriv = VGroup(*deriv_equation[:7]) exponent = VGroup(*deriv_equation[-2:]) circle = Circle(color = YELLOW) circle.replace(exponent, stretch = True) circle.scale_in_place(1.5) self.teacher_says("Think of the \\\\ chain rule") self.change_student_modes(*["pondering"]*3) self.play( Write(deriv), RemovePiCreatureBubble( self.teacher, target_mode = "raise_right_hand" ), ) self.wait(2) self.play(*[ Transform( *deriv_equation.get_parts_by_tex( tex, substring = False ).copy()[:2], path_arc = -np.pi, run_time = 2 ) for tex in ("e^", "{3", "t}") ] + [ Write(deriv_equation.get_part_by_tex("=")) ]) self.play(self.teacher.change_mode, "happy") self.wait() self.play(ShowCreation(circle)) self.play(Transform( *deriv_equation.get_parts_by_tex("3").copy()[-1:-3:-1] )) self.play(FadeOut(circle)) self.wait(3) class ChainRuleIntuition(ThreeLinesChainRule): CONFIG = { "line_configs" : [ { "func" : lambda t : t, "func_label" : "t", "triangle_color" : WHITE, "center_y" : 3, "x_min" : 0, "x_max" : 3, "numbers_to_show" : list(range(4)), "numbers_with_elongated_ticks" : list(range(4)), "tick_frequency" : 1, }, { "func" : lambda t : 3*t, "func_label" : "3t", "triangle_color" : GREEN, "center_y" : 0.5, "x_min" : 0, "x_max" : 3, "numbers_to_show" : list(range(0, 4)), "numbers_with_elongated_ticks" : list(range(4)), "tick_frequency" : 1, }, { "func" : lambda t : np.exp(3*t), "func_label" : "e^{3t}", "triangle_color" : BLUE, "center_y" : -2, "x_min" : 0, "x_max" : 10, "numbers_to_show" : list(range(0, 11, 3)), "numbers_with_elongated_ticks" : list(range(11)), "tick_frequency" : 1, }, ], "example_x" : 0.4, "start_x" : 0.4, "max_x" : 0.6, "min_x" : 0.2, } def construct(self): self.introduce_line_group() self.nudge_x() def nudge_x(self): lines, labels = self.line_group def get_value_points(): return [ label[0].get_bottom() for label in labels ] starts = get_value_points() self.animate_x_change(self.example_x + self.dx, run_time = 0) ends = get_value_points() self.animate_x_change(self.example_x, run_time = 0) nudge_lines = VGroup() braces = VGroup() numbers = VGroup() for start, end, line, label, config in zip(starts, ends, lines, labels, self.line_configs): color = label[0].get_color() nudge_line = Line(start, end) nudge_line.set_stroke(color, width = 6) brace = Brace(nudge_line, DOWN, buff = SMALL_BUFF) brace.set_color(color) func_label = config["func_label"] if len(func_label) == 1: text = "$d%s$"%func_label else: text = "$d(%s)$"%func_label brace.text = brace.get_text(text, buff = SMALL_BUFF) brace.text.set_color(color) brace.add(brace.text) line.add(nudge_line) nudge_lines.add(nudge_line) braces.add(brace) numbers.add(line.numbers) line.remove(*line.numbers) dt_brace, d3t_brace, dexp3t_brace = braces self.play(*list(map(FadeIn, [nudge_lines, braces]))) self.wait() for count in range(3): for dx in self.dx, 0: self.animate_x_change( self.example_x + dx, run_time = 2 ) self.wait() class WhyNaturalLogOf2ShowsUp(TeacherStudentsScene): def construct(self): self.add_e_to_the_three_t() self.show_e_to_log_2() def add_e_to_the_three_t(self): exp_c = self.get_exp_C("c") exp_c.next_to(self.teacher, UP+LEFT) self.play( FadeIn( exp_c, run_time = 2, lag_ratio = 0.5 ), self.teacher.change, "raise_right_hand" ) self.wait() self.look_at(4*LEFT + UP) self.wait(3) self.exp_c = exp_c def show_e_to_log_2(self): equation = TexMobject( "2", "^t", "= e^", "{\\ln(2)", "t}" ) equation.move_to(self.exp_c) t_group = equation.get_parts_by_tex("t") non_t_group = VGroup(*equation) non_t_group.remove(*t_group) log_words = TextMobject("``$e$ to the ", "\\emph{what}", "equals 2?''") log_words.set_color_by_tex("what", BLUE) log_words.next_to(equation, UP+LEFT) log_words_arrow = Arrow( log_words.get_right(), equation.get_part_by_tex("ln(2)").get_corner(UP+LEFT), color = BLUE, ) derivative = TexMobject( "\\ln(2)", "2", "^t", "=", "\\ln(2)", "e^", "{\\ln(2)", "t}" ) derivative.move_to(equation) for tex_mob in equation, derivative: tex_mob.set_color_by_tex("ln(2)", BLUE) tex_mob.set_color_by_tex("t", YELLOW) derivative_arrow = Arrow(1.5*UP, ORIGIN, buff = 0) derivative_arrow.set_color(WHITE) derivative_arrow.next_to( derivative.get_parts_by_tex("="), UP ) derivative_symbol = TextMobject("Derivative") derivative_symbol.next_to(derivative_arrow, RIGHT) self.play( Write(non_t_group), self.exp_c.next_to, equation, LEFT, 2*LARGE_BUFF, self.exp_c.to_edge, UP, ) self.change_student_modes("confused", "sassy", "erm") self.play( Write(log_words), ShowCreation( log_words_arrow, run_time = 2, rate_func = squish_rate_func(smooth, 0.5, 1) ) ) self.change_student_modes( *["pondering"]*3, look_at_arg = log_words ) self.wait(2) t_group.save_state() t_group.shift(UP) t_group.set_fill(opacity = 0) self.play( ApplyMethod( t_group.restore, run_time = 2, lag_ratio = 0.5, ), self.teacher.change_mode, "speaking" ) self.wait(2) self.play(FocusOn(self.exp_c)) self.play(Indicate(self.exp_c, scale_factor = 1.05)) self.wait(2) self.play( equation.next_to, derivative_arrow, UP, equation.shift, MED_SMALL_BUFF*RIGHT, FadeOut(VGroup(log_words, log_words_arrow)), self.teacher.change_mode, "raise_right_hand", ) self.play( ShowCreation(derivative_arrow), Write(derivative_symbol), Write(derivative) ) self.wait(3) self.play(self.teacher.change_mode, "happy") self.wait(2) student = self.get_students()[1] ln = derivative.get_part_by_tex("ln(2)").copy() rhs = TexMobject("=%s"%self.get_log_str(2)) self.play( ln.next_to, student, UP+LEFT, MED_LARGE_BUFF, student.change_mode, "raise_left_hand", ) rhs.next_to(ln, RIGHT) self.play(Write(rhs)) self.wait(2) ###### def get_exp_C(self, C): C_str = str(C) result = TexMobject( "{d(", "e^", "{%s"%C_str, "t}", ")", "\\over", "dt}", "=", C_str, "e^", "{%s"%C_str, "t}", ) result.set_color_by_tex(C_str, BLUE) result.C_str = C_str return result def get_a_to_t(self, a): a_str = str(a) log_str = self.get_log_str(a) result = TexMobject( "{d(", a_str, "^t", ")", "\\over", "dt}", "=", log_str, a_str, "^t" ) result.set_color_by_tex(log_str, BLUE) return result def get_log_str(self, a): return "%.4f\\dots"%np.log(float(a)) class CompareWaysToWriteExponentials(GraphScene): CONFIG = { "y_max" : 50, "y_tick_frequency" : 5, "x_max" : 7, } def construct(self): self.setup_axes() bases = list(range(2, 7)) graphs = [ self.get_graph(lambda t : base**t, color = GREEN) for base in bases ] graph = graphs[0] a_to_t = TexMobject("a^t") a_to_t.move_to(self.coords_to_point(6, 45)) cross = TexMobject("\\times") cross.set_color(RED) cross.replace(a_to_t, stretch = True) e_to_ct = TexMobject("e^", "{c", "t}") e_to_ct.set_color_by_tex("c", BLUE) e_to_ct.scale(1.5) e_to_ct.next_to(a_to_t, DOWN) equations = VGroup() for base in bases: log_str = "%.4f\\dots"%np.log(base) equation = TexMobject( str(base), "^t", "=", "e^", "{(%s)"%log_str, "t}", ) equation.set_color_by_tex(log_str, BLUE) equation.scale(1.2) equations.add(equation) equation = equations[0] equations.next_to(e_to_ct, DOWN, LARGE_BUFF, LEFT) self.play( ShowCreation(graph), Write( a_to_t, rate_func = squish_rate_func(smooth, 0.5, 1) ), run_time = 2 ) self.play(Write(cross, run_time = 2)) self.play(Write(e_to_ct, run_time = 2)) self.wait(2) self.play(Write(equation)) self.wait(2) for new_graph, new_equation in zip(graphs, equations)[1:]: self.play( Transform(graph, new_graph), Transform(equation, new_equation) ) self.wait(2) self.wait() class ManyExponentialForms(TeacherStudentsScene): def construct(self): lhs = TexMobject("2", "^t") rhs_list = [ TexMobject("=", "%s^"%tex, "{(%.5f\\dots)"%log, "t}") for tex, log in [ ("e", np.log(2)), ("\\pi", np.log(2)/np.log(np.pi)), ("42", np.log(2)/np.log(42)), ] ] group = VGroup(lhs, *rhs_list) group.arrange(RIGHT) group.set_width(FRAME_WIDTH - LARGE_BUFF) group.next_to(self.get_pi_creatures(), UP, 2*LARGE_BUFF) for part in group: part.set_color_by_tex("t", YELLOW) const = part.get_part_by_tex("dots") if const: const.set_color(BLUE) brace = Brace(const, UP) log = brace.get_text( "$\\log_{%s}(2)$"%part[1].get_tex_string()[:-1] ) log.set_color(BLUE) part.add(brace, log) exp = VGroup(*rhs_list[0][1:4]) rect = BackgroundRectangle(group) self.add(lhs, rhs_list[0]) self.wait() for rhs in rhs_list[1:]: self.play(FadeIn( rhs, run_time = 2, lag_ratio = 0.5, )) self.wait(2) self.wait() self.play( FadeIn(rect), exp.next_to, self.teacher, UP+LEFT, self.teacher.change, "raise_right_hand", ) self.play(*[ ApplyFunction( lambda m : m.shift(SMALL_BUFF*UP).set_color(RED), part, run_time = 2, rate_func = squish_rate_func(there_and_back, a, a+0.3) ) for part, a in zip(exp[1], np.linspace(0, 0.7, len(exp[1]))) ]) self.change_student_modes( *["pondering"]*3, look_at_arg = exp ) self.wait(3) class TooManySymbols(TeacherStudentsScene): def construct(self): self.student_says( "Too symbol heavy!", target_mode = "pleading" ) self.play(self.teacher.change_mode, "guilty") self.wait(3) class TemperatureOverTimeOfWarmWater(GraphScene): CONFIG = { "x_min" : 0, "x_axis_label" : "$t$", "y_axis_label" : "Temperature", "T_room" : 4, "include_solution" : False, } def construct(self): self.setup_axes() graph = self.get_graph( lambda t : 3*np.exp(-0.3*t) + self.T_room, color = RED ) h_line = DashedLine(*[ self.coords_to_point(x, self.T_room) for x in (self.x_min, self.x_max) ]) T_room_label = TexMobject("T_{\\text{room}}") T_room_label.next_to(h_line, LEFT) ode = TexMobject( "\\frac{d\\Delta T}{dt} = -k \\Delta T" ) ode.to_corner(UP+RIGHT) solution = TexMobject( "\\Delta T(", "t", ") = e", "^{-k", "t}" ) solution.next_to(ode, DOWN, MED_LARGE_BUFF) solution.set_color_by_tex("t", YELLOW) solution.set_color_by_tex("Delta", WHITE) delta_T_brace = Brace(graph, RIGHT) delta_T_label = TexMobject("\\Delta T") delta_T_group = VGroup(delta_T_brace, delta_T_label) def update_delta_T_group(group): brace, label = group v_line = Line( graph.points[-1], graph.points[-1][0]*RIGHT + h_line.get_center()[1]*UP ) brace.set_height(v_line.get_height()) brace.next_to(v_line, RIGHT, SMALL_BUFF) label.set_height(min( label.get_height(), brace.get_height() )) label.next_to(brace, RIGHT, SMALL_BUFF) self.add(ode) self.play( Write(T_room_label), ShowCreation(h_line, run_time = 2) ) if self.include_solution: self.play(Write(solution)) graph_growth = ShowCreation(graph, rate_func=linear) delta_T_group_update = UpdateFromFunc( delta_T_group, update_delta_T_group ) self.play( GrowFromCenter(delta_T_brace), Write(delta_T_label), ) self.play(graph_growth, delta_T_group_update, run_time = 15) self.wait(2) class TemperatureOverTimeOfWarmWaterWithSolution(TemperatureOverTimeOfWarmWater): CONFIG = { "include_solution" : True } class InvestedMoney(Scene): def construct(self): # cash_str = "\\$\\$\\$" cash_str = "M" equation = TexMobject( "{d", cash_str, "\\over", "dt}", "=", "(1 + r)", cash_str ) equation.set_color_by_tex(cash_str, GREEN) equation.next_to(ORIGIN, LEFT) equation.to_edge(UP) arrow = Arrow(LEFT, RIGHT, color = WHITE) arrow.next_to(equation) solution = TexMobject( cash_str, "(", "t", ")", "=", "e^", "{(1+r)", "t}" ) solution.set_color_by_tex("t", YELLOW) solution.set_color_by_tex(cash_str, GREEN) solution.next_to(arrow, RIGHT) cash = TexMobject("\\$") cash_pile = VGroup(*[ cash.copy().shift( x*(1+MED_SMALL_BUFF)*cash.get_width()*RIGHT +\ y*(1+MED_SMALL_BUFF)*cash.get_height()*UP ) for x in range(40) for y in range(8) ]) cash_pile.set_color(GREEN) cash_pile.center() cash_pile.shift(DOWN) anims = [] cash_size = len(cash_pile) run_time = 10 const = np.log(cash_size)/run_time for i, cash in enumerate(cash_pile): start_time = np.log(i+1)/const prop = start_time/run_time rate_func = squish_rate_func( smooth, np.clip(prop-0.5/run_time, 0, 1), np.clip(prop+0.5/run_time, 0, 1), ) anims.append(GrowFromCenter( cash, rate_func = rate_func, )) self.add(equation) self.play(*anims, run_time = run_time) self.wait() self.play(ShowCreation(arrow)) self.play(Write(solution, run_time = 2)) self.wait() self.play(FadeOut(cash_pile)) self.play(*anims, run_time = run_time) self.wait() class NaturalLog(Scene): def construct(self): expressions = VGroup(*list(map(self.get_expression, [2, 3, 7]))) expressions.arrange(DOWN, buff = MED_SMALL_BUFF) expressions.to_edge(LEFT) self.play(FadeIn( expressions, run_time = 3, lag_ratio = 0.5 )) self.wait() self.play( expressions.set_fill, None, 1, run_time = 2, lag_ratio = 0.5 ) self.wait() for i in 0, 2, 1: self.show_natural_loggedness(expressions[i]) def show_natural_loggedness(self, expression): base, constant = expression[1], expression[-3] log_constant, exp_constant = constant.copy(), constant.copy() log_base, exp_base = base.copy(), base.copy() log_equals, exp_equals = list(map(TexMobject, "==")) ln = TexMobject("\\ln(2)") log_base.move_to(ln[-2]) ln.remove(ln[-2]) log_equals.next_to(ln, LEFT) log_constant.next_to(log_equals, LEFT) log_expression = VGroup( ln, log_constant, log_equals, log_base ) e = TexMobject("e") exp_constant.scale(0.7) exp_constant.next_to(e, UP+RIGHT, buff = 0) exp_base.next_to(exp_equals, RIGHT) VGroup(exp_base, exp_equals).next_to( VGroup(e, exp_constant), RIGHT, aligned_edge = DOWN ) exp_expression = VGroup( e, exp_constant, exp_equals, exp_base ) for group, vect in (log_expression, UP), (exp_expression, DOWN): group.to_edge(RIGHT) group.shift(vect) self.play( ReplacementTransform(base.copy(), log_base), ReplacementTransform(constant.copy(), log_constant), run_time = 2 ) self.play(Write(ln), Write(log_equals)) self.wait() self.play( ReplacementTransform( log_expression.copy(), exp_expression, run_time = 2, ) ) self.wait(2) ln_a = expression[-1] self.play( FadeOut(expression[-2]), FadeOut(constant), ln_a.move_to, constant, LEFT, ln_a.set_color, BLUE ) self.wait() self.play(*list(map(FadeOut, [log_expression, exp_expression]))) self.wait() def get_expression(self, base): expression = TexMobject( "{d(", "%d^"%base, "t", ")", "\\over \\,", "dt}", "=", "%d^"%base, "t", "(%.4f\\dots)"%np.log(base), ) expression.set_color_by_tex("t", YELLOW) expression.set_color_by_tex("dt", GREEN) expression.set_color_by_tex("\\dots", BLUE) brace = Brace(expression.get_part_by_tex("\\dots"), UP) brace_text = brace.get_text("$\\ln(%d)$"%base) for mob in brace, brace_text: mob.set_fill(opacity = 0) expression.add(brace, brace_text) return expression class NextVideo(TeacherStudentsScene): def construct(self): series = VideoSeries() series.to_edge(UP) this_video = series[3] next_video = series[4] brace = Brace(this_video, DOWN) this_video.save_state() this_video.set_color(YELLOW) this_tex = TexMobject( "{d(", "a^t", ") \\over dt} = ", "a^t", "\\ln(a)" ) this_tex[1][1].set_color(YELLOW) this_tex[3][1].set_color(YELLOW) this_tex.next_to(brace, DOWN) next_tex = VGroup(*list(map(TextMobject, [ "Chain rule", "Product rule", "$\\vdots$" ]))) next_tex.arrange(DOWN) next_tex.next_to(brace, DOWN) next_tex.shift( next_video.get_center()[0]*RIGHT\ -next_tex.get_center()[0]*RIGHT ) self.add(series, brace, *this_tex[:3]) self.change_student_modes( "confused", "pondering", "erm", look_at_arg = this_tex ) self.play(ReplacementTransform( this_tex[1].copy(), this_tex[3] )) self.wait() self.play( Write(this_tex[4]), ReplacementTransform( this_tex[3][0].copy(), this_tex[4][3], path_arc = np.pi, remover = True ) ) self.wait(2) self.play(this_tex.replace, this_video) self.play( brace.next_to, next_video, DOWN, this_video.restore, Animation(this_tex), next_video.set_color, YELLOW, Write(next_tex), self.get_teacher().change_mode, "raise_right_hand" ) self.change_student_modes( *["pondering"]*3, look_at_arg = next_tex ) self.wait(3) class ExpPatreonThanks(PatreonThanks): CONFIG = { "specific_patrons" : [ "Ali Yahya", "Meshal Alshammari", "CrypticSwarm ", "Kathryn Schmiedicke", "Nathan Pellegrin", "Karan Bhargava", "Justin Helps", "Ankit Agarwal", "Yu Jun", "Dave Nicponski", "Damion Kistler", "Juan Benet", "Othman Alikhan", "Justin Helps", "Markus Persson", "Dan Buchoff", "Derek Dai", "Joseph John Cox", "Luc Ritchie", "Mustafa Mahdi", "Daan Smedinga", "Jonathan Eppele", "Albert Nguyen", "Nils Schneider", "Mustafa Mahdi", "Mathew Bramson", "Guido Gambardella", "Jerry Ling", "Mark Govea", "Vecht", "Shimin Kuang", "Rish Kundalia", "Achille Brighton", "Kirk Werklund", "Ripta Pasay", "Felipe Diniz", ] } class Thumbnail(GraphOfTwoToT): CONFIG = { "x_axis_label" : "", "y_axis_label" : "", "x_labeled_nums" : None, "y_labeled_nums" : None, "y_max" : 32, "y_tick_frequency" : 4, "graph_origin" : 3*DOWN + 5*LEFT, "x_axis_width" : 12, } def construct(self): derivative = TexMobject( "\\frac{d(a^t)}{dt} =", "a^t \\ln(a)" ) derivative[0][3].set_color(YELLOW) derivative[1][1].set_color(YELLOW) derivative[0][2].set_color(BLUE) derivative[1][0].set_color(BLUE) derivative[1][5].set_color(BLUE) derivative.scale(2) derivative.add_background_rectangle() derivative.to_corner(DOWN+RIGHT, buff = MED_SMALL_BUFF) # brace = Brace(Line(LEFT, RIGHT), UP) # brace.set_width(derivative[1].get_width()) # brace.next_to(derivative[1], UP) # question = TextMobject("Why?") # question.scale(2.5) # question.next_to(brace, UP) # randy = Randolph() # randy.scale(1.3) # randy.next_to(ORIGIN, LEFT).to_edge(DOWN) # randy.change_mode("pondering") question = TextMobject("What is $e\\,$?") e = question[-2] e.scale(1.2, about_point = e.get_bottom()) e.set_color(BLUE) question.scale(3) question.add_background_rectangle() question.to_edge(UP) # randy.look_at(question) self.setup_axes() graph = self.get_graph(np.exp) graph.set_stroke(YELLOW, 8) self.add(graph, question, derivative)