看其他篇章到目錄選擇。
首先從我們計(jì)算機(jī)人最熟悉的線(xiàn)性代數(shù)開(kāi)始。
今天先寫(xiě)第一篇:向量——vector。另外補(bǔ)充一句,每一個(gè)具體類(lèi)或者包的研究都是示例性質(zhì)的,具體要用到什么類(lèi)型的類(lèi)或者接口,大家應(yīng)該自己動(dòng)手去翻閱api doc。
Vector是一個(gè)普通的向量。在math包org.apache.commons.math.linear中有RealVector和FieldVector這兩種向量,均是接口類(lèi)型。前者是實(shí)數(shù)類(lèi)型的向量,后者是場(chǎng)向量。以實(shí)數(shù)向量為例,RealVector有AbstractRealVector, ArrayRealVector。具體的結(jié)構(gòu)類(lèi)圖見(jiàn)下:
這個(gè)結(jié)構(gòu)可能會(huì)有些變化,因?yàn)樵?/span>doc中,可以看到ArrayRealVector是繼承AbstractRealVector的,而2.0的代碼中ArrayRealVector還是直接實(shí)現(xiàn)了RealVector,且包中也沒(méi)有AbstractRealVector。可見(jiàn)代碼的變化和doc中的描述也有不同,雖然doc中說(shuō)明了AbstractRealVector是since 2.0的,而且ArrayRealVector也是since 2.0的。呵呵,一個(gè)不一致。其實(shí)是update date的不同了。
向量這個(gè)概念是線(xiàn)性代數(shù)的基礎(chǔ)。RealVector作為基本的接口,已經(jīng)定義了基本所有的向量操作。比如向量的加減乘除運(yùn)算、向量外積、向量?jī)?nèi)積、向量范數(shù)等等,當(dāng)然vector的實(shí)現(xiàn)時(shí)基于數(shù)組類(lèi)型的。RealVector的內(nèi)部實(shí)現(xiàn)是double []data;。
需要重點(diǎn)解釋的是一個(gè)操作map***:就像原來(lái)的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操作就是對(duì)向量的每一個(gè)元素做固定操作的意思。而map***是返回新的實(shí)例的,而map***toself則返回自己。這個(gè)從源碼可以看出,比如mapAdd()的實(shí)現(xiàn):
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()的實(shí)現(xiàn):
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
區(qū)別顯然了,一個(gè)返回new ArrayRealVector,一個(gè)返回this。
具體見(jiàn)代碼:
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
對(duì)應(yīng)的輸出:
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}
向量是一個(gè)基礎(chǔ)數(shù)學(xué)結(jié)構(gòu),以后還會(huì)大量的提到。Commons Math庫(kù)為我們提供了這樣方便的向量表示,在用Java寫(xiě)起程序來(lái)也是得心應(yīng)手。
當(dāng)然所有的研究要以文檔為主,參看文檔寫(xiě)代碼這是必須做到的事情。所以,不要嫌麻煩,趕緊把api doc放到桌面上,開(kāi)始coding吧。
相關(guān)資料:
向量定義:http://zh.wikipedia.org/zh/%E7%9F%A2%E9%87%8F
Commons math包:http://commons.apache.org/math/index.html