bool transposition_based_synthesis( circuit& circ, const binary_truth_table& spec, properties::ptr settings, properties::ptr statistics ) { // Settings parsing // Run-time measuring timer<properties_timer> t; if ( statistics ) { properties_timer rt( statistics ); t.start( rt ); } unsigned bw = spec.num_outputs(); circ.set_lines( bw ); copy_metadata( spec, circ ); std::map<unsigned, unsigned> values_map; for ( binary_truth_table::const_iterator it = spec.begin(); it != spec.end(); ++it ) { binary_truth_table::cube_type in( it->first.first, it->first.second ); binary_truth_table::cube_type out( it->second.first, it->second.second ); values_map.insert( std::make_pair( truth_table_cube_to_number( in ), truth_table_cube_to_number( out ) ) ); } // Set of cycles std::vector<std::vector<unsigned> > cycles; while ( !values_map.empty() ) { unsigned start_value = values_map.begin()->first; // first key in values_map std::vector<unsigned> cycle; unsigned target = start_value; do { cycle += target; unsigned old_target = target; target = values_map[target]; values_map.erase( old_target ); // erase this entry } while ( target != start_value ); cycles += cycle; } for ( auto& cycle : cycles ) { unsigned max_distance = 0u; unsigned max_index = 0u; for ( unsigned i = 0u; i < cycle.size(); ++i ) { unsigned first = cycle.at(i); unsigned second = cycle.at( (i + 1u) % cycle.size() ); unsigned distance = hamming_distance( first, second ); if ( distance > max_distance ) { max_distance = distance; max_index = i; } } std::vector<unsigned> tmp; std::copy( cycle.begin() + ( max_index + 1u ), cycle.end(), std::back_inserter( tmp ) ); std::copy( cycle.begin(), cycle.begin() + ( max_index + 1u ), std::back_inserter( tmp ) ); std::copy( tmp.begin(), tmp.end(), cycle.begin() ); std::reverse( cycle.begin(), cycle.end() ); } // TODO create transpositions function for ( auto& cycle : cycles ) { for ( unsigned i = 0u; i < cycle.size() - 1; ++i ) { circuit transposition_circ( spec.num_inputs() ); unsigned first = cycle.at(i); unsigned second = cycle.at( (i + 1) % cycle.size() ); boost::dynamic_bitset<> first_bits( spec.num_inputs(), first ); boost::dynamic_bitset<> second_bits( spec.num_inputs(), second ); transposition_to_circuit( transposition_circ, first_bits, second_bits ); append_circuit( circ, transposition_circ); } } return true; }
int Bits::first_bit(Spot p) { return first_bits(bits[idx_of_spot(p)]); }
void ywing_process_hinge(Bits* bits, Spot hinge, std::vector<Spot>* double_spots, std::vector<YWing>* ret) { int hinge_bits = bits->bit_of_spot(hinge); for(int i=0; i < double_spots->size(); i++) { Spot wing1 = (*double_spots)[i]; int wing1_bits = bits->bit_of_spot(wing1); // only consider wings that aren't the hinge, but are visible to the hinge, and have exactly 1 candidate in common with the hinge if(spot_equal(wing1,hinge) || !spot_visible(wing1,hinge) || count_bits(hinge_bits & wing1_bits) != 1 ) { continue; } for(int j=i+1; j < double_spots->size(); j++) { Spot wing2 = (*double_spots)[j]; int wing2_bits = bits->bit_of_spot(wing2); // only consider wings that aren't the hinge, but are visible to the hinge, and have exactly 1 candidate in common with the hinge and the other wing if(spot_equal(wing2,hinge) || !spot_visible(wing2,hinge) || count_bits(hinge_bits & wing2_bits) != 1 || count_bits(wing1_bits & wing2_bits) != 1 || count_bits(hinge_bits & wing1_bits & wing2_bits) != 0) { continue; } // now we have two unique wings that can see the hinge, and each has only one candidate shared between each other // the candidate we can exclude is the shared candidate between the two wings int shared_candidate = first_bits(wing1_bits & wing2_bits); // determine all spots that are visible to both wing1 and wing2 (same row, column, or box) std::vector<Spot> shared_spots; for(int ia=0; ia < 9; ia++) { for(int ib=0; ib < 9; ib++) { Spot p = Spot(ia,ib); // exclude the hinge and wing spots if(spot_equal(p,hinge) || spot_equal(p,wing1) || spot_equal(p,wing2)) { continue; } if((p.row == wing1.row || p.col == wing1.col || boxid_of_spot(p) == boxid_of_spot(wing1)) && (p.row == wing2.row || p.col == wing2.col || boxid_of_spot(p) == boxid_of_spot(wing2))) { shared_spots.push_back(p); } } } // NOTE: potentially more-efficient version commented out, didn't figure out the best way to make this compile. // if(wing1.row == wing2.row) { // shared_spots = spots_union(shared_spots,spots_of_row(wing1.row)); // } // if(wing1.col == wing2.col) { // shared_spots = spots_union(shared_spots,spots_of_col(wing1.col)); // } // if(boxid_of_spot(wing1) == boxid_of_spot(wing2)) { // shared_spots = spots_union(shared_spots,spots_of_box(boxid_of_spot(wing1))); // } // remove any excluded spots (hinge,wings) from our list // std::vector<Spot> excluded_spots; // excluded_spots.push_back(hinge); // excluded_spots.push_back(wing1); // excluded_spots.push_back(wing2); // shared_spots = spots_subtract(shared_spots,excluded_spots); // candidate array (if necessary) std::vector<int> candidates; candidates.push_back(shared_candidate); std::vector<Target> targets; for(int k=0; k < shared_spots.size(); k++) { Spot target_spot = shared_spots[k]; if(bits->has_candidate(target_spot,shared_candidate) && bits->count_candidates(target_spot) > 1) { targets.push_back(Target(target_spot, candidates, 0)); } } if(targets.size() > 0) { KeyRank keyrank; std::vector<Spot> wings; wings.push_back(wing1); wings.push_back(wing2); ret->push_back(YWing(targets, keyrank.keys, hinge, wings)); } } } }