0

我正在尝试使用 MatLab 代码作为程序员学习数学的一种方式。

所以阅读我这篇关于子空间的文章并尝试构建一些简单的 matlab 函数来为我做这件事。

这是我走了多远:

function performSubspaceTest(subset, numArgs)
% Just a quick and dirty function to perform subspace test on a vector(subset)
%
% INPUT
% subset        is the anonymous function that defines the vector
% numArgs       is the the number of argument that subset takes

% Author:   Lasse Nørfeldt (Norfeldt)
% Date:     2012-05-30
% License:  http://creativecommons.org/licenses/by-sa/3.0/

if numArgs == 1
    subspaceTest = @(subset) single(rref(subset(rand)+subset(rand))) ...
        == single(rref(rand*subset(rand)));

elseif numArgs == 2
    subspaceTest = @(subset) single(rref(subset(rand,rand)+subset(rand,rand))) ...
        == single(rref(rand*subset(rand,rand)));
end
% rand just gives a random number. Converting to single avoids round off
% errors.
% Know that the code can crash if numArgs isn't given or bigger than 2.

outcome = subspaceTest(subset);
if outcome == true
    display(['subset IS a subspace of R^' num2str(size(outcome,2))])
else
    display(['subset is NOT a subspace of R^' num2str(size(outcome,2))])
end

这些是我正在测试的子集

%% Checking for subspaces
V = @(x) [x, 3*x]
performSubspaceTest(V, 1)

A = @(x) [x, 3*x+1]
performSubspaceTest(A, 1)

B = @(x) [x, x^2, x^3]
performSubspaceTest(B, 1)

C = @(x1, x3) [x1, 0, x3, -5*x1]
performSubspaceTest(C, 2)

运行代码给了我这个

V = 
@(x)[x,3*x]
subset IS a subspace of R^2

A = 
@(x)[x,3*x+1]
subset is NOT a subspace of R^2

B = 
@(x)[x,x^2,x^3]
subset is NOT a subspace of R^3

C = 
@(x1,x3)[x1,0,x3,-5*x1]
subset is NOT a subspace of R^4

C 不起作用(仅当它只接受一个 arg 时才起作用)。我知道我对 numArgs 的解决方案不是最优的——但这是我目前能想到的。

有什么方法可以优化这段代码,使 C 能够正常工作,并且可能避免超过 2 个参数的elseif语句..?

PS:我似乎找不到一个内置的 matlab 函数来为我做这个洞的事情..

4

2 回答 2

1

不是最优的解决方案几乎没有触及问题的表面。

我认为您一次做的太多了:rref不应该使用并且使一切复杂化。尤其是numArgs大于 1。

想一想:[1 0 3 -5]并且[3 0 3 -5]都是 C 的成员,但它们的总和[4 0 6 -10](属于 C)不是先前向量之一(例如[2 0 6 -10])的乘积的线性乘积。所以rref世界上所有的人都无法解决你的问题。

那么你能做什么呢?

你需要检查是否

(randn*subset(randn,randn)+randn*subset(randn,randn))) 

是 C 的成员,除非我弄错了,否则这是一个难题:从概念上讲,您需要遍历向量的每个元素并确保它与预定条件匹配。或者,您可以尝试找到一个 C(x1,x2) 为您提供正确答案的集合。在这种情况下,您可以使用fminsearch以数值方式解决此问题并验证返回值是否在定义的容差范围内:

[s,error] = fminsearch(@(x) norm(C(x(1),x(2)) - [2 0 6 -10]),[1 1])
s =
   1.999996976386119   6.000035034493023
error =
     3.827680714104862e-05

编辑:您需要确保可以在乘法中使用负数,所以不要使用 rand,而是使用其他东西。我把它改成了randn。

于 2012-05-30T12:33:39.020 回答
1

这是一种方法。它测试给定函数是否代表线性子空间。从技术上讲,这只是一个概率测试,但它失败的机会非常小。

首先,我们定义了一个很好的抽象。这个高阶函数将一个函数作为其第一个参数,并将该函数应用于矩阵的每一行x。这允许我们同时测试多个参数func

function y = apply(func,x)
  for k = 1:size(x,1)
    y(k,:) = func(x(k,:));
  end

现在我们编写核心函数。这func是一个参数的函数(假定是一个向量 in R^m),它返回一个向量 in R^n。我们应用func100 个随机选择的向量R^m来获得一个输出矩阵。如果func表示一个线性子空间,那么输出的将小于或等于m

function result = isSubspace(func,m)
  inputs  = rand(100,m);
  outputs = apply(func,inputs);
  result  = rank(outputs) <= m;

这是在行动。请注意,这些函数只接受一个参数——你写的地方是c(x1,x2)=[x1,0,x2]我写c(x) = [x(1),0,x(2)]的,这有点冗长,但它的优点是我们不必乱用 if 语句来决定我们的函数有多少参数——这很有效对于接受R^m任何输入的函数m,而不仅仅是 1 或 2。

>> v = @(x) [x,3*x]
>> isSubspace(v,1)
ans =
     1

>> a = @(x) [x(1),3*x(1)+1]
>> isSubspace(a,1)
ans =
     0

>> c = @(x) [x(1),0,x(2),-5*x(1)]
>> isSubspace(c,2)
ans =
     1
于 2012-05-30T11:59:52.407 回答