# How to define a function with different types of arguments by setting conditions on function's domain?

I need help in order to properly define a function of $4$ variables.

Given that:

    beta[k_Integer /; k == 1] := {0.088, -0.029, -0.010, -0.029, 0.019, 0.012};
beta[k_Integer /; k >= 2] := {0.227, -0.098, -0.024, -0.060, 0.027, 0.000};
size = {"low", "medium", "high"};
type = {"a", "b", "c"};


The "incomplete" definition for my function f looks like this:

    f[k_Integer, x_, y_, z_] :=
Total[beta[k]*{1, Log[x], DiscreteIndicator[y, "medium", size],
DiscreteIndicator[y, "low", size],
DiscreteIndicator[z, "b", type], DiscreteIndicator[z, "a", type]}]


I'm using Table to iterate values of function's arguments:

    Table[f[k, x, y, z], {k, 1, 2}, {z, Reverse[type]}, {y, size}] // MatrixForm


The output result is:

   (* {{{0.059 - 0.029 Log[x], 0.078 - 0.029 Log[x],
0.088 - 0.029 Log[x]}, {0.078 - 0.029 Log[x], 0.097 - 0.029 Log[x],
0.107 - 0.029 Log[x]}, {0.071 - 0.029 Log[x], 0.09 - 0.029 Log[x],
0.1 - 0.029 Log[x]}}, {{0.167 - 0.098 Log[x],
0.203 - 0.098 Log[x], 0.227 - 0.098 Log[x]}, {0.194 - 0.098 Log[x],
0.23 - 0.098 Log[x], 0.254 - 0.098 Log[x]}, {0.167 - 0.098 Log[x],
0.203 - 0.098 Log[x], 0.227 - 0.098 Log[x]}}} *)


The problem is that the function f should not be defined for a specific combination of argument values:

    k=1  &&  y="low"    && z="b"
k=1  &&  y="high"   && z="b"
k=1  &&  y="medium" && z="a"
k=1  &&  y="high"   && z="a"
k>=2 &&  y="high"   && z="b"
k>=2 &&  y="medium" && z="a"
k>=2 &&  y="high"   && z="a"


The first condition is actualy saying that there are no "low" objects (or whatever) in the category "b", for k==1.

How can I define the function f exactly, so that f would not be defined for the conditions listed above?

I think that the solution is to restrict the domain of function f, by setting conditions on its arguments, but I have no idea how to do this.

This is what I ended up with (worst code ever):

    {{{f[1, x, "low", "c"], f[1, x, "medium", "c"],
f[1, x, "high", "c"]}, {"not defined", f[1, x, "medium", "b"],
"not defined"}, {f[1, x, "low", "a"], "not defined",
"not defined"}}, {{f[2, x, "low", "c"], f[2, x, "medium", "c"],
f[2, x, "high", "c"]}, {f[2, x, "low", "b"],
f[2, x, "medium", "b"], "not defined"}, {f[2, x, "low", "a"],
"not defined", "not defined"}}}


Output:

    {{{0.059 - 0.029 Log[x], 0.078 - 0.029 Log[x],
0.088 - 0.029 Log[x]}, {"not defined", 0.097 - 0.029 Log[x],
"not defined"}, {0.071 - 0.029 Log[x], "not defined",
"not defined"}}, {{0.167 - 0.098 Log[x], 0.203 - 0.098 Log[x],
0.227 - 0.098 Log[x]}, {0.194 - 0.098 Log[x], 0.23 - 0.098 Log[x],
"not defined"}, {0.167 - 0.098 Log[x], "not defined",
"not defined"}}}


I appreciate any suggestion.

-

Here is a solution :

 acceptableQ[k_, y_, z_] := Not[Or[
k == 1 && y == "low"    && z == "b",
k == 1 && y == "high"   && z == "b",
k == 1 && y == "medium" && z == "a",
k == 1 && y == "high"   && z == "a",
k >= 2 && y == "high"   && z == "b",
k >= 2 && y == "medium" && z == "a",
k >= 2 && y == "high"   && z == "a"]]

f1[k_Integer, x_, y_, z_] := "Undefined" /; Not[acceptableQ[k, y, z]]

f1[k_Integer, x_, y_, z_] :=
Total[beta[k]*{1, Log[x],
DiscreteIndicator[y, "medium", size],
DiscreteIndicator[y, "low"   , size],
DiscreteIndicator[z, "b"     , type],
DiscreteIndicator[z, "a"     , type]}
] /; acceptableQ[k, y, z]


Verification :

  Table[f1[k, x, y, z], {k, 1, 2}, {z, Reverse[type]}, {y, size}] //
Map[Column, #, {2}] & // Grid


gives :

Here are the corresponding inputs (just to help the reading) :

Note : You can also put the condition /; ... before the := :

f2[k_Integer, x_, y_, z_] /; Not[acceptableQ[k, y, z]] := "Undefined"
f2[k_Integer, x_, y_, z_] /; acceptableQ[k, y, z] := ...

-
I feel stupid, cause your answer is simple. Is there a way to use negation of Exists so that the function returns some kind of a built-in output, instead of string character "Undefined"? –  bst Oct 31 '13 at 19:07
I don't understand what you mean by "negation of Exists". In Mathematica Exists, like ForAll are special expressions (mathematical quantifier that goes with predicates) that are not usable here. –  andre Oct 31 '13 at 19:17