def inverse(expr): if type(expr) == atoms.ceil: return lambda t: atoms.floor(t) elif type(expr) == atoms.floor: return lambda t: atoms.ceil(t) elif type(expr) == NegExpression: return lambda t: -t elif type(expr) == atoms.exp: return lambda t: atoms.log(t) if t.is_nonneg() else -np.inf elif type(expr) == atoms.log: return lambda t: atoms.exp(t) elif type(expr) == atoms.log1p: return lambda t: atoms.exp(t) - 1 elif type(expr) == atoms.logistic: return lambda t: atoms.log(atoms.exp(t) - 1) if t.is_nonneg() else -np.inf elif type(expr) == atoms.power: def power_inv(t): if expr.p == 1: return t return atoms.power(t, 1/expr.p) if t.is_nonneg() else np.inf return power_inv elif type(expr) == atoms.multiply: if expr.args[0].is_constant(): const = expr.args[0] else: const = expr.args[1] return lambda t: t / const elif type(expr) == DivExpression: if expr.args[0].is_constant(): const = expr.args[0] else: const = expr.args[1] return lambda t: t * const else: raise ValueError
def inverse(expr): if type(expr) == atoms.ceil: return lambda t: atoms.floor(t) elif type(expr) == atoms.floor: return lambda t: atoms.ceil(t) elif type(expr) == NegExpression: return lambda t: -t elif type(expr) == atoms.exp: return lambda t: atoms.log(t) if t.is_nonneg() else -np.inf elif type(expr) == atoms.log: return lambda t: atoms.exp(t) elif type(expr) == atoms.log1p: return lambda t: atoms.exp(t) - 1 elif type(expr) == atoms.logistic: return lambda t: atoms.log(atoms.exp(t) - 1) if t.is_nonneg( ) else -np.inf elif type(expr) == atoms.power: def power_inv(t): if expr.p.value == 1: return t return atoms.power(t, 1 / expr.p.value) if t.is_nonneg() else np.inf return power_inv elif type(expr) == atoms.multiply: if expr.args[0].is_constant(): const = expr.args[0] else: const = expr.args[1] return lambda t: t / const elif type(expr) == DivExpression: # either const / x <= t or x / const <= t if expr.args[0].is_constant(): # numerator is constant const = expr.args[0] return lambda t: const / t else: # denominator is constant const = expr.args[1] return lambda t: const * t elif type(expr) == AddExpression: if expr.args[0].is_constant(): const = expr.args[0] else: const = expr.args[1] return lambda t: t - const elif type(expr) == atoms.abs: arg = expr.args[0] if arg.is_nonneg(): return lambda t: t elif arg.is_nonpos(): return lambda t: -t else: raise ValueError("Sign of argument must be known.") elif type(expr) in (Sum, atoms.cumsum): return lambda t: t else: raise ValueError