Set every element to zero in matrix unless it's `1` or `1/2`












5












$begingroup$


I have the following code:



max = 1;

PotentialTilde[V0_] :=
SparseArray[{Band[{1, 1}] -> V0/1, Band[{2, 1}] -> V0/2,
Band[{1, 2}] -> V0/2}, {2*max + 1, 2*max + 1 }];

a = KroneckerProduct[PotentialTilde[1], PotentialTilde[1]] //
MatrixForm


That generates this matrix:



<span class=$$ $$">





How do I set every element that is not equal to 1 or 1/2 to 0?










share|improve this question











$endgroup$












  • $begingroup$
    Something like a /. {1 -> 0, 1/2 -> 0} should do it.
    $endgroup$
    – Carl Lange
    6 hours ago










  • $begingroup$
    Yeah, but I want the opposite. Anything that is NOT equal to 1 and 1/2
    $endgroup$
    – SuperCiocia
    6 hours ago










  • $begingroup$
    Also, your command does not change anything to my a
    $endgroup$
    – SuperCiocia
    6 hours ago






  • 1




    $begingroup$
    Look up Except. Also, if you want to change a, you have to assign the result to a again. (In Mathematica, barely anything changes variables, most things are immutable)
    $endgroup$
    – Lukas Lang
    5 hours ago










  • $begingroup$
    Ah, sorry, I misread (and I wasn't at a computer). Glad you've found the answer!
    $endgroup$
    – Carl Lange
    3 hours ago
















5












$begingroup$


I have the following code:



max = 1;

PotentialTilde[V0_] :=
SparseArray[{Band[{1, 1}] -> V0/1, Band[{2, 1}] -> V0/2,
Band[{1, 2}] -> V0/2}, {2*max + 1, 2*max + 1 }];

a = KroneckerProduct[PotentialTilde[1], PotentialTilde[1]] //
MatrixForm


That generates this matrix:



<span class=$$ $$">





How do I set every element that is not equal to 1 or 1/2 to 0?










share|improve this question











$endgroup$












  • $begingroup$
    Something like a /. {1 -> 0, 1/2 -> 0} should do it.
    $endgroup$
    – Carl Lange
    6 hours ago










  • $begingroup$
    Yeah, but I want the opposite. Anything that is NOT equal to 1 and 1/2
    $endgroup$
    – SuperCiocia
    6 hours ago










  • $begingroup$
    Also, your command does not change anything to my a
    $endgroup$
    – SuperCiocia
    6 hours ago






  • 1




    $begingroup$
    Look up Except. Also, if you want to change a, you have to assign the result to a again. (In Mathematica, barely anything changes variables, most things are immutable)
    $endgroup$
    – Lukas Lang
    5 hours ago










  • $begingroup$
    Ah, sorry, I misread (and I wasn't at a computer). Glad you've found the answer!
    $endgroup$
    – Carl Lange
    3 hours ago














5












5








5





$begingroup$


I have the following code:



max = 1;

PotentialTilde[V0_] :=
SparseArray[{Band[{1, 1}] -> V0/1, Band[{2, 1}] -> V0/2,
Band[{1, 2}] -> V0/2}, {2*max + 1, 2*max + 1 }];

a = KroneckerProduct[PotentialTilde[1], PotentialTilde[1]] //
MatrixForm


That generates this matrix:



<span class=$$ $$">





How do I set every element that is not equal to 1 or 1/2 to 0?










share|improve this question











$endgroup$




I have the following code:



max = 1;

PotentialTilde[V0_] :=
SparseArray[{Band[{1, 1}] -> V0/1, Band[{2, 1}] -> V0/2,
Band[{1, 2}] -> V0/2}, {2*max + 1, 2*max + 1 }];

a = KroneckerProduct[PotentialTilde[1], PotentialTilde[1]] //
MatrixForm


That generates this matrix:



<span class=$$ $$">





How do I set every element that is not equal to 1 or 1/2 to 0?







list-manipulation matrix sparse-arrays






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 3 hours ago









Henrik Schumacher

50.6k469144




50.6k469144










asked 6 hours ago









SuperCiociaSuperCiocia

535311




535311












  • $begingroup$
    Something like a /. {1 -> 0, 1/2 -> 0} should do it.
    $endgroup$
    – Carl Lange
    6 hours ago










  • $begingroup$
    Yeah, but I want the opposite. Anything that is NOT equal to 1 and 1/2
    $endgroup$
    – SuperCiocia
    6 hours ago










  • $begingroup$
    Also, your command does not change anything to my a
    $endgroup$
    – SuperCiocia
    6 hours ago






  • 1




    $begingroup$
    Look up Except. Also, if you want to change a, you have to assign the result to a again. (In Mathematica, barely anything changes variables, most things are immutable)
    $endgroup$
    – Lukas Lang
    5 hours ago










  • $begingroup$
    Ah, sorry, I misread (and I wasn't at a computer). Glad you've found the answer!
    $endgroup$
    – Carl Lange
    3 hours ago


















  • $begingroup$
    Something like a /. {1 -> 0, 1/2 -> 0} should do it.
    $endgroup$
    – Carl Lange
    6 hours ago










  • $begingroup$
    Yeah, but I want the opposite. Anything that is NOT equal to 1 and 1/2
    $endgroup$
    – SuperCiocia
    6 hours ago










  • $begingroup$
    Also, your command does not change anything to my a
    $endgroup$
    – SuperCiocia
    6 hours ago






  • 1




    $begingroup$
    Look up Except. Also, if you want to change a, you have to assign the result to a again. (In Mathematica, barely anything changes variables, most things are immutable)
    $endgroup$
    – Lukas Lang
    5 hours ago










  • $begingroup$
    Ah, sorry, I misread (and I wasn't at a computer). Glad you've found the answer!
    $endgroup$
    – Carl Lange
    3 hours ago
















$begingroup$
Something like a /. {1 -> 0, 1/2 -> 0} should do it.
$endgroup$
– Carl Lange
6 hours ago




$begingroup$
Something like a /. {1 -> 0, 1/2 -> 0} should do it.
$endgroup$
– Carl Lange
6 hours ago












$begingroup$
Yeah, but I want the opposite. Anything that is NOT equal to 1 and 1/2
$endgroup$
– SuperCiocia
6 hours ago




$begingroup$
Yeah, but I want the opposite. Anything that is NOT equal to 1 and 1/2
$endgroup$
– SuperCiocia
6 hours ago












$begingroup$
Also, your command does not change anything to my a
$endgroup$
– SuperCiocia
6 hours ago




$begingroup$
Also, your command does not change anything to my a
$endgroup$
– SuperCiocia
6 hours ago




1




1




$begingroup$
Look up Except. Also, if you want to change a, you have to assign the result to a again. (In Mathematica, barely anything changes variables, most things are immutable)
$endgroup$
– Lukas Lang
5 hours ago




$begingroup$
Look up Except. Also, if you want to change a, you have to assign the result to a again. (In Mathematica, barely anything changes variables, most things are immutable)
$endgroup$
– Lukas Lang
5 hours ago












$begingroup$
Ah, sorry, I misread (and I wasn't at a computer). Glad you've found the answer!
$endgroup$
– Carl Lange
3 hours ago




$begingroup$
Ah, sorry, I misread (and I wasn't at a computer). Glad you've found the answer!
$endgroup$
– Carl Lange
3 hours ago










3 Answers
3






active

oldest

votes


















10












$begingroup$

Be careful with assigning a "form" (e.g. MatrixForm) to a variable. Another observation is that a is a SparseArray uses rules to store the values and since ReplaceAll works with the FullForm of an expression care has to be taken (using Normal will make the array a regular matrix again).



This should work:



max = 1;
PotentialTilde[V0_] := SparseArray[{Band[{1, 1}] -> V0/1, Band[{2, 1}] -> V0/2,
Band[{1, 2}] -> V0/2}, {2*max + 1, 2*max + 1}];

a = KroneckerProduct[PotentialTilde[1], PotentialTilde[1]];
(* a // MatrixForm *)

aMod = (a // Normal) /. x_?NumericQ /; Not@MatchQ[x, 1 | 1/2] -> 0;
aMod // MatrixForm


Matrix



Lukas Lang's suggestion is even nicer:



aMod = (a // Normal) /. Except[1 | 1/2, _?NumericQ] -> 0;


UPDATE



@HenrikSchumacher is of course right in warning against the use of Normal for a SparseArray -- after all there may have been a good reason for using it in the first place. So for a pattern replacement solution the use of ArrayRules may be safer:



aMod = ( a // ArrayRules ) // RightComposition[
ReplaceAll @ Rule[
Rule[{row_?NumericQ, col_?NumericQ}, Except[ 1 | 1/2, _?NumericQ ],
Rule[{row,col}, 0]
]
, SparseArray
];
aMod // MatrixForm





share|improve this answer











$endgroup$









  • 1




    $begingroup$
    Huh, never apply Normal to SparseArrays. Hell might break loose... ;) (Anyways, +1 of course.)
    $endgroup$
    – Henrik Schumacher
    5 hours ago





















9












$begingroup$

A = KroneckerProduct[PotentialTilde[1], PotentialTilde[1]];
B = A (1 - Unitize[A - 1/2] Unitize[A - 1]);
B // MatrixForm




It is even much more efficient to use machine precision numbers:



max = 100;
A = KroneckerProduct[PotentialTilde[1], PotentialTilde[1]];
B = A (1 - Unitize[A - 1/2] Unitize[A - 1]); // RepeatedTiming // First

NA = N[A];
NB1 = NA (1. - Unitize[NA - 0.5] Unitize[NA - 1.]); // RepeatedTiming // First

Max[Abs[B - NB]]



0.269



0.0163



0.




It is even faster (but also quite a bit more tedious, though), to operate only on the list of nonzero values by using the low-level representation of SparseArray and the following undocumented constructor:



NB2 = SparseArray[
SparseArray @@ {
Automatic,
Dimensions[NA],
NA["Background"],
{1(*version of SparseArray implementation*),
{
NA["RowPointers"],
NA["ColumnIndices"]
},
With[{vals = NA["NonzeroValues"]},
vals Subtract[1., Unitize[vals - 0.5] Unitize[vals - 1.]]
]
}
}
]; // RepeatedTiming // First



0.00670




The advantage over modifying ArrayRules is that it leaves all array packed (they can only be backed for machine precisision numbers or machine integers; not for symbolic entries) while ArrayRules unpacks the list of nonzero positions and nonzero positions in order to generate the symbolic list of rules.



Should you wonder why SparseArray appears twice here: SparseArray@@{...} constructs the sparse array literally by the row pointers, column indices and "nonzero values" provided, even if there are actually zeroes among the "nonzero values"; wrapping this with a further SparseArray removes these "ghosts" from the internal representation, so that NB2["NonzeroValues"] returns really only the nonzero values.






share|improve this answer











$endgroup$













  • $begingroup$
    (+1) Very concise and elegant. I updated my solution - maybe for a pattern matching solution applying ArrayRules instead of Normal is saver?
    $endgroup$
    – gwr
    4 hours ago










  • $begingroup$
    @gwr Jepp, it definitely is.
    $endgroup$
    – Henrik Schumacher
    3 hours ago



















5












$begingroup$

a cannot be a MatrixForm:



(a = KroneckerProduct[PotentialTilde[1], 
PotentialTilde[1]]) // MatrixForm


Convert to a regular Matrix:



Normal[a] /. {ij_ /; (NumberQ[
ij] && ( ij != 1/2 && ij != 1)) :> 0}

(a = Normal[
a] /. {ij_ /; (NumberQ[
ij] && ( ij != 1/2 && ij != 1)) :>
0}) // MatrixForm
a

MatrixForm[a]





share|improve this answer









$endgroup$













    Your Answer





    StackExchange.ifUsing("editor", function () {
    return StackExchange.using("mathjaxEditing", function () {
    StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
    StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["$", "$"], ["\\(","\\)"]]);
    });
    });
    }, "mathjax-editing");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "387"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: false,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fmathematica.stackexchange.com%2fquestions%2f189758%2fset-every-element-to-zero-in-matrix-unless-its-1-or-1-2%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    3 Answers
    3






    active

    oldest

    votes








    3 Answers
    3






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    10












    $begingroup$

    Be careful with assigning a "form" (e.g. MatrixForm) to a variable. Another observation is that a is a SparseArray uses rules to store the values and since ReplaceAll works with the FullForm of an expression care has to be taken (using Normal will make the array a regular matrix again).



    This should work:



    max = 1;
    PotentialTilde[V0_] := SparseArray[{Band[{1, 1}] -> V0/1, Band[{2, 1}] -> V0/2,
    Band[{1, 2}] -> V0/2}, {2*max + 1, 2*max + 1}];

    a = KroneckerProduct[PotentialTilde[1], PotentialTilde[1]];
    (* a // MatrixForm *)

    aMod = (a // Normal) /. x_?NumericQ /; Not@MatchQ[x, 1 | 1/2] -> 0;
    aMod // MatrixForm


    Matrix



    Lukas Lang's suggestion is even nicer:



    aMod = (a // Normal) /. Except[1 | 1/2, _?NumericQ] -> 0;


    UPDATE



    @HenrikSchumacher is of course right in warning against the use of Normal for a SparseArray -- after all there may have been a good reason for using it in the first place. So for a pattern replacement solution the use of ArrayRules may be safer:



    aMod = ( a // ArrayRules ) // RightComposition[
    ReplaceAll @ Rule[
    Rule[{row_?NumericQ, col_?NumericQ}, Except[ 1 | 1/2, _?NumericQ ],
    Rule[{row,col}, 0]
    ]
    , SparseArray
    ];
    aMod // MatrixForm





    share|improve this answer











    $endgroup$









    • 1




      $begingroup$
      Huh, never apply Normal to SparseArrays. Hell might break loose... ;) (Anyways, +1 of course.)
      $endgroup$
      – Henrik Schumacher
      5 hours ago


















    10












    $begingroup$

    Be careful with assigning a "form" (e.g. MatrixForm) to a variable. Another observation is that a is a SparseArray uses rules to store the values and since ReplaceAll works with the FullForm of an expression care has to be taken (using Normal will make the array a regular matrix again).



    This should work:



    max = 1;
    PotentialTilde[V0_] := SparseArray[{Band[{1, 1}] -> V0/1, Band[{2, 1}] -> V0/2,
    Band[{1, 2}] -> V0/2}, {2*max + 1, 2*max + 1}];

    a = KroneckerProduct[PotentialTilde[1], PotentialTilde[1]];
    (* a // MatrixForm *)

    aMod = (a // Normal) /. x_?NumericQ /; Not@MatchQ[x, 1 | 1/2] -> 0;
    aMod // MatrixForm


    Matrix



    Lukas Lang's suggestion is even nicer:



    aMod = (a // Normal) /. Except[1 | 1/2, _?NumericQ] -> 0;


    UPDATE



    @HenrikSchumacher is of course right in warning against the use of Normal for a SparseArray -- after all there may have been a good reason for using it in the first place. So for a pattern replacement solution the use of ArrayRules may be safer:



    aMod = ( a // ArrayRules ) // RightComposition[
    ReplaceAll @ Rule[
    Rule[{row_?NumericQ, col_?NumericQ}, Except[ 1 | 1/2, _?NumericQ ],
    Rule[{row,col}, 0]
    ]
    , SparseArray
    ];
    aMod // MatrixForm





    share|improve this answer











    $endgroup$









    • 1




      $begingroup$
      Huh, never apply Normal to SparseArrays. Hell might break loose... ;) (Anyways, +1 of course.)
      $endgroup$
      – Henrik Schumacher
      5 hours ago
















    10












    10








    10





    $begingroup$

    Be careful with assigning a "form" (e.g. MatrixForm) to a variable. Another observation is that a is a SparseArray uses rules to store the values and since ReplaceAll works with the FullForm of an expression care has to be taken (using Normal will make the array a regular matrix again).



    This should work:



    max = 1;
    PotentialTilde[V0_] := SparseArray[{Band[{1, 1}] -> V0/1, Band[{2, 1}] -> V0/2,
    Band[{1, 2}] -> V0/2}, {2*max + 1, 2*max + 1}];

    a = KroneckerProduct[PotentialTilde[1], PotentialTilde[1]];
    (* a // MatrixForm *)

    aMod = (a // Normal) /. x_?NumericQ /; Not@MatchQ[x, 1 | 1/2] -> 0;
    aMod // MatrixForm


    Matrix



    Lukas Lang's suggestion is even nicer:



    aMod = (a // Normal) /. Except[1 | 1/2, _?NumericQ] -> 0;


    UPDATE



    @HenrikSchumacher is of course right in warning against the use of Normal for a SparseArray -- after all there may have been a good reason for using it in the first place. So for a pattern replacement solution the use of ArrayRules may be safer:



    aMod = ( a // ArrayRules ) // RightComposition[
    ReplaceAll @ Rule[
    Rule[{row_?NumericQ, col_?NumericQ}, Except[ 1 | 1/2, _?NumericQ ],
    Rule[{row,col}, 0]
    ]
    , SparseArray
    ];
    aMod // MatrixForm





    share|improve this answer











    $endgroup$



    Be careful with assigning a "form" (e.g. MatrixForm) to a variable. Another observation is that a is a SparseArray uses rules to store the values and since ReplaceAll works with the FullForm of an expression care has to be taken (using Normal will make the array a regular matrix again).



    This should work:



    max = 1;
    PotentialTilde[V0_] := SparseArray[{Band[{1, 1}] -> V0/1, Band[{2, 1}] -> V0/2,
    Band[{1, 2}] -> V0/2}, {2*max + 1, 2*max + 1}];

    a = KroneckerProduct[PotentialTilde[1], PotentialTilde[1]];
    (* a // MatrixForm *)

    aMod = (a // Normal) /. x_?NumericQ /; Not@MatchQ[x, 1 | 1/2] -> 0;
    aMod // MatrixForm


    Matrix



    Lukas Lang's suggestion is even nicer:



    aMod = (a // Normal) /. Except[1 | 1/2, _?NumericQ] -> 0;


    UPDATE



    @HenrikSchumacher is of course right in warning against the use of Normal for a SparseArray -- after all there may have been a good reason for using it in the first place. So for a pattern replacement solution the use of ArrayRules may be safer:



    aMod = ( a // ArrayRules ) // RightComposition[
    ReplaceAll @ Rule[
    Rule[{row_?NumericQ, col_?NumericQ}, Except[ 1 | 1/2, _?NumericQ ],
    Rule[{row,col}, 0]
    ]
    , SparseArray
    ];
    aMod // MatrixForm






    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited 4 hours ago

























    answered 5 hours ago









    gwrgwr

    7,86322659




    7,86322659








    • 1




      $begingroup$
      Huh, never apply Normal to SparseArrays. Hell might break loose... ;) (Anyways, +1 of course.)
      $endgroup$
      – Henrik Schumacher
      5 hours ago
















    • 1




      $begingroup$
      Huh, never apply Normal to SparseArrays. Hell might break loose... ;) (Anyways, +1 of course.)
      $endgroup$
      – Henrik Schumacher
      5 hours ago










    1




    1




    $begingroup$
    Huh, never apply Normal to SparseArrays. Hell might break loose... ;) (Anyways, +1 of course.)
    $endgroup$
    – Henrik Schumacher
    5 hours ago






    $begingroup$
    Huh, never apply Normal to SparseArrays. Hell might break loose... ;) (Anyways, +1 of course.)
    $endgroup$
    – Henrik Schumacher
    5 hours ago













    9












    $begingroup$

    A = KroneckerProduct[PotentialTilde[1], PotentialTilde[1]];
    B = A (1 - Unitize[A - 1/2] Unitize[A - 1]);
    B // MatrixForm




    It is even much more efficient to use machine precision numbers:



    max = 100;
    A = KroneckerProduct[PotentialTilde[1], PotentialTilde[1]];
    B = A (1 - Unitize[A - 1/2] Unitize[A - 1]); // RepeatedTiming // First

    NA = N[A];
    NB1 = NA (1. - Unitize[NA - 0.5] Unitize[NA - 1.]); // RepeatedTiming // First

    Max[Abs[B - NB]]



    0.269



    0.0163



    0.




    It is even faster (but also quite a bit more tedious, though), to operate only on the list of nonzero values by using the low-level representation of SparseArray and the following undocumented constructor:



    NB2 = SparseArray[
    SparseArray @@ {
    Automatic,
    Dimensions[NA],
    NA["Background"],
    {1(*version of SparseArray implementation*),
    {
    NA["RowPointers"],
    NA["ColumnIndices"]
    },
    With[{vals = NA["NonzeroValues"]},
    vals Subtract[1., Unitize[vals - 0.5] Unitize[vals - 1.]]
    ]
    }
    }
    ]; // RepeatedTiming // First



    0.00670




    The advantage over modifying ArrayRules is that it leaves all array packed (they can only be backed for machine precisision numbers or machine integers; not for symbolic entries) while ArrayRules unpacks the list of nonzero positions and nonzero positions in order to generate the symbolic list of rules.



    Should you wonder why SparseArray appears twice here: SparseArray@@{...} constructs the sparse array literally by the row pointers, column indices and "nonzero values" provided, even if there are actually zeroes among the "nonzero values"; wrapping this with a further SparseArray removes these "ghosts" from the internal representation, so that NB2["NonzeroValues"] returns really only the nonzero values.






    share|improve this answer











    $endgroup$













    • $begingroup$
      (+1) Very concise and elegant. I updated my solution - maybe for a pattern matching solution applying ArrayRules instead of Normal is saver?
      $endgroup$
      – gwr
      4 hours ago










    • $begingroup$
      @gwr Jepp, it definitely is.
      $endgroup$
      – Henrik Schumacher
      3 hours ago
















    9












    $begingroup$

    A = KroneckerProduct[PotentialTilde[1], PotentialTilde[1]];
    B = A (1 - Unitize[A - 1/2] Unitize[A - 1]);
    B // MatrixForm




    It is even much more efficient to use machine precision numbers:



    max = 100;
    A = KroneckerProduct[PotentialTilde[1], PotentialTilde[1]];
    B = A (1 - Unitize[A - 1/2] Unitize[A - 1]); // RepeatedTiming // First

    NA = N[A];
    NB1 = NA (1. - Unitize[NA - 0.5] Unitize[NA - 1.]); // RepeatedTiming // First

    Max[Abs[B - NB]]



    0.269



    0.0163



    0.




    It is even faster (but also quite a bit more tedious, though), to operate only on the list of nonzero values by using the low-level representation of SparseArray and the following undocumented constructor:



    NB2 = SparseArray[
    SparseArray @@ {
    Automatic,
    Dimensions[NA],
    NA["Background"],
    {1(*version of SparseArray implementation*),
    {
    NA["RowPointers"],
    NA["ColumnIndices"]
    },
    With[{vals = NA["NonzeroValues"]},
    vals Subtract[1., Unitize[vals - 0.5] Unitize[vals - 1.]]
    ]
    }
    }
    ]; // RepeatedTiming // First



    0.00670




    The advantage over modifying ArrayRules is that it leaves all array packed (they can only be backed for machine precisision numbers or machine integers; not for symbolic entries) while ArrayRules unpacks the list of nonzero positions and nonzero positions in order to generate the symbolic list of rules.



    Should you wonder why SparseArray appears twice here: SparseArray@@{...} constructs the sparse array literally by the row pointers, column indices and "nonzero values" provided, even if there are actually zeroes among the "nonzero values"; wrapping this with a further SparseArray removes these "ghosts" from the internal representation, so that NB2["NonzeroValues"] returns really only the nonzero values.






    share|improve this answer











    $endgroup$













    • $begingroup$
      (+1) Very concise and elegant. I updated my solution - maybe for a pattern matching solution applying ArrayRules instead of Normal is saver?
      $endgroup$
      – gwr
      4 hours ago










    • $begingroup$
      @gwr Jepp, it definitely is.
      $endgroup$
      – Henrik Schumacher
      3 hours ago














    9












    9








    9





    $begingroup$

    A = KroneckerProduct[PotentialTilde[1], PotentialTilde[1]];
    B = A (1 - Unitize[A - 1/2] Unitize[A - 1]);
    B // MatrixForm




    It is even much more efficient to use machine precision numbers:



    max = 100;
    A = KroneckerProduct[PotentialTilde[1], PotentialTilde[1]];
    B = A (1 - Unitize[A - 1/2] Unitize[A - 1]); // RepeatedTiming // First

    NA = N[A];
    NB1 = NA (1. - Unitize[NA - 0.5] Unitize[NA - 1.]); // RepeatedTiming // First

    Max[Abs[B - NB]]



    0.269



    0.0163



    0.




    It is even faster (but also quite a bit more tedious, though), to operate only on the list of nonzero values by using the low-level representation of SparseArray and the following undocumented constructor:



    NB2 = SparseArray[
    SparseArray @@ {
    Automatic,
    Dimensions[NA],
    NA["Background"],
    {1(*version of SparseArray implementation*),
    {
    NA["RowPointers"],
    NA["ColumnIndices"]
    },
    With[{vals = NA["NonzeroValues"]},
    vals Subtract[1., Unitize[vals - 0.5] Unitize[vals - 1.]]
    ]
    }
    }
    ]; // RepeatedTiming // First



    0.00670




    The advantage over modifying ArrayRules is that it leaves all array packed (they can only be backed for machine precisision numbers or machine integers; not for symbolic entries) while ArrayRules unpacks the list of nonzero positions and nonzero positions in order to generate the symbolic list of rules.



    Should you wonder why SparseArray appears twice here: SparseArray@@{...} constructs the sparse array literally by the row pointers, column indices and "nonzero values" provided, even if there are actually zeroes among the "nonzero values"; wrapping this with a further SparseArray removes these "ghosts" from the internal representation, so that NB2["NonzeroValues"] returns really only the nonzero values.






    share|improve this answer











    $endgroup$



    A = KroneckerProduct[PotentialTilde[1], PotentialTilde[1]];
    B = A (1 - Unitize[A - 1/2] Unitize[A - 1]);
    B // MatrixForm




    It is even much more efficient to use machine precision numbers:



    max = 100;
    A = KroneckerProduct[PotentialTilde[1], PotentialTilde[1]];
    B = A (1 - Unitize[A - 1/2] Unitize[A - 1]); // RepeatedTiming // First

    NA = N[A];
    NB1 = NA (1. - Unitize[NA - 0.5] Unitize[NA - 1.]); // RepeatedTiming // First

    Max[Abs[B - NB]]



    0.269



    0.0163



    0.




    It is even faster (but also quite a bit more tedious, though), to operate only on the list of nonzero values by using the low-level representation of SparseArray and the following undocumented constructor:



    NB2 = SparseArray[
    SparseArray @@ {
    Automatic,
    Dimensions[NA],
    NA["Background"],
    {1(*version of SparseArray implementation*),
    {
    NA["RowPointers"],
    NA["ColumnIndices"]
    },
    With[{vals = NA["NonzeroValues"]},
    vals Subtract[1., Unitize[vals - 0.5] Unitize[vals - 1.]]
    ]
    }
    }
    ]; // RepeatedTiming // First



    0.00670




    The advantage over modifying ArrayRules is that it leaves all array packed (they can only be backed for machine precisision numbers or machine integers; not for symbolic entries) while ArrayRules unpacks the list of nonzero positions and nonzero positions in order to generate the symbolic list of rules.



    Should you wonder why SparseArray appears twice here: SparseArray@@{...} constructs the sparse array literally by the row pointers, column indices and "nonzero values" provided, even if there are actually zeroes among the "nonzero values"; wrapping this with a further SparseArray removes these "ghosts" from the internal representation, so that NB2["NonzeroValues"] returns really only the nonzero values.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited 3 hours ago

























    answered 5 hours ago









    Henrik SchumacherHenrik Schumacher

    50.6k469144




    50.6k469144












    • $begingroup$
      (+1) Very concise and elegant. I updated my solution - maybe for a pattern matching solution applying ArrayRules instead of Normal is saver?
      $endgroup$
      – gwr
      4 hours ago










    • $begingroup$
      @gwr Jepp, it definitely is.
      $endgroup$
      – Henrik Schumacher
      3 hours ago


















    • $begingroup$
      (+1) Very concise and elegant. I updated my solution - maybe for a pattern matching solution applying ArrayRules instead of Normal is saver?
      $endgroup$
      – gwr
      4 hours ago










    • $begingroup$
      @gwr Jepp, it definitely is.
      $endgroup$
      – Henrik Schumacher
      3 hours ago
















    $begingroup$
    (+1) Very concise and elegant. I updated my solution - maybe for a pattern matching solution applying ArrayRules instead of Normal is saver?
    $endgroup$
    – gwr
    4 hours ago




    $begingroup$
    (+1) Very concise and elegant. I updated my solution - maybe for a pattern matching solution applying ArrayRules instead of Normal is saver?
    $endgroup$
    – gwr
    4 hours ago












    $begingroup$
    @gwr Jepp, it definitely is.
    $endgroup$
    – Henrik Schumacher
    3 hours ago




    $begingroup$
    @gwr Jepp, it definitely is.
    $endgroup$
    – Henrik Schumacher
    3 hours ago











    5












    $begingroup$

    a cannot be a MatrixForm:



    (a = KroneckerProduct[PotentialTilde[1], 
    PotentialTilde[1]]) // MatrixForm


    Convert to a regular Matrix:



    Normal[a] /. {ij_ /; (NumberQ[
    ij] && ( ij != 1/2 && ij != 1)) :> 0}

    (a = Normal[
    a] /. {ij_ /; (NumberQ[
    ij] && ( ij != 1/2 && ij != 1)) :>
    0}) // MatrixForm
    a

    MatrixForm[a]





    share|improve this answer









    $endgroup$


















      5












      $begingroup$

      a cannot be a MatrixForm:



      (a = KroneckerProduct[PotentialTilde[1], 
      PotentialTilde[1]]) // MatrixForm


      Convert to a regular Matrix:



      Normal[a] /. {ij_ /; (NumberQ[
      ij] && ( ij != 1/2 && ij != 1)) :> 0}

      (a = Normal[
      a] /. {ij_ /; (NumberQ[
      ij] && ( ij != 1/2 && ij != 1)) :>
      0}) // MatrixForm
      a

      MatrixForm[a]





      share|improve this answer









      $endgroup$
















        5












        5








        5





        $begingroup$

        a cannot be a MatrixForm:



        (a = KroneckerProduct[PotentialTilde[1], 
        PotentialTilde[1]]) // MatrixForm


        Convert to a regular Matrix:



        Normal[a] /. {ij_ /; (NumberQ[
        ij] && ( ij != 1/2 && ij != 1)) :> 0}

        (a = Normal[
        a] /. {ij_ /; (NumberQ[
        ij] && ( ij != 1/2 && ij != 1)) :>
        0}) // MatrixForm
        a

        MatrixForm[a]





        share|improve this answer









        $endgroup$



        a cannot be a MatrixForm:



        (a = KroneckerProduct[PotentialTilde[1], 
        PotentialTilde[1]]) // MatrixForm


        Convert to a regular Matrix:



        Normal[a] /. {ij_ /; (NumberQ[
        ij] && ( ij != 1/2 && ij != 1)) :> 0}

        (a = Normal[
        a] /. {ij_ /; (NumberQ[
        ij] && ( ij != 1/2 && ij != 1)) :>
        0}) // MatrixForm
        a

        MatrixForm[a]






        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered 5 hours ago









        Craig CarterCraig Carter

        529412




        529412






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Mathematica Stack Exchange!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            Use MathJax to format equations. MathJax reference.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fmathematica.stackexchange.com%2fquestions%2f189758%2fset-every-element-to-zero-in-matrix-unless-its-1-or-1-2%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            香粉寮

            GameSpot