Exemple #1
0
    def construct(self):
        circle = manim.Circle()
        circle.set_fill(manim.PINK, opacity=0.5)

        square = manim.Square()
        square.flip(manim.RIGHT)
        square.rotate(-3 * manim.TAU / 8)

        self.play(manim.ShowCreation(square))
        self.play(manim.Transform(square, circle))
        self.play(manim.FadeOut(square))
Exemple #2
0
    def construct_def_box(self):
        """Construct the function's definition in a box"""
        fact = self.get_def()
        rect = ThinRectangle().surround(fact, stretch=True)

        self.play(m.Write(fact))
        self.play(m.ShowCreation(rect))

        self.def_box = m.VDict([("function", fact), ("box", rect)])
        self.def_box.generate_target().scale(self.def_scale_ratio).to_corner(
            m.UL)

        self.play(m.MoveToTarget(self.def_box))
Exemple #3
0
    def construct_def_box(self) -> None:
        """Show the creation of the OCaml definiton, with a box"""
        # Create the function definition and its rectangular box
        self.def_box = m.VDict([("function", self.get_def())])
        self.def_box.add([
            ("box",
             ThinRectangle(height=1.5).surround(self.def_box["function"]))
        ])

        # Animate the creations
        self.play(m.Write(self.def_box["function"]))
        self.play(m.ShowCreation(self.def_box["box"]))

        # Move and scale down to up-left corner of the scene
        self.def_box.generate_target()
        self.def_box.target.scale(self.def_scale_ratio).to_corner(m.UL)
        self.play(m.MoveToTarget(self.def_box))
Exemple #4
0
    def construct_call(self, val: int) -> None:
        """Show how a call to the function with the given argument is evaluated"""
        call = m.VDict([
            ("name", m.Tex("\\verb|fact|").shift(m.LEFT * 5 + m.DOWN * 0.7)),
            ("val", m.Tex(f"\\verb|{val}|")),
        ])
        call["val"].next_to(call["name"], m.RIGHT, aligned_edge=m.UP)
        self.play(m.FadeIn(call))

        # Show the first call
        def_instance = deepcopy(self.def_box["function"]).remove("fn")
        def_instance.generate_target().scale(1 / self.def_scale_ratio).next_to(
            call, m.RIGHT * 5)
        lines = m.VGroup(
            ThinLine(
                call.get_corner(m.RIGHT) + m.RIGHT * 0.2,
                def_instance.target.get_corner(m.LEFT) + m.LEFT * 0.2,
                color=m.BLUE,
            ),
            ThinLine(
                def_instance.target.get_corner(m.DL) + m.LEFT * 0.2,
                def_instance.target.get_corner(m.UL) + m.LEFT * 0.2,
                color=m.BLUE,
            ),
        )
        self.wait()
        self.play(m.Indicate(self.def_box))
        self.play(
            m.MoveToTarget(def_instance),
            m.ShowCreation(lines),
        )
        self.wait()

        _, res_mobject = self.eval_call(def_instance, val, call["val"])

        self.play(m.FadeOut(call), m.FadeOut(lines),
                  m.ApplyMethod(res_mobject.center))
Exemple #5
0
    def construct_call(self, val: int) -> None:
        """Show how a call to the OCaml function is evaluated

        val: the argument given to square_of_pred
        """
        call = m.VDict([
            ("name", m.Tex("\\verb|square_of_pred|").shift(m.LEFT * 2)),
            ("val", m.Tex(f"\\verb|{val}|")),
        ])
        call["val"].next_to(call["name"], m.RIGHT, aligned_edge=m.UP)
        self.play(m.FadeIn(call))

        # Shift the call and show instanciated definition of the function
        def_instance = deepcopy(self.def_box["function"]).remove("fn")
        def_instance.generate_target().scale(1 / self.def_scale_ratio).next_to(
            call, m.RIGHT * 5)
        lines = m.VGroup(
            ThinLine(
                call.get_corner(m.RIGHT) + m.RIGHT * 0.2,
                def_instance.target.get_corner(m.LEFT) + m.LEFT * 0.2,
                color=m.BLUE,
            ),
            ThinLine(
                def_instance.target.get_corner(m.DL) + m.LEFT * 0.2,
                def_instance.target.get_corner(m.UL) + m.LEFT * 0.2,
                color=m.BLUE,
            ),
        )
        self.wait()
        self.play(m.Indicate(self.def_box))
        self.play(
            m.MoveToTarget(def_instance),
            m.ShowCreation(lines),
        )
        self.wait()

        # Show context
        context = CallContext(def_instance, self)
        # add x=val to context
        context.add("x", call["val"])

        # Replace x by its value
        self.wait()
        context.replace_occurrence(-1, def_instance["pred"]["def"]["val"]["x"])
        self.wait()

        # Evaluate pred_x
        replace_expr(self, def_instance["pred"]["def"]["val"],
                     f"\\verb|{val-1}|")
        self.wait()
        # add pred_x=val-1 to context
        context.add(
            "pred\\_x",
            def_instance["pred"]["def"]["val"],
            highlight=def_instance["pred"],
            extra_animations=[
                m.FadeOutAndShift(def_instance["pred"], direction=m.UP),
                m.ApplyMethod(def_instance["res"].next_to, lines[1], m.RIGHT),
            ],
        )
        self.wait()

        # Replace pred_x by its value
        context.replace_occurrence(-1, def_instance["res"]["op2"])
        context.replace_occurrence(-1, def_instance["res"]["op1"])

        # Evaluate the result
        self.wait()
        replace_expr(
            self,
            def_instance["res"],
            f"\\verb|{(val-1) * (val-1)}|",
            aligned_edge=m.LEFT,
        )

        # Wrap up
        self.wait()
        self.play(
            m.FadeOut(context.entries),
            m.FadeOut(call),
            m.ApplyMethod(def_instance["res"].center),
            m.Uncreate(lines),
        )
Exemple #6
0
    def eval_call(self, call: m.Mobject, val: int,
                  val_mobject: m.Mobject) -> Tuple[int, m.Mobject]:
        """Show the evaluation of one function call, recursively

        call: the manim object representing the call, expected to be oneline
        val: the value of `n` for that call

        Returns the value and the corresponding Mobject of the result of the call
        """
        context = CallContext(call, self)
        context.add("n", val_mobject)
        self.wait()

        # Evaluate the if's condition
        context.replace_occurrence(-1, call["if"]["cond"]["n"])
        self.wait()
        replace_expr(self, call["if"]["cond"],
                     f"\\verb|{str(val == 0).lower()}|")

        # Replace the expression with the correct if branch
        self.wait()
        self.play(m.Indicate(call["if"]["cond"]))
        if val == 0:
            bad = "rec"
            good = "base"
        else:
            good = "rec"
            bad = "base"
        strike_through = ThinLine(
            call[bad].get_corner(m.DL) + m.DL * 0.1,
            call[bad].get_corner(m.UR) + m.UR * 0.1,
        )
        rect = ThinRectangle().surround(call[good], stretch=True)
        self.play(m.ShowCreation(strike_through), m.ShowCreation(rect))
        self.wait()
        self.play(
            *map(m.FadeOut,
                 [strike_through, rect, call["if"], call[bad], call["else"]]))
        self.play(
            m.ApplyMethod(call[good].next_to, call.get_corner(m.LEFT),
                          m.RIGHT * 0.1))

        if val == 0:  # end of recursion
            self.play(*map(m.FadeOut, context.entries))
            return 1, call["base"]

        # Evaluate the expression containing the recursive call up to the call, starting
        # by the right-hand operand of the multiplication
        self.wait()
        self.play(m.Indicate(call["rec"]["call"]))
        context.replace_occurrence(-1, call["rec"]["call"]["arg"]["n"])
        self.wait(m.DEFAULT_WAIT_TIME / 2)
        replace_expr(self,
                     call["rec"]["call"]["arg"],
                     f"\\verb|{val - 1}|",
                     aligned_edge=m.LEFT)
        # Evaluate the recursive call
        rect = ThinRectangle(color=m.BLUE).surround(call["rec"]["call"],
                                                    stretch=True)
        def_instance = deepcopy(self.def_box["function"]).remove("fn")
        def_instance.generate_target().scale(1 / self.def_scale_ratio).next_to(
            rect, m.RIGHT * 5)
        lines = m.VGroup(
            ThinLine(
                rect.get_corner(m.RIGHT),
                def_instance.target.get_corner(m.LEFT) + m.LEFT * 0.2,
                color=m.BLUE,
            ),
            ThinLine(
                def_instance.target.get_corner(m.DL) + m.LEFT * 0.2,
                def_instance.target.get_corner(m.UL) + m.LEFT * 0.2,
                color=m.BLUE,
            ),
        )
        self.play(m.ShowCreation(rect))
        self.wait(m.DEFAULT_WAIT_TIME / 2)
        self.play(m.Indicate(self.def_box))
        self.play(m.MoveToTarget(def_instance), m.ShowCreation(lines))
        self.wait()
        shift_vector = (call["rec"]["call"]["arg"].get_center() -
                        val_mobject.get_center())
        self.play(
            m.ApplyMethod(self.camera.frame.shift, shift_vector),
            m.ApplyMethod(self.def_box.shift, shift_vector),
        )
        recursive_call_res, recursive_call_res_mobject = self.eval_call(
            def_instance, val - 1, call["rec"]["call"]["arg"])
        self.play(
            m.ApplyMethod(self.camera.frame.shift, -shift_vector),
            m.ApplyMethod(self.def_box.shift, -shift_vector),
        )
        self.play(
            m.FadeOut(lines),
            m.FadeOut(rect),
            m.FadeOut(call["rec"]["call"]),
            m.ApplyMethod(recursive_call_res_mobject.next_to, call["rec"]["*"],
                          m.RIGHT),
        )
        self.wait()
        call["rec"]["call"] = recursive_call_res_mobject
        # Evaluate the left-hand operand of the multiplication
        context.replace_occurrence(-1, call["rec"]["n"])
        res = val * recursive_call_res
        replace_expr(self, call["rec"], f"\\verb|{res}|", aligned_edge=m.LEFT)
        self.play(*map(m.FadeOut, context.entries))
        return res, call["rec"]