MATLAB:测试匿名向量是否是R ^ n的子集

时间:2012-05-30 08:42:22

标签: matlab math vector

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

所以阅读我是关于子空间的post并试图构建一些简单的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个args的 elseif 声明..?

PS:我似乎无法找到一个内置的matlab函数,它可以帮我解决这个问题。

2 个答案:

答案 0 :(得分:1)

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

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

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

现在我们编写核心功能。这里func是一个参数的函数(假设是R^m中的向量),它返回R^n中的向量。我们将func应用于R^m中的100个随机选择的向量,以获得输出矩阵。如果func表示线性子空间,则输出的rank将小于或等于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

答案 1 :(得分: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,而是使用其他东西。我把它换成了兰特。