Что-то в этом духе обсуждается в посте MathGroup по адресу
http://forums.wolfram.com/mathgroup/archive/2009/Oct/msg00023.html
(я вижу, что в нем есть апокрифическое примечание, которое весьма актуально, по крайней мере для автора этого поста.)
Вот как это можно применить в приведенном выше примере.В целях сохранения самодостаточности я повторю код замены.
replacementFunction[expr_, rep_, vars_] :=
Module[{num = Numerator[expr], den = Denominator[expr],
hed = Head[expr], base, expon},
If[PolynomialQ[num, vars] &&
PolynomialQ[den, vars] && ! NumberQ[den],
replacementFunction[num, rep, vars]/
replacementFunction[den, rep, vars],
If[hed === Power && Length[expr] == 2,
base = replacementFunction[expr[[1]], rep, vars];
expon = replacementFunction[expr[[2]], rep, vars];
PolynomialReduce[base^expon, rep, vars][[2]],
If[Head[hed] === Symbol &&
MemberQ[Attributes[hed], NumericFunction],
Map[replacementFunction[#, rep, vars] &, expr],
PolynomialReduce[expr, rep, vars][[2]]]]]]
Ваш пример теперь выглядит следующим образом.Мы берем вход, а также замену.Для последнего мы делаем эквивалентный многочлен, очищая знаменатели.
kK = a*b*t/((t + f) c*d);
rep = Numerator[Together[p - t/(t + f)]];
Теперь мы можем вызвать замену.Мы перечислим переменные, которые мы хотим заменить, рассматривая 'p' как параметр.Таким образом, он будет упорядочен ниже, чем другие, что означает, что замены попытаются удалить их в пользу 'p'.
In[127]:= replacementFunction[kK, rep, {t, f}]
Out[127]= (a b p)/(c d)
Этот подход имеет немного магии в определении того, что должно быть в списке«переменные».Возможно, что-то еще можно сделать, чтобы улучшить это.Но я считаю, что, как правило, просто не указывать то, что мы хотим использовать в качестве новых замен, - это правильный путь.
На протяжении многих лет в MathGroup были варианты этой идеи.Вполне возможно, что некоторые другие могут лучше подходить для конкретных выражений, которые вы хотите обработать.
--- edit ---
Идея, лежащая в основе этого, заключается в использовании PolynomialReduce длясделать алгебраическую замену.То есть мы не пытаемся сопоставить с образцом, а вместо этого используем полиномиальный метод канонизации.Но в целом мы не работаем с полиномиальными входами.Таким образом, мы рекурсивно применяем эту идею к аргументам PolynomialQ внутри функций NumericQ.
Более ранние версии этой идеи, наряду с некоторыми дополнительными пояснениями, можно найти в примечании, указанном ниже, а также в примечаниях, на которые оно ссылается (как этодля пояснительной рекурсии?).
http://forums.wolfram.com/mathgroup/archive/2006/Aug/msg00283.html
--- конец edit ---
--- edit 2 ---
Asнаблюдаемый в дикой природе, этот подход не всегда упрощает.Он выполняет алгебраическую замену, которая включает в себя понятие «упорядочения терминов» (грубо говоря, «какие вещи заменяются другими?») И, следовательно, простые переменные могут расширяться до более длинных выражений.
ДругойФорма переписывания термина - это синтаксическая замена через сопоставление с образцом, и другие ответы обсуждаются с использованием этого подхода.У этого есть другой недостаток, поскольку общность шаблонов для рассмотрения может стать подавляющей.Например, что делать с k ^ 2 / (w + p ^ 4) ^ 3, когда правилом является замена k / (w + p ^ 4) на q?(В частности, как мы узнаем, что это эквивалентно (k / (w + p ^ 4)) ^ 2 * 1 / (w + p ^ 4)?)
Результат должен бытьпредставление о том, что является желательным и какие методы могут быть осуществимы.Это, конечно, обычно зависит от конкретной проблемы.
Одна вещь, которая возникает, возможно, вы хотите найти и заменить все часто встречающиеся «сложные» выражения более простыми.Это называется устранением общего подвыражения (CSE).В Mathematica это можно сделать с помощью функции Experimental`OptimizeExpression [].Вот несколько ссылок на посты MathGroup, которые обсуждают это.
http://forums.wolfram.com/mathgroup/archive/2009/Jul/msg00138.html
http://forums.wolfram.com/mathgroup/archive/2007/Nov/msg00270.html
http://forums.wolfram.com/mathgroup/archive/2006/Sep/msg00300.html
http://forums.wolfram.com/mathgroup/archive/2005/Jan/msg00387.html
http://forums.wolfram.com/mathgroup/archive/2002/Jan/msg00369.html
Вот пример из одной из этих заметок.
InputForm[Experimental`OptimizeExpression[(3 + 3*a^2 + Sqrt[5 + 6*a + 5*a^2] +
a*(4 + Sqrt[5 + 6*a + 5*a^2]))/6]]
Out[206]//InputForm=
Experimental`OptimizedExpression[Block[{Compile`$1, Compile`$3, Compile`$4,
Compile`$5, Compile`$6}, Compile`$1 = a^2; Compile`$3 = 6*a;
Compile`$4 = 5*Compile`$1; Compile`$5 = 5 + Compile`$3 + Compile`$4;
Compile`$6 = Sqrt[Compile`$5]; (3 + 3*Compile`$1 + Compile`$6 +
a*(4 + Compile`$6))/6]]
--- end edit 2 ---
Daniel Lichtblau