> For the complete documentation index, see [llms.txt](https://jona-projects.gitbook.io/kiwicalc/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://jona-projects.gitbook.io/kiwicalc/symbolic-computation/poly.md).

# Poly

Polynomials are mainly supported via the `Poly` class. This class represents a polynomial, namely, a collection of monomials. Since a monomial is represented by the Mono class, each Poly object contains a collection of Mono objects. In order to use the class, you must import it first:&#x20;

```python
from kiwicalc import Poly
```

### Creating a new polynomial

There are several ways to create a Poly object:

1. **Entering a collection of `Mono` or `Var` objects**

   A given collection of Mono objects will be evaluated and inserted into a new Poly object. In addition, ints, floats and valid strings will also be accepted as items in the collection. The easiest way to do that is to use the Var class. For Example:                &#x20;

   ```python
   x, y = Var('x'), Var('y')
   polynomial = Poly((3*x**2,2.6,"4y^2",7*x**4 * y**5))
   ```

2. You can also create the `Mono` objects on the spot. For instance:

   ```python
   polynomial = Poly((Mono(2,{'x':3,'y':4}),Mono("4xy^3")))
   ```

3. **Create a `Poly` object with `Var` object arithmetics**

   You can actually construct `Poly` objects in an even simpler manner using the `Var` class. However, this approach might be slower, as more objects are created during the `Var` objects arithmetic. For example:

   ```python
   x = Var('x')
   polynomial = x**2 + 3*x + 6

                               
   ```

   The expression on the right actually computes to a `Poly` object, so the polynomial is generated for us automatically.

4. **Create a `Poly` object from a string**

   Just enter a string in the right format, and a corresponding Poly object will be generated soon enough! This approach is rather simple, however, it requires string manipulation from the class, and thus it might be a bit more expensive on runtime than the first approach. Despite the obvious simplicity of this approach, as for this version, the strings must follow specific rules and limitations:

   * The variable name represented by a single English letter, i.e: a-z , A-Z.
   * Use of parenthesis isn't supported yet.
   * Division operator isn't supported yet.

   For instance:

   <pre class="language-python"><code class="lang-python"><strong>expression = Poly("8 + 3x^2 + 6x + 9 + 2x^3 + 2x^2")
   </strong>print(expression)

   # output:
   # '2x^3+5x^2+6x+17'
                           
   </code></pre>

5. **Create a new `Poly` object by copying an existing one**

   You can also create a new Poly object from an existing one. Alternatively, you can copy Poly objects with the `__copy__()` method. For example:

   ```python
   x = Var('x')
   existing_polynomial = 3*x**2- 6*x + 7
   new_polynomial = Poly(existing_polynomial)

                               
   ```

### Arithmetic Operators

You can perform arithmetic operations between polynomials with the corresponding operators:

* Addition is done by the `+` operator
* Subtraction is done by the `-` operator
* Multiplication is done by the `*` operator
* Division is done by the `/` operator.
* Power is done by the `**` operator. (polynomial `**` number)

**Polynomial Addition**

You can easily add up polynomials with the `+` operator.

**Example 5 - Polynomial Addition**

```python
x = Var('x')
y = Var('y')
first = 2*x + 3
second = 3*y - 4*x + 5
print(first+second)

# output:
# -2x+8+3y
```

**Polynomial Subtraction**

You can also subtract polynomials using the `-` operator.

**Example 6 - Polynomial Subtraction**

```python
x = Var('x')
first = 3*x + 5
second = 2*x - 1

print(first-second)
# output:
# x+6
```

**Polynomial Multiplication**

You can use the `*` operator in order to multiply between:

* A polynomial and another polynomial.
* A polynomial and any `IExpression` object.
* A polynomial and a float or an int.

For example:                   &#x20;

<pre class="language-python"><code class="lang-python"><strong>x = Var('x')
</strong>y = Var('y')
print((x + 5) * (x - 2))
print( (x + y) * (x - y))

# output:
# x^2+3x-10
# x^2-y^2                              
</code></pre>

**Polynomial Division**

You can use the built in `/` operator in order to divide between polynomials. For example:

```python
x = Var('x')
first = x**2 + 6*x + 8
second = x + 4
division_result = first / second
print(division_result)
```

**Additional feature**

You can also divide by a string that represents a polynomial, for the sake of simplicity.

**Raising a polynomial by a power**

You can raise a polynomial by an integer or float power with the `**` operator.

**For example:**

```python
a, b = Var('a'), Var('b')
print((a+b)**2)

# output:
# a^2+2a*b+b^2
```

#### Assigning values

You can assign values to variables\_dict using the `assign()` method from a Poly object. For example, after assigning \`x=5\` for the expression \`2x-4\` It will represent \`6\`:

```python
x = Var('x')
poly = 2*x - 4
poly.assign(x=5)
print(poly)

# output:
# 6
```

Sometimes we want to see what happens when we assign a certain value to a polynomial, but we want to leave the original polynomial unchanged. For that, we can use the `when()` method. For example:

```python
y = Var('y') # Declaring a variable
original = 3*y**2 + 6*y + 7 # Creating the original polynomial
assigned = original.when(y=-2) # Saving the assigned polynomial
print(f"Original is {original}")
print(f"Assigned is {assigned}")

# output:
# Original is 3y^2+6y+7
# Assigned is 7
```

**Evaluating a polynomial to a number**

Sometimes when a polynomial represents a free number, we want to extract its value as an integer. For that, we can use the `try_evaluate()` method. The method will return the int or float value if the polynomial represents a free number, and `None` otherwise.

For example,

```python
x = Var('x') # Declaring a variable named x
poly = 3*x - 2 # Creating a polynomial
poly.assign(x=4) # Assigning a value to it, so it will hold a free number
number = poly.try_evaluate() # Extract the free number from the polynomial
print(f"poly represents {poly} and its type is {type(poly)}")
print(f"number is {number} and its type is {type(number)}")

# output:
# poly represents 10 and its type is <class '__main__.Poly'>
# number is 10 and its type is <class 'int'>

```

#### Plot Polynomials

You can plot univariate polynomials (polynomials with only one variable) in a 2D axis system via the `plot()` method. Here is the signature of the method:

```python
def plot(self, start: float = -10, stop: float = 10,step: float = 0.01, ymin: float = -10, ymax: float = 10, text=None, fig=None, ax=None, show_axis=True,show=True):
                    
```

For example:

```python
x = Var('x')
poly = x**2 + 6*x + 8
poly.plot()
                    
```

#### Scatter polynomials

You can scatter univariate polynomials (polynomials with only one variable) on a 2D axis.

For example:

```python
x = Var('x')
poly = x**2 + 6*x + 8
poly.scatter()
                    
```

#### Derivatives

You can find a derivative of a polynomial via the `derivative()` method. The method will return a corresponding `Poly` or `Mono` object that represents the derivative. For example:

```python
x = Var('x')
poly = 2*x**3 - 6*x + 7
print(poly.derivative())
                    
```

#### Partial Derivatives

You can find the partial derivatives in respect to a variable with the `partial_derivative()` method. The method accepts a string that represent the corresponding variable/s. For instance, the partial derivative of the polynomial function \`f(x,y)=x^2+y^2\` in respect to \`x\` can be denoted as \`f'\_x\` and it is \`2x\`. For example:

```python
x, y = Var('x'), Var('y')
f = x**2 + y**2
f_x = f.partial_derivative('x')
print(f_x)
                    
```

You can also do several partial derivatives. For instance, let $$f(x) = x^2 + 2xy + y^2$$. In order to find $$\frac{\partial}{\partial y} \frac{\partial f}{\partial x}$$we have to first derive for  $$x$$  : $$\frac{\partial f}{\partial x} = 2x + 2y$$ , and then for  $$y$$   and therefore $$\frac{\partial}{\partial y} \frac{\partial f}{\partial x}  = 2$$.  It's important to mention that the order of the differentation that does not matter in well behaved, continuous functions in general, and for polymomials in specific.

```python
x, y = Var('x'), Var('y')
f = x**2 + 2*x*y + y**2
f_xy = f.partial_derivative('xy')
                    
```
