Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add context flag multiplyRightToLeft #481

Conversation

paultpearson
Copy link
Member

Add a context flag multiplyRightToLeft with default value 0 that does not change existing behavior, and also document this feature.  Many textbooks use the convention that permutations are functions that are composed from right-to-left, which is why this feature is useful for problem authors.  Adding this flag should not affect any of the existing webwork problems that use this macro because the default behavior (multiply left-to-right) is the same as before.  For instance, we have (1 2 3)(1 2) = (2 3) with the default setting multiplyRightToLeft=>0, whereas we have (1 2 3)(1 2) = (1 3) when multiplyRightToLeft=>1.

Add a context flag `multiplyRightToLeft` with default value `0` that does not change existing behavior, and also document this feature.  Many textbooks use the convention that permutations are functions that are composed from right-to-left, which is why this feature is useful for problem authors.  Adding this flag should not affect any of the existing webwork problems that use this macro because the default behavior (multiply left-to-right) is the same as before.  For instance, we have `(1 2 3)(1 2) = (2 3)` with the default setting `multiplyRightToLeft=>0`, whereas we have `(1 2 3)(1 2) = (1 3)` when `multiplyRightToLeft=>1`.
@paultpearson
Copy link
Member Author

Here is some code that exhibits the changes.

DOCUMENT();
loadMacros(
"PGstandard.pl",
"PGML.pl",
"contextPermutation.pl",
);
TEXT(beginproblem());

Context("Permutation");
Context()->flags->set(multiplyRightToLeft => 0);
$a = Compute("(1 2 3)");
$b = Compute("(1 2)");
$ab = Compute("(1 2 3)(1 2)")->canonical;
$multflag = $ab->getFlag("multiplyRightToLeft");

BEGIN_PGML
# Order of multiplication of permutations

Part 1: The current value of the flag [| multiplyRightToLeft |] is [$multflag] (for left-to-right multiplication) and [` [$a] [$b] = [$ab] `]. 

END_PGML

Context("Permutation");
Context()->flags->set(multiplyRightToLeft => 1);
$a = Compute("(1 2 3)");
$b = Compute("(1 2)");
$ab = Compute("(1 2 3)(1 2)")->canonical;
$multflag = $ab->getFlag("multiplyRightToLeft");

BEGIN_PGML
Part 2: The current value of the flag [| multiplyRightToLeft |] is [$multflag] (for right-to-left multiplication) and [` [$a] [$b] = [$ab] `]. 
END_PGML

ENDDOCUMENT();

@dpvc
Copy link
Member

dpvc commented Jun 8, 2020

This looks OK to me. I did some testing, and it seems to work fine. I was not initially sure the canonical representation would work, but it does seem to.

@paultpearson
Copy link
Member Author

There is one issue, though. When multiplyRightToLeft => 1, the command $p1 = Compute("(4 3 2 1) (2 3) (3 2 1)") reverses the order in which the cycles appear when $p1 is printed, that is, $p1 prints as (3 2 1) (2 3) (4 3 2 1). Here's an example that shows the issue more clearly.

DOCUMENT();

loadMacros(
"PGstandard.pl",
"PGML.pl",
"contextPermutation.pl",
"PGchoicemacros.pl",
"PGcourse.pl",
);
TEXT(beginproblem());

Context("Permutation");
Context()->flags->set(multiplyRightToLeft => 0);

$p = "(4 3 2 1) (2 3) (3 2 1)";
$p1 = Compute($p);
$p1c = $p1->canonical;

BEGIN_PGML
# Multiplying permutations left-to-right

Here's the permutation as a raw string [$p]

Here's the computed permutation and it's canonical representation [$p1] = [$p1c]
[@ $PAR @]*
END_PGML

Context("Permutation");
Context()->flags->set(multiplyRightToLeft => 1);

$p = "(4 3 2 1) (2 3) (3 2 1)";
$p1 = Compute($p);
$p1c = $p1->canonical;

BEGIN_PGML
# Multiplying permutations right-to-left

Here's the permutation as a raw string [$p]

Here's the computed permutation and it's canonical representation [$p1] != [$p1c]. Notice that they're not equal.  This is because the computed permutation [$p1] is printed in the reverse order of the raw string [$p].

The raw string does equal the canonical representation [$p] = [$p1c], so they're equal and that's a relief.
END_PGML

ENDDOCUMENT();

@dpvc
Copy link
Member

dpvc commented Jun 9, 2020

@paultpearson, I've made a PR to your branch that fixes the problem you point out with the presentation being reversed. It turns out that your modification is in the routine that puts the cycles into the permutation (not the one that actually performs the multiplication), so that is causing the reversal of the order. The makeP methods are the ones that actually handle the evaluation of the permutations, and it is there that the order needs to be reversed. The PR linked above does that. It also makes it possible to apply a permutation to a number by multiplication on the right (rather than on the left) when multiplyRightToLeft is in effect.

Fix problem with RTL multiplication, and make it apply to numbers on the right
@dpvc
Copy link
Member

dpvc commented Jun 9, 2020

I think this now works as it should. But since I contributed to the PR, I don't think my approval is sufficient for review. Someone else will want to try it out and review the PR.

@mgage mgage requested review from daverosoff and enriqueacosta June 9, 2020 16:45
@enriqueacosta
Copy link

This seems to be working as it should. I wrote a test problem that generates random permutations that are products of 3 cycles and saw it behave as expected.

## TEST file based on Library/UMass-Amherst/Abstract-Algebra/PS-Permutations/Permutations8.pg

DOCUMENT();        # This should be the first executable line in the problem.

loadMacros(
  "PGstandard.pl",
  "PGML.pl",
  "contextPermutation.pl",
);

# from algebraMacros.pl
sub fyshuffle
{
    my $array = shift;
    my $i = @$array;
    while ( --$i )
    {
        my $j = random( 0, $i, 1 );
        @$array[$i,$j] = @$array[$j,$i];
    }
};

TEXT(beginproblem());
$showPartialCorrectAnswers = 0;

# the set on which our permutations will be defined
@x = ( 1 .. 9 );

# make our permutation:
# f is a product of three cycles
# To make each cycle, start with @x, shuffle it, then cut off the last few elements
@fCycle1 = @fCycle2 = @fCycle3 = @x;
fyshuffle( ~~@fCycle1 );
fyshuffle( ~~@fCycle2 );
fyshuffle( ~~@fCycle3 );

@fCycle1 = @fCycle1[ 0 .. random( 1, 5, 1 ) ];
@fCycle2 = @fCycle2[ 0 .. random( 1, 5, 1 ) ];
@fCycle3 = @fCycle3[ 0 .. random( 1, 5, 1 ) ];

# generate strings for the Permutation Objects 
$fCycle1string = "(" . join( ' ', @fCycle1 ) . ")";
$fCycle2string = "(" . join( ' ', @fCycle2 ) . ")";
$fCycle3string = "(" . join( ' ', @fCycle3 ) . ")";

# Permutation context with flag set to zero

Context("Permutation");
Context()->flags->set(multiplyRightToLeft => 0);

$pObj = Permutation($fCycle1string,$fCycle2string,$fCycle3string);
$pObjCan = $pObj->canonical;

BEGIN_PGML
# Setup

Random permutation as a raw string (product of three cycles): [$fCycle1string] [$fCycle2string] [$fCycle3string]

# Multiplying permutations left-to-right

Here's the computed permutation with left-to-right composition (should be same as raw string): [$pObj]

and it's canonical representation with left-to-right composition: [$pObjCan]

And the answer checker: [__________________]{$pObj}

END_PGML

Context("Permutation");
Context()->flags->set(multiplyRightToLeft => 1);

$pObjRtL = Permutation($fCycle1string,$fCycle2string,$fCycle3string);
$pObjRtLCan = $pObjRtL->canonical;

BEGIN_PGML
# Multiplying permutations right-to-left

Here's the computed permutation with right-to-left composition (should be same as raw string): [$pObjRtL]

and it's canonical representation with right-to-left composition: [$pObjRtLCan]

And the answer checker: [__________________]{$pObjRtL}
END_PGML

ENDDOCUMENT(); 

Only strange behavior is with the checker, but does not seem related to this PR: if canonical representation is a cycle, then the answer checker gives an error like Your answer isn't a permutation (it looks like a cycle) independent of the value of the multiplyRightToLeft flag. I do not know if it is due to some silly thing in the problem code.

@mgage
Copy link
Member

mgage commented Jun 13, 2020

Thanks everyone. I'll merge this request.

@mgage mgage merged commit 4379c54 into openwebwork:develop Jun 13, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants