Microsoft Solver Foundation和F#

时间:2016-09-18 03:27:44

标签: f# c#-to-f# ms-solver-foundation

我正在尝试将此MS Solver Foundation example从C#转换为F#,但不断遇到类型转换问题,特别是在第5节中,C#接受从double到Rational的隐式转换,F#不接受 - 任何想法如何解决? Rational类型本身对我来说是一个难题,因为除了将其设置为预定义的Rational.One或Rational.Zero之外,几乎不可能进行初始化。有任何想法吗?请参阅下面的简约缩小版本(不使用任何数组或任何内容)。

let main argv = 

printfn "%A" argv
Console.WriteLine("\nBegin Solver demo\n")
let mean = 1.0
let solver = new InteriorPointSolver()
let allocation = ref 0
solver.AddVariable("MSFT", allocation) |> ignore
solver.SetBounds(!allocation, Rational.Zero, Rational.One)

let expRet = ref 0
solver.AddRow("expRet", expRet) |> ignore
solver.SetBounds(!expRet, Rational.Zero, Rational.PositiveInfinity)

let unity = ref 0
solver.AddRow("Investments sum to one", unity) |> ignore
solver.SetBounds(!unity, Rational.One, Rational.One)

solver.SetCoefficient(!expRet, !allocation, Rational.)
solver.SetCoefficient(!unity, !allocation, Rational.One);

Console.WriteLine("\nEnd Solver demo\n")
Console.ReadLine() |> ignore
0 // return an integer exit code

1 个答案:

答案 0 :(得分:0)

这是一个旧帖子,但没有人回答,这些信息可能对其他人有用。

我不懂 F#(所以任何懂 F# 的人,请编辑我的语法),但 Rational 类中的以下方法应该有用。您还需要来自 Microsoft.SolverFoundation.Common 名称空间的 BigInteger 类。 (见https://docs.microsoft.com/en-us/previous-versions/visualstudio/ff526610

首先,正如您所指出的,您可以使用许多“隐式”构造函数中的任何一个,直接从其他类型构造一个 Rational:

    let Rational rat5 = Rational.op_Implicit(5.0:float)
    let Rational rat2 = Rational.op_Implicit(2:int)

我猜测 F# 语法的地方。

另一个非常有说明性的例子,货币价值(例如 10.43 美元)很少能用双精度准确表示。 (唯一“美分”值精确到双精度值是 xx.00、xx.25、xx.50 和 xx.75,所有其他值都会出现数字错误/差异。)所以当我们从一个声称代表货币价值的 double 构造一个理性时,我们经常必须小心。这为另一种构造有理数的方法提供了一个很好的示例:

    let BigInteger bi100 = BigInteger.op_Implicit(100:int)
    let float mv = 1000000000000.43 //I am assuming this gets classified by F# as a double.

    //Now, we assume mv is any double that represents a monetary value, and so should be an even 2 decimal places in base 10
    //I have no idea how to Round in F#, nor how to cast to an integer - I have guessed - but should illustrate the idea if it is not valid F#
    let BigInteger cents = BigInteger.op_Implicit( ( Round(mv * 100.0) ):int ) //get exact monetary value, in cents
    let Rational ratMv = Rational.Get(cents:BigInteger, bi100:BigInteger)

因此我们从两个 BigInteger 类型构建了一个 Rational,它准确地表示存储为双精度值的货币值 mv。

这里是整个 Rational 界面,尽管使用的是 c# 语法:

namespace Microsoft.SolverFoundation.Common
{
    [CLSCompliant(true)]
    public struct Rational : IComparable, IComparable<Rational>, IEquatable<Rational>, IComparable<BigInteger>, IEquatable<BigInteger>, IComparable<int>, IEquatable<int>, IComparable<uint>, IEquatable<uint>, IComparable<long>, IEquatable<long>, IComparable<ulong>, IEquatable<ulong>, IComparable<double>, IEquatable<double>
    {
        public static readonly Rational NegativeInfinity;
        public static readonly Rational Zero;
        public static readonly Rational One;
        public static readonly Rational PositiveInfinity;
        public static readonly Rational Indeterminate;
        public static readonly Rational UnsignedInfinity;

        public bool IsOne { get; }
        public bool IsFinite { get; }
        public bool IsIndeterminate { get; }
        public bool IsInfinite { get; }
        public bool IsSignedInfinity { get; }
        public bool IsUnsignedInfinity { get; }
        public bool HasSign { get; }
        public bool IsNegativeInfinity { get; }
        public bool IsZero { get; }
        public int BitCount { get; }
        public int Sign { get; }
        public BigInteger Numerator { get; }
        public bool IsPositiveInfinity { get; }
        public BigInteger Denominator { get; }
        public Rational AbsoluteValue { get; }

        public static Rational AddMul(Rational ratAdd, Rational ratMul1, Rational ratMul2);
        public static Rational Get(BigInteger bnNum, BigInteger bnDen);
        public static void Negate(ref Rational num);
        public static bool Power(Rational ratBase, Rational ratExp, out Rational ratRes);
        public void AppendDecimalString(StringBuilder sb, int cchMax);
        public int CompareTo(BigInteger bn);
        [CLSCompliant(false)]
        public int CompareTo(uint u);
        public int CompareTo(Rational rat);
        public int CompareTo(long nn);
        [CLSCompliant(false)]
        public int CompareTo(ulong uu);
        public int CompareTo(double dbl);
        public int CompareTo(int n);
        public int CompareTo(object obj);
        [CLSCompliant(false)]
        public bool Equals(uint u);
        public bool Equals(Rational rat);
        public bool Equals(long nn);
        [CLSCompliant(false)]
        public bool Equals(ulong uu);
        public bool Equals(int n);
        public bool Equals(BigInteger bn);
        public override bool Equals(object obj);
        public bool Equals(double dbl);
        public Rational GetCeiling();
        public Rational GetCeilingResidual();
        public Rational GetFloor();
        public Rational GetFloorResidual();
        public Rational GetFractionalPart();
        public override int GetHashCode();
        public Rational GetIntegerPart();
        public double GetSignedDouble();
        public Rational Invert();
        public bool IsInteger(out BigInteger bn);
        public bool IsInteger();
        public double ToDouble();
        public override string ToString();

        public static Rational operator +(Rational rat1, Rational rat2);
        public static Rational operator -(Rational rat);
        public static Rational operator -(Rational rat1, Rational rat2);
        public static Rational operator *(Rational rat1, Rational rat2);
        public static Rational operator /(Rational rat1, Rational rat2);
        [CLSCompliant(false)]
        public static bool operator ==(uint n, Rational rat);
        [CLSCompliant(false)]
        public static bool operator ==(Rational rat, uint n);
        public static bool operator ==(int n, Rational rat);
        public static bool operator ==(long n, Rational rat);
        public static bool operator ==(Rational rat, BigInteger bn);
        public static bool operator ==(Rational rat, int n);
        public static bool operator ==(Rational rat, long n);
        public static bool operator ==(BigInteger bn, Rational rat);
        public static bool operator ==(double dbl, Rational rat);
        [CLSCompliant(false)]
        public static bool operator ==(Rational rat, ulong n);
        public static bool operator ==(Rational rat1, Rational rat2);
        [CLSCompliant(false)]
        public static bool operator ==(ulong n, Rational rat);
        public static bool operator ==(Rational rat, double dbl);
        [CLSCompliant(false)]
        public static bool operator !=(ulong n, Rational rat);
        [CLSCompliant(false)]
        public static bool operator !=(Rational rat, ulong n);
        [CLSCompliant(false)]
        public static bool operator !=(uint n, Rational rat);
        public static bool operator !=(BigInteger bn, Rational rat);
        [CLSCompliant(false)]
        public static bool operator !=(Rational rat, uint n);
        public static bool operator !=(double dbl, Rational rat);
        public static bool operator !=(int n, Rational rat);
        public static bool operator !=(Rational rat, int n);
        public static bool operator !=(long n, Rational rat);
        public static bool operator !=(Rational rat, BigInteger bn);
        public static bool operator !=(Rational rat1, Rational rat2);
        public static bool operator !=(Rational rat, double dbl);
        public static bool operator !=(Rational rat, long n);
        public static bool operator <(double dbl, Rational rat);
        public static bool operator <(Rational rat, double dbl);
        [CLSCompliant(false)]
        public static bool operator <(ulong n, Rational rat);
        [CLSCompliant(false)]
        public static bool operator <(Rational rat, ulong n);
        [CLSCompliant(false)]
        public static bool operator <(uint n, Rational rat);
        public static bool operator <(Rational rat1, Rational rat2);
        public static bool operator <(Rational rat, BigInteger bn);
        public static bool operator <(long n, Rational rat);
        public static bool operator <(BigInteger bn, Rational rat);
        public static bool operator <(Rational rat, int n);
        public static bool operator <(int n, Rational rat);
        [CLSCompliant(false)]
        public static bool operator <(Rational rat, uint n);
        public static bool operator <(Rational rat, long n);
        public static bool operator >(long n, Rational rat);
        public static bool operator >(Rational rat1, Rational rat2);
        public static bool operator >(Rational rat, BigInteger bn);
        public static bool operator >(BigInteger bn, Rational rat);
        public static bool operator >(Rational rat, int n);
        [CLSCompliant(false)]
        public static bool operator >(Rational rat, uint n);
        public static bool operator >(double dbl, Rational rat);
        [CLSCompliant(false)]
        public static bool operator >(uint n, Rational rat);
        public static bool operator >(int n, Rational rat);
        public static bool operator >(Rational rat, long n);
        public static bool operator >(Rational rat, double dbl);
        [CLSCompliant(false)]
        public static bool operator >(ulong n, Rational rat);
        [CLSCompliant(false)]
        public static bool operator >(Rational rat, ulong n);
        [CLSCompliant(false)]
        public static bool operator <=(ulong n, Rational rat);
        public static bool operator <=(Rational rat, int n);
        public static bool operator <=(Rational rat, BigInteger bn);
        public static bool operator <=(int n, Rational rat);
        [CLSCompliant(false)]
        public static bool operator <=(Rational rat, uint n);
        public static bool operator <=(BigInteger bn, Rational rat);
        [CLSCompliant(false)]
        public static bool operator <=(Rational rat, ulong n);
        public static bool operator <=(Rational rat1, Rational rat2);
        public static bool operator <=(long n, Rational rat);
        public static bool operator <=(Rational rat, double dbl);
        public static bool operator <=(double dbl, Rational rat);
        [CLSCompliant(false)]
        public static bool operator <=(uint n, Rational rat);
        public static bool operator <=(Rational rat, long n);
        public static bool operator >=(Rational rat, BigInteger bn);
        public static bool operator >=(Rational rat1, Rational rat2);
        [CLSCompliant(false)]
        public static bool operator >=(Rational rat, ulong n);
        [CLSCompliant(false)]
        public static bool operator >=(uint n, Rational rat);
        public static bool operator >=(Rational rat, long n);
        public static bool operator >=(int n, Rational rat);
        public static bool operator >=(BigInteger bn, Rational rat);
        public static bool operator >=(Rational rat, int n);
        [CLSCompliant(false)]
        public static bool operator >=(ulong n, Rational rat);
        public static bool operator >=(long n, Rational rat);
        public static bool operator >=(double dbl, Rational rat);
        [CLSCompliant(false)]
        public static bool operator >=(Rational rat, uint n);
        public static bool operator >=(Rational rat, double dbl);

        public static implicit operator Rational(double dbl);
        public static implicit operator Rational(BigInteger bn);
        [CLSCompliant(false)]
        public static implicit operator Rational(uint u);
        public static implicit operator Rational(long nn);
        [CLSCompliant(false)]
        public static implicit operator Rational(ulong uu);
        public static implicit operator Rational(int n);
        public static explicit operator BigInteger(Rational rat);
        public static explicit operator double(Rational rat);
        [CLSCompliant(false)]
        public static explicit operator ulong(Rational rat);
        public static explicit operator long(Rational rat);
        [CLSCompliant(false)]
        public static explicit operator uint(Rational rat);
        public static explicit operator int(Rational rat);
    }
}

可以在上述链接中找到的另一个非常有用的信息是此表:

"下表列出了有理数的特殊情况是如何表示的。

<头>
有理数 代表
非零有限有理值 (numerator, denominator) 分母 > 0
(0, 0)
负无穷 (-1, 0)
正无穷 (+1, 0)
无符号无穷 (+2, 0)
不确定(NaN) (+3, 0)

将非零值除以零会导致无符号无穷大,因为 0 是无符号的。将有限值除以任何无限值的结果为 0。"