224
225
if(loc!=comparator.replacement_map.end()) { // name wildcards
225
// std::cerr << "rule : " << *((*loc).first.begin()->name) << " -> " << std::endl;
226
// std::cerr << "going to replace " << *it->name << " with " << *((*loc).second.begin()->name) << std::endl;
226
// std::cerr << "rule : " << *((*loc).first.begin()->name) << " -> "
227
// << *((*loc).second.begin()->name) << std::endl;
228
// std::cerr << "going to replace " << *it->name << " with " << *((*loc).second.begin()->name) << std::endl;
228
230
// When a replacement is made here, and the index is actually
229
231
// a dummy in the replacement, we screw up the ind_dummy
236
238
ind_dummy.erase(exptree(it));
238
240
str_node::bracket_t remember_br=it->fl.bracket;
240
it->name=(*loc).second.begin()->name;
241
if(is_stripped || (it->is_name_wildcard() && !it->is_index()) ) {
242
// a?_{i j k} type patterns should only replace the head
243
// TODO: should we replace brackets here too?
244
it->name=(*loc).second.begin()->name;
245
it->multiplier=(*loc).second.begin()->multiplier;
246
it->fl=(*loc).second.begin()->fl;
242
249
it=tr.replace_index(it, (*loc).second.begin());
243
250
it->fl.bracket=remember_br;
398
Vary should take into account the depth of an object in a more clever way than
399
is currently done. Consider an expression
401
A \partial{ A C + B } + D A;
403
and A->a, B->b etc. This should vary to
405
a \partial{ A C + B } + A \partial{ a C + A c + b } + d A + a D;
407
Right now it produces a total mess for the partial derivative, because it does
408
not understand that the depth counting for factors inside the partial involves
409
knowing about the top-level product.
411
So what we should do is introduce a 'factor depth' and a 'sum index', which equal
413
A \partial{ A C + B } + D A;
388
420
vary::vary(exptree& tr, iterator it)
389
421
: algorithm(tr, it)
398
430
bool vary::can_apply(iterator it)
400
432
if(*it->name=="\\prod") return true;
433
if(*it->name=="\\sum") return true;
401
434
if(is_single_term(it)) return true;
435
if(is_nonprod_factor_in_prod(it)) return true;
436
const Derivative *der = properties::get<Derivative>(it);
438
der = properties::get<Derivative>(tr.parent(it));
440
const Accent *acc = properties::get<Accent>(it);
442
acc = properties::get<Accent>(tr.parent(it));
405
447
algorithm::result_t vary::apply(iterator& it)
407
if(is_single_term(it)) { // easy: just vary this term
449
const Derivative *der = properties::get<Derivative>(it);
450
const Accent *acc = properties::get<Accent>(it);
452
vary vry(tr, this_command);
454
sibling_iterator sib=tr.begin(it);
455
while(sib!=tr.end(it)) {
458
if(app->is_index()) continue;
459
if(vry.can_apply(app)) {
461
}// not complete: should remove object when zero
463
expression_modified=true;
467
if(*it->name=="\\prod") {
469
result.set_head(str_node("\\expression"));
470
iterator newsum=result.append_child(result.begin(), str_node("\\sum"));
472
// Iterate over all factors, attempting a substitute. If this
473
// succeeds, copy the term to the "result" tree. Then restore the
474
// original. We have to do the substitute on the original tree so
475
// that index relabelling takes into account the rest of the tree.
477
exptree prodcopy(it); // keep a copy to restore after each substitute
479
vary subs(tr, this_command);
482
sibling_iterator fcit=tr.begin(it);
484
if(fcit==tr.end(it)) break;
486
iterator fcit2(fcit);
487
if(subs.can_apply(fcit2)) {
489
expression_modified=true;
491
if(fcit2->is_zero()==false)
492
iterator newterm=result.append_child(newsum, it);
495
it=tr.replace(it, prodcopy.begin());
499
if(expression_modified && tr.number_of_children(newsum)>0) {
500
it=tr.move_ontop(it, newsum);
501
cleanup_nests(tr, it);
502
cleanup_expression(tr, it);
504
else { // varying any of the factors produces nothing, variation is zero
505
zero(it->multiplier);
506
expression_modified=true;
511
if(*it->name=="\\sum") { // call vary on every term
512
vary vry(tr, this_command);
514
sibling_iterator sib=tr.begin(it);
515
while(sib!=tr.end(it)) {
518
if(vry.can_apply(app)) {
529
expression_modified=true;
533
der = properties::get<Derivative>(tr.parent(it));
534
acc = properties::get<Accent>(tr.parent(it));
536
if(der || acc || is_single_term(it)) { // easy: just vary this term by substitution
408
537
substitute subs(tr, this_command);
409
538
if(subs.can_apply(it)) {
410
539
if(subs.apply(it)==l_applied) {
415
544
return l_no_action;
419
result.set_head(str_node("\\expression"));
420
iterator newsum=result.append_child(result.begin(), str_node("\\sum"));
422
// Iterate over all factors, attempting a substitute. If this
423
// succeeds, copy the term to the "result" tree. Then restore the
424
// original. We have to do the substitute on the original tree so
425
// that index relabelling takes into account the rest of the tree.
427
exptree prodcopy(it); // keep a copy to restore after each substitute
429
substitute subs(tr, this_command);
432
sibling_iterator fcit=tr.begin(it);
434
if(fcit==tr.end(it)) break;
436
iterator fcit2(fcit);
437
if(subs.apply_recursive(fcit2, false)) {
438
expression_modified=true;
439
iterator newterm=result.append_child(newsum, it);
441
it=tr.replace(it, prodcopy.begin());
547
if(is_nonprod_factor_in_prod(it)) {
548
substitute subs(tr, this_command);
549
if(subs.can_apply(it)) {
550
if(subs.apply(it)==l_applied) {
551
expression_modified=true;
445
if(expression_modified) {
446
it=tr.move_ontop(it, newsum);
447
cleanup_nests(tr, it);
448
cleanup_expression(tr, it);
450
else { // substitute didn't act anywhere, variation is zero
451
556
zero(it->multiplier);
452
557
expression_modified=true;