balanced pair optimization

This commit is contained in:
tim
2025-09-18 22:16:01 -04:00
parent a96b494cef
commit 3eba6412a6
7 changed files with 549 additions and 27 deletions

View File

@@ -855,8 +855,7 @@ library LMSRStabilized {
) internal pure returns (int128) {
// Quick sanity checks that decide whether the heterogeneous formula is applicable.
// If not, fall back to the closed-form equal-asset formula for stability.
int128 one = _one();
int128 onePlusS = one.add(targetSlippage);
int128 onePlusS = ONE.add(targetSlippage);
int128 n64 = ABDKMath64x64.fromUInt(nAssets);
int128 nMinus1_64 = ABDKMath64x64.fromUInt(nAssets - 1);
@@ -896,8 +895,6 @@ library LMSRStabilized {
require(f > int128(0), "LMSR: f=0");
require(f < ONE, "LMSR: f>=1");
int128 one = _one();
// Top-level input debug
console2.log("computeBFromSlippageCore: inputs");
console2.log("q (64.64)");
@@ -921,8 +918,8 @@ library LMSRStabilized {
// b = q / y = q * f / (-ln(E))
int128 nMinus1 = ABDKMath64x64.fromUInt(nAssets - 1);
int128 numerator = one.sub(targetSlippage.mul(nMinus1)); // 1 - s*(n-1)
int128 denominator = one.add(targetSlippage); // 1 + s
int128 numerator = ONE.sub(targetSlippage.mul(nMinus1)); // 1 - s*(n-1)
int128 denominator = ONE.add(targetSlippage); // 1 + s
console2.log("equal-case intermediates:");
console2.log("numerator = 1 - s*(n-1)");
@@ -937,7 +934,7 @@ library LMSRStabilized {
console2.logInt(ratio);
// E must be strictly between 0 and 1 for a positive y
require(ratio > int128(0) && ratio < one, "LMSR: bad E ratio");
require(ratio > int128(0) && ratio < ONE, "LMSR: bad E ratio");
int128 lnE = _ln(ratio); // ln(E) < 0
console2.log("ln(E)");
@@ -959,7 +956,7 @@ library LMSRStabilized {
int128 E_sim = _exp(expArg);
int128 n64 = ABDKMath64x64.fromUInt(nAssets);
int128 nMinus1_64 = ABDKMath64x64.fromUInt(nAssets - 1);
int128 simulatedSlippage = n64.div(nMinus1_64.add(E_sim)).sub(_one());
int128 simulatedSlippage = n64.div(nMinus1_64.add(E_sim)).sub(ONE);
console2.log("simulatedSlippage (using computed b)");
console2.logInt(simulatedSlippage);
@@ -969,7 +966,7 @@ library LMSRStabilized {
// E = exp(-y * f) where y = q / b
// and E = (1+s) * (n-1) / (n - (1+s))
// so y = -ln(E) / f and b = q / y.
int128 onePlusS = one.add(targetSlippage);
int128 onePlusS = ONE.add(targetSlippage);
console2.log("heterogeneous intermediates:");
console2.log("onePlusS = 1 + s");
@@ -1007,7 +1004,7 @@ library LMSRStabilized {
// Correct E candidate for the slippage relation:
// E = (1 - s*(n-1)) / (1 + s)
int128 E_candidate = (one.sub(targetSlippage.mul(nMinus1_64))).div(onePlusS);
int128 E_candidate = (ONE.sub(targetSlippage.mul(nMinus1_64))).div(onePlusS);
console2.log("E candidate ((1 - s*(n-1)) / (1+s))");
console2.logInt(E_candidate);
@@ -1031,7 +1028,7 @@ library LMSRStabilized {
// Simulate slippage using this b to verify
int128 expArg = y.mul(f).neg();
int128 E_sim = _exp(expArg);
int128 simulatedSlippage = n64.div(nMinus1_64.add(E_sim)).sub(_one());
int128 simulatedSlippage = n64.div(nMinus1_64.add(E_sim)).sub(ONE);
console2.log("simulatedSlippage (heterogeneous)");
console2.logInt(simulatedSlippage);
@@ -1055,7 +1052,7 @@ library LMSRStabilized {
}
/// @notice Compute M (shift) and Z (sum of exponentials) dynamically
function _computeMAndZ(int128 b, int128[] memory qInternal) private pure returns (int128 M, int128 Z) {
function _computeMAndZ(int128 b, int128[] memory qInternal) internal pure returns (int128 M, int128 Z) {
require(qInternal.length > 0, "LMSR: no assets");
// Precompute reciprocal of b to replace divisions with multiplications in the loop
@@ -1083,7 +1080,7 @@ library LMSRStabilized {
}
/// @notice Compute all e[i] = exp(z[i]) values dynamically
function _computeE(int128 b, int128[] memory qInternal, int128 M) private pure returns (int128[] memory e) {
function _computeE(int128 b, int128[] memory qInternal, int128 M) internal pure returns (int128[] memory e) {
uint len = qInternal.length;
e = new int128[](len);
@@ -1100,7 +1097,7 @@ library LMSRStabilized {
/// @notice Compute r0 = e_i / e_j directly as exp((q_i - q_j) / b)
/// This avoids computing two separate exponentials and a division
function _computeR0(int128 b, int128[] memory qInternal, uint256 i, uint256 j) private pure returns (int128) {
function _computeR0(int128 b, int128[] memory qInternal, uint256 i, uint256 j) internal pure returns (int128) {
return _exp(qInternal[i].sub(qInternal[j]).div(b));
}
@@ -1110,16 +1107,15 @@ library LMSRStabilized {
-------------------- */
// Precomputed Q64.64 representation of 1.0 (1 << 64).
int128 private constant ONE = 0x10000000000000000;
int128 internal constant ONE = 0x10000000000000000;
// Precomputed Q64.64 representation of 32.0 for exp guard
int128 private constant EXP_LIMIT = 0x200000000000000000;
int128 internal constant EXP_LIMIT = 0x200000000000000000;
function _exp(int128 x) private pure returns (int128) { return ABDKMath64x64.exp(x); }
function _ln(int128 x) private pure returns (int128) { return ABDKMath64x64.ln(x); }
function _one() private pure returns (int128) { return ONE; }
function _exp(int128 x) internal pure returns (int128) { return ABDKMath64x64.exp(x); }
function _ln(int128 x) internal pure returns (int128) { return ABDKMath64x64.ln(x); }
/// @notice Compute size metric S(q) = sum of all asset quantities
function _computeSizeMetric(int128[] memory qInternal) private pure returns (int128) {
function _computeSizeMetric(int128[] memory qInternal) internal pure returns (int128) {
int128 total = int128(0);
for (uint i = 0; i < qInternal.length; ) {
total = total.add(qInternal[i]);
@@ -1129,7 +1125,7 @@ library LMSRStabilized {
}
/// @notice Compute b from kappa and current asset quantities
function _computeB(State storage s) private view returns (int128) {
function _computeB(State storage s) internal view returns (int128) {
int128 sizeMetric = _computeSizeMetric(s.qInternal);
require(sizeMetric > int128(0), "LMSR: size metric zero");
return s.kappa.mul(sizeMetric);