mirror of
https://github.com/3b1b/manim.git
synced 2025-11-01 15:08:59 +00:00
Up to Venn Diagrams of Bell's project
This commit is contained in:
parent
f249da02cc
commit
80c433820c
3 changed files with 365 additions and 25 deletions
356
bell.py
356
bell.py
|
|
@ -192,21 +192,28 @@ class DirectionOfPolarization(FilterScene):
|
|||
about_point = self.em_wave.start_point,
|
||||
)
|
||||
if self.apply_filter:
|
||||
filter_x = self.pol_filter.get_center()[0]
|
||||
for vect_group, angle in (self.em_wave.E_vects, 0), (self.em_wave.M_vects, np.pi/2):
|
||||
proj_vect = rotate_vector(
|
||||
OUT, self.pol_filter.filter_angle + angle, RIGHT,
|
||||
filters = sorted(
|
||||
self.pol_filters,
|
||||
lambda pf1, pf2 : cmp(
|
||||
pf1.get_center()[0],
|
||||
pf2.get_center()[0],
|
||||
)
|
||||
proj_matrix = np.array([RIGHT] + [
|
||||
proj_vect*np.dot(proj_vect, basis)
|
||||
for basis in UP, OUT
|
||||
]).T
|
||||
for vect in vect_group:
|
||||
start, end = vect.get_start_and_end()
|
||||
if start[0] > filter_x:
|
||||
vect.apply_matrix(proj_matrix)
|
||||
vect.shift(start - vect.get_start())
|
||||
|
||||
)
|
||||
for pol_filter in filters:
|
||||
filter_x = pol_filter.get_center()[0]
|
||||
for vect_group, angle in (self.em_wave.E_vects, 0), (self.em_wave.M_vects, np.pi/2):
|
||||
proj_vect = rotate_vector(
|
||||
OUT, pol_filter.filter_angle + angle, RIGHT,
|
||||
)
|
||||
proj_matrix = np.array([RIGHT] + [
|
||||
proj_vect*np.dot(proj_vect, basis)
|
||||
for basis in UP, OUT
|
||||
]).T
|
||||
for vect in vect_group:
|
||||
start, end = vect.get_start_and_end()
|
||||
if start[0] > filter_x:
|
||||
vect.apply_matrix(proj_matrix)
|
||||
vect.shift(start - vect.get_start())
|
||||
|
||||
class PhotonsThroughPerpendicularFilters(DirectionOfPolarization):
|
||||
CONFIG = {
|
||||
|
|
@ -258,7 +265,7 @@ class PhotonsThroughPerpendicularFilters(DirectionOfPolarization):
|
|||
em_wave = self.em_wave.copy(),
|
||||
run_time = 1.5,
|
||||
)
|
||||
for x in 2, -2, 10
|
||||
for x in -2, 2, 10
|
||||
]
|
||||
|
||||
def get_probability_text(self, prob = 0):
|
||||
|
|
@ -288,6 +295,57 @@ class PhotonsThroughPerpendicularFilters(DirectionOfPolarization):
|
|||
|
||||
return prob_text
|
||||
|
||||
class MoreFiltersMoreLight(FilterScene):
|
||||
CONFIG = {
|
||||
"filter_x_coordinates" : range(-2, 3),
|
||||
"pol_filter_configs" : [
|
||||
{
|
||||
"include_arrow_label" : False,
|
||||
"filter_angle" : angle
|
||||
}
|
||||
for angle in np.linspace(0, np.pi/2, 5)
|
||||
],
|
||||
"ambient_rotation_rate" : 0,
|
||||
}
|
||||
def construct(self):
|
||||
self.remove(self.axes)
|
||||
pfs = self.pol_filters
|
||||
for pf in pfs:
|
||||
pf.set_fill(WHITE, opacity = 0.25)
|
||||
pf.arrow.set_fill(opacity = 1)
|
||||
turn_off_3d_shading(pfs)
|
||||
self.remove(pfs)
|
||||
self.add(pfs[4], pfs[2], pfs[0])
|
||||
|
||||
self.move_camera(
|
||||
phi = 0.9*np.pi/2,
|
||||
theta = -0.95*np.pi,
|
||||
)
|
||||
self.dither()
|
||||
for i in 1, 3:
|
||||
pf = pfs[i]
|
||||
foreground = VGroup(*reversed(pfs[:i]))
|
||||
pf.save_state()
|
||||
pf.shift(6*OUT)
|
||||
self.remove(foreground)
|
||||
self.play(
|
||||
pf.restore,
|
||||
Animation(foreground),
|
||||
run_time = 2
|
||||
)
|
||||
self.dither()
|
||||
|
||||
class ConfusedPiCreature(Scene):
|
||||
def construct(self):
|
||||
randy = Randolph()
|
||||
self.play(
|
||||
randy.change, "confused", 3*(UP+RIGHT),
|
||||
)
|
||||
self.play(Blink(randy))
|
||||
self.dither(2)
|
||||
self.play(Blink(randy))
|
||||
self.dither(2)
|
||||
|
||||
class AngryPiCreature(PiCreatureScene):
|
||||
def construct(self):
|
||||
self.pi_creature_says(
|
||||
|
|
@ -490,7 +548,7 @@ class ShowVariousFilterPairs(PhotonsThroughPerpendicularFilters):
|
|||
def show_photons(self, n_photons = 5):
|
||||
p = self.get_prob()
|
||||
photons = [
|
||||
copy.deepcopy(self.photons[2 if random.random() < p else 0])
|
||||
copy.deepcopy(self.photons[2 if random.random() < p else 1])
|
||||
for x in range(n_photons)
|
||||
]
|
||||
for photon in photons:
|
||||
|
|
@ -514,7 +572,6 @@ class ShowVariousFilterPairs(PhotonsThroughPerpendicularFilters):
|
|||
def get_prob(self):
|
||||
return np.cos(self.second_filter.filter_angle)**2
|
||||
|
||||
|
||||
class ForgetPreviousActions(PhotonsThroughPerpendicularFilters):
|
||||
CONFIG = {
|
||||
"filter_x_coordinates" : [-6, -2, 2],
|
||||
|
|
@ -525,20 +582,271 @@ class ForgetPreviousActions(PhotonsThroughPerpendicularFilters):
|
|||
"start_theta" : -0.6*np.pi
|
||||
}
|
||||
def construct(self):
|
||||
self.photons = self.get_photons()[1:]
|
||||
|
||||
for pf in self.pol_filters:
|
||||
pf.arrow_label.rotate_in_place(np.pi/2, OUT)
|
||||
pf.arrow_label.next_to(pf.arrow, RIGHT)
|
||||
|
||||
rect = SurroundingRectangle(VGroup(*self.pol_filters[1:]))
|
||||
rect.rotate_in_place(np.pi/2, RIGHT)
|
||||
rect.stretch_
|
||||
words = TextMobject(
|
||||
group = VGroup(*self.pol_filters[1:])
|
||||
rect1 = SurroundingRectangle(group)
|
||||
rect1.rotate_in_place(np.pi/2, RIGHT)
|
||||
rect1.rescale_to_fit(group.get_depth()+MED_SMALL_BUFF, 2, True)
|
||||
rect1.stretch_in_place(1.2, 0)
|
||||
prob_words = TextMobject(
|
||||
"Probabilities depend only\\\\",
|
||||
"on this angle difference"
|
||||
)
|
||||
words.rotate(np.pi/2, RIGHT)
|
||||
words.next_to(rect, OUT)
|
||||
self.add(rect, words)
|
||||
prob_words.add_background_rectangle()
|
||||
prob_words.rotate(np.pi/2, RIGHT)
|
||||
prob_words.next_to(rect1, OUT)
|
||||
|
||||
self.add(rect1)
|
||||
self.play(Write(prob_words))
|
||||
for x in range(2):
|
||||
self.shoot_photon()
|
||||
|
||||
rect2 = SurroundingRectangle(self.pol_filter, color = RED)
|
||||
rect2.rotate_in_place(np.pi/2, RIGHT)
|
||||
rect2.rescale_to_fit(self.pol_filter.get_depth()+MED_SMALL_BUFF, 2, True)
|
||||
rect2.stretch_in_place(1.5, 0)
|
||||
ignore_words = TextMobject("Photon \\\\", "``forgets'' this")
|
||||
ignore_words.add_background_rectangle()
|
||||
ignore_words.rotate(np.pi/2, RIGHT)
|
||||
ignore_words.next_to(rect2, OUT)
|
||||
|
||||
self.play(
|
||||
ShowCreation(rect2),
|
||||
Write(ignore_words, run_time = 1)
|
||||
)
|
||||
for x in range(4):
|
||||
self.shoot_photon()
|
||||
|
||||
|
||||
def shoot_photon(self):
|
||||
photon = random.choice(self.photons)
|
||||
added_anims = []
|
||||
if photon.filter_distance == SPACE_WIDTH + 2:
|
||||
added_anims.append(self.get_filter_absorbtion_animation(
|
||||
self.pol_filters[2], photon
|
||||
))
|
||||
self.play(photon, *added_anims, run_time = 1.5)
|
||||
|
||||
class NumbersSuggestHiddenVariablesAreImpossible(TeacherStudentsScene):
|
||||
def construct(self):
|
||||
self.teacher_says(
|
||||
"These numbers suggest\\\\",
|
||||
"no hidden variables"
|
||||
)
|
||||
self.change_student_modes("erm", "sassy", "confused")
|
||||
self.dither(3)
|
||||
|
||||
class VennDiagramProofByContradiction(Scene):
|
||||
CONFIG = {
|
||||
"circle_colors" : [RED, GREEN, BLUE]
|
||||
}
|
||||
def construct(self):
|
||||
# self.force_skipping()
|
||||
|
||||
self.draw_venn_diagram()
|
||||
self.show_100_photons()
|
||||
self.show_one_photon_answering_questions()
|
||||
self.put_all_photons_in_A()
|
||||
self.separate_by_B()
|
||||
self.separate_by_C()
|
||||
self.show_two_relevant_subsets()
|
||||
self.show_real_value()
|
||||
self.contradiction()
|
||||
|
||||
def draw_venn_diagram(self):
|
||||
venn_diagrom = VGroup(*[
|
||||
Circle(
|
||||
radius = 3,
|
||||
stroke_width = 3,
|
||||
stroke_color = c,
|
||||
fill_opacity = 0.2,
|
||||
fill_color = c,
|
||||
).shift(vect)
|
||||
for c, vect in zip(
|
||||
self.circle_colors,
|
||||
compass_directions(3, UP)
|
||||
)
|
||||
])
|
||||
venn_diagrom.center()
|
||||
props = [1./12, 0.5, 0]
|
||||
for circle, char, prop in zip(venn_diagrom, "ABC", props):
|
||||
label = TextMobject("Would pass \\\\ through", char)
|
||||
label.highlight_by_tex(char, circle.get_color())
|
||||
center = circle.get_center()
|
||||
label.move_to(center)
|
||||
label.generate_target()
|
||||
point = circle.point_from_proportion(prop)
|
||||
label.target.next_to(point, point-center, SMALL_BUFF)
|
||||
|
||||
circle.label = label
|
||||
|
||||
last_circle = None
|
||||
for circle in venn_diagrom:
|
||||
added_anims = []
|
||||
if last_circle:
|
||||
added_anims.append(MoveToTarget(last_circle.label))
|
||||
self.play(
|
||||
DrawBorderThenFill(circle, run_time = 2),
|
||||
Write(circle.label, run_time = 2),
|
||||
*added_anims
|
||||
)
|
||||
last_circle = circle
|
||||
self.play(MoveToTarget(last_circle.label))
|
||||
self.dither()
|
||||
|
||||
venn_diagrom.add(*[c.label for c in venn_diagrom])
|
||||
self.venn_diagrom = venn_diagrom
|
||||
for part in self.venn_diagrom:
|
||||
part.save_state()
|
||||
|
||||
self.play(
|
||||
self.venn_diagrom.scale, 0.25,
|
||||
self.venn_diagrom.to_corner, UP+RIGHT
|
||||
)
|
||||
|
||||
def show_100_photons(self):
|
||||
photon = FunctionGraph(
|
||||
lambda x : -np.cos(3*np.pi*x)*np.exp(-x*x),
|
||||
x_min = -2,
|
||||
x_max = 2,
|
||||
color = YELLOW
|
||||
)
|
||||
photon.shift(LEFT + 2*UP)
|
||||
eyes = Eyes(photon)
|
||||
photon.eyes = eyes
|
||||
|
||||
hundred, photon_word, s = words = TextMobject(
|
||||
"100 ", "Photon", "s",
|
||||
arg_separator = ""
|
||||
)
|
||||
words.next_to(eyes, UP)
|
||||
|
||||
self.play(
|
||||
ShowCreation(photon),
|
||||
FadeIn(photon.eyes),
|
||||
Write(photon_word, run_time = 1.5)
|
||||
)
|
||||
photon.add(photon.eyes)
|
||||
|
||||
#Split to hundred
|
||||
photons = VGroup(*[photon.deepcopy() for x in range(100)])
|
||||
self.arrange_photons_in_circle(photons)
|
||||
photons.scale_to_fit_height(6)
|
||||
photons.next_to(words, DOWN)
|
||||
photons.to_edge(LEFT)
|
||||
|
||||
self.play(
|
||||
Write(hundred), Write(s),
|
||||
ReplacementTransform(
|
||||
VGroup(photon), photons,
|
||||
submobject_mode = "lagged_start"
|
||||
)
|
||||
)
|
||||
|
||||
self.photons = photons
|
||||
self.photon_words = words
|
||||
|
||||
def show_one_photon_answering_questions(self):
|
||||
photon = self.photons[-1]
|
||||
photon.save_state()
|
||||
photon.generate_target()
|
||||
photon.target.scale(4)
|
||||
photon.target.next_to(self.photons, RIGHT)
|
||||
|
||||
answers = TextMobject(
|
||||
"Pass through A?", "Yes\\\\",
|
||||
"Pass through B?", "No\\\\",
|
||||
"Pass through C?", "No\\\\",
|
||||
)
|
||||
answers.highlight_by_tex_to_color_map({
|
||||
"Yes" : GREEN,
|
||||
"No" : RED,
|
||||
})
|
||||
answers.next_to(photon.target, RIGHT)
|
||||
|
||||
self.play(
|
||||
MoveToTarget(photon),
|
||||
FadeIn(answers)
|
||||
)
|
||||
self.dither(2)
|
||||
self.play(
|
||||
FadeOut(answers),
|
||||
photon.restore,
|
||||
)
|
||||
|
||||
def put_all_photons_in_A(self):
|
||||
A_circle, B_circle, C_circle = circles = self.venn_diagrom[:3]
|
||||
A_group, B_group, C_group = [
|
||||
VGroup(circle, circle.label)
|
||||
for circle in circles
|
||||
]
|
||||
B_group.save_state()
|
||||
C_group.save_state()
|
||||
|
||||
A_group.generate_target()
|
||||
A_group.target.scale(4)
|
||||
A_group.target.center().to_edge(UP)
|
||||
|
||||
self.play(
|
||||
B_group.fade, 1,
|
||||
C_group.fade, 1,
|
||||
MoveToTarget(A_group),
|
||||
FadeOut(self.photon_words),
|
||||
self.photons.scale_to_fit_height,
|
||||
0.85*A_group.target.get_height(),
|
||||
self.photons.move_to, A_group.target[0].get_center(),
|
||||
)
|
||||
self.dither()
|
||||
|
||||
self.A_group = A_group
|
||||
self.B_group = B_group
|
||||
self.C_group = C_group
|
||||
|
||||
def separate_by_B(self):
|
||||
pass
|
||||
|
||||
def separate_by_C(self):
|
||||
pass
|
||||
|
||||
def show_two_relevant_subsets(self):
|
||||
pass
|
||||
|
||||
def show_real_value(self):
|
||||
pass
|
||||
|
||||
def contradiction(self):
|
||||
pass
|
||||
|
||||
#######
|
||||
|
||||
def arrange_photons_in_circle(self, photons):
|
||||
R = np.sqrt(len(photons) / np.pi)
|
||||
pairs = []
|
||||
rejected = []
|
||||
for x, y in it.product(*[range(-int(R)-1, int(R)+2)]*2):
|
||||
if x**2 + y**2 < R**2:
|
||||
pairs.append((x, y))
|
||||
else:
|
||||
rejected.append((x, y))
|
||||
rejected.sort(
|
||||
lambda (x1, y1), (x2, y2) : (x2**2 + y2**2) - (x1**2 + y1**2)
|
||||
)
|
||||
for i in range(len(photons) - len(pairs)):
|
||||
pairs.append(rejected.pop())
|
||||
for photon, (x, y) in zip(photons, pairs):
|
||||
photon.scale_to_fit_width(0.7)
|
||||
photon.move_to(x*RIGHT + y*UP)
|
||||
return photons
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -542,6 +542,12 @@ class Mobject(object):
|
|||
def get_left(self):
|
||||
return self.get_edge_center(LEFT)
|
||||
|
||||
def get_zenith(self):
|
||||
return self.get_edge_center(OUT)
|
||||
|
||||
def get_nadir(self):
|
||||
return self.get_edge_center(IN)
|
||||
|
||||
def length_over_dim(self, dim):
|
||||
return (
|
||||
self.reduce_across_dimension(np.max, np.max, dim) -
|
||||
|
|
@ -554,6 +560,9 @@ class Mobject(object):
|
|||
def get_height(self):
|
||||
return self.length_over_dim(1)
|
||||
|
||||
def get_depth(self):
|
||||
return self.length_over_dim(2)
|
||||
|
||||
def point_from_proportion(self, alpha):
|
||||
raise Exception("Not implemented")
|
||||
|
||||
|
|
@ -591,6 +600,25 @@ class Mobject(object):
|
|||
self.center()
|
||||
return self
|
||||
|
||||
def arrange_submobjects_in_grid(self, n_rows = None, n_cols = None, **kwargs):
|
||||
submobs = self.submobjects
|
||||
if n_rows is None and n_cols is None:
|
||||
n_cols = int(np.sqrt(len(submobs)))
|
||||
|
||||
if n_rows is not None:
|
||||
v1 = RIGHT
|
||||
v2 = DOWN
|
||||
n = n_rows
|
||||
elif n_cols is not None:
|
||||
v1 = DOWN
|
||||
v2 = RIGHT
|
||||
n = n_cols
|
||||
Group(*[
|
||||
Group(*submobs[i:i+n]).arrange_submobjects(v1, **kwargs)
|
||||
for i in range(0, len(submobs), n)
|
||||
]).arrange_submobjects(v2, **kwargs)
|
||||
return self
|
||||
|
||||
def sort_submobjects(self, point_to_num_func = lambda p : p[0]):
|
||||
self.submobjects.sort(
|
||||
lambda *mobs : cmp(*[
|
||||
|
|
|
|||
|
|
@ -179,12 +179,16 @@ class ThreeDScene(Scene):
|
|||
##############
|
||||
|
||||
def should_shade_in_3d(mobject):
|
||||
return hasattr(mobject, "shade_in_3d")
|
||||
return hasattr(mobject, "shade_in_3d") and mobject.shade_in_3d
|
||||
|
||||
def shade_in_3d(mobject):
|
||||
for submob in mobject.submobject_family():
|
||||
submob.shade_in_3d = True
|
||||
|
||||
def turn_off_3d_shading(mobject):
|
||||
for submob in mobject.submobject_family():
|
||||
submob.shade_in_3d = False
|
||||
|
||||
class ThreeDMobject(VMobject):
|
||||
def __init__(self, *args, **kwargs):
|
||||
VMobject.__init__(self, *args, **kwargs)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue