GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/arith/matrix.h Lines: 307 401 76.6 %
Date: 2021-08-14 Branches: 252 1116 22.6 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Tim King, Mathias Preiner, Morgan Deters
4
 *
5
 * This file is part of the cvc5 project.
6
 *
7
 * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS
8
 * in the top-level source directory and their institutional affiliations.
9
 * All rights reserved.  See the file COPYING in the top-level source
10
 * directory for licensing information.
11
 * ****************************************************************************
12
 * Sparse matrix implementations for different types.
13
 *
14
 * Sparse matrix implementations for different types.
15
 * This defines Matrix<T>, IntegerEqualityTables and Tableau.
16
 */
17
18
#include "cvc5_private.h"
19
20
#pragma once
21
22
#include <queue>
23
#include <utility>
24
#include <vector>
25
26
#include "base/output.h"
27
#include "theory/arith/arithvar.h"
28
#include "util/dense_map.h"
29
#include "util/index.h"
30
31
namespace cvc5 {
32
namespace theory {
33
namespace arith {
34
35
typedef Index EntryID;
36
const EntryID ENTRYID_SENTINEL = std::numeric_limits<EntryID>::max();
37
38
typedef Index RowIndex;
39
const RowIndex ROW_INDEX_SENTINEL  = std::numeric_limits<RowIndex>::max();
40
41
9853
class CoefficientChangeCallback {
42
public:
43
102575
  virtual ~CoefficientChangeCallback() {}
44
  virtual void update(RowIndex ridx, ArithVar nb, int oldSgn, int currSgn) = 0;
45
  virtual void multiplyRow(RowIndex ridx, int Sgn) = 0;
46
  virtual bool canUseRow(RowIndex ridx) const = 0;
47
};
48
49
92722
class NoEffectCCCB : public CoefficientChangeCallback {
50
public:
51
 void update(RowIndex ridx, ArithVar nb, int oldSgn, int currSgn) override;
52
 void multiplyRow(RowIndex ridx, int Sgn) override;
53
 bool canUseRow(RowIndex ridx) const override;
54
};
55
56
template<class T>
57
54559050
class MatrixEntry {
58
private:
59
  RowIndex d_rowIndex;
60
  ArithVar d_colVar;
61
62
  EntryID d_nextRow;
63
  EntryID d_nextCol;
64
65
  EntryID d_prevRow;
66
  EntryID d_prevCol;
67
68
  T d_coefficient;
69
70
public:
71
744800
  MatrixEntry():
72
    d_rowIndex(ROW_INDEX_SENTINEL),
73
    d_colVar(ARITHVAR_SENTINEL),
74
    d_nextRow(ENTRYID_SENTINEL),
75
    d_nextCol(ENTRYID_SENTINEL),
76
    d_prevRow(ENTRYID_SENTINEL),
77
    d_prevCol(ENTRYID_SENTINEL),
78
744800
    d_coefficient()
79
744800
  {}
80
81
25166637
  MatrixEntry(RowIndex row, ArithVar col, const T& coeff):
82
     d_rowIndex(row),
83
     d_colVar(col),
84
     d_nextRow(ENTRYID_SENTINEL),
85
     d_nextCol(ENTRYID_SENTINEL),
86
     d_prevRow(ENTRYID_SENTINEL),
87
     d_prevCol(ENTRYID_SENTINEL),
88
25166637
     d_coefficient(coeff)
89
25166637
  {}
90
91
private:
92
24727203
  bool unusedConsistent() const {
93
    return
94
49652511
      (d_rowIndex == ROW_INDEX_SENTINEL && d_colVar == ARITHVAR_SENTINEL) ||
95
25123413
      (d_rowIndex != ROW_INDEX_SENTINEL && d_colVar != ARITHVAR_SENTINEL);
96
  }
97
98
public:
99
100
323110905
  EntryID getNextRowEntryID() const {
101
323110905
    return d_nextRow;
102
  }
103
104
76769036
  EntryID getNextColEntryID() const {
105
76769036
    return d_nextCol;
106
  }
107
24529098
  EntryID getPrevRowEntryID() const {
108
24529098
    return d_prevRow;
109
  }
110
111
24529098
  EntryID getPrevColEntryID() const {
112
24529098
    return d_prevCol;
113
  }
114
115
39217280
  void setNextRowEntryID(EntryID id) {
116
39217280
    d_nextRow = id;
117
39217280
  }
118
43631215
  void setNextColEntryID(EntryID id) {
119
43631215
    d_nextCol = id;
120
43631215
  }
121
49397993
  void setPrevRowEntryID(EntryID id) {
122
49397993
    d_prevRow = id;
123
49397993
  }
124
48997974
  void setPrevColEntryID(EntryID id) {
125
48997974
    d_prevCol = id;
126
48997974
  }
127
128
80378330
  RowIndex getRowIndex() const{
129
80378330
    return d_rowIndex;
130
  }
131
132
229410304
  ArithVar getColVar() const{
133
229410304
    return d_colVar;
134
  }
135
136
256057729
  const T& getCoefficient() const {
137
256057729
    return d_coefficient;
138
  }
139
140
69204006
  T& getCoefficient(){
141
69204006
    return d_coefficient;
142
  }
143
144
  void setCoefficient(const T& t){
145
    d_coefficient = t;
146
  }
147
148
24529098
  void markBlank() {
149
24529098
    d_rowIndex = ROW_INDEX_SENTINEL;
150
24529098
    d_colVar = ARITHVAR_SENTINEL;
151
24529098
  }
152
153
24727203
  bool blank() const{
154
24727203
    Assert(unusedConsistent());
155
156
24727203
    return d_rowIndex == ROW_INDEX_SENTINEL;
157
  }
158
}; /* class MatrixEntry<T> */
159
160
template<class T>
161
19706
class MatrixEntryVector {
162
private:
163
  typedef MatrixEntry<T> EntryType;
164
  typedef std::vector<EntryType> EntryArray;
165
166
  EntryArray d_entries;
167
  std::queue<EntryID> d_freedEntries;
168
169
  uint32_t d_size;
170
171
public:
172
19706
  MatrixEntryVector():
173
19706
    d_entries(), d_freedEntries(), d_size(0)
174
19706
  {}
175
176
633072161
  const EntryType& operator[](EntryID id) const{
177
633072161
    Assert(inBounds(id));
178
633072161
    return d_entries[id];
179
  }
180
181
462518753
  EntryType& get(EntryID id){
182
462518753
    Assert(inBounds(id));
183
462518753
    return d_entries[id];
184
  }
185
186
24529098
  void freeEntry(EntryID id){
187
24529098
    Assert(get(id).blank());
188
24529098
    Assert(d_size > 0);
189
190
24529098
    d_freedEntries.push(id);
191
24529098
    --d_size;
192
24529098
  }
193
194
25166637
  EntryID newEntry(){
195
    EntryID newId;
196
25166637
    if(d_freedEntries.empty()){
197
725094
      newId = d_entries.size();
198
725094
      d_entries.push_back(MatrixEntry<T>());
199
    }else{
200
24441543
      newId = d_freedEntries.front();
201
24441543
      d_freedEntries.pop();
202
    }
203
25166637
    ++d_size;
204
25166637
    return newId;
205
  }
206
207
  uint32_t size() const{ return d_size; }
208
  uint32_t capacity() const{ return d_entries.capacity(); }
209
210
211
private:
212
1095590914
  bool inBounds(EntryID id) const{
213
1095590914
    return id <  d_entries.size();
214
  }
215
}; /* class MatrixEntryVector<T> */
216
217
template <class T, bool isRow>
218
class MatrixVector {
219
private:
220
  EntryID d_head;
221
  uint32_t d_size;
222
223
  MatrixEntryVector<T>* d_entries;
224
225
  class Iterator {
226
  private:
227
    EntryID d_curr;
228
    const MatrixEntryVector<T>* d_entries;
229
230
  public:
231
36597737
    Iterator(EntryID start, const MatrixEntryVector<T>* entries) :
232
36597737
      d_curr(start), d_entries(entries)
233
36597737
    {}
234
235
  public:
236
237
90589280
    EntryID getID() const {
238
90589280
      return d_curr;
239
    }
240
241
282052311
    const MatrixEntry<T>& operator*() const{
242
282052311
      Assert(!atEnd());
243
282052311
      return (*d_entries)[d_curr];
244
    }
245
246
350821745
    Iterator& operator++(){
247
350821745
      Assert(!atEnd());
248
350821745
      const MatrixEntry<T>& entry = (*d_entries)[d_curr];
249
350821745
      d_curr = isRow ? entry.getNextRowEntryID() : entry.getNextColEntryID();
250
350821745
      return *this;
251
    }
252
253
871174095
    bool atEnd() const {
254
871174095
      return d_curr == ENTRYID_SENTINEL;
255
    }
256
257
    bool operator==(const Iterator& i) const{
258
      return d_curr == i.d_curr && d_entries == i.d_entries;
259
    }
260
261
141346651
    bool operator!=(const Iterator& i) const{
262
141346651
      return !(d_curr == i.d_curr && d_entries == i.d_entries);
263
    }
264
  }; /* class MatrixVector<T, isRow>::Iterator */
265
266
public:
267
254569
  MatrixVector(MatrixEntryVector<T>* mev)
268
254569
    : d_head(ENTRYID_SENTINEL), d_size(0), d_entries(mev)
269
254569
  {}
270
271
  MatrixVector(EntryID head, uint32_t size, MatrixEntryVector<T>* mev)
272
    : d_head(head), d_size(size), d_entries(mev)
273
  {}
274
275
  typedef Iterator const_iterator;
276
28824945
  const_iterator begin() const {
277
28824945
    return Iterator(d_head, d_entries);
278
  }
279
7772792
  const_iterator end() const {
280
7772792
    return Iterator(ENTRYID_SENTINEL, d_entries);
281
  }
282
283
  EntryID getHead() const { return d_head; }
284
285
62530075
  uint32_t getSize() const { return d_size; }
286
287
50333274
  void insert(EntryID newId){
288
    if(isRow){
289
25166637
      d_entries->get(newId).setNextRowEntryID(d_head);
290
291
25166637
      if(d_head != ENTRYID_SENTINEL){
292
25073915
        d_entries->get(d_head).setPrevRowEntryID(newId);
293
      }
294
    }else{
295
25166637
      d_entries->get(newId).setNextColEntryID(d_head);
296
297
25166637
      if(d_head != ENTRYID_SENTINEL){
298
25016515
        d_entries->get(d_head).setPrevColEntryID(newId);
299
      }
300
    }
301
302
50333274
    d_head = newId;
303
50333274
    ++d_size;
304
50333274
  }
305
49058196
  void remove(EntryID id){
306
49058196
    Assert(d_size > 0);
307
49058196
    --d_size;
308
    if(isRow){
309
24529098
      EntryID prevRow = d_entries->get(id).getPrevRowEntryID();
310
24529098
      EntryID nextRow = d_entries->get(id).getNextRowEntryID();
311
312
24529098
      if(d_head == id){
313
10478455
        d_head = nextRow;
314
      }
315
24529098
      if(prevRow != ENTRYID_SENTINEL){
316
14050643
        d_entries->get(prevRow).setNextRowEntryID(nextRow);
317
      }
318
24529098
      if(nextRow != ENTRYID_SENTINEL){
319
24324078
        d_entries->get(nextRow).setPrevRowEntryID(prevRow);
320
      }
321
    }else{
322
24529098
      EntryID prevCol = d_entries->get(id).getPrevColEntryID();
323
24529098
      EntryID nextCol = d_entries->get(id).getNextColEntryID();
324
325
24529098
      if(d_head == id){
326
6064520
        d_head = nextCol;
327
      }
328
329
24529098
      if(prevCol != ENTRYID_SENTINEL){
330
18464578
        d_entries->get(prevCol).setNextColEntryID(nextCol);
331
      }
332
24529098
      if(nextCol != ENTRYID_SENTINEL){
333
23981459
        d_entries->get(nextCol).setPrevColEntryID(prevCol);
334
      }
335
    }
336
49058196
  }
337
}; /* class MatrixVector<T, isRow> */
338
339
template <class T>
340
  class RowVector : public MatrixVector<T, true>
341
{
342
private:
343
  typedef MatrixVector<T, true> SuperT;
344
public:
345
  typedef typename SuperT::const_iterator const_iterator;
346
347
92722
  RowVector(MatrixEntryVector<T>* mev) : SuperT(mev){}
348
  RowVector(EntryID head, uint32_t size, MatrixEntryVector<T>* mev)
349
    : SuperT(head, size, mev){}
350
};/* class RowVector<T> */
351
352
template <class T>
353
  class ColumnVector : public MatrixVector<T, false>
354
{
355
private:
356
  typedef MatrixVector<T, false> SuperT;
357
public:
358
  typedef typename SuperT::const_iterator const_iterator;
359
360
161847
  ColumnVector(MatrixEntryVector<T>* mev) : SuperT(mev){}
361
  ColumnVector(EntryID head, uint32_t size, MatrixEntryVector<T>* mev)
362
    : SuperT(head, size, mev){}
363
};/* class ColumnVector<T> */
364
365
template <class T>
366
19706
class Matrix {
367
public:
368
  typedef MatrixEntry<T> Entry;
369
370
protected:
371
 typedef cvc5::theory::arith::RowVector<T> RowVectorT;
372
 typedef cvc5::theory::arith::ColumnVector<T> ColumnVectorT;
373
374
public:
375
  typedef typename RowVectorT::const_iterator RowIterator;
376
  typedef typename ColumnVectorT::const_iterator ColIterator;
377
378
protected:
379
  // RowTable : RowID |-> RowVector
380
  typedef std::vector< RowVectorT > RowTable;
381
  RowTable d_rows;
382
383
  // ColumnTable : ArithVar |-> ColumnVector
384
  typedef std::vector< ColumnVectorT > ColumnTable;
385
  ColumnTable d_columns;
386
387
  /* The merge buffer is used to store a row in order to optimize row addition. */
388
  typedef std::pair<EntryID, bool> PosUsedPair;
389
  typedef DenseMap< PosUsedPair > RowToPosUsedPairMap;
390
  RowToPosUsedPairMap d_mergeBuffer;
391
392
  /* The row that is in the merge buffer. */
393
  RowIndex d_rowInMergeBuffer;
394
395
  uint32_t d_entriesInUse;
396
  MatrixEntryVector<T> d_entries;
397
398
  std::vector<RowIndex> d_pool;
399
400
  T d_zero;
401
402
public:
403
  /**
404
   * Constructs an empty Matrix.
405
   */
406
  Matrix()
407
  : d_rows(),
408
    d_columns(),
409
    d_mergeBuffer(),
410
    d_rowInMergeBuffer(ROW_INDEX_SENTINEL),
411
    d_entriesInUse(0),
412
    d_entries(),
413
    d_zero(0)
414
  {}
415
416
19706
  Matrix(const T& zero)
417
  : d_rows(),
418
    d_columns(),
419
    d_mergeBuffer(),
420
    d_rowInMergeBuffer(ROW_INDEX_SENTINEL),
421
    d_entriesInUse(0),
422
    d_entries(),
423
19706
    d_zero(zero)
424
19706
  {}
425
426
  Matrix(const Matrix& m)
427
  : d_rows(),
428
    d_columns(),
429
    d_mergeBuffer(m.d_mergeBuffer),
430
    d_rowInMergeBuffer(m.d_rowInMergeBuffer),
431
    d_entriesInUse(m.d_entriesInUse),
432
    d_entries(m.d_entries),
433
    d_zero(m.d_zero)
434
  {
435
    d_columns.clear();
436
    for(typename ColumnTable::const_iterator c=m.d_columns.begin(), cend = m.d_columns.end(); c!=cend; ++c){
437
      const ColumnVectorT& col = *c;
438
      d_columns.push_back(ColumnVectorT(col.getHead(),col.getSize(),&d_entries));
439
    }
440
    d_rows.clear();
441
    for(typename RowTable::const_iterator r=m.d_rows.begin(), rend = m.d_rows.end(); r!=rend; ++r){
442
      const RowVectorT& row = *r;
443
      d_rows.push_back(RowVectorT(row.getHead(),row.getSize(),&d_entries));
444
    }
445
  }
446
447
  Matrix& operator=(const Matrix& m){
448
    d_mergeBuffer = (m.d_mergeBuffer);
449
    d_rowInMergeBuffer = (m.d_rowInMergeBuffer);
450
    d_entriesInUse = (m.d_entriesInUse);
451
    d_entries = (m.d_entries);
452
    d_zero = (m.d_zero);
453
    d_columns.clear();
454
    for(typename ColumnTable::const_iterator c=m.d_columns.begin(), cend = m.d_columns.end(); c!=cend; ++c){
455
      const ColumnVector<T>& col = *c;
456
      d_columns.push_back(ColumnVector<T>(col.getHead(), col.getSize(), &d_entries));
457
    }
458
    d_rows.clear();
459
    for(typename RowTable::const_iterator r=m.d_rows.begin(), rend = m.d_rows.end(); r!=rend; ++r){
460
      const RowVector<T>& row = *r;
461
      d_rows.push_back(RowVector<T>(row.getHead(), row.getSize(), &d_entries));
462
    }
463
    return *this;
464
  }
465
466
protected:
467
468
25166637
  void addEntry(RowIndex row, ArithVar col, const T& coeff){
469
25166637
    Debug("tableau") << "addEntry(" << row << "," << col <<"," << coeff << ")" << std::endl;
470
471
25166637
    Assert(coeff != 0);
472
25166637
    Assert(row < d_rows.size());
473
25166637
    Assert(col < d_columns.size());
474
475
25166637
    EntryID newId = d_entries.newEntry();
476
25166637
    Entry& newEntry = d_entries.get(newId);
477
25166637
    newEntry = Entry(row, col, coeff);
478
479
25166637
    Assert(newEntry.getCoefficient() != 0);
480
481
25166637
    ++d_entriesInUse;
482
483
25166637
    d_rows[row].insert(newId);
484
25166637
    d_columns[col].insert(newId);
485
25166637
  }
486
487
24529098
  void removeEntry(EntryID id){
488
24529098
    Assert(d_entriesInUse > 0);
489
24529098
    --d_entriesInUse;
490
491
24529098
    Entry& entry = d_entries.get(id);
492
493
24529098
    RowIndex ridx = entry.getRowIndex();
494
24529098
    ArithVar col = entry.getColVar();
495
496
24529098
    Assert(d_rows[ridx].getSize() > 0);
497
24529098
    Assert(d_columns[col].getSize() > 0);
498
499
24529098
    d_rows[ridx].remove(id);
500
24529098
    d_columns[col].remove(id);
501
502
24529098
    entry.markBlank();
503
504
24529098
    d_entries.freeEntry(id);
505
24529098
  }
506
507
 private:
508
92722
  RowIndex requestRowIndex(){
509
92722
    if(d_pool.empty()){
510
92722
      RowIndex ridx = d_rows.size();
511
92722
      d_rows.push_back(RowVectorT(&d_entries));
512
92722
      return ridx;
513
    }else{
514
      RowIndex rid = d_pool.back();
515
      d_pool.pop_back();
516
      return rid;
517
    }
518
  }
519
520
  void releaseRowIndex(RowIndex rid){
521
    d_pool.push_back(rid);
522
  }
523
524
public:
525
526
  size_t getNumRows() const {
527
    return d_rows.size();
528
  }
529
530
306684
  size_t getNumColumns() const {
531
306684
    return d_columns.size();
532
  }
533
534
161847
  void increaseSize(){
535
161847
    d_columns.push_back(ColumnVector<T>(&d_entries));
536
161847
  }
537
538
  void increaseSizeTo(size_t s){
539
    while(getNumColumns() < s){
540
      increaseSize();
541
    }
542
  }
543
544
39551858
  const RowVector<T>& getRow(RowIndex r) const {
545
39551858
    Assert(r < d_rows.size());
546
39551858
    return d_rows[r];
547
  }
548
549
9725338
  const ColumnVector<T>& getColumn(ArithVar v) const {
550
9725338
    Assert(v < d_columns.size());
551
9725338
    return d_columns[v];
552
  }
553
554
10492993
  uint32_t getRowLength(RowIndex r) const{
555
10492993
    return getRow(r).getSize();
556
  }
557
558
2978886
  uint32_t getColLength(ArithVar x) const{
559
2978886
    return getColumn(x).getSize();
560
  }
561
562
  /**
563
   * Adds a row to the matrix.
564
   * The new row is equivalent to:
565
   *   \f$\sum_i\f$ coeffs[i] * variables[i]
566
   */
567
92722
  RowIndex addRow(const std::vector<T>& coeffs,
568
                  const std::vector<ArithVar>& variables){
569
570
92722
    RowIndex ridx = requestRowIndex();
571
572
    //RowIndex ridx = d_rows.size();
573
    //d_rows.push_back(RowVectorT(&d_entries));
574
575
92722
    typename std::vector<T>::const_iterator coeffIter = coeffs.begin();
576
92722
    std::vector<ArithVar>::const_iterator varsIter = variables.begin();
577
92722
    std::vector<ArithVar>::const_iterator varsEnd = variables.end();
578
579
520646
    for(; varsIter != varsEnd; ++coeffIter, ++varsIter){
580
213962
      const T& coeff = *coeffIter;
581
213962
      ArithVar var_i = *varsIter;
582
213962
      Assert(var_i < getNumColumns());
583
213962
      addEntry(ridx, var_i, coeff);
584
    }
585
586
92722
    return ridx;
587
  }
588
589
590
250182
  void loadRowIntoBuffer(RowIndex rid){
591
250182
    Assert(d_mergeBuffer.empty());
592
250182
    Assert(d_rowInMergeBuffer == ROW_INDEX_SENTINEL);
593
594
250182
    RowIterator i = getRow(rid).begin(), i_end = getRow(rid).end();
595
10663878
    for(; i != i_end; ++i){
596
5206848
      EntryID id = i.getID();
597
5206848
      const MatrixEntry<T>& entry = *i;
598
5206848
      ArithVar colVar = entry.getColVar();
599
10413696
      d_mergeBuffer.set(colVar, std::make_pair(id, false));
600
    }
601
602
250182
    d_rowInMergeBuffer = rid;
603
250182
  }
604
605
250182
  void clearBuffer() {
606
250182
    Assert(d_rowInMergeBuffer != ROW_INDEX_SENTINEL);
607
608
250182
    d_rowInMergeBuffer = ROW_INDEX_SENTINEL;
609
250182
    d_mergeBuffer.purge();
610
250182
  }
611
612
  /* to *= mult */
613
  void multiplyRowByConstant(RowIndex to, const T& mult){
614
    RowIterator i = getRow(to).begin();
615
    RowIterator i_end = getRow(to).end();
616
    for( ; i != i_end; ++i){
617
      EntryID id = i.getID();
618
      Entry& entry = d_entries.get(id);
619
      T& coeff = entry.getCoefficient();
620
      coeff *= mult;
621
    }
622
  }
623
624
  /**  to += mult * from.
625
   * Use the more efficient rowPlusBufferTimesConstant() for
626
   * repeated use.
627
   */
628
  void rowPlusRowTimesConstant(RowIndex to, RowIndex from, const T& mult){
629
    Assert(to != from);
630
    loadRowIntoBuffer(from);
631
    rowPlusBufferTimesConstant(to, mult);
632
    clearBuffer();
633
  }
634
635
  /**  to += mult * buffer.
636
   * Invalidates coefficients on the row.
637
   * (mult should never be a direct copy of a coefficient!)
638
   */
639
  void rowPlusBufferTimesConstant(RowIndex to, const T& mult){
640
    Assert(d_rowInMergeBuffer != ROW_INDEX_SENTINEL);
641
    Assert(to != ROW_INDEX_SENTINEL);
642
643
    Debug("tableau") << "rowPlusRowTimesConstant("
644
                     << to << "," << mult << "," << d_rowInMergeBuffer << ")"
645
                     << std::endl;
646
647
    Assert(debugNoZeroCoefficients(to));
648
    Assert(debugNoZeroCoefficients(d_rowInMergeBuffer));
649
650
    Assert(mult != 0);
651
652
    RowIterator i = getRow(to).begin();
653
    RowIterator i_end = getRow(to).end();
654
    while(i != i_end){
655
      EntryID id = i.getID();
656
      Entry& entry = d_entries.get(id);
657
      ArithVar colVar = entry.getColVar();
658
659
      ++i;
660
661
      if(d_mergeBuffer.isKey(colVar)){
662
        EntryID bufferEntry = d_mergeBuffer[colVar].first;
663
        Assert(!d_mergeBuffer[colVar].second);
664
        d_mergeBuffer.get(colVar).second = true;
665
666
        const Entry& other = d_entries.get(bufferEntry);
667
        T& coeff = entry.getCoefficient();
668
        coeff += mult * other.getCoefficient();
669
670
        if(coeff.sgn() == 0){
671
          removeEntry(id);
672
        }
673
      }
674
    }
675
676
    i = getRow(d_rowInMergeBuffer).begin();
677
    i_end = getRow(d_rowInMergeBuffer).end();
678
679
    for(; i != i_end; ++i){
680
      const Entry& entry = *i;
681
      ArithVar colVar = entry.getColVar();
682
683
      if(d_mergeBuffer[colVar].second){
684
        d_mergeBuffer.get(colVar).second = false;
685
      }else{
686
        Assert(!(d_mergeBuffer[colVar]).second);
687
        T newCoeff =  mult * entry.getCoefficient();
688
        addEntry(to, colVar, newCoeff);
689
      }
690
    }
691
692
    Assert(mergeBufferIsClear());
693
694
    if(Debug.isOn("matrix")) { printMatrix(); }
695
  }
696
697
  /**  to += mult * buffer. */
698
3563200
  void rowPlusBufferTimesConstant(RowIndex to, const T& mult, CoefficientChangeCallback& cb){
699
3563200
    Assert(d_rowInMergeBuffer != ROW_INDEX_SENTINEL);
700
3563200
    Assert(to != ROW_INDEX_SENTINEL);
701
702
7126400
    Debug("tableau") << "rowPlusRowTimesConstant("
703
3563200
                     << to << "," << mult << "," << d_rowInMergeBuffer << ")"
704
                     << std::endl;
705
706
3563200
    Assert(debugNoZeroCoefficients(to));
707
3563200
    Assert(debugNoZeroCoefficients(d_rowInMergeBuffer));
708
709
3563200
    Assert(mult != 0);
710
711
3563200
    RowIterator i = getRow(to).begin();
712
3563200
    RowIterator i_end = getRow(to).end();
713
132958384
    while(i != i_end){
714
64697592
      EntryID id = i.getID();
715
64697592
      Entry& entry = d_entries.get(id);
716
64697592
      ArithVar colVar = entry.getColVar();
717
718
64697592
      ++i;
719
720
64697592
      if(d_mergeBuffer.isKey(colVar)){
721
35464822
        EntryID bufferEntry = d_mergeBuffer[colVar].first;
722
35464822
        Assert(!d_mergeBuffer[colVar].second);
723
35464822
        d_mergeBuffer.get(colVar).second = true;
724
725
35464822
        const Entry& other = d_entries.get(bufferEntry);
726
35464822
        T& coeff = entry.getCoefficient();
727
35464822
        int coeffOldSgn = coeff.sgn();
728
35464822
        coeff += mult * other.getCoefficient();
729
35464822
        int coeffNewSgn = coeff.sgn();
730
731
35464822
        if(coeffOldSgn != coeffNewSgn){
732
28324249
          cb.update(to, colVar, coeffOldSgn,  coeffNewSgn);
733
734
28324249
          if(coeffNewSgn == 0){
735
24529098
            removeEntry(id);
736
          }
737
        }
738
      }
739
    }
740
741
3563200
    i = getRow(d_rowInMergeBuffer).begin();
742
3563200
    i_end = getRow(d_rowInMergeBuffer).end();
743
744
124212750
    for(; i != i_end; ++i){
745
60324775
      const Entry& entry = *i;
746
60324775
      ArithVar colVar = entry.getColVar();
747
748
60324775
      if(d_mergeBuffer[colVar].second){
749
35464822
        d_mergeBuffer.get(colVar).second = false;
750
      }else{
751
24859953
        Assert(!(d_mergeBuffer[colVar]).second);
752
49719906
        T newCoeff =  mult * entry.getCoefficient();
753
24859953
        addEntry(to, colVar, newCoeff);
754
755
24859953
        cb.update(to, colVar, 0,  newCoeff.sgn());
756
      }
757
    }
758
759
3563200
    Assert(mergeBufferIsClear());
760
761
3563200
    if(Debug.isOn("matrix")) { printMatrix(); }
762
3563200
  }
763
764
3563200
  bool mergeBufferIsClear() const{
765
3563200
    RowToPosUsedPairMap::const_iterator i = d_mergeBuffer.begin();
766
3563200
    RowToPosUsedPairMap::const_iterator i_end = d_mergeBuffer.end();
767
124212750
    for(; i != i_end; ++i){
768
60324775
      RowIndex rid = *i;
769
60324775
      if(d_mergeBuffer[rid].second){
770
        return false;
771
      }
772
    }
773
3563200
    return true;
774
  }
775
776
protected:
777
778
298039
  EntryID findOnRow(RowIndex rid, ArithVar column) const {
779
298039
    RowIterator i = d_rows[rid].begin(), i_end = d_rows[rid].end();
780
6587367
    for(; i != i_end; ++i){
781
3442703
      EntryID id = i.getID();
782
3442703
      const MatrixEntry<T>& entry = *i;
783
3442703
      ArithVar colVar = entry.getColVar();
784
785
3442703
      if(colVar == column){
786
298039
        return id;
787
      }
788
    }
789
    return ENTRYID_SENTINEL;
790
  }
791
792
98171
  EntryID findOnCol(RowIndex rid, ArithVar column) const{
793
98171
    ColIterator i = d_columns[column].begin(), i_end = d_columns[column].end();
794
498131
    for(; i != i_end; ++i){
795
298151
      EntryID id = i.getID();
796
298151
      const MatrixEntry<T>& entry = *i;
797
298151
      RowIndex currRow = entry.getRowIndex();
798
799
298151
      if(currRow == rid){
800
98171
        return id;
801
      }
802
    }
803
    return ENTRYID_SENTINEL;
804
  }
805
806
198105
  EntryID findEntryID(RowIndex rid, ArithVar col) const{
807
198105
    bool colIsShorter = getColLength(col) < getRowLength(rid);
808
198105
    EntryID id = colIsShorter ? findOnCol(rid, col) : findOnRow(rid,col);
809
198105
    return id;
810
  }
811
  MatrixEntry<T> d_failedFind;
812
public:
813
814
  /** If the find fails, isUnused is true on the entry. */
815
198105
  const MatrixEntry<T>& findEntry(RowIndex rid, ArithVar col) const{
816
198105
    EntryID id = findEntryID(rid, col);
817
198105
    if(id == ENTRYID_SENTINEL){
818
      return d_failedFind;
819
    }else{
820
198105
      return d_entries[id];
821
    }
822
  }
823
824
  /**
825
   * Prints the contents of the Matrix to Debug("matrix")
826
   */
827
  void printMatrix(std::ostream& out) const {
828
    out << "Matrix::printMatrix"  << std::endl;
829
830
    for(RowIndex i = 0, N = d_rows.size(); i < N; ++i){
831
      printRow(i, out);
832
    }
833
  }
834
  void printMatrix() const {
835
    printMatrix(Debug("matrix"));
836
  }
837
838
  void printRow(RowIndex rid, std::ostream& out) const {
839
    out << "{" << rid << ":";
840
    const RowVector<T>& row = getRow(rid);
841
    RowIterator i = row.begin();
842
    RowIterator i_end = row.end();
843
    for(; i != i_end; ++i){
844
      printEntry(*i, out);
845
      out << ",";
846
    }
847
    out << "}" << std::endl;
848
  }
849
  void printRow(RowIndex rid) const {
850
    printRow(rid, Debug("matrix"));
851
  }
852
853
  void printEntry(const MatrixEntry<T>& entry, std::ostream& out) const {
854
    out << entry.getColVar() << "*" << entry.getCoefficient();
855
  }
856
  void printEntry(const MatrixEntry<T>& entry) const {
857
    printEntry(entry, Debug("matrix"));
858
  }
859
public:
860
15204
  uint32_t size() const {
861
15204
    return d_entriesInUse;
862
  }
863
  uint32_t getNumEntriesInTableau() const {
864
    return d_entries.size();
865
  }
866
  uint32_t getEntryCapacity() const {
867
    return d_entries.capacity();
868
  }
869
870
  void manipulateRowEntry(RowIndex row, ArithVar col, const T& c, CoefficientChangeCallback& cb){
871
    int coeffOldSgn;
872
    int coeffNewSgn;
873
874
    EntryID id = findEntryID(row, col);
875
    if(id == ENTRYID_SENTINEL){
876
      coeffOldSgn = 0;
877
      addEntry(row, col, c);
878
      coeffNewSgn = c.sgn();
879
    }else{
880
      Entry& e = d_entries.get(id);
881
      T& t = e.getCoefficient();
882
      coeffOldSgn = t.sgn();
883
      t += c;
884
      coeffNewSgn = t.sgn();
885
    }
886
887
    if(coeffOldSgn != coeffNewSgn){
888
      cb.update(row, col, coeffOldSgn,  coeffNewSgn);
889
    }
890
    if(coeffNewSgn == 0){
891
      removeEntry(id);
892
    }
893
  }
894
895
  void removeRow(RowIndex rid){
896
    RowIterator i = getRow(rid).begin();
897
    RowIterator i_end = getRow(rid).end();
898
    for(; i != i_end; ++i){
899
      EntryID id = i.getID();
900
      removeEntry(id);
901
    }
902
    releaseRowIndex(rid);
903
  }
904
905
  double densityMeasure() const{
906
    Assert(numNonZeroEntriesByRow() == numNonZeroEntries());
907
    Assert(numNonZeroEntriesByCol() == numNonZeroEntries());
908
909
    uint32_t n = getNumRows();
910
    if(n == 0){
911
      return 1.0;
912
    }else {
913
      uint32_t s = numNonZeroEntries();
914
      uint32_t m = d_columns.size();
915
      uint32_t divisor = (n *(m - n + 1));
916
917
      Assert(n >= 1);
918
      Assert(m >= n);
919
      Assert(divisor > 0);
920
      Assert(divisor >= s);
921
922
      return (double(s)) / divisor;
923
    }
924
  }
925
926
  void loadSignQueries(RowIndex rid, DenseMap<int>& target) const{
927
928
    RowIterator i = getRow(rid).begin(), i_end = getRow(rid).end();
929
    for(; i != i_end; ++i){
930
      const MatrixEntry<T>& entry = *i;
931
      target.set(entry.getColVar(), entry.getCoefficient().sgn());
932
    }
933
  }
934
935
protected:
936
  uint32_t numNonZeroEntries() const { return size(); }
937
938
  uint32_t numNonZeroEntriesByRow() const {
939
    uint32_t rowSum = 0;
940
    for(RowIndex rid = 0, N = d_rows.size(); rid < N; ++rid){
941
      rowSum += getRowLength(rid);
942
    }
943
    return rowSum;
944
  }
945
946
  uint32_t numNonZeroEntriesByCol() const {
947
    uint32_t colSum = 0;
948
    for(ArithVar v = 0, N = d_columns.size(); v < N; ++v){
949
      colSum += getColLength(v);
950
    }
951
    return colSum;
952
  }
953
954
955
7219122
  bool debugNoZeroCoefficients(RowIndex ridx){
956
132678145
    for(RowIterator i=getRow(ridx).begin(); !i.atEnd(); ++i){
957
125459023
      const Entry& entry = *i;
958
125459023
      if(entry.getCoefficient() == 0){
959
        return false;
960
      }
961
    }
962
7219122
    return true;
963
  }
964
92722
  bool debugMatchingCountsForRow(RowIndex ridx){
965
529378
    for(RowIterator i=getRow(ridx).begin(); !i.atEnd(); ++i){
966
436656
      const Entry& entry = *i;
967
436656
      ArithVar colVar = entry.getColVar();
968
436656
      uint32_t count = debugCountColLength(colVar);
969
1309968
      Debug("tableau") << "debugMatchingCountsForRow "
970
436656
                       << ridx << ":" << colVar << " " << count
971
873312
                       <<" "<< getColLength(colVar) << std::endl;
972
436656
      if( count != getColLength(colVar) ){
973
        return false;
974
      }
975
    }
976
92722
    return true;
977
  }
978
979
436656
  uint32_t debugCountColLength(ArithVar var){
980
436656
    Debug("tableau") << var << " ";
981
436656
    uint32_t count = 0;
982
8808095
    for(ColIterator i=getColumn(var).begin(); !i.atEnd(); ++i){
983
8371439
      const Entry& entry = *i;
984
8371439
      Debug("tableau") << "(" << entry.getRowIndex() << ", " << i.getID() << ") ";
985
8371439
      ++count;
986
    }
987
436656
    Debug("tableau") << std::endl;
988
436656
    return count;
989
  }
990
  uint32_t debugCountRowLength(RowIndex ridx){
991
    uint32_t count = 0;
992
    for(RowIterator i=getRow(ridx).begin(); !i.atEnd(); ++i){
993
      ++count;
994
    }
995
    return count;
996
  }
997
998
};/* class Matrix<T> */
999
1000
}  // namespace arith
1001
}  // namespace theory
1002
}  // namespace cvc5