Class: LogicTools::Cover
- Inherits:
-
Object
- Object
- LogicTools::Cover
- Includes:
- Traces
- Defined in:
- lib/logic_tools/logiccover.rb,
lib/logic_tools/logicconvert.rb,
lib/logic_tools/logicsimplify_es.rb
Overview
– Enhances the Cover class with simplifying using the Espresso algorithm. ++
Constant Summary
Constants included from Traces
Traces::TRACES, Traces::TRACES_INDENT
Instance Method Summary collapse
-
#[](index) ⇒ Object
Gets a cube by
index
. -
#add(cube) ⇒ Object
(also: #<<)
Adds a
cube
to the cover. -
#clone ⇒ Object
(also: #dup)
Duplicates the cover.
-
#cofactor(var, val) ⇒ Object
Generates the cofactor obtained when
var
is set toval
. -
#cofactor_cube(cube) ⇒ Object
Generates the generalized cofactor from
cube
. -
#complement ⇒ Object
Generates the complement cover.
-
#each_cube(&blk) ⇒ Object
(also: #each)
Iterates over the cubes of the cover.
-
#each_variable(&blk) ⇒ Object
Iterates over the variables of the cube.
-
#empty? ⇒ Boolean
Tells if the cover is empty.
-
#eval_input(input) ⇒ Object
Evaluates the corresponding function’s value for a binary
input
. -
#find_binate ⇒ Object
Looks for a binate variable.
-
#initialize(*variables) ⇒ Cover
constructor
Creates a new cover on a boolean space represented by a list of
variables
. -
#intersects?(cube_or_cover) ⇒ Boolean
Checks if
self
intersects withcube_or_cover
. -
#is_tautology? ⇒ Boolean
Checks if self is a tautology.
-
#simpler_clone ⇒ Object
Duplicate the cover while improving a bit the result (for faster processing later).
-
#simplify(deadline = Float::INFINITY, volume = Float::INFINITY) ⇒ Object
Generates an equivalent but simplified cover.
-
#size ⇒ Object
Gets the size (the number of cubes).
-
#smallest_containing_cube ⇒ Object
Creates the smallest cube containing
self
. -
#sort!(&blk) ⇒ Object
Sorts the cubes of the cover.
-
#split_simplify(deadline, volume) ⇒ Object
Generates an equivalent but simplified cover from a set splitting it for faster solution.
-
#subtract(cover) ⇒ Object
(also: #-)
Creates the subtraction from
self
minus onecover
. -
#to_s ⇒ Object
Converts to a string.
-
#to_tree ⇒ Object
Coverts to an AND-OR-NOT tree.
-
#uniq! ⇒ Object
Removes duplicate cubes.
-
#unite(cover) ⇒ Object
(also: #+)
Creates the union of self and
cover
. -
#unshift(cube) ⇒ Object
Adds a
cube
in front of the cover. -
#variable(index) ⇒ Object
Gets a variable by
index
. -
#variable_index(variable) ⇒ Object
Gets the index of a
variable
. -
#width ⇒ Object
Gets the width (the number of variables of the boolean space).
Methods included from Traces
#debug, #dec_indent, #error, #inc_indent, #info, #traces_debug, #traces_error, #traces_info, #traces_warn, #warn
Constructor Details
#initialize(*variables) ⇒ Cover
Creates a new cover on a boolean space represented by a list of
+variables+.
335 336 337 338 339 340 |
# File 'lib/logic_tools/logiccover.rb', line 335 def initialize(*variables) @variables = *variables # Initialize the cover @cubes = [] # @sorted = false # Initialy, the cover is not sorted end |
Instance Method Details
#[](index) ⇒ Object
Gets a cube by index
.
410 411 412 |
# File 'lib/logic_tools/logiccover.rb', line 410 def [](index) return @cubes[index] end |
#add(cube) ⇒ Object Also known as: <<
Adds a cube
to the cover.
Creates a new cube if +cube+ is not an instance of LogicTools::Cube.
370 371 372 373 374 375 376 377 378 379 380 |
# File 'lib/logic_tools/logiccover.rb', line 370 def add(cube) # Check the cube. cube = Cube.new(cube) unless cube.is_a?(Cube) if cube.width != self.width then raise "Invalid cube width for #{cube}, expecting: #{self.width}" end # The cube is valid, add it. @cubes.push(cube) # # The cubes of the cover are therefore unsorted. # @sorted = false end |
#clone ⇒ Object Also known as: dup
Duplicates the cover.
415 416 417 418 419 |
# File 'lib/logic_tools/logiccover.rb', line 415 def clone # :nodoc: cover = Cover.new(*@variables) @cubes.each { |cube| cover << cube } return cover end |
#cofactor(var, val) ⇒ Object
Generates the cofactor obtained when var
is set to val
.
479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 |
# File 'lib/logic_tools/logiccover.rb', line 479 def cofactor(var,val) # if val != "0" and val != "1" then if val != 48 and val != 49 then raise "Invalid value for generating a cofactor: #{val}" end # Get the index of the variable. i = @variables.index(var) # Create the new cover. cover = Cover.new(*@variables) # Set its cubes. @cubes.each do |cube| cube = cube.to_s # cube[i] = "-" if cube[i] == val cube.setbyte(i,45) if cube.getbyte(i) == val # cover << Cube.new(cube) if cube[i] == "-" cover << Cube.new(cube,false) if cube.getbyte(i) == 45 end cover.uniq! return cover end |
#cofactor_cube(cube) ⇒ Object
Generates the generalized cofactor from cube
.
501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 |
# File 'lib/logic_tools/logiccover.rb', line 501 def cofactor_cube(cube) # Create the new cover. cover = Cover.new(*@variables) # Set its cubes. @cubes.each do |scube| scube = scube.to_s scube.size.times do |i| if scube.getbyte(i) == cube.getbyte(i) then # scube[i] = "-" scube.setbyte(i,45) # elsif (scube[i] != "-" and cube[i] != "-") then elsif (scube.getbyte(i)!=45 and cube.getbyte(i)!=45) then # The cube is to remove from the cover. scube = nil break end end if scube then # The cube is to keep in the cofactor. cover << Cube.new(scube,false) end end cover.uniq! return cover end |
#complement ⇒ Object
Generates the complement cover.
623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 |
# File 'lib/logic_tools/logiccover.rb', line 623 def complement # First treat the case when the cover is empty: # the result is the tautology. if @cubes.empty? then result = Cover.new(*@variables) result << Cube.new("-"*self.width,false) return result end # Otherwise... # Look for a binate variable to split on. binate = self.find_binate unless binate then # The cover is actually unate, complement it the fast way. # Step 1: Generate the following boolean matrix: # each "0" and "1" is transformed to "1" # each "-" is transformed to "0" matrix = [] @cubes.each do |cube| line = " " * self.width matrix << line cube.each_byte.with_index do |bit,i| # line[i] = (bit == "0" or bit == "1") ? "1" : "0" line.setbyte(i, (bit == 48 or bit == 49) ? 49 : 48 ) end end # Step 2: finds all the minimal column covers of the matrix mins = minimal_column_covers(matrix) # Step 3: generates the complent cover from the minimal # column covers. # Each minimal column cover is converted to a cube using # the following rules (only valid because the initial cover # is unate): # * a minimal column whose variable can be reduced to 1 # is converted to the not of the variable # * a minimal column whose variable can be reduced to 0 is # converted to the variable # # +result+ is the final complement cover. result = Cover.new(*@variables) # print "mins=#{mins}\n" mins.each do |min| # +cbits+ is the bit string describing the cube built # from the column cover +min+. cbits = "-" * self.width min.each do |col| # if @cubes.find {|cube| cube[col] == "1" } then if @cubes.find {|cube| cube.getbyte(col) == 49 } then # cbits[col] = "0" cbits.setbyte(col,48) else # cbits[col] = "1" cbits.setbyte(col,49) end end result << Cube.new(cbits,false) end return result else # Compute the cofactors over the binate variables. # cf0 = self.cofactor(binate,"0") cf0 = self.cofactor(binate,48) # cf1 = self.cofactor(binate,"1") cf1 = self.cofactor(binate,49) # Complement them. cf0 = cf0.complement cf1 = cf1.complement # Build the resulting complement cover as: # (cf0 and (not binate)) or (cf1 and binate) result = Cover.new(*@variables) # Get the index of the binate variable. i = @variables.index(binate) cf0.each_cube do |cube| # cf0 and (not binate) # if cube[i] != "1" then if cube.getbyte(i) != 49 then # Cube's binate is not "1" so the cube can be kept # cube[i] = "0" cube.setbyte(i,48) result << cube end end cf1.each_cube do |cube| # cf1 and binate # if cube[i] != "0" then if cube.getbyte(i) != 48 then # Cube's binate is not "0" so the cube can be kept # cube[i] = "1" cube.setbyte(i,49) result << cube end end return result end end |
#each_cube(&blk) ⇒ Object Also known as: each
Iterates over the cubes of the cover.
Returns an enumerator if no block is given.
401 402 403 404 405 406 |
# File 'lib/logic_tools/logiccover.rb', line 401 def each_cube(&blk) # No block given? Return an enumerator. return to_enum(:each_cube) unless block_given? # Block given? Apply it. @cubes.each(&blk) end |
#each_variable(&blk) ⇒ Object
Iterates over the variables of the cube
Returns an enumberator if no block is given
438 439 440 441 442 443 |
# File 'lib/logic_tools/logiccover.rb', line 438 def each_variable(&blk) # No block given? Return an enumerator return to_enum(:each_variable) unless block_given? # Block given? Apply it. @variables.each(&blk) end |
#empty? ⇒ Boolean
Tells if the cover is empty.
353 354 355 |
# File 'lib/logic_tools/logiccover.rb', line 353 def empty? return @cubes.empty? end |
#eval_input(input) ⇒ Object
Evaluates the corresponding function’s value for a binary input
.
+input+ is assumed to be an integer.
Returns the evaluation result as a boolean.
449 450 451 452 |
# File 'lib/logic_tools/logiccover.rb', line 449 def eval_input(input) # Evaluates each cube, if one results in true the result is true. return !!@cubes.each.find {|cube| cube.eval_input(input) } end |
#find_binate ⇒ Object
Looks for a binate variable.
Returns the found binate variable or nil if not found.
NOTE: Can also be used for checking if the cover is unate.
532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 |
# File 'lib/logic_tools/logiccover.rb', line 532 def find_binate # Merge the cube over one another until a 1 over 0 or 0 over 1 # is met. # The merging rules are to followings: # 1 over 1 => 1 # 1 over - => 1 # 1 over 0 => not unate # 0 over 0 => 0 # 0 over - => 0 # 0 over 1 => not unate merge = "-" * self.width @cubes.each do |cube| cube.each_byte.with_index do |bit,i| # if bit == "1" then if bit == 49 then # if merge[i] == "0" then if merge.getbyte(i) == 48 then # A 1 over 0 is found, a binate variable is found. return @variables[i] else # merge[i] = "1" merge.setbyte(i,49) end # elsif bit == "0" then elsif bit == 48 then # if merge[i] == "1" then if merge.getbyte(i) == 49 then # A 0 over 1 is found, a binate variable is found. return @variables[i] else # merge[i] = "0" merge.setbyte(i,48) end end end end # The cover is unate: no binate variable. return nil end |
#intersects?(cube_or_cover) ⇒ Boolean
Checks if self
intersects with cube_or_cover
.
+cube_or_cover+ is either a full LogicTools::Cover object or a single
cube object (LogicTools::Cube or bit string).
809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 |
# File 'lib/logic_tools/logiccover.rb', line 809 def intersects?(cube_or_cover) if cube_or_cover.is_a?(Cover) then # Cover case: check intersect with each cube of +cube_or_cover+. # # NOTE: !! is for converting the result to boolean. return !!( cube_or_cover.each_cube.find do |cube| self.intersects?(cube) end ) else # Cube case. # # NOTE: !! is for converting the result to boolean. return !!( @cubes.find do |cube| cube.intersects?(cube_or_cover) end ) end end |
#is_tautology? ⇒ Boolean
Checks if self is a tautology.
719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 |
# File 'lib/logic_tools/logiccover.rb', line 719 def is_tautology? # Look for a binate variable to split on. binate = self.find_binate # Gets its index i = @variables.index(binate) unless binate then # The cover is actually unate, check it the fast way. # Does it contain a "-" only cube? If yes, this is a tautology. @cubes.each do |cube| # return true unless cube.each_bit.find { |bit| bit != "-" } return true unless cube.each_byte.find { |bit| bit != 45 } end # No "-" only cube, this is not a tautology return false # # Other techniques: actually general, not necessarily on # unate cover! Therefore WRONG place! # The cover is actually unate, check it the fast way. # Does it contain a "-" only cube? If yes, this is a tautology. # @cubes.each do |cube| # # return true unless cube.each_bit.find { |bit| bit != "-" } # return true unless cube.each_bit.find { |bit| bit != 45 } # end # # Is there a "1" only or "0" only column? If yes, this is not # # a tautology. # self.width.times do |col| # fbit = @cubes[0][col] # # next if fbit == "-" # next if fbit == 45 # next if (1..(@cubes.size-1)).each.find do |bit| # bit != fbit # end # return false # Not a tautology. # end # # Check the upper bound of the number of minterms: # # if < 2**width, not a tautology. # num_minterms = 0 # @cubes.each do |cube| # # num_minterms += 2 ** cube.each_bit.count {|b| b == "-"} # num_minterms += 2 ** cube.each_bit.count {|b| b == 45} # end # return false if num_minterms < 2**self.width # # Last check: the truth table. # (2**self.width).times do |input| # return false if self.eval_input(input) == 0 # end else # Compute the cofactors over the binate variables. # cf0 = self.cofactor(binate,"0") cf0 = self.cofactor(binate,48) # cf1 = self.cofactor(binate,"1") cf1 = self.cofactor(binate,49) # Check both: if there are tautologies, self is also a # tautology return ( cf0.is_tautology? and cf1.is_tautology? ) end end |
#simpler_clone ⇒ Object
Duplicate the cover while improving a bit the result (for faster
processing later).
424 425 426 427 428 429 430 431 432 433 |
# File 'lib/logic_tools/logiccover.rb', line 424 def simpler_clone # Clone. cover = self.clone # But remove duplicate cubes. cover.uniq! # And sort the cubes to group together cubes with a shorter # distance. cover.sort! { |c0,c1| c0.distance(c1) - 1 } return cover end |
#simplify(deadline = Float::INFINITY, volume = Float::INFINITY) ⇒ Object
Generates an equivalent but simplified cover.
Param:
* +deadline+:: the deadline for irredudant in seconds.
* +volume+:: the "volume" above which the cover is split before
being solved.
Uses the Espresso method.
618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 |
# File 'lib/logic_tools/logicsimplify_es.rb', line 618 def simplify(deadline = Float::INFINITY, volume = Float::INFINITY) # Compute the cost before any simplifying. @first_cost = cost(self) info do "Cost before simplifying: #{@first_cost} " + "(with #{@cubes.size} cubes)" end # If the cover is too big, split before solving. if (self.size > 2) and (self.size * (self.width ** 2) > volume) then return split_simplify(deadline,volume) end # Step 1: # The on set is a copy of self [F]. on = self.simpler_clone # Initialization # # print "on=#{on}\n" # print "#1 #{Time.now}\n" # And the initial set of don't care: dc [D]. dc = Cover.new(*on.each_variable) # At first dc is empty # print "#2 #{Time.now}\n" # Step 2: generate the complement cover: off [R = COMPLEMENT(F)]. off = on.complement # off = irredundant_partial(off) # quickly simlify off. # print "off=#{off}\n" info { "off with #{off.size} cubes." } # # Process the cover by pieces if the off and the on are too big. # If on and off are too big together, split before solving. if (on.size > 2) and (on.size*off.size > volume) then return split_simplify(deadline,volume) end # print "#3 #{Time.now}\n" # Step 3: perform the initial expansion [F = EXPAND(F,R)]. on = (on,off,deadline) # print "expand:\non=#{on}\n" # Remove the duplicates. on.uniq! # print "#4 #{Time.now}\n" # Step 4: perform the irredundant cover [F = IRREDUNDANT(F,D)]. on = irredundant(on,dc,deadline) # print "irredundant:\non=#{on}\n" # print "#5 #{Time.now}\n" # Step 5: Detect the essential primes [E = ESSENTIAL(F,D)]. essentials = essentials(on,dc) # print "essentials=#{essentials}\n" # print "#6 #{Time.now}\n" # Step 6: remove the essential primes from on and add them to dc on = on - essentials dc = dc + essentials # Optimiation loop # Computes the cost after preprocessing. new_cost = cost(on) essentials_cost = cost(essentials) info { "After preprocessing, cost=#{new_cost+essentials_cost}" } if new_cost >0 then begin # print "#7.1 #{Time.now}\n" cost = new_cost # Step 1: perform the reduction of on [F = REDUCE(F,D)] on = LogicTools.reduce(on,dc) # print "reduce:\non=#{on.to_s}\n" # Step 2: perform the expansion of on [F = EXPAND(F,R)] on = (on,off,deadline) # Also remove the duplicates on.uniq! # Step 3: perform the irredundant cover [F = IRREDUNDANT(F,D)] on = irredundant(on,dc,deadline) # on.each_cube do |cube| # if ((on+dc)-cube).cofactor_cube(cube).is_tautology? then # print "on=[#{on}]\ndc=[#{dc}]\ncube=#{cube}\n" # raise "REDUNDANT AFTER IRREDUNDANT" # end # end # Step 4: compute the cost new_cost = cost(on) info { "cost=#{new_cost+essentials_cost}" } end while(new_cost < cost) end # Readd the essential primes to the on result on += essentials # This is the resulting cover. info { "Final cost: #{cost(on)} (with #{on.size} cubes)" } return on end |
#size ⇒ Object
Gets the size (the number of cubes).
348 349 350 |
# File 'lib/logic_tools/logiccover.rb', line 348 def size return @cubes.size end |
#smallest_containing_cube ⇒ Object
Creates the smallest cube containing self
.
779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 |
# File 'lib/logic_tools/logiccover.rb', line 779 def smallest_containing_cube return nil if @cubes.empty? # Empty cover case. # Create a new cube including "-" unless the columns of # all the cubes are identical. cbits = "-" * self.width self.width.times do |i| # print "cbits=#{cbits}\n" # cbits[i] = @cubes.reduce(nil) do |bit,cube| cbits.setbyte(i, @cubes.reduce(nil) do |bit,cube| # print "bit=#{bit} i=#{i} cube=#{cube}\n" if bit == nil then # bit = cube[i] bit = cube.getbyte(i) # elsif bit != cube[i] elsif bit != cube.getbyte(i) # bit = "-" bit = 45 break bit end bit end) end return Cube.new(cbits,false) # No need to clone cbits end |
#sort!(&blk) ⇒ Object
Sorts the cubes of the cover.
474 475 476 |
# File 'lib/logic_tools/logiccover.rb', line 474 def sort!(&blk) @cubes.sort!(&blk) end |
#split_simplify(deadline, volume) ⇒ Object
Generates an equivalent but simplified cover from a set
splitting it for faster solution.
Param:
* +deadline+:: the deadline for each step in second.
* +volume+:: the "volume" above which the cover is split before
being solved.
NOTE: the deadline is acutally applied to the longest step
only.
560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 |
# File 'lib/logic_tools/logicsimplify_es.rb', line 560 def split_simplify(deadline,volume) info { "Spliting..." } # The on set is a copy of self [F]. on = self.simpler_clone on0 = Cover.new(*@variables) (0..(on.size/2-1)).each do |i| on0 << on[i].clone end on1 = Cover.new(*@variables) (((on.size)/2)..(on.size-1)).each do |i| on1 << on[i].clone end debug { "on0=#{on0}\n" } debug { "on1=#{on1}\n" } # Simplify each part independently inc_indent on0 = on0.simplify(deadline,volume) on1 = on1.simplify(deadline,volume) dec_indent # And merge the results for simplifying it globally. on = on0 + on1 on.uniq! new_cost = cost(on) # if (new_cost >= @first_cost) then # info { "Giving up with final cost=#{new_cost}" } # # Probably not much possible optimization, end here. # result = self.clone # result.uniq! # return result # end # Try to go on but with a timer (set to 7 times the deadline since # there are 7 different steps in total). begin Timeout::timeout(7*deadline) { on = on.simplify(deadline,Float::INFINITY) } rescue Timeout::Error info do "Time out for global optimization, ends here..." end end info do "Final cost: #{cost(on)} (with #{on.size} cubes)" end return on end |
#subtract(cover) ⇒ Object Also known as: -
Creates the subtraction from self
minus one cover
.
+cover+ is either an instance of LogicTools::Cover or
a single instance of LogicTools::Cube.
602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 |
# File 'lib/logic_tools/logiccover.rb', line 602 def subtract(cover) # Check if the covers are compatible. if (cover.width != self.width) then raise "Incompatible cover for union: #{cover}" end # Creates the substraction cover. subtraction = Cover.new(*@variables) if cover.is_a?(Cube) then cover = [cover] elsif !(cover.is_a?(Cover)) then raise "Invalid class for cover union: #{cover.class}" end @cubes.each do |cube| subtraction << cube unless cover.each.include?(cube) end # Return the result. return subtraction end |
#to_s ⇒ Object
Converts to a string.
455 456 457 |
# File 'lib/logic_tools/logiccover.rb', line 455 def to_s # :nodoc: "[#{@variables.join(",")}],#{@cubes.join(",")}" end |
#to_tree ⇒ Object
Coverts to an AND-OR-NOT tree.
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
# File 'lib/logic_tools/logicconvert.rb', line 129 def to_tree() # Generate the variable index. vars = self.each_variable.to_a # Treat the trivial cases. if vars.empty? then return self.empty? ? NodeFalse.new : NodeTrue.new end return NodeFalse.new if self.empty? # Treat the other cases. # Generate the products. prods = self.each_cube.map do |cube| # Generate the litterals of the and litterals = [] cube.each.with_index do |val,i| if val == "0" then # "0" bits are converted to not litteral. litterals << NodeNot.new(NodeVar.new(vars[i])) elsif val == "1" then # "1" bits are converted to variable litteral litterals << NodeVar.new(vars[i]) end end # Create and and with the generated litterals. NodeAnd.new(*litterals) end # Is there an empty and? if prods.find { |node| node.empty? } then # Yes, this is a tautology. return NodeTrue.new else # No, generate the sum and return it. return NodeOr.new(*prods) end end |
#uniq! ⇒ Object
Removes duplicate cubes.
468 469 470 471 |
# File 'lib/logic_tools/logiccover.rb', line 468 def uniq! @cubes.uniq! return self end |
#unite(cover) ⇒ Object Also known as: +
Creates the union of self and cover
.
+cover+ is either an instance of LogicTools::Cover or
a single instance of LogicTools::Cube.
577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 |
# File 'lib/logic_tools/logiccover.rb', line 577 def unite(cover) # Check if the covers are compatible. if (cover.width != self.width) then raise "Incompatible cover for union: #{cover}" end # Creates the union cover. union = Cover.new(*@variables) # Fill it with the cubes of self and +cover+. @cubes.each { |cube| union.add(cube.clone) } if cover.is_a?(Cover) then cover.each_cube { |cube| union.add(cube.clone) } elsif cover.is_a?(Cube) then union.add(cover.clone) else raise "Invalid class for cover union: #{cover.class}" end # Return the result. return union end |
#unshift(cube) ⇒ Object
Adds a cube
in front of the cover.
Creates a new cube if +cube+ is not an instance of LogicTools::Cube.
386 387 388 389 390 391 392 393 394 395 396 |
# File 'lib/logic_tools/logiccover.rb', line 386 def unshift(cube) # Check the cube. cube = Cube.new(cube) unless cube.is_a?(Cube) if cube.width != self.width then raise "Invalid cube width for #{cube}, expecting: #{self.width}" end # The cube is valid, add it. @cubes.unshift(cube) # # The cubes of the cover are therefore unsorted. # @sorted = false end |
#variable(index) ⇒ Object
Gets a variable by index
.
358 359 360 |
# File 'lib/logic_tools/logiccover.rb', line 358 def variable(index) return @variables[index].clone end |
#variable_index(variable) ⇒ Object
Gets the index of a variable
.
363 364 365 |
# File 'lib/logic_tools/logiccover.rb', line 363 def variable_index(variable) return @variables.index(variable) end |
#width ⇒ Object
Gets the width (the number of variables of the boolean space).
343 344 345 |
# File 'lib/logic_tools/logiccover.rb', line 343 def width return @variables.length end |