(multiIndex: MultiIndex, providers: ProposalProvider[], prefix: any[], rounds: number, rows: any[], options: any)
| 736 | // A join round takes a set of providers, the current prefix, how many rounds are remaining, |
| 737 | // and an array to hold accepted rows. |
| 738 | function joinRound(multiIndex: MultiIndex, providers: ProposalProvider[], prefix: any[], rounds: number, rows: any[], options: any) { |
| 739 | let {solverInfo} = options; |
| 740 | // To start out we need to find the best proposal given the providers we have. We'll |
| 741 | // start our bestProposal out at some horrible cardinality |
| 742 | let bestProposal: Proposal = {providing: undefined, cardinality: Infinity}; |
| 743 | let bestProvider, bestProviderIx; |
| 744 | let ix = 0; |
| 745 | // Walk through the providers and ask for proposals |
| 746 | for(let provider of providers) { |
| 747 | let proposed = provider.propose(multiIndex, prefix); |
| 748 | // if we've found a lower cardinality, we want to keep track of that provider |
| 749 | if(proposed !== undefined && proposed.cardinality < bestProposal.cardinality) { |
| 750 | bestProposal = proposed; |
| 751 | bestProvider = provider; |
| 752 | bestProviderIx = ix; |
| 753 | if(proposed.cardinality === 0) { |
| 754 | solverInfo[ix]++; |
| 755 | break; |
| 756 | } |
| 757 | } |
| 758 | ix++; |
| 759 | } |
| 760 | |
| 761 | // console.log("Best provider", rounds, bestProvider, bestProposal); |
| 762 | // if we never found a provider that means we have no more valid solutions |
| 763 | // and we have nothing more to do |
| 764 | if(bestProvider === undefined || bestProposal.cardinality === 0) { |
| 765 | return; |
| 766 | } |
| 767 | |
| 768 | // Otherwise, we ask the provider to resolve their proposal into values that |
| 769 | // we then need to see if the other providers accept. |
| 770 | let values = bestProvider.resolveProposal(bestProposal, prefix); |
| 771 | let providing:any = bestProposal.providing; |
| 772 | let providingOne = providing.constructor !== Array; |
| 773 | if(providingOne) { |
| 774 | providing = [providing]; |
| 775 | } |
| 776 | let providingLength = providing.length; |
| 777 | for(let value of values) { |
| 778 | // Set the current value in our prefix of solved variables |
| 779 | let providingIx = 0; |
| 780 | for(let currentProvide of providing) { |
| 781 | if(providingOne) { |
| 782 | prefix[currentProvide.id] = value; |
| 783 | } else { |
| 784 | prefix[currentProvide.id] = value[providingIx]; |
| 785 | } |
| 786 | providingIx++; |
| 787 | } |
| 788 | // Unless someone tells us otherwise, we'll assume that we can accept |
| 789 | // this proposal and continue solving |
| 790 | let accepted = true; |
| 791 | let providerIx = 0; |
| 792 | for(let provider of providers) { |
| 793 | // we don't need to check this prefix against ourselves since we're the ones |
| 794 | // who proposed it |
| 795 | if(provider !== bestProvider) { |
no test coverage detected