解析几何算法实现之(矩阵类实现)

2021-11-12 18:16:18 浏览数 (1)

大一学这个解析几何的时候就想着用一门语言把里面的算法都实现了,可是一直拖拖拉拉的处于未完工的状态。

这就是我的书(我的字怎么这么丑)

实现起来其实算法都在书里面,就是你没有写过大项目,所以不知道咋写。那第一个思路就是找找有没有现成的书,翻着看。就找到一本,我还找不到电子版的。

书中的目录可以看,就用的4个库,因为都是普通的底层算法。所以这些库就可以实现,第一个是数组,第二个是科学计算,第三个是绘图,第四个数值运算的库。

然后里面大部分是矩阵运算,看着没有高等代数难。

然后我还找到一个关于解析几何的GitHub库,就是我认为不错的库。

代码语言:javascript复制
https://github.com/jan-mue/geometer

简单的介绍

代码语言:javascript复制
pip install geometer

pip安装一下就行,当然也会安装一些依赖库,安装就行。

代码语言:javascript复制
https://geometer.readthedocs.io/en/stable/

这个项目也是提供了一个参考的文档来学习。

你可以这样的创建一个最基础的点

可以看一下类定义

实现的源码

点的定义

内部的初始化类

大部分都是Numpy的库,这些函数都没有用过,所以得先看看Numpy的库

代码语言:javascript复制
https://numpy.org/doc/stable/user/whatisnumpy.html

文档在此

代码语言:javascript复制
https://github.com/search?l=Jupyter Notebook&q=numpy&type=Repositories

在Github里面找一下Numpy相关的库。

代码语言:javascript复制
https://github.com/rougier/numpy-100

找到一个合适的库,100道题

我们传统的Python代码实现的逐元素向乘

C系语言版本

Numpy的运算是一种叫广播的机制:广播是用于描述操作的隐式逐元素行为的术语;一般而言,在 NumPy 中,所有操作,不仅是算术运算,还有逻辑、按位、函数等,都以这种隐式的逐元素方式表现,即它们进行广播。此外,在上面的例子中,可以是相同形状的多维数组,ab可以是标量和数组,甚至是两个不同形状的数组,前提是较小的数组可以“扩展”为较大的数组的形状结果广播是明确的。

维度称为轴

里面的常见的几个方法

一个列表也可以成为最简单的一个数组元素

接下来我们使用Python实现一下自己的矩阵类及其计算:

我们就写两个脚本先,main这个文件是测试脚本

直接放一段我写的代码看看,在文章的后面会有完整的实现

这里说一下编写这个东西的一些考量,因为向量最基本的东西就是一个点,所以用列表当参数。因为下面的方法要的都是引用,万一进来的时候不是引用,用list()来复制一下,确保传参数无误。

代码语言:javascript复制
  def __repr__(self):
    return "Vector({})".format(self._values)

  def __str__(self):
    return "({})".format(", ".join(e for e in self._values))

在一个类制作出来的时候,就该考虑,机器层面的展示和面向人类展示方法 ,引入自带的魔法方法,定义一下,然后__str__里面使用了一下for。

为了编写更有专业味道的代码,这里进行了改进,使用了迭代器。你看参数的调用样子,也需要注意使用了断言判断向量的维数在运算的时候是不是同维的。

就是这样的就可以

测试文件,提前写这里

实现加法

加法运算更加通俗的理解

扩展三维

证明

数乘

普遍理解

证明

一些性质(在类中已经全部实现 )

证明

源码在此:

代码语言:javascript复制
class Vector:

  def __init__(self, lst):
    self._values = list(lst)

  # 此处是一个引用,复制一下

  # 为了处理这个地方的私有变量访问的事情,下面写个迭代器出来

  def __len__(self):
    """返回向量长度(有多少个元素)"""
    return len(self._values)

  def __repr__(self):
    return "Vector({})".format(self._values)

  def __str__(self):
    return "({})".format(", ".join(e for e in self._values))

  def __getitem__(self, index):
    """取向量的第index个元素"""
    return self._values[index]

  def __add__(self, another):
    """向量加法,返回结果向量"""
    assert len(self) == len(another), 
      "Error in adding. Length of vectors must be same."
    # 判断维度的大小
    # return Vector([a   b for a, b in zip(self._values, another._values)])
    return Vector([a   b for a, b in zip(self, another)])

  def __sub__(self, another):
    """向量减法,返回结果向量"""
    assert len(self) == len(another), 
      "Error in adding. Length of vectors must be same."
    # 判断维度的大小
    # return Vector([a - b for a, b in zip(self._values, another._values)])
    return Vector([a - b for a, b in zip(self, another)])

  def __mul__(self, k):
    """返回数量乘法的结果向量:slef * k"""
    # 向量乘数
    return Vector([k * e for e in self])

  def __rmul__(self, k):
    """返回数量乘法的结果向量:k * slef """
    # 向量乘数
    return self * k

  def __iter__(self):
    """返回向量的迭代器"""
    return self._values.__iter__()

  def __pos__(self):
    """返回i向量取正的结果"""
    return 1 * self

  def __neg__(self):
    """ 返回一个负值"""
    return -1 * self
# 因为是有了迭代器,所以这里可以直接使用for循环了

╰( ̄ω ̄o)

内容还有很多,大家请持续关注~

0 人点赞