# CSCI-142 Project 1: Functions

Due Friday, March 8, 2019, 11:59 PM

## Project description

This project is concerned with representing mathematical expressions in software so they can be manipulated in various ways and evaluated.

We define the abstraction called `Function` that represents any calculation that can be treated as the definition of a mathematical function of one variable. Your job is first to express `Function` as an abstract Java class (or interface) and then to build concrete implementors of the `Function` abstraction and for each one implement `Function`'s operations:

• `evaluate`: Given a double floating point value of x, compute the value of the function.
• `toString`: Return a human-readable expression of the function as a Java String. `Function`s using an infix operator with two or more operands must include parentheses.
• `derivative`: Return the `Function` that is the (first) derivative of the function with respect to x.
• `integral`: Compute the (double) value of the definite integral of the function with respect to x over a given interval. The interval is expressed by two double arguments. For all but the simplest functions the integral has to be computed numerically using the trapezoid rule, so the number of trapezoids (i.e. the granularity of the calculation) is also given in case it is needed.
• `isConstant`: Answer whether or not this function is constant (including if it is a combination of other constants).

## Design Overview

The set of classes in the `Function` hierarchy form a classic Composite design pattern. Some functions are primitive; they have no smaller parts. The simple constant and the expression x are the most common examples of primitive equations. Most other functions are composites, meaning that they are composed of other "smaller" functions. For example, 2x is a product composite containing the primitives 2, a constant, and x, a simple variable. Observe the following figure. Figure 1

sin(x) is a transcendental function that is actually a composite but containing only one subordinate. sin(2x) is an instance of the sine composite with a multiplication composite inside it, which in turn contains two primitives. Figure 2

2x·sin(x) would at the top level be a product containing three functions: Figure 3

## Examples

Now let's look at what the operations listed above do to some of these functions.

2x:

• Calling `evaluate` with argument 7.5 would yield the double 15.0.
• Calling `toString` would yield `( 2 * x )`.
• Calling `derivative` would yield a `Constant` object representing the value 2.0.
• Calling `integral` from 1.0 to 5.0 would hopefully yield something close to the value of x2 at 5.0 minus the value of x2 at 1.0, or 24.0. However, since there is no universal closed form for integrating products, it has to be calculated by numerical means. The larger the 3rd argument is, the closer to 24.0 the answer should be.
• `isConstant` would yield false.

sin(2x):

• Calling `evaluate` with argument 7.5 would yield the double 0.65028784016.
• Calling `toString` would yield ```sin( ( 2 * x ) ) ```.
• Calling `derivative` would yield a `Product` object representing the function 2·cos(2x)
• Calling `integral` from 1.0 to 5.0 would yield something close to the value of -cos(2x)/2 at 5.0 minus the value of -cos(2x)/2 at 1.0, or 0.21146234626.
• Calling `isConstant` would yield false.

The third example 2x·sin(x) would of course be even more complex. However, it is important to remember that each function only deals with its immediate descendants. The full answer is computed by using recursion.

## Hints / tips

#### Derivatives Refresher

The derivative is always calculable in closed form. Here are some things to remember.

• The derivative of a sum is the sum of the derivatives.
• The derivative of a product yz is y times the derivative of z plus z times the derivative of y. (You must generalize this to a product of more than two factors. Think recursively!)
• The derivative of f(g(x)) with respect to x is the derivative of f(g(x)) with respect to g(x) times the derivative of g(x) with respect to x. (This is the chain rule.)
• The integral of a sum is the sum of the integrals.
• Functions containing products and trigonometric functions cannot be integrated to a closed form. (Remember, you cannot assume the argument of sine or cosine is simply x.) It is for these cases that you must approximate the integral with the trapezoid rule. This occurs in multiple functions, but you should figure out how to implement it only once!

#### Constants

`isConstant()` can be defined recursively, if you look at functions as forming trees, as they did in the figures above. A `Function` object is constant if:

• It is an instance of `Constant` (base case), or
• all of its "child" `Function` objects are constant.

In the discussion below the term "constant" refers to any object that answers true to `isConstant`().

• If several constants are provided to the `Sum` or `Product` constructor, they should be combined into a single `Constant` instance. Example: ```2.0 * sin( x ) * 3.0 ``` should be `sin( x ) * 6.0`.
• An empty (size 0) `Sum` or `Product` should represent 0.0 or 1.0, respectively.
• If in the end the `Sum` or `Product` contains a `Constant` equal to 0 or 1, respectively, it must be eliminated altogether from the sequence of terms stored unless it is the only one left.

#### No Other Simplifications

Clearly one can do many other things to reduce the size of the `Sum` and `Product` objects' string representations. Do not do any other simplifications besides the ones explained above for `Constant`s.

#### Unusual Method Declaration for Varying the Number of Parameters

You will notice that some class's constructors, such as `Sum`'s, accept a variable number of arguments. Here is how you allow it. If you define a method in this way

`public void foo( Thing... all ) { … }`

It means that you have a choice on how to call the method. First, you can pass a primitive array of the expected type:

```Thing[] things = … ;
foo( things );```

And in fact, inside the method, the parameter (`all`) will be a reference to that array.

However the caller can choose to list elements explicitly.

```Thing t1 = …;
Thing t2 = …;
Thing t3 = …;
foo( t1, t2, t3 );```

They will still be packaged up into the `all` array inside the method. So for the Sum class you might write

`public Sum( Function... terms ) { … }`

#### Design Choices

You are free to implement your Function class as either an interface or an abstract class. The advantage of using an abstract class is that you can remove some of the redundancy you'll encounter with an interface.

## Source Code

We are providing three test programs here. The expected output is in comments at the bottom of the program. You should make sure your output matches exactly.

Keep in mind these are not complete. Your own tests in FunctionTest should be much more rigorous.

## Part One

Although this project only has one due date, you can use the requirements in Part One to make sure you are not too far behind. Set a goal to get this part finished two weeks before the due date. Note that some points are awarded based only on the Part One instructions.

Write Java code to declare Function as described in section 2, but without the integral method, then write the following implementing classes:

• `Constant` -- The constructor takes the value as its argument.
• `Variable` -- This constructor takes no argument, since the only variable allowed is x. There should only be one instance of `Variable`. Therefore, the constructor is private and there is a public final static instance of `Variable` within the Variable class. The instance's name should be `X`.
• `Sum` -- The constructor takes an argument list of functions to be added together.

Example: the function 2x + 7 could be constructed as follows: ```new Sum( Variable.X, Variable.X, new Constant( 7 ) ) ```

NOTE: The above function will print out as `(x + x + 7)` - do not attempt to make special code to have it print as `2x + 7` as you could have many different complicated Sums and should not make special cases for every case!

Important: The `Sum` constructor is declared as follows: `public Sum( Function... terms ) { ... }` This way, it can accept either an array of `Function`s or a sequence of separate `Function` arguments (as in the 2x+7 example above). In either case, the number of Function terms is not fixed. Inside the method, `terms` is treated as if it were declared as `Function[]`. This rule also applies to the `Product` constructor.

Finally, you must also write a test program FunctionTest1 that thoroughly exercises the above code.

## Part Two

Add the `integral` method to the `Function` interface/class. Override the method only in the classes where the integral is bound to have a closed form, i.e., `Constant`, `Variable`, and `Sum`. Next, write the following additional descendants of `Function`:

• `Product` -- constructor takes an argument list of functions to be multiplied together. `Product` should treat `Constant`s like `Sum` does, but there are two differences. First, if all the `Constant` factors multiply to 1, then it can be eliminated unless it's the only one left. Second, if they all multiply to 0, then the `Product` should be made up of a single `Constant` factor 0.
• `Sine` -- constructor takes a function to which the sine function is to be applied.
• `Cosine` -- constructor takes a function to which the cosine function is to be applied.
Example: the function x2 + cos( 2x ) + 7 would be constructed as follows:
```new Sum(
new Product( Variable.X, Variable.X ),
new Cosine( new Product( new Constant(2), Variable.X ) ),
new Constant( 7 )
)
```

Again, note that this should be printed as `( ( x * x ) + cos( ( 2 * x ) ) + 7.0 )` .

Finally, you must extend your test program so that it thoroughly exercises all of your code. Call the new one FunctionTest2.

## Submission

When you are done your IntelliJ IDEA™ project source directory should show these contents. To submit, do the following.

1. Go to your project directory.
2. Zip up your src/ folder and name the file project1.zip.
(Make sure the zip file does not contain the .idea directory or any .iml file.)
3. Upload your zip file to the MyCourses dropbox for Project 1.
Don't forget to verify that your submission went through and that the zip file's contents are correct.

## Grading

Your grade is based on the following aspects of your work.

• Part One: 30%
• Conforming design - 10%
• Functional correctness - 15%
• Part 1 Test program completeness - 5%
• Part Two: 70%
• Conforming design - 5%
• Functional correctness - 40%
• Sufficient commits to repository - 5%
• Conforming source code style - 10%
• Part 2 Test program completeness - 10%*

* The Part 2 Test must test all functionality, not just that added since Part 1.