我正在尝试使用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函数,它可以帮我解决这个问题。
答案 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,而是使用其他东西。我把它换成了兰特。