用manim实现Gram-Schmidt正交化过程

        在线性代数中,正交基有许多美丽的性质。例如,由正交列向量组成的矩阵(又称正交矩阵)可以通过矩阵的转置很容易地进行反转。此外,例如:在由彼此正交的向量张成的子空间上投影向量也更容易。Gram-Schmidt过程是一个重要的算法,它允许我们将任意基转换为生成同一子空间的正交基。在这篇文章中,我们将使用一个流行的开源库。manim在3D中实现和可视化这个算法

        Gram-Schmidt过程是一种用于将一组线性无关的向量转化为一组正交(或正交归一化)的向量的算法。这个过程在数学和工程中广泛应用,特别是在计算机图形学、信号处理和统计分析中。

Gram-Schmidt 正交化的步骤

假设我们有一组线性无关的向量 {v_{1},v_{2},...,v_{n}},Gram-Schmidt过程的步骤如下:

  1. 初始化:给定向量v_{1},定它为第一个正交向量 u_{1}:

u_{1}=v_{1}

     2.后续向量的正交化:对于每个i=1,2,3,...,n,计算新的正交向量 u_{1}​:

u_{1}=v_{1}- \sum_{j=1}^{i-1}proj_{u_{i}}(v_{i})

        其中,投影 proj_{u_{i}}(v_{i}) 是:

proj_{u_{i}}(v_{i})=\frac{v_{i}.u_{j}}{v_{j}.u_{j}}.u_{j}

        这里表示向量的点积。

     3.归一化(可选):如果需要将向量归一化,使其单位长度,可以通过以下公式进行:

q_{i}=\frac{u_{i}}{||u_{i}||}

        其中 ||u_{i}||是向量u_{i}的模。

应用

  • 正交基:Gram-Schmidt过程的输出结果是正交基,可以用于简化内积空间中的计算。
  • 数值稳定性:在计算中使用正交向量能提高数值稳定性,特别是在进行矩阵分解(如QR分解)时。
  • 计算简化:在许多应用中(如最小二乘法),正交向量可以简化计算,使得更容易处理高维数据。

用manim实现向量的表示

        代码为了实现 Gram-Schmidt 正交化的可视化过程而构建,使用了 Manim 库。

from manim import *  # 导入 Manim 库  
import numpy as np  # 导入 NumPy 库以进行数值计算  
from enum import Enum  # 导入枚举模块以创建动作类型  # 定义颜色  
basis_i_color = GREEN  # 基向量 i 的颜色  
basis_j_color = RED    # 基向量 j 的颜色  
basis_k_color = GOLD   # 基向量 k 的颜色  
q_color = PURPLE       # 向量 q 的颜色  
q_shifted_color = PINK # 移动的向量 q 的颜色  
projection_color = BLUE # 投影向量的颜色  # 定义动作枚举,便于管理不同的操作  
class Action(Enum):  UPDATE_MATRIX_REMOVE_Q = 1  # 更新矩阵并移除 q 向量  ADD_PROJECTION = 2           # 添加一个投影向量  REMOVE_PROJECTIONS_SET_Q = 3 # 移除投影向量并设置新的 q 向量  NORMALIZE_Q = 4              # 规范化 q 向量  # 实现 Gram-Schmidt 过程  
def gram_schmidt(A):  (n, m) = A.shape  # 获取矩阵 A 的形状  for i in range(m):  q = A[:, i]  # 选取矩阵 A 的第 i 列  for j in range(i):  # 计算并从 q 中减去之前列的投影  projection = np.dot(A[:, j], A[:, i]) * A[:, j]  q = q - projection  # 归一化 q 向量  q /= np.linalg.norm(q)  yield Action.NORMALIZE_Q, q  # 返回规范化的 q 向量  # 创建一个新的场景,用于展示 Gram-Schmidt  
class GramSchmidt(Scene):  def construct(self):  # 创建基础向量的颜色,并初始化向量和矩阵 M  M = np.random.rand(3, 3)  # 随机初始化 3x3 矩阵 M  projection_vectors = []     # 初始化用于存储投影向量的列表  q = None                    # 初始化 q 向量为 None  # 初始化基向量箭头  i_vec = Vector(M[:, 0], color=basis_i_color)  # i 向量  j_vec = Vector(M[:, 1], color=basis_j_color)  # j 向量  k_vec = Vector(M[:, 2], color=basis_k_color)  # k 向量  # 播放箭头和矩阵的动画  self.play(GrowArrow(i_vec), GrowArrow(j_vec), GrowArrow(k_vec))  self.wait()  # 遍历 Gram-Schmidt 的步骤  for (action, payload) in gram_schmidt(M):  if action == Action.UPDATE_MATRIX_REMOVE_Q:  # 此步骤用于更新矩阵,并移除旧的 q 向量  assert q is not None  M_rounded = np.round(M.copy(), 2)  # 对矩阵 M 进行四舍五入  matrix = self.create_matrix(M_rounded)  # 创建新的矩阵对象  self.remove(matrix)  # 移除旧的矩阵  # 更新基向量  i_vec_new = Vector(M[:, 0], color=basis_i_color)  j_vec_new = Vector(M[:, 1], color=basis_j_color)  k_vec_new = Vector(M[:, 2], color=basis_k_color)  animation_time = 2.0  # 动画时间  # 播放更新基向量的动画  self.play(  FadeOut(q, run_time=animation_time * 0.75),  ReplacementTransform(i_vec, i_vec_new, run_time=animation_time),  ReplacementTransform(j_vec, j_vec_new, run_time=animation_time),  ReplacementTransform(k_vec, k_vec_new, run_time=animation_time)  )  self.wait()  # 等待一段时间  # 更新现有向量引用  i_vec, j_vec, k_vec = i_vec_new, j_vec_new, k_vec_new  elif action == Action.ADD_PROJECTION:  # 添加新的投影向量  p = Vector(payload, color=projection_color)  projection_vectors.append(p)  # 将投影向量添加到列表中  self.play(GrowArrow(p))  # 播放投影箭头的动画  self.wait()  # 等待  if len(projection_vectors) == 2:  # 当有两个投影向量时,更新其显示效果  first_projection_end = projection_vectors[0].get_end()  p_shifted = Arrow(first_projection_end, first_projection_end + payload, buff=0, color=projection_color)  projection_vectors[1] = p_shifted  self.play(ReplacementTransform(p, p_shifted))  # 替换动画  self.wait()  # 等待  elif action == Action.REMOVE_PROJECTIONS_SET_Q:  # 移除投影并设置新的 q 向量  if not projection_vectors:  q = Vector(payload, color=q_color)  self.play(GrowArrow(q))  # 播放 q 向量的动画  self.wait()  else:  last_projection_end = projection_vectors[-1].get_end()  q_shifted = Arrow(last_projection_end, last_projection_end + payload, buff=0, color=q_shifted_color)  self.play(GrowArrow(q_shifted))  self.wait()  q = Vector(payload, color=q_color)  # 设置新的 q 向量  self.play(  ReplacementTransform(q_shifted, q),  *[FadeOut(p) for p in projection_vectors]  # 移除所有投影  )  self.wait()  projection_vectors = []  # 清空投影向量列表  elif action == Action.NORMALIZE_Q:  # 规范化 q 向量  q_normalized = Vector(payload, color=q_color)  self.play(ReplacementTransform(q, q_normalized))  # 播放规范化动画  self.wait()  q = q_normalized  # 更新 q 向量  else:  assert False  # 确保没有未识别的动作  self.wait(1)  # 在每轮操作间等待  # 验证结果  assert np.allclose(M.T @ M, np.identity(3))  # 确保 M 的转置乘以 M 为单位矩阵  self.wait(15)  # 等待更长时间以查看最终结果

代码解释

  1. 依赖导入:导入了 Manim 和 NumPy 库,Manim 用于创建动画,NumPy 用于数值计算。
  2. 颜色和动作类型定义:定义了不同颜色用于表示基向量、投影、规范化向量等,并通过枚举类型管理不同的动画操作。
  3. 实现 Gram-Schmidt:定义了 gram_schmidt 函数,用于计算 Gram-Schmidt 正交化,逐列处理输入矩阵。
  4. 创建场景:在 GramSchmidt 类中,设置基向量和矩阵,并实现了多个动画步骤,以展示算法的每一步。
  5. 动画逻辑:根据不同的 Action 执行相应的动画,包括更新向量、添加和移除投影向量、规范化向量等。
  6. 验证结果:程序的最后一步确保生成的矩阵是正交的,即其转置乘以自身等于单位矩阵。

你可以根据自己的需求调整参数、颜色或动画,以实现所需的效果。

运行结果:

 

 

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/439906.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python Tips6 基于数据库和钉钉机器人的通知

说明 起因是我第一版quant程序的短信通知失效了。最初认为短信是比较即时且比较醒目的通知方式,现在看来完全不行。 列举三个主要问题: 1 延时。在早先还能收到消息的时候,迟滞就很严重,几分钟都算短的。2 完全丢失。我手机没有…

AI 时代:产品经理不“AI”就出局?

即便你没想去做“AI 产品经理”,那你也不能成为一个不会用 AI 的产品经理。 产品经理肯定是所有互联网从业者中,最先捕捉到 AI 趋势的岗位。 但只知道 AI、关注 AI 还不够,仔细审视一下:你自己的工作,被 AI 提效了么…

《Windows PE》4.1导入表

导入表顾名思义,就是记录外部导入函数信息的表。这些信息包括外部导入函数的序号、名称、地址和所属的DLL动态链接库的名称。Windows程序中使用的所有API接口函数都是从系统DLL中调用的。当然也可能是自定义的DLL动态链接库。对于调用方,我们称之为导入函…

安防监控/视频系统EasyCVR视频汇聚平台如何过滤134段的告警通道?

视频汇聚/集中存储EasyCVR安防监控视频系统采用先进的网络传输技术,支持高清视频的接入和传输,能够满足大规模、高并发的远程监控需求。平台支持国标GB/T 28181协议、部标JT808、GA/T 1400协议、RTMP、RTSP/Onvif协议、海康Ehome、海康SDK、大华SDK、华为…

STM32定时器(TIM)

目录 一、概述 二、定时器的类型 三、时序 四、定时器中断基本结构 五、定时器定时中断代码 六、定时器外部时钟代码 一、概述 TIM(Timer)定时器 定时器可以对输入的时钟进行计数,并在计数值达到设定值时触发中断16位计数器、预分频器、自动重装寄存器的时基…

力扣刷题 | 两数之和

目前主要分为三个专栏,后续还会添加: 专栏如下: C语言刷题解析 C语言系列文章 我的成长经历 感谢阅读! 初来乍到,如有错误请指出,感谢! 给定一个整数数组 nums 和…

网站建设完成后,切勿让公司官网成为摆设

在当今这个数字化时代,公司官网已经成为企业展示形象、传递信息、吸引客户的重要平台。然而,许多企业在网站建设完成后,往往忽视了对官网的持续运营和维护,导致官网逐渐沦为摆设,无法发挥其应有的作用。为了确保公司官…

15分钟学 Python 第40天:Python 爬虫入门(六)第一篇

Day40 :Python 爬取豆瓣网前一百的电影信息 1. 项目背景 在这个项目中,我们将学习如何利用 Python 爬虫技术从豆瓣网抓取前一百部电影的信息。通过这一练习,您将掌握网页抓取的基本流程,包括发送请求、解析HTML、存储数据等核心…

jvisualvm学习

系列文章目录 JavaSE基础知识、数据类型学习万年历项目代码逻辑训练习题代码逻辑训练习题方法、数组学习图书管理系统项目面向对象编程:封装、继承、多态学习封装继承多态习题常用类、包装类、异常处理机制学习集合学习IO流、多线程学习仓库管理系统JavaSE项目员工…

ssm服装店销售管理系统

系统包含:源码论文 所用技术:SpringBootVueSSMMybatisMysql 免费提供给大家参考或者学习,获取源码请私聊我 需要定制请私聊 目 录 摘 要 I Abstract II 第1章 绪论 1 1.1研究背景 1 1.2研究意义 1 1.3国内外研究现状 2 1.3.1国外研…

提高顾客满意度,餐饮业如何开展客户调研?

餐饮行业需明确调研目的,选择合适工具,设计问卷,收集并分析数据,持续追踪优化。通过客户调研,提升服务质量、顾客满意度和竞争力,利用ZohoSurvey等工具实现高效调研。 一、明确调研目的 进行客户调研前&am…

【hot100-java】【将有序数组转换为二叉搜索树】

二叉树篇 中序遍历实现 /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* TreeNode(int val) { this.val val; }* TreeNode(int val, TreeNode left, TreeNode right…

yolo自动化项目实例解析(七)自建UI--工具栏选项

在上一章我们基本实现了关于预览窗口的显示&#xff0c;现在我们主要完善一下工具栏菜单按键 一、添加任务ui 先加个ui页面&#xff0c;不想看ui的复制完这个文件到ui目录下转下py直接从第二步开始看 vi ui/formpy.ui <?xml version"1.0" encoding"UTF-8&q…

Mysql数据库--删除和备份、约束类型

目录 1.删除操作 1.1表的删除操作 1.2数据库备份 2.约束 2.1基本概况 2.2not null约束演示 2.3unique约束演示 2.4default约束演示 2.5primary key约束演示 2.6foreign key约束演示 2.7check约束演示 1.删除操作 1.1表的删除操作 delete from 表名 where 条件…

kubeadm部署k8s

1.1 安装Docker [rootk8s-all ~]# wget -O /etc/yum.repos.d/docker-ce.repo https://mirrors.huaweicloud.com/docker-ce/linux/centos/docker-ce.repo [rootk8s-all ~]# sed -i sdownload.docker.commirrors.huaweicloud.com/docker-ce /etc/yum.repos.d/docker-ce.repo [ro…

数据结构双向链表和循环链表

目录 一、循环链表二、双向链表三、循环双向链表 一、循环链表 循环链表就是首尾相接的的链表&#xff0c;就是尾节点的指针域指向头节点使整个链表形成一个循环&#xff0c;这就弥补了以前单链表无法在后面某个节点找到前面的节点&#xff0c;可以从任意一个节点找到目标节点…

用HTML5+CSS+JavaScript庆祝国庆

用HTML5CSSJavaScript庆祝国庆 中华人民共和国的国庆日是每年的10月1日。 1949年10月1日&#xff0c;中华人民共和国中央人民政府成立&#xff0c;在首都北京天安门广场举行了开国大典&#xff0c;中央人民政府主席毛泽东庄严宣告中华人民共和国成立&#xff0c;并亲手升起了…

[单master节点k8s部署]31.ceph分布式存储(二)

Ceph配置 Ceph集群通常是一个独立的存储集群&#xff0c;可以部署在 Kubernetes 集群之外。Ceph 提供分布式存储服务&#xff0c;能够通过 RADOS、CephFS、RBD&#xff08;块存储&#xff09;、和 RGW&#xff08;对象存储&#xff09;等方式与 Kubernetes 集成。即使 Ceph 部…

王者农药更新版

一、启动文件配置 二、GPIO使用 2.1基本步骤 1.配置GPIO&#xff0c;所以RCC开启APB2时钟 2.GPIO初始化&#xff08;结构体&#xff09; 3.给GPIO引脚设置高/低电平&#xff08;WriteBit&#xff09; 2.2Led循环点亮&#xff08;GPIO输出&#xff09; 1.RCC开启APB2时钟。…

CSS | 响应式布局之媒体查询(media-query)详解

media type(媒体类型)是CSS 2中的一个非常有用的属性&#xff0c;通过media type我们可以对不同的设备指定特定的样式&#xff0c;从而实现更丰富的界面。media query(媒体查询)是对media type的一种增强&#xff0c;是CSS 3的重要内容之一。随着移动互联网的发展&#xff0c;m…