Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dev fix examples #177

Merged
merged 27 commits into from
Apr 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
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
213 changes: 125 additions & 88 deletions grama/comp_building.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ def _comp_function_data(model, fun, var, out, name, runtime):
def comp_function(model, fun=None, var=None, out=None, name=None, runtime=0):
r"""Add a function to a model

Composition. Add a function to an existing model.
Composition. Add a (non-vectorized) function to an existing model. See ``gr.comp_vec_function()`` to add a function that is vectorized over DataFrames.

Args:
model (gr.model): Model to compose
Expand All @@ -102,16 +102,19 @@ def comp_function(model, fun=None, var=None, out=None, name=None, runtime=0):
@pre (len(var) == d) | (var == d)
@pre (len(out) == r) | (var == r)

Examples:

>>> import grama as gr
>>> md = gr.Model("test") >> \
>>> gr.function(
>>> fun=lambda x: x,
>>> var=1,
>>> out=["y"],
>>> name="identity"
>>> )
Examples::

import grama as gr
## Simple example
md = (
gr.Model("test")
>> gr.cp_function(
fun=lambda x: x,
var=["x"],
out=["y"],
name="identity"
)
)

"""
model_new = model.copy()
Expand All @@ -138,7 +141,10 @@ def comp_vec_function(model, fun=None, var=None, out=None, name=None, runtime=0)

Composition. Add a function to an existing model. Function must be
vectorized over DataFrames, and must add new columns matching its `out`
set.
set. See ``gr.cp_function()`` to add a non-vectorized function.

Notes:
The helper function ``gr.df_make()`` is useful for constructing a vectorized lambda function (see Examples below).

Args:
model (gr.model): Model to compose
Expand All @@ -153,18 +159,19 @@ def comp_vec_function(model, fun=None, var=None, out=None, name=None, runtime=0)
@pre (len(var) == d) | (var == d)
@pre (len(out) == r) | (var == r)

Examples:

>>> import grama as gr
>>> md = (
>>> gr.Model("Test")
>>> >> gr.cp_vec_function(
>>> fun=lambda df: gr.df_make(y=1 + 0.5 * df.x),
>>> var=["x"],
>>> out=["y"],
>>> name="Simple linear function",
>>> )
>>> )
Examples::

import grama as gr
## Simple example
md = (
gr.Model("Test")
>> gr.cp_vec_function(
fun=lambda df: gr.df_make(y=1 + 0.5 * df.x),
var=["x"],
out=["y"],
name="Simple linear function",
)
)

"""
model_new = model.copy()
Expand Down Expand Up @@ -199,7 +206,20 @@ def comp_md_det(model, md=None):
Returns:
gr.model: New model with added function

Examples:
Examples::

import grama as gr
from grama.models import make_cantilever_beam
## Use functions from beam model, but introduce new marginals
md_plate = (
gr.Model("New beam model")
>> gr.cp_md_det(md=make_cantilever_beam())
>> gr.cp_marginals(
H=gr.marg_mom("norm", mean=1000, cov=0.1),
V=gr.marg_mom("norm", mean=500, cov=0.1),
)
>> gr.cp_copula_independence()
)

"""
if md is None:
Expand Down Expand Up @@ -235,7 +255,7 @@ def comp_md_sample(model, md=None, param=None, rand2out=False):
Returns:
gr.model: New model with added function

Examples:
Examples::

"""
## Check invariants
Expand Down Expand Up @@ -307,32 +327,34 @@ def _ev(md, df):
def comp_bounds(model, **kwargs):
r"""Add variable bounds to a model

Composition. Add variable bounds to an existing model. Bounds are specified
by iterable; the model variable name is specified by the keyword argument
name.
Composition. Add variable bounds to an existing model. Bounds are specified by iterable; the model variable name is specified by the keyword argument name.

Args:
model (gr.model): Model to modify
var (iterable): Bound information

Kwargs:
var (iterable): Bound information; keyword argument name is targeted variable, value should be a length 2 iterable of the form (lower_bound, upper_bound)

Returns:
gr.model: Model with new marginals

@pre len(var) >= 2

Examples:
Examples::

>>> import grama as gr
>>> md = gr.Model() >> \
>>> cp_function(
>>> lambda x: x[0] + x[1],
>>> var=["x0", "x1"],
>>> out=1
>>> ) >> \
>>> cp_bounds(
>>> x0=(-1, 1),
>>> x1=(0, np.inf)
>>> )
import grama as gr
md = (
gr.Model("Simple Model")
>> gr.cp_function(
lambda x: x[0] + x[1],
var=["x0", "x1"],
out=1
)
>> gr.cp_bounds(
x0=(-1, 1), # Finite bounds
x1=(0, np.inf) # Semi-infinite bounds
)
)

"""
new_model = model.copy()
Expand All @@ -358,26 +380,37 @@ def comp_marginals(model, **kwargs):
either by dictionary entries or by gr.Marginal() object. The model variable
name is specified by the keyword argument name.

Notes:
Several helper functions are available to fit marginal distributions

- ``gr.marg_fit()`` fits a distribution using a dataset (via maximum likelihood estimation)
- ``gr.marg_mom()`` fits a distribution using moments (via the method of moments)
- ``gr.marg_gkde()`` fits a gaussian kernel density using a dataset

Args:
model (gr.model): Model to modify
var (dict OR gr.Marginal): Marginal information

Returns:
gr.model: Model with new marginals

Examples:

>>> import grama as gr
>>> print(gr.valid_dist.keys()) # Supported distributions
>>> md = gr.Model() >> \
>>> cp_function(
>>> lambda x: x[0] + x[1],
>>> var=["x0", "x1"],
>>> out=1
>>> ) >> \
>>> cp_marginals(
>>> x0={"dist": "norm", "loc": 0, "scale": 1}
>>> )
Examples::

import grama as gr
## Print all of the grama-supported distributions
print(gr.valid_dist.keys())
## Construct a simple example model
md = (
gr.Model()
>> gr.cp_function(
lambda x: x[0] + x[1],
var=["x0", "x1"],
out=["y"],
)
>> gr.cp_marginals(
x0=gr.marg_mom("norm", mean=0, sd=1),
)
)

"""
new_model = model.copy()
Expand Down Expand Up @@ -423,21 +456,25 @@ def comp_copula_independence(model):

Composition. Add an independence copula to an existing model.

NOTE: Independence of random variables is a *very* strong assumption!
Recommend using comp_copula_gaussian instead.
NOTE: Independence of random variables is a *very* strong assumption! Recommend using comp_copula_gaussian instead.

Args:
model (gr.model): Model to modify

Returns:
gr.model: Model with independence copula

>>> import grama as gr
>>> md = gr.Model() >> \
>>> cp_marginals(
>>> x0={"dist": "norm", "loc": 0, "scale": 1}
>>> ) >> \
>>> cp_copula_independence()
Examples::

import grama as gr
md = (
gr.Model()
>> gr.cp_marginals(
x0=gr.marg_mom("norm", mean=0, sd=1),
x1=gr.marg_mom("beta", mean=0, sd=1, skew=0, kurt=2),
)
>> gr.cp_copula_independence()
)

"""
new_model = model.copy()
Expand Down Expand Up @@ -467,31 +504,31 @@ def comp_copula_gaussian(model, df_corr=None, df_data=None):
Returns:
gr.model: Model with Gaussian copula

Examples:

>>> import grama as gr
>>> ## Manual assignment
>>> md = gr.Model() >> \
>>> cp_marginals(
>>> x0={"dist": "norm", "loc": 0, "scale": 1}
>>> x1={"dist": "uniform", "loc": -1, "scale": 2}
>>> ) >> \
>>> cp_copula_gaussian(
>>> df_corr=pd.DataFrame(dict(
>>> var1=["x0"],
>>> var2=["x1"],
>>> corr=[0.5]
>>> ))
>>> )
>>> ## Automated fitting
>>> from grama.data import df_stang
>>> md = gr.Model() >> \
>>> gr.cp_marginals(
>>> E=gr.marg_named(df_stang.E, "norm"),
>>> mu=gr.marg_named(df_stang.mu, "beta"),
>>> thick=gr.marg_named(df_stang.thick, "norm")
>>> ) >> \
>>> gr.cp_copula_gaussian(df_data=df_stang)
Examples::

import grama as gr
## Manual assignment
md_manual = (gr.Model()
>> gr.cp_marginals(
x0=gr.marg_mom("norm", mean=0, sd=1),
x1=gr.marg_mom("uniform", mean=0, sd=1),
)
>> gr.cp_copula_gaussian(
# Specify correlation structure explicitly
df_corr=gr.df_make(var1="x0", var2="x1", corr=0.5)
)
)
## Automated fitting
from grama.data import df_stang
md_auto = (
gr.Model()
>> gr.cp_marginals(
E=gr.marg_fit("norm", df_stang.E),
mu=gr.marg_fit("beta", df_stang.mu),
thick=gr.marg_fit("norm", df_stang.thick)
)
>> gr.cp_copula_gaussian(df_data=df_stang)
)

"""
if not (df_corr is None):
Expand Down
49 changes: 23 additions & 26 deletions grama/dataframe.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,32 +25,30 @@ def safelen(x):
def df_make(**kwargs):
r"""Construct a DataFrame

Helper function to construct a DataFrame.
Helper function to construct a DataFrame. A common use-case is to use df_make() to pass values to the df (and related) keyword arguments succinctly.

Kwargs:
varname (iterable): Column for constructed dataframe; column name inferred from variable name.

Keyword Args:
varname (iterable): Column for constructed dataframe; column
name inferred from variable name.
Returns:
DataFrame: Constructed DataFrame

Preconditions:
All provided iterables must have identical length or be of
length one.

All provided iterables must have identical length or be of length one.
All provided variable names (keyword arguments) must be distinct.

Examples:
A common use-case is to use df_make() to pass values to
the df_det keyword argument succinctly;
Examples::

>>> import grama as gr
>>> from models import make_test
>>> md = make_test()
>>> md >> \
>>> gr.ev_monte_carlo(
>>> n=1e3,
>>> df_det=gr.df_make(x2=[1, 2])
>>> )
import grama as gr
from models import make_test
md = make_test()
(
md
>> gr.ev_sample(
n=1e3,
df_det=gr.df_make(x2=[1, 2])
)
)

"""
## Catch passed Intention operator
Expand Down Expand Up @@ -89,8 +87,7 @@ def df_make(**kwargs):
def df_equal(df1, df2, close=False, precision=3):
"""Check DataFrame equality

Check that two dataframes have the same columns and values. Allow column
order to differ.
Check that two dataframes have the same columns and values. Allows column order to differ.

Args:
df1 (DataFrame): Comparison input 1
Expand Down Expand Up @@ -123,19 +120,19 @@ def df_equal(df1, df2, close=False, precision=3):
def df_grid(**kwargs):
r"""Construct a DataFrame as outer-product

Helper function to construct a DataFrame as an outer-product of the given
columns.
Helper function to construct a DataFrame as an outer-product of the given columns.

Kwargs:
varname (iterable): Column for constructed dataframe; column name inferred from variable name.

Keyword Args:
varname (iterable): Column for constructed dataframe; column
name inferred from variable name.
Returns:
DataFrame: Constructed DataFrame

Preconditions:
All provided variable names (keyword arguments) must be distinct.

Examples:
Examples::

import grama as gr
## Make an empty DataFrame
gr.df_grid()
Expand Down
Loading