von Udacity
This commit is contained in:
360
von_Udacity/NOTES.md
Executable file
360
von_Udacity/NOTES.md
Executable file
@@ -0,0 +1,360 @@
|
|||||||
|
### Vectors
|
||||||
|
|
||||||
|
|
||||||
|
A point represents a location, defined with x, y, z (2, -1, 0).
|
||||||
|
A vector represents a change in direction and it is also defined with x, y, z.
|
||||||
|
This time x, y and z represent the change in each of the coordinates.
|
||||||
|
A vectors doesn't have a specific location.
|
||||||
|
|
||||||
|
|
||||||
|
Vectors have magnitude and direction. The magnitude of a vector is calculated
|
||||||
|
using the pythagorian formula adapted to as many dimensions as the vector has.
|
||||||
|
e.g. 3 dimensions = `square-root(x**2 + y**2 + z**2)`
|
||||||
|
|
||||||
|
|
||||||
|
The Zero vector is the one that has all its coordinates equal to 0. The Zero
|
||||||
|
vector has no direction and no normalization.
|
||||||
|
|
||||||
|
A unit vector is any vector in which it's magnitude is 1.
|
||||||
|
|
||||||
|
The process of finding a unit vector from a given vector is called normalization.
|
||||||
|
There are 2 steps involved when normilizing a vector:
|
||||||
|
- A. Find magnitude.
|
||||||
|
- B. Multiply vector by 1/magnitude of vector.
|
||||||
|
|
||||||
|
#### Dot product
|
||||||
|
The inner multiplication or dot product multiplication of vectors is a way of
|
||||||
|
multiplying 2 vectors and getting a scalar (a couple of references [here](http://betterexplained.com/articles/vector-calculus-understanding-the-dot-product/) and [here](http://mathworld.wolfram.com/InnerProduct.html)).
|
||||||
|
The dot product represents a scalar a number that applies the directional growth
|
||||||
|
of a vector into another one.
|
||||||
|
|
||||||
|
It is calculated by multiplying their magnitudes times the multiplications of the
|
||||||
|
cos of their angle.
|
||||||
|
|
||||||
|
`v1 * v2 = magnitude(v1) * magnitude(v2) * cos(v1-v2)`
|
||||||
|
|
||||||
|
cos is bounded by -1 and +1 so:
|
||||||
|
|
||||||
|
`v1 * v2 <= magnitude(v1) * magnitude(v2)` // Inequality of Cauchy-Schwartz.
|
||||||
|
|
||||||
|
if `v1 * v2 == magnitude(v1) * magnitude(v2)` => Angle is 0deg (same angle).
|
||||||
|
|
||||||
|
if `v1 * v2 == - (magnitude(v1) * magnitude(v2))` => Angle is 180deg
|
||||||
|
(opposite angle).
|
||||||
|
|
||||||
|
if `v1 * v2 == 0 and v1 != 0 and v2 != 0` => Angle is 90deg
|
||||||
|
|
||||||
|
`v * v => magnitude(v) * magnitude(v) * cos(0)` => `magnitude(v) = sqrt(v * v)`
|
||||||
|
|
||||||
|
It can also be expressed as:
|
||||||
|
|
||||||
|
`v1 * v2 = sum of multiplication of each of its coordinates`
|
||||||
|
|
||||||
|
To find out the angle of 2 vectors:
|
||||||
|
|
||||||
|
`arc-cosin ((v1*v2)/(magnitude(v1) * magnitude(2)))` => radians.
|
||||||
|
|
||||||
|
`arc-cosin((normalize(v1) * normalize(v2)))`.
|
||||||
|
|
||||||
|
#### Parallel and orthogonal vectors
|
||||||
|
2 vectors are parallel if one is a scalar multiple of another one.
|
||||||
|
e.g: v and 2v and 1/2v and Zero vector
|
||||||
|
|
||||||
|
2 vectors are orthogonal if v1 * v2 is = 0. There are 2 possibilities.
|
||||||
|
A vector that is 90 deg with another vector or the Zero vector.
|
||||||
|
|
||||||
|
Zero vector is both parallel and orthogonal to all other vectors.
|
||||||
|
Zero vector is the only one that is orthogonal to itself.
|
||||||
|
|
||||||
|
Orthogonality is a tool for decomposing objects into combinations of simpler
|
||||||
|
objects in a structured way.
|
||||||
|
|
||||||
|
#### Proyecting a vector into another vector
|
||||||
|
[Proyecting a vector into another vector](https://www.udacity.com/course/viewer#!/c-ud953/l-4374471116/m-4583493277):
|
||||||
|
|
||||||
|
`v1 = v1-parallel (to base vector) + v1-orthogonal (to base vector)`
|
||||||
|
|
||||||
|
`v1-parallel` is a cathetus, `v2-orthogonal` is the other cathetus and `v1` is the
|
||||||
|
hipotenuse.
|
||||||
|
|
||||||
|
|
||||||
|
`(*)` `cos angle = magnitude(v1-parallel) / magnitude(v1)` =>
|
||||||
|
|
||||||
|
`magnitude(v1-parallel) = cos angle * magnitude(v1)`.
|
||||||
|
|
||||||
|
|
||||||
|
Being v2 the base vector:
|
||||||
|
|
||||||
|
`(v1 * v2) / (magnitude(v1) * magnitude(v2)) = cos(v1-v2)`.
|
||||||
|
|
||||||
|
Substituting cos from `(*)`:
|
||||||
|
|
||||||
|
`magnitude(v1-parallel) = magnitude(v1) * (v1 * v2) / (magnitude(v1) * magnitude(v2))` =>
|
||||||
|
|
||||||
|
(eliminating `magnitude(v1)` in right equation) =>
|
||||||
|
|
||||||
|
`magnitude(v1-parallel) = (v1 * v2) / magnitude(v2))` =>
|
||||||
|
|
||||||
|
`magnitude(v1-parallel) = v1 * normalize(v2)`
|
||||||
|
|
||||||
|
v1 parallel has the same direction as v2.
|
||||||
|
|
||||||
|
`magnitude(v1-parallel) * normalize(v2) = v1-parallel` =>
|
||||||
|
|
||||||
|
`(v1 * normalize(v2)) * normalize(v2) = v1-parallel`
|
||||||
|
|
||||||
|
|
||||||
|
#### Cross product
|
||||||
|
Cross product: It's only possible in 3-dimension vectors and it gives another
|
||||||
|
vector.
|
||||||
|
|
||||||
|
Cross product of v and w is a vector that is orthogonal to both and its
|
||||||
|
`magintute = magnitude(v) * magnitude(w) * sin(angle v-w)`.
|
||||||
|
|
||||||
|
Cross product of 2 parallel vectors is the 0 vector.
|
||||||
|
If v or w are the 0 vector the cross product will be the 0 vector.
|
||||||
|
Cross product is anticommutative, which means that the order matters, in this
|
||||||
|
case changing the order results on vectors having opposite directions.
|
||||||
|
|
||||||
|
`cross product(v, w) = - cross product(v, w)`
|
||||||
|
|
||||||
|
The area of the parallelogram created with v and w is the magnitude of the
|
||||||
|
cross product of v and w.
|
||||||
|
|
||||||
|
The area of the triangle created by those 2 vectors v and w is half of
|
||||||
|
the area of the parallelogram
|
||||||
|
|
||||||
|
For more information in cross products go [here](http://betterexplained.com/articles/cross-product/)
|
||||||
|
|
||||||
|
|
||||||
|
### Intersections
|
||||||
|
|
||||||
|
Flat objects such as lines and planes are defined by linear equations:
|
||||||
|
- Can add and subtract vars and constants
|
||||||
|
- Can multiply a var by a constant
|
||||||
|
|
||||||
|
`x + 2y = 1` // `y/2 - 2z = x` => Linear equations
|
||||||
|
|
||||||
|
`x**2 - 1 = y` // `y/x = 3` => Non linear equations
|
||||||
|
|
||||||
|
Finding intersections is solving systems of equations. We are basicaly converting a real world problems (linear equations) into a geometrical problem (n dimensional objects).
|
||||||
|
|
||||||
|
#### Lines and systems with 2 dimensional objects
|
||||||
|
The most basic problem is finding intersection between lines.
|
||||||
|
|
||||||
|
A line is defined with its basepoint (x0) and the direction of the vector(v).
|
||||||
|
|
||||||
|
`x(t) = x0 + times_scalar(v, t)` => `x(t) = x0 + t * v` (parametrization of line)
|
||||||
|
|
||||||
|
Parametrization of a line (dimensional object) is the act of conveting a system
|
||||||
|
of equations into a set of one dimension equations that all take the same
|
||||||
|
parameters in this case "t" (parameter).
|
||||||
|
|
||||||
|
Note that x0 is a point, but it's treated as a vector in order to computer other
|
||||||
|
points (x(t))
|
||||||
|
|
||||||
|
A given line has infinetely many base points (basically each of its points).
|
||||||
|
|
||||||
|
A given line has infinetely many directions (we can multiply the direction
|
||||||
|
vector by any postive scalar and it will give the same direction)
|
||||||
|
|
||||||
|
`x(t) = [1, -2] + t*[3, 1]`
|
||||||
|
|
||||||
|
for `t = 0` => `x = [1, -2]` => Base point
|
||||||
|
|
||||||
|
for `t = 1` => `x = [1, -2] + [3, 1]` = `[3, -1]` => Another point on the line
|
||||||
|
|
||||||
|
A generic way of representing a line: `Ax + By = k` (A, B not both 0)
|
||||||
|
|
||||||
|
k => constant term
|
||||||
|
|
||||||
|
Base point => `(0, k/B)` and `(k/A, 0)`
|
||||||
|
|
||||||
|
if `k = 0` =>
|
||||||
|
|
||||||
|
`[A, B] (dot product) [x, y] = 0` => `[x, y]` is orthogonal to `[A, B]` =>
|
||||||
|
|
||||||
|
`[B, -A]` is orthogonal to `[A, B]` (that's how we figure out the direction vector)
|
||||||
|
|
||||||
|
Direction vector => `[B, -A]`
|
||||||
|
|
||||||
|
`Ax + By = k` => Gives us an implicit representation of the line such that for
|
||||||
|
a set of points (x, y):
|
||||||
|
|
||||||
|
`[A, B] (dot product) [x, y] = k`
|
||||||
|
|
||||||
|
A line is defined by its normal vector [A, B] and its constant term k.
|
||||||
|
An orthogonal or normal vector to the line is the one represented by [A, B].
|
||||||
|
|
||||||
|
2 lines are parallel if their normal vectors are parallel.
|
||||||
|
|
||||||
|
If 2 lines are not parallel they'll have an intersection in a single point.
|
||||||
|
|
||||||
|
If 2 lines are parallel there are 2 options:
|
||||||
|
- They never cross
|
||||||
|
- They are the same line, which means that they are conincidental and intersect
|
||||||
|
in infinite points
|
||||||
|
|
||||||
|
So 2 lines could have:
|
||||||
|
- 1 point of intersection
|
||||||
|
- 0 points of intersection
|
||||||
|
- infinite points of intersection
|
||||||
|
|
||||||
|
To solve the system:
|
||||||
|
- First check if 2 lines are parallel by checking if their normal vecotrs are parallel.
|
||||||
|
- If normal vectors are parallel, then check if they are the same vector.
|
||||||
|
- Make a line connecting a point of line 1 and line 2 and if that third
|
||||||
|
line is orthogonal to either normal vectors for line 1 and 2 => line 1 and 2
|
||||||
|
are coincident or the same.
|
||||||
|
- If we have 2 lines that are not parallel, to know how they intersect:
|
||||||
|
|
||||||
|
`Ax + By = k1`
|
||||||
|
|
||||||
|
`Cx + Dy = k2`
|
||||||
|
|
||||||
|
Either A or C need to not be 0, b/c if not the lines would both be horizontal
|
||||||
|
and these lines intersect with each other.
|
||||||
|
|
||||||
|
if `A = 0` => swap A by C, B by D and k1 by k2 => A will never be 0
|
||||||
|
|
||||||
|
`(AD - BC)` is never 0 b/c that would mean that both lines are parallel
|
||||||
|
|
||||||
|
`y = (-Ck1 + Ak2) / (AD - BC)`
|
||||||
|
|
||||||
|
`x = (Dk1 - Bk2) / (AD - BC)`
|
||||||
|
|
||||||
|
|
||||||
|
If there are no intersections in a system => the system is "Inconsistent"
|
||||||
|
|
||||||
|
|
||||||
|
#### Planes and systems with 3 dimensional objects
|
||||||
|
|
||||||
|
Three dimensional spaces are defined by linear equations of 3 variables
|
||||||
|
`Ax + By + Cz = k` => `[A B C] (dot product) [x y z] = k`
|
||||||
|
|
||||||
|
`[A B C]` => Normal vector (similiar with lines)
|
||||||
|
|
||||||
|
Changing k shifts the plane but it doesn't change the direction of the plane
|
||||||
|
|
||||||
|
Same rules as with lines apply here.
|
||||||
|
|
||||||
|
- Planes that are not parallel intersect on a line not a point.
|
||||||
|
|
||||||
|
With 2 planes (a system of 2, 3-dimenstion equations) could have:
|
||||||
|
- No intersections (parallel planes)
|
||||||
|
- Intesect in a line
|
||||||
|
- Intersect in a whole plane
|
||||||
|
|
||||||
|
With 3 planes (a system of 3, 3-dimenstion equations), the planes could intersect:
|
||||||
|
- In a line
|
||||||
|
- No solution
|
||||||
|
- A plane
|
||||||
|
- A single point
|
||||||
|
|
||||||
|
The coefficients of a linear equation are the coordinates of a normal vector
|
||||||
|
to the object the equation defines
|
||||||
|
|
||||||
|
In order to solve a system wtih 3 linear equations and 3 variables we need
|
||||||
|
a set of "tools" to manipulate its data (they need to be reversible):
|
||||||
|
- Swap equations
|
||||||
|
- Multiply each of the sides of the planes that is not 0
|
||||||
|
- Add a multiple of one equation to another equation
|
||||||
|
|
||||||
|
Gaussanian elimination:
|
||||||
|
|
||||||
|
- Clear a variable in successive equations until there is only one equation with
|
||||||
|
one variable.
|
||||||
|
- At that point 3 eq with 3 variables have been converted to a system of 3
|
||||||
|
equations, one with 3 variables, one with 2 variables and another one with
|
||||||
|
one variable (triangular form)
|
||||||
|
|
||||||
|
The triangular form doesn't represent the same set of planes as the original
|
||||||
|
system, but it represents the same result.
|
||||||
|
|
||||||
|
If when we are resolving the system and at any point we get the one of the sides
|
||||||
|
of an equation is 0 and the side is not 0 => Inconsistent system, the system has no
|
||||||
|
solution.
|
||||||
|
|
||||||
|
If the system gets to a point in which we have 0 = 0, that means that the
|
||||||
|
last equation that we were soloving was redundant and gives no additional
|
||||||
|
information.
|
||||||
|
|
||||||
|
The system in this case has been converted from a 3 plane system to a 2 plane
|
||||||
|
system, and now we are not looking for a single point of intersection but
|
||||||
|
for a line of intersection
|
||||||
|
|
||||||
|
When the solution is not a point we need to parametrize the solution set.
|
||||||
|
We need to identify the pivot variables (lead variables), which are variables
|
||||||
|
in the leading term, when the system is in a triangular form.
|
||||||
|
The other variables are called the free variable.
|
||||||
|
|
||||||
|
This free variables will become a parameter in the parametrization. So in
|
||||||
|
order to find the values of the pivotal variables for any given point in the
|
||||||
|
line we'll use the free variable (parameter) to compute it.
|
||||||
|
|
||||||
|
Then we have to make the coefficient of pivot variable to be 1
|
||||||
|
|
||||||
|
Then we clear the pivot variable of the second equation in the first
|
||||||
|
equation leaving the system:
|
||||||
|
|
||||||
|
`x + Az = B`
|
||||||
|
|
||||||
|
`y + Cz = D`
|
||||||
|
|
||||||
|
The leading variables have coefficient one and they only appear on one
|
||||||
|
equation each. The system is simplified as much as possible giving us the
|
||||||
|
"reduced row-echelon form" or rref.
|
||||||
|
|
||||||
|
With the rref we are able to get a basepoint and a direction vector that define
|
||||||
|
the parametrization of the soluton for the system.
|
||||||
|
|
||||||
|
`[x y z] = [(B - AZ) (D - Cz) z ]`=> `[B D 0] + z* [-A -C 1]`
|
||||||
|
|
||||||
|
Base point `[B D 0]`
|
||||||
|
|
||||||
|
Direction vector `[-A -C 1]`
|
||||||
|
|
||||||
|
In order for a system to intersect in only one point it needs at least
|
||||||
|
3 equations, 3 planes.
|
||||||
|
|
||||||
|
A system is inconsistent if we find `0 = k` during Gaussian elimination
|
||||||
|
|
||||||
|
A consistent solution has a unique solution and each variable is a pivotal
|
||||||
|
or lead variable.
|
||||||
|
|
||||||
|
Number of free variables is equal to the dimension of the solution set.
|
||||||
|
|
||||||
|
-----------
|
||||||
|
|
||||||
|
Hyperplane in n dimensions is defined as a single linear equation with n
|
||||||
|
variables.
|
||||||
|
|
||||||
|
A hyperplane in n dimensions is an (n-1) dimensional object. // I don't
|
||||||
|
understand this concept yet.
|
||||||
|
|
||||||
|
Gaussian elimination and parametrization through the rref works the same way
|
||||||
|
with planes as with hyperplanes.
|
||||||
|
|
||||||
|
A 2 dimenstional plane in 3 dimensions. Single linear equation with 3
|
||||||
|
dimensions
|
||||||
|
|
||||||
|
|
||||||
|
---------------
|
||||||
|
|
||||||
|
#### Bugs in the course
|
||||||
|
|
||||||
|
[In video 23 of Intersections](https://www.udacity.com/course/viewer#!/c-ud953/l-4624329808/e-4897268655/m-4897268656)
|
||||||
|
it says that parametrization code is in the instructor notes, but it isn't.
|
||||||
|
It redirects [here](https://storage.googleapis.com/supplemental_media/udacityu/4897268656/linsys.py)
|
||||||
|
but this page has the linear system code, not the parametrization code.
|
||||||
|
My implementation of `Parametrization` which was partially copied from one of the
|
||||||
|
videos is at the end of [linear_system.py](https://github.com/omarrayward/Linear-Algebra-Refresher-Udacity/blob/master/linear_system.py)
|
||||||
|
|
||||||
|
The same quiz video as has some typos in the second ecuation of the first system.
|
||||||
|
In the video it shows `-0.138x -0.138y + 0.244z = 0.319` but it should be
|
||||||
|
`-0.131x -0.131y + 0.244z = 0.319`
|
||||||
|
|
||||||
|
The solution [video](https://www.udacity.com/course/viewer#!/c-ud953/l-4624329808/e-4897268655/m-4897268657)
|
||||||
|
uses the correct equation.
|
||||||
|
|
||||||
|
|
||||||
165
von_Udacity/OBJECTS_USED_IN_TESTS.md
Executable file
165
von_Udacity/OBJECTS_USED_IN_TESTS.md
Executable file
@@ -0,0 +1,165 @@
|
|||||||
|
###Vectors
|
||||||
|
|
||||||
|
- Vectors used for test is video 4:
|
||||||
|
```python
|
||||||
|
v = Vector([8.218, -9.341])
|
||||||
|
w = Vector([-1.129, 2.111])
|
||||||
|
```
|
||||||
|
|
||||||
|
```python
|
||||||
|
v = Vector([7.119, 8.215])
|
||||||
|
w = Vector([-8.223, 0.878])
|
||||||
|
```
|
||||||
|
|
||||||
|
```python
|
||||||
|
v = Vector([1.671, -1.012, -0.318])
|
||||||
|
```
|
||||||
|
|
||||||
|
- Vectors used for test is video 6:
|
||||||
|
|
||||||
|
```python
|
||||||
|
v = Vector([-0.221, 7.437])
|
||||||
|
```
|
||||||
|
```python
|
||||||
|
v = Vector([8.813, -1.331, -6.247])
|
||||||
|
```
|
||||||
|
```python
|
||||||
|
v = Vector([5.581, -2.136])
|
||||||
|
```
|
||||||
|
```python
|
||||||
|
v = Vector([1.996, 3.108, -4.554])
|
||||||
|
```
|
||||||
|
|
||||||
|
- Vectors used for test is video 8:
|
||||||
|
```python
|
||||||
|
v = Vector([7.887, 4.138])
|
||||||
|
w = Vector([-8.802, 6.776])
|
||||||
|
```
|
||||||
|
```python
|
||||||
|
v = Vector([-5.955, -4.904, -1.874])
|
||||||
|
w = Vector([-4.496, -8.755, 7.103])
|
||||||
|
```
|
||||||
|
```python
|
||||||
|
v = Vector([3.183, -7.627])
|
||||||
|
w = Vector([-2.668, 5.319])
|
||||||
|
```
|
||||||
|
```python
|
||||||
|
v = Vector([7.35, 0.221, 5.188])
|
||||||
|
w = Vector([2.751, 8.259, 3.985])
|
||||||
|
```
|
||||||
|
|
||||||
|
- Vectors used for test is video 10:
|
||||||
|
|
||||||
|
```python
|
||||||
|
v = Vector([-7.579, -7.88])
|
||||||
|
w = Vector([22.737, 23.64])
|
||||||
|
```
|
||||||
|
```python
|
||||||
|
v = Vector([-2.029, 9.97, 4.172])
|
||||||
|
w = Vector([-9.231, -6.639, -7.245])
|
||||||
|
```
|
||||||
|
```python
|
||||||
|
v = Vector([-2.328, -7.284, -1.214])
|
||||||
|
w = Vector([-1.821, 1.072, -2.94])
|
||||||
|
```
|
||||||
|
```python
|
||||||
|
v = Vector([2.118, 4.827])
|
||||||
|
w = Vector([0, 0])
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
- Vectors used for test is video 12:
|
||||||
|
```python
|
||||||
|
v = Vector([3.039, 1.879])
|
||||||
|
w = Vector([0.825, 2.036])
|
||||||
|
```
|
||||||
|
```python
|
||||||
|
v = Vector([-9.88, -3.264, -8.159])
|
||||||
|
w = Vector([-2.155, -9.353, -9.473])
|
||||||
|
```
|
||||||
|
```python
|
||||||
|
v = Vector([3.009, -6.172, 3.692, -2.51])
|
||||||
|
w = Vector([6.404, -9.144, 2.759, 8.718])
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
- Vectors used for test is video 14:
|
||||||
|
```python
|
||||||
|
v1 = Vector([8.462, 7.893, -8.187])
|
||||||
|
w1 = Vector([6.984, -5.975, 4.778])
|
||||||
|
```
|
||||||
|
```python
|
||||||
|
v2 = Vector([-8.987, -9.838, 5.031])
|
||||||
|
w2 = Vector([-4.268, -1.861, -8.866])
|
||||||
|
```
|
||||||
|
```python
|
||||||
|
v3 = Vector([1.5, 9.547, 3.691])
|
||||||
|
w3 = Vector([-6.007, 0.124, 5.772])
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
###Intersections
|
||||||
|
|
||||||
|
- Lines used for test is video 4:
|
||||||
|
```python
|
||||||
|
line1 = Line(Vector([4.046, 2.836]), 1.21)
|
||||||
|
line2 = Line(Vector([10.115, 7.09]), 3.025)
|
||||||
|
```
|
||||||
|
```python
|
||||||
|
line3 = Line(Vector([7.204, 3.182]), 8.68)
|
||||||
|
line4 = Line(Vector([8.172, 4.114]), 9.883)
|
||||||
|
```
|
||||||
|
```python
|
||||||
|
line5 = Line(Vector([1.182, 5.562]), 6.744)
|
||||||
|
line6 = Line(Vector([1.773, 8.343]), 9.525)
|
||||||
|
```
|
||||||
|
|
||||||
|
- Planes used for test is video 7:
|
||||||
|
```python
|
||||||
|
plane1 = Plane(Vector([-0.412, 3.806, 0.728]), -3.46)
|
||||||
|
plane2 = Plane(Vector([1.03, -9.515, -1.82]), 8.65)
|
||||||
|
```
|
||||||
|
```python
|
||||||
|
plane3 = Plane(Vector([2.611, 5.528, 0.283]), 4.6)
|
||||||
|
plane4 = Plane(Vector([7.715, 8.306, 5.342]), 3.76)
|
||||||
|
```
|
||||||
|
```python
|
||||||
|
plane5 = Plane(Vector([-7.926, 8.625, -7.212]), -7.952)
|
||||||
|
plane6 = Plane(Vector([-2.642, 2.875, -2.404]), -2.443)
|
||||||
|
```
|
||||||
|
|
||||||
|
- Vectors used for test is video 22:
|
||||||
|
```python
|
||||||
|
p1 = Plane(Vector([5.862, 1.178, -10.366]), -8.15)
|
||||||
|
p2 = Plane(Vector([-2.931, -0.589, 5.183]), -4.075)
|
||||||
|
```
|
||||||
|
```python
|
||||||
|
p1 = Plane(Vector([8.631, 5.112, -1.816]), -5.113)
|
||||||
|
p2 = Plane(Vector([4.315, 11.132, -5.27]), -6.775)
|
||||||
|
p3 = Plane(Vector([-2.158, 3.01, -1.727]), -0.831)
|
||||||
|
```
|
||||||
|
```python
|
||||||
|
p1 = Plane(Vector([5.262, 2.739, -9.878]), -3.441)
|
||||||
|
p2 = Plane(Vector([5.111, 6.358, 7.638]), -2.152)
|
||||||
|
p3 = Plane(Vector([2.016, -9.924, -1.367]), -9.278)
|
||||||
|
p4 = Plane(Vector([2.167, -13.543, -18.883]), -10.567)
|
||||||
|
```
|
||||||
|
|
||||||
|
- Vectors used for test is video 23:
|
||||||
|
```python
|
||||||
|
# Note that in the video the second vector is written as:
|
||||||
|
# Vector([-0.138, -0.138, 0.244]), but bellow is the right implementation
|
||||||
|
p1 = Plane(Vector([0.786, 0.786, 0.588]), -0.714)
|
||||||
|
p2 = Plane(Vector([-0.131, -0.131, 0.244]), 0.319)
|
||||||
|
```
|
||||||
|
```python
|
||||||
|
p1 = Plane(Vector([8.631, 5.112, -1.816]), -5.113)
|
||||||
|
p2 = Plane(Vector([4.315, 11.132, -5.27]), -6.775)
|
||||||
|
p3 = Plane(Vector([-2.158, 3.01, -1.727]), -0.831)
|
||||||
|
```
|
||||||
|
```python
|
||||||
|
p1 = Plane(Vector([0.935, 1.76, -9.365]), -9.955)
|
||||||
|
p2 = Plane(Vector([0.187, 0.352, -1.873]), -1.991)
|
||||||
|
p3 = Plane(Vector([0.374, 0.704, -3.746]), -3.982)
|
||||||
|
p4 = Plane(Vector([-0.561, -1.056, 5.619]), 5.973)
|
||||||
|
```
|
||||||
8
von_Udacity/README.md
Executable file
8
von_Udacity/README.md
Executable file
@@ -0,0 +1,8 @@
|
|||||||
|
[Udacity Linear algebra refresher course](https://www.udacity.com/course/viewer#!/c-ud953) as a "pre-requisite" to do
|
||||||
|
[Udacity's Machine Learning nanodegree](https://www.udacity.com/course/machine-learning-engineer-nanodegree--nd009).
|
||||||
|
|
||||||
|
- To avoid syntax errors when completing the assignments copy-paste the vectors, lines and planes in [OBJECTS_USED_IN_TESTS.md](https://github.com/omarrayward/Linear-Algebra-Refresher-Udacity/blob/master/OBJECTS_USED_IN_TESTS.md) used in them.
|
||||||
|
|
||||||
|
- To follow the course explanation with my own notes go to [NOTES.md](https://github.com/omarrayward/Linear-Algebra-Refresher-Udacity/blob/master/NOTES.md)
|
||||||
|
|
||||||
|
- I also found a couple of [bugs](https://github.com/omarrayward/Linear-Algebra-Refresher-Udacity/blob/master/NOTES.md#bugs-in-the-course) in the course.
|
||||||
147
von_Udacity/hyperplane.py
Executable file
147
von_Udacity/hyperplane.py
Executable file
@@ -0,0 +1,147 @@
|
|||||||
|
from decimal import Decimal, getcontext
|
||||||
|
from vector import Vector
|
||||||
|
|
||||||
|
getcontext().prec = 30
|
||||||
|
|
||||||
|
|
||||||
|
class MyDecimal(Decimal):
|
||||||
|
def is_near_zero(self, eps=1e-10):
|
||||||
|
return abs(self) < eps
|
||||||
|
|
||||||
|
|
||||||
|
class Hyperplane(object):
|
||||||
|
|
||||||
|
NO_NONZERO_ELTS_FOUND_MSG = 'No nonzero elements found'
|
||||||
|
EITHER_DIM_OR_NORMAL_VEC_MUST_BE_PROVIDED_MSG = (
|
||||||
|
'Either the dimension of the hyperplane or the normal vector '
|
||||||
|
'must be provided')
|
||||||
|
|
||||||
|
def __init__(self, dimension=None, normal_vector=None, constant_term=None):
|
||||||
|
if not dimension and not normal_vector:
|
||||||
|
raise Exception(self.EITHER_DIM_OR_NORMAL_VEC_MUST_BE_PROVIDED_MSG)
|
||||||
|
|
||||||
|
elif not normal_vector:
|
||||||
|
self.dimension = dimension
|
||||||
|
all_zeros = ['0'] * self.dimension
|
||||||
|
normal_vector = Vector(all_zeros)
|
||||||
|
else:
|
||||||
|
self.dimension = normal_vector.dimension
|
||||||
|
|
||||||
|
self.normal_vector = normal_vector
|
||||||
|
|
||||||
|
if not constant_term:
|
||||||
|
constant_term = Decimal('0')
|
||||||
|
self.constant_term = Decimal(constant_term)
|
||||||
|
|
||||||
|
self.set_basepoint()
|
||||||
|
|
||||||
|
def set_basepoint(self):
|
||||||
|
try:
|
||||||
|
n = self.normal_vector
|
||||||
|
c = self.constant_term
|
||||||
|
basepoint_coords = ['0'] * self.dimension
|
||||||
|
|
||||||
|
initial_index = Hyperplane.first_nonzero_index(n)
|
||||||
|
initial_coefficient = n[initial_index]
|
||||||
|
|
||||||
|
basepoint_coords[initial_index] = c / initial_coefficient
|
||||||
|
self.basepoint = Vector(basepoint_coords)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
if str(e) == Hyperplane.NO_NONZERO_ELTS_FOUND_MSG:
|
||||||
|
self.basepoint = None
|
||||||
|
else:
|
||||||
|
raise e
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
|
||||||
|
num_decimal_places = 3
|
||||||
|
|
||||||
|
def write_coefficient(coefficient, is_initial_term=False):
|
||||||
|
coefficient = round(coefficient, num_decimal_places)
|
||||||
|
if coefficient % 1 == 0:
|
||||||
|
coefficient = int(coefficient)
|
||||||
|
|
||||||
|
output = ''
|
||||||
|
|
||||||
|
if coefficient < 0:
|
||||||
|
output += '-'
|
||||||
|
if coefficient > 0 and not is_initial_term:
|
||||||
|
output += '+'
|
||||||
|
|
||||||
|
if not is_initial_term:
|
||||||
|
output += ' '
|
||||||
|
|
||||||
|
if abs(coefficient) != 1:
|
||||||
|
output += '{}'.format(abs(coefficient))
|
||||||
|
|
||||||
|
return output
|
||||||
|
|
||||||
|
n = self.normal_vector
|
||||||
|
|
||||||
|
try:
|
||||||
|
initial_index = Hyperplane.first_nonzero_index(n)
|
||||||
|
terms = [write_coefficient(
|
||||||
|
n[i], is_initial_term=(i == initial_index)) +
|
||||||
|
'x_{}'.format(i + 1)
|
||||||
|
for i in range(self.dimension)
|
||||||
|
if round(n[i], num_decimal_places) != 0]
|
||||||
|
output = ' '.join(terms)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
if str(e) == self.NO_NONZERO_ELTS_FOUND_MSG:
|
||||||
|
output = '0'
|
||||||
|
else:
|
||||||
|
raise e
|
||||||
|
|
||||||
|
constant = round(self.constant_term, num_decimal_places)
|
||||||
|
if constant % 1 == 0:
|
||||||
|
constant = int(constant)
|
||||||
|
output += ' = {}'.format(constant)
|
||||||
|
|
||||||
|
return output
|
||||||
|
|
||||||
|
def is_parallel(self, plane2):
|
||||||
|
return self.normal_vector.is_parallel(plane2.normal_vector)
|
||||||
|
|
||||||
|
def __eq__(self, plane2):
|
||||||
|
if self.normal_vector.is_zero():
|
||||||
|
if not plane2.normal_vector.is_zero():
|
||||||
|
return False
|
||||||
|
|
||||||
|
diff = self.constant_term - plane2.constant_term
|
||||||
|
return MyDecimal(diff).is_near_zero()
|
||||||
|
|
||||||
|
elif plane2.normal_vector.is_zero():
|
||||||
|
return False
|
||||||
|
|
||||||
|
if not self.is_parallel(plane2):
|
||||||
|
return False
|
||||||
|
|
||||||
|
basepoint_difference = self.basepoint.minus(plane2.basepoint)
|
||||||
|
return basepoint_difference.is_orthogonal(self.normal_vector)
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
self.current = 0
|
||||||
|
return self
|
||||||
|
|
||||||
|
def next(self):
|
||||||
|
if self.current >= len(self.normal_vector):
|
||||||
|
raise StopIteration
|
||||||
|
else:
|
||||||
|
current_value = self.normal_vector[self.current]
|
||||||
|
self.current += 1
|
||||||
|
return current_value
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return len(self.normal_vector)
|
||||||
|
|
||||||
|
def __getitem__(self, i):
|
||||||
|
return self.normal_vector[i]
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def first_nonzero_index(iterable):
|
||||||
|
for k, item in enumerate(iterable):
|
||||||
|
if not MyDecimal(item).is_near_zero():
|
||||||
|
return k
|
||||||
|
raise Exception(Hyperplane.NO_NONZERO_ELTS_FOUND_MSG)
|
||||||
169
von_Udacity/line.py
Executable file
169
von_Udacity/line.py
Executable file
@@ -0,0 +1,169 @@
|
|||||||
|
from decimal import Decimal, getcontext
|
||||||
|
from vector import Vector
|
||||||
|
|
||||||
|
getcontext().prec = 30
|
||||||
|
|
||||||
|
|
||||||
|
class MyDecimal(Decimal):
|
||||||
|
def is_near_zero(self, eps=1e-10):
|
||||||
|
return abs(self) < eps
|
||||||
|
|
||||||
|
|
||||||
|
class Line(object):
|
||||||
|
|
||||||
|
NO_NONZERO_ELTS_FOUND_MSG = 'No nonzero elements found'
|
||||||
|
|
||||||
|
def __init__(self, normal_vector=None, constant_term=None):
|
||||||
|
self.dimension = 2
|
||||||
|
|
||||||
|
if not normal_vector:
|
||||||
|
all_zeros = ['0'] * self.dimension
|
||||||
|
normal_vector = Vector(all_zeros)
|
||||||
|
self.normal_vector = normal_vector
|
||||||
|
|
||||||
|
if not constant_term:
|
||||||
|
constant_term = Decimal('0')
|
||||||
|
self.constant_term = Decimal(constant_term)
|
||||||
|
|
||||||
|
self.set_basepoint()
|
||||||
|
|
||||||
|
def set_basepoint(self):
|
||||||
|
try:
|
||||||
|
n = self.normal_vector
|
||||||
|
c = self.constant_term
|
||||||
|
basepoint_coords = ['0'] * self.dimension
|
||||||
|
|
||||||
|
initial_index = Line.first_nonzero_index(n)
|
||||||
|
initial_coefficient = n[initial_index]
|
||||||
|
basepoint_coords[initial_index] = c / initial_coefficient
|
||||||
|
self.basepoint = Vector(basepoint_coords)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
if str(e) == Line.NO_NONZERO_ELTS_FOUND_MSG:
|
||||||
|
self.basepoint = None
|
||||||
|
else:
|
||||||
|
raise e
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
|
||||||
|
num_decimal_places = 3
|
||||||
|
|
||||||
|
def write_coefficient(coefficient, is_initial_term=False):
|
||||||
|
coefficient = round(coefficient, num_decimal_places)
|
||||||
|
if coefficient % 1 == 0:
|
||||||
|
coefficient = int(coefficient)
|
||||||
|
|
||||||
|
output = ''
|
||||||
|
|
||||||
|
if coefficient < 0:
|
||||||
|
output += '-'
|
||||||
|
if coefficient > 0 and not is_initial_term:
|
||||||
|
output += '+'
|
||||||
|
|
||||||
|
if not is_initial_term:
|
||||||
|
output += ' '
|
||||||
|
|
||||||
|
if abs(coefficient) != 1:
|
||||||
|
output += '{}'.format(abs(coefficient))
|
||||||
|
|
||||||
|
return output
|
||||||
|
|
||||||
|
n = self.normal_vector
|
||||||
|
|
||||||
|
try:
|
||||||
|
initial_index = Line.first_nonzero_index(n)
|
||||||
|
terms = [write_coefficient(n[i],
|
||||||
|
is_initial_term=(i == initial_index)) +
|
||||||
|
'x_{}'.format(i + 1)
|
||||||
|
for i in range(self.dimension)
|
||||||
|
if round(n[i], num_decimal_places) != 0]
|
||||||
|
output = ' '.join(terms)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
if str(e) == self.NO_NONZERO_ELTS_FOUND_MSG:
|
||||||
|
output = '0'
|
||||||
|
else:
|
||||||
|
raise e
|
||||||
|
|
||||||
|
constant = round(self.constant_term, num_decimal_places)
|
||||||
|
if constant % 1 == 0:
|
||||||
|
constant = int(constant)
|
||||||
|
output += ' = {}'.format(constant)
|
||||||
|
|
||||||
|
return output
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def first_nonzero_index(iterable):
|
||||||
|
for k, item in enumerate(iterable):
|
||||||
|
if not MyDecimal(item).is_near_zero():
|
||||||
|
return k
|
||||||
|
raise Exception(Line.NO_NONZERO_ELTS_FOUND_MSG)
|
||||||
|
|
||||||
|
def is_parallel(self, line2):
|
||||||
|
return self.normal_vector.is_parallel(line2.normal_vector)
|
||||||
|
|
||||||
|
def __eq__(self, line2):
|
||||||
|
if self.normal_vector.is_zero():
|
||||||
|
if not line2.normal_vector.is_zero():
|
||||||
|
return False
|
||||||
|
|
||||||
|
diff = self.constant_term - line2.constant_term
|
||||||
|
return MyDecimal(diff).is_near_zero()
|
||||||
|
|
||||||
|
elif line2.normal_vector.is_zero():
|
||||||
|
return False
|
||||||
|
|
||||||
|
if not self.is_parallel(line2):
|
||||||
|
return False
|
||||||
|
|
||||||
|
basepoint_difference = self.basepoint.minus(line2.basepoint)
|
||||||
|
return basepoint_difference.is_orthogonal(self.normal_vector)
|
||||||
|
|
||||||
|
def intersection(self, line2):
|
||||||
|
|
||||||
|
a, b = self.normal_vector.coordinates
|
||||||
|
c, d = line2.normal_vector.coordinates
|
||||||
|
k1 = self.constant_term
|
||||||
|
k2 = line2.constant_term
|
||||||
|
denom = ((a * d) - (b * c))
|
||||||
|
|
||||||
|
if MyDecimal(denom).is_near_zero():
|
||||||
|
if self == line2:
|
||||||
|
return self
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
one_over_denom = Decimal('1') / ((a * d) - (b * c))
|
||||||
|
x_num = (d * k1 - b * k2)
|
||||||
|
y_num = (-c * k1 + a * k2)
|
||||||
|
|
||||||
|
return Vector([x_num, y_num]).times_scalar(one_over_denom)
|
||||||
|
|
||||||
|
|
||||||
|
# first system
|
||||||
|
# 4.046x + 2.836y = 1.21
|
||||||
|
# 10.115x + 7.09y = 3.025
|
||||||
|
|
||||||
|
line1 = Line(Vector([4.046, 2.836]), 1.21)
|
||||||
|
line2 = Line(Vector([10.115, 7.09]), 3.025)
|
||||||
|
|
||||||
|
print 'first system instersects in: {}'.format(line1.intersection(line2))
|
||||||
|
|
||||||
|
|
||||||
|
# second system
|
||||||
|
# 7.204x + 3.182y = 8.68
|
||||||
|
# 8.172x + 4.114y = 9.883
|
||||||
|
|
||||||
|
line3 = Line(Vector([7.204, 3.182]), 8.68)
|
||||||
|
line4 = Line(Vector([8.172, 4.114]), 9.883)
|
||||||
|
|
||||||
|
print 'second system instersects in: {}'.format(line3.intersection(line4))
|
||||||
|
|
||||||
|
# third system
|
||||||
|
# 1.182x + 5.562y = 6.744
|
||||||
|
# 1.773x + 8.343y = 9.525
|
||||||
|
|
||||||
|
line5 = Line(Vector([1.182, 5.562]), 6.744)
|
||||||
|
line6 = Line(Vector([1.773, 8.343]), 9.525)
|
||||||
|
|
||||||
|
print 'third system instersects in: {}'.format(line5.intersection(line6))
|
||||||
520
von_Udacity/linear_system.py
Executable file
520
von_Udacity/linear_system.py
Executable file
@@ -0,0 +1,520 @@
|
|||||||
|
from copy import deepcopy
|
||||||
|
from decimal import Decimal, getcontext
|
||||||
|
from hyperplane import Hyperplane
|
||||||
|
from plane import Plane
|
||||||
|
from vector import Vector
|
||||||
|
|
||||||
|
getcontext().prec = 30
|
||||||
|
|
||||||
|
|
||||||
|
class MyDecimal(Decimal):
|
||||||
|
def is_near_zero(self, eps=1e-10):
|
||||||
|
return abs(self) < eps
|
||||||
|
|
||||||
|
|
||||||
|
def _get_new_plane(coefficient, plane):
|
||||||
|
new_normal_vector = plane.normal_vector.times_scalar(coefficient)
|
||||||
|
return Hyperplane(normal_vector=new_normal_vector,
|
||||||
|
constant_term=coefficient * plane.constant_term)
|
||||||
|
|
||||||
|
|
||||||
|
class LinearSystem(object):
|
||||||
|
|
||||||
|
ALL_PLANES_MUST_BE_IN_SAME_DIM_MSG = ('All planes in the system should '
|
||||||
|
'live in the same dimension')
|
||||||
|
NO_SOLUTIONS_MSG = 'No solutions'
|
||||||
|
INF_SOLUTIONS_MSG = 'Infinitely many solutions'
|
||||||
|
|
||||||
|
def __init__(self, planes):
|
||||||
|
try:
|
||||||
|
d = planes[0].dimension
|
||||||
|
for p in planes:
|
||||||
|
assert p.dimension == d
|
||||||
|
|
||||||
|
self.planes = planes
|
||||||
|
self.dimension = d
|
||||||
|
|
||||||
|
except AssertionError:
|
||||||
|
raise Exception(self.ALL_PLANES_MUST_BE_IN_SAME_DIM_MSG)
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return len(self.planes)
|
||||||
|
|
||||||
|
def __getitem__(self, i):
|
||||||
|
return self.planes[i]
|
||||||
|
|
||||||
|
def __setitem__(self, i, x):
|
||||||
|
try:
|
||||||
|
assert x.dimension == self.dimension
|
||||||
|
self.planes[i] = x
|
||||||
|
|
||||||
|
except AssertionError:
|
||||||
|
raise Exception(self.ALL_PLANES_MUST_BE_IN_SAME_DIM_MSG)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
ret = 'Linear System:\n'
|
||||||
|
temp = ['Equation {}: {}'.format(i + 1, p)
|
||||||
|
for i, p in enumerate(self.planes)]
|
||||||
|
ret += '\n'.join(temp)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def swap_rows(self, row1, row2):
|
||||||
|
self[row1], self[row2] = self[row2], self[row1]
|
||||||
|
|
||||||
|
def multiply_coefficient_and_row(self, coefficient, row):
|
||||||
|
self[row] = _get_new_plane(coefficient, self[row])
|
||||||
|
|
||||||
|
def add_multiple_times_row_to_row(self, coefficient, row_to_add,
|
||||||
|
row_to_be_added_to):
|
||||||
|
recipient_plane = self[row_to_be_added_to]
|
||||||
|
new_plane = _get_new_plane(coefficient, self[row_to_add])
|
||||||
|
new_normal_vector = \
|
||||||
|
recipient_plane.normal_vector.plus(new_plane.normal_vector)
|
||||||
|
constant_term = new_plane.constant_term + recipient_plane.constant_term
|
||||||
|
self[row_to_be_added_to] = Hyperplane(normal_vector=new_normal_vector,
|
||||||
|
constant_term=constant_term)
|
||||||
|
|
||||||
|
def indices_of_first_nonzero_terms_in_each_row(self):
|
||||||
|
num_equations = len(self)
|
||||||
|
|
||||||
|
indices = [-1] * num_equations
|
||||||
|
|
||||||
|
for i, p in enumerate(self.planes):
|
||||||
|
try:
|
||||||
|
p.first_nonzero_index(p.normal_vector)
|
||||||
|
indices[i] = p.first_nonzero_index(p.normal_vector)
|
||||||
|
except Exception as e:
|
||||||
|
if str(e) == Plane.NO_NONZERO_ELTS_FOUND_MSG:
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
raise e
|
||||||
|
|
||||||
|
return indices
|
||||||
|
|
||||||
|
def compute_triangular_form(self):
|
||||||
|
system = deepcopy(self)
|
||||||
|
|
||||||
|
num_equations = len(system)
|
||||||
|
num_variables = system.dimension
|
||||||
|
|
||||||
|
col = 0
|
||||||
|
for row in range(num_equations):
|
||||||
|
while col < num_variables:
|
||||||
|
c = MyDecimal(system[row].normal_vector[col])
|
||||||
|
if c.is_near_zero():
|
||||||
|
swap_succeeded = system.did_swap_with_row_below(row, col)
|
||||||
|
if not swap_succeeded:
|
||||||
|
col += 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
system.clear_coefficients_bellow(row, col)
|
||||||
|
col += 1
|
||||||
|
break
|
||||||
|
|
||||||
|
return system
|
||||||
|
|
||||||
|
def did_swap_with_row_below(self, row, col):
|
||||||
|
num_equations = len(self)
|
||||||
|
|
||||||
|
for k in range(row + 1, num_equations):
|
||||||
|
coefficient = MyDecimal(self[k].normal_vector[col])
|
||||||
|
if not coefficient.is_near_zero():
|
||||||
|
self.swap_rows(row, k)
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
def clear_coefficients_bellow(self, row, col):
|
||||||
|
num_equations = len(self)
|
||||||
|
beta = MyDecimal(self[row].normal_vector[col])
|
||||||
|
|
||||||
|
for row_to_be_added_to in range(row + 1, num_equations):
|
||||||
|
n = self[row_to_be_added_to].normal_vector
|
||||||
|
gamma = n[col]
|
||||||
|
alpha = -gamma / beta
|
||||||
|
self.add_multiple_times_row_to_row(alpha, row, row_to_be_added_to)
|
||||||
|
|
||||||
|
def clear_coefficients_above(self, row, col):
|
||||||
|
for row_to_be_added_to in range(row)[::-1]:
|
||||||
|
n = self[row_to_be_added_to].normal_vector
|
||||||
|
alpha = -(n[col])
|
||||||
|
self.add_multiple_times_row_to_row(alpha, row, row_to_be_added_to)
|
||||||
|
|
||||||
|
def compute_rref(self):
|
||||||
|
tf = self.compute_triangular_form()
|
||||||
|
|
||||||
|
num_equations = len(tf)
|
||||||
|
pivot_indices = tf.indices_of_first_nonzero_terms_in_each_row()
|
||||||
|
|
||||||
|
for row in range(num_equations)[::-1]:
|
||||||
|
pivot_var = pivot_indices[row]
|
||||||
|
if pivot_var < 0:
|
||||||
|
continue
|
||||||
|
tf.scale_row_to_make_coefficient_equal_one(row, pivot_var)
|
||||||
|
tf.clear_coefficients_above(row, pivot_var)
|
||||||
|
|
||||||
|
return tf
|
||||||
|
|
||||||
|
def scale_row_to_make_coefficient_equal_one(self, row, col):
|
||||||
|
n = self[row].normal_vector
|
||||||
|
beta = Decimal('1.0') / n[col]
|
||||||
|
self.multiply_coefficient_and_row(beta, row)
|
||||||
|
|
||||||
|
def do_gaussian_elimination(self):
|
||||||
|
rref = self.compute_rref()
|
||||||
|
|
||||||
|
try:
|
||||||
|
rref.raise_excepion_if_contradictory_equation()
|
||||||
|
rref.raise_excepion_if_too_few_pivots()
|
||||||
|
except Exception as e:
|
||||||
|
return e.message
|
||||||
|
|
||||||
|
num_variables = rref.dimension
|
||||||
|
solution_coordinates = [rref.planes[i].constant_term
|
||||||
|
for i in range(num_variables)]
|
||||||
|
|
||||||
|
return Vector(solution_coordinates)
|
||||||
|
|
||||||
|
def raise_excepion_if_contradictory_equation(self):
|
||||||
|
for plane in self.planes:
|
||||||
|
try:
|
||||||
|
plane.first_nonzero_index(plane.normal_vector)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
if str(e) == 'No nonzero elements found':
|
||||||
|
constant_term = MyDecimal(plane.constant_term)
|
||||||
|
if not constant_term.is_near_zero():
|
||||||
|
raise Exception(self.NO_SOLUTIONS_MSG)
|
||||||
|
|
||||||
|
else:
|
||||||
|
raise e
|
||||||
|
|
||||||
|
def raise_excepion_if_too_few_pivots(self):
|
||||||
|
pivot_indices = self.indices_of_first_nonzero_terms_in_each_row()
|
||||||
|
num_pivots = sum([1 if index >= 0 else 0 for index in pivot_indices])
|
||||||
|
num_variables = self.dimension
|
||||||
|
|
||||||
|
if num_pivots < num_variables:
|
||||||
|
raise Exception(self.INF_SOLUTIONS_MSG)
|
||||||
|
|
||||||
|
def compute_solution(self):
|
||||||
|
try:
|
||||||
|
return self.do_gaussian_elimination_and_parametrization()
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
if str(e) == self.NO_SOLUTIONS_MSG:
|
||||||
|
return str(e)
|
||||||
|
else:
|
||||||
|
raise e
|
||||||
|
|
||||||
|
def do_gaussian_elimination_and_parametrization(self):
|
||||||
|
rref = self.compute_rref()
|
||||||
|
rref.raise_excepion_if_contradictory_equation()
|
||||||
|
|
||||||
|
direction_vectors = rref.extract_direction_vectors_for_parametrization() # NOQA
|
||||||
|
basepoint = rref.extract_basepoint_for_parametrization()
|
||||||
|
|
||||||
|
return Parametrization(basepoint, direction_vectors)
|
||||||
|
|
||||||
|
def extract_direction_vectors_for_parametrization(self):
|
||||||
|
num_variables = self.dimension
|
||||||
|
pivot_indices = self.indices_of_first_nonzero_terms_in_each_row()
|
||||||
|
free_variable_indices = set(range(num_variables)) - set(pivot_indices)
|
||||||
|
|
||||||
|
direction_vectors = []
|
||||||
|
|
||||||
|
for free_var in free_variable_indices:
|
||||||
|
vector_coords = [0] * num_variables
|
||||||
|
vector_coords[free_var] = 1
|
||||||
|
for index, plane in enumerate(self.planes):
|
||||||
|
pivot_var = pivot_indices[index]
|
||||||
|
if pivot_var < 0:
|
||||||
|
break
|
||||||
|
vector_coords[pivot_var] = -plane.normal_vector[free_var]
|
||||||
|
|
||||||
|
direction_vectors.append(Vector(vector_coords))
|
||||||
|
|
||||||
|
return direction_vectors
|
||||||
|
|
||||||
|
def extract_basepoint_for_parametrization(self):
|
||||||
|
num_variables = self.dimension
|
||||||
|
pivot_indices = self.indices_of_first_nonzero_terms_in_each_row()
|
||||||
|
|
||||||
|
basepoint_coords = [0] * num_variables
|
||||||
|
|
||||||
|
for index, plane in enumerate(self.planes):
|
||||||
|
pivot_var = pivot_indices[index]
|
||||||
|
if pivot_var < 0:
|
||||||
|
break
|
||||||
|
basepoint_coords[pivot_var] = plane.constant_term
|
||||||
|
|
||||||
|
return Vector(basepoint_coords)
|
||||||
|
|
||||||
|
|
||||||
|
p0 = Plane(normal_vector=Vector(['1', '1', '1']), constant_term='1')
|
||||||
|
p1 = Plane(normal_vector=Vector(['0', '1', '0']), constant_term='2')
|
||||||
|
p2 = Plane(normal_vector=Vector(['1', '1', '-1']), constant_term='3')
|
||||||
|
p3 = Plane(normal_vector=Vector(['1', '0', '-2']), constant_term='2')
|
||||||
|
|
||||||
|
s = LinearSystem([p0, p1, p2, p3])
|
||||||
|
# Print initial system
|
||||||
|
# print s
|
||||||
|
|
||||||
|
p0 = Plane(normal_vector=Vector(['1', '1', '1']), constant_term='1')
|
||||||
|
p1 = Plane(normal_vector=Vector(['0', '1', '0']), constant_term='2')
|
||||||
|
p2 = Plane(normal_vector=Vector(['1', '1', '-1']), constant_term='3')
|
||||||
|
p3 = Plane(normal_vector=Vector(['1', '0', '-2']), constant_term='2')
|
||||||
|
|
||||||
|
s = LinearSystem([p0, p1, p2, p3])
|
||||||
|
s.swap_rows(0, 1)
|
||||||
|
if not (s[0] == p1 and s[1] == p0 and s[2] == p2 and s[3] == p3):
|
||||||
|
print 'test case 1 failed'
|
||||||
|
|
||||||
|
s.swap_rows(1, 3)
|
||||||
|
if not (s[0] == p1 and s[1] == p3 and s[2] == p2 and s[3] == p0):
|
||||||
|
print 'test case 2 failed'
|
||||||
|
|
||||||
|
s.swap_rows(3, 1)
|
||||||
|
if not (s[0] == p1 and s[1] == p0 and s[2] == p2 and s[3] == p3):
|
||||||
|
print 'test case 3 failed'
|
||||||
|
|
||||||
|
s.multiply_coefficient_and_row(1, 0)
|
||||||
|
if not (s[0] == p1 and s[1] == p0 and s[2] == p2 and s[3] == p3):
|
||||||
|
print 'test case 4 failed'
|
||||||
|
|
||||||
|
s.multiply_coefficient_and_row(-1, 2)
|
||||||
|
new_s2 = Plane(normal_vector=Vector(['-1', '-1', '1']), constant_term='-3')
|
||||||
|
if not (s[0] == p1 and
|
||||||
|
s[1] == p0 and
|
||||||
|
s[2] == new_s2 and
|
||||||
|
s[3] == p3):
|
||||||
|
print 'test case 5 failed'
|
||||||
|
|
||||||
|
s.multiply_coefficient_and_row(10, 1)
|
||||||
|
new_s1 = Plane(normal_vector=Vector(['10', '10', '10']), constant_term='10')
|
||||||
|
if not (s[0] == p1 and
|
||||||
|
s[1] == new_s1 and
|
||||||
|
s[2] == new_s2 and
|
||||||
|
s[3] == p3):
|
||||||
|
print 'test case 6 failed'
|
||||||
|
|
||||||
|
s.add_multiple_times_row_to_row(0, 0, 1)
|
||||||
|
if not (s[0] == p1 and
|
||||||
|
s[1] == new_s1 and
|
||||||
|
s[2] == new_s2 and
|
||||||
|
s[3] == p3):
|
||||||
|
print 'test case 7 failed'
|
||||||
|
|
||||||
|
s.add_multiple_times_row_to_row(1, 0, 1)
|
||||||
|
added_s1 = Plane(normal_vector=Vector(['10', '11', '10']), constant_term='12')
|
||||||
|
if not (s[0] == p1 and
|
||||||
|
s[1] == added_s1 and
|
||||||
|
s[2] == new_s2 and
|
||||||
|
s[3] == p3):
|
||||||
|
print 'test case 8 failed'
|
||||||
|
|
||||||
|
s.add_multiple_times_row_to_row(-1, 1, 0)
|
||||||
|
new_s0 = Plane(normal_vector=Vector(['-10', '-10', '-10']),
|
||||||
|
constant_term='-10')
|
||||||
|
if not (s[0] == new_s0 and
|
||||||
|
s[1] == added_s1 and
|
||||||
|
s[2] == new_s2 and
|
||||||
|
s[3] == p3):
|
||||||
|
print 'test case 9 failed'
|
||||||
|
|
||||||
|
p1 = Plane(normal_vector=Vector(['1', '1', '1']), constant_term='1')
|
||||||
|
p2 = Plane(normal_vector=Vector(['0', '1', '1']), constant_term='2')
|
||||||
|
s = LinearSystem([p1, p2])
|
||||||
|
t = s.compute_triangular_form()
|
||||||
|
if not (t[0] == p1 and
|
||||||
|
t[1] == p2):
|
||||||
|
print 'test case 1 failed'
|
||||||
|
|
||||||
|
p1 = Plane(normal_vector=Vector(['1', '1', '1']), constant_term='1')
|
||||||
|
p2 = Plane(normal_vector=Vector(['1', '1', '1']), constant_term='2')
|
||||||
|
s = LinearSystem([p1, p2])
|
||||||
|
t = s.compute_triangular_form()
|
||||||
|
if not (t[0] == p1 and
|
||||||
|
t[1] == Plane(constant_term='1')):
|
||||||
|
print 'test case 2 failed'
|
||||||
|
|
||||||
|
p1 = Plane(normal_vector=Vector(['1', '1', '1']), constant_term='1')
|
||||||
|
p2 = Plane(normal_vector=Vector(['0', '1', '0']), constant_term='2')
|
||||||
|
p3 = Plane(normal_vector=Vector(['1', '1', '-1']), constant_term='3')
|
||||||
|
p4 = Plane(normal_vector=Vector(['1', '0', '-2']), constant_term='2')
|
||||||
|
s = LinearSystem([p1, p2, p3, p4])
|
||||||
|
t = s.compute_triangular_form()
|
||||||
|
if not (t[0] == p1 and
|
||||||
|
t[1] == p2 and
|
||||||
|
t[2] == Plane(normal_vector=Vector(['0', '0', '-2']),
|
||||||
|
constant_term='2') and
|
||||||
|
t[3] == Plane()):
|
||||||
|
print 'test case 3 failed'
|
||||||
|
|
||||||
|
p1 = Plane(normal_vector=Vector(['0', '1', '1']), constant_term='1')
|
||||||
|
p2 = Plane(normal_vector=Vector(['1', '-1', '1']), constant_term='2')
|
||||||
|
p3 = Plane(normal_vector=Vector(['1', '2', '-5']), constant_term='3')
|
||||||
|
s = LinearSystem([p1, p2, p3])
|
||||||
|
t = s.compute_triangular_form()
|
||||||
|
if not (t[0] == Plane(normal_vector=Vector(['1', '-1', '1']),
|
||||||
|
constant_term='2') and
|
||||||
|
t[1] == Plane(normal_vector=Vector(['0', '1', '1']),
|
||||||
|
constant_term='1') and
|
||||||
|
t[2] == Plane(normal_vector=Vector(['0', '0', '-9']),
|
||||||
|
constant_term='-2')):
|
||||||
|
print 'test case 4 failed'
|
||||||
|
|
||||||
|
|
||||||
|
# ***************
|
||||||
|
|
||||||
|
p1 = Plane(normal_vector=Vector(['1', '1', '1']), constant_term='1')
|
||||||
|
p2 = Plane(normal_vector=Vector(['0', '1', '1']), constant_term='2')
|
||||||
|
s = LinearSystem([p1, p2])
|
||||||
|
r = s.compute_rref()
|
||||||
|
if not (r[0] == Plane(normal_vector=Vector(['1', '0', '0']),
|
||||||
|
constant_term='-1') and
|
||||||
|
r[1] == p2):
|
||||||
|
print 'test case 1 failed'
|
||||||
|
|
||||||
|
p1 = Plane(normal_vector=Vector(['1', '1', '1']), constant_term='1')
|
||||||
|
p2 = Plane(normal_vector=Vector(['1', '1', '1']), constant_term='2')
|
||||||
|
s = LinearSystem([p1, p2])
|
||||||
|
r = s.compute_rref()
|
||||||
|
if not (r[0] == p1 and
|
||||||
|
r[1] == Plane(constant_term='1')):
|
||||||
|
print 'test case 2 failed'
|
||||||
|
|
||||||
|
p1 = Plane(normal_vector=Vector(['1', '1', '1']), constant_term='1')
|
||||||
|
p2 = Plane(normal_vector=Vector(['0', '1', '0']), constant_term='2')
|
||||||
|
p3 = Plane(normal_vector=Vector(['1', '1', '-1']), constant_term='3')
|
||||||
|
p4 = Plane(normal_vector=Vector(['1', '0', '-2']), constant_term='2')
|
||||||
|
s = LinearSystem([p1, p2, p3, p4])
|
||||||
|
r = s.compute_rref()
|
||||||
|
if not (r[0] == Plane(normal_vector=Vector(['1', '0', '0']),
|
||||||
|
constant_term='0') and
|
||||||
|
r[1] == p2 and
|
||||||
|
r[2] == Plane(normal_vector=Vector(['0', '0', '-2']),
|
||||||
|
constant_term='2') and
|
||||||
|
r[3] == Plane()):
|
||||||
|
print 'test case 3 failed'
|
||||||
|
|
||||||
|
p1 = Plane(normal_vector=Vector(['0', '1', '1']), constant_term='1')
|
||||||
|
p2 = Plane(normal_vector=Vector(['1', '-1', '1']), constant_term='2')
|
||||||
|
p3 = Plane(normal_vector=Vector(['1', '2', '-5']), constant_term='3')
|
||||||
|
s = LinearSystem([p1, p2, p3])
|
||||||
|
r = s.compute_rref()
|
||||||
|
if not (r[0] == Plane(normal_vector=Vector(['1', '0', '0']),
|
||||||
|
constant_term=Decimal('23') / Decimal('9')) and
|
||||||
|
r[1] == Plane(normal_vector=Vector(['0', '1', '0']),
|
||||||
|
constant_term=Decimal('7') / Decimal('9')) and
|
||||||
|
r[2] == Plane(normal_vector=Vector(['0', '0', '1']),
|
||||||
|
constant_term=Decimal('2') / Decimal('9'))):
|
||||||
|
print 'test case 4 failed'
|
||||||
|
|
||||||
|
|
||||||
|
# first system
|
||||||
|
p1 = Plane(Vector([5.862, 1.178, -10.366]), -8.15)
|
||||||
|
p2 = Plane(Vector([-2.931, -0.589, 5.183]), -4.075)
|
||||||
|
system1 = LinearSystem([p1, p2])
|
||||||
|
print 'first system: {}'.format(system1.do_gaussian_elimination())
|
||||||
|
|
||||||
|
|
||||||
|
# # second system
|
||||||
|
p1 = Plane(Vector([8.631, 5.112, -1.816]), -5.113)
|
||||||
|
p2 = Plane(Vector([4.315, 11.132, -5.27]), -6.775)
|
||||||
|
p3 = Plane(Vector([-2.158, 3.01, -1.727]), -0.831)
|
||||||
|
system2 = LinearSystem([p1, p2, p3])
|
||||||
|
print 'second system: {}'.format(system2.do_gaussian_elimination())
|
||||||
|
|
||||||
|
|
||||||
|
# third system
|
||||||
|
p1 = Plane(Vector([5.262, 2.739, -9.878]), -3.441)
|
||||||
|
p2 = Plane(Vector([5.111, 6.358, 7.638]), -2.152)
|
||||||
|
p3 = Plane(Vector([2.016, -9.924, -1.367]), -9.278)
|
||||||
|
p4 = Plane(Vector([2.167, -13.543, -18.883]), -10.567)
|
||||||
|
system3 = LinearSystem([p1, p2, p3, p4])
|
||||||
|
print 'thrid system: {} '.format(system3.do_gaussian_elimination())
|
||||||
|
|
||||||
|
|
||||||
|
class Parametrization(object):
|
||||||
|
|
||||||
|
BASEPT_AND_DIR_VECTORS_MUST_BE_IN_SAME_DIM = (
|
||||||
|
'The basepoint and direction vectors should all live in the same '
|
||||||
|
'dimension')
|
||||||
|
|
||||||
|
def __init__(self, basepoint, direction_vectors):
|
||||||
|
|
||||||
|
self.basepoint = basepoint
|
||||||
|
self.direction_vectors = direction_vectors
|
||||||
|
self.dimension = self.basepoint.dimension
|
||||||
|
|
||||||
|
try:
|
||||||
|
for v in direction_vectors:
|
||||||
|
assert v.dimension == self.dimension
|
||||||
|
|
||||||
|
except AssertionError:
|
||||||
|
raise Exception(self.BASEPT_AND_DIR_VECTORS_MUST_BE_IN_SAME_DIM)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
|
||||||
|
output = ''
|
||||||
|
for coord in range(self.dimension):
|
||||||
|
output += 'x_{} = {} '.format(coord + 1,
|
||||||
|
round(self.basepoint[coord], 3))
|
||||||
|
for free_var, vector in enumerate(self.direction_vectors):
|
||||||
|
output += '+ {} t_{}'.format(round(vector[coord], 3),
|
||||||
|
free_var + 1)
|
||||||
|
output += '\n'
|
||||||
|
return output
|
||||||
|
|
||||||
|
|
||||||
|
p1 = Plane(normal_vector=Vector([0.786, 0.786, 0.588]), constant_term=-0.714)
|
||||||
|
p2 = Plane(normal_vector=Vector([-0.131, -0.131, 0.244]), constant_term=0.319)
|
||||||
|
|
||||||
|
system = LinearSystem([p1, p2])
|
||||||
|
print system.compute_solution()
|
||||||
|
|
||||||
|
|
||||||
|
p1 = Plane(Vector([8.631, 5.112, -1.816]), -5.113)
|
||||||
|
p2 = Plane(Vector([4.315, 11.132, -5.27]), -6.775)
|
||||||
|
p3 = Plane(Vector([-2.158, 3.01, -1.727]), -0.831)
|
||||||
|
|
||||||
|
system = LinearSystem([p1, p2, p3])
|
||||||
|
print system.compute_solution()
|
||||||
|
|
||||||
|
p1 = Plane(Vector([0.935, 1.76, -9.365]), -9.955)
|
||||||
|
p2 = Plane(Vector([0.187, 0.352, -1.873]), -1.991)
|
||||||
|
p3 = Plane(Vector([0.374, 0.704, -3.746]), -3.982)
|
||||||
|
p4 = Plane(Vector([-0.561, -1.056, 5.619]), 5.973)
|
||||||
|
|
||||||
|
print system.compute_solution()
|
||||||
|
|
||||||
|
|
||||||
|
# The systems bellow are just to test hyperplanes
|
||||||
|
|
||||||
|
p1 = Hyperplane(normal_vector=Vector([0.786, 0.786]), constant_term=0.786)
|
||||||
|
p2 = Hyperplane(normal_vector=Vector([-0.131, -0.131]), constant_term=-0.131)
|
||||||
|
|
||||||
|
system = LinearSystem([p1, p2])
|
||||||
|
print system.compute_solution()
|
||||||
|
|
||||||
|
|
||||||
|
p1 = Hyperplane(normal_vector=Vector([2.102, 7.489, -0.786]),
|
||||||
|
constant_term=-5.113)
|
||||||
|
p2 = Hyperplane(normal_vector=Vector([-1.131, 8.318, -1.209]),
|
||||||
|
constant_term=-6.775)
|
||||||
|
p3 = Hyperplane(normal_vector=Vector([9.015, 5.873, -1.105]),
|
||||||
|
constant_term=-0.831)
|
||||||
|
|
||||||
|
system = LinearSystem([p1, p2, p3])
|
||||||
|
print system.compute_solution()
|
||||||
|
|
||||||
|
p1 = Hyperplane(normal_vector=Vector([0.786, 0.786, 8.123, 1.111, -8.363]),
|
||||||
|
constant_term=-9.955)
|
||||||
|
p2 = Hyperplane(normal_vector=Vector([0.131, -0.131, 7.05, -2.813, 1.19]),
|
||||||
|
constant_term=-1.991)
|
||||||
|
p3 = Hyperplane(normal_vector=Vector([9.015, -5.873, -1.105, 2.013, -2.802]),
|
||||||
|
constant_term=-3.982)
|
||||||
|
|
||||||
|
system = LinearSystem([p1, p2, p3])
|
||||||
|
print system.compute_solution()
|
||||||
171
von_Udacity/plane.py
Executable file
171
von_Udacity/plane.py
Executable file
@@ -0,0 +1,171 @@
|
|||||||
|
from decimal import Decimal, getcontext
|
||||||
|
from vector import Vector
|
||||||
|
|
||||||
|
getcontext().prec = 30
|
||||||
|
|
||||||
|
|
||||||
|
class MyDecimal(Decimal):
|
||||||
|
def is_near_zero(self, eps=1e-10):
|
||||||
|
return abs(self) < eps
|
||||||
|
|
||||||
|
|
||||||
|
class Plane(object):
|
||||||
|
|
||||||
|
NO_NONZERO_ELTS_FOUND_MSG = 'No nonzero elements found'
|
||||||
|
|
||||||
|
def __init__(self, normal_vector=None, constant_term=None):
|
||||||
|
self.dimension = 3
|
||||||
|
|
||||||
|
if not normal_vector:
|
||||||
|
all_zeros = ['0'] * self.dimension
|
||||||
|
normal_vector = Vector(all_zeros)
|
||||||
|
self.normal_vector = normal_vector
|
||||||
|
|
||||||
|
if not constant_term:
|
||||||
|
constant_term = Decimal('0')
|
||||||
|
self.constant_term = Decimal(constant_term)
|
||||||
|
|
||||||
|
self.set_basepoint()
|
||||||
|
|
||||||
|
def set_basepoint(self):
|
||||||
|
try:
|
||||||
|
n = self.normal_vector
|
||||||
|
c = self.constant_term
|
||||||
|
basepoint_coords = ['0'] * self.dimension
|
||||||
|
|
||||||
|
initial_index = Plane.first_nonzero_index(n)
|
||||||
|
initial_coefficient = n[initial_index]
|
||||||
|
|
||||||
|
basepoint_coords[initial_index] = c / initial_coefficient
|
||||||
|
self.basepoint = Vector(basepoint_coords)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
if str(e) == Plane.NO_NONZERO_ELTS_FOUND_MSG:
|
||||||
|
self.basepoint = None
|
||||||
|
else:
|
||||||
|
raise e
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
|
||||||
|
num_decimal_places = 3
|
||||||
|
|
||||||
|
def write_coefficient(coefficient, is_initial_term=False):
|
||||||
|
coefficient = round(coefficient, num_decimal_places)
|
||||||
|
if coefficient % 1 == 0:
|
||||||
|
coefficient = int(coefficient)
|
||||||
|
|
||||||
|
output = ''
|
||||||
|
|
||||||
|
if coefficient < 0:
|
||||||
|
output += '-'
|
||||||
|
if coefficient > 0 and not is_initial_term:
|
||||||
|
output += '+'
|
||||||
|
|
||||||
|
if not is_initial_term:
|
||||||
|
output += ' '
|
||||||
|
|
||||||
|
if abs(coefficient) != 1:
|
||||||
|
output += '{}'.format(abs(coefficient))
|
||||||
|
|
||||||
|
return output
|
||||||
|
|
||||||
|
n = self.normal_vector
|
||||||
|
|
||||||
|
try:
|
||||||
|
initial_index = Plane.first_nonzero_index(n)
|
||||||
|
terms = [write_coefficient(
|
||||||
|
n[i], is_initial_term=(i == initial_index)) +
|
||||||
|
'x_{}'.format(i + 1)
|
||||||
|
for i in range(self.dimension)
|
||||||
|
if round(n[i], num_decimal_places) != 0]
|
||||||
|
output = ' '.join(terms)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
if str(e) == self.NO_NONZERO_ELTS_FOUND_MSG:
|
||||||
|
output = '0'
|
||||||
|
else:
|
||||||
|
raise e
|
||||||
|
|
||||||
|
constant = round(self.constant_term, num_decimal_places)
|
||||||
|
if constant % 1 == 0:
|
||||||
|
constant = int(constant)
|
||||||
|
output += ' = {}'.format(constant)
|
||||||
|
|
||||||
|
return output
|
||||||
|
|
||||||
|
def is_parallel(self, plane2):
|
||||||
|
return self.normal_vector.is_parallel(plane2.normal_vector)
|
||||||
|
|
||||||
|
def __eq__(self, plane2):
|
||||||
|
if self.normal_vector.is_zero():
|
||||||
|
if not plane2.normal_vector.is_zero():
|
||||||
|
return False
|
||||||
|
|
||||||
|
diff = self.constant_term - plane2.constant_term
|
||||||
|
return MyDecimal(diff).is_near_zero()
|
||||||
|
|
||||||
|
elif plane2.normal_vector.is_zero():
|
||||||
|
return False
|
||||||
|
|
||||||
|
if not self.is_parallel(plane2):
|
||||||
|
return False
|
||||||
|
|
||||||
|
basepoint_difference = self.basepoint.minus(plane2.basepoint)
|
||||||
|
return basepoint_difference.is_orthogonal(self.normal_vector)
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
self.current = 0
|
||||||
|
return self
|
||||||
|
|
||||||
|
def next(self):
|
||||||
|
if self.current >= len(self.normal_vector):
|
||||||
|
raise StopIteration
|
||||||
|
else:
|
||||||
|
current_value = self.normal_vector[self.current]
|
||||||
|
self.current += 1
|
||||||
|
return current_value
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return len(self.normal_vector)
|
||||||
|
|
||||||
|
def __getitem__(self, i):
|
||||||
|
return self.normal_vector[i]
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def first_nonzero_index(iterable):
|
||||||
|
for k, item in enumerate(iterable):
|
||||||
|
if not MyDecimal(item).is_near_zero():
|
||||||
|
return k
|
||||||
|
raise Exception(Plane.NO_NONZERO_ELTS_FOUND_MSG)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
# first system of planes:
|
||||||
|
# -0.412x + 3.806y + 0.728z = -3.46
|
||||||
|
# 1.03x - 9.515y - 1.82z = 8.65
|
||||||
|
|
||||||
|
plane1 = Plane(Vector([-0.412, 3.806, 0.728]), -3.46)
|
||||||
|
plane2 = Plane(Vector([1.03, -9.515, -1.82]), 8.65)
|
||||||
|
|
||||||
|
print '1 is parallel: {}'.format(plane1.is_parallel(plane2))
|
||||||
|
print '1 is equal: {}'.format(plane1 == plane2)
|
||||||
|
|
||||||
|
# second system of planes:
|
||||||
|
# 2.611x + 5.528y + 0.283z = 4.6
|
||||||
|
# 7.715x + 8.306y + 5.342z = 3.76
|
||||||
|
|
||||||
|
plane3 = Plane(Vector([2.611, 5.528, 0.283]), 4.6)
|
||||||
|
plane4 = Plane(Vector([7.715, 8.306, 5.342]), 3.76)
|
||||||
|
|
||||||
|
print '2 is parallel: {}'.format(plane3.is_parallel(plane4))
|
||||||
|
print '2 is equal: {}'.format(plane3 == plane4)
|
||||||
|
|
||||||
|
# third system of planes:
|
||||||
|
# -7.926x + 8.625y - 7.212z = -7.952
|
||||||
|
# -2.642x + 2.875y - 2.404z = -2.443
|
||||||
|
|
||||||
|
plane5 = Plane(Vector([-7.926, 8.625, -7.212]), -7.952)
|
||||||
|
plane6 = Plane(Vector([-2.642, 2.875, -2.404]), -2.443)
|
||||||
|
|
||||||
|
print '3 is parallel: {}'.format(plane5.is_parallel(plane6))
|
||||||
|
print '3 is equal: {}'.format(plane5 == plane6)
|
||||||
204
von_Udacity/summary.py
Executable file
204
von_Udacity/summary.py
Executable file
@@ -0,0 +1,204 @@
|
|||||||
|
# Purpose: Combining the information learned from the course linear algebra into an interactive code which can be
|
||||||
|
# used to test equations easily.
|
||||||
|
|
||||||
|
from vector import Vector
|
||||||
|
from line import Line
|
||||||
|
from linear_system import LinearSystem
|
||||||
|
from plane import Plane
|
||||||
|
|
||||||
|
|
||||||
|
def error_check_input(text, lower=-99999999999, upper=99999999999):
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
operation = float(input(text))
|
||||||
|
if operation >= lower and operation <= upper:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
print("Only enter one of the specified options")
|
||||||
|
except ValueError:
|
||||||
|
print("You may only enter a number")
|
||||||
|
return operation
|
||||||
|
|
||||||
|
|
||||||
|
# Function creates a vector using user input
|
||||||
|
def enter_vector(times=3):
|
||||||
|
coordinates = []
|
||||||
|
for x in range(times):
|
||||||
|
coordinates.append(float(input("Enter coordinate: ")))
|
||||||
|
return Vector(coordinates)
|
||||||
|
|
||||||
|
|
||||||
|
def enter_vectors(vectors=2, choice=True, dimension=None):
|
||||||
|
if choice:
|
||||||
|
dimension = int(error_check_input("How many dimensions would you like your vectors to include(2-5): ", 2, 5))
|
||||||
|
my_vectors = []
|
||||||
|
for i in range(vectors):
|
||||||
|
print("Entering Vector #%s:" % str(i + 1))
|
||||||
|
v = enter_vector(dimension)
|
||||||
|
my_vectors.append(v)
|
||||||
|
return my_vectors
|
||||||
|
|
||||||
|
|
||||||
|
def vector():
|
||||||
|
print("Vector is a quantity with both magnitude and direction\n"
|
||||||
|
"Using vectors, we may perform mathematical operations including: \n"
|
||||||
|
"\t1) Vector addition\n"
|
||||||
|
"\t2) Vector Subtraction\n "
|
||||||
|
"\t3) Multiply the vector by a scalar\n"
|
||||||
|
"\t4) Find one vector's magnitude\n"
|
||||||
|
"\t5) Normalize a vector\n"
|
||||||
|
"\t6) Calculate dot product \n"
|
||||||
|
"\t7) Compute angle\n"
|
||||||
|
"\t8) Determine whether parallel\n"
|
||||||
|
"\t9) Determine whether orthogonal\n"
|
||||||
|
"\t10) Determine the projected vector\n"
|
||||||
|
"\t11) Determine the orthogonal vector\n"
|
||||||
|
"\t12) Determine the cross product\n"
|
||||||
|
"\t13) Find the area of the parallelogram formed\n"
|
||||||
|
"\t14) Find the area of the triangle formed\n")
|
||||||
|
option_to_execute = error_check_input("Pick one of the above operations to perform on vectors: ", 1, 14)
|
||||||
|
print("===================================================")
|
||||||
|
if option_to_execute == 1:
|
||||||
|
v, w = enter_vectors(2)
|
||||||
|
addition = v.plus(w)
|
||||||
|
print("Together the vectors form: %s" % addition)
|
||||||
|
elif option_to_execute == 2:
|
||||||
|
v, w = enter_vectors(2)
|
||||||
|
subtraction = v.minus(w)
|
||||||
|
print("Subtracting the vectors forms: %s" % subtraction)
|
||||||
|
elif option_to_execute == 3:
|
||||||
|
v = enter_vectors(1)[0]
|
||||||
|
scalar = error_check_input("Enter scalar: ")
|
||||||
|
multiplied = v.times_scalar(scalar)
|
||||||
|
print("Multiplying the vector by scalar returns: %s" % multiplied)
|
||||||
|
elif option_to_execute == 4:
|
||||||
|
v = enter_vectors(1)[0]
|
||||||
|
magnitude = v.magnitude()
|
||||||
|
print("The magnitude of the vector is: %s" % magnitude)
|
||||||
|
elif option_to_execute == 5:
|
||||||
|
v = enter_vectors(1)[0]
|
||||||
|
normalized = v.normalize()
|
||||||
|
print("The vector normalized is: %s" % normalized)
|
||||||
|
elif option_to_execute == 6:
|
||||||
|
v, w = enter_vectors(2)
|
||||||
|
dot_product = v.dot_product(w)
|
||||||
|
print('dot_product: {}'.format(round(dot_product, 3)))
|
||||||
|
elif option_to_execute == 7:
|
||||||
|
v, w = enter_vectors(2)
|
||||||
|
angle_degrees = v.get_angle_deg(w)
|
||||||
|
angle_radiants = v.get_angle_rad(w)
|
||||||
|
print("The first angle is:")
|
||||||
|
print("%s in radiant and %s in degrees " % (angle_degrees, angle_radiants))
|
||||||
|
elif option_to_execute == 8:
|
||||||
|
v, w = enter_vectors(2)
|
||||||
|
is_parallel = v.is_parallel(w)
|
||||||
|
if is_parallel:
|
||||||
|
print("The vectors are parallel")
|
||||||
|
else:
|
||||||
|
print("The vectors aren't parallel")
|
||||||
|
elif option_to_execute == 9:
|
||||||
|
v, w = enter_vectors(2)
|
||||||
|
is_orthogonal = v.is_orthogonal(w)
|
||||||
|
if is_orthogonal:
|
||||||
|
print("The vectors are orthogonal")
|
||||||
|
else:
|
||||||
|
print("The vectors aren't orthogonal")
|
||||||
|
elif option_to_execute == 10:
|
||||||
|
v, w = enter_vectors(2)
|
||||||
|
projected_vector = v.get_projected_vector(w)
|
||||||
|
print("The projected vector is: %s" % projected_vector)
|
||||||
|
elif option_to_execute == 11:
|
||||||
|
v, w = enter_vectors(2)
|
||||||
|
orthogonal_vector = v.get_orthogonal_vector(w)
|
||||||
|
print("The orthogonal vector: %s" % orthogonal_vector)
|
||||||
|
elif option_to_execute == 12:
|
||||||
|
v, w = enter_vectors(2, False, 3)
|
||||||
|
cross_product = v.cross_product(w)
|
||||||
|
print("The cross product is: %s" % cross_product)
|
||||||
|
elif option_to_execute == 13:
|
||||||
|
v, w = enter_vectors(2, False, 3)
|
||||||
|
area_parallelogram = v.area_parallelogram(w)
|
||||||
|
print("The parallelogram formed area is: %s" % area_parallelogram)
|
||||||
|
elif option_to_execute == 14:
|
||||||
|
v, w = enter_vectors(2, False, 3)
|
||||||
|
area_triangle = v.area_triangle(w)
|
||||||
|
print("The triangle formed area is: %s" % area_triangle)
|
||||||
|
|
||||||
|
|
||||||
|
def enter_lines(times):
|
||||||
|
current_lines = []
|
||||||
|
for i in range(times):
|
||||||
|
print("Enter the two-dimensional vector below:")
|
||||||
|
vec = enter_vector(2)
|
||||||
|
base_point = error_check_input("Enter the base point: ")
|
||||||
|
current_lines.append(Line(vec, base_point))
|
||||||
|
return current_lines
|
||||||
|
|
||||||
|
|
||||||
|
def lines():
|
||||||
|
print("A line can be defined by a basepoint and a direction vector. ")
|
||||||
|
line1, line2 = enter_lines(2)
|
||||||
|
print("The lines intersect in %s" % line1.intersection(line2))
|
||||||
|
|
||||||
|
|
||||||
|
def linear_system():
|
||||||
|
print("Linear systems use gaussian elimination to\n"
|
||||||
|
"\t1) Determine amount of possible solutions for planes\n"
|
||||||
|
"\t2) Solve a system of hyperplanes \n")
|
||||||
|
option_to_execute = error_check_input("Pick one of the above: ", 1, 2)
|
||||||
|
if option_to_execute == 1:
|
||||||
|
total_planes = int(error_check_input("Enter amount of planes(2/5): ", 2, 5))
|
||||||
|
myPlanes = enter_plane(total_planes)
|
||||||
|
system1 = LinearSystem([i for i in myPlanes])
|
||||||
|
print("System intersection: ", system1.do_gaussian_elimination())
|
||||||
|
elif option_to_execute == 2:
|
||||||
|
total_planes = int(error_check_input("Enter amount of planes(2/5): ", 2, 5))
|
||||||
|
myPlanes = enter_plane(total_planes)
|
||||||
|
system1 = LinearSystem([i for i in myPlanes])
|
||||||
|
print(system1.compute_solution())
|
||||||
|
|
||||||
|
|
||||||
|
def enter_plane(times):
|
||||||
|
planes = []
|
||||||
|
for i in range(times):
|
||||||
|
print("Plane #%s" % str(i + 1))
|
||||||
|
print("First, enter a 3 dimensional vector: ")
|
||||||
|
vector = enter_vector(3)
|
||||||
|
base_point = error_check_input("Now, enter base point: ")
|
||||||
|
planes.append(Plane(vector, base_point))
|
||||||
|
return planes
|
||||||
|
|
||||||
|
|
||||||
|
def plane():
|
||||||
|
print("A plane is similar to line, but in three dimensions\nLet's check whether two planes are parallel/equal: ")
|
||||||
|
p1, p2 = enter_plane(2)
|
||||||
|
if p1.is_parallel(p2):
|
||||||
|
print("The planes are parallel")
|
||||||
|
else:
|
||||||
|
print("The planes are not parallel")
|
||||||
|
if p1 == p2:
|
||||||
|
print("The planes are equal")
|
||||||
|
else:
|
||||||
|
print("The planes are not equal")
|
||||||
|
|
||||||
|
|
||||||
|
print("Welcome to the interactive math problem solving library. In this library you will find solutions to well-known"
|
||||||
|
"\nmath problems such as vectors, intersection, linear systems and planes.")
|
||||||
|
while True:
|
||||||
|
print("\n"
|
||||||
|
"\t1) Vectors\n"
|
||||||
|
"\t2) Intersection of lines\n"
|
||||||
|
"\t3) Linear Systems\n"
|
||||||
|
"\t4) Planes\n"
|
||||||
|
"\t5) Exit Program")
|
||||||
|
section_view = error_check_input("Choose the operation you would like to execute from the above: ", 1, 4)
|
||||||
|
if section_view == 1:
|
||||||
|
vector()
|
||||||
|
elif section_view == 2:
|
||||||
|
lines()
|
||||||
|
elif section_view == 3:
|
||||||
|
linear_system()
|
||||||
|
elif section_view == 4:
|
||||||
|
plane()
|
||||||
|
elif section_view == 5:
|
||||||
|
break
|
||||||
247
von_Udacity/vector.py
Executable file
247
von_Udacity/vector.py
Executable file
@@ -0,0 +1,247 @@
|
|||||||
|
from math import acos, sqrt, pi
|
||||||
|
from decimal import Decimal, getcontext
|
||||||
|
|
||||||
|
getcontext().prec = 30
|
||||||
|
|
||||||
|
|
||||||
|
class MyDecimal(Decimal):
|
||||||
|
def is_near_zero(self, eps=1e-10):
|
||||||
|
return abs(self) < eps
|
||||||
|
|
||||||
|
|
||||||
|
class Vector(object):
|
||||||
|
def __init__(self, coordinates):
|
||||||
|
try:
|
||||||
|
if not coordinates:
|
||||||
|
raise ValueError
|
||||||
|
self.coordinates = tuple([Decimal(c) for c in coordinates])
|
||||||
|
self.dimension = len(coordinates)
|
||||||
|
|
||||||
|
except ValueError:
|
||||||
|
raise ValueError('The coordinates must be nonempty')
|
||||||
|
|
||||||
|
except TypeError:
|
||||||
|
raise TypeError('The coordinates must be an iterable')
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
self.current = 0
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __next__(self):
|
||||||
|
if self.current >= len(self.coordinates):
|
||||||
|
raise StopIteration
|
||||||
|
else:
|
||||||
|
current_value = self.coordinates[self.current]
|
||||||
|
self.current += 1
|
||||||
|
return current_value
|
||||||
|
|
||||||
|
def next(self):
|
||||||
|
return self.__next__()
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return len(self.coordinates)
|
||||||
|
|
||||||
|
def __getitem__(self, i):
|
||||||
|
return self.coordinates[i]
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return 'Vector: {}'.format([round(coord, 3)
|
||||||
|
for coord in self.coordinates])
|
||||||
|
|
||||||
|
def __eq__(self, v):
|
||||||
|
return self.coordinates == v.coordinates
|
||||||
|
|
||||||
|
def is_zero(self):
|
||||||
|
return set(self.coordinates) == set([Decimal(0)])
|
||||||
|
|
||||||
|
def plus(self, other):
|
||||||
|
new_coordinates = [x + y for x, y in zip(self.coordinates, other.coordinates)]
|
||||||
|
return Vector(new_coordinates)
|
||||||
|
|
||||||
|
def minus(self, other):
|
||||||
|
return Vector([coords[0] - coords[1]
|
||||||
|
for coords in zip(self.coordinates, other.coordinates)])
|
||||||
|
|
||||||
|
def times_scalar(self, factor):
|
||||||
|
return Vector([Decimal(factor) * coord for coord in self.coordinates])
|
||||||
|
|
||||||
|
def magnitude(self):
|
||||||
|
return Decimal(sqrt(sum([coord * coord
|
||||||
|
for coord in self.coordinates])))
|
||||||
|
|
||||||
|
def normalize(self):
|
||||||
|
try:
|
||||||
|
return self.times_scalar(Decimal('1.0') / self.magnitude())
|
||||||
|
except ZeroDivisionError:
|
||||||
|
raise Exception('Cannot normalize the zero vector')
|
||||||
|
|
||||||
|
def dot_product(self, other):
|
||||||
|
return sum(x * y for x, y in zip(self.coordinates, other.coordinates))
|
||||||
|
|
||||||
|
def get_angle_rad(self, other):
|
||||||
|
dot_prod = round(self.normalize().dot_product(other.normalize()), 3)
|
||||||
|
return acos(dot_prod)
|
||||||
|
|
||||||
|
def get_angle_deg(self, other):
|
||||||
|
degrees_per_rad = 180. / pi
|
||||||
|
return degrees_per_rad * self.get_angle_rad(other)
|
||||||
|
|
||||||
|
def is_parallel(self, other):
|
||||||
|
return (self.is_zero() or other.is_zero() or
|
||||||
|
self.get_angle_rad(other) in [0, pi])
|
||||||
|
|
||||||
|
def is_orthogonal(self, other):
|
||||||
|
return round(self.dot_product(other), 3) == 0
|
||||||
|
|
||||||
|
def get_projected_vector(self, other):
|
||||||
|
"""
|
||||||
|
Gets projection of vector v in b
|
||||||
|
"""
|
||||||
|
b_normalized = other.normalize()
|
||||||
|
return b_normalized.times_scalar(self.dot_product(b_normalized))
|
||||||
|
|
||||||
|
def get_orthogonal_vector(self, other):
|
||||||
|
return self.minus(self.get_projected_vector(other))
|
||||||
|
|
||||||
|
def cross_product(self, other):
|
||||||
|
[x1, y1, z1] = self.coordinates
|
||||||
|
[x2, y2, z2] = other.coordinates
|
||||||
|
x = (y1 * z2) - (y2 * z1)
|
||||||
|
y = -((x1 * z2) - (x2 * z1))
|
||||||
|
z = (x1 * y2) - (x2 * y1)
|
||||||
|
return Vector([x, y, z])
|
||||||
|
|
||||||
|
def area_parallelogram(self, other):
|
||||||
|
return self.cross_product(other).magnitude()
|
||||||
|
|
||||||
|
def area_triangle(self, other):
|
||||||
|
return self.cross_product(other).magnitude() / 2
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
v = Vector([8.218, -9.341])
|
||||||
|
w = Vector([-1.129, 2.111])
|
||||||
|
addition = v.plus(w)
|
||||||
|
print('addition: {}'.format(addition))
|
||||||
|
|
||||||
|
v = Vector([7.119, 8.215])
|
||||||
|
w = Vector([-8.223, 0.878])
|
||||||
|
subtraction = v.minus(w)
|
||||||
|
print('subtraction: {}'.format(subtraction))
|
||||||
|
|
||||||
|
v = Vector([1.671, -1.012, -0.318])
|
||||||
|
multiplication = v.times_scalar(7.41)
|
||||||
|
print('multiplication: {}'.format(multiplication))
|
||||||
|
|
||||||
|
# *****************
|
||||||
|
|
||||||
|
v = Vector([-0.221, 7.437])
|
||||||
|
first_magintude = v.magnitude()
|
||||||
|
print('first_magintude: {}'.format(round(first_magintude, 3)))
|
||||||
|
|
||||||
|
v = Vector([8.813, -1.331, -6.247])
|
||||||
|
second_magintude = v.magnitude()
|
||||||
|
print('second_magintude: {}'.format(round(second_magintude, 3)))
|
||||||
|
|
||||||
|
v = Vector([5.581, -2.136])
|
||||||
|
first_normalization = v.normalize()
|
||||||
|
print('first_normailization: {}'.format(first_normalization))
|
||||||
|
|
||||||
|
v = Vector([1.996, 3.108, -4.554])
|
||||||
|
second_normalization = v.normalize()
|
||||||
|
print('second_normailization: {}'.format(second_normalization))
|
||||||
|
|
||||||
|
# *****************
|
||||||
|
|
||||||
|
v = Vector([7.887, 4.138])
|
||||||
|
w = Vector([-8.802, 6.776])
|
||||||
|
dot_product = v.dot_product(w)
|
||||||
|
print('first_dot_product: {}'.format(round(dot_product, 3)))
|
||||||
|
|
||||||
|
v = Vector([-5.955, -4.904, -1.874])
|
||||||
|
w = Vector([-4.496, -8.755, 7.103])
|
||||||
|
dot_product = v.dot_product(w)
|
||||||
|
print('second_dot_product: {}'.format(round(dot_product, 3)))
|
||||||
|
|
||||||
|
# *****************
|
||||||
|
|
||||||
|
v = Vector([3.183, -7.627])
|
||||||
|
w = Vector([-2.668, 5.319])
|
||||||
|
angle_rads = v.get_angle_rad(w)
|
||||||
|
print('first_angle_rads: {}'.format(angle_rads))
|
||||||
|
|
||||||
|
v = Vector([7.35, 0.221, 5.188])
|
||||||
|
w = Vector([2.751, 8.259, 3.985])
|
||||||
|
angle_degrees = v.get_angle_deg(w)
|
||||||
|
print('first_angle_rads: {}'.format(angle_degrees))
|
||||||
|
|
||||||
|
# *****************
|
||||||
|
|
||||||
|
v = Vector([-7.579, -7.88])
|
||||||
|
w = Vector([22.737, 23.64])
|
||||||
|
is_parallel = v.is_parallel(w)
|
||||||
|
is_orthogonal = v.is_orthogonal(w)
|
||||||
|
|
||||||
|
print('1 parallel: {}, orthogonal: {}'.format(is_parallel, is_orthogonal))
|
||||||
|
|
||||||
|
v = Vector([-2.029, 9.97, 4.172])
|
||||||
|
w = Vector([-9.231, -6.639, -7.245])
|
||||||
|
is_parallel = v.is_parallel(w)
|
||||||
|
is_orthogonal = v.is_orthogonal(w)
|
||||||
|
|
||||||
|
print('2 parallel: {}, orthogonal: {}'.format(is_parallel, is_orthogonal))
|
||||||
|
|
||||||
|
v = Vector([-2.328, -7.284, -1.214])
|
||||||
|
w = Vector([-1.821, 1.072, -2.94])
|
||||||
|
is_parallel = v.is_parallel(w)
|
||||||
|
is_orthogonal = v.is_orthogonal(w)
|
||||||
|
print('3 parallel: {}, orthogonal: {}'.format(is_parallel, is_orthogonal))
|
||||||
|
|
||||||
|
v = Vector([2.118, 4.827])
|
||||||
|
w = Vector([0, 0])
|
||||||
|
is_parallel = v.is_parallel(w)
|
||||||
|
is_orthogonal = v.is_orthogonal(w)
|
||||||
|
|
||||||
|
print('4 parallel: {}, orthogonal: {}'.format(is_parallel, is_orthogonal))
|
||||||
|
|
||||||
|
# *****************
|
||||||
|
|
||||||
|
v = Vector([3.039, 1.879])
|
||||||
|
w = Vector([0.825, 2.036])
|
||||||
|
projected_vector = v.get_projected_vector(w)
|
||||||
|
|
||||||
|
print('projected vector is: {}'.format(projected_vector))
|
||||||
|
|
||||||
|
v = Vector([-9.88, -3.264, -8.159])
|
||||||
|
w = Vector([-2.155, -9.353, -9.473])
|
||||||
|
orthogonal_vector = v.get_orthogonal_vector(w)
|
||||||
|
|
||||||
|
print('orthogonal vector is: {}'.format(orthogonal_vector))
|
||||||
|
|
||||||
|
v = Vector([3.009, -6.172, 3.692, -2.51])
|
||||||
|
w = Vector([6.404, -9.144, 2.759, 8.718])
|
||||||
|
projected_vector = v.get_projected_vector(w)
|
||||||
|
orthogonal_vector = v.get_orthogonal_vector(w)
|
||||||
|
|
||||||
|
print('second projected vector is: {}'.format(projected_vector))
|
||||||
|
|
||||||
|
print('second orthogonal vector is: {}'.format(orthogonal_vector))
|
||||||
|
|
||||||
|
# *****************
|
||||||
|
|
||||||
|
v1 = Vector([8.462, 7.893, -8.187])
|
||||||
|
w1 = Vector([6.984, -5.975, 4.778])
|
||||||
|
|
||||||
|
v2 = Vector([-8.987, -9.838, 5.031])
|
||||||
|
w2 = Vector([-4.268, -1.861, -8.866])
|
||||||
|
|
||||||
|
v3 = Vector([1.5, 9.547, 3.691])
|
||||||
|
w3 = Vector([-6.007, 0.124, 5.772])
|
||||||
|
|
||||||
|
first_cross_product = v1.cross_product(w1)
|
||||||
|
print('cross product is: {}'.format(first_cross_product))
|
||||||
|
|
||||||
|
area_parallelogram = v2.area_parallelogram(w2)
|
||||||
|
print('area parallelogram is: {}'.format(round(area_parallelogram, 3)))
|
||||||
|
|
||||||
|
area_triangle = v3.area_triangle(w3)
|
||||||
|
print('area triangle is: {}'.format(round(area_triangle, 3)))
|
||||||
Reference in New Issue
Block a user