18using System.Collections;
19using System.Collections.Generic;
21using System.Runtime.CompilerServices;
22using Google.Protobuf.Collections;
37internal static class HelperExtensions
39 [MethodImpl(MethodImplOptions.AggressiveInlining)]
40 public static void AddOrIncrement(
this Dictionary<int, long> dict,
int key,
long increment)
43 System.Runtime.InteropServices.CollectionsMarshal.GetValueRefOrAddDefault(dict, key, out _) += increment;
45 if (dict.TryGetValue(key, out var value))
47 dict[key] = value + increment;
51 dict.Add(key, increment);
56 [MethodImpl(MethodImplOptions.AggressiveInlining)]
57 internal static void TrySetCapacity<TField, TValues>(
this RepeatedField<TField> field, IEnumerable<TValues> values)
59 if (values is ICollection<TValues> collection)
61 field.Capacity = collection.Count;
65 [MethodImpl(MethodImplOptions.AggressiveInlining)]
66 internal static void TryEnsureCapacity<TValue, TValues>(
this List<TValue> list, IEnumerable<TValues> values)
69 if (values is ICollection collection)
71 list.Capacity = Math.Max(list.Count + collection.Count, list.Capacity);
76 [MethodImpl(MethodImplOptions.AggressiveInlining)]
77 internal static bool TryDequeue<T>(
this Queue<T> queue, out T value)
81 value = queue.Dequeue();
100 this.coefficient = c;
168 return Prod(expr, coeff);
174 if (literal is
BoolVar boolVar)
176 return Prod(boolVar, coeff);
187 return Prod(var, coeff);
195 return Prod(expr, coeff);
365 internal static long GetVarValueMap(LinearExpr e, Dictionary<int, long> dict, Queue<Term> terms)
368 long coefficient = 1;
376 case LinearExprBuilder builder:
377 constant += coefficient * builder.Offset;
378 if (coefficient == 1)
380 foreach (
Term sub
in builder.Terms)
387 foreach (
Term sub
in builder.Terms)
389 terms.Enqueue(
new Term(sub.expr, sub.coefficient * coefficient));
394 dict.AddOrIncrement(intVar.GetIndex(), coefficient);
396 case NotBoolVar notBoolVar:
397 dict.AddOrIncrement(notBoolVar.Not().GetIndex(), -coefficient);
398 constant += coefficient;
401 throw new ArgumentException(
"Cannot evaluate '" + expr +
"' in an integer expression");
404 if (!terms.TryDequeue(out var term))
409 coefficient = term.coefficient;
415 internal static LinearExpr RebuildLinearExprFromLinearExpressionProto(LinearExpressionProto proto,
418 int numElements = proto.Vars.Count;
419 long offset = proto.Offset;
420 if (numElements == 0)
422 return LinearExpr.Constant(offset);
424 else if (numElements == 1)
426 IntVar var =
new IntVar(model, proto.Vars[0]);
427 long coeff = proto.Coeffs[0];
428 return LinearExpr.Affine(var, coeff, offset);
432 LinearExprBuilder builder = LinearExpr.NewBuilder(numElements);
433 for (
int i = 0; i < numElements; ++i)
435 builder.AddTerm(
new IntVar(model, proto.Vars[i]), proto.Coeffs[i]);
448 terms_ =
new List<Term>(sizeHint);
480 terms_.Add(
new Term(expr, coefficient));
487 if (literal is
BoolVar boolVar)
489 terms_.Add(
new Term(boolVar, coefficient));
493 offset_ += coefficient;
502 terms_.Add(
new Term(var, coefficient));
509 terms_.TryEnsureCapacity(exprs);
520 terms_.TryEnsureCapacity(literals);
521 foreach (
ILiteral literal
in literals)
531 terms_.TryEnsureCapacity(vars);
542 terms_.TryEnsureCapacity(exprs);
543 foreach (var p
in exprs.Zip(coefficients, (e, c) =>
new { Expr = e, Coeff = c }))
553 terms_.TryEnsureCapacity(exprs);
554 foreach (var p
in exprs.Zip(coefficients, (e, c) =>
new { Expr = e, Coeff = c }))
564 terms_.TryEnsureCapacity(literals);
565 foreach (var p
in literals.Zip(coefficients, (l, c) =>
new { Literal = l, Coeff = c }))
575 terms_.TryEnsureCapacity(literals);
576 foreach (var p
in literals.Zip(coefficients, (l, c) =>
new { Literal = l, Coeff = c }))
586 terms_.TryEnsureCapacity(vars);
587 foreach (var p
in vars.Zip(coefficients, (v, c) =>
new { Var = v, Coeff = c }))
597 terms_.TryEnsureCapacity(vars);
598 foreach (var p
in vars.Zip(coefficients, (v, c) =>
new { Var = v, Coeff = c }))
608 bool need_parenthesis =
false;
609 foreach (
Term term
in terms_)
611 bool first = String.IsNullOrEmpty(result);
621 need_parenthesis =
true;
624 result += term.
expr.ToString();
630 need_parenthesis =
true;
634 result += String.Format(
"{0} * {1}", term.
coefficient, term.
expr.ToString());
640 need_parenthesis =
true;
641 result += String.Format(
" - {0}", term.
expr.ToString());
645 result += String.Format(
"-{0}", term.
expr.ToString());
652 need_parenthesis =
true;
653 result += String.Format(
" - {0} * {1}", -term.
coefficient, term.
expr.ToString());
657 result += String.Format(
"{0} * {1}", term.
coefficient, term.
expr.ToString());
663 if (!String.IsNullOrEmpty(result))
665 need_parenthesis =
true;
666 result += String.Format(
" + {0}", offset_);
670 result += String.Format(
"{0}", offset_);
673 else if (offset_ < 0)
675 if (!String.IsNullOrEmpty(result))
677 need_parenthesis =
true;
678 result += String.Format(
" - {0}", -offset_);
682 result += String.Format(
"{0}", offset_);
686 if (need_parenthesis)
688 return string.Format(
"({0})", result);
707 private long offset_;
708 private List<Term> terms_;
735 var_.Domain.Capacity = 2;
871 return String.Format(
"Not({0})", boolvar_.
ToString());
874 private readonly
BoolVar boolvar_;
902 type_ =
Type.BoundExpression;
911 type_ = equality ? Type.VarEqVar :
Type.VarDiffVar;
920 type_ = equality ? Type.VarEqCst :
Type.VarDiffCst;
925 if (type_ ==
Type.VarEqVar)
927 return (
object)left_ == (object)right_;
929 else if (type_ ==
Type.VarDiffVar)
931 return (
object)left_ != (object)right_;
943 return !bie.IsTrue();
950 case Type.BoundExpression:
951 return String.Format(
"{0} <= {1} <= {2}", lb_, left_, ub_);
953 return String.Format(
"{0} == {1}", left_, right_);
954 case Type.VarDiffVar:
955 return String.Format(
"{0} != {1}", left_, right_);
957 return String.Format(
"{0} == {1}", left_, lb_);
958 case Type.VarDiffCst:
959 return String.Format(
"{0} != {1}", left_, lb_);
961 throw new ArgumentException(
"Wrong mode in BoundedLinearExpression.");
967 if (a.
CtType !=
Type.BoundExpression || a.
Ub != Int64.MaxValue)
969 throw new ArgumentException(
"Operator <= not supported for this BoundedLinearExpression");
976 if (a.
CtType !=
Type.BoundExpression || a.
Ub != Int64.MaxValue)
978 throw new ArgumentException(
"Operator < not supported for this BoundedLinearExpression");
985 if (a.
CtType !=
Type.BoundExpression || a.
Lb != Int64.MinValue)
987 throw new ArgumentException(
"Operator >= not supported for this BoundedLinearExpression");
994 if (a.
CtType !=
Type.BoundExpression || a.
Lb != Int64.MinValue)
996 throw new ArgumentException(
"Operator < not supported for this BoundedLinearExpression");
long[] FlattenedIntervals()