 9bdcbe0447
			
		
	
	9bdcbe0447
	
	
	
		
			
			Major integrations and fixes: - Added BACKBEAT SDK integration for P2P operation timing - Implemented beat-aware status tracking for distributed operations - Added Docker secrets support for secure license management - Resolved KACHING license validation via HTTPS/TLS - Updated docker-compose configuration for clean stack deployment - Disabled rollback policies to prevent deployment failures - Added license credential storage (CHORUS-DEV-MULTI-001) Technical improvements: - BACKBEAT P2P operation tracking with phase management - Enhanced configuration system with file-based secrets - Improved error handling for license validation - Clean separation of KACHING and CHORUS deployment stacks 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
		
			
				
	
	
		
			182 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			182 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // Derived from SciPy's special/c_misc/fsolve.c and special/c_misc/misc.h
 | |
| // https://github.com/scipy/scipy/blob/master/scipy/special/c_misc/fsolve.c
 | |
| // https://github.com/scipy/scipy/blob/master/scipy/special/c_misc/misc.h
 | |
| 
 | |
| // Copyright ©2017 The Gonum Authors. All rights reserved.
 | |
| // Use of this source code is governed by a BSD-style
 | |
| // license that can be found in the LICENSE file.
 | |
| 
 | |
| package mathext
 | |
| 
 | |
| import "math"
 | |
| 
 | |
| type objectiveFunc func(float64, []float64) float64
 | |
| 
 | |
| type fSolveResult uint8
 | |
| 
 | |
| const (
 | |
| 	// An exact solution was found, in which case the first point on the
 | |
| 	// interval is the value
 | |
| 	fSolveExact fSolveResult = iota + 1
 | |
| 	// Interval width is less than the tolerance
 | |
| 	fSolveConverged
 | |
| 	// Root-finding didn't converge in a set number of iterations
 | |
| 	fSolveMaxIterations
 | |
| )
 | |
| 
 | |
| const (
 | |
| 	machEp = 1.0 / (1 << 53)
 | |
| )
 | |
| 
 | |
| // falsePosition uses a combination of bisection and false position to find a
 | |
| // root of a function within a given interval. This is guaranteed to converge,
 | |
| // and always keeps a bounding interval, unlike Newton's method. Inputs are:
 | |
| //
 | |
| //	x1, x2:   initial bounding interval
 | |
| //	f1, f2: value of f() at x1 and x2
 | |
| //	absErr, relErr: absolute and relative errors on the bounding interval
 | |
| //	bisectTil: if > 0.0, perform bisection until the width of the bounding
 | |
| //	           interval is less than this
 | |
| //	f, fExtra: function to find root of is f(x, fExtra)
 | |
| //
 | |
| // Returns:
 | |
| //
 | |
| //	result: whether an exact root was found, the process converged to a
 | |
| //	        bounding interval small than the required error, or the max number
 | |
| //	        of iterations was hit
 | |
| //	bestX: best root approximation
 | |
| //	bestF: function value at bestX
 | |
| //	errEst: error estimation
 | |
| func falsePosition(x1, x2, f1, f2, absErr, relErr, bisectTil float64, f objectiveFunc, fExtra []float64) (fSolveResult, float64, float64, float64) {
 | |
| 	// The false position steps are either unmodified, or modified with the
 | |
| 	// Anderson-Bjorck method as appropriate. Theoretically, this has a "speed of
 | |
| 	// convergence" of 1.7 (bisection is 1, Newton is 2).
 | |
| 	// Note that this routine was designed initially to work with gammaincinv, so
 | |
| 	// it may not be tuned right for other problems. Don't use it blindly.
 | |
| 
 | |
| 	if f1*f2 >= 0 {
 | |
| 		panic("Initial interval is not a bounding interval")
 | |
| 	}
 | |
| 
 | |
| 	const (
 | |
| 		maxIterations = 100
 | |
| 		bisectIter    = 4
 | |
| 		bisectWidth   = 4.0
 | |
| 	)
 | |
| 
 | |
| 	const (
 | |
| 		bisect = iota + 1
 | |
| 		falseP
 | |
| 	)
 | |
| 
 | |
| 	var state uint8
 | |
| 	if bisectTil > 0 {
 | |
| 		state = bisect
 | |
| 	} else {
 | |
| 		state = falseP
 | |
| 	}
 | |
| 
 | |
| 	gamma := 1.0
 | |
| 
 | |
| 	w := math.Abs(x2 - x1)
 | |
| 	lastBisectWidth := w
 | |
| 
 | |
| 	var nFalseP int
 | |
| 	var x3, f3, bestX, bestF float64
 | |
| 	for i := 0; i < maxIterations; i++ {
 | |
| 		switch state {
 | |
| 		case bisect:
 | |
| 			x3 = 0.5 * (x1 + x2)
 | |
| 			if x3 == x1 || x3 == x2 {
 | |
| 				// i.e., x1 and x2 are successive floating-point numbers
 | |
| 				bestX = x3
 | |
| 				if x3 == x1 {
 | |
| 					bestF = f1
 | |
| 				} else {
 | |
| 					bestF = f2
 | |
| 				}
 | |
| 				return fSolveConverged, bestX, bestF, w
 | |
| 			}
 | |
| 
 | |
| 			f3 = f(x3, fExtra)
 | |
| 			if f3 == 0 {
 | |
| 				return fSolveExact, x3, f3, w
 | |
| 			}
 | |
| 
 | |
| 			if f3*f2 < 0 {
 | |
| 				x1 = x2
 | |
| 				f1 = f2
 | |
| 			}
 | |
| 			x2 = x3
 | |
| 			f2 = f3
 | |
| 			w = math.Abs(x2 - x1)
 | |
| 			lastBisectWidth = w
 | |
| 			if bisectTil > 0 {
 | |
| 				if w < bisectTil {
 | |
| 					bisectTil = -1.0
 | |
| 					gamma = 1.0
 | |
| 					nFalseP = 0
 | |
| 					state = falseP
 | |
| 				}
 | |
| 			} else {
 | |
| 				gamma = 1.0
 | |
| 				nFalseP = 0
 | |
| 				state = falseP
 | |
| 			}
 | |
| 		case falseP:
 | |
| 			s12 := (f2 - gamma*f1) / (x2 - x1)
 | |
| 			x3 = x2 - f2/s12
 | |
| 			f3 = f(x3, fExtra)
 | |
| 			if f3 == 0 {
 | |
| 				return fSolveExact, x3, f3, w
 | |
| 			}
 | |
| 
 | |
| 			nFalseP++
 | |
| 			if f3*f2 < 0 {
 | |
| 				gamma = 1.0
 | |
| 				x1 = x2
 | |
| 				f1 = f2
 | |
| 			} else {
 | |
| 				// Anderson-Bjorck method
 | |
| 				g := 1.0 - f3/f2
 | |
| 				if g <= 0 {
 | |
| 					g = 0.5
 | |
| 				}
 | |
| 				gamma *= g
 | |
| 			}
 | |
| 			x2 = x3
 | |
| 			f2 = f3
 | |
| 			w = math.Abs(x2 - x1)
 | |
| 
 | |
| 			// Sanity check. For every 4 false position checks, see if we really are
 | |
| 			// decreasing the interval by comparing to what bisection would have
 | |
| 			// achieved (or, rather, a bit more lenient than that -- interval
 | |
| 			// decreased by 4 instead of by 16, as the fp could be decreasing gamma
 | |
| 			// for a bit). Note that this should guarantee convergence, as it makes
 | |
| 			// sure that we always end up decreasing the interval width with a
 | |
| 			// bisection.
 | |
| 			if nFalseP > bisectIter {
 | |
| 				if w*bisectWidth > lastBisectWidth {
 | |
| 					state = bisect
 | |
| 				}
 | |
| 				nFalseP = 0
 | |
| 				lastBisectWidth = w
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		tol := absErr + relErr*math.Max(math.Max(math.Abs(x1), math.Abs(x2)), 1.0)
 | |
| 		if w <= tol {
 | |
| 			if math.Abs(f1) < math.Abs(f2) {
 | |
| 				bestX = x1
 | |
| 				bestF = f1
 | |
| 			} else {
 | |
| 				bestX = x2
 | |
| 				bestF = f2
 | |
| 			}
 | |
| 			return fSolveConverged, bestX, bestF, w
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return fSolveMaxIterations, x3, f3, w
 | |
| }
 |