看其他篇章到目錄選擇。
首先從我們計算機人最熟悉的線性代數開始。
今天先寫第一篇:向量——vector。另外補充一句,每一個具體類或者包的研究都是示例性質的,具體要用到什么類型的類或者接口,大家應該自己動手去翻閱api doc。
Vector是一個普通的向量。在math包org.apache.commons.math.linear中有RealVector和FieldVector這兩種向量,均是接口類型。前者是實數類型的向量,后者是場向量。以實數向量為例,RealVector有AbstractRealVector, ArrayRealVector。具體的結構類圖見下:
這個結構可能會有些變化,因為在doc中,可以看到ArrayRealVector是繼承AbstractRealVector的,而2.0的代碼中ArrayRealVector還是直接實現了RealVector,且包中也沒有AbstractRealVector。可見代碼的變化和doc中的描述也有不同,雖然doc中說明了AbstractRealVector是since 2.0的,而且ArrayRealVector也是since 2.0的。呵呵,一個不一致。其實是update date的不同了。
向量這個概念是線性代數的基礎。RealVector作為基本的接口,已經定義了基本所有的向量操作。比如向量的加減乘除運算、向量外積、向量內積、向量范數等等,當然vector的實現時基于數組類型的。RealVector的內部實現是double []data;。
需要重點解釋的是一個操作map***:就像原來的api解釋的“The various mapXxx and mapXxxToSelf methods operate on vectors element-wise, i.e. they perform the same operation (adding a scalar, applying a function ...) on each element in turn. The mapXxx versions create a new vector to hold the result and do not change the instance. The mapXxxToSelf versions use the instance itself to store the results, so the instance is changed by these methods. In both cases, the result vector is returned by the methods”。
具體是什么呢?很多的map***操作和map***toself操作就是對向量的每一個元素做固定操作的意思。而map***是返回新的實例的,而map***toself則返回自己。這個從源碼可以看出,比如mapAdd()的實現:
1
public RealVector mapAdd(double d)
{
2
double[] out = new double[data.length];
3
for (int i = 0; i < data.length; i++)
{
4
out[i] = data[i] + d;
5
}
6
return new ArrayRealVector(out);
7
}
8
而mapAddToSelf()的實現:
1
public RealVector mapAddToSelf(double d)
{
2
for (int i = 0; i < data.length; i++)
{
3
data[i] = data[i] + d;
4
}
5
return this;
6
}
7
區別顯然了,一個返回new ArrayRealVector,一個返回this。
具體見代碼:
1
/** *//**
2
*
3
*/
4
package algorithm.math;
5
6
import org.apache.commons.math.linear.ArrayRealVector;
7
import org.apache.commons.math.linear.RealVector;
8
9
/** *//**
10
* @author Jia Yu
11
* @date 2010-11-18
12
*/
13
public class VectorTest
{
14
15
/** *//**
16
* @param args
17
*/
18
public static void main(String[] args)
{
19
// TODO Auto-generated method stub
20
vector();
21
}
22
23
private static void vector()
{
24
// TODO Auto-generated method stub
25
double[] vec1 =
{ 1d, 2d, 3d };
26
double[] vec2 =
{ 4d, 5d, 6d };
27
ArrayRealVector v1 = new ArrayRealVector(vec1);
28
ArrayRealVector v2 = new ArrayRealVector(vec2);
29
30
// output directly
31
System.out.println("v1 is " + v1);
32
// dimension : size of vector
33
System.out.println("size is " + v1.getDimension());
34
// vector add
35
System.out.println("v1 + v2 = " + v1.add(v2));
36
System.out.println("v1 + v2 = " + v1.add(vec2));
37
// vector substract
38
System.out.println("v1 - v2 = " + v1.subtract(v2));
39
// vector element by element multiply
40
System.out.println("v1 * v2 = " + v1.ebeMultiply(v2));
41
// vector element by element divide
42
System.out.println("v1 / v2 = " + v1.ebeDivide(v2));
43
// get index at 1
44
System.out.println("v1[1] = " + v1.getEntry(1));
45
// vector append
46
RealVector t_vec = v1.append(v2);
47
System.out.println("v1 append v2 is " + t_vec);
48
// vector distance
49
System.out.println("distance between v1 and v2 is "
50
+ v1.getDistance(v2));
51
System.out.println("L1 distance between v1 and v2 is "
52
+ v1.getL1Distance(v2));
53
// vector norm
54
System.out.println("norm of v1 is " + v1.getNorm());
55
// vector dot product
56
System.out.println("dot product of v1 and v2 is " + v1.dotProduct(v2));
57
// vector outer product
58
System.out.println("outer product of v1 and v2 is "
59
+ v1.outerProduct(v2));
60
// vector orthogonal projection
61
System.out.println("hogonal projection of v1 and v2 is "
62
+ v1.projection(v2));
63
// vector map operations
64
System.out.println("Map the Math.abs(double) function to v1 is "
65
+ v1.mapAbs());
66
v1.mapInvToSelf();
67
System.out.println("Map the 1/x function to v1 itself is " + v1);
68
// vector get sub vector
69
System.out.println("sub vector of v1 is " + v1.getSubVector(0, 2));
70
}
71
72
}
73
對應的輸出:
v1 is {1; 2; 3}
size is 3
v1 + v2 = {5; 7; 9}
v1 + v2 = {5; 7; 9}
v1 - v2 = {-3; -3; -3}
v1 * v2 = {4; 10; 18}
v1 / v2 = {0.25; 0.4; 0.5}
v1[1] = 2.0
v1 append v2 is {1; 2; 3; 4; 5; 6}
distance between v1 and v2 is 5.196152422706632
L1 distance between v1 and v2 is 9.0
norm of v1 is 3.7416573867739413
dot product of v1 and v2 is 32.0
outer product of v1 and v2 is Array2DRowRealMatrix{{4.0,5.0,6.0},{8.0,10.0,12.0},{12.0,15.0,18.0}}
hogonal projection of v1 and v2 is {1.66; 2.08; 2.49}
Map the Math.abs(double) function to v1 is {1; 2; 3}
Map the 1/x function to v1 itself is {1; 0.5; 0.33}
sub vector of v1 is {1; 0.5}
向量是一個基礎數學結構,以后還會大量的提到。Commons Math庫為我們提供了這樣方便的向量表示,在用Java寫起程序來也是得心應手。
當然所有的研究要以文檔為主,參看文檔寫代碼這是必須做到的事情。所以,不要嫌麻煩,趕緊把api doc放到桌面上,開始coding吧。
相關資料:
向量定義:http://zh.wikipedia.org/zh/%E7%9F%A2%E9%87%8F
Commons math包:http://commons.apache.org/math/index.html