text:
# Julia wrapper for header: /usr/include/nlpi/pub_expr.h
# Automatically generated using Clang.jl wrap_c

function SCIPexprcurvAdd(curv1, curv2)
    ccall((:SCIPexprcurvAdd, libscip), SCIP_EXPRCURV, (SCIP_EXPRCURV, SCIP_EXPRCURV), curv1, curv2)
end

function SCIPexprcurvNegate(curvature)
    ccall((:SCIPexprcurvNegate, libscip), SCIP_EXPRCURV, (SCIP_EXPRCURV,), curvature)
end

function SCIPexprcurvMultiply(factor, curvature)
    ccall((:SCIPexprcurvMultiply, libscip), SCIP_EXPRCURV, (Cdouble, SCIP_EXPRCURV), factor, curvature)
end

function SCIPexprcurvPower(basebounds, basecurv, exponent)
    ccall((:SCIPexprcurvPower, libscip), SCIP_EXPRCURV, (SCIP_INTERVAL, SCIP_EXPRCURV, Cdouble), basebounds, basecurv, exponent)
end

function SCIPexprcurvMonomial(nfactors, exponents, factoridxs, factorcurv, factorbounds)
    ccall((:SCIPexprcurvMonomial, libscip), SCIP_EXPRCURV, (Cint, Ptr{Cdouble}, Ptr{Cint}, Ptr{SCIP_EXPRCURV}, Ptr{SCIP_INTERVAL}), nfactors, exponents, factoridxs, factorcurv, factorbounds)
end

function SCIPexprcurvGetName(curv)
    ccall((:SCIPexprcurvGetName, libscip), Cstring, (SCIP_EXPRCURV,), curv)
end

function SCIPexpropGetName(op)
    ccall((:SCIPexpropGetName, libscip), Cstring, (SCIP_EXPROP,), op)
end

function SCIPexpropGetNChildren(op)
    ccall((:SCIPexpropGetNChildren, libscip), Cint, (SCIP_EXPROP,), op)
end

function SCIPexprGetOperator(expr)
    ccall((:SCIPexprGetOperator, libscip), SCIP_EXPROP, (Ptr{SCIP_EXPR},), expr)
end

function SCIPexprGetNChildren(expr)
    ccall((:SCIPexprGetNChildren, libscip), Cint, (Ptr{SCIP_EXPR},), expr)
end

function SCIPexprGetChildren(expr)
    ccall((:SCIPexprGetChildren, libscip), Ptr{Ptr{SCIP_EXPR}}, (Ptr{SCIP_EXPR},), expr)
end

function SCIPexprGetOpIndex(expr)
    ccall((:SCIPexprGetOpIndex, libscip), Cint, (Ptr{SCIP_EXPR},), expr)
end

function SCIPexprGetOpReal(expr)
    ccall((:SCIPexprGetOpReal, libscip), Cdouble, (Ptr{SCIP_EXPR},), expr)
end

function SCIPexprGetOpData(expr)
    ccall((:SCIPexprGetOpData, libscip), Ptr{Cvoid}, (Ptr{SCIP_EXPR},), expr)
end

function SCIPexprGetRealPowerExponent(expr)
    ccall((:SCIPexprGetRealPowerExponent, libscip), Cdouble, (Ptr{SCIP_EXPR},), expr)
end

function SCIPexprGetIntPowerExponent(expr)
    ccall((:SCIPexprGetIntPowerExponent, libscip), Cint, (Ptr{SCIP_EXPR},), expr)
end

function SCIPexprGetSignPowerExponent(expr)
    ccall((:SCIPexprGetSignPowerExponent, libscip), Cdouble, (Ptr{SCIP_EXPR},), expr)
end

function SCIPexprGetLinearCoefs(expr)
    ccall((:SCIPexprGetLinearCoefs, libscip), Ptr{Cdouble}, (Ptr{SCIP_EXPR},), expr)
end

function SCIPexprGetLinearConstant(expr)
    ccall((:SCIPexprGetLinearConstant, libscip), Cdouble, (Ptr{SCIP_EXPR},), expr)
end

function SCIPexprGetQuadElements(expr)
    ccall((:SCIPexprGetQuadElements, libscip), Ptr{SCIP_QUADELEM}, (Ptr{SCIP_EXPR},), expr)
end

function SCIPexprGetQuadConstant(expr)
    ccall((:SCIPexprGetQuadConstant, libscip), Cdouble, (Ptr{SCIP_EXPR},), expr)
end

function SCIPexprGetQuadLinearCoefs(expr)
    ccall((:SCIPexprGetQuadLinearCoefs, libscip), Ptr{Cdouble}, (Ptr{SCIP_EXPR},), expr)
end

function SCIPexprGetNQuadElements(expr)
    ccall((:SCIPexprGetNQuadElements, libscip), Cint, (Ptr{SCIP_EXPR},), expr)
end

function SCIPexprGetMonomials(expr)
    ccall((:SCIPexprGetMonomials, libscip), Ptr{Ptr{SCIP_EXPRDATA_MONOMIAL}}, (Ptr{SCIP_EXPR},), expr)
end

function SCIPexprGetNMonomials(expr)
    ccall((:SCIPexprGetNMonomials, libscip), Cint, (Ptr{SCIP_EXPR},), expr)
end

function SCIPexprGetPolynomialConstant(expr)
    ccall((:SCIPexprGetPolynomialConstant, libscip), Cdouble, (Ptr{SCIP_EXPR},), expr)
end

function SCIPexprGetMonomialCoef(monomial)
    ccall((:SCIPexprGetMonomialCoef, libscip), Cdouble, (Ptr{SCIP_EXPRDATA_MONOMIAL},), monomial)
end

function SCIPexprGetMonomialNFactors(monomial)
    ccall((:SCIPexprGetMonomialNFactors, libscip), Cint, (Ptr{SCIP_EXPRDATA_MONOMIAL},), monomial)
end

function SCIPexprGetMonomialChildIndices(monomial)
    ccall((:SCIPexprGetMonomialChildIndices, libscip), Ptr{Cint}, (Ptr{SCIP_EXPRDATA_MONOMIAL},), monomial)
end

function SCIPexprGetMonomialExponents(monomial)
    ccall((:SCIPexprGetMonomialExponents, libscip), Ptr{Cdouble}, (Ptr{SCIP_EXPRDATA_MONOMIAL},), monomial)
end

function SCIPexprGetUserData(expr)
    ccall((:SCIPexprGetUserData, libscip), Ptr{SCIP_USEREXPRDATA}, (Ptr{SCIP_EXPR},), expr)
end

function SCIPexprHasUserEstimator(expr)
    ccall((:SCIPexprHasUserEstimator, libscip), UInt32, (Ptr{SCIP_EXPR},), expr)
end

function SCIPexprGetUserEvalCapability(expr)
    ccall((:SCIPexprGetUserEvalCapability, libscip), SCIP_EXPRINTCAPABILITY, (Ptr{SCIP_EXPR},), expr)
end

function SCIPexprCopyDeep(blkmem, targetexpr, sourceexpr)
    ccall((:SCIPexprCopyDeep, libscip), SCIP_RETCODE, (Ptr{BMS_BLKMEM}, Ptr{Ptr{SCIP_EXPR}}, Ptr{SCIP_EXPR}), blkmem, targetexpr, sourceexpr)
end

function SCIPexprFreeDeep(blkmem, expr)
    ccall((:SCIPexprFreeDeep, libscip), Cvoid, (Ptr{BMS_BLKMEM}, Ptr{Ptr{SCIP_EXPR}}), blkmem, expr)
end

function SCIPexprFreeShallow(blkmem, expr)
    ccall((:SCIPexprFreeShallow, libscip), Cvoid, (Ptr{BMS_BLKMEM}, Ptr{Ptr{SCIP_EXPR}}), blkmem, expr)
end

function SCIPexprAdd(blkmem, expr, coef1, term1, coef2, term2, constant)
    ccall((:SCIPexprAdd, libscip), SCIP_RETCODE, (Ptr{BMS_BLKMEM}, Ptr{Ptr{SCIP_EXPR}}, Cdouble, Ptr{SCIP_EXPR}, Cdouble, Ptr{SCIP_EXPR}, Cdouble), blkmem, expr, coef1, term1, coef2, term2, constant)
end

function SCIPexprMulConstant(blkmem, expr, term, factor)
    ccall((:SCIPexprMulConstant, libscip), SCIP_RETCODE, (Ptr{BMS_BLKMEM}, Ptr{Ptr{SCIP_EXPR}}, Ptr{SCIP_EXPR}, Cdouble), blkmem, expr, term, factor)
end

function SCIPexprCreateLinear(blkmem, expr, nchildren, children, coefs, constant)
    ccall((:SCIPexprCreateLinear, libscip), SCIP_RETCODE, (Ptr{BMS_BLKMEM}, Ptr{Ptr{SCIP_EXPR}}, Cint, Ptr{Ptr{SCIP_EXPR}}, Ptr{Cdouble}, Cdouble), blkmem, expr, nchildren, children, coefs, constant)
end

function SCIPexprAddToLinear(blkmem, expr, nchildren, coefs, children, constant)
    ccall((:SCIPexprAddToLinear, libscip), SCIP_RETCODE, (Ptr{BMS_BLKMEM}, Ptr{SCIP_EXPR}, Cint, Ptr{Cdouble}, Ptr{Ptr{SCIP_EXPR}}, Cdouble), blkmem, expr, nchildren, coefs, children, constant)
end

function SCIPexprCreateQuadratic(blkmem, expr, nchildren, children, constant, lincoefs, nquadelems, quadelems)
    ccall((:SCIPexprCreateQuadratic, libscip), SCIP_RETCODE, (Ptr{BMS_BLKMEM}, Ptr{Ptr{SCIP_EXPR}}, Cint, Ptr{Ptr{SCIP_EXPR}}, Cdouble, Ptr{Cdouble}, Cint, Ptr{SCIP_QUADELEM}), blkmem, expr, nchildren, children, constant, lincoefs, nquadelems, quadelems)
end

function SCIPexprSortQuadElems(expr)
    ccall((:SCIPexprSortQuadElems, libscip), Cvoid, (Ptr{SCIP_EXPR},), expr)
end

function SCIPexprCreatePolynomial(blkmem, expr, nchildren, children, nmonomials, monomials, constant, copymonomials)
    ccall((:SCIPexprCreatePolynomial, libscip), SCIP_RETCODE, (Ptr{BMS_BLKMEM}, Ptr{Ptr{SCIP_EXPR}}, Cint, Ptr{Ptr{SCIP_EXPR}}, Cint, Ptr{Ptr{SCIP_EXPRDATA_MONOMIAL}}, Cdouble, UInt32), blkmem, expr, nchildren, children, nmonomials, monomials, constant, copymonomials)
end

function SCIPexprAddMonomials(blkmem, expr, nmonomials, monomials, copymonomials)
    ccall((:SCIPexprAddMonomials, libscip), SCIP_RETCODE, (Ptr{BMS_BLKMEM}, Ptr{SCIP_EXPR}, Cint, Ptr{Ptr{SCIP_EXPRDATA_MONOMIAL}}, UInt32), blkmem, expr, nmonomials, monomials, copymonomials)
end

function SCIPexprChgPolynomialConstant(expr, constant)
    ccall((:SCIPexprChgPolynomialConstant, libscip), Cvoid, (Ptr{SCIP_EXPR}, Cdouble), expr, constant)
end

function SCIPexprMultiplyPolynomialByConstant(blkmem, expr, factor)
    ccall((:SCIPexprMultiplyPolynomialByConstant, libscip), Cvoid, (Ptr{BMS_BLKMEM}, Ptr{SCIP_EXPR}, Cdouble), blkmem, expr, factor)
end

function SCIPexprMultiplyPolynomialByMonomial(blkmem, expr, factor, childmap)
    ccall((:SCIPexprMultiplyPolynomialByMonomial, libscip), SCIP_RETCODE, (Ptr{BMS_BLKMEM}, Ptr{SCIP_EXPR}, Ptr{SCIP_EXPRDATA_MONOMIAL}, Ptr{Cint}), blkmem, expr, factor, childmap)
end

function SCIPexprMultiplyPolynomialByPolynomial(blkmem, expr, factor, childmap)
    ccall((:SCIPexprMultiplyPolynomialByPolynomial, libscip), SCIP_RETCODE, (Ptr{BMS_BLKMEM}, Ptr{SCIP_EXPR}, Ptr{SCIP_EXPR}, Ptr{Cint}), blkmem, expr, factor, childmap)
end

function SCIPexprPolynomialPower(blkmem, expr, exponent)
    ccall((:SCIPexprPolynomialPower, libscip), SCIP_RETCODE, (Ptr{BMS_BLKMEM}, Ptr{SCIP_EXPR}, Cint), blkmem, expr, exponent)
end

function SCIPexprMergeMonomials(blkmem, expr, eps, mergefactors)
    ccall((:SCIPexprMergeMonomials, libscip), Cvoid, (Ptr{BMS_BLKMEM}, Ptr{SCIP_EXPR}, Cdouble, UInt32), blkmem, expr, eps, mergefactors)
end

function SCIPexprCreateMonomial(blkmem, monomial, coef, nfactors, childidxs, exponents)
    ccall((:SCIPexprCreateMonomial, libscip), SCIP_RETCODE, (Ptr{BMS_BLKMEM}, Ptr{Ptr{SCIP_EXPRDATA_MONOMIAL}}, Cdouble, Cint, Ptr{Cint}, Ptr{Cdouble}), blkmem, monomial, coef, nfactors, childidxs, exponents)
end

function SCIPexprFreeMonomial(blkmem, monomial)
    ccall((:SCIPexprFreeMonomial, libscip), Cvoid, (Ptr{BMS_BLKMEM}, Ptr{Ptr{SCIP_EXPRDATA_MONOMIAL}}), blkmem, monomial)
end

function SCIPexprSortMonomialFactors(monomial)
    ccall((:SCIPexprSortMonomialFactors, libscip), Cvoid, (Ptr{SCIP_EXPRDATA_MONOMIAL},), monomial)
end

function SCIPexprFindMonomialFactor(monomial, childidx, pos)
    ccall((:SCIPexprFindMonomialFactor, libscip), UInt32, (Ptr{SCIP_EXPRDATA_MONOMIAL}, Cint, Ptr{Cint}), monomial, childidx, pos)
end

function SCIPexprAreMonomialsEqual(monomial1, monomial2, eps)
    ccall((:SCIPexprAreMonomialsEqual, libscip), UInt32, (Ptr{SCIP_EXPRDATA_MONOMIAL}, Ptr{SCIP_EXPRDATA_MONOMIAL}, Cdouble), monomial1, monomial2, eps)
end

function SCIPexprAddMonomialFactors(blkmem, monomial, nfactors, childidxs, exponents)
    ccall((:SCIPexprAddMonomialFactors, libscip), SCIP_RETCODE, (Ptr{BMS_BLKMEM}, Ptr{SCIP_EXPRDATA_MONOMIAL}, Cint, Ptr{Cint}, Ptr{Cdouble}), blkmem, monomial, nfactors, childidxs, exponents)
end

function SCIPexprChgMonomialCoef(monomial, newcoef)
    ccall((:SCIPexprChgMonomialCoef, libscip), Cvoid, (Ptr{SCIP_EXPRDATA_MONOMIAL}, Cdouble), monomial, newcoef)
end

function SCIPexprMultiplyMonomialByMonomial(blkmem, monomial, factor, childmap)
    ccall((:SCIPexprMultiplyMonomialByMonomial, libscip), SCIP_RETCODE, (Ptr{BMS_BLKMEM}, Ptr{SCIP_EXPRDATA_MONOMIAL}, Ptr{SCIP_EXPRDATA_MONOMIAL}, Ptr{Cint}), blkmem, monomial, factor, childmap)
end

function SCIPexprMonomialPower(monomial, exponent)
    ccall((:SCIPexprMonomialPower, libscip), Cvoid, (Ptr{SCIP_EXPRDATA_MONOMIAL}, Cint), monomial, exponent)
end

function SCIPexprMergeMonomialFactors(monomial, eps)
    ccall((:SCIPexprMergeMonomialFactors, libscip), Cvoid, (Ptr{SCIP_EXPRDATA_MONOMIAL}, Cdouble), monomial, eps)
end

function SCIPexprSortMonomials(expr)
    ccall((:SCIPexprSortMonomials, libscip), Cvoid, (Ptr{SCIP_EXPR},), expr)
end

function SCIPexprCreateUser(blkmem, expr, nchildren, children, data, evalcapability, eval, inteval, curv, prop, estimate, copydata, freedata, print)
    ccall((:SCIPexprCreateUser, libscip), SCIP_RETCODE, (Ptr{BMS_BLKMEM}, Ptr{Ptr{SCIP_EXPR}}, Cint, Ptr{Ptr{SCIP_EXPR}}, Ptr{SCIP_USEREXPRDATA}, SCIP_EXPRINTCAPABILITY, Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}), blkmem, expr, nchildren, children, data, evalcapability, eval, inteval, curv, prop, estimate, copydata, freedata, print)
end

function SCIPexprHasParam(expr)
    ccall((:SCIPexprHasParam, libscip), UInt32, (Ptr{SCIP_EXPR},), expr)
end

function SCIPexprGetMaxDegree(expr, maxdegree)
    ccall((:SCIPexprGetMaxDegree, libscip), SCIP_RETCODE, (Ptr{SCIP_EXPR}, Ptr{Cint}), expr, maxdegree)
end

function SCIPexprGetVarsUsage(expr, varsusage)
    ccall((:SCIPexprGetVarsUsage, libscip), Cvoid, (Ptr{SCIP_EXPR}, Ptr{Cint}), expr, varsusage)
end

function SCIPexprAreEqual(expr1, expr2, eps)
    ccall((:SCIPexprAreEqual, libscip), UInt32, (Ptr{SCIP_EXPR}, Ptr{SCIP_EXPR}, Cdouble), expr1, expr2, eps)
end

function SCIPexprSimplify(blkmem, messagehdlr, expr, eps, maxexpansionexponent, nvars, nlinvars, linidxs, lincoefs)
    ccall((:SCIPexprSimplify, libscip), SCIP_RETCODE, (Ptr{BMS_BLKMEM}, Ptr{SCIP_MESSAGEHDLR}, Ptr{SCIP_EXPR}, Cdouble, Cint, Cint, Ptr{Cint}, Ptr{Cint}, Ptr{Cdouble}), blkmem, messagehdlr, expr, eps, maxexpansionexponent, nvars, nlinvars, linidxs, lincoefs)
end

function SCIPexprEvalShallow(expr, argvals, varvals, param, val)
    ccall((:SCIPexprEvalShallow, libscip), SCIP_RETCODE, (Ptr{SCIP_EXPR}, Ptr{Cdouble}, Ptr{Cdouble}, Ptr{Cdouble}, Ptr{Cdouble}), expr, argvals, varvals, param, val)
end

function SCIPexprEval(expr, varvals, param, val)
    ccall((:SCIPexprEval, libscip), SCIP_RETCODE, (Ptr{SCIP_EXPR}, Ptr{Cdouble}, Ptr{Cdouble}, Ptr{Cdouble}), expr, varvals, param, val)
end

function SCIPexprEvalIntShallow(expr, infinity, argvals, varvals, param, val)
    ccall((:SCIPexprEvalIntShallow, libscip), SCIP_RETCODE, (Ptr{SCIP_EXPR}, Cdouble, Ptr{SCIP_INTERVAL}, Ptr{SCIP_INTERVAL}, Ptr{Cdouble}, Ptr{SCIP_INTERVAL}), expr, infinity, argvals, varvals, param, val)
end

function SCIPexprEvalInt(expr, infinity, varvals, param, val)
    ccall((:SCIPexprEvalInt, libscip), SCIP_RETCODE, (Ptr{SCIP_EXPR}, Cdouble, Ptr{SCIP_INTERVAL}, Ptr{Cdouble}, Ptr{SCIP_INTERVAL}), expr, infinity, varvals, param, val)
end

function SCIPexprEvalUser(expr, argvals, val, gradient, hessian)
    ccall((:SCIPexprEvalUser, libscip), SCIP_RETCODE, (Ptr{SCIP_EXPR}, Ptr{Cdouble}, Ptr{Cdouble}, Ptr{Cdouble}, Ptr{Cdouble}), expr, argvals, val, gradient, hessian)
end

function SCIPexprEvalIntUser(expr, infinity, argvals, val, gradient, hessian)
    ccall((:SCIPexprEvalIntUser, libscip), SCIP_RETCODE, (Ptr{SCIP_EXPR}, Cdouble, Ptr{SCIP_INTERVAL}, Ptr{SCIP_INTERVAL}, Ptr{SCIP_INTERVAL}, Ptr{SCIP_INTERVAL}), expr, infinity, argvals, val, gradient, hessian)
end

function SCIPexprCheckCurvature(expr, infinity, varbounds, param, curv, bounds)
    ccall((:SCIPexprCheckCurvature, libscip), SCIP_RETCODE, (Ptr{SCIP_EXPR}, Cdouble, Ptr{SCIP_INTERVAL}, Ptr{Cdouble}, Ptr{SCIP_EXPRCURV}, Ptr{SCIP_INTERVAL}), expr, infinity, varbounds, param, curv, bounds)
end

function SCIPexprEstimateUser(expr, infinity, argvals, argbounds, overestimate, coeffs, constant, success)
    ccall((:SCIPexprEstimateUser, libscip), SCIP_RETCODE, (Ptr{SCIP_EXPR}, Cdouble, Ptr{Cdouble}, Ptr{SCIP_INTERVAL}, UInt32, Ptr{Cdouble}, Ptr{Cdouble}, Ptr{UInt32}), expr, infinity, argvals, argbounds, overestimate, coeffs, constant, success)
end

function SCIPexprSubstituteVars(blkmem, expr, substexprs)
    ccall((:SCIPexprSubstituteVars, libscip), SCIP_RETCODE, (Ptr{BMS_BLKMEM}, Ptr{SCIP_EXPR}, Ptr{Ptr{SCIP_EXPR}}), blkmem, expr, substexprs)
end

function SCIPexprReindexVars(expr, newindices)
    ccall((:SCIPexprReindexVars, libscip), Cvoid, (Ptr{SCIP_EXPR}, Ptr{Cint}), expr, newindices)
end

function SCIPexprReindexParams(expr, newindices)
    ccall((:SCIPexprReindexParams, libscip), Cvoid, (Ptr{SCIP_EXPR}, Ptr{Cint}), expr, newindices)
end

function SCIPexprPrint(expr, messagehdlr, file, varnames, paramnames, paramvals)
    ccall((:SCIPexprPrint, libscip), Cvoid, (Ptr{SCIP_EXPR}, Ptr{SCIP_MESSAGEHDLR}, Ptr{FILE}, Ptr{Cstring}, Ptr{Cstring}, Ptr{Cdouble}), expr, messagehdlr, file, varnames, paramnames, paramvals)
end

function SCIPexprParse(blkmem, messagehdlr, expr, str, lastchar, nvars, varnames, varnameslength)
    ccall((:SCIPexprParse, libscip), SCIP_RETCODE, (Ptr{BMS_BLKMEM}, Ptr{SCIP_MESSAGEHDLR}, Ptr{Ptr{SCIP_EXPR}}, Cstring, Cstring, Ptr{Cint}, Ptr{Cint}, Cint), blkmem, messagehdlr, expr, str, lastchar, nvars, varnames, varnameslength)
end

function SCIPexprtreeGetRoot(tree)
    ccall((:SCIPexprtreeGetRoot, libscip), Ptr{SCIP_EXPR}, (Ptr{SCIP_EXPRTREE},), tree)
end

function SCIPexprtreeGetNVars(tree)
    ccall((:SCIPexprtreeGetNVars, libscip), Cint, (Ptr{SCIP_EXPRTREE},), tree)
end

function SCIPexprtreeGetNParams(tree)
    ccall((:SCIPexprtreeGetNParams, libscip), Cint, (Ptr{SCIP_EXPRTREE},), tree)
end

function SCIPexprtreeGetParamVals(tree)
    ccall((:SCIPexprtreeGetParamVals, libscip), Ptr{Cdouble}, (Ptr{SCIP_EXPRTREE},), tree)
end

function SCIPexprtreeSetParamVal(tree, paramidx, paramval)
    ccall((:SCIPexprtreeSetParamVal, libscip), Cvoid, (Ptr{SCIP_EXPRTREE}, Cint, Cdouble), tree, paramidx, paramval)
end

function SCIPexprtreeGetInterpreterData(tree)
    ccall((:SCIPexprtreeGetInterpreterData, libscip), Ptr{SCIP_EXPRINTDATA}, (Ptr{SCIP_EXPRTREE},), tree)
end

function SCIPexprtreeSetInterpreterData(tree, interpreterdata)
    ccall((:SCIPexprtreeSetInterpreterData, libscip), Cvoid, (Ptr{SCIP_EXPRTREE}, Ptr{SCIP_EXPRINTDATA}), tree, interpreterdata)
end

function SCIPexprtreeFreeInterpreterData(tree)
    ccall((:SCIPexprtreeFreeInterpreterData, libscip), SCIP_RETCODE, (Ptr{SCIP_EXPRTREE},), tree)
end

function SCIPexprtreeHasParam(tree)
    ccall((:SCIPexprtreeHasParam, libscip), UInt32, (Ptr{SCIP_EXPRTREE},), tree)
end

function SCIPexprtreeGetMaxDegree(tree, maxdegree)
    ccall((:SCIPexprtreeGetMaxDegree, libscip), SCIP_RETCODE, (Ptr{SCIP_EXPRTREE}, Ptr{Cint}), tree, maxdegree)
end

function SCIPexprtreeEval(tree, varvals, val)
    ccall((:SCIPexprtreeEval, libscip), SCIP_RETCODE, (Ptr{SCIP_EXPRTREE}, Ptr{Cdouble}, Ptr{Cdouble}), tree, varvals, val)
end

function SCIPexprtreeEvalInt(tree, infinity, varvals, val)
    ccall((:SCIPexprtreeEvalInt, libscip), SCIP_RETCODE, (Ptr{SCIP_EXPRTREE}, Cdouble, Ptr{SCIP_INTERVAL}, Ptr{SCIP_INTERVAL}), tree, infinity, varvals, val)
end

function SCIPexprtreePrint(tree, messagehdlr, file, varnames, paramnames)
    ccall((:SCIPexprtreePrint, libscip), Cvoid, (Ptr{SCIP_EXPRTREE}, Ptr{SCIP_MESSAGEHDLR}, Ptr{FILE}, Ptr{Cstring}, Ptr{Cstring}), tree, messagehdlr, file, varnames, paramnames)
end

function SCIPexprtreeCreate(blkmem, tree, root, nvars, nparams, params)
    ccall((:SCIPexprtreeCreate, libscip), SCIP_RETCODE, (Ptr{BMS_BLKMEM}, Ptr{Ptr{SCIP_EXPRTREE}}, Ptr{SCIP_EXPR}, Cint, Cint, Ptr{Cdouble}), blkmem, tree, root, nvars, nparams, params)
end

function SCIPexprtreeCopy(blkmem, targettree, sourcetree)
    ccall((:SCIPexprtreeCopy, libscip), SCIP_RETCODE, (Ptr{BMS_BLKMEM}, Ptr{Ptr{SCIP_EXPRTREE}}, Ptr{SCIP_EXPRTREE}), blkmem, targettree, sourcetree)
end

function SCIPexprtreeFree(tree)
    ccall((:SCIPexprtreeFree, libscip), SCIP_RETCODE, (Ptr{Ptr{SCIP_EXPRTREE}},), tree)
end

function SCIPexprtreeSetParams(tree, nparams, paramvals)
    ccall((:SCIPexprtreeSetParams, libscip), SCIP_RETCODE, (Ptr{SCIP_EXPRTREE}, Cint, Ptr{Cdouble}), tree, nparams, paramvals)
end

function SCIPexprtreeGetVarsUsage(tree, varsusage)
    ccall((:SCIPexprtreeGetVarsUsage, libscip), Cvoid, (Ptr{SCIP_EXPRTREE}, Ptr{Cint}), tree, varsusage)
end

function SCIPexprtreeSimplify(tree, messagehdlr, eps, maxexpansionexponent, nlinvars, linidxs, lincoefs)
    ccall((:SCIPexprtreeSimplify, libscip), SCIP_RETCODE, (Ptr{SCIP_EXPRTREE}, Ptr{SCIP_MESSAGEHDLR}, Cdouble, Cint, Ptr{Cint}, Ptr{Cint}, Ptr{Cdouble}), tree, messagehdlr, eps, maxexpansionexponent, nlinvars, linidxs, lincoefs)
end

function SCIPexprtreeAddExpr(tree, expr, copyexpr)
    ccall((:SCIPexprtreeAddExpr, libscip), SCIP_RETCODE, (Ptr{SCIP_EXPRTREE}, Ptr{SCIP_EXPR}, UInt32), tree, expr, copyexpr)
end

function SCIPexprtreeCheckCurvature(tree, infinity, varbounds, curv, bounds)
    ccall((:SCIPexprtreeCheckCurvature, libscip), SCIP_RETCODE, (Ptr{SCIP_EXPRTREE}, Cdouble, Ptr{SCIP_INTERVAL}, Ptr{SCIP_EXPRCURV}, Ptr{SCIP_INTERVAL}), tree, infinity, varbounds, curv, bounds)
end

function SCIPexprtreeSubstituteVars(tree, substexprs)
    ccall((:SCIPexprtreeSubstituteVars, libscip), SCIP_RETCODE, (Ptr{SCIP_EXPRTREE}, Ptr{Ptr{SCIP_EXPR}}), tree, substexprs)
end

function SCIPquadelemSort(quadelems, nquadelems)
    ccall((:SCIPquadelemSort, libscip), Cvoid, (Ptr{SCIP_QUADELEM}, Cint), quadelems, nquadelems)
end

function SCIPquadelemSortedFind(quadelems, idx1, idx2, nquadelems, pos)
    ccall((:SCIPquadelemSortedFind, libscip), UInt32, (Ptr{SCIP_QUADELEM}, Cint, Cint, Cint, Ptr{Cint}), quadelems, idx1, idx2, nquadelems, pos)
end

function SCIPquadelemSqueeze(quadelems, nquadelems, nquadelemsnew)
    ccall((:SCIPquadelemSqueeze, libscip), Cvoid, (Ptr{SCIP_QUADELEM}, Cint, Ptr{Cint}), quadelems, nquadelems, nquadelemsnew)
end

function SCIPexprgraphCaptureNode(node)
    ccall((:SCIPexprgraphCaptureNode, libscip), Cvoid, (Ptr{SCIP_EXPRGRAPHNODE},), node)
end

function SCIPexprgraphIsNodeEnabled(node)
    ccall((:SCIPexprgraphIsNodeEnabled, libscip), UInt32, (Ptr{SCIP_EXPRGRAPHNODE},), node)
end

function SCIPexprgraphGetNodeNChildren(node)
    ccall((:SCIPexprgraphGetNodeNChildren, libscip), Cint, (Ptr{SCIP_EXPRGRAPHNODE},), node)
end

function SCIPexprgraphGetNodeChildren(node)
    ccall((:SCIPexprgraphGetNodeChildren, libscip), Ptr{Ptr{SCIP_EXPRGRAPHNODE}}, (Ptr{SCIP_EXPRGRAPHNODE},), node)
end

function SCIPexprgraphGetNodeNParents(node)
    ccall((:SCIPexprgraphGetNodeNParents, libscip), Cint, (Ptr{SCIP_EXPRGRAPHNODE},), node)
end

function SCIPexprgraphGetNodeParents(node)
    ccall((:SCIPexprgraphGetNodeParents, libscip), Ptr{Ptr{SCIP_EXPRGRAPHNODE}}, (Ptr{SCIP_EXPRGRAPHNODE},), node)
end

function SCIPexprgraphGetNodeDepth(node)
    ccall((:SCIPexprgraphGetNodeDepth, libscip), Cint, (Ptr{SCIP_EXPRGRAPHNODE},), node)
end

function SCIPexprgraphGetNodePosition(node)
    ccall((:SCIPexprgraphGetNodePosition, libscip), Cint, (Ptr{SCIP_EXPRGRAPHNODE},), node)
end

function SCIPexprgraphGetNodeOperator(node)
    ccall((:SCIPexprgraphGetNodeOperator, libscip), SCIP_EXPROP, (Ptr{SCIP_EXPRGRAPHNODE},), node)
end

function SCIPexprgraphGetNodeOperatorIndex(node)
    ccall((:SCIPexprgraphGetNodeOperatorIndex, libscip), Cint, (Ptr{SCIP_EXPRGRAPHNODE},), node)
end

function SCIPexprgraphGetNodeOperatorReal(node)
    ccall((:SCIPexprgraphGetNodeOperatorReal, libscip), Cdouble, (Ptr{SCIP_EXPRGRAPHNODE},), node)
end

function SCIPexprgraphGetNodeVar(exprgraph, node)
    ccall((:SCIPexprgraphGetNodeVar, libscip), Ptr{Cvoid}, (Ptr{SCIP_EXPRGRAPH}, Ptr{SCIP_EXPRGRAPHNODE}), exprgraph, node)
end

function SCIPexprgraphGetNodeRealPowerExponent(node)
    ccall((:SCIPexprgraphGetNodeRealPowerExponent, libscip), Cdouble, (Ptr{SCIP_EXPRGRAPHNODE},), node)
end

function SCIPexprgraphGetNodeIntPowerExponent(node)
    ccall((:SCIPexprgraphGetNodeIntPowerExponent, libscip), Cint, (Ptr{SCIP_EXPRGRAPHNODE},), node)
end

function SCIPexprgraphGetNodeSignPowerExponent(node)
    ccall((:SCIPexprgraphGetNodeSignPowerExponent, libscip), Cdouble, (Ptr{SCIP_EXPRGRAPHNODE},), node)
end

function SCIPexprgraphGetNodeLinearCoefs(node)
    ccall((:SCIPexprgraphGetNodeLinearCoefs, libscip), Ptr{Cdouble}, (Ptr{SCIP_EXPRGRAPHNODE},), node)
end

function SCIPexprgraphGetNodeLinearConstant(node)
    ccall((:SCIPexprgraphGetNodeLinearConstant, libscip), Cdouble, (Ptr{SCIP_EXPRGRAPHNODE},), node)
end

function SCIPexprgraphGetNodeQuadraticConstant(node)
    ccall((:SCIPexprgraphGetNodeQuadraticConstant, libscip), Cdouble, (Ptr{SCIP_EXPRGRAPHNODE},), node)
end

function SCIPexprgraphGetNodeQuadraticLinearCoefs(node)
    ccall((:SCIPexprgraphGetNodeQuadraticLinearCoefs, libscip), Ptr{Cdouble}, (Ptr{SCIP_EXPRGRAPHNODE},), node)
end

function SCIPexprgraphGetNodeQuadraticQuadElements(node)
    ccall((:SCIPexprgraphGetNodeQuadraticQuadElements, libscip), Ptr{SCIP_QUADELEM}, (Ptr{SCIP_EXPRGRAPHNODE},), node)
end

function SCIPexprgraphGetNodeQuadraticNQuadElements(node)
    ccall((:SCIPexprgraphGetNodeQuadraticNQuadElements, libscip), Cint, (Ptr{SCIP_EXPRGRAPHNODE},), node)
end

function SCIPexprgraphGetNodePolynomialMonomials(node)
    ccall((:SCIPexprgraphGetNodePolynomialMonomials, libscip), Ptr{Ptr{SCIP_EXPRDATA_MONOMIAL}}, (Ptr{SCIP_EXPRGRAPHNODE},), node)
end

function SCIPexprgraphGetNodePolynomialNMonomials(node)
    ccall((:SCIPexprgraphGetNodePolynomialNMonomials, libscip), Cint, (Ptr{SCIP_EXPRGRAPHNODE},), node)
end

function SCIPexprgraphGetNodePolynomialConstant(node)
    ccall((:SCIPexprgraphGetNodePolynomialConstant, libscip), Cdouble, (Ptr{SCIP_EXPRGRAPHNODE},), node)
end

function SCIPexprgraphGetNodePolynomialMonomialCurvature(node, monomialidx, infinity, curv)
    ccall((:SCIPexprgraphGetNodePolynomialMonomialCurvature, libscip), SCIP_RETCODE, (Ptr{SCIP_EXPRGRAPHNODE}, Cint, Cdouble, Ptr{SCIP_EXPRCURV}), node, monomialidx, infinity, curv)
end

function SCIPexprgraphGetNodeUserData(node)
    ccall((:SCIPexprgraphGetNodeUserData, libscip), Ptr{SCIP_USEREXPRDATA}, (Ptr{SCIP_EXPRGRAPHNODE},), node)
end

function SCIPexprgraphHasNodeUserEstimator(node)
    ccall((:SCIPexprgraphHasNodeUserEstimator, libscip), UInt32, (Ptr{SCIP_EXPRGRAPHNODE},), node)
end

function SCIPexprgraphGetNodeBounds(node)
    ccall((:SCIPexprgraphGetNodeBounds, libscip), SCIP_INTERVAL, (Ptr{SCIP_EXPRGRAPHNODE},), node)
end

function SCIPexprgraphGetNodeVal(node)
    ccall((:SCIPexprgraphGetNodeVal, libscip), Cdouble, (Ptr{SCIP_EXPRGRAPHNODE},), node)
end

function SCIPexprgraphGetNodeCurvature(node)
    ccall((:SCIPexprgraphGetNodeCurvature, libscip), SCIP_EXPRCURV, (Ptr{SCIP_EXPRGRAPHNODE},), node)
end

function SCIPexprgraphCreateNodeLinear(blkmem, node, ncoefs, coefs, constant)
    ccall((:SCIPexprgraphCreateNodeLinear, libscip), SCIP_RETCODE, (Ptr{BMS_BLKMEM}, Ptr{Ptr{SCIP_EXPRGRAPHNODE}}, Cint, Ptr{Cdouble}, Cdouble), blkmem, node, ncoefs, coefs, constant)
end

function SCIPexprgraphCreateNodeQuadratic(blkmem, node, nchildren, lincoefs, nquadelems, quadelems, constant)
    ccall((:SCIPexprgraphCreateNodeQuadratic, libscip), SCIP_RETCODE, (Ptr{BMS_BLKMEM}, Ptr{Ptr{SCIP_EXPRGRAPHNODE}}, Cint, Ptr{Cdouble}, Cint, Ptr{SCIP_QUADELEM}, Cdouble), blkmem, node, nchildren, lincoefs, nquadelems, quadelems, constant)
end

function SCIPexprgraphCreateNodePolynomial(blkmem, node, nmonomials, monomials, constant, copymonomials)
    ccall((:SCIPexprgraphCreateNodePolynomial, libscip), SCIP_RETCODE, (Ptr{BMS_BLKMEM}, Ptr{Ptr{SCIP_EXPRGRAPHNODE}}, Cint, Ptr{Ptr{SCIP_EXPRDATA_MONOMIAL}}, Cdouble, UInt32), blkmem, node, nmonomials, monomials, constant, copymonomials)
end

function SCIPexprgraphNodePolynomialAddMonomials(blkmem, node, nmonomials, monomials, copymonomials)
    ccall((:SCIPexprgraphNodePolynomialAddMonomials, libscip), SCIP_RETCODE, (Ptr{BMS_BLKMEM}, Ptr{SCIP_EXPRGRAPHNODE}, Cint, Ptr{Ptr{SCIP_EXPRDATA_MONOMIAL}}, UInt32), blkmem, node, nmonomials, monomials, copymonomials)
end

function SCIPexprgraphCreateNodeUser(blkmem, node, data, evalcapability, eval, inteval, curv, prop, estimate, copydata, freedata, print)
    ccall((:SCIPexprgraphCreateNodeUser, libscip), SCIP_RETCODE, (Ptr{BMS_BLKMEM}, Ptr{Ptr{SCIP_EXPRGRAPHNODE}}, Ptr{SCIP_USEREXPRDATA}, SCIP_EXPRINTCAPABILITY, Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}), blkmem, node, data, evalcapability, eval, inteval, curv, prop, estimate, copydata, freedata, print)
end

function SCIPexprgraphNodeSplitOffLinear(exprgraph, node, linvarssize, nlinvars, linvars, lincoefs, constant)
    ccall((:SCIPexprgraphNodeSplitOffLinear, libscip), SCIP_RETCODE, (Ptr{SCIP_EXPRGRAPH}, Ptr{Ptr{SCIP_EXPRGRAPHNODE}}, Cint, Ptr{Cint}, Ptr{Ptr{Cvoid}}, Ptr{Cdouble}, Ptr{Cdouble}), exprgraph, node, linvarssize, nlinvars, linvars, lincoefs, constant)
end

function SCIPexprgraphMoveNodeParents(exprgraph, srcnode, targetnode)
    ccall((:SCIPexprgraphMoveNodeParents, libscip), SCIP_RETCODE, (Ptr{SCIP_EXPRGRAPH}, Ptr{Ptr{SCIP_EXPRGRAPHNODE}}, Ptr{SCIP_EXPRGRAPHNODE}), exprgraph, srcnode, targetnode)
end

function SCIPexprgraphReleaseNode(exprgraph, node)
    ccall((:SCIPexprgraphReleaseNode, libscip), SCIP_RETCODE, (Ptr{SCIP_EXPRGRAPH}, Ptr{Ptr{SCIP_EXPRGRAPHNODE}}), exprgraph, node)
end

function SCIPexprgraphFreeNode(blkmem, node)
    ccall((:SCIPexprgraphFreeNode, libscip), Cvoid, (Ptr{BMS_BLKMEM}, Ptr{Ptr{SCIP_EXPRGRAPHNODE}}), blkmem, node)
end

function SCIPexprgraphEnableNode(exprgraph, node)
    ccall((:SCIPexprgraphEnableNode, libscip), Cvoid, (Ptr{SCIP_EXPRGRAPH}, Ptr{SCIP_EXPRGRAPHNODE}), exprgraph, node)
end

function SCIPexprgraphDisableNode(exprgraph, node)
    ccall((:SCIPexprgraphDisableNode, libscip), Cvoid, (Ptr{SCIP_EXPRGRAPH}, Ptr{SCIP_EXPRGRAPHNODE}), exprgraph, node)
end

function SCIPexprgraphHasNodeSibling(node)
    ccall((:SCIPexprgraphHasNodeSibling, libscip), UInt32, (Ptr{SCIP_EXPRGRAPHNODE},), node)
end

function SCIPexprgraphAreAllNodeChildrenVars(node)
    ccall((:SCIPexprgraphAreAllNodeChildrenVars, libscip), UInt32, (Ptr{SCIP_EXPRGRAPHNODE},), node)
end

function SCIPexprgraphHasNodeNonlinearAncestor(node)
    ccall((:SCIPexprgraphHasNodeNonlinearAncestor, libscip), UInt32, (Ptr{SCIP_EXPRGRAPHNODE},), node)
end

function SCIPexprgraphPrintNode(node, messagehdlr, file)
    ccall((:SCIPexprgraphPrintNode, libscip), Cvoid, (Ptr{SCIP_EXPRGRAPHNODE}, Ptr{SCIP_MESSAGEHDLR}, Ptr{FILE}), node, messagehdlr, file)
end

function SCIPexprgraphTightenNodeBounds(exprgraph, node, nodebounds, minstrength, infinity, cutoff)
    ccall((:SCIPexprgraphTightenNodeBounds, libscip), Cvoid, (Ptr{SCIP_EXPRGRAPH}, Ptr{SCIP_EXPRGRAPHNODE}, SCIP_INTERVAL, Cdouble, Cdouble, Ptr{UInt32}), exprgraph, node, nodebounds, minstrength, infinity, cutoff)
end

function SCIPexprgraphUpdateNodeBoundsCurvature(node, infinity, minstrength, clearreverseprop)
    ccall((:SCIPexprgraphUpdateNodeBoundsCurvature, libscip), SCIP_RETCODE, (Ptr{SCIP_EXPRGRAPHNODE}, Cdouble, Cdouble, UInt32), node, infinity, minstrength, clearreverseprop)
end

function SCIPexprgraphGetDepth(exprgraph)
    ccall((:SCIPexprgraphGetDepth, libscip), Cint, (Ptr{SCIP_EXPRGRAPH},), exprgraph)
end

function SCIPexprgraphGetNNodes(exprgraph)
    ccall((:SCIPexprgraphGetNNodes, libscip), Ptr{Cint}, (Ptr{SCIP_EXPRGRAPH},), exprgraph)
end

function SCIPexprgraphGetNodes(exprgraph)
    ccall((:SCIPexprgraphGetNodes, libscip), Ptr{Ptr{Ptr{SCIP_EXPRGRAPHNODE}}}, (Ptr{SCIP_EXPRGRAPH},), exprgraph)
end

function SCIPexprgraphGetNVars(exprgraph)
    ccall((:SCIPexprgraphGetNVars, libscip), Cint, (Ptr{SCIP_EXPRGRAPH},), exprgraph)
end

function SCIPexprgraphGetVars(exprgraph)
    ccall((:SCIPexprgraphGetVars, libscip), Ptr{Ptr{Cvoid}}, (Ptr{SCIP_EXPRGRAPH},), exprgraph)
end

function SCIPexprgraphGetVarNodes(exprgraph)
    ccall((:SCIPexprgraphGetVarNodes, libscip), Ptr{Ptr{SCIP_EXPRGRAPHNODE}}, (Ptr{SCIP_EXPRGRAPH},), exprgraph)
end

function SCIPexprgraphSetVarNodeValue(varnode, value)
    ccall((:SCIPexprgraphSetVarNodeValue, libscip), Cvoid, (Ptr{SCIP_EXPRGRAPHNODE}, Cdouble), varnode, value)
end

function SCIPexprgraphSetVarsBounds(exprgraph, varbounds)
    ccall((:SCIPexprgraphSetVarsBounds, libscip), Cvoid, (Ptr{SCIP_EXPRGRAPH}, Ptr{SCIP_INTERVAL}), exprgraph, varbounds)
end

function SCIPexprgraphSetVarBounds(exprgraph, var, varbounds)
    ccall((:SCIPexprgraphSetVarBounds, libscip), Cvoid, (Ptr{SCIP_EXPRGRAPH}, Ptr{Cvoid}, SCIP_INTERVAL), exprgraph, var, varbounds)
end

function SCIPexprgraphSetVarNodeBounds(exprgraph, varnode, varbounds)
    ccall((:SCIPexprgraphSetVarNodeBounds, libscip), Cvoid, (Ptr{SCIP_EXPRGRAPH}, Ptr{SCIP_EXPRGRAPHNODE}, SCIP_INTERVAL), exprgraph, varnode, varbounds)
end

function SCIPexprgraphSetVarNodeLb(exprgraph, varnode, lb)
    ccall((:SCIPexprgraphSetVarNodeLb, libscip), Cvoid, (Ptr{SCIP_EXPRGRAPH}, Ptr{SCIP_EXPRGRAPHNODE}, Cdouble), exprgraph, varnode, lb)
end

function SCIPexprgraphSetVarNodeUb(exprgraph, varnode, ub)
    ccall((:SCIPexprgraphSetVarNodeUb, libscip), Cvoid, (Ptr{SCIP_EXPRGRAPH}, Ptr{SCIP_EXPRGRAPHNODE}, Cdouble), exprgraph, varnode, ub)
end

function SCIPexprgraphGetVarsBounds(exprgraph)
    ccall((:SCIPexprgraphGetVarsBounds, libscip), Ptr{SCIP_INTERVAL}, (Ptr{SCIP_EXPRGRAPH},), exprgraph)
end

function SCIPexprgraphCreate(blkmem, exprgraph, varssizeinit, depthinit, exprgraphvaradded, exprgraphvarremove, exprgraphvarchgidx, userdata)
    ccall((:SCIPexprgraphCreate, libscip), SCIP_RETCODE, (Ptr{BMS_BLKMEM}, Ptr{Ptr{SCIP_EXPRGRAPH}}, Cint, Cint, Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}), blkmem, exprgraph, varssizeinit, depthinit, exprgraphvaradded, exprgraphvarremove, exprgraphvarchgidx, userdata)
end

function SCIPexprgraphFree(exprgraph)
    ccall((:SCIPexprgraphFree, libscip), SCIP_RETCODE, (Ptr{Ptr{SCIP_EXPRGRAPH}},), exprgraph)
end

function SCIPexprgraphAddNode(exprgraph, node, mindepth, nchildren, children)
    ccall((:SCIPexprgraphAddNode, libscip), SCIP_RETCODE, (Ptr{SCIP_EXPRGRAPH}, Ptr{SCIP_EXPRGRAPHNODE}, Cint, Cint, Ptr{Ptr{SCIP_EXPRGRAPHNODE}}), exprgraph, node, mindepth, nchildren, children)
end

function SCIPexprgraphAddVars(exprgraph, nvars, vars, varnodes)
    ccall((:SCIPexprgraphAddVars, libscip), SCIP_RETCODE, (Ptr{SCIP_EXPRGRAPH}, Cint, Ptr{Ptr{Cvoid}}, Ptr{Ptr{SCIP_EXPRGRAPHNODE}}), exprgraph, nvars, vars, varnodes)
end

function SCIPexprgraphAddConst(exprgraph, constant, constnode)
    ccall((:SCIPexprgraphAddConst, libscip), SCIP_RETCODE, (Ptr{SCIP_EXPRGRAPH}, Cdouble, Ptr{Ptr{SCIP_EXPRGRAPHNODE}}), exprgraph, constant, constnode)
end

function SCIPexprgraphAddExprtreeSum(exprgraph, nexprtrees, exprtrees, coefs, rootnode, rootnodeisnew)
    ccall((:SCIPexprgraphAddExprtreeSum, libscip), SCIP_RETCODE, (Ptr{SCIP_EXPRGRAPH}, Cint, Ptr{Ptr{SCIP_EXPRTREE}}, Ptr{Cdouble}, Ptr{Ptr{SCIP_EXPRGRAPHNODE}}, Ptr{UInt32}), exprgraph, nexprtrees, exprtrees, coefs, rootnode, rootnodeisnew)
end

function SCIPexprgraphReplaceVarByLinearSum(exprgraph, var, ncoefs, coefs, vars, constant)
    ccall((:SCIPexprgraphReplaceVarByLinearSum, libscip), SCIP_RETCODE, (Ptr{SCIP_EXPRGRAPH}, Ptr{Cvoid}, Cint, Ptr{Cdouble}, Ptr{Ptr{Cvoid}}, Cdouble), exprgraph, var, ncoefs, coefs, vars, constant)
end

function SCIPexprgraphFindVarNode(exprgraph, var, varnode)
    ccall((:SCIPexprgraphFindVarNode, libscip), UInt32, (Ptr{SCIP_EXPRGRAPH}, Ptr{Cvoid}, Ptr{Ptr{SCIP_EXPRGRAPHNODE}}), exprgraph, var, varnode)
end

function SCIPexprgraphFindConstNode(exprgraph, constant, constnode)
    ccall((:SCIPexprgraphFindConstNode, libscip), UInt32, (Ptr{SCIP_EXPRGRAPH}, Cdouble, Ptr{Ptr{SCIP_EXPRGRAPHNODE}}), exprgraph, constant, constnode)
end

function SCIPexprgraphPrintDot(exprgraph, messagehdlr, file, varnames)
    ccall((:SCIPexprgraphPrintDot, libscip), SCIP_RETCODE, (Ptr{SCIP_EXPRGRAPH}, Ptr{SCIP_MESSAGEHDLR}, Ptr{FILE}, Ptr{Cstring}), exprgraph, messagehdlr, file, varnames)
end

function SCIPexprgraphEval(exprgraph, varvals)
    ccall((:SCIPexprgraphEval, libscip), SCIP_RETCODE, (Ptr{SCIP_EXPRGRAPH}, Ptr{Cdouble}), exprgraph, varvals)
end

function SCIPexprgraphPropagateVarBounds(exprgraph, infinity, clearreverseprop, domainerror)
    ccall((:SCIPexprgraphPropagateVarBounds, libscip), SCIP_RETCODE, (Ptr{SCIP_EXPRGRAPH}, Cdouble, UInt32, Ptr{UInt32}), exprgraph, infinity, clearreverseprop, domainerror)
end

function SCIPexprgraphPropagateNodeBounds(exprgraph, infinity, minstrength, cutoff)
    ccall((:SCIPexprgraphPropagateNodeBounds, libscip), Cvoid, (Ptr{SCIP_EXPRGRAPH}, Cdouble, Cdouble, Ptr{UInt32}), exprgraph, infinity, minstrength, cutoff)
end

function SCIPexprgraphCheckCurvature(exprgraph, infinity, clearreverseprop)
    ccall((:SCIPexprgraphCheckCurvature, libscip), SCIP_RETCODE, (Ptr{SCIP_EXPRGRAPH}, Cdouble, UInt32), exprgraph, infinity, clearreverseprop)
end

function SCIPexprgraphSimplify(exprgraph, messagehdlr, eps, maxexpansionexponent, havechange, domainerror)
    ccall((:SCIPexprgraphSimplify, libscip), SCIP_RETCODE, (Ptr{SCIP_EXPRGRAPH}, Ptr{SCIP_MESSAGEHDLR}, Cdouble, Cint, Ptr{UInt32}, Ptr{UInt32}), exprgraph, messagehdlr, eps, maxexpansionexponent, havechange, domainerror)
end

function SCIPexprgraphGetTree(exprgraph, rootnode, exprtree)
    ccall((:SCIPexprgraphGetTree, libscip), SCIP_RETCODE, (Ptr{SCIP_EXPRGRAPH}, Ptr{SCIP_EXPRGRAPHNODE}, Ptr{Ptr{SCIP_EXPRTREE}}), exprgraph, rootnode, exprtree)
end

function SCIPexprgraphGetSeparableTrees(exprgraph, node, exprtreessize, nexprtrees, exprtrees, exprtreecoefs)
    ccall((:SCIPexprgraphGetSeparableTrees, libscip), SCIP_RETCODE, (Ptr{SCIP_EXPRGRAPH}, Ptr{SCIP_EXPRGRAPHNODE}, Cint, Ptr{Cint}, Ptr{Ptr{SCIP_EXPRTREE}}, Ptr{Cdouble}), exprgraph, node, exprtreessize, nexprtrees, exprtrees, exprtreecoefs)
end

function SCIPexprgraphGetSubtreeVarsUsage(exprgraph, node, varsusage)
    ccall((:SCIPexprgraphGetSubtreeVarsUsage, libscip), Cvoid, (Ptr{SCIP_EXPRGRAPH}, Ptr{SCIP_EXPRGRAPHNODE}, Ptr{Cint}), exprgraph, node, varsusage)
end

function SCIPexprgraphGetSumTreesNSummands(node)
    ccall((:SCIPexprgraphGetSumTreesNSummands, libscip), Cint, (Ptr{SCIP_EXPRGRAPHNODE},), node)
end

function SCIPexprgraphGetSumTrees(exprgraph, node, exprtreessize, nexprtrees, exprtrees, exprtreecoefs)
    ccall((:SCIPexprgraphGetSumTrees, libscip), SCIP_RETCODE, (Ptr{SCIP_EXPRGRAPH}, Ptr{SCIP_EXPRGRAPHNODE}, Cint, Ptr{Cint}, Ptr{Ptr{SCIP_EXPRTREE}}, Ptr{Cdouble}), exprgraph, node, exprtreessize, nexprtrees, exprtrees, exprtreecoefs)
end


text:
using Flux, Test, Random, Statistics
using Random

Random.seed!(0)

# So we can use the system CuArrays
insert!(LOAD_PATH, 2, "@v#.#")

@testset "Flux" begin

@info "Testing Basics"

include("utils.jl")
include("onehot.jl")
include("optimise.jl")
include("data.jl")

@info "Testing Layers"

include("layers/basic.jl")
include("layers/normalisation.jl")
include("layers/stateless.jl")
include("layers/conv.jl")

@info "Running Gradient Checks"

include("tracker.jl")

if Base.find_package("CuArrays") != nothing
  include("cuda/cuda.jl")
end

end

ext: jl


text:
using JSON
using JuMP, Ipopt

function read_json_file(fname)
    #TODO: write description
    dict2 = Dict()
    open(fname, "r") do f
        dicttxt = read(f, String)
        dict2 = JSON.parse(dicttxt)
    end
    return dict2
end

function read_nx_file(fname, flow)
    #TODO: write description
    G_dict = read_json_file(fname)
    G = Dict()
    nodes = []
    for edge in G_dict["links"]
        s = string(edge["source"])
        t = string(edge["target"])
        G[(s,t)] = Dict()
        push!(nodes, s)
        push!(nodes, t)
        nodes = unique(nodes)

        G[(s,t)]["source"] = s
        G[(s,t)]["target"] = t

        if flow == 0
            for att in ["capacity", "length", "t_0"]
                G[(s,t)][att] = edge[att]

            end
        else
            for att in ["capacity", "length", "t_0", "flow"]
                G[(s,t)][att] = edge[att]
            end
        end
    end
    return G, sort(nodes)

end

function read_fcoeffs(fname)
    #TODO: write description
    return read_json_file(fname)
end

function read_g(fname)
    #TODO: write description
    g_dict = Dict()
    dict2 = read_json_file(fname)
    for od in keys(dict2)
        a = split(split(split(od, "(")[2],")")[1],",")
        g_dict[(a[1], a[2][2:end])] = dict2[od]
    end
    return g_dict
end

function dict2json(dict, fname)
    json_string = JSON.json(dict)
    open(fname,"w") do f
        write(f, json_string)
    end
end

function get_incoming_edges(G, i)
    a = []
    a = unique([if G[k]["target"]==i G[k]["source"] else 0 end for k in keys(G)])
    filter!(x->x≠0,a)
    return a
end

function get_outgoing_edges(G, i)
    a = []
    a = unique([if G[k]["source"]==i G[k]["target"] else 0 end for k in keys(G)])
    filter!(x->x≠0,a)
    return a
end

function add_demand_cnstr(model,G,g,xc,nodes)
    od_pairs = keys(g)
    links = keys(G)
    for j in nodes
        for od in od_pairs
            if od[1] == j
                @constraint(m, sum(xc[od][(i,j)] for i in get_incoming_edges(G, j)) + g[od] == sum(xc[od][(j,i)] for i in get_outgoing_edges(G, j)) )
            elseif od[2] == j
                @constraint(m, sum(xc[od][(i,j)] for i in get_incoming_edges(G, j)) == g[od] + sum(xc[od][(j,i)] for i in get_outgoing_edges(G, j)) )
            else
                @constraint(m, sum(xc[od][(i,j)] for i in get_incoming_edges(G, j)) == sum(xc[od][(j,i)] for i in get_outgoing_edges(G, j)) )
            end
        end
    end
end

function add_rebalancing_cnstr(m,G,xc,xr,nodes)
    od_pairs = keys(g)
    @constraint(m, [j in nodes], sum(xr[(i,j)] + sum(xc[od][(i,j)] for od in od_pairs) for i in get_incoming_edges(G, j)) == sum(xr[(j,k)] + sum(xc[od][(j,k)] for od in od_pairs) for k in get_outgoing_edges(G, j)))
end

function define_xc_vars(od_pairs, links)
    xc = Dict()
    for od in od_pairs
        xc[od] = Dict()
        for link in links
            xc[od][link] = @variable(m, lower_bound=0)
            set_name(xc[od][link], string("xc-(",od[1],",",od[2],")-(",link[1],",",link[2],")"))
        end
    end
    return xc
end

function define_xr_vars(links)
    xr = Dict()
    for link in links
        xr[link] = @variable(m, lower_bound=0)
        set_name(xr[link], string("xr-(",link[1],",",link[2],")"))
    end
    return xr
end

function sol2dict(m, G, xc, od_pairs, links)
    dict = Dict()
    for link in links
        flow = 0
        for od in od_pairs
            var = string("xc-(",od[1],",",od[2],")-(",link[1],",",link[2],")")
            flow +=  value(variable_by_name(m, var))
        end
        #reb_var = value(variable_by_name(m, string("xr-(",link[1],",",link[2],")")))
        dict[link] = Dict()
        dict[link]["flow"] = flow
       # dict[link]["flowNoRebalancing"] = flow - reb_var
    end
    return dict
end

function export_results(m, G, xc, od_pairs, links, fname)
    dict = sol2dict(m, G, xc, od_pairs, links)
    dict2json(dict, fname)

end

function print_sol(m, xc, od_pairs, links, flag=1)
    if flag == 1
        for od in od_pairs
            xc[od] = Dict()
            for link in links
                var = string("xc-(",od[1],",",od[2],")-(",link[1],",",link[2],")")
                println(var, "= ", value(variable_by_name(m, var)))
            end
        end

        for link in links
            var =
            println(value(variable_by_name(m, string("xr-(",link[1],",",link[2],")"))))
        end
    else
        return 0
    end
end

G, nodes = read_nx_file("tmp/G.json", 0)
G, nodes = read_nx_file("tmp/G_supergraph.json", 0)
G_exogenous, nodes_ex = read_nx_file("tmp/exogenous_G.json", 1)
#G_exogenous = "False"
fcoeffs = read_fcoeffs("tmp/fcoeffs.json")
g = read_g("tmp/g.json")
out_file = "tmp/out.json"

od_pairs = keys(g)
links = keys(G)
N = length(fcoeffs)

m = Model(with_optimizer(Ipopt.Optimizer))

# Define variables
xc = define_xc_vars(od_pairs, links)
#xr = define_xr_vars(links)

# Define sum od flow
x = Dict()
for link in links
    x[link] = @NLexpression(m, sum(xc[od][link] for od in od_pairs))
end

## Define Objective
@NLobjective(m, Min, sum( (x[link]+G_exogenous[link]["flow"])* G[link]["t_0"]* sum( fcoeffs[n]*((x[link] + G_exogenous[link]["flow"])/G[link]["capacity"])^(n-1) for n=1:N ) for link in links))

## Define Constraints
add_demand_cnstr(m, G, g, xc, nodes)
#add_rebalancing_cnstr(m, G, xc, xr, nodes)

optimize!(m)

export_results(m, G, xc, od_pairs, links, out_file)

#print_sol(m, xc, xr, od_pairs, links, 1)


text:
# Autogenerated wrapper script for Qt5Charts_jll for x86_64-w64-mingw32-cxx03
export charts, libqt5charts

using Qt5Declarative_jll
JLLWrappers.@generate_wrapper_header("Qt5Charts")
JLLWrappers.@declare_file_product(charts)
JLLWrappers.@declare_library_product(libqt5charts, "Qt5Charts.dll")
function __init__()
    JLLWrappers.@generate_init_header(Qt5Declarative_jll)
    JLLWrappers.@init_file_product(
        charts,
        "qml\\QtCharts",
    )

    JLLWrappers.@init_library_product(
        libqt5charts,
        "bin\\Qt5Charts.dll",
        RTLD_LAZY | RTLD_DEEPBIND,
    )

    JLLWrappers.@generate_init_footer()
end  # __init__()


text:
export hadamard_test, hadamard_test_circuit, swap_test_circuit

"""
see WiKi.
"""
function hadamard_test_circuit(U::AbstractBlock{N}, ϕ::Real) where N
    chain(N+1, put(N+1, 1=>H),
        put(N+1, 1=>Rz(ϕ)),
        control(N+1, 1, 2:N+1=>U),  # get matrix first, very inefficient
        put(N+1, 1=>H)
        )
end

function hadamard_test(U::AbstractBlock{N}, reg::AbstractRegister, ϕ::Real) where N
    c = hadamard_test_circuit(U, ϕ::Real)
    reg = join(reg, zero_state(1))
    expect(put(N+1, 1=>Z), reg |> c)
end

"""
Estimation of overlap between multiple density matrices.

PRL 88.217901
"""
function swap_test_circuit(nbit::Int, nstate::Int, ϕ::Real)
    N = nstate*nbit + 1

    chain(N, put(N, 1=>H),
        put(N, 1=>Rz(ϕ)),
        chain(N, [chain(N, [control(N, 1, (i+(k*nbit-nbit)+1, i+k*nbit+1)=>SWAP) for i=1:nbit]) for k=1:nstate-1]),  # get matrix first, very inefficient
        put(N, 1=>H)
        )
end


text:
using ShortCodes
using Test

@testset "Kroki tests" begin
    @test ShortCodes.kroki("digraph G {Hello->World}") == "https://kroki.io/graphviz/svg/eJxLyUwvSizIUHBXqPZIzcnJ17ULzy_KSakFAGxACMY="
end

@testset "DOI tests"  begin
    julia = DOI("10.1137/141000671")

    @test julia.doi == "10.1137/141000671"
    @test ShortDOI(julia).shortdoi == "10/f9wkpj"
    @test length(split(julia.author,";")) == 4
    @test julia.year == 2017

    emjulia = EmDOI(julia, "Stefan Karpinski")
    @test emjulia.highlight == "Stefan Karpinski"
    io = IOBuffer()
    show(io, MIME("text/html"), emjulia)
    @test findfirst("<b>", String(take!(io)) ) == 37:39
end


text:
# TODO: there should be a distinction between an object that will manage a full plot, vs a component of a plot.
# the PlotRecipe as currently implemented is more of a "custom component"
# a recipe should fully describe the plotting command(s) and call them, likewise for updating.
#   actually... maybe those should explicitly derive from AbstractPlot???

abstract PlotRecipe

getRecipeXY(recipe::PlotRecipe) = Float64[], Float64[]
getRecipeArgs(recipe::PlotRecipe) = ()

plot(recipe::PlotRecipe, args...; kw...) = plot(getRecipeXY(recipe)..., args...; getRecipeArgs(recipe)..., kw...)
plot!(recipe::PlotRecipe, args...; kw...) = plot!(getRecipeXY(recipe)..., args...; getRecipeArgs(recipe)..., kw...)
plot!(plt::Plot, recipe::PlotRecipe, args...; kw...) = plot!(getRecipeXY(recipe)..., args...; getRecipeArgs(recipe)..., kw...)

num_series(x::AMat) = size(x,2)
num_series(x) = 1

# _apply_recipe(d::KW, kw::KW) = ()

# if it's not a recipe, just do nothing and return the args
function RecipesBase.apply_recipe(d::KW, kw::KW, args...; issubplot=false)
    if issubplot && !isempty(args) && !haskey(d, :n) && !haskey(d, :layout)
        # put in a sensible default
        d[:n] = maximum(map(num_series, args))
    end
    args
end

# macro kw(k, v)
#     esc(:(get!(d, $k, $v)))
# end
#
# function _is_arrow_tuple(expr::Expr)
#     expr.head == :tuple &&
#         isa(expr.args[1], Expr) &&
#         expr.args[1].head == :(-->)
# end
#
# function _equals_symbol(arg::Symbol, sym::Symbol)
#     arg == sym
# end
# function _equals_symbol(arg::Expr, sym::Symbol)
#     arg.head == :quote && arg.args[1] == sym
# end
#
# # TODO: when this is moved out of Plots, also move the replacement of key aliases to just after the _apply_recipe calls
# function replace_recipe_arrows!(expr::Expr)
#     for (i,e) in enumerate(expr.args)
#         if isa(e,Expr)
#
#             # process trailing flags, like:
#             #   a --> b, :quiet, :force
#             quiet, require, force = false, false, false
#             if _is_arrow_tuple(e)
#                 for flag in e.args
#                     if _equals_symbol(flag, :quiet)
#                         quiet = true
#                     elseif _equals_symbol(flag, :require)
#                         require = true
#                     elseif _equals_symbol(flag, :force)
#                         force = true
#                     end
#                 end
#                 e = e.args[1]
#             end
#
#             # we are going to recursively swap out `a --> b, flags...` commands
#             if e.head == :(-->)
#                 k, v = e.args
#                 keyexpr = :(get(Plots._keyAliases, $k, $k))
#
#                 set_expr = if force
#                     # forced override user settings
#                     :(d[$keyexpr] = $v)
#                 else
#                     # if the user has set this keyword, use theirs
#                     :(get!(d, $keyexpr, $v))
#                 end
#
#                 expr.args[i] = if quiet
#                     # quietly ignore keywords which are not supported
#                     :($keyexpr in supportedArgs() ? $set_expr : nothing)
#                 elseif require
#                     # error when not supported by the backend
#                     :($keyexpr in supportedArgs() ? $set_expr : error("In recipe: required keyword ", $k, " is not supported by backend $(backend_name())"))
#                 else
#                     set_expr
#                 end
#
#                 # @show quiet, force, expr.args[i]
#
#             elseif e.head != :call
#                 # we want to recursively replace the arrows, but not inside function calls
#                 # as this might include things like Dict(1=>2)
#                 replace_recipe_arrows!(e)
#             end
#         end
#     end
# end
#
#
# macro recipe(funcexpr::Expr)
#     lhs, body = funcexpr.args
#
#     if !(funcexpr.head in (:(=), :function))
#         error("Must wrap a valid function call!")
#     end
#     if !(isa(lhs, Expr) && lhs.head == :call)
#         error("Expected `lhs = ...` with lhs as a call Expr... got: $lhs")
#     end
#
#     # for parametric definitions, take the "curly" expression and add the func
#     front = lhs.args[1]
#     func = :(Plots._apply_recipe)
#     if isa(front, Expr) && front.head == :curly
#         front.args[1] = func
#         func = front
#     end
#
#     # get the arg list, stripping out any keyword parameters into a
#     # bunch of get!(kw, key, value) lines
#     args = lhs.args[2:end]
#     kw_body = Expr(:block)
#     if isa(args[1], Expr) && args[1].head == :parameters
#         for kwpair in args[1].args
#             k, v = kwpair.args
#             push!(kw_body.args, :(get!(kw, $(QuoteNode(k)), $v)))
#         end
#         args = args[2:end]
#     end
#
#     # replace all the key => value lines with argument setting logic
#     replace_recipe_arrows!(body)
#
#     # now build a function definition for _apply_recipe, wrapping the return value in a tuple if needed
#     esc(quote
#         function $func(d::KW, kw::KW, $(args...); issubplot=false)
#             $kw_body
#             ret = $body
#             if typeof(ret) <: Tuple
#                 ret
#             else
#                 (ret,)
#             end
#         end
#     end)
# end
#

# ---------------------------------------------------------------------------

"""
`apply_series_recipe` should take a processed series KW dict and break it up
into component parts.  For example, a box plot is made up of `shape` for the
boxes, `path` for the lines, and `scatter` for the outliers.

Returns a Vector{KW}.
"""
apply_series_recipe(d::KW, lt) = KW[d]

# ---------------------------------------------------------------------------
# Box Plot

const _box_halfwidth = 0.4

function apply_series_recipe(d::KW, ::Type{Val{:box}})
    # dumpdict(d, "box before", true)
    # TODO: add scatter series with outliers

    # create a list of shapes, where each shape is a single boxplot
    shapes = Shape[]
    d[:linetype] = :shape
    groupby = extractGroupArgs(d[:x])

    for (i, glabel) in enumerate(groupby.groupLabels)

        # filter y values, then compute quantiles
        q1,q2,q3,q4,q5 = quantile(d[:y][groupby.groupIds[i]], linspace(0,1,5))

        # make the shape
        l, m, r = i - _box_halfwidth, i, i + _box_halfwidth
        xcoords = [
            m, l, r, m, m, NaN,         # lower T
            l, l, r, r, l, NaN,         # lower box
            l, l, r, r, l, NaN,         # upper box
            m, l, r, m, m               # upper T
        ]
        ycoords = [
            q1, q1, q1, q1, q2, NaN,    # lower T
            q2, q3, q3, q2, q2, NaN,    # lower box
            q4, q3, q3, q4, q4, NaN,    # upper box
            q5, q5, q5, q5, q4, NaN,    # upper T
        ]
        push!(shapes, Shape(xcoords, ycoords))
    end

    d[:x], d[:y] = shape_coords(shapes)
    d[:plotarg_overrides] = KW(:xticks => (1:length(shapes), groupby.groupLabels))

    KW[d]
end

# ---------------------------------------------------------------------------
# Violin Plot

# if the user has KernelDensity installed, use this for violin plots.
# otherwise, just use a histogram
try
    Pkg.installed("KernelDensity")
    import KernelDensity

    # warn("using KD for violin")
    @eval function violin_coords(y)
        kd = KernelDensity.kde(y, npoints = 30)
        kd.density, kd.x
    end
catch
    # warn("using hist for violin")
    @eval function violin_coords(y)
        edges, widths = hist(y, 20)
        centers = 0.5 * (edges[1:end-1] + edges[2:end])
        ymin, ymax = extrema(y)
        vcat(0.0, widths, 0.0), vcat(ymin, centers, ymax)
    end
end

function apply_series_recipe(d::KW, ::Type{Val{:violin}})
    # dumpdict(d, "box before", true)
    # TODO: add scatter series with outliers

    # create a list of shapes, where each shape is a single boxplot
    shapes = Shape[]
    d[:linetype] = :shape
    groupby = extractGroupArgs(d[:x])

    for (i, glabel) in enumerate(groupby.groupLabels)

        # get the edges and widths
        y = d[:y][groupby.groupIds[i]]
        widths, centers = violin_coords(y)

        # normalize
        widths = _box_halfwidth * widths / maximum(widths)

        # make the violin
        xcoords = vcat(widths, -reverse(widths)) + i
        ycoords = vcat(centers, reverse(centers))
        push!(shapes, Shape(xcoords, ycoords))
    end

    d[:x], d[:y] = shape_coords(shapes)
    d[:plotarg_overrides] = KW(:xticks => (1:length(shapes), groupby.groupLabels))

    KW[d]
end

# ---------------------------------------------------------------------------
# Error Bars

function error_style!(d::KW)
    d[:linetype] = :path
    d[:linecolor] = d[:markerstrokecolor]
    d[:linewidth] = d[:markerstrokewidth]
    d[:label] = ""
end

# if we're passed a tuple of vectors, convert to a vector of tuples
function error_zipit(ebar)
    if istuple(ebar)
        collect(zip(ebar...))
    else
        ebar
    end
end

function error_coords(xorig, yorig, ebar)
    # init empty x/y, and zip errors if passed Tuple{Vector,Vector}
    x, y = zeros(0), zeros(0)

    # for each point, create a line segment from the bottom to the top of the errorbar
    for i = 1:max(length(xorig), length(yorig))
        xi = get_mod(xorig, i)
        yi = get_mod(yorig, i)
        ebi = get_mod(ebar, i)
        nanappend!(x, [xi, xi])
        e1, e2 = if istuple(ebi)
            first(ebi), last(ebi)
        elseif isscalar(ebi)
            ebi, ebi
        else
            error("unexpected ebi type $(typeof(ebi)) for errorbar: $ebi")
        end
        nanappend!(y, [yi - e1, yi + e2])
    end
    x, y
end

# we will create a series of path segments, where each point represents one
# side of an errorbar
function apply_series_recipe(d::KW, ::Type{Val{:yerror}})
    error_style!(d)
    d[:markershape] = :hline
    d[:x], d[:y] = error_coords(d[:x], d[:y], error_zipit(d[:yerror]))
    KW[d]
end

function apply_series_recipe(d::KW, ::Type{Val{:xerror}})
    error_style!(d)
    d[:markershape] = :vline
    d[:y], d[:x] = error_coords(d[:y], d[:x], error_zipit(d[:xerror]))
    KW[d]
end

# ---------------------------------------------------------------------------
# quiver

# function apply_series_recipe(d::KW, ::Type{Val{:quiver}})
#     d[:label] = ""
#     d[:linetype] = :scatter
#
#     # create a second series to draw the arrow shaft
#     dpath = copy(d)
#     error_style!(dpath)
#     dpath[:markershape] = :none
#
#     velocity = error_zipit(d[:quiver])
#     xorig, yorig = d[:x], d[:y]
#
#     # for each point, we create an arrow of velocity vi, translated to the x/y coordinates
#     # x, y = zeros(0), zeros(0)
#     paths = P2[]
#     arrows = P2[]
#     arrowshapes = Shape[]
#     for i = 1:max(length(xorig), length(yorig))
#
#         # get the starting position
#         xi = get_mod(xorig, i)
#         yi = get_mod(yorig, i)
#         p = P2(xi, yi)
#
#         # get the velocity
#         vi = get_mod(velocity, i)
#         vx, vy = if istuple(vi)
#             first(vi), last(vi)
#         elseif isscalar(vi)
#             vi, vi
#         else
#             error("unexpected vi type $(typeof(vi)) for quiver: $vi")
#         end
#         v = P2(vx, vy)
#
#         nanappend!(paths, [p, p+v])
#         push!(arrows, p+v)
#         push!(arrowshapes, makearrowhead(compute_angle(v)))
#
#         # # dist = sqrt(vx^2 + vy^2)
#         # dist = norm(v)
#         # arrow_h = 0.1dist          # height of arrowhead
#         # arrow_w = 0.5arrow_h       # halfwidth of arrowhead
#         # U1 = v ./ dist             # vector of arrowhead height
#         # U2 = P2(-U1[2], U1[1])     # vector of arrowhead halfwidth
#         # U1 *= arrow_h
#         # U2 *= arrow_w
#         #
#         # append!(pts, P2(xi, yi) .+ P2[(0,0), v-U1, v-U1+U2, v, v-U1-U2, v-U1, (NaN,NaN)])
#         # # a1 = v - arrow_h * U1 + arrow_w * U2
#         # # a2 = v - arrow_h * U1 - arrow_w * U2
#         # # nanappend!(x, xi + [0.0, vx, a1[1], a2[1], vx])
#         # # nanappend!(y, yi + [0.0, vy, a1[2], a2[2], vy])
#     end
#
#     # d[:x], d[:y] = Plots.unzip(pts)
#     dpath[:x], dpath[:y] = Plots.unzip(paths)
#     d[:x], d[:y] = Plots.unzip(arrows)
#     d[:markershape] = arrowshapes
#
#     KW[dpath, d]
# end

function apply_series_recipe(d::KW, ::Type{Val{:quiver}})
    d[:label] = ""
    d[:linetype] = :shape

    velocity = error_zipit(d[:quiver])
    xorig, yorig = d[:x], d[:y]

    # for each point, we create an arrow of velocity vi, translated to the x/y coordinates
    pts = P2[]
    for i = 1:max(length(xorig), length(yorig))

        # get the starting position
        xi = get_mod(xorig, i)
        yi = get_mod(yorig, i)
        p = P2(xi, yi)

        # get the velocity
        vi = get_mod(velocity, i)
        vx, vy = if istuple(vi)
            first(vi), last(vi)
        elseif isscalar(vi)
            vi, vi
        elseif isa(vi,Function)
            vi(xi, yi)
        else
            error("unexpected vi type $(typeof(vi)) for quiver: $vi")
        end
        v = P2(vx, vy)

        dist = norm(v)
        arrow_h = 0.1dist          # height of arrowhead
        arrow_w = 0.5arrow_h       # halfwidth of arrowhead
        U1 = v ./ dist             # vector of arrowhead height
        U2 = P2(-U1[2], U1[1])     # vector of arrowhead halfwidth
        U1 *= arrow_h
        U2 *= arrow_w

        ppv = p+v
        nanappend!(pts, P2[p, ppv-U1, ppv-U1+U2, ppv, ppv-U1-U2, ppv-U1])
    end

    d[:x], d[:y] = Plots.unzip(pts[2:end])
    KW[d]
end

# ---------------------------------------------------------------------------
# ---------------------------------------------------------------------------
# ---------------------------------------------------------------------------

function rotate(x::Real, y::Real, θ::Real; center = (0,0))
  cx = x - center[1]
  cy = y - center[2]
  xrot = cx * cos(θ) - cy * sin(θ)
  yrot = cy * cos(θ) + cx * sin(θ)
  xrot + center[1], yrot + center[2]
end

# ---------------------------------------------------------------------------

type EllipseRecipe <: PlotRecipe
  w::Float64
  h::Float64
  x::Float64
  y::Float64
  θ::Float64
end
EllipseRecipe(w,h,x,y) = EllipseRecipe(w,h,x,y,0)

# return x,y coords of a rotated ellipse, centered at the origin
function rotatedEllipse(w, h, x, y, θ, rotθ)
  # # coord before rotation
  xpre = w * cos(θ)
  ypre = h * sin(θ)

  # rotate and translate
  r = rotate(xpre, ypre, rotθ)
  x + r[1], y + r[2]
end

function getRecipeXY(ep::EllipseRecipe)
  x, y = unzip([rotatedEllipse(ep.w, ep.h, ep.x, ep.y, u, ep.θ) for u in linspace(0,2π,100)])
  top = rotate(0, ep.h, ep.θ)
  right = rotate(ep.w, 0, ep.θ)
  linex = Float64[top[1], 0, right[1]] + ep.x
  liney = Float64[top[2], 0, right[2]] + ep.y
  Any[x, linex], Any[y, liney]
end

function getRecipeArgs(ep::EllipseRecipe)
  [(:line, (3, [:dot :solid], [:red :blue], :path))]
end

# # -------------------------------------------------

"Sparsity plot... heatmap of non-zero values of a matrix"
function spy{T<:Real}(z::AMat{T}; kw...)
    mat = map(zi->float(zi!=0), z)'
    xn, yn = size(mat)
    heatmap(mat; leg=false, yflip=true, aspect_ratio=:equal,
        xlim=(0.5, xn+0.5), ylim=(0.5, yn+0.5),
        kw...)
end

"Adds a+bx... straight line over the current plot"
function abline!(plt::Plot, a, b; kw...)
    plot!(plt, [extrema(plt)...], x -> b + a*x; kw...)
end

abline!(args...; kw...) = abline!(current(), args...; kw...)

# =================================================
# Arc and chord diagrams

"Takes an adjacency matrix and returns source, destiny and weight lists"
function mat2list{T}(mat::AbstractArray{T,2})
    nrow, ncol = size(mat) # rows are sources and columns are destinies

    nosymmetric = !issym(mat) # plots only triu for symmetric matrices
    nosparse = !issparse(mat) # doesn't plot zeros from a sparse matrix

    L = length(mat)

    source  = Array(Int, L)
    destiny = Array(Int, L)
    weight  = Array(T, L)

    idx = 1
    for i in 1:nrow, j in 1:ncol
        value = mat[i, j]
        if !isnan(value) && ( nosparse || value != zero(T) ) # TODO: deal with Nullable

            if i < j
                source[idx]  = i
                destiny[idx] = j
                weight[idx]  = value
                idx += 1
            elseif nosymmetric && (i > j)
                source[idx]  = i
                destiny[idx] = j
                weight[idx]  = value
                idx += 1
            end

        end
    end

    resize!(source, idx-1), resize!(destiny, idx-1), resize!(weight, idx-1)
end

# ---------------------------------------------------------------------------
# Arc Diagram

curvecolor(value, min, max, grad) = getColorZ(grad, (value-min)/(max-min))

"Plots a clockwise arc, from source to destiny, colored by weight"
function arc!(source, destiny, weight, min, max, grad)
    radius = (destiny - source) / 2
    arc = Plots.partialcircle(0, π, 30, radius)
    x, y = Plots.unzip(arc)
    plot!(x .+ radius .+ source,  y, line = (curvecolor(weight, min, max, grad), 0.5, 2), legend=false)
end

"""
`arcdiagram(source, destiny, weight[, grad])`

Plots an arc diagram, form `source` to `destiny` (clockwise), using `weight` to determine the colors.
"""
function arcdiagram(source, destiny, weight; kargs...)

    args = KW(kargs)
    grad = pop!(args, :grad,   ColorGradient([colorant"darkred", colorant"darkblue"]))

    if length(source) == length(destiny) == length(weight)

        vertices = unique(vcat(source, destiny))
        sort!(vertices)

        xmin, xmax = extrema(vertices)
        plot(xlim=(xmin - 0.5, xmax + 0.5), legend=false)

        wmin,wmax = extrema(weight)

        for (i, j, value) in zip(source,destiny,weight)
            arc!(i, j, value, wmin, wmax, grad)
        end

        scatter!(vertices, zeros(length(vertices)); legend=false, args...)

    else

        throw(ArgumentError("source, destiny and weight should have the same length"))

    end
end

"""
`arcdiagram(mat[, grad])`

Plots an arc diagram from an adjacency matrix, form rows to columns (clockwise),
using the values on the matrix as weights to determine the colors.
Doesn't show edges with value zero if the input is sparse.
For simmetric matrices, only the upper triangular values are used.
"""
arcdiagram{T}(mat::AbstractArray{T,2}; kargs...) = arcdiagram(mat2list(mat)...; kargs...)

# ---------------------------------------------------------------------------
# Chord diagram

arcshape(θ1, θ2) = Shape(vcat(Plots.partialcircle(θ1, θ2, 15, 1.1),
                            reverse(Plots.partialcircle(θ1, θ2, 15, 0.9))))

colorlist(grad, ::Void) = :darkgray

function colorlist(grad, z)
    zmin, zmax = extrema(z)
    RGBA{Float64}[getColorZ(grad, (zi-zmin)/(zmax-zmin)) for zi in z]'
end

"""
`chorddiagram(source, destiny, weight[, grad, zcolor, group])`

Plots a chord diagram, form `source` to `destiny`,
using `weight` to determine the edge colors using `grad`.
`zcolor` or `group` can be used to determine the node colors.
"""
function chorddiagram(source, destiny, weight; kargs...)

    args  = KW(kargs)
    grad  = pop!(args, :grad,   ColorGradient([colorant"darkred", colorant"darkblue"]))
    zcolor= pop!(args, :zcolor, nothing)
    group = pop!(args, :group,  nothing)

    if zcolor !== nothing && group !== nothing
        throw(ErrorException("group and zcolor can not be used together."))
    end

    if length(source) == length(destiny) == length(weight)

        plt = plot(xlim=(-2,2), ylim=(-2,2), legend=false, grid=false,
        xticks=nothing, yticks=nothing,
        xlim=(-1.2,1.2), ylim=(-1.2,1.2))

        nodemin, nodemax = extrema(vcat(source, destiny))

        weightmin, weightmax = extrema(weight)

        A  = 1.5π # Filled space
        B  = 0.5π # White space (empirical)

        Δα = A / nodemax
        Δβ = B / nodemax

        δ = Δα  + Δβ

        for i in 1:length(source)
            curve = BezierCurve(P2[ (cos((source[i ]-1)*δ + 0.5Δα), sin((source[i ]-1)*δ + 0.5Δα)), (0,0),
                                    (cos((destiny[i]-1)*δ + 0.5Δα), sin((destiny[i]-1)*δ + 0.5Δα)) ])
            plot!(curve_points(curve), line = (Plots.curvecolor(weight[i], weightmin, weightmax, grad), 1, 1))
        end

        if group === nothing
            c =  colorlist(grad, zcolor)
        elseif length(group) == nodemax

            idx = collect(0:(nodemax-1))

            for g in group
                plot!([arcshape(n*δ, n*δ + Δα) for n in idx[group .== g]]; args...)
            end

            return plt

        else
            throw(ErrorException("group should the ", nodemax, " elements."))
        end

        plot!([arcshape(n*δ, n*δ + Δα) for n in 0:(nodemax-1)]; mc=c, args...)

        return plt

    else
        throw(ArgumentError("source, destiny and weight should have the same length"))
    end
end

"""
`chorddiagram(mat[, grad, zcolor, group])`

Plots a chord diagram from an adjacency matrix,
using the values on the matrix as weights to determine edge colors.
Doesn't show edges with value zero if the input is sparse.
For simmetric matrices, only the upper triangular values are used.
`zcolor` or `group` can be used to determine the node colors.
"""
chorddiagram(mat::AbstractMatrix; kargs...) = chorddiagram(mat2list(mat)...; kargs...)


text:
"""
    example_constraints(X::AbstractUncertainIndexValueDataset,
        d_xinds = Uniform(0.5, 1.1), d_yinds = Uniform(0.9, 1.7))

Generate a set of random sampling constraints that can be used to constrain
the indices and values of an uncertain index-value dataset `X`. These are
generated as follows:

- `constraints_inds = TruncateStd(rand(d_xinds))`
- `constraints_vals = [TruncateQuantiles(0.5 - rand(d_xvals), 0.5 + rand(d_xvals)) for i = 1:length(X)];`

Returns the tuple (constraints_inds, constraints_vals).
"""
function example_constraints(X::AbstractUncertainIndexValueDataset,
        d_xinds = Uniform(0.5, 1.1), d_yinds = Uniform(0.9, 1.7))

    # Truncate indices at some fraction time their standard deviation around the man
    constraints_inds = TruncateStd(rand(d_xinds))

    # Truncate values at some percentile range
    constraints_vals = [TruncateQuantiles(0.5 - rand(d_xvals), 0.5 + rand(d_xvals)) for i = 1:length(X)];

    return (constraints_x_inds, constraints_vals)
end

"""
    example_constraints(X::AbstractUncertainIndexValueDataset,
        Y::AbstractUncertainIndexValueDataset;
        d_xinds = Uniform(0.5, 1.1), d_yinds = Uniform(0.9, 1.7),
        d_xvals = Uniform(0.05, 0.15), d_yvals = Uniform(0.3, 0.4))

Generate a set of random sampling constraints that can be used to constrain
the indices and values of two uncertain index-value datasets `X` and `Y`.
The constraints are generated as follows:

- `constraints_inds_x = TruncateStd(rand(d_xinds))`
- `constraints_inds_x = TruncateStd(rand(d_yinds))`
- `constraints_vals_x = [TruncateQuantiles(0.5 - rand(d_xvals), 0.5 + rand(d_xvals)) for i = 1:length(X)]`
- `constraints_vals_x = [TruncateQuantiles(0.5 - rand(d_yvals), 0.5 + rand(d_yvals)) for i = 1:length(Y)]`

Returns the tuple of tuples `((constraints_inds_x, constraints_vals_x), (constraints_inds_y, constraints_vals_y))`
"""
function example_constraints(X::AbstractUncertainIndexValueDataset,
        Y::AbstractUncertainIndexValueDataset;
        d_xinds = Uniform(0.5, 1.1), d_yinds = Uniform(0.9, 1.7),
        d_xvals = Uniform(0.05, 0.15), d_yvals = Uniform(0.3, 0.4))

    # Truncate indices at some fraction time their standard deviation around the man
    constraints_x_inds = TruncateStd(rand(d_xinds))
    constraints_y_inds = TruncateStd(rand(d_yinds))

    # Truncate values at some percentile range
    constraints_x_vals = [TruncateQuantiles(0.5 - rand(d_xvals), 0.5 + rand(d_xvals)) for i = 1:length(X)];
    constraints_y_vals = [TruncateQuantiles(0.5 - rand(d_yvals), 0.5 + rand(d_yvals)) for i = 1:length(Y)];
    cs_x = (constraints_x_inds, constraints_x_vals)
    cs_y = (constraints_y_inds, constraints_y_vals)

    cs_x, cs_y
end

export example_constraints


text:
# module for optimizing policy
# by value iteration
# considering belief distribution get narrow

using FreqTables, NamedArrays, LinearAlgebra, Distributions

include(joinpath(split(@__FILE__, "src")[1], "src/model/goal/goal.jl"))
include(joinpath(split(@__FILE__, "src")[1], "src/model/agent/puddle_ignore_agent.jl"))
include(joinpath(split(@__FILE__, "src")[1], "src/common/state_transition/state_transition.jl"))
include(joinpath(split(@__FILE__, "src")[1], "src/model/puddle/puddle.jl"))
include(joinpath(split(@__FILE__, "src")[1], "src/localization/extended_kalman_filter/extended_kalman_filter.jl"))
include(joinpath(split(@__FILE__, "src")[1], "src/model/sensor/sensor.jl"))

mutable struct BeliefDynamicProgramming
  pose_min
  pose_max
  widths
  goal
  index_nums
  indexes
  value_function
  is_final_state
  policy
  actions
  state_transition_probs
  depths
  delta_time
  puddle_coef
  dev_borders
  dev_borders_side
  motion_sigma_transition_probs
  obs_sigma_transition_probs

  # init
  function BeliefDynamicProgramming(widths, goal,
                                    puddles,
                                    delta_time,
                                    sampling_num,
                                    sensor;
                                    puddle_coef=100,
                                    lower_left=[-4.0, -4.0],
                                    upper_right=[4.0, 4.0],
                                    dev_borders=[0.1, 0.2, 0.4, 0.8])
    self = new()
    self.pose_min = [lower_left[1], lower_left[2], 0.0]
    self.pose_max = [upper_right[1], upper_right[2], 2*pi]
    self.widths = widths
    self.goal = goal

    index_nums_3d = round.(Int64, (self.pose_max - self.pose_min)./self.widths)
    self.index_nums = [index_nums_3d[1], index_nums_3d[2], index_nums_3d[3], length(dev_borders)]
    nx, ny, nt, nh = self.index_nums[1], self.index_nums[2], self.index_nums[3] , self.index_nums[4]
    self.indexes = vec(collect(Base.product(0:nx-1, 0:ny-1, 0:nt-1, 0:nh-1)))
    self.value_function, self.is_final_state = init_belief_value_function(self)

    self.policy = init_policy(self)
    actions_set = Set([Tuple(self.policy[i[1]+1, i[2]+1, i[3]+1, i[4]+1, :]) for i in self.indexes])
    self.actions = [a for a in actions_set]
    self.state_transition_probs = init_state_transition_probs(self, delta_time, sampling_num)
    self.policy = zeros(Tuple([self.index_nums[1], self.index_nums[2], self.index_nums[3], self.index_nums[4], 2]))

    self.delta_time = delta_time
    self.puddle_coef = puddle_coef

    self.dev_borders = dev_borders
    self.dev_borders_side = [dev_borders[1]/10, dev_borders[1], dev_borders[2], dev_borders[3], dev_borders[4], dev_borders[4]*10]
    self.motion_sigma_transition_probs = init_motion_sigma_transition_probs(self)

    self.obs_sigma_transition_probs = init_obs_sigma_transition_probs(self, sensor)

    self.depths = expected_depths(self, puddles)

    return self
  end
end

function expected_depths(self::BeliefDynamicProgramming,
                         puddles, sampling_num=100)
  depths = Dict()

  # x, y, sigma
  for index in collect(Base.product(0:self.index_nums[1]-1, 0:self.index_nums[2]-1, 0:self.index_nums[4]-1))
    pose = self.pose_min[1:2] + self.widths[1:2].*(index[1:2] .+ 0.5) # center of cell
    sigma = (self.dev_borders_side[index[3]+1] +self.dev_borders_side[index[3]+2])/2 # center of sigma
    belief = MvNormal(pose, (sigma^2).*Matrix{Float64}(I,2,2))

    depth_sum = 0.0
    for pos in [rand(belief, sampling_num)[:,i] for i in 1:sampling_num]
      depth_sum += sum([p.depth*inside(p, pos) for p in puddles])
    end

    depths[index] = depth_sum / sampling_num
  end

  return depths
end

function init_obs_sigma_transition_probs(self::BeliefDynamicProgramming, sensor)
  probs = Dict()

  for index in self.indexes
    pose = self.pose_min + self.widths.*(index[1:3] .+ 0.5)
    sigma = (self.dev_borders_side[index[4]+1] +self.dev_borders_side[index[4]+2])/2
    cov_mat = (sigma^2) .* Matrix{Float64}(I, 3, 3)

    # considering observation
    for d in data(sensor, pose)
      cov_mat = observation_update(self, d[2], cov_mat, sensor, pose)
    end

    probs[index] = Dict(cov_to_index(self, cov_mat) => 1.0)
  end

  return probs
end

function observation_update(self::BeliefDynamicProgramming,
                            landmark_id, cov_mat, sensor, pose)
  dist_dev_rate = 0.14 # sigma parameter of observed distance
  dir_dev = 0.05 # sigma parameter of observed direction

  H = mat_H(pose, sensor.map.objects[landmark_id].pose)
  est_z = observation_function(pose, sensor.map.objects[landmark_id].pose)
  Q = mat_Q(dist_dev_rate*est_z[1], dir_dev)
  K = cov_mat * H' * inv(Q + H*cov_mat*H')

  return (Matrix{Float64}(I, 3, 3) - K*H) * cov_mat
end

function depth_means(self::BeliefDynamicProgramming, puddles, sampling_num)
  # sampling
  dx = range(0, self.widths[1], length=sampling_num)
  dy = range(0, self.widths[2], length=sampling_num)
  samples = vec(collect(Base.product(dx, dy)))

  # mean of depth at each cell
  tmp = zeros(Tuple([self.index_nums[1], self.index_nums[2]]))
  for xy in collect(Base.product(0:self.index_nums[1]-1, 0:self.index_nums[2]-1))
    for s in samples
      center = self.pose_min + self.widths.*[xy[1], xy[2], 0] + [s[1], s[2], 0]
      for p in puddles
        tmp[xy[1]+1, xy[2]+1] += p.depth * inside(p, center)
      end
    end
    tmp[xy[1]+1, xy[2]+1] /= sampling_num^2
  end

  return tmp
end

function init_motion_sigma_transition_probs(self::BeliefDynamicProgramming)
  probs = Dict()

  for a in self.actions
    for i in 0:length(self.dev_borders)
      probs[i, a] = calc_motion_sigma_transition_probs(self,
                                                       self.dev_borders_side[i+1],
                                                       self.dev_borders_side[i+2],
                                                       a)
    end
  end

  return probs
end

function cov_to_index(self::BeliefDynamicProgramming, cov)
  sigma = det(cov)^(1.0/6)

  for (i, e) in enumerate(self.dev_borders)
    if sigma < e
      return i-1
    end
  end

  return length(self.dev_borders)-1
end

function calc_motion_sigma_transition_probs(self::BeliefDynamicProgramming,
                                            min_sigma, max_sigma, action;
                                            sampling_num=100)
  speed, yaw_rate = action[1], action[2]
  if abs(yaw_rate) < 1e-5
    yaw_rate = 1e-5
  end

  F = mat_F(speed, yaw_rate, self.delta_time, 0.0)
  M = mat_M(speed, yaw_rate, self.delta_time, Dict("nn"=>0.20, "no"=>0.001, "on"=>0.11, "oo"=>0.20))
  A = mat_A(speed, yaw_rate, self.delta_time, 0.0)

  ans = Dict()
  for sigma in range(min_sigma, max_sigma*0.999, length=sampling_num)
    index_after = cov_to_index(self, (sigma^2).*F*F+A*M*A')
    if haskey(ans, index_after) == false
      ans[index_after] = 1
    else
      ans[index_after] += 1
    end
  end

  # convert from frequency to probability
  for e in ans
    ans[e[1]] /= sampling_num
  end

  return ans
end

function init_state_transition_probs(self::BeliefDynamicProgramming, delta_time, sampling_num)
  # sampling
  dx = range(0.001, self.widths[1]*0.999, length=sampling_num)
  dy = range(0.001, self.widths[2]*0.999, length=sampling_num)
  dt = range(0.001, self.widths[3]*0.999, length=sampling_num)
  samples = vec(collect(Base.product(dx, dy, dt)))

  # move sampled points and record delta index
  tmp = Dict()
  for a in self.actions
    for i_t in 0:self.index_nums[3]-1
      transition = []
      for s in samples
        # before transition
        before_pose = [s[1], s[2], s[3] + i_t*self.widths[3]] + self.pose_min
        before_index = [1, 1, i_t+1]

        # after transition
        after_pose = state_transition(a[1], a[2], delta_time, before_pose)
        after_index = get_index(self, after_pose)

        # index difference
        push!(transition, after_index-before_index)
      end
      # frequency of each index difference
      freq_tbl = freqtable(transition)
      freqs = [value for (name, value) in enumerate(freq_tbl)]
      diffs = [diff for diff in names(freq_tbl, 1)]

      # probability
      probs = freqs ./ sampling_num^3
      tmp[a, i_t+1] = [[d, p] for (d, p) in zip(diffs, probs)]
    end
  end

  return tmp
end

function get_index(self::BeliefDynamicProgramming, pose)
  return Int64.(floor.((pose - self.pose_min)./self.widths))
end

function init_policy(self::BeliefDynamicProgramming)
  tmp = zeros(Tuple([self.index_nums[1], self.index_nums[2], self.index_nums[3], self.index_nums[4], 2]))

  for index in self.indexes
    center = self.pose_min + self.widths.*(index[1:3] .+ 0.5)
    tmp[index[1]+1, index[2]+1, index[3]+1, index[4]+1, :] .= policy(center, self.goal)
  end

  return tmp
end

function init_belief_value_function(self::BeliefDynamicProgramming)
  v = Array{Float64}(undef, Tuple(self.index_nums))
  f = zeros(Tuple(self.index_nums))

  for index in self.indexes
    f[index[1]+1, index[2]+1, index[3]+1, index[4]+1] = belief_final_state(self, index)
    if f[index[1]+1, index[2]+1, index[3]+1, index[4]+1] == true
      v[index[1]+1, index[2]+1, index[3]+1, index[4]+1] = self.goal.value
    else
      v[index[1]+1, index[2]+1, index[3]+1, index[4]+1] = -100.0
    end
  end

  return v, f
end

function belief_final_state(self::BeliefDynamicProgramming, index)
  lower_left = self.pose_min + self.widths.*index[1:3]
  upper_right = self.pose_min + self.widths.*(index[1:3].+1)

  corners = [[lower_left[1], lower_left[2]],
             [lower_left[1], upper_right[2]],
             [upper_right[1], lower_left[2]],
             [upper_right[1], upper_right[2]]]

  return all([inside(self.goal, c) for c in corners])
end

# give penalty when robot moved out of space
# and then, return state inside space
function out_correction(self::BeliefDynamicProgramming, index)
  out_reward = 0.0

  # direction
  index[3] = (index[3] + self.index_nums[3])%self.index_nums[3]

  for i in 1:2
    if index[i] < 0
      index[i] = 0
      out_reward = -1e100
    elseif index[i] >= self.index_nums[i]
      index[i] = self.index_nums[i] - 1
      out_reward = -1e100
    end
  end

  return index, out_reward
end

function action_value(self::BeliefDynamicProgramming, action, index; out_penalty=true)
  value = 0.0

  for delta_prob in self.state_transition_probs[(action, index[3]+1)]
    after, out_reward = out_correction(self, [index[1]+1, index[2]+1, index[3]+1]+delta_prob[1])

    for sigma_after_prob in self.motion_sigma_transition_probs[(index[4]+1, action)]
      for sigma_obs_prob in self.obs_sigma_transition_probs[(after[1], after[2], after[3], sigma_after_prob[1])]
        reward = -self.delta_time*self.depths[(after[1], after[2], sigma_obs_prob[1])]*self.puddle_coef - self.delta_time + out_reward*out_penalty
        value += (self.value_function[after[1]+1, after[2]+1, after[3]+1, sigma_obs_prob[1]+1] + reward) * delta_prob[2] * sigma_after_prob[2] * sigma_obs_prob[2]
      end
    end
  end

  return value
end

function value_iteration_sweep(self::BeliefDynamicProgramming)
  max_delta = 0.0

  for i in self.indexes
    if self.is_final_state[i[1]+1, i[2]+1, i[3]+1, i[4]+1] != true
      max_q = -1e100
      max_a = nothing

      qs = [action_value(self, a, i) for a in self.actions]
      max_q = findmax(qs)[1]
      max_a = self.actions[argmax(qs)]

      delta = abs(self.value_function[i[1]+1, i[2]+1, i[3]+1, i[4]+1] - max_q)
      if delta > max_delta
        max_delta = delta
      else
        max_delta = max_delta
      end

      self.value_function[i[1]+1, i[2]+1, i[3]+1, i[4]+1] = max_q
      self.policy[i[1]+1, i[2]+1, i[3]+1, i[4]+1, :] .= max_a
    end
  end

  return max_delta
end

max_stars_repo_name: ShisatoYano/JuliaAutonomy

max_issues_repo_name: ShisatoYano/JuliaAutonomy

max_forks_repo_name: ShisatoYano/JuliaAutonomy


text:
using Mosek

# The 'prob' structure specifies the moment problem
#
# minimize    prob.obj'*y
# subject to  prob.mom[k]*y is PSD ,  k=1,...,length(prob.mom)
#             y[1] = 1
#
# We formulate the dual problem for MOSEK
#
# maximize    -sum_j dot(prob.mom[j][:,1], Xj)
# subject to   sum_j dot(prob.mom[j][:,i], Xj) = prob.obj[i],  i=2,...,length(prob.obj)
#              Xj is PSD, j=1,...,length(prob.mom)
function solve_mosek(prob::MomentProb, scaling=false)

    printstream(msg::String) = print(msg)

    # Create a task object and attach log stream printer
    task = maketask()
    putstreamfunc(task,MSK_STREAM_LOG,printstream)

    # The momemt problem is in dual form, so we dualize it
    numcon = length(prob.obj) - 1
    numbarvar = length(prob.mom)
    barvardim = Int[ sqrt(size(prob.mom[k],1)) for k=1:numbarvar ]

    eqdim = Int[ sqrt(size(prob.eq[k],1)) for k=1:length(prob.eq) ]
    eqidx = Array(Int, length(prob.eq)+1)
    eqidx[1] = 0
    for k=1:length(prob.eq)
        eqidx[k+1] = eqidx[k] + eqdim[k]*(eqdim[k]+1)>>1
    end
    numvar = eqidx[ end ]

    # Append 'numcon' empty constraints.
    appendcons(task, int32(numcon))

    # find norm of each row in (A, b)
    norm_rows = ones(numcon)
    if scaling
        for i=1:numcon
            norm_rows[i] = max(norm_rows[i], abs(prob.obj[i+1]))
            for j=1:length(prob.mom)
                norm_rows[i] = max(norm_rows[i], norm(prob.mom[j].nzval[prob.mom[j].colptr[i+1]:prob.mom[j].colptr[i+2]-1], Inf))
            end

            for j=1:length(prob.eq)
                norm_rows[i] = max(norm_rows[i], norm(prob.eq[j].nzval[prob.eq[j].colptr[i+1]:prob.eq[j].colptr[i+2]-1], Inf))
            end
        end
    end

    # add free variables from equality constraints
    if numvar > 0
        appendvars(task, int32(numvar))

        putvarboundslice(task, 1, numvar+1,
                         [ MSK_BK_FR::Int32 for i in 1:numvar ],
                         [ -Inf             for i in 1:numvar ],
                         [ +Inf             for i in 1:numvar ])

        for j=1:length(prob.eq)
            k = prob.eq[j].colptr[1]:prob.eq[j].colptr[2]-1
            subj = trilind( prob.eq[j].rowval[k], eqdim[j] ) + eqidx[j]
            putclist(task, subj, -float64(prob.eq[j].nzval[k])/norm_rows[subj])
        end

        for j=1:length(prob.eq)
            for i=1:numcon
                k = prob.eq[j].colptr[i+1]:prob.eq[j].colptr[i+2]-1
                subj = trilind( prob.eq[j].rowval[k], eqdim[j] ) + eqidx[j]
                putaijlist(task, i*ones(Int, length(subj)), subj, float64(prob.eq[j].nzval[k])/norm_rows[i])
            end
        end
    end

    # Append matrix variables of sizes in 'BARVARDIM'.
    appendbarvars(task, int32(barvardim))

    bkc = Int32[ MSK_BK_FX for k=1:numcon ]
    blc = float64(prob.obj[2:end])./norm_rows
    buc = float64(prob.obj[2:end])./norm_rows

    # Set the bounds on constraints.
    putconboundslice(task, 1, numcon+1, bkc, blc, buc)

    # Add objective
    for j=1:numbarvar
        nj = int64(barvardim[j])
        k = prob.mom[j].colptr[1]:prob.mom[j].colptr[2]-1
        subk, subl = ind2sub( (nj, nj), prob.mom[j].rowval[k] )
        cj = appendsparsesymmat(task,
                                int32(nj),
                                int32(subk),
                                int32(subl),
                                float64(-prob.mom[j].nzval[k]))
        putbarcj(task, j, [cj], [1.0])
    end

    # Add constraints
    for i=1:numcon
        for j=1:numbarvar
            nj = int64(barvardim[j])
            k = prob.mom[j].colptr[i+1]:prob.mom[j].colptr[i+2]-1
            subk, subl = ind2sub( (nj, nj), prob.mom[j].rowval[k] )
            aij = appendsparsesymmat(task, int32(nj), int32(subk), int32(subl), float64(prob.mom[j].nzval[k])/norm_rows[i])
            putbaraij(task, int32(i), int32(j), [aij], [1.0])
        end
    end

    # Input the objective sense (minimize/maximize)
    putobjsense(task,MSK_OBJECTIVE_SENSE_MAXIMIZE)

    # Write .task file
    #writetask(task, "polyopt.task")

    # Solve the problem and print summary
    optimize(task)
    solutionsummary(task,MSK_STREAM_MSG)

    # Get status information about the solution
    prosta = getprosta(task,MSK_SOL_ITR)
    solsta = getsolsta(task,MSK_SOL_ITR)

    #return getbarxj(task, MSK_SOL_ITR, 1)

    if solsta == MSK_SOL_STA_OPTIMAL
        return ([1, gety(task, MSK_SOL_ITR)], getprimalobj(task, MSK_SOL_ITR), "Optimal")
    elseif solsta == MSK_SOL_STA_NEAR_OPTIMAL
        return ([1, gety(task, MSK_SOL_ITR)], getprimalobj(task, MSK_SOL_ITR), "Near optimal")
    elseif solsta == MSK_SOL_STA_DUAL_INFEAS_CER
        error("Primal or dual infeasibility.\n")
    elseif solsta == MSK_SOL_STA_PRIM_INFEAS_CER
        error("Primal or dual infeasibility.\n")
    elseif solsta == MSK_SOL_STA_NEAR_DUAL_INFEAS_CER
        error("Primal or dual infeasibility.\n")
    elseif solsta == MSK_SOL_STA_NEAR_PRIM_INFEAS_CER
        error("Primal or dual infeasibility.\n")
    elseif solsta == MSK_SOL_STA_UNKNOWN
        println("Unknown solution status")
        return ([1, gety(task, MSK_SOL_ITR)],  getprimalobj(task, MSK_SOL_ITR), "Unknown")
    else
        error("Other solution status")
    end

end

trilind(k::Vector{Int}, n::Int) = Int[i + (j-1)*(n-1) - (j-1)*(j-2)>>1 for (i,j) = zip(ind2sub((n, n), k)...) ]


text:
two_point_forward(f, x::Real, h::Real=1.0) = (f(x+h) - f(x)) / h
three_point_endpoint(f, x::Real, h::Real=1.0) = (-3f(x) + 4f(x+h)-f(x+2h)) / 2h
three_point_midpoint(f, x::Real, h::Real=1.0) = (f(x+h) - f(x-h)) / 2h
five_point_endpoint(f, x::Real, h::Real=1.0) = (-25f(x) + 48f(x+h) - 36f(x+2h) + 16f(x+3h) - 3f(x+4h)) / 12h
five_point_midpoint(f, x::Real, h::Real=1.0) = (f(x-2h) - 8f(x-h) + 8f(x+h)-f(x+2h)) / 12h

_beta_inc(z1::Real, z2::Real, a::Real, b::Real) = inv(a) * (z2^a * _₂F₁(a,1-b,a+1,z2) - z1^a * _₂F₁(a,1-b,a+1,z1))
_beta_inc(x::Real, a::Real, b::Real) = _beta_inc(0.0, x, a, b)
_beta_inc(a::Real, b::Real) = _beta_inc(0.0, prevfloat(1.0), a, b)

_gsd_quantile(p::Real, F₀::Real, x₀::Real, α::Real, g::Real, k::Real, γ::Real) = x₀ + _beta_inc(F₀^k, p^k, (1-g)/k, 1-γ) / (α*k)

function _gsd_mean(F₀::Real, x₀::Real, α::Real, g::Real, k::Real, γ::Real)
	z1 = F₀^k
	a1 = (1 - g) / k
	b1 = 1 - γ
	a2 = (2 - g) / k
	b2 = 1 - γ
	x₀ + (_beta_inc(z1, prevfloat(1.0), a1, b1) - _beta_inc(a2, b2)) * inv(α * k)
end

function _gsd_moment(F₀::Real, x₀::Real, α::Real, g::Real, k::Real, γ::Real; moment::Int=1)
    z1 = F₀^k
    a = (1 - g) / k
    b = 1 - γ
    c = inv(α * k)

    f = q -> (x₀ + c*_beta_inc(z1, q^k, a, b))^moment
    quadgk(f, 0, 1, atol=1e-4)[1]
end

function _piecewise_cdf(α, g, k, γ, dist; probs=[0.01, 0.15, 0.85, 0.99])
	p = [α, g, k, γ]
	cutpoint = Float64.(quantile.(dist, probs))
	d = length(probs) - 1

    function gsd!(du, u, p, t)
        α, g, k, γ = p
        du[1] = α * u[1]^g * (1 - u[1]^k)^γ
    end

	P = [ODEProblem(gsd!, [probs[i]], (cutpoint[i], cutpoint[i+1]), p) for i in 1:d]
	S = [solve(x, AutoTsit5(Rosenbrock23())) for x in P]

	# Make a piecewise CDF
	x -> begin
		x < cutpoint[1]   && return max(S[1](x)[1],   0.0)
		x > cutpoint[end] && return min(S[end](x)[1], 1.0)
		idx = findfirst(cutpoint[1:end-1] .≤ x .≤ cutpoint[2:end])
		return S[idx](x)[1]
	end
end


text:
latex_symbol_map = Dict(
    ";" => " ",
    "texttrademark" => '™',
    "trademark" => '™',
    "textregistered" => '®',
    "registered" => '®',
    "copyright" => '©',
    "pilcrow" => '¶',
    "pound" => '£',
    "euro" => '€',
    "cents" => '¢',
    "section" => '§',
    "space" => '␣',
    "degree" => '°',
    "zeta" => 'ζ',
    "Xi" => 'Ξ',
    "xi" => 'ξ',
    "wr" => '≀',
    "wp" => '℘',
    "wedge" => '∧',
    "Vvdash" => '⊪',
    "veebar" => '⊻',
    "vee" => '∨',
    "vdots" => '⋮',
    "Vdash" => '⊩',
    "vDash" => '⊨',
    "vdash" => '⊢',
    "vartriangleright" => '⊳',
    "vartriangleleft" => '⊲',
    "vartriangle" => '△',
    "vartheta" => 'ϑ',
    "varsigma" => 'ς',
    "varrho" => 'ϱ',
    "varpropto" => '∝',
    "varpi" => 'ϖ',
    "varphi" => 'φ',
    "varnothing" => '∅',
    "varkappa" => 'ϰ',
    "varepsilon" => 'ε',
    "upuparrows" => '⇈',
    "Upsilon" => 'Υ',
    "upsilon" => 'υ',
    "uplus" => '⊎',
    "upharpoonright" => '↾',
    "upharpoonleft" => '↿',
    "Updownarrow" => '⇕',
    "updownarrow" => '↕',
    "Uparrow" => '⇑',
    "uparrow" => '↑',
    "unrhd" => '⊵',
    "unlhd" => '⊴',
    "twoheadrightarrow" => '↠',
    "twoheadleftarrow" => '↞',
    "trianglerighteq" => '⊵',
    "triangleright" => '▷',
    "triangleq" => '≜',
    "trianglelefteq" => '⊴',
    "triangleleft" => '◁',
    "triangledown" => '▽',
    "triangle" => '△',
    "top" => '⊤',
    "times" => '×',
    "thicksim" => '∼',
    "thickapprox" => '≈',
    "Theta" => 'Θ',
    "theta" => 'θ',
    "therefore" => '∴',
    "tau" => 'τ',
    "swarrow" => '↙',
    "surd" => '√',
    "supseteq" => '⊇',
    "Supset" => '⋑',
    "supset" => '⊃',
    "sum" => '∑',
    "succsim" => '≿',
    "succeq" => '⪰',
    "succcurlyeq" => '≽',
    "succ" => '≻',
    "subseteq" => '⊆',
    "Subset" => '⋐',
    "subset" => '⊂',
    "star" => '⋆',
    "square" => '□',
    "sqsupseteq" => '⊒',
    "sqsupset" => '⊐',
    "sqsubseteq" => '⊑',
    "sqsubset" => '⊏',
    "sqrt" => '√',
    "sqcup" => '⊔',
    "sqcap" => '⊓',
    "sphericalangle" => '∢',
    "spadesuit" => '♠',
    "smile" => '⌣',
    "smallsmile" => '⌣',
    "smallsetminus" => '∖',
    "smallfrown" => '⌢',
    "simeq" => '≃',
    "sim" => '∼',
    "sigma" => 'σ',
    "shortparallel" => '∥',
    "sharp" => '♯',
    "setminus" => '∖',
    "searrow" => '↘',
    "rtimes" => '⋊',
    "Rsh" => '↱',
    "Rrightarrow" => '⇛',
    "risingdotseq" => '≓',
    "rightthreetimes" => '⋌',
    "rightsquigarrow" => '⇝',
    "rightrightarrows" => '⇉',
    "rightleftharpoons" => '⇌',
    "rightleftarrows" => '⇄',
    "rightharpoonup" => '⇀',
    "rightharpoondown" => '⇁',
    "rightarrowtail" => '↣',
    "Rightarrow" => '⇒',
    "rightarrow" => '→',
    "rho" => 'ρ',
    "rhd" => '⊳',
    "rfloor" => '⌋',
    "Re" => 'ℜ',
    "rceil" => '⌉',
    "rangle" => '〉',
    "Psi" => 'Ψ',
    "psi" => 'ψ',
    "propto" => '∝',
    "prod" => '∏',
    "prime" => '′',
    "precsim" => '≾',
    "preceq" => '⪯',
    "preccurlyeq" => '≼',
    "prec" => '≺',
    "pm" => '±',
    "Pi" => 'Π',
    "pi" => 'π',
    "pitchfork" => '⋔',
    "Phi" => 'Φ',
    "phi" => 'ϕ',
    "perp" => '⊥',
    "partial" => '∂',
    "parallel" => '∥',
    "otimes" => '⊗',
    "oslash" => '⊘',
    "oplus" => '⊕',
    "ominus" => '⊖',
    "Omega" => 'Ω',
    "omega" => 'ω',
    "oint" => '∮',
    "odot" => '⊙',
    "nwarrow" => '↖',
    "nu" => 'ν',
    "notin" => '∉',
    "ni" => '∋',
    "nexists" => '∄',
    "neq" => '≠',
    "neg" => '¬',
    "nearrow" => '↗',
    "natural" => '♮',
    "nabla" => '∇',
    "mu" => 'μ',
    "multimap" => '⊸',
    "mp" => '∓',
    "models" => '⊨',
    "mid" => '∣',
    "mho" => '℧',
    "measuredangle" => '∡',
    "mapsto" => '↦',
    "ltimes" => '⋉',
    "Lsh" => '↰',
    "lozenge" => '◊',
    "looparrowright" => '↬',
    "looparrowleft" => '↫',
    "Longrightarrow" => '⟹',
    "longrightarrow" => '⟶',
    "longmapsto" => '⟼',
    "Longleftrightarrow" => '⟺',
    "longleftrightarrow" => '⟷',
    "Longleftarrow" => '⟸',
    "longleftarrow" => '⟵',
    "lll" => '⋘',
    "Lleftarrow" => '⇚',
    "ll" => '≪',
    "lhd" => '⊲',
    "lfloor" => '⌊',
    "lesssim" => '≲',
    "lessgtr" => '≶',
    "lesseqgtr" => '⋚',
    "lessdot" => '⋖',
    "leqslant" => '⩽',
    "leqq" => '≦',
    "leq" => '≤',
    "leftthreetimes" => '⋋',
    "leftrightsquigarrow" => '↭',
    "leftrightharpoons" => '⇋',
    "leftrightarrows" => '⇆',
    "Leftrightarrow" => '⇔',
    "leftrightarrow" => '↔',
    "leftleftarrows" => '⇇',
    "leftharpoonup" => '↼',
    "leftharpoondown" => '↽',
    "leftarrowtail" => '↢',
    "Leftarrow" => '⇐',
    "leftarrow" => '←',
    "leadsto" => '↝',
    "le" => '≤',
    "lceil" => '⌈',
    "langle" => '〈',
    "Lambda" => 'Λ',
    "lambda" => 'λ',
    "kappa" => 'κ',
    "Join" => '⋈',
    "iota" => 'ι',
    "intercal" => '⊺',
    "int" => '∫',
    "infty" => '∞',
    "in" => '∈',
    "implies" => '⇒',
    "Im" => 'ℑ',
    "hslash" => 'ℏ',
    "hookrightarrow" => '↪',
    "hookleftarrow" => '↩',
    "heartsuit" => '♡',
    "hbar" => 'ℏ',
    "gtrsim" => '≳',
    "gtrless" => '≷',
    "gtreqless" => '⋛',
    "gtrdot" => '⋗',
    "gimel" => 'ℷ',
    "ggg" => '⋙',
    "gg" => '≫',
    "geqq" => '≧',
    "geq" => '≥',
    "ge" => '≥',
    "Gamma" => 'Γ',
    "gamma" => 'γ',
    "frown" => '⌢',
    "forall" => '∀',
    "flat" => '♭',
    "Finv" => 'Ⅎ',
    "fallingdotseq" => '≒',
    "exists" => '∃',
    "eth" => 'ð',
    "eta" => 'η',
    "equiv" => '≡',
    "eqcirc" => '≖',
    "epsilon" => '∊',
    "emptyset" => '∅',
    "ell" => 'ℓ',
    "downharpoonright" => '⇂',
    "downharpoonleft" => '⇃',
    "downdownarrows" => '⇊',
    "Downarrow" => '⇓',
    "downarrow" => '↓',
    "dots" => '…',
    "dotplus" => '∔',
    "doteqdot" => '≑',
    "doteq" => '≐',
    "divideontimes" => '⋇',
    "div" => '÷',
    "digamma" => 'Ϝ',
    "diamondsuit" => '♢',
    "Diamond" => '◇',
    "diamond" => '⋄',
    "Delta" => 'Δ',
    "delta" => 'δ',
    "ddots" => '⋱',
    "ddagger" => '‡',
    "dashv" => '⊣',
    "dashrightarrow" => '⇢',
    "dashleftarrow" => '⇠',
    "daleth" => 'ℸ',
    "dagger" => '†',
    "curvearrowright" => '↷',
    "curvearrowleft" => '↶',
    "curlywedge" => '⋏',
    "curlyvee" => '⋎',
    "curlyeqsucc" => '⋟',
    "curlyeqprec" => '⋞',
    "Cup" => '⋓',
    "cup" => '∪',
    "coprod" => '∐',
    "cong" => '≅',
    "complement" => '∁',
    "clubsuit" => '♣',
    "circledS" => 'Ⓢ',
    "circleddash" => '⊝',
    "circledcirc" => '⊚',
    "circledast" => '⊛',
    "circlearrowright" => '↻',
    "circlearrowleft" => '↺',
    "circeq" => '≗',
    "circ" => '∘',
    "chi" => 'χ',
    "centerdot" => '⋅',
    "cdots" => '⋯',
    "cdot" => '⋅',
    "cbrt" => '∛',
    "Cap" => '⋒',
    "cap" => '∩',
    "Bumpeq" => '≎',
    "bumpeq" => '≏',
    "bullet" => '∙',
    "boxtimes" => '⊠',
    "boxplus" => '⊞',
    "boxminus" => '⊟',
    "boxdot" => '⊡',
    "Box" => '□',
    "bowtie" => '⋈',
    "bot" => '⊥',
    "blacktriangleright" => '▶',
    "blacktriangleleft" => '◀',
    "blacktriangledown" => '▼',
    "blacktriangle" => '▲',
    "blacksquare" => '■',
    "blacklozenge" => '◆',
    "bigwedge" => '⋀',
    "bigvee" => '⋁',
    "biguplus" => '⨄',
    "bigtriangleup" => '△',
    "bigtriangledown" => '▽',
    "bigstar" => '★',
    "bigsqcup" => '⨆',
    "bigotimes" => '⨂',
    "bigoplus" => '⨁',
    "bigodot" => '⨀',
    "bigcup" => '⋃',
    "bigcirc" => '○',
    "bigcap" => '⋂',
    "between" => '≬',
    "beth" => 'ℶ',
    "beta" => 'β',
    "because" => '∵',
    "barwedge" => '⊼',
    "backsim" => '∽',
    "backprime" => '‵',
    "backepsilon" => '∍',
    "asymp" => '≍',
    "ast" => '∗',
    "approxeq" => '≊',
    "approx" => '≈',
    "angle" => '∠',
    "alpha" => 'α',
    "aleph" => 'ℵ'
)