I'm going to bundle this into a function that you can use multiple times and then get your final result by aggregation.
IndexedBinaryChoice[listA_, listB_, slotCount_Integer] :=
Map[
Apply[Times]@*Flatten@*MapIndexed[Part[{listA, listB}, ##] &],
Tuples[{1, 2}, slotCount]] /;
Length[listA] == Length[listB]
I came up with this by interpreting your question as follows. The pattern seems to take 1, 2, and 3 "columns" of the matrix {U1, U2}
in turn. It appears that we have 2 terms from the 1-column case, 4 terms from the 2-column case, and 8 terms from the 3 column case. Further inspection of your example suggests that for the n-column case we have a "template" list of indexes of length n, something like {x[[1]], x[[2]], x[[3]]}
in the 3-column case, where we can then replace each x
with either U1
or U2
. There are 2^n ways to choose the replacements, which matches our observation above.
So, at the heart we have Tuples[{1, 2}, slotCount]
. The 1
and 2
represent our choices (choose from U1
or from U2
), and slotCount
is how many columns we want to cover. A tuple like {1, 2, 1}
means "in the first slot, choose from U1
, in the second from U2
, and in the third from U1
. Of course, we want to generalize, so U1
and U2
really mean "the first and second inputs".
Now, I want to map a "chooser" over each tuple. The chooser will index into the input lists. If I bundle my inputs like inputs = {first, second}
, then the tuple {1, 2, 1}
means {inputs[[1]][[1]], inputs[[2]][[2]], inputs[[1]][[3]]}
, which means I need to keep track of where in the tuple I am as I map the chooser over it. That suggests using MapIndexed
: MapIndexed[Part[{first, second}, ##] &][{1, 2, 1}]
. We need to compose this basic chooser function with Times
since that's how you wanted to transform each tuple-choice, and we need to map this whole thing over all the tuples.
Testing it on the 1-slot case:
IndexedBinaryChoice[U1, U2, 1]
(* {u10, u20} *)
2-slot case:
IndexedBinaryChoice[U1, U2, 2]
(* {u10 u11, u10 u21, u11 u20, u20 u21} *)
3-slot case:
IndexedBinaryChoice[U1, U2, 3]
(* {u10 u11 u12, u10 u11 u22, u10 u12 u21, u10 u21 u22, u11 u12 u20, u11 u20 u22, u12 u20 u21, u20 u21 u22} *)
Now, let's just refine our definition of IndexedBinaryChoice
by adding this:
IndexedBinaryChoice[listA_, listB_] :=
Flatten[IndexedBinaryChoice[listA, listB, #] & /@ Range[Length@listA]] /;
Length[listA] == Length[listB]
And now,
IndexedBinaryChoice[U1, U2]
(* This should be equal to UU *)
You might want to add other validity checks.
UU
is definitely a subset ofMapApply[Times, Subsets[all, {1, 3}]]
. $$ $$allProducts =MapApply[Times, Subsets[all, {1, 3}]];
Sort@Intersection[UU, allProducts] === Sort@UU
(*True*)
I am still struggling to see what property links all the elements in UU together though. There has to be some way to select the right products fromallProducts
if they share some kind of property. $\endgroup$