Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
647 changes: 0 additions & 647 deletions intervals/methods.py

This file was deleted.

51 changes: 45 additions & 6 deletions intervals/plotting.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,54 @@
from __future__ import annotations
import numpy as np
import matplotlib.pyplot as plt

"""
--------------------------
Created Feb 2022
Marco De Angelis
github.com/marcodeangelis
Editted by Leslie Feb 2024
MIT License
--------------------------
"""
from __future__ import annotations

import matplotlib.pyplot as pyplot
def plot_intervals(x, y_i, **kwargs):
""" plot intervals vertically

args:
x: array-like precise values
x-axis coordinates
y_i: array-like Interval objects
array of intervals
"""

fig, ax = plt.subplots()

def basic_plot(x, y_i, **kwargs):
ax.plot([x, x], [y_i.hi, y_i.lo], 'blue', **kwargs)
if np.any(y_i.lo == y_i.hi):
sc_x = x[y_i.lo == y_i.hi]
sc_y = y_i[y_i.lo == y_i.hi].lo
ax.scatter(sc_x, sc_y, c='blue', **kwargs)

if len(x.shape) > 1:
for xx, interval in zip(x, y_i):
basic_plot([xx, xx], [interval.hi, interval.lo])
else:
basic_plot(x, y_i)
return ax



from intervals.number import Interval
def plot_lower_bound(x, y_i, **kwargs):
""" plot lower bound of intervals

args:
x: array-like
x-axis coordinates
y_i: array-like
array of intervals
"""

fig, ax = plt.subplots()
ax.scatter(x, y_i.lo, label='lower bound', **kwargs)
ax.legend()


20 changes: 0 additions & 20 deletions pyproject.toml

This file was deleted.

3 changes: 3 additions & 0 deletions questions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Here I note some questions that are to be solved by Marco

- [ ] how to squeeze e.g. shape (32, 1) into (32,)
11 changes: 11 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from setuptools import find_packages, setup

setup(
name='intervals',
packages=find_packages(where="src"),
package_dir={"": "src"},
version='0.2.0',
description='A modified version of the intervals library by Leslie',
author='Marco, Leslie',
license='MIT',
)
File renamed without changes.
15 changes: 15 additions & 0 deletions src/intervals/activation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from intervals.number import Interval
from intervals.methods import exp
import numpy as np


''' a series of popular activation functions for interval arithmetic '''

def sigmoid(x:Interval): return 1/(1 + exp(-x))
def tanh(x:Interval): return (exp(2*x)-1)/(exp(2*x)+1)


def relu(x):
xs=x.shape
x0=np.zeros(xs)
return np.maximum(x0,x)
File renamed without changes.
File renamed without changes.
131 changes: 131 additions & 0 deletions src/intervals/mat_features.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
import numpy as np
from intervals.methods import (lo,hi,mid,rad,width,intervalise)

''' this file contains the functions to create interval matrices from numpy arrays

TODO: func `intervalise()` change the default setting to consume by the last axis to first axis or 2by2 matrix will be wrong;
'''

def consume_interval(low, high):
""" initialise an interval matrix from `low, high` arrays;

note:
initialise from the shape (2, m, n) as preferred;

example:
low = np.arange(9).reshape(3,3)
high = np.arange(10, 19).reshape(3,3)
"""

a_matrix = np.stack([low, high], axis=0)
return intervalise(a_matrix)


def create_interval(matrix, half_width=0.1):
""" mannually create an interval matrix from a numpy array """

low = matrix - half_width
high = matrix + half_width
return consume_interval(low, high)


def dot(x,y): return sum(x*y)


def rowcol(W,x):
""" marco's original implementation of the rowcol function """

s = W.shape
y=[]
for i in range(s[0]):
y.append(dot(W[i],x))
return intervalise(y)


def rowcol2(x,W):
""" Leslie changed the argument order for notational convecience original implementation of the rowcol function

args:
- W: have to be a vector;
"""

s = x.shape
if len(s) > 1:
y=[]
for i in range(s[0]):
y.append(dot(x[i],W))

return intervalise(y)
else:
print('x shall be a 2 dimensional array')



# def rowcol_wrong(x, W):
# """ Leslie's implementation of the rowcol function

# args:
# - x: a vector, e.g. hidden layer output, as a row vector
# - W: weight matrix of the next layer

# note:
# - this is not full-fleged interval matrix computation
# - it currently only fits for `x` as a vector
# - it can be used for hidden-layer tensor propagation
# """

# s = W.shape
# y=[]
# for j in range(s[1]):
# y.append(dot(x, W[:, j]))
# result = intervalise(y)
# return result[np.newaxis, :]


def consume_list(list_intervals):
""" consume a list of interval matrices into a single interval matrix

! of no use now
note:

- being used for interval matrix multiplication
"""

low, upper = [], []
for interval in list_intervals:
low.append(interval.lo)
upper.append(interval.hi)

low_a = np.vstack(low)
upper_a = np.vstack(upper)

return intervalise(low_a, upper_a)


def intvl_matmul(x, W):
""" draft matrix multiplication function for interval matrices

note:
- can be used for general matrix multiplication

return:
- an interval matrix
"""

row_cp_list = []
sW = W.shape
if (len(sW)) > 1:
if (sW[1]>1):
for j in range(sW[1]):
row_cp_list.append(rowcol2(x, W[:, j]))
return intervalise(row_cp_list)
elif sW[1]==1:
return rowcol2(x, W[:, 0])
else:
return rowcol2(x, W)
else:
return rowcol2(x, W)




Loading