private double computeTapValue() { double modifiedAcc = getModifiedAcc(); // Assume SS for non-stream parts double accOnStreams = 1 - (1 - modifiedAcc) * totalHits / Attributes.StreamNoteCount; double mashLevel = 1 - SpecialFunctions.Logistic((accOnStreams - 0.75) / 0.1) / SpecialFunctions.Logistic(2.5); double tapSkill = LinearSpline.InterpolateSorted(Attributes.MashLevels, Attributes.TapSkills) .Interpolate(mashLevel); double tapValue = tapSkillToPP(tapSkill); // Buff high acc double accBuff = Math.Exp((accOnStreams - 1) * 60) * tapValue * 0.2f; tapValue += accBuff; // Penalize misses exponentially tapValue *= Math.Pow(0.93f, countMiss); double approachRateFactor = 1.0f; if (Attributes.ApproachRate > 10.33f) { approachRateFactor += 0.2f * (Attributes.ApproachRate - 10.33f); } tapValue *= approachRateFactor; return(tapValue); }
/// <summary> /// Creates a curve. The curve will be flat from the anchor date to the first date and from the last date in dates until maximumDate /// </summary> /// <param name="currency"></param> /// <param name="anchorDate">Date from which the curve applies. Interpolation before this date won't work.</param> /// <param name="dates">Must be sorted in increasing order.</param> /// <param name="rates">The rates. If the curve is going to be used to supply discount factors then these rates must be continuously compounded.</param> /// <param name="maximumDate">The date beyond which interpolation will not be allowed. If it is null or left out then the last date in dates will be used.</param> public DatesAndRates(Currency currency, Date anchorDate, Date[] dates, double[] rates, Date maximumDate = null) { this.anchorDate = anchorDate; for (int i = 1; i < dates.Length; i++) { if (dates[i].value <= dates[i - 1].value) { throw new ArgumentException("Dates must be strictly increasing"); } } List <double> datesList = new List <double>(dates.GetValues()); List <double> ratesList = new List <double>(rates.Clone() as double[]); if (dates[0] > anchorDate) { datesList.Insert(0, anchorDate.value); ratesList.Insert(0, rates[0]); } if (maximumDate != null) { datesList.Add(maximumDate); ratesList.Add(rates.Last()); } this.anchorDateValue = anchorDate; this.dates = datesList.ToArray(); this.rates = ratesList.ToArray(); this.currency = currency; spline = LinearSpline.InterpolateSorted(this.dates, this.rates); }
public PiecewiseLinearInjectWithdrawConstraint([NotNull] IEnumerable <InjectWithdrawRangeByInventory> injectWithdrawRanges) { if (injectWithdrawRanges == null) { throw new ArgumentNullException(nameof(injectWithdrawRanges)); } _injectWithdrawRanges = injectWithdrawRanges.OrderBy(injectWithdrawRange => injectWithdrawRange.Inventory) .ToArray(); if (_injectWithdrawRanges.Length < 2) { throw new ArgumentException("Inject/withdraw ranges collection must contain at least two elements.", nameof(injectWithdrawRanges)); } double[] inventories = _injectWithdrawRanges.Select(injectWithdrawRange => injectWithdrawRange.Inventory) .ToArray(); double[] maxInjectWithdrawRates = _injectWithdrawRanges .Select(injectWithdrawRange => injectWithdrawRange.InjectWithdrawRange.MaxInjectWithdrawRate) .ToArray(); double[] minInjectWithdrawRates = _injectWithdrawRanges .Select(injectWithdrawRange => injectWithdrawRange.InjectWithdrawRange.MinInjectWithdrawRate) .ToArray(); _maxInjectWithdrawLinear = LinearSpline.InterpolateSorted(inventories, maxInjectWithdrawRates); _minInjectWithdrawLinear = LinearSpline.InterpolateSorted(inventories, minInjectWithdrawRates); }
private IInterpolation interpolation_U(UV point, Index index) { IndexRange horizontalExpansion = this.horizontalRange(index); //getting all vertical ranges of the horizontal IndexRange[] verticals = new IndexRange[horizontalExpansion.Length]; Index next = horizontalExpansion.Min.Copy(); for (int i = 0; i < horizontalExpansion.Length; i++) { verticals[i] = this.verticalRange(next); next.I++; } //getting interpolators for u values IInterpolation[] verticalsU = new IInterpolation[horizontalExpansion.Length]; for (int i = 0; i < verticals.Length; i++) { verticalsU[i] = this.toInterpolation(verticals[i]); } //generating u interpolation double[] x = new double[horizontalExpansion.Length]; double[] y = new double[horizontalExpansion.Length]; next = horizontalExpansion.Min.Copy(); for (int i = 0; i < horizontalExpansion.Length; i++) { x[i] = this._cellularFloor.FindCell(next).U; y[i] = verticalsU[i].Interpolate(point.V); next.I++; } IInterpolation interpolatorU = null; switch (Activity.InterpolationMethod) { case SpatialAnalysis.FieldUtility.InterpolationMethod.CubicSpline: if (x.Length > 1) { interpolatorU = CubicSpline.InterpolateBoundariesSorted(x, y, SplineBoundaryCondition.Natural, 0, SplineBoundaryCondition.Natural, 0); } else { interpolatorU = LinearSpline.InterpolateSorted(x, y); } break; //case FieldUtility.InterpolationMethod.Barycentric: // interpolatorU = Barycentric.InterpolatePolynomialEquidistantSorted(x, y); // break; case SpatialAnalysis.FieldUtility.InterpolationMethod.Linear: interpolatorU = LinearSpline.InterpolateSorted(x, y); break; default: break; } return(interpolatorU); }
public void SetRate(int index, double rate) { if (dateOffset == 1 && index == 0) { rates[0] = rate; } rates[index + dateOffset] = rate; spline = LinearSpline.InterpolateSorted(dateValues, rates); }
public override void Calculate() { Times = Generate.LinearSpaced(base.Samples, base.Start, base.Start + base.Duration); LinearSpline interpolator = (UserTimes.Length < 2) ? LinearSpline.InterpolateSorted(new double[] { UserTimes[0] + 1, UserTimes[0] }, new double[] { UserValues[0], UserValues[0] }) : LinearSpline.InterpolateSorted(UserTimes, UserValues); values = Times.Select(t => interpolator.Interpolate(t)).ToArray(); }
/// <summary> /// Interpolate the curve. /// </summary> /// <param name="date">The date at which the rate is required.</param> /// <returns></returns> public double InterpAtDate(Date date) { if (spline == null) { spline = LinearSpline.InterpolateSorted(this.dates, this.rates); } if (date.value < anchorDateValue) { throw new ArgumentException("Interpolation date (" + date.ToString() + ") is before the anchor date of the curve.(" + (new Date(anchorDateValue)).ToString() + ")"); } if (date.value > dates.Last()) { throw new ArgumentException("Interpolation date (" + date.ToString() + ") is after the last date on the curve.(" + (new Date(dates.Last())).ToString() + ")"); } return(spline.Interpolate(date)); }
public void SetDates(Date[] dates) { if (dates[0] > anchorDate) { List <Date> dateList = dates.ToList(); dateList.Insert(0, anchorDate); this.dates = dateList.ToArray(); dateOffset = 1; } else { this.dates = dates; } dateValues = this.dates.GetValues(); rates = Vector.Ones(this.dates.Length).Multiply(0.02); spline = LinearSpline.InterpolateSorted(dateValues, rates); }
public static object[,] InterpLinear([ExcelArgument(Description = "A vector of x values. Must be in increasing order")] double[] knownX, [ExcelArgument(Description = "A vector of y values. Must be the same length as knownX")] Double[] knownY, [ExcelArgument(Description = "x values at which interpolation is required.")] Double[,] requiredX) { LinearSpline spline = LinearSpline.InterpolateSorted(knownX, knownY); object[,] result = new object[requiredX.GetLength(0), requiredX.GetLength(1)]; for (int x = 0; x < requiredX.GetLength(0); x += 1) { for (int y = 0; y < requiredX.GetLength(1); y += 1) { result[x, y] = spline.Interpolate(requiredX[x, y]); } } return(result); }
private static IInterpolation GetInterpolator(ColorInterpolation interpolation, double[] x, double[] y) { switch (interpolation) { case ColorInterpolation.Akima: return(CubicSpline.InterpolateAkimaSorted(x, y)); case ColorInterpolation.Spline: return(CubicSpline.InterpolateNaturalSorted(x, y)); case ColorInterpolation.Linear: return(LinearSpline.InterpolateSorted(x, y)); default: throw new ArgumentException("interpolation"); } }
private static void prepareInterp(double[] ds, double[] ks, double[] scales, double[,,] coeffs, ref LinearSpline kInterp, ref LinearSpline scaleInterp, ref LinearSpline[,] coeffsInterps) { kInterp = LinearSpline.InterpolateSorted(ds, ks); scaleInterp = LinearSpline.InterpolateSorted(ds, scales); coeffsInterps = new LinearSpline[coeffs.GetLength(0), numCoeffs]; for (int i = 0; i < coeffs.GetLength(0); i++) { for (int j = 0; j < numCoeffs; j++) { double[] coeff_ij = new double[coeffs.GetLength(2)]; for (int k = 0; k < coeffs.GetLength(2); k++) { coeff_ij[k] = coeffs[i, j, k]; } coeffsInterps[i, j] = LinearSpline.InterpolateSorted(ds, coeff_ij); } } }
private double computeTapValue() { double modifiedAcc = getModifiedAcc(); // Assume SS for non-stream parts double accOnStreams = 1 - (1 - modifiedAcc) * totalHits / Attributes.StreamNoteCount; // accOnStreams can be negative. The formula below ensures a positive acc while // preserving the value when accOnStreams is close to 1 double accOnStreamsPositive = Math.Exp(accOnStreams - 1); double urOnStreams = 10 * (greatWindow) / (Math.Sqrt(2) * SpecialFunctions.ErfInv(accOnStreamsPositive)); double mashLevel = SpecialFunctions.Logistic(((urOnStreams * Attributes.BurstStrain) - 4000) / 1000); double tapSkill = LinearSpline.InterpolateSorted(Attributes.MashLevels, Attributes.TapSkills) .Interpolate(mashLevel); double tapValue = tapSkillToPP(tapSkill); // Buff high acc double accBuff = Math.Exp((accOnStreams - 1) * 60) * tapValue * 0.2f; tapValue += accBuff; // Penalize misses exponentially tapValue *= Math.Pow(0.93f, countMiss); double approachRateFactor = 1.0f; if (Attributes.ApproachRate > 10.33f) { approachRateFactor += 0.2f * (Attributes.ApproachRate - 10.33f); } tapValue *= approachRateFactor; return(tapValue); }
public InterpolatedCurve(double[] xVals, double[] yVals) { _spline = LinearSpline.InterpolateSorted(xVals, yVals); }
private double computeAimValue() { // Guess the number of misaims from combo int effectiveMissCount = Math.Max(countMiss, (int)(Math.Floor((beatmapMaxCombo - 0.1 * countSliders) / scoreMaxCombo))); // Get player's throughput according to combo int comboTPCount = Attributes.ComboTPs.Length; var comboPercentages = Generate.LinearSpaced(comboTPCount, 1.0 / comboTPCount, 1); double scoreComboPercentage = ((double)scoreMaxCombo) / beatmapMaxCombo; double comboTP = LinearSpline.InterpolateSorted(comboPercentages, Attributes.ComboTPs) .Interpolate(scoreComboPercentage); // Get player's throughput according to miss count double missTP; if (effectiveMissCount == 0) { missTP = Attributes.MissTPs[0]; } else { missTP = LinearSpline.InterpolateSorted(Attributes.MissCounts, Attributes.MissTPs) .Interpolate(effectiveMissCount); missTP = Math.Max(missTP, 0); } // Combine combo based throughput and miss count based throughput double tp = Math.Pow(comboTP, comboWeight) * Math.Pow(missTP, 1 - comboWeight); double modifiedAcc = getModifiedAcc(); double accOnCheeseNotes = 1 - (1 - modifiedAcc) * Math.Sqrt(totalHits / Attributes.CheeseNoteCount); // accOnCheeseNotes can be negative. The formula below ensures a positive acc while // preserving the value when accOnCheeseNotes is close to 1 double accOnCheeseNotesPositive = Math.Exp(accOnCheeseNotes - 1); double urOnCheeseNotes = 10 * greatWindow / (Math.Sqrt(2) * SpecialFunctions.ErfInv(accOnCheeseNotesPositive)); double cheeseLevel = SpecialFunctions.Logistic(((urOnCheeseNotes * Attributes.AimDiff) - 4300) / 2000); double cheeseFactor = LinearSpline.InterpolateSorted(Attributes.CheeseLevels, Attributes.CheeseFactors) .Interpolate(cheeseLevel); if (mods.Any(m => m is OsuModTouchDevice)) { tp = Math.Pow(tp, 0.8); } double aimValue = tpToPP(tp * cheeseFactor); // penalize misses aimValue *= Math.Pow(0.96f, effectiveMissCount); // Buff very high AR and low AR double approachRateFactor = 1.0f; if (Attributes.ApproachRate > 10.33f) { approachRateFactor += 0.2f * (Attributes.ApproachRate - 10.33f); } else if (Attributes.ApproachRate < 8.0f) { approachRateFactor += 0.01f * (8.0f - Attributes.ApproachRate); } aimValue *= approachRateFactor; // We want to give more reward for lower AR when it comes to aim and HD. This nerfs high AR and buffs lower AR. if (mods.Any(h => h is OsuModHidden)) { aimValue *= 1.0f + 0.04f * (12.0f - Attributes.ApproachRate); } if (mods.Any(h => h is OsuModFlashlight)) { // Apply object-based bonus for flashlight. aimValue *= 1.0f + 0.35f * Math.Min(1.0f, totalHits / 200.0f) + (totalHits > 200 ? 0.3f * Math.Min(1.0f, (totalHits - 200) / 300.0f) + (totalHits > 500 ? (totalHits - 500) / 2000.0f : 0.0f) : 0.0f); } // Scale the aim value down slightly with accuracy double accLeniency = greatWindow * Attributes.AimDiff / 300; double accPenalty = (SpecialFunctions.Logistic((accuracy - 0.97f) / (-0.01f)) - SpecialFunctions.Logistic(-3)) * (accLeniency + 1.5f) * 0.1f; aimValue *= Math.Exp(-accPenalty); return(aimValue); }
private double computeAimValue() { if (Attributes.TotalObjectCount <= 1) { return(0); } // Get player's throughput according to combo int comboTpCount = Attributes.ComboThroughputs.Length; var comboPercentages = Generate.LinearSpaced(comboTpCount, 1.0 / comboTpCount, 1); double scoreComboPercentage = ((double)scoreMaxCombo) / Attributes.MaxCombo; double comboTp = LinearSpline.InterpolateSorted(comboPercentages, Attributes.ComboThroughputs) .Interpolate(scoreComboPercentage); // Get player's throughput according to miss count double missTp = LinearSpline.InterpolateSorted(Attributes.MissCounts, Attributes.MissThroughputs) .Interpolate(effectiveMissCount); missTp = Math.Max(missTp, 0); // Combine combo based throughput and miss count based throughput double tp = PowerMean.Of(comboTp, missTp, 20); // Hidden mod if (mods.Any(h => h is OsuModHidden)) { double hiddenFactor = Attributes.AimHiddenFactor; // the buff starts decreasing at AR9.75 and reaches 0 at AR10.75 if (Attributes.ApproachRate > 10.75) { hiddenFactor = 1; } else if (Attributes.ApproachRate > 9.75) { hiddenFactor = 1 + (1 - Math.Pow(Math.Sin((Attributes.ApproachRate - 9.75) * Math.PI / 2), 2)) * (hiddenFactor - 1); } tp *= hiddenFactor; } // Account for cheesing double modifiedAcc = getModifiedAcc(); double accOnCheeseNotes = 1 - (1 - modifiedAcc) * Math.Sqrt(totalHits / Attributes.CheeseNoteCount); // accOnCheeseNotes can be negative. The formula below ensures a positive acc while // preserving the value when accOnCheeseNotes is close to 1 double accOnCheeseNotesPositive = Math.Exp(accOnCheeseNotes - 1); double urOnCheeseNotes = 10 * greatWindow / (Math.Sqrt(2) * SpecialFunctions.ErfInv(accOnCheeseNotesPositive)); double cheeseLevel = SpecialFunctions.Logistic(((urOnCheeseNotes * Attributes.AimDifficulty) - 3200) / 2000); double cheeseFactor = LinearSpline.InterpolateSorted(Attributes.CheeseLevels, Attributes.CheeseFactors) .Interpolate(cheeseLevel); if (mods.Any(m => m is OsuModTouchDevice)) { tp = Math.Min(tp, 1.47 * Math.Pow(tp, 0.8)); } double aimValue = tpToPP(tp * cheeseFactor); // penalize misses aimValue *= Math.Pow(0.96, Math.Max(effectiveMissCount - miss_count_leniency, 0)); // Buff long maps aimValue *= 1 + (SpecialFunctions.Logistic((totalHits - 2800) / 500.0) - SpecialFunctions.Logistic(-2800 / 500.0)) * 0.22; // Buff very high AR and low AR double approachRateFactor = 1.0; if (Attributes.ApproachRate > 10) { approachRateFactor += (0.05 + 0.35 * Math.Pow(Math.Sin(Math.PI * Math.Min(totalHits, 1250) / 2500), 1.7)) * Math.Pow(Attributes.ApproachRate - 10, 2); } else if (Attributes.ApproachRate < 8.0) { approachRateFactor += 0.01 * (8.0 - Attributes.ApproachRate); } aimValue *= approachRateFactor; if (mods.Any(h => h is OsuModFlashlight)) { // Apply object-based bonus for flashlight. aimValue *= 1.0 + 0.35 * Math.Min(1.0, totalHits / 200.0) + (totalHits > 200 ? 0.3 * Math.Min(1.0, (totalHits - 200) / 300.0) + (totalHits > 500 ? (totalHits - 500) / 2000.0 : 0.0) : 0.0); } // Scale the aim value down with accuracy double accLeniency = greatWindow * Attributes.AimDifficulty / 300; double accPenalty = (0.09 / (accuracy - 1.3) + 0.3) * (accLeniency + 1.5); aimValue *= 0.2 + SpecialFunctions.Logistic(-((accPenalty - 0.24953) / 0.18)); return(aimValue); }
private IInterpolation toInterpolation(IndexRange range) { double[] x = new double[range.Length]; double[] y = new double[x.Length]; Index next = range.Min.Copy(); switch (range.Direction) { case Direction.Horizontal: for (int i = 0; i < x.Length; i++) { Cell cell = this._cellularFloor.FindCell(next); x[i] = cell.U; y[i] = this.Potentials[cell]; next.I += 1; } break; case Direction.Vertical: for (int i = 0; i < x.Length; i++) { Cell cell = this._cellularFloor.FindCell(next); x[i] = cell.V; y[i] = this.Potentials[cell]; next.J += 1; } break; default: break; } IInterpolation interpolator = null; switch (Activity.InterpolationMethod) { case SpatialAnalysis.FieldUtility.InterpolationMethod.CubicSpline: if (x.Length > 1) { interpolator = CubicSpline.InterpolateBoundariesSorted(x, y, SplineBoundaryCondition.Natural, 0, SplineBoundaryCondition.Natural, 0); } else { interpolator = LinearSpline.InterpolateSorted(x, y); } break; //case FieldUtility.InterpolationMethod.Barycentric: // interpolator = Barycentric.InterpolatePolynomialEquidistantSorted(x, y); // break; case SpatialAnalysis.FieldUtility.InterpolationMethod.Linear: interpolator = LinearSpline.InterpolateSorted(x, y); break; default: break; } x = null; y = null; next = null; return(interpolator); }
public PairDouble evaluateResonanceFrequency(ChartTypes type, SignalUnits targetUnits, double approximationResonanceFrequency = 0.0) { int kNumSteps = 4096; // Only acceleration data is used to estimate the resonance frequency SignalUnits baseUnits = SignalUnits.UNKNOWN; if (data[SignalUnits.METERS_PER_SECOND2] != null) { baseUnits = SignalUnits.METERS_PER_SECOND2; } else if (data.ContainsKey(SignalUnits.METERS_PER_SECOND2_PER_FORCE) && data[SignalUnits.METERS_PER_SECOND2_PER_FORCE] != null) { baseUnits = SignalUnits.METERS_PER_SECOND2_PER_FORCE; } if (baseUnits == SignalUnits.UNKNOWN) { return(null); } double[,] complexData = data[baseUnits]; int nData = frequency.Length; double[] realPart = new double[nData]; double[] imagPart = new double[nData]; for (int i = 0; i != nData; ++i) { realPart[i] = complexData[i, 0]; imagPart[i] = complexData[i, 1]; } LinearSpline splineRealPart = LinearSpline.InterpolateSorted(frequency, realPart); LinearSpline splineImagPart = LinearSpline.InterpolateSorted(frequency, imagPart); List <double> resFrequencies = null; Func <double, double> fun = null; Func <double, double> diffFun = null; switch (type) { case ChartTypes.REAL_FREQUENCY: fun = x => splineRealPart.Interpolate(x); diffFun = x => splineRealPart.Differentiate(x); break; case ChartTypes.IMAG_FREQUENCY: fun = x => splineImagPart.Differentiate(x); diffFun = x => splineImagPart.Differentiate2(x); break; } if (fun == null || diffFun == null) { return(null); } double startFrequency = frequency[0]; double endFrequency = frequency[nData - 1]; resFrequencies = findAllRootsBisection(fun, startFrequency, endFrequency, kNumSteps); if (resFrequencies == null || resFrequencies.Count == 0) { return(null); } double distance; double minDistance = Double.MaxValue; int indClosestResonance = 0; int numFrequencies = resFrequencies.Count; for (int i = 0; i != numFrequencies; ++i) { try { resFrequencies[i] = NewtonRaphson.FindRootNearGuess(fun, diffFun, resFrequencies[i], startFrequency, endFrequency); } catch { } distance = Math.Abs(resFrequencies[i] - approximationResonanceFrequency); if (distance < minDistance) { minDistance = distance; indClosestResonance = i; } } double resonanceFrequency = resFrequencies[indClosestResonance]; // Evaluate the amplitude value by using data of the target type if (baseUnits != targetUnits) { complexData = data[targetUnits]; for (int i = 0; i != nData; ++i) { realPart[i] = complexData[i, 0]; imagPart[i] = complexData[i, 1]; } splineRealPart = LinearSpline.InterpolateSorted(frequency, realPart); splineImagPart = LinearSpline.InterpolateSorted(frequency, imagPart); } double realPeak = splineRealPart.Interpolate(resonanceFrequency); double imagPeak = splineImagPart.Interpolate(resonanceFrequency); double ampPeak = Math.Sqrt(Math.Pow(realPeak, 2.0) + Math.Pow(imagPeak, 2.0)); return(new PairDouble(resonanceFrequency, ampPeak)); }