3
$\begingroup$

I have a 3x3 matrix

testweightedgraph = {{{}, {p, q, pq, pq}, {}}, {{p, q, pq, 
pq}, {q}, {}}, {{}, {}, {}}};

whose elements are (possibly empty) lists.

I would like to apply the pure function

1 - Apply[Times, 1 - #] &

to every nonempty element of the matrix, leaving the empty elements exactly as they are. The result I want is this:

{{{}, {1 - (1 - p) (1 - pq)^2 (1 - q)}, {}}, {{1 - (1 - p) (1 - 
   pq)^2 (1 - q)}, {q}, {}}, {{}, {}, {}}}

If I use

Map[{1 - Apply[Times, 1 - #]} &, testweightedgraph, {2}]

then I get

{{{0}, {1 - (1 - p) (1 - pq)^2 (1 - q)}, {0}}, {{1 - (1 - p) (1 - 
   pq)^2 (1 - q)}, {q}, {0}}, {{0}, {0}, {0}}}

which is perfect, except that all instances of {0} should be replaced by {}.

Rather than patching the result, by somehow replacing {0}s by {}s, I would like to get it right in the first place.

One option seems to be to use Position and feed its results to MapAt. This has two disadvantages for me: 1) Perhaps Position needs to be told exactly what to look for, and cannot be asked to look for elements satisfying a pattern (such as, in this case "not being the empty list"). 2) If we are going to have to use pattern matching anyway, then isn't there a more direct way to do it, without using Position or MapAt ?

I have studied the tutorials on Pattern Matching but I confess I find it very hard to understand.

$\endgroup$
4
$\begingroup$

Design a function that ignores empty lists:

f[{}] = {};
f[{a__}] := {1 - Times @@ (1 - {a})}
Map[f, testweightedgraph, {2}]
{
 {{}, {1 - (1 - p) (1 - pq)^2 (1 - q)}, {}}, 
 {{1 - (1 - p) (1 - pq)^2 (1 - q)}, {q}, {}},
 {{}, {}, {}}
}
$\endgroup$
2
  • 1
    $\begingroup$ @Simon note the minor correction I just added (f[{a__}] rather than f[a__]). It might be better suited to handling certain corner cases. $\endgroup$
    – LLlAMnYP
    Oct 21 '15 at 9:39
  • $\begingroup$ Thank you ! Yes when I tried your first set of code the nonempty lists were simply wrapped in {}, without the subtraction, multiplication and subtraction being performed. Your new code works perfectly for me. This serves two purposes: Solving my problem and also giving me a good example from which to start understanding pattern matching. Very many thanks ! $\endgroup$
    – Simon
    Oct 21 '15 at 9:41
3
$\begingroup$

This is the sort of thing If[] was meant for:

Map[If[# =!= {}, 1 - Apply[Times, 1 - #], #] &, testweightedgraph, {2}]
$\endgroup$
1
  • $\begingroup$ That is also a very nice answer, thank you J. M. I like the piecewise definition of LLIAMnYP's answer, and I like that J. M.'s doesn't define a named function. P.S. J. M. since I want my matrix elements to be lists, I have added some curly braces to your code: Map[If[# =!= {}, {1 - Apply[Times, 1 - #]}, #] &, testweightedgraph, {2}] $\endgroup$
    – Simon
    Oct 21 '15 at 12:18
2
$\begingroup$

With respect to your list of disadvantages about using Position to resolve the problem

Perhaps Position needs to be told exactly what to look for, and cannot be asked to look for elements satisfying a pattern (such as, in this case "not being the empty list")

I think that you can use a general pattern to extract non empty lists

testweightedgraph = {{{}, {p, q, pq, pq}, {}}, {{p, q, pq, 
    pq}, {q}, {}}, {{}, {}, {}}}

Position[testweightedgraph, {x__}, {2}]
(* {{1, 2}, {2, 1}, {2, 2}} *)

and then as you suggested use MapAt

MapAt[{1 - Apply[Times, 1 - #]} &, testweightedgraph, 
 Position[testweightedgraph, {a__}, {2}]]

Mathematica graphics

$\endgroup$
1
  • $\begingroup$ You are absolutely right, Jack - thank you very much for answering ! It's so nice to have many different ways of doing the same thing. I can imagine each of these might be preferable to the others, in the right situation. $\endgroup$
    – Simon
    Oct 22 '15 at 17:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.