# Define a bilinear function of strings

I have a linear combinations of strings, e.g.

combStrings = 0.1 "a" + 0.2 "b"


I want to define a function f[] which deals with strings in the following way

f[combStrings, combStrings] = 0.01 g["a","a"] + 0.02 g["a","b"] +0.02 g["b","a"]  + 0.04 g["b","b"]


where g[string1_,string2_] is some function dealing with the strings.

Moreover, I want f[] to be generalizable to any arbitrary linear combinations of strings, for example for

combStrings = 0.1 "a" + 0.2 "b"  + 0.3 "c" + 0.4 "d".


I know that I can define linear function on strings like in the following way

Fun[c1_?NumberQ h1_?StringQ + c2_?NumberQ h2_?StringQ ] := c1 g[h1] + c2 g[h2]


However, I don't know how to define a function satisfying my requirements

• You can do something like Distribute[g[combStrings, combStrings]], along with a definition for g to handle Times[]. – J. M.'s technical difficulties Oct 15 '18 at 18:53

ClearAll[f]
f = Outer[g, ##] /. g[a : Times[_, _String] ..] :>
Times[Times @@ {a}[[All, 1]], g @@ {a}[[All, 2]]] &;


Examples:

f[combStrings, combStrings]


0.01 g["a", "a"] + 0.02 g["a", "b"] + 0.02 g["b", "a"] + 0.04 g["b", "b"]

combStrings2 = 0.1 "a" + 0.2 "b" + 0.3 "c" + 0.4 "d";
f[combStrings2, combStrings2]


0.01 g[a,a]+ 0.02 g[a,b]+0.03 g[a,c]+0.04 g[a,d]+0.02 g[b,a]+0.04 g[b,b]+0.06 g[b,c]+0.08 g[b,d]+0.03 g[c,a]+0.06 g[c,b]+0.09 g[c,c]+0.12 g[c,d]+0.04 g[d,a]+0.08 g[d,b]+0.12 g[d,c]+0.16 g[d,d]

Alternatively,

ClearAll[g, f]
f = Module[{h}, h[a_. b_String, c_. d_String] := a c g[b, d]; Plus @@ Tuples @ h @ ##] &;
f[combStrings, combStrings]


0.01 g["a", "a"] + 0.02 g["a", "b"] + 0.02 g["b", "a"] + 0.04 g["b", "b"]

You can just define rules so that g does this automatically:

g[a_Plus, b_] := Distribute @ Unevaluated @ g[a,b]
g[a_, b_Plus] := Distribute @ Unevaluated @ g[a,b]

g[a_?NumericQ b_, c_]:=a g[b,c]
g[a_, b_?NumericQ c_]:=b g[a,c]


Then:

g[.1 "a" + .2 "b", .1 "a" + .2 "b"]


0.01 g["a", "a"] + 0.02 g["a", "b"] + 0.02 g["b", "a"] + 0.04 g["b", "b"]

and:

g[0.1 "a" + 0.2 "b"  + 0.3 "c" + 0.4 "d", 0.1 "a" + 0.2 "b"  + 0.3 "c" + 0.4 "d"]


0.01 g["a", "a"] + 0.02 g["a", "b"] + 0.03 g["a", "c"] + 0.04 g["a", "d"] + 0.02 g["b", "a"] + 0.04 g["b", "b"] + 0.06 g["b", "c"] + 0.08 g["b", "d"] + 0.03 g["c", "a"] + 0.06 g["c", "b"] + 0.09 g["c", "c"] + 0.12 g["c", "d"] + 0.04 g["d", "a"] + 0.08 g["d", "b"] + 0.12 g["d", "c"] + 0.16 g["d", "d"]