Matlab OOP:操作后对象类的更改-操作不再符合要求

Matlab OOP:操作后对象类的更改-操作不再符合要求,matlab,oop,symbolic-math,symbolic-computation,mupad,Matlab,Oop,Symbolic Math,Symbolic Computation,Mupad,我不熟悉面向对象编程。经过大量的强调,我终于在matlab的符号引擎muPad中定义了我自己的对象类。该引擎有自己的语言,其语法非常符合逻辑,与matlab本身类似 我想指出的是,没有必要了解muPad来帮助解决这个问题。我认为任何有相关OOP经验的人都能够提供更多关于这个问题的见解 我将从一点背景知识开始。我的班级叫Bx。它的对象有两个不同的属性,n和k,因此n=>k=>0。因此,“Bx”中正确定义的对象可能看起来像Bx(0,0),或Bx(2,2)或Bx(7,2)。。。“Bx”中的每个对象都是

我不熟悉面向对象编程。经过大量的强调,我终于在matlab的符号引擎muPad中定义了我自己的对象类。该引擎有自己的语言,其语法非常符合逻辑,与matlab本身类似

我想指出的是,没有必要了解muPad来帮助解决这个问题。我认为任何有相关OOP经验的人都能够提供更多关于这个问题的见解

我将从一点背景知识开始。我的班级叫Bx。它的对象有两个不同的属性,n和k,因此n=>k=>0。因此,“Bx”中正确定义的对象可能看起来像Bx(0,0),或Bx(2,2)或Bx(7,2)。。。“Bx”中的每个对象都是唯一的;如果n1=n2,k1=k2,这意味着Bx(n1,k1)=Bx(n2,k2)

请注意,muPad有一个名为“DOM_EXPR”的内置表达式类,它是子类型“_mult”、“_plus”等的超类。例如,a+b将是类型“_plus”,a*b将是类型“_mult”等

我在类中定义的操作之一是乘法。规则如下:

Bx(a, b) * Bx(c, d) = binomial(a, c) * binomial(b, d) / binomial(a+c, b+d) * Bx(a+c, b+d)
这在我的代码中非常有效,只要两个相乘的对象中有一个属于类“Bx”。例如:

Input:   Bx(2, 1)*Bx(4, 2)
Output:  (3*Bx(6, 3))/5

Input:   2*y*Bx(2, 1)*Bx(4, 2)^2
Output:  ((4*y)/7)*Bx(10, 5)
问题如下。每当我将类“Bx”的两个对象相乘时,输出将属于另一个类,称为“DOM_EXPR”和类型“\u mult”。上述输出就是一个很好的例子。这是有道理的;3/5*Bx(6,3)是一个表达式,由类“DOM_RAT”和“Bx”的对象组成,(4*y)/7*Bx(10,5)由“DOM_RAT”、“DOM_IDENT”和“Bx”组成

如果我将此类表达式与纯“Bx”相乘,例如:

然后我得到了预期的输出:(10*Bx(9,7))/3。这是因为在类“Bx”的_mult操作定义中,我定义了“Bx”对象与“_mult”类型的“DOM_EXPR”对象相乘时的行为

但是,有时可能会出现两个“Bx”对象都作为“DOM_EXPR”对象的一部分出现的情况。下面是一个例子:

a:=6*Bx(5,4); => n.b. type is "_mult"
b:=3*Bx(4,3); => n.b. type is "_mult"
c:=a*b
现在输出如下:(3*Bx(4,3))*(6*Bx(5,4))

这不是我想要的。我想让muPad进一步计算这个表达式。如果我将参数的所有操作数与现有代码相乘,我将得到:

Input:   6*Bx(5,4)*3*Bx(4,3)
Output:  10*Bx(9, 7)
这是正确的,我希望muPad在将上面的a和b相乘时所做的

如果我能深入了解如何更正代码以使其正确运行,我会非常受欢迎。我不一定在寻找语法,但也许更多的是关于你,一个经验丰富的OOP程序员,如何实现我正在尝试做的事情,以及它与我正在做的事情有何不同。一旦我了解了我的方法的错误,以及如何改进它,我就可以自己找出语法了

我已经在下面粘贴了完整的muPad代码。您可以在matlab中运行它,只需在命令窗口中键入mupadwelcome,打开一个新的mupad笔记本,并将各个代码块粘贴到新行中

Bx := newDomain("Bx"):
Bx::new := proc(n,k)
begin

//++++//
if args(0)<>2 then
error("There must be exactly two arguments")
end_if;

//----//
new(dom,n,k)

end_proc:

------------------------------------

Bx::print := proc(x)
begin

//++++//
"Bx(".expr2text(op(x,1),op(x,2)).")";

end_proc:

------------------------------------

Bx::_mult := proc(a,b)
local type1,type2,berns,c,berns1,c1,berns2,c2,n,k,ni,ki;
begin

//++++//
if select(args(),testtype,"_mult") = null()

then
lists := split(args(),testtype,Bx);
berns := [lists[1]];
c := _mult(lists[2]);
ni := [op(berns[1])][1];
ki := [op(berns[1])][2];

//----//
if nops(berns) >= 2 and [op(berns)][1] <> [op([op(berns)][1])][1]
then
delete berns[1];
coefficient:=1;

//
while nops(berns)>=1
do
n := op(berns[1],1);
k := op(berns[1],2);
prod := Bx(_plus(ni,n),_plus(ki,k));
coefficient := coefficient*binomial(n,k)*binomial(ni,ki)/binomial(_plus(n,ni),_plus(k,ki));
delete berns[1];
ni := op(prod,1);
ki := op(prod,2);
end_while;
//

c := _mult(coefficient,c);
case c
of 1 do Bx(ni,ki); break;
otherwise freeze(_mult)(c,dom(ni,ki));
end_case;

else
case c
of 1 do berns[1]; break;
otherwise freeze(_mult)(c,berns[1]);
end_case;

end_if;
//----//

//++++//
else
lists := split(args(),testtype,"_mult");
_mult(op(lists[1]),lists[2],lists[3])

end_if;
//++++//

end_proc:

------------------------------------

Bx::_power := proc(a,b)
local res;
begin

//++++//
case b
of 0 do 1; break;
of 1 do a; break;
otherwise
res:=a;

//----//
for i from 1 to b-1 do
res:=res*a;
end_for;
//----//

res;

end_case;
//++++//

end_proc:


a:=6*Bx(5,4)

b:=3*Bx(4,3)

6*Bx(5,4)*3*Bx(4,3)
Bx:=newDomain(“Bx”):
Bx::new:=proc(n,k)
开始
//++++//
如果args(0)2,则
错误(“必须正好有两个参数”)
结束(如有);
//----//
新建(dom、n、k)
结束程序:
------------------------------------
Bx::print:=proc(x)
开始
//++++//
“Bx(“.expr2text(op(x,1),op(x,2))”;
结束程序:
------------------------------------
Bx::_mult:=proc(a,b)
本地类型1,类型2,berns,c,berns1,c1,berns2,c2,n,k,ni,ki;
开始
//++++//
如果选择(args(),testtype,“\u mult”)=null()
然后
列表:=split(args(),testtype,Bx);
berns:=[列表[1]];
c:=_mult(列表[2]);
ni:=[op(berns[1])][1];
ki:=[op(berns[1])][2];
//----//
如果nops(伯尔尼)>=2和[op(伯尔尼)][1][op([op(伯尔尼)][1])][1]
然后
删除伯尔尼[1];
系数:=1;
//
而nops(berns)>=1
做
n:=op(berns[1],1);
k:=op(berns[1],2);
prod:=Bx(_-plus(ni,n),_-plus(ki,k));
系数:=系数*二项式(n,k)*二项式(ni,ki)/二项式(_加(n,ni),_加(k,ki));
删除伯尔尼[1];
ni:=op(产品,1);
ki:=op(产品,2);
结束时;
//
c:=_mult(系数c);
案例c
1个do-Bx(ni,ki);打破
否则冻结(_mult)(c,dom(ni,ki));
结束案例;
其他的
案例c
1个do berns[1];打破
否则冻结(_mult)(c,berns[1]);
结束案例;
结束(如有);
//----//
//++++//
其他的
列表:=split(args(),testtype,“_mult”);
_mult(op(列表[1]),列表[2],列表[3])
结束(如有);
//++++//
结束程序:
------------------------------------
Bx::_power:=proc(a,b)
本地资源;
开始
//++++//
案例b
0对1;打破
其中1个做一个;打破
否则
res:=a;
//----//
对于从1到b-1的i
res:=res*a;
结束!;
//----//
物件;
结束案例;
//++++//
结束程序:
a:=6*Bx(5,4)
b:=3*Bx(4,3)
6*Bx(5,4)*3*Bx(4,3)
Edit:有趣的是,如果我没有定义自己的mult和power方法,那么当将两个包含“Bx”的mult对象相乘时,muPad似乎做了我想做的事情,除了实际的“Bx”相乘,请参见下图。


我认为您的最后一个示例
6*Bx(5,4)*3*Bx(4,3)
如您所料工作的原因是因为MuPAD重新排列了术语,以便对以下内容进行计算:
(6*3)*(Bx(5,4)*Bx(4,3))==18*(5/9*Bx(9,7))==10*Bx(9,7)
(假设乘法是可交换的)。也许您需要在代码中这样做;将所有参数分解为
Bx
对象和其他内部类型,分别乘以每个组,然后乘以每个组的结果。现在我不完全理解mupad代码,但我可以看到您正在按照这些思路做一些事情,对吗?也许您当前缺少的是递归地查找操作数类型中的
Bx
对象。例如,
type(3*Bx(1,1))
被认为是类型
\u mult
,但您需要将其分为
op(..,1)
op(..,2)
,并可能对这两种类型中的每一种进行递归操作(对于更复杂的表达式),直到您将所有术语拆分为
Bx
类型和其他内置类型,然后做乘法a
Bx := newDomain("Bx"):
Bx::new := proc(n,k)
begin

//++++//
if args(0)<>2 then
error("There must be exactly two arguments")
end_if;

//----//
new(dom,n,k)

end_proc:

------------------------------------

Bx::print := proc(x)
begin

//++++//
"Bx(".expr2text(op(x,1),op(x,2)).")";

end_proc:

------------------------------------

Bx::_mult := proc(a,b)
local type1,type2,berns,c,berns1,c1,berns2,c2,n,k,ni,ki;
begin

//++++//
if select(args(),testtype,"_mult") = null()

then
lists := split(args(),testtype,Bx);
berns := [lists[1]];
c := _mult(lists[2]);
ni := [op(berns[1])][1];
ki := [op(berns[1])][2];

//----//
if nops(berns) >= 2 and [op(berns)][1] <> [op([op(berns)][1])][1]
then
delete berns[1];
coefficient:=1;

//
while nops(berns)>=1
do
n := op(berns[1],1);
k := op(berns[1],2);
prod := Bx(_plus(ni,n),_plus(ki,k));
coefficient := coefficient*binomial(n,k)*binomial(ni,ki)/binomial(_plus(n,ni),_plus(k,ki));
delete berns[1];
ni := op(prod,1);
ki := op(prod,2);
end_while;
//

c := _mult(coefficient,c);
case c
of 1 do Bx(ni,ki); break;
otherwise freeze(_mult)(c,dom(ni,ki));
end_case;

else
case c
of 1 do berns[1]; break;
otherwise freeze(_mult)(c,berns[1]);
end_case;

end_if;
//----//

//++++//
else
lists := split(args(),testtype,"_mult");
_mult(op(lists[1]),lists[2],lists[3])

end_if;
//++++//

end_proc:

------------------------------------

Bx::_power := proc(a,b)
local res;
begin

//++++//
case b
of 0 do 1; break;
of 1 do a; break;
otherwise
res:=a;

//----//
for i from 1 to b-1 do
res:=res*a;
end_for;
//----//

res;

end_case;
//++++//

end_proc:


a:=6*Bx(5,4)

b:=3*Bx(4,3)

6*Bx(5,4)*3*Bx(4,3)