DotNet Reference

DotNet Reference

IntegerExpressions.cs
Go to the documentation of this file.
1 // Copyright 2010-2018 Google LLC
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 // http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
14 namespace Google.OrTools.Sat
15 {
16  using System;
17  using System.Collections.Generic;
18  using Google.OrTools.Util;
19 
20  // Helpers.
21 
22  // IntVar[] helper class.
23  public static class IntVarArrayHelper
24  {
25  [Obsolete("This Sum method is deprecated, please use LinearExpr.Sum() instead.")]
26  public static LinearExpr Sum(this IntVar[] vars)
27  {
28  return LinearExpr.Sum(vars);
29  }
30  [Obsolete("This ScalProd method is deprecated, please use LinearExpr.ScalProd() instead.")]
31  public static LinearExpr ScalProd(this IntVar[] vars, int[] coeffs)
32  {
33  return LinearExpr.ScalProd(vars, coeffs);
34  }
35  [Obsolete("This ScalProd method is deprecated, please use LinearExpr.ScalProd() instead.")]
36  public static LinearExpr ScalProd(this IntVar[] vars, long[] coeffs)
37  {
38  return LinearExpr.ScalProd(vars, coeffs);
39  }
40  }
41 
42  public interface ILiteral
43  {
44  ILiteral Not();
45  int GetIndex();
46  }
47 
48  // Holds an linear expression.
49  public class LinearExpr
50  {
51 
52  public static LinearExpr Sum(IEnumerable<IntVar> vars)
53  {
54  return new SumArray(vars);
55  }
56 
57  public static LinearExpr Sum(IEnumerable<LinearExpr> exprs)
58  {
59  return new SumArray(exprs);
60  }
61 
62  public static LinearExpr ScalProd(IEnumerable<IntVar> vars, IEnumerable<int> coeffs)
63  {
64  return new SumArray(vars, coeffs);
65  }
66  public static LinearExpr ScalProd(IEnumerable<IntVar> vars, IEnumerable<long> coeffs)
67  {
68  return new SumArray(vars, coeffs);
69  }
70 
71  public static LinearExpr Term(IntVar var, long coeff) {
72  return Prod(var, coeff);
73  }
74 
75  public int Index
76  {
77  get { return GetIndex(); }
78  }
79 
80  public virtual int GetIndex()
81  {
82  throw new NotImplementedException();
83  }
84 
85  public virtual string ShortString()
86  {
87  return ToString();
88  }
89 
91  {
92  return new SumArray(a, b);
93  }
94 
95  public static LinearExpr operator +(LinearExpr a, long v)
96  {
97  return new SumArray(a, v);
98  }
99 
100  public static LinearExpr operator +(long v, LinearExpr a)
101  {
102  return new SumArray(a, v);
103  }
104 
106  {
107  return new SumArray(a, Prod(b, -1));
108  }
109 
110  public static LinearExpr operator -(LinearExpr a, long v)
111  {
112  return new SumArray(a, -v);
113  }
114 
115  public static LinearExpr operator -(long v, LinearExpr a)
116  {
117  return new SumArray(Prod(a, -1), v);
118  }
119 
120  public static LinearExpr operator *(LinearExpr a, long v)
121  {
122  return Prod(a, v);
123  }
124 
125  public static LinearExpr operator *(long v, LinearExpr a)
126  {
127  return Prod(a, v);
128  }
129 
131  {
132  return Prod(a, -1);
133  }
134 
136  {
137  return new BoundedLinearExpression(a, b, true);
138  }
139 
141  {
142  return new BoundedLinearExpression(a, b, false);
143  }
144 
146  {
147  return new BoundedLinearExpression(a, v, true);
148  }
149 
151  {
152  return new BoundedLinearExpression(a, v, false);
153  }
154 
156  {
157  return new BoundedLinearExpression(v, a, Int64.MaxValue);
158  }
159 
161  {
162  return a <= v;
163  }
164 
166  {
167  return new BoundedLinearExpression(v + 1, a, Int64.MaxValue);
168  }
169 
171  {
172  return a < v;
173  }
174 
176  {
177  return new BoundedLinearExpression(Int64.MinValue, a, v);
178  }
179 
181  {
182  return a >= v;
183  }
184 
186  {
187  return new BoundedLinearExpression(Int64.MinValue, a, v - 1);
188  }
189 
191  {
192  return a > v;
193  }
194 
196  {
197  return new BoundedLinearExpression(0, a - b, Int64.MaxValue);
198  }
199 
201  {
202  return new BoundedLinearExpression(1, a - b, Int64.MaxValue);
203  }
204 
206  {
207  return new BoundedLinearExpression(Int64.MinValue, a - b, 0);
208  }
209 
211  {
212  return new BoundedLinearExpression(Int64.MinValue, a - b, -1);
213  }
214 
215  public static LinearExpr Prod(LinearExpr e, long v)
216  {
217  if (v == 1)
218  {
219  return e;
220  }
221  else if (e is ProductCst)
222  {
223  ProductCst p = (ProductCst)e;
224  return new ProductCst(p.Expr, p.Coeff * v);
225  }
226  else
227  {
228  return new ProductCst(e, v);
229  }
230  }
231 
232  public static long GetVarValueMap(LinearExpr e,
233  long initial_coeff,
234  Dictionary<IntVar, long> dict)
235  {
236  List<LinearExpr> exprs = new List<LinearExpr>();
237  List<long> coeffs = new List<long>();
238  if ((Object)e != null)
239  {
240  exprs.Add(e);
241  coeffs.Add(initial_coeff);
242  }
243  long constant = 0;
244 
245  while (exprs.Count > 0)
246  {
247  LinearExpr expr = exprs[0];
248  exprs.RemoveAt(0);
249  long coeff = coeffs[0];
250  coeffs.RemoveAt(0);
251  if (coeff == 0 || (Object)expr == null) continue;
252 
253  if (expr is ProductCst)
254  {
255  ProductCst p = (ProductCst)expr;
256  if (p.Coeff != 0)
257  {
258  exprs.Add(p.Expr);
259  coeffs.Add(p.Coeff * coeff);
260  }
261  }
262  else if (expr is SumArray)
263  {
264  SumArray a = (SumArray)expr;
265  constant += coeff * a.Constant;
266  foreach (LinearExpr sub in a.Expressions)
267  {
268  if (sub is IntVar)
269  {
270  IntVar i = (IntVar)sub;
271  if (dict.ContainsKey(i))
272  {
273  dict[i] += coeff;
274  }
275  else
276  {
277  dict.Add(i, coeff);
278  }
279  }
280  else if (sub is ProductCst && ((ProductCst)sub).Expr is IntVar)
281  {
282  ProductCst sub_prod = (ProductCst)sub;
283  IntVar i = (IntVar)sub_prod.Expr;
284  long sub_coeff = sub_prod.Coeff;
285 
286  if (dict.ContainsKey(i))
287  {
288  dict[i] += coeff * sub_coeff;
289  }
290  else
291  {
292  dict.Add(i, coeff * sub_coeff);
293  }
294  }
295  else
296  {
297  exprs.Add(sub);
298  coeffs.Add(coeff);
299  }
300  }
301  }
302  else if (expr is IntVar)
303  {
304  IntVar i = (IntVar)expr;
305  if (dict.ContainsKey(i))
306  {
307  dict[i] += coeff;
308  }
309  else
310  {
311  dict.Add(i, coeff);
312  }
313  }
314  else if (expr is NotBooleanVariable)
315  {
316  IntVar i = ((NotBooleanVariable)expr).NotVar();
317  if (dict.ContainsKey(i))
318  {
319  dict[i] -= coeff;
320  }
321  else
322  {
323  dict.Add(i, -coeff);
324  }
325  constant += coeff;
326  }
327  else
328  {
329  throw new ArgumentException("Cannot interpret '" + expr.ToString() +
330  "' in an integer expression");
331  }
332  }
333  return constant;
334  }
335  }
336 
337  public class ProductCst : LinearExpr
338  {
339  public ProductCst(LinearExpr e, long v)
340  {
341  expr_ = e;
342  coeff_ = v;
343  }
344 
345  public LinearExpr Expr
346  {
347  get { return expr_; }
348  }
349 
350  public long Coeff
351  {
352  get { return coeff_; }
353  }
354 
355  private LinearExpr expr_;
356  private long coeff_;
357 
358  }
359 
360  public class SumArray : LinearExpr
361  {
363  {
364  expressions_ = new List<LinearExpr>();
365  AddExpr(a);
366  AddExpr(b);
367  constant_ = 0L;
368  }
369 
370  public SumArray(LinearExpr a, long b)
371  {
372  expressions_ = new List<LinearExpr>();
373  AddExpr(a);
374  constant_ = b;
375  }
376 
377  public SumArray(IEnumerable<LinearExpr> exprs)
378  {
379  expressions_ = new List<LinearExpr>(exprs);
380  constant_ = 0L;
381  }
382 
383  public SumArray(IEnumerable<IntVar> vars)
384  {
385  expressions_ = new List<LinearExpr>(vars);
386  constant_ = 0L;
387  }
388 
389  public SumArray(IntVar[] vars, long[] coeffs)
390  {
391  expressions_ = new List<LinearExpr>(vars.Length);
392  for (int i = 0; i < vars.Length; ++i)
393  {
394  AddExpr(Prod(vars[i], coeffs[i]));
395  }
396  constant_ = 0L;
397  }
398  public SumArray(IEnumerable<IntVar> vars, IEnumerable<long> coeffs)
399  {
400  List<IntVar> tmp_vars = new List<IntVar>();
401  foreach (IntVar v in vars)
402  {
403  tmp_vars.Add(v);
404  }
405  List<long> tmp_coeffs = new List<long>();
406  foreach (long c in coeffs)
407  {
408  tmp_coeffs.Add(c);
409  }
410  if (tmp_vars.Count != tmp_coeffs.Count)
411  {
412  throw new ArgumentException(
413  "in SumArray(vars, coeffs), the two lists do not have the same length");
414  }
415  IntVar[] flat_vars = tmp_vars.ToArray();
416  long[] flat_coeffs = tmp_coeffs.ToArray();
417  expressions_ = new List<LinearExpr>(flat_vars.Length);
418  for (int i = 0; i < flat_vars.Length; ++i)
419  {
420  expressions_.Add(Prod(flat_vars[i], flat_coeffs[i]));
421  }
422  constant_ = 0L;
423  }
424 
425  public SumArray(IEnumerable<IntVar> vars, IEnumerable<int> coeffs)
426  {
427  List<IntVar> tmp_vars = new List<IntVar>();
428  foreach (IntVar v in vars)
429  {
430  tmp_vars.Add(v);
431  }
432  List<long> tmp_coeffs = new List<long>();
433  foreach (int c in coeffs)
434  {
435  tmp_coeffs.Add(c);
436  }
437  if (tmp_vars.Count != tmp_coeffs.Count)
438  {
439  throw new ArgumentException(
440  "in SumArray(vars, coeffs), the two lists do not have the same length");
441  }
442  IntVar[] flat_vars = tmp_vars.ToArray();
443  long[] flat_coeffs = tmp_coeffs.ToArray();
444  expressions_ = new List<LinearExpr>(flat_vars.Length);
445  for (int i = 0; i < flat_vars.Length; ++i)
446  {
447  expressions_.Add(Prod(flat_vars[i], flat_coeffs[i]));
448  }
449  constant_ = 0L;
450  }
451 
452  public void AddExpr(LinearExpr expr)
453  {
454  if ((Object)expr != null)
455  {
456  expressions_.Add(expr);
457  }
458  }
459 
460  public List<LinearExpr> Expressions
461  {
462  get { return expressions_; }
463  }
464 
465  public long Constant
466  {
467  get { return constant_; }
468  }
469 
470  public override string ShortString()
471  {
472  return String.Format("({0})", ToString());
473  }
474 
475  public override string ToString()
476  {
477  string result = "";
478  foreach (LinearExpr expr in expressions_)
479  {
480  if ((Object)expr == null) continue;
481  if (!String.IsNullOrEmpty(result))
482  {
483  result += String.Format(" + ");
484  }
485 
486  result += expr.ShortString();
487  }
488  return result;
489  }
490 
491  private List<LinearExpr> expressions_;
492  private long constant_;
493  }
494 
495  public class IntVar : LinearExpr, ILiteral
496  {
497  public IntVar(CpModelProto model, Domain domain, string name)
498  {
499  model_ = model;
500  index_ = model.Variables.Count;
501  var_ = new IntegerVariableProto();
502  var_.Name = name;
503  var_.Domain.Add(domain.FlattenedIntervals());
504  model.Variables.Add(var_);
505  negation_ = null;
506  }
507 
508  public int Index
509  {
510  get { return index_; }
511  }
512 
513  public override int GetIndex()
514  {
515  return index_;
516  }
517 
519  {
520  get { return var_; }
521  set { var_ = value; }
522  }
523 
524  public override string ToString()
525  {
526  return var_.ToString();
527  }
528 
529  public override string ShortString()
530  {
531  if (var_.Name != null)
532  {
533  return var_.Name;
534  }
535  else
536  {
537  return var_.ToString();
538  }
539  }
540 
541  public string Name()
542  {
543  return var_.Name;
544  }
545 
546  public ILiteral Not()
547  {
548  foreach (long b in var_.Domain)
549  {
550  if (b < 0 || b > 1)
551  {
552  throw new ArgumentException(
553  "Cannot call Not() on a non boolean variable");
554  }
555  }
556  if (negation_ == null)
557  {
558  negation_ = new NotBooleanVariable(this);
559  }
560  return negation_;
561  }
562 
563 
564  private CpModelProto model_;
565  private int index_;
566  private List<long> bounds_;
567  private IntegerVariableProto var_;
568  private NotBooleanVariable negation_;
569  }
570 
572  {
573  public NotBooleanVariable(IntVar boolvar)
574  {
575  boolvar_ = boolvar;
576  }
577 
578  public override int GetIndex()
579  {
580  return -boolvar_.Index - 1;
581  }
582 
583  public ILiteral Not()
584  {
585  return boolvar_;
586  }
587 
588  public IntVar NotVar()
589  {
590  return boolvar_;
591  }
592 
593  public override string ShortString()
594  {
595  return String.Format("Not({0})", boolvar_.ShortString());
596  }
597 
598  private IntVar boolvar_;
599  }
600 
602  {
603  public enum Type
604  {
605  BoundExpression,
606  VarEqVar,
607  VarDiffVar,
608  VarEqCst,
609  VarDiffCst,
610  }
611 
612  public BoundedLinearExpression(long lb, LinearExpr expr, long ub)
613  {
614  left_ = expr;
615  right_ = null;
616  lb_ = lb;
617  ub_ = ub;
618  type_ = Type.BoundExpression;
619  }
620 
622  bool equality)
623  {
624  left_ = left;
625  right_ = right;
626  lb_ = 0;
627  ub_ = 0;
628  type_ = equality ? Type.VarEqVar : Type.VarDiffVar;
629  }
630 
631  public BoundedLinearExpression(LinearExpr left, long v, bool equality)
632  {
633  left_ = left;
634  right_ = null;
635  lb_ = v;
636  ub_ = 0;
637  type_ = equality ? Type.VarEqCst : Type.VarDiffCst;
638  }
639 
640  bool IsTrue()
641  {
642  if (type_ == Type.VarEqVar)
643  {
644  return (object)left_ == (object)right_;
645  }
646  else if (type_ == Type.VarDiffVar)
647  {
648  return (object)left_ != (object)right_;
649  }
650  return false;
651  }
652 
653  public static bool operator true(BoundedLinearExpression bie)
654  {
655  return bie.IsTrue();
656  }
657 
658  public static bool operator false(BoundedLinearExpression bie)
659  {
660  return !bie.IsTrue();
661  }
662 
663  public override string ToString()
664  {
665  switch (type_)
666  {
667  case Type.BoundExpression:
668  return String.Format("{0} <= {1} <= {2}", lb_, left_, ub_);
669  case Type.VarEqVar:
670  return String.Format("{0} == {1}", left_, right_);
671  case Type.VarDiffVar:
672  return String.Format("{0} != {1}", left_, right_);
673  case Type.VarEqCst:
674  return String.Format("{0} == {1}", left_, lb_);
675  case Type.VarDiffCst:
676  return String.Format("{0} != {1}", left_, lb_);
677  default:
678  throw new ArgumentException("Wrong mode in BoundedLinearExpression.");
679  }
680  }
681 
683  long v)
684  {
685  if (a.CtType != Type.BoundExpression || a.Ub != Int64.MaxValue)
686  {
687  throw new ArgumentException(
688  "Operator <= not supported for this BoundedLinearExpression");
689  }
690  return new BoundedLinearExpression(a.Lb, a.Left, v);
691  }
692 
694  long v)
695  {
696  if (a.CtType != Type.BoundExpression || a.Ub != Int64.MaxValue)
697  {
698  throw new ArgumentException(
699  "Operator < not supported for this BoundedLinearExpression");
700  }
701  return new BoundedLinearExpression(a.Lb, a.Left, v - 1);
702  }
703 
705  long v)
706  {
707  if (a.CtType != Type.BoundExpression || a.Lb != Int64.MinValue)
708  {
709  throw new ArgumentException(
710  "Operator >= not supported for this BoundedLinearExpression");
711  }
712  return new BoundedLinearExpression(v, a.Left, a.Ub);
713  }
714 
716  long v)
717  {
718  if (a.CtType != Type.BoundExpression || a.Lb != Int64.MinValue)
719  {
720  throw new ArgumentException(
721  "Operator < not supported for this BoundedLinearExpression");
722  }
723  return new BoundedLinearExpression(v + 1, a.Left, a.Ub);
724  }
725 
726  public LinearExpr Left
727  {
728  get { return left_; }
729  }
730 
731  public LinearExpr Right
732  {
733  get { return right_; }
734  }
735 
736  public long Lb
737  {
738  get { return lb_; }
739  }
740 
741  public long Ub
742  {
743  get { return ub_; }
744  }
745 
746  public Type CtType
747  {
748  get { return type_; }
749  }
750 
751  private LinearExpr left_;
752  private LinearExpr right_;
753  private long lb_;
754  private long ub_;
755  private Type type_;
756  }
757 
758 } // namespace Google.OrTools.Sat
static long GetVarValueMap(LinearExpr e, long initial_coeff, Dictionary< IntVar, long > dict)
IntVar(CpModelProto model, Domain domain, string name)
SumArray(IEnumerable< IntVar > vars, IEnumerable< long > coeffs)
override string ShortString()
Definition: Domain.cs:17
BoundedLinearExpression(LinearExpr left, LinearExpr right, bool equality)
SumArray(IEnumerable< LinearExpr > exprs)
IntVar NotVar()
override int GetIndex()
List< LinearExpr > Expressions
long Constant
LinearExpr Expr
SumArray(IEnumerable< IntVar > vars)
An integer variable.
Definition: CpModel.pb.cs:225
long Coeff
static BoundedLinearExpression operator<(BoundedLinearExpression a, long v)
static LinearExpr ScalProd(IEnumerable< IntVar > vars, IEnumerable< long > coeffs)
static BoundedLinearExpression operator<(LinearExpr a, long v)
static LinearExpr Sum(IEnumerable< IntVar > vars)
Type
string Name()
ProductCst(LinearExpr e, long v)
ILiteral Not()
static BoundedLinearExpression operator!=(LinearExpr a, LinearExpr b)
static LinearExpr operator-(LinearExpr a, LinearExpr b)
static LinearExpr ScalProd(IEnumerable< IntVar > vars, IEnumerable< int > coeffs)
static LinearExpr operator*(LinearExpr a, long v)
static BoundedLinearExpression operator>(BoundedLinearExpression a, long v)
static BoundedLinearExpression operator>=(BoundedLinearExpression a, long v)
override string ShortString()
Definition: KInt64Vector.cs:11
override int GetIndex()
void AddExpr(LinearExpr expr)
override string ShortString()
int Index
long Lb
static LinearExpr Sum(this IntVar[] vars)
virtual int GetIndex()
ILiteral Not()
static LinearExpr Prod(LinearExpr e, long v)
static BoundedLinearExpression operator==(LinearExpr a, LinearExpr b)
SumArray(IntVar[] vars, long[] coeffs)
long Ub
override string ToString()
IntegerVariableProto Proto
override string ToString()
long[] FlattenedIntervals()
Definition: Domain.cs:84
static BoundedLinearExpression operator>=(LinearExpr a, long v)
static BoundedLinearExpression operator>(LinearExpr a, long v)
static LinearExpr ScalProd(this IntVar[] vars, long[] coeffs)
BoundedLinearExpression(long lb, LinearExpr expr, long ub)
static LinearExpr ScalProd(this IntVar[] vars, int[] coeffs)
LinearExpr Left
SumArray(IEnumerable< IntVar > vars, IEnumerable< int > coeffs)
override string ToString()
NotBooleanVariable(IntVar boolvar)
Definition: KInt64Vector.cs:11
static LinearExpr Sum(IEnumerable< LinearExpr > exprs)
static BoundedLinearExpression operator<=(LinearExpr a, long v)
static BoundedLinearExpression operator<=(BoundedLinearExpression a, long v)
Type CtType
BoundedLinearExpression(LinearExpr left, long v, bool equality)
LinearExpr Right
Definition: Domain.cs:11
public override string ToString()
ILiteral Not()
static LinearExpr operator+(LinearExpr a, LinearExpr b)
virtual string ShortString()
int Index
int GetIndex()
SumArray(LinearExpr a, long b)
static LinearExpr Term(IntVar var, long coeff)
SumArray(LinearExpr a, LinearExpr b)
Definition: CpModel.pb.cs:12