On “well-defined” functions
As a TA for CS251 I frequently see people verify that a function is well-defined when there is no need to. And just as often I see the opposite. So let’s set the record straight here: what exactly is a function, and when do we need to check whether something is genuinely a function?
Given two sets and , a function if is just a subset of the Cartesian product such that for each , there is exactly one such that .
As you expect, we write to denote said unique .
So what happens when we attempt to define a function? Essentially, we are associating each with some subset of elements in . For example, in the function where , we are associating with . For example, we just associate with , with , and so on.
When we attempt to define a function , we would like to have associate each with exactly one value in .
Most of the time we write a function as and in this case there are no problems. If it is some formula of , this is always fine. Perhaps it is a piecewise formula, where you first have to check whether is even or odd. No matter. This will always be fine.
Now let me give you a very quick bad definition of a function. Suppose that we are attempting to map the positive rationals to positive integers. Suppose you say, “we associate the rational (where , are integers) with the integer .” News flash: we associate with and with . Since , we have associated multiple elements with the same rational.
Now what is the actual issue? When we define a function, we are associating a representation of an element in with some value in . What we are really doing when we say “for all , ” is that we are representing each element of as . The “for all ” quantifier guarantees that each element in is accessed exactly once with the representation , and then we associate each with .
But when we look at , what we are doing is associating a value to every fractional representation of a number. And we have already seen that a rational number has many fractional representations, such as . Of course, the way we fix this is stipulate “for all relatively prime , we have ”. Now this genuinely is a function, because we have ensured that we are only associating values to one representation of each rational number.
If we are earnestly trying to define a function , we are not going to associate a representation of an element with more than one value. Because if we do, the subset of we are describing automatically is not a function anymore.
Now, we do not need ascribe every representation of an element in with a value in . Ideally, we would like to ascribe exactly one representation of an element with a value, which is why there is no need to check that functions of the form “for all , ” are well-defined. There is nothing to check! It is obviously a function.
But what of functions where you genuinely have no choice but to associate a value to multiple representations of an element? In this case, I personally say we check for representation invariance of the function, or that such a function is representation invariant.
As an example, take modular arithmetic. We would like to be able to define modulo the same way that is defined modulo , and it turns out that modulo . Likewise, modulo . So it is okay to ascribe a value to multiple representations when defining multiplication, because they are all consistent.
In general, what we need to check here is representation invariance. In other words, if and , we need to make sure that . (All these equivalences are modulo .) And it is easy to check that this is indeed true, so multiplication can be properly defined in modular arithmetic.
To summarize,
- a function is a subset of ,
- we associate values in to representations of values in when we attempt to define a function,
- ideally for each element in , we only ascribe values to one representation of the element,
- but sometimes we genuinely need to ascribe a value to multiple representations of the element, in which case we must check that the ascribed value is the same across all representations we access.
And the last bullet point is the only time you need to check that a function is “well-defined”.