Mathematica Asked by arutar on February 11, 2021
Is it possible to restrict Inner
to a certain level? According to the documentation, the expected behaviour for Inner
is to compute the generalized inner products of tensors at as high a level as possible.
As a simple example, if
f[{a_},{b_}]:={a b}
g[{a_},{b_}]:={a+b}
then for the calls
Inner[f, {{{a}, {b}}, {{c}, {d}}}, {{{x}}, {{y}}}, g]
Inner[f, {{{a}}}, {{{b}}}, g]
the first throws an error (the dimensions do not line up) and the second returns {{{f[a,b]}}}
.
However, I want to restrict Inner
to, say, level 2, so that
level2Inner[f, {{{a}, {b}}, {{c}, {d}}}, {{{x}}, {{y}}}, g] === {{a x + b y}, {c x + d y}}
level2Inner[f, {{{a}}}, {{{b}}}, g] === {{a b}}
I only really care about the level 2 behaviour, but it would be nice to know if more general behaviour is possible. Is there an elegant or standard way to do this?
Edit: One special case I am concerned with is the following. Define the function
f[nestedList1_,nestedList2_]:=Flatten /@ Tuples[{nestedList1, nestedList2}]
which just computes all possible concatenations of lists from the collection nestedList1
with lists from the collection nestedList2
. Then given two matrices M1
and M2
, where the entries of these matrices are lists of lists, I want something like
level2Inner[f, M1, M2, Join]
One can think of the operation f
as computing all possible combinations, except the level2Inner
restricts such combinations only to "valid pairs", i.e. where the indices in M1
and M2
line up appropriately.
For example, if you have a directed graph on n
vertices, and M
is the matrix n
by n
matrix with entry i,j
consisting of a given list of paths (where each path is a list of edges) in G
connecting vertex i
with vertex j
, then the i,j
entry of level2Inner[f,M,M,Join]
is a list of all possible (valid) paths from vertex i
to vertex j
which are concatenations of two paths originally specified in the matrix M
.
I believe you want
MapThread[f, {M1, M2}, 2]
where you could also take (just to mention the useful Outer
function)
f[M1ij_, M2ij_] := Flatten[Outer[Join, M1ij, M2ij, 1], 1]
for your all-concatenations-of-lists-in-lists function!
Answered by thorimur on February 11, 2021
Maybe like this.
Flatten/@Inner[Times, {{{a}, {b}}, {{c}, {d}}}, {{{x}}, {{y}}}, Plus, 2]
level2Inner[f_, list1_?ListQ, list2_?ListQ, g_] :=
Flatten /@ Inner[f, list1, list2, g, 2];
level2Inner[Times, {{{a}, {b}}, {{c}, {d}}}, {{{x}}, {{y}}}, Plus]
level2Inner[Times, {{{a}}}, {{{b}}}, Plus]
{{a x + b y}, {c x + d y}}
{{a b}}
Answered by cvgmt on February 11, 2021
Why don't you strip appropriate List
heads first? Like this
f[a_, b_] := a*b;
g[a__] := Plus[a];
level2Inner = Inner[#1, #2[[All, All, 1]], #3[[All, All, 1]], #4] &;
level2Inner[f, {{{a}, {b}}, {{c}, {d}}}, {{{x}}, {{y}}}, g](*=> {{a x+b y},{c x+d y}}*)
level2Inner[f, {{{a}}}, {{{b}}}, g](*=> {{a b}}*)
Note that for your second example to work g
should be defined for arbitrary number of arguments.
EDIT: If you don't want to change the definitions of f and g, and also as a generalization for generic level, you can use
LevelInner[f_, m1_, m2_, g_, lvl_] :=
Module[{f1, g1, id},
Inner[f1, Map[id, m1, {lvl}], Map[id, m2, {lvl}], g1] /.
id -> Identity /. f1 -> f/. g1 -> g}];
LevelInner[f, {{{a}, {b}}, {{c}, {d}}}, {{{x}}, {{y}}}, g, 2](*=> {{g[f[{a}, {x}], f[{b}, {y}]]}, {g[f[{c}, {x}], f[{d}, {y}]]}}*)
Answered by Roma Lee on February 11, 2021
Get help from others!
Recent Questions
Recent Answers
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP